Advertisement

C++ and SDL loop

Started by April 01, 2018 01:21 PM
2 comments, last by James Cabrera 6 years, 7 months ago

I'm a C++ and SDL beginner and I'm trying to make my first 2d game (blackjack) but I'm struggling to get an elegant loop in place to control the images, animations and input.

 

in my rush and excitement to get graphics on the screen I ended up with a massive function handling everything, which just 2 'player decisions' in, has become a monstrous unmaintainable mess, e.g.:

 


bool decision_one = true;
		bool decision_two = false;
		card playercard3 = this->deal();

		while (decision_one)
		{
			SDL_PollEvent(&e);

			if (e.type == SDL_KEYDOWN)
			{
				if (e.key.keysym.sym == SDLK_h)
				{
					while (playersource3.x != playerdestination3.x)
					{
						playersource3.x += 10;
						playersource3.y += 10;
						SDL_BlitSurface(background, NULL, screenSurface, NULL);
						SDL_BlitSurface(this->getImage(playercard1.image_number), NULL, screenSurface, &playersource1);
						SDL_BlitSurface(redback, NULL, screenSurface, &dealersource1);
						SDL_BlitSurface(this->getImage(playercard2.image_number), NULL, screenSurface, &playersource2);
						SDL_BlitSurface(this->getImage(dealercard2.image_number), NULL, screenSurface, &dealersource2);
						SDL_BlitSurface(this->getImage(playercard3.image_number), NULL, screenSurface, &playersource3);

						SDL_UpdateWindowSurface(window);
						decision_one = false;
						decision_two = true;
					}
				}
				else if (e.key.keysym.sym == SDLK_s)
				{
					card dealercard1 = this->deal();
					SDL_BlitSurface(this->getImage(dealercard1.image_number), NULL, screenSurface, &dealersource1);
					SDL_UpdateWindowSurface(window);
					decision_one = false;
				}
			}
			SDL_Delay(80);
		}

So I'm trying break it up into smaller chunks like this:


class card {
private:
	std::string name;
	int value;
	int suit;
public:
	int image_number;
	SDL_Rect source;
	SDL_Rect dest;
	int vel;
	card(std::string name, int value, int suit, int image_number);
	card() {};
	~card() {};
	void display() const;
};

class blackjack {
private:
	std::vector<card> deck;
	int minBet;
	int maxBet;
	int decks;
public:
	blackjack(int minBet, int maxBet, int decks);
	~blackjack() {};
	SDL_Surface* getImage(int i);
	void play_hand(std::shared_ptr<player> p);
	void getinput(std::shared_ptr<player> p);
	void create_card(card c, int sourceX, int sourceY, int destX, int destY, int vel);
	void animate_card(card c);
	void shuffle();
	void reshuffle();
	void render();
	card deal();
	void play(std::shared_ptr<player> p);
};

card blackjack::deal()
{
	card dealCard = this->deck[this->deck.size() - 1];
	this->deck.pop_back();

	return dealCard;
}

void blackjack::create_card(card c, int sourceX, int sourceY, int destX, int destY, int vel)
{
	SDL_Surface* newCard = this->getImage(c.image_number);
	entities.push_back(*newCard);
	
	c.source.x = sourceX; c.source.y = sourceY;
	c.dest.x = destX; c.dest.y = destY;
	c.vel = vel;
}

void blackjack::animate_card(card c)
{
	while (c.source.x != c.dest.x)
	{
		c.source.x += c.vel;
		c.source.x += c.vel;
		for (auto i : entities)
		{
			SDL_Surface *s = &i;
			SDL_BlitSurface(background, NULL, screenSurface, NULL);
			SDL_BlitSurface(s, NULL, screenSurface, //HOW TO GET IMAGE POS HERE?);
			SDL_UpdateWindowSurface(window);
		}
	}
}

void blackjack::render()
{
}

void blackjack::play(std::shared_ptr<player> p)
{
	this->shuffle();
	init_graphics();
	this->getinput(p);
}

The main problem I'm struggling to get my head around is rendering all current images in the game and animating them until they reach their destination. I've created a global variable std::vector<SDL_Surface> entities to hold all images in a hand, and I've gotten to the animate card function above but can't understand how i'm going to pass in the location of all the sdl_surface entities for the blitsurface function - any advise on a simple way to add images, animate them from a source to a dest, and keep track of all of this in one 'render' function would be great

You should add a table with cards, and split the problem in four steps:


while not done:
    # Get input from the player, or "no input" if the player doesn't do anything within a short time interval.
    # Typically interval is somewhere between 1/60th to 1/30th of a second, the animation frame rate.
    inp = receive_input()

    # Process any input from the user, and update the cards on the table accordingly.
    # Note this are only logical game actions, like 'take card', or 'deal' or so.
    table.process_input(inp)
    
    # Cards are animated, so update the position for any card that is flying.
    table.update_card_positions()
    
    # And finally, render the table as it is.
    table.render()

The table is the central data structure that knows where each card is. It can also hold the state of the game. If the game gets complicated, you may want to take that into a new class.

The above loop runs at animation frame rate. Input processing obviously doesn't do anything if the user doesn't give a command. Animation moves each card that is not where it should be a little. Rendering then just draws the entire table. Attach an entity to the card (or give the card an index number pointing to the entity to draw).

Your blunt "pos += vel" position update may fail (not to mention you update x twice, and y never). As an example, suppose vel =2, pos = 1, dest = 6. Position will update like 1, 3, 5, 7, 9, ...  since pos is never dest. Instead, just update to the final destination when the card is "close enough" (less than 'vel' away, for example).

Advertisement

Thank your for the advice, it is rather useful for me as I am also trying to make my first game and have the same trouble. 

Don't waste your time, live colorful student life while DoAHomework makes your assignment!

This topic is closed to new replies.

Advertisement