Madness with frames and button

I wasted hours trying to solve this, but I just can't... :\

I am building a "Button" class that given a texture and the number of frames, it iterates trough all the frames of the current Button state before processing the next state, this is to allow the button to finish it's animation instead of cutting straight to the next state animation.

The possible states are
enum class BUTTON { INACTIVE, HIGHLIGHTED, PRESSED, RELEASED };

and they get passed to the Button from the class that contains it.

This is the texture I'm using to test it -> http://i.imgur.com/7khYiRI.png
Each row represent a BUTTON state or an animation sequence if you willl, that need to be completed regardless of new input changes in states.

This is the function to choose the next frame
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
void Button::nextFrame(BUTTON state, SDL_Rect &sRect)
{
	switch (state)
	{
		case BUTTON::INACTIVE:
		{
			sRect.x = frameSize->x * currFrameNumber;
			sRect.y = 0;
		}break;
		case BUTTON::HIGHLIGHTED:
		{
			sRect.x = frameSize->x * currFrameNumber;
			sRect.y = frameSize->y;
		}break;
		case BUTTON::PRESSED:
		{
			sRect.x = frameSize->x * currFrameNumber;
			sRect.y = frameSize->y * 2;
		}break;
		case BUTTON::RELEASED:
		{
			sRect.x = frameSize->x * currFrameNumber;
			sRect.y = frameSize->y * 3;
		}break;
	}
}

Given a state and a currFrameNumber, it fills the sourceRect with the appropriate x-y.
When currFrameNumber is 0, picks the first frame, when is 7 it picks the last.

And this is the function that control which state we are processing
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void Button::update()
{
	//totalFrames is 8, currFrameNumber range is 0-7
	currFrameNumber = (SDL_GetTicks() / 200) % totalFrames;

	//queue that stores max 2 states, the current and the next
	if (queuedState.size() < 2)
	{
		//currState contains the  (almost but not quite) most updated state request
		//button states are:  BUTTON { INACTIVE, HIGHLIGHTED, PRESSED, RELEASED };
		queuedState.emplace(currState);
	}

	// this function  internally uses currFrameNumber as offset to get the correct sprite for the passed In BUTTON state
	nextFrame(queuedState.front(), *sourceRect);

	//currFrameNumber last possible value is 7. If we processed the last frame, then remove the front item from the queue.
	if (currFrameNumber == totalFrames -1)
	{
		queuedState.pop();
	}
}


A queue takes 2 requests at most and do feed them into the nextFrame()function.
This all kinda works, the problem is that the state/color of the sprite is changing one too soon, when it is displaying the 7 (instead of changing at the 0 which represent the beggining of a different state) thus it appears with the color of the following BUTTON state, as if the queuedState.pop(); where applied too soon and currFrameNumber = 7 where applied to the following BUTTON state.
I quite don't get it, if there is a logical error, then I can't see it, if there is a reason for SDL and this whole thing to go somehow out of sync, then I don't know about it.

Don't know if I've explained it well enough, but you can download the .exe here and try yourself -> http://s000.tinyupload.com/index.php?file_id=53989755943481086486

If you guys can see why this weird behavious is happening, then please let meknow u_u
Last edited on
Apologies, I must be tired...found the logical bug...
currFrameNumber = (SDL_GetTicks() / 200) % totalFrames;

ofc that call would still return 7 for 0.2 seconds after the queuedState.pop(); call x_x

solved like this using deque

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
void Button::update()
{
	SDL_Delay(100);

	currFrameNumber %= totalFrames;

	if (queuedState.size() <= 2)
	{
		if (currFrameNumber == totalFrames - 1 && (!queuedState.empty()))
		{
			queuedState.pop_back();
			queuedState.push_back(currState);
		}
		else
		{
			if (queuedState.size() < 2)
			{
				queuedState.push_back(currState);
			}
		}
	}

	nextFrame(queuedState.front(), *sourceRect);

	if (currFrameNumber == totalFrames - 1)
	{
		queuedState.pop_front();
		currFrameNumber = 0;
	}
	else
	{
		++currFrameNumber;
	}
}
Last edited on
Topic archived. No new replies allowed.