-
Hey,
as the title says I'm new to SFML and fairly new to C++ aswell. I'm making Memory card game as my final project in the C++ course I'm studying but are currently stuck on the "game" part. What I need is some guidelines to continue :)
The game should be like this:
Create a game where you draw out 16 cards. When the game starts, 2 cards should be randomized and displayed. The cards are shown for one second, one after another. The player should click on which cards he saw, in order, and if he's correct the next round is started with 3 cards and so on. The total amount of cards that the player has found should be displayed.
Here's my project so far:
#include "SFML/Graphics.hpp"
#include <iostream>
#include "Meny.h";
int main() {
const int bredd = 640;
const int höjd = 480;
sf::RenderWindow fönster(sf::VideoMode(bredd, höjd), "Kortspel!");
Meny meny(bredd, höjd);
bool gameStart = false;
while (fönster.isOpen()) {
sf::Event event;
fönster.clear();
while (fönster.pollEvent(event)) {
if (gameStart) {
std::cout << "It works!";
}
else {
switch (event.type) {
case sf::Event::KeyPressed:
switch (event.key.code) {
case sf::Keyboard::Return:
gameStart = true;
break;
case sf::Keyboard::Escape:
fönster.close();
break;
}
break;
case sf::Event::Closed:
fönster.close();
break;
}
}
}
meny.Rita(fönster);
fönster.display();
}
}
#pragma once
#include "SFML/Graphics.hpp"
class Meny {
private:
sf::Font typsnitt;
sf::Text meny1, meny2;
public:
Meny(float bredd, float höjd);
~Meny();
void Rita(sf::RenderWindow &fönster);
};
#include "Meny.h"
Meny::Meny(float bredd, float höjd) {
if (!typsnitt.loadFromFile("resurser/ARCADECLASSIC.TTF")) {
// ta hand om error
}
meny1.setFont(typsnitt);
meny1.setCharacterSize(80);
meny1.setColor(sf::Color::Green);
meny1.setString("Memory");
meny1.setPosition(bredd / 2 - meny1.getGlobalBounds().width / 2, 100);
meny2.setFont(typsnitt);
meny2.setCharacterSize(30);
meny2.setColor(sf::Color::Green);
meny2.setString("Press ENTER to play");
meny2.setPosition(bredd / 2 - meny2.getGlobalBounds().width / 2, 275);
}
Meny::~Meny() {}
void Meny::Rita(sf::RenderWindow &fönster) {
fönster.draw(meny1);
fönster.draw(meny2);
}
My questions/wonderings are:
I will create a class for the cards that can be used for both the backside of the cards and showing the front. How do I create that in a simple way for my project? Do I need to keep track of the x and y coordinates of every card? I plan to use vectors and random_shuffle in some sort of way to randomize the cards. I came across this https://github.com/SFML/SFML/wiki/Tutorial:-Image-Manager (https://github.com/SFML/SFML/wiki/Tutorial:-Image-Manager) image manager but it feels like it's a bit too complicated for my project.
Also, how do I keep track of which card I've clicked on?
Well, as you can see the questions just build up, there's no end. How would you create my game? I appreciate all help!
-
I will create a class for the cards that can be used for both the backside of the cards and showing the front. How do I create that in a simple way for my project?
You could just use a bool or an enum to keep track if it's up or down facing.
Do I need to keep track of the x and y coordinates of every card?
That really depends. Can the cards be located anywhere, or only in fixed locations? It's entirely reasonable to just keep your cards in some sort of container and have the graphics code deduce where they should be drawn and your input code to deduce which one you've clicked on. Or you could store the position in the cards. Whichever works best for you.
Also, how do I keep track of which card I've clicked on?
There's no one way to do this. You could use pointers, integer handles, etc. I'd really need to see how your cards are implemented to make any helpful suggestions.
Also, please use English in your code. There are a lot of programmers that speak English as a secondary language, but only use English in their code. Why? Because reasons. That and if everybody used their native languages, nobody would be able to read each others code.
-
Hi Samm
I can do a basic sample app of what you explained, but in C#. I hope someone can translate it to C++ for you.
I didn´t understand this: there are 16 cards; You are shown by a second 2 of them; then 3; and so on;
But if you add: 2 + 3 + 4 + 5 (+ 6) the sum is not 16 anyway
Could you tell me how many different types of cards are there, and how many cards are there of each type?
By now i'll start doing the app with it showing 2 cards a time (as i remember this game was as it), and when you clear out the issue, then i (or maybe you) would change the code
Suppose we have a 4x4 matrix with the cards (from cards[0, 0] to cards[3, 3]), we could know which one is clicked using:
Vector2i position = Mouse.GetPosition();
int xPos = (position.X - playBox.Position.X) / (playBox.Size.X / 4);
int yPos = (position.Y - playBox.Position.Y) / (playBox.Size.Y / 4);
where 'playBox' is, i.e. a RectangleShape object (square) that contains the cards as a 4x4 grx matrix, and cards is a Card objects bidimensional array.
then you can access the selected card by: cards[xPos, yPos]
Please correct the issues that should be another way.
Pablo
Bs As - Argentina
-
Hi
Here is what i did, i'm afraid it's not exactly what you asked for, plus i haven't understood well what it was. :-\
https://www.dropbox.com/s/ynkt0hkpu8s9opm/MemoCards.rar?dl=0
there is a "square" with 16 cards, 8 pairs of twin. They are shown by 4 secs then hidden. Then you have to click one and then the twin. And then the same again. You have 3 lives. I couldn't win by now. :P
if your system is 32 bit, then you should change the DLLs in the folder where the .exe is and int the project References node. ;)
i hope some nice member, Lady or Guy, can translate this (that is in C#) to C++ for you. ;D
also if you could explain me what is exactly what you want, i would try to modify the code to that. :)
Pablo
Bs As - Argentina
-
Hey man, sorry for not answering! ;/ I totally forgot about the thread as I went straight to action, creating the game on my own after the first reply :) Here's the result so far, https://www.dropbox.com/s/kmrf5b90b9wwjjf/Nostalgitripp.rar?dl=0 (https://www.dropbox.com/s/kmrf5b90b9wwjjf/Nostalgitripp.rar?dl=0)
I'm almost done with the game, there's still some left.
This is what's left:
- Show all cards clicked on while playing. Right now they're disappearing one after another.
Add a text that displays which round it is.Add an end, so if you manage to beat all levels, you have to possibility to start over.- Fix a start delay of each round so the first card isn't shown instantly.
- Make a "flawless" gameplay with no bugs and logic errors.
You'll get the "what's left" list and how the game is supposed to be when you run my game. Right now there's a pretty big bug that gets you stuck while playing the game if you click the cards too fast (I think?) or if you're just unlucky clicking in the wrong "cycle"? I don't really know what's causing it as I've tried to play through the rounds slowly but even that doesn't help if you click the cards irregurarly. I'm pretty sure it's a logic error as I'm still pretty new to coding and even if it works partually it's not the most optimal way to do it in :D
To finish off, thanks for helping me, appreciate it a lot!
EDIT: Fixed a text which displays which round it is and an end so you can start over + a little bit of clean up in the project.
-
it looks cool game, good job
there are few things need to clarify a bit regarding your source code
Randomness
no need to call std::srand every time when you called std::random_shuffle, unless you want to generate a new seed sequence every time which is not necessary here.
better you declared std::srand at first of your project right after the main().
or if you're interesting on c++11 you can use <random> which is better in seeding and generating randomness.
the easiest implementation is to define free function for it like this
std::mt19937 rnd()
{
static std::mt19937 r{ std::random_device{}() };
return r;
}
and then you can use it else where like so,
std::vector<int> cardOrder(16);
int i = 0;
std::transform(cardOrder.begin(), cardOrder.end(), cardOrder.begin(), [&i](int j) { return j = i++;});
std::shuffle(cardOrder.begin(), cardOrder.end(), rnd());
-
About rand and random:
The C++ <random> Lame List (http://www.elbeno.com/blog/?p=1318)
Stefan T. Lavavej rand() Considered Harmful (https://m.youtube.com/watch?v=8hREcJ4CFKI)
Other random stuff you may find useful:
http://www.redblobgames.com/
http://www-cs-students.stanford.edu/~amitp/gameprog.html
http://gameprogrammingpatterns.com/
http://www.koonsolo.com/news/dewitters-gameloop/
http://gafferongames.com/game-physics/fix-your-timestep/
http://en.cppreference.com/
https://isocpp.org/
http://tinodidriksen.com/2003/05/06/but-can-you-make-pong/
-
it looks cool game, good job
there are few things need to clarify a bit regarding your source code
Randomness
no need to call std::srand every time when you called std::random_shuffle, unless you want to generate a new seed sequence every time which is not necessary here.
better you declared std::srand at first of your project right after the main().
or if you're interesting on c++11 you can use <random> which is better in seeding and generating randomness.
the easiest implementation is to define free function for it like this
std::mt19937 rnd()
{
static std::mt19937 r{ std::random_device{}() };
return r;
}
and then you can use it else where like so,
std::vector<int> cardOrder(16);
int i = 0;
std::transform(cardOrder.begin(), cardOrder.end(), cardOrder.begin(), [&i](int j) { return j = i++;});
std::shuffle(cardOrder.begin(), cardOrder.end(), rnd());
I implemented the mt19937 code but need some things clarified. What's the benefits of using it, specially compared to this http://www.cplusplus.com/reference/algorithm/shuffle/? Here's the recent changes https://www.dropbox.com/s/7s7d7s2la0pp0ci/Nostalgitripp.mt19937.rar?dl=0 (https://www.dropbox.com/s/7s7d7s2la0pp0ci/Nostalgitripp.mt19937.rar?dl=0). I'm using the function in both main.cpp and Cards.cpp (void Cards::shuffleDeck). Do you know of a better way to implement it in my code so there's no need to write the function twice?
@Jesper Juhl, awesome, thanks for sharing! =)
Does anyone of you know how to improve my game logic? It "works" but is pretty shitty right now ;/
-
I implemented the mt19937 code but need some things clarified. What's the benefits of using it, specially compared to this http://www.cplusplus.com/reference/algorithm/shuffle/?
Jesper Juhl provided awesome links regarding the benefits of using std::mt19937 over std::srand for seeding. here again link to Stefan T. Lavavej speech
https://www.youtube.com/watch?v=8hREcJ4CFKI
for comparison to cplusplus example i think we both need expert like Stefan T. Lavavej to tell us the differences :-\
Here's the recent changes https://www.dropbox.com/s/7s7d7s2la0pp0ci/Nostalgitripp.mt19937.rar?dl=0 (https://www.dropbox.com/s/7s7d7s2la0pp0ci/Nostalgitripp.mt19937.rar?dl=0). I'm using the function in both main.cpp and Cards.cpp (void Cards::shuffleDeck). Do you know of a better way to implement it in my code so there's no need to write the function twice?
yes
mostly this function is called utility function so, it is better to make a new .h .cpp files for it like this:
Utility.hpp
#include <random>
namespace utility
{
std::mt19937 random();
}
and in Utility.cpp
#include "Utility.hpp"
std::mt19937 utility::random()
{
std::mt19937 r{ std::random_device{}() };
return r;
}
usage is simply like this
std::shuffle(cardOrder.begin(), cardOrder.end(), utility::random());
-
yes
mostly this function is called utility function so, it is better to make a new .h .cpp files for it like this:
Utility.hpp
#include <random>
namespace utility
{
std::mt19937 random();
}
and in Utility.cpp
#include "Utility.hpp"
std::mt19937 utility::random()
{
std::mt19937 r{ std::random_device{}() };
return r;
}
usage is simply like this
std::shuffle(cardOrder.begin(), cardOrder.end(), utility::random());
Ah, I tried to do it that way actually but I only used a header file, which might explain the errors I got :D Figured out, instead of creating a utility function for the std::mt19937 I created one for shuffling vectors instead. Less code so it doesn't look so messy :)
-
hello Ladies and Guys
I tried to run Samm's app i downloaded, and after having it asked me for MSVCP140D.dll and MSVCP140.dll and i have downloaded and put them with the exe file, the dialogbox i attached was shown.
Another thing i would appreciate if someone could tell me is how to start C++ IDE. I already downloaded C++ .Net and could not start the environment. There is no shortcut anywhere. I would like to try to run the app from the IDE and perhaps i find what's failing.
Thanks
Pablo
-
hello Ladies and Guys
I tried to run Samm's app i downloaded, and after having it asked me for MSVCP140D.dll and MSVCP140.dll and i have downloaded and put them with the exe file, the dialogbox i attached was shown.
Another thing i would appreciate if someone could tell me is how to start C++ IDE. I already downloaded C++ .Net and could not start the environment. There is no shortcut anywhere. I would like to try to run the app from the IDE and perhaps i find what's failing.
Thanks
Pablo
I also had the same problem when trying to run it on the computers in school, which had Visual Studio 2010 C++. Try downloading Visual Studio 2015, might solve the problem :)
Also, I've made some changes. In this link https://www.dropbox.com/s/hmqhj89dih6p5wu/Nostalgitripp.help.rar?dl=0 (https://www.dropbox.com/s/hmqhj89dih6p5wu/Nostalgitripp.help.rar?dl=0) you'll find my progress so far. I've implemented a new "randomizer" + a new logic when clicking on the cards and displaying the clicked cards, so there's some new problems now. If you want to look at the logic I used before they're in the previous links :)
-
the dialogbox i attached
See if this helps (http://www.pcadvisor.co.uk/how-to/windows/how-fix-application-was-unable-start-correctly-0xc000007b-error-message-3613164/).
-
since you defined shuffleVector() as free function in utility header file then no need for old std::mt19937 random(). you can declare random in shuffleVector() like this:
void utilities::shuffleVector(std::vector<int> &shuffle) {
int i = 0;
std::transform(shuffle.begin(), shuffle.end(), shuffle.begin(), [&i](int j) { return j = i++; });
std::mt19937 random{ std::random_device{}() };
std::shuffle(shuffle.begin(), shuffle.end(), random); // <-- note no ()
}
-
That would create/destroy an std::mt19937 every time that function is called though. Which isn't a very good idea, it's not small by any means. And recreating it generally loses the whole point of randomness.
An explanation: http://www.elbeno.com/blog/?p=1325
-
That would create/destroy an std::mt19937 every time that function is called though. Which isn't a very good idea, it's not small by any means. And recreating it generally loses the whole point of randomness.
An explanation: http://www.elbeno.com/blog/?p=1325
thanks for the link.
the correct implementation for random shuffle is like this:
void utilities::shuffleVector(std::vector<int> &shuffle) {
int i = 0;
std::transform(shuffle.begin(), shuffle.end(), shuffle.begin(), [&i](int j) { return j = i++; });
thread_local static std::random_device rd{};
thread_local static std::mt19937 random{ rd() };
std::shuffle(shuffle.begin(), shuffle.end(), random);
}
-
You are not seeding all of the internal state.
Something like his would be better for seeding it:
std::array<int, std::mt19937::state_size> seed_data;
std::random_device r;
std::generate_n(seed_data.data(), seed_data.size(), std::ref(r));
std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
std::mt19937 engine(seq);
-
You are not seeding all of the internal state.
Something like his would be better for seeding it:
std::array<int, std::mt19937::state_size> seed_data;
std::random_device r;
std::generate_n(seed_data.data(), seed_data.size(), std::ref(r));
std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
std::mt19937 engine(seq);
thanks for mention it, i have done that for a my game but i have experienced performance issue when i try to seed for every call. in this game it okay it is not noticeable.
for generic random engine i have modified Jesper Juhl suggested to allow user to use either std::mt19937 or std::mt19937_64. by default it is for 32 bit like this:
template<class T = std::mt19937, std::size_t N = T::state_size>
auto ProperlySeededRandomEngine() -> typename std::enable_if_t<!!N, T> {
std::array<typename T::result_type, N> seed_data;
thread_local static std::random_device source;
std::generate(std::begin(seed_data), std::end(seed_data), std::ref(source));
std::seed_seq seeds(std::begin(seed_data), std::end(seed_data));
T seeded_engine(seeds);
return seeded_engine;
}
void utilities::shuffleVector(std::vector<int> &shuffle) {
int i = 0;
std::transform(shuffle.begin(), shuffle.end(), shuffle.begin(), [&i](int j) { return j = i++; });
std::shuffle(shuffle.begin(), shuffle.end(), ProperlySeededRandomEngine());
}
-
thanks for mention it, i have done that for a my game but i have experience efficiency issue when i try to seed for every call. in this game it okay it is not noticeable.
Why would you seed on every call? That's just silly.
You create and seed your engine once and then you keep reusing it (and never copy it - this is important; always pass it by reference or pointer).
-
thanks for mention it, i have done that for a my game but i have experience efficiency issue when i try to seed for every call. in this game it okay it is not noticeable.
Why would you seed on every call? That's just silly.
You create and seed your engine once and then you keep reusing it (and never copy it - this is important; always pass it by reference or pointer).
exactly that i what i did to solve performance issue, i have devoted a class for it as showing here https://github.com/MORTAL2000/Space-Invaders-Clone/blob/master/Random.hpp (https://github.com/MORTAL2000/Space-Invaders-Clone/blob/master/Random.hpp)
-
After a bit of coding, I'm finally done! The game is working perfectly and exactly as it should.
I'd like to thank everyone who helped me, I learned a lot and the new randomizer noticeably improved the performance .
Here's the final product, https://www.dropbox.com/s/kmrf5b90b9wwjjf/Nostalgitripp.rar?dl=0 (https://www.dropbox.com/s/kmrf5b90b9wwjjf/Nostalgitripp.rar?dl=0)
-
sorry for late, i was thinking about what Jesper Juhl suggest to correct my previous implementation for shuffle. here latest update. i have comments the change to distinguished the differences between both codes
#include "Utilities.h"
#include <random>
#include <algorithm>
#include <functional> // std::ref
#include <array>
template<class T = std::mt19937, std::size_t N = T::state_size>
static auto ProperlySeededRandomEngine() -> std::enable_if_t<!!N, T&> //using typename, it's unnecessary. in c++14 std::enable_if_t will take care of that for us.
{
std::array<typename T::result_type, N> seed_data;
static std::random_device source; // thread_local implies static so writing both is redundant
std::generate(std::begin(seed_data), std::end(seed_data), std::ref(source));
std::seed_seq seeds(std::begin(seed_data), std::end(seed_data));
static T seeded_engine(seeds);
return seeded_engine;
}
void utilities::shuffleVector(std::vector<int> &shuffle) {
static auto& RandomEngine = ProperlySeededRandomEngine(); // only once, take it by reference no copy
int i = 0;
std::transform(shuffle.begin(), shuffle.end(), shuffle.begin(), [&i](int j) { return j = i++; });
std::shuffle(shuffle.begin(), shuffle.end(), RandomEngine); // reuse it
}
-
After a bit of coding, I'm finally done! The game is working perfectly and exactly as it should.
I'd like to thank everyone who helped me, I learned a lot and the new randomizer noticeably improved the performance .
Here's the final product, https://www.dropbox.com/s/kmrf5b90b9wwjjf/Nostalgitripp.rar?dl=0 (https://www.dropbox.com/s/kmrf5b90b9wwjjf/Nostalgitripp.rar?dl=0)
congart, :)
it looks really awesome
-
congart, :)
it looks really awesome
Thanks! Regarding the seed generator, is it really necessary to implement that in my small game for a perfect "random"? Because I doubt it'll matter when I turn it in to my teacher. I probably won't be able to explain it in detail if I'm questioned, as I lack "general" knowledge in C++, and the game itself is enough for an A :)
Also, mind explaining what std::transform does? I read that it has something to do with lambas but can't really find the real mening behind its purpose when I use it ;/
-
Regarding the seed generator, is it really necessary to implement that in my small game for a perfect "random"? Because I doubt it'll matter when I turn it in to my teacher. I probably won't be able to explain it in detail if I'm questioned, as I lack "general" knowledge in C++, and the game itself is enough for an A :)
in your game it is not necessary but for your knowledge it is.
just little improvement to exist code, make sure when you use thread_local no need for explicit static, thread_local implies static for us.
Also, mind explaining what std::transform does? I read that it has something to do with lambas but can't really find the real mening behind its purpose when I use it ;/
best source for understanding std::transform is in this link
http://en.cppreference.com/w/cpp/algorithm/transform
-
I have to ask you... does the cards show up on different locations for you every time you start it or is it only the order that they're shown in that's randomized?
EDIT: My fault, removed and changed some old code. Solved it =)
-
I have to ask you... does the cards show up on different locations for you every time you start it or is it only the order that they're shown in that's randomized?
i have modified your original code, so the code in my side is bit different than yours . and for your question, yeah the code here generates a new locations for sprites for every run.
here the code after modification: https://gist.github.com/MORTAL2000/9b8ac45d28abb97f6281
EDIT: My fault, removed and changed some old code. Solved it =)
glad you solved it :)
-
Try this guide to fix Error Code 0xc000007b (http://errorcodespro.com/fix-error-code-0xc000007b-windows-7-10/) worked for me as i have faced the same problem