Player Animation on a keypress
Lasaqus7

Is there anywhere good sources where I can go and read to find out how to start to code my game so if I click a key (eg 1) that my player with cycle through his attack animation and continue to move in his current direction and only be able to attack within a certain timeframe ?

I have tried to look at other people code in games I found where the code was available but since they code with classes, it gets me confused alot as I am still learning.

I read this post https://www.allegro.cc/forums/thread/589018/634227#target. Although this kind of helps, for me it would mean putting a state within a state.

Is this possible ?

I currently have a CombatIdle state (Enemy sat idle), a Combat Chasing state (Enemy is chasing the player around) and a CombatRetreat state (Player out of range, enemy heading back to be idle). If I can put a state within a state, I'm guessing I could just put the state in the CombatChasing state as this is the one where the enemy would be in range.

I haven't posted code as I haven't began coding it. just looking for helpful resources on this before I come back and ask why it doesn't work ;D

Cheers

Dizzy Egg

...just show some code, and point out specifically what doesn't work the way you want it to....

Lasaqus7

Ok, I'm working on this now so once I get some code up and running I'll do that

Dizzy Egg

Ok cool! I guess basically it's going to come down to conditions every time your game loop starts again, so, did I press attack? No? Carry on then...or...yes? Is there an enemy next to me? No? just play my attack animation then....or....yes? Well, how many DP does it have?....etc etc etc

Lasaqus7

Ok, here's what I have so far

#SelectExpand
1enum STATE{MENU, PLAYING, COMBATSCREEN, COMBATIDLE, COMBATCHASING, COMBATRETREATING, ATTACKING, GAMEOVER}; 2enum KEYS{UP, DOWN, LEFT, RIGHT, ESCAPE, W, A, S, D, SPACE, C, KEY_1}; 3bool keys[] = { false, false, false, false, false, false, false, false, false, false, false, false}; 4 5Player Human; 6 7void PlayerAttack(Player &Human); 8 9int main(int argc, char **argv) 10{ 11 12 //ALLEGRO VARIABLES 13 ALLEGRO_DISPLAY *display = NULL; 14 ALLEGRO_EVENT_QUEUE *event_queue = NULL; 15 ALLEGRO_TIMER *timer = NULL; 16 ALLEGRO_BITMAP *HumanImage; 17 18 //ALLEGRO INIT FUNCTIONS 19 if (!al_init()) //Initialize Allegro 20 return -1; 21 22 display = al_create_display(WIDTH, HEIGHT); //Create display object 23 24 if (!display) //Test display object 25 return -1; 26 27 //ADDON INSTALL 28 al_init_primitives_addon(); 29 al_install_keyboard(); 30 al_install_mouse(); 31 al_init_image_addon(); 32 al_init_font_addon(); 33 al_init_ttf_addon(); 34 35 //PROJECT INIT 36 event_queue = al_create_event_queue(); 37 timer = al_create_timer(1.0 / FPS); 38 39 HumanImage = al_load_bitmap("spritesheethuman.bmp"); 40 al_convert_mask_to_alpha(HumanImage, al_map_rgb(106, 76, 48)); 41 42 InitHuman(Human, HumanImage); 43 44 //TIMER INIT AND STARTUP 45 al_register_event_source(event_queue, al_get_keyboard_event_source()); 46 al_register_event_source(event_queue, al_get_mouse_event_source()); 47 al_register_event_source(event_queue, al_get_timer_event_source(timer)); 48 al_register_event_source(event_queue, al_get_display_event_source(display)); 49 50 al_start_timer(timer); 51 while (!done) 52 { 53 ALLEGRO_EVENT ev; 54 al_wait_for_event(event_queue, &ev); 55 56 if (ev.type == ALLEGRO_EVENT_TIMER) 57 { 58 render = true; 59 60 //UPDATE=========================================== 61 if (keys[UP] || keys[W]) 62 MoveHumanUp(Human); 63 else if (keys[DOWN] || keys[S]) 64 MoveHumanDown(Human); 65 else if (keys[LEFT] || keys[A]) 66 MoveHumanLeft(Human); 67 else if (keys[RIGHT] || keys[D]) 68 MoveHumanRight(Human); 69 else if (keys[SPACE]) 70 { 71 72 } 73 //===================================================== 74 if (state == MENU) 75 { 76 } 77 else if (state == PLAYING) 78 { 79 } 80 else if (state == COMBATSCREEN) 81 { 82 } 83 else if (state == COMBATIDLE) 84 { 85 } 86 else if (state == COMBATCHASING) 87 { 88 if (threshold < CheckDistance(Orc.x, Orc.y, Orc.Startx, Orc.Starty)) 89 ChangeState(state, COMBATRETREATING); 90 else 91 { 92 float angle = AngleToTarget(Orc.x, Orc.y, Human.x, Human.y); 93 Orc.y += (Orc.speed * sin(angle)); 94 Orc.x += (Orc.speed * cos(angle)); 95 96 if (threshold < CheckDistance(Orc.x, Orc.y, Human.x, Human.y)) 97 ChangeState(state, COMBATRETREATING); 98 } 99 if (Orc.x > Human.x) 100 MoveOrcLeft(Orc); 101 else if (Orc.x < Human.x) 102 MoveOrcRight(Orc); 103 if (keys[KEY_1]) 104 PlayerAttack(Human); //Placed function here as best scenario for an attack to happen 105 } 106 else if (state == COMBATRETREATING) 107 { 108 } 109 } 110 else if (ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) 111 { 112 done = true; 113 } 114 115 else if (ev.type == ALLEGRO_EVENT_KEY_DOWN) 116 { 117 switch (ev.keyboard.keycode) 118 { 119 case ALLEGRO_KEY_1: 120 keys[KEY_1] = true; 121 break; 122 } 123 } 124 else if (ev.type == ALLEGRO_EVENT_KEY_UP) 125 { 126 switch (ev.keyboard.keycode) 127 { 128 case ALLEGRO_KEY_1: 129 keys[KEY_1] = false; 130 break; 131 } 132 } 133 134 //========================================================== 135 //RENDER 136 //========================================================== 137 if (render && al_is_event_queue_empty(event_queue)) 138 { 139 render = false; 140 141 else if (state == COMBATCHASING) 142 { 143 al_draw_bitmap(BattleBackground, 0, 0, 0); 144 DrawHuman(Human); 145 } 146 147 //FLIP BUFFERS ========================================= 148 al_flip_display(); 149 al_clear_to_color(al_map_rgb(0, 0, 0)); 150 } 151 } 152 return 0; 153} 154 155//Function for my attack 156void PlayerAttack(Player &Human) 157{ 158 Human.maxFrame = 13; 159 Human.frameCount = 0; 160 Human.animationRow = 0; 161 Human.animationColumns = 13; 162 Human.animationDirection = 1; 163 Human.frameDelay = 5; 164 Human.curFrame = 0; 165 keys[KEY_1] = true; 166 167 while (keys[KEY_1] && Human.curFrame != Human.maxFrame) //Does a loop as if 1 is held down 168 { 169 if (++Human.frameCount >= Human.frameDelay) //Cycles through frames at a speed based on the delay 170 { 171 Human.curFrame += Human.animationDirection; //Animation frames increased each cycle for new animation 172 Human.frameCount = 0; //Resets count to keep in touch with the delay 173 if (Human.curFrame >= Human.maxFrame) // If the last frame is reached stop animating 174 { 175 keys[KEY_1] = false; //1 is now up and back to game state(CHASING) 176 } 177 Human.x += Human.speed; //Player moves forward with each frame (may have to change this) 178 if (Human.x > WIDTH) //Stops player going past the end of the screen 179 Human.x = WIDTH; 180 } 181 } 182}

Again my code is too long to fit it all in so cut most of it out.

So what I believe is my code is actually performing an attack animation although it is too quick for me to see. All i see if my players jumping across the screen by X pixels

This may work, however I think I need some kind of timer to slow the animation down so instead of it playing faster than I can see, it maybe takes 1-1.5 secs to complete.

This I don't know how to do.

EDIT:- If you need my full code let me know and i'll try and post it somehow

Dizzy Egg

Ultimately I think you'll want a timer, but you can slow down things as well by using a 'miniCounter', that increments the frame, something like:

int miniFrame;
int mainFrame;

function movePlayer()
{
    miniFrame++;
    
    if(miniFrame > 1000) //increase/decrease this to slow down/speed up
    {
        mainFrame++;
    }
}

That way you can control when the frame count goes up by using the miniFrame counter, which can be a huge number - the only problem with this is that it wont run at the same speeds on different machines (probably), so not as precise as a timer, but it should slow things down enough to see the animation!

taron 
Lasaqus7 said:

So what I believe is my code is actually performing an attack animation although it is too quick for me to see.

Shouldn't be the case, unless the whole animation happens in less than 16ms since it may end before the average screen can refresh.

while (keys[KEY_1] && Human.curFrame != Human.maxFrame) //Does a loop as if 1 is held down
{

This loop right here will do the whole attack in one frame without doing anything.

I wrote a pretty simple way to do animation based on your already existing code. (Not tested btw, just to give an idea of the logic you can possibly use)
Fix and change as you see fit.

#SelectExpand
1 2// A struct to keep track of Animation data. 3struct Animation 4{ 5 enum 6 { 7 IDLE, 8 MOVE, 9 ATTACK, 10 ... 11 }; 12 13 // Does the animation loop? 14 bool loop; 15 // Optionally add this if you want to be able to cancel animations. 16 // You might for example not want to allow the player 17 // to cancel a slide or attack but you do want to allow the player 18 // to cancel the idle animation. 19 // You could build a far more complex system with some animations 20 // allowing to be canceled by a few others but not all. 21 bool cancellable; 22 // Makes it easier to track whether or not the animation is still playing. 23 bool ended; 24 25 int maxFrame; 26 int frameCount; 27 int animationRow; 28 int animationColumns; 29 int animationDirection; 30 int frameDelay; 31 int curFrame; 32} 33 34struct Player 35{ 36 ... 37 // Hold the animation data; 38 Animation animation; 39 ... 40} 41 42// Always call this once per frame for each object with an animation. 43void UpdateAnimation(Animation &animation) 44{ 45 ++animation.frameCount; 46 if (animation.frameCount > animation.frameDelay) 47 { 48 ++animation.curFrame; 49 animation.frameCount = 0; 50 if (animation.curFrame >= animation.maxFrame) 51 { 52 if (animation.loop) 53 { 54 // Go back to the first frame if it should loop. 55 animation.curFrame = 0; 56 } 57 else 58 { 59 // Freeze the animation on the last frame. 60 // And flag it as ended. 61 animation.curFrame = animation.maxFrame; 62 animation.ended = true; 63 // Once the animation has ended assume 64 // that it may now be cancelled. 65 animation.cancellable = true; 66 } 67 } 68 } 69} 70 71// When you want to change the animation being played. 72// newAnimation is passed as a reference to a const Animation 73// to avoid accidentally writing to newAnimation instead of the 74// target animation. Not necessary. 75void ChangeAnimation(Animation &animation, const Animation &newAnimation) 76{ 77 // If the current animation can't be cancelled, do nothing. 78 // You might possibly want to change this to an assert. 79 // So the program terminates with an error instead of ignoring it. 80 if (animation.cancellable) 81 { 82 // Copy new animation here 83 // Alternatively remove this whole function and just do this assignment inline. 84 // But this might be more error-prone if you forget to check any important information 85 // about the animation like cancellable. 86 animation = newAnimation; 87 } 88} 89 90void PlayerAttack(Player &player) 91{ 92 if (!player.animation.cancellable) 93 { 94 // If the current animation can't be cancelled, do an early return 95 // and don't do any attack stuff. 96 // Might not want to allow the player to attack if he's been stunned for example. 97 return; 98 } 99 // *else* 100 // Create a new animation 101 Animation newAnimation; 102 103 // Initialize the new animation here 104 newAnimation.curFrame = 0; 105 ... 106 107 // Once the new animation has been initialized the player's animation can be changed 108 // to the new one. 109 ChangeAnimation(player.animation, newAnimation); 110 111 // Do whatever is necessary for dealing damage and all that here. 112 113}

Lasaqus7

Cheers for the help guys.

I'm working through your code taron, trying to understand it all, but I have ran into a few issues and questions.

#SelectExpand
1struct Animation 2{ 3 enum 4 { 5 IDLE, 6 MOVE, 7 ATTACK, 8 ... 9 };

How do I declare or reference these within my main code ? (I've tried animation.IDLE, animation[IDLE], Animation.animation[IDLE] but none work, unless as its a struct it works differently to the way I done my enum keys[].)
I'm assuming these would be where I code my variables for different animations. I haven't done this or seen this before.

Eg if ATTACK, use animationRow 1, and animationColumns = 12
if IDLE, use animation Row 2 etc.

Then I have added this into my Player struct

#SelectExpand
1struct Player 2{ 3 ... 4 // Hold the animation data; 5 Animation animation; 6 ... 7}

However I do get the following errors
C2146: syntax error: missing ';' before identifier 'animation'
C4430: missing type specifier - int assumed.Note C++ does not support default-int
C2039: 'animation' : is not a member of 'Player'(previously all my Player struct worked) And my Player struct is in a objects.h file, if this makes any difference.

I can place this in my main body of code although this would stop PlayerAttack from working as it would no longer reference to player (I think).

I do like the way you wrote this aswell, I understand most of it can see how it works and how it does the animations ;D

Dizzy Egg

You need a ; at the end of the struct!

struct Player
{
    Animation animation;
};

Lasaqus7

I copied that from taron, didn't see his didn't have a ; at the end of the struct.
In my code I do have this at the end.

Dizzy Egg

You haven't put ... in there have you??

Lasaqus7

No

My current player struct looks like this (this is working before starting to add in taron's code) I have added the Animation animation just to show how it would be

#SelectExpand
1struct Player 2{ 3 int ID; 4 int x; 5 int y; 6 int speed; 7 int boundx; 8 int boundy; 9 10 int dirX; 11 int dirY; 12 13 int maxFrame; 14 int curFrame; 15 int frameCount; 16 int frameDelay; 17 int frameWidth; 18 int frameHeight; 19 int animationColumns; 20 int animationDirection; 21 22 int animationRow; 23 24 int imageWidth; 25 int imageHeight; 26 27 int PlayerMaxHP; 28 int PlayerCurHP; 29 int PlayerMaxMana; 30 int PlayerCurMana; 31 int PlayerStr; 32 int PlayerInt; 33 int PlayerAgi; 34 int PlayerArmour; 35 int PlayerCrit; 36 int AttackCount; 37 38 int PlayerGold; 39 40 bool isAlive = true; 41 bool Attacking = false; 42 bool Crit = false; 43 44 ALLEGRO_BITMAP *image; 45 46 Animation animation; 47};

And then the error being displayed is attached

taron 

I often forget to put a ';' after classes and structs if I recently programmed in a different language.

Lasaqus7 said:

How do I declare or reference these within my main code ? (I've tried animation.IDLE, animation[IDLE], Animation.animation[IDLE] but none work

Animation::IDLE would be the correct syntax.

Also you'd have to add int animationState or something inside the Animation struct to track which animation is being played, I forgot to add that.

Quote:

C2146: syntax error: missing ';' before identifier 'animation'
C4430: missing type specifier - int assumed.Note C++ does not support default-int

Generally this means it doesn't recognize the type. If you've put the Animation in its own header file, make sure to include that header in your Player header, otherwise the compiler will not be able to find the definition of the type.
If you've defined the Animation in your main.cpp or whatever file, move it to a header file.
So it would look something like this:

#ifndef PLAYER_H
#define PLAYER_H

#include "animation.h"

struct Player
{
   ...
};

#endif

Or the shorter but less portable way. (Non standard extension, but supported by many compilers)

#pragma once
#include "animation.h"

struct Player
{
   ...
};

Dizzy Egg

Yeah the code is fine, have you declared Animation before player?

Lasaqus7

Nope, I had declared Animation after it, changed it and that's fixed that part, thanks Dizzy.

Taron, thanks for the help on the correct syntax, now to work on getting it right, not long left to finish it

All my structs are in the same file, I only have 2 objects.h (all my structs) and main.cpp

Hopefully I should be able to figure this out now.

Dizzy Egg

Cool! Let us know if you get stuck again....I'm warming up for Speedhack so need motivation to get coding Allegro5 again! ;D

Lasaqus7

I think i'm doing this wrong :-(

#SelectExpand
1else if (state == COMBATIDLE) 2 { 3 if (threshold > CheckDistance(Human.x, Human.y, Orc.x, Orc.y)) 4 { 5 ChangeState(state, COMBATCHASING); 6 } 7 8 if (keys[KEY_1]) 9 { 10 ChangeAnimation(animation, newAnimation); <-- This errors - identifier "newAnimation" is undefined 11 } 12 }

I have placed my ChangeAnimation in my ALLEGRO_EVENT_TIMER code, so to me it says, if Player is in the CombatIdle state and KEY_1 is pressed then change the animation.

#SelectExpand
1void ChangeAnimation(Animation &animation, const Animation &newAnimation) 2{ 3 if (animation.cancellable) 4 { 5 if (Animation::IDLE) 6 { 7 animation.maxFrame = 1; 8 animation.animationRow = 1; 9 animation.animationColumns = 1; 10 animation.cancellable = true; 11 animation.loop = false; 12 animation.animationState = 1; 13 } 14 else if (Animation::ATTACK) 15 { 16 animation.maxFrame = 13; 17 animation.animationRow = 0; 18 animation.animationColumns = 13; 19 animation.cancellable = false; 20 animation.loop = false; 21 animation.animationState = 2; 22 } 23 animation = newAnimation; 24 } 25}

Then for the function I have placed some states of the animations.

What would go in place of newAnimation in this line ChangeAnimation(animation, newAnimation); ?

I tried Animation::ATTACK, animation::ATTACK, animation.ATTACK with no luck.

Dizzy Egg

Before you use 'newAnimation', do you create it?

ie:

Animation *newAnimation;

ChangeAnimation(animation, newAnimation);

(the above code wont work, I was just seeing if you'd 'created' the newAnimation...)

EDIT:

Consider this...

int i = 5;

void changeInt(int &arg)
{
     arg = 20;
}

int main()
{
    changeInt(i);
    
    //i now = 20!!
}

Lasaqus7

That will be it, no I haven't created it apart from in the ChangeAnimation function. I see that part is in the PlayerAttack part of tarons code.

I feel i'm getting more and more confused as I delve further into the depths of the unknown :-) And going from zero Allegro5 experience to doing it alot everyday is also confusing me.

Cheers Dizzy :-)

Dizzy Egg

Try not to go too far down a road that is suggested on here if it seems alien; I used 1 .cpp file and hundreds of separate variables for my first 20 odd projects....LONG before I started delving into enums and structs....keep it simple, and as soon as something doesn't make sense, come on here and post some code...that's how I learned!

Lasaqus7

Cheers for the advice.

So trying to do it in a way I understand. Using Mike Geig's tutorial on his spaceshooter he has a comet going across his screen using no input. It move across without any keys being involved and his code for that is

#SelectExpand
1void UpdateComet(Comet comets[], int size) 2{ 3 for(int i = 0; i < size; i++) //His comet array size, so for every comet available 4 { 5 if(comets[i].live) //Is the comet on screen then do the below 6 { 7 if(++comets[i].frameCount >= comets[i].frameDelay) 8 { 9 comets[i].curFrame += comets[i].animationDirection; 10 if(comets[i].curFrame >= comets[i].maxFrame) 11 comets[i].curFrame = 0; 12 else if( comets[i].curFrame <= 0) 13 comets[i].curFrame = comets[i].maxFrame - 1; 14 15 comets[i].frameCount = 0; // Do all the updating and frame cycling to appear as if it is moving 16 } 17 18 comets[i].x -= comets[i].speed; //Move the comet 19 } 20 } 21}

I added comments to compare to my code.

So based on that, I want a animation to happen basically the same way except I press a key first so I press the key and declare that the player is attacking

#SelectExpand
1void PlayerAttack(Player &Human) 2{ 3 Human.Attacking = true; 4if (Human.Attacking) // Is my player attacking, then do the code below 5 { 6 ++Human.frameCount; 7 if (Human.frameCount > Human.frameDelay) 8 { 9 ++Human.curFrame; 10 Human.frameCount = 0; 11 if (Human.curFrame >= Human.maxFrame) // All the frame cycling stuff as above 12 { 13 Human.curFrame = Human.maxFrame; 14 Human.Attacking = false; //Has the animation reached the end frame, if so player stops attacking and end the function 15 } 16 } 17 }

So looking at the 2 codes, why is one allowing it to be cycled all the time and perform the animation across the screen, yet with my code only cycle through the animation when I actually hold down the key. From what I gather I have removed the keypress part by adding the PlayerAttacking, so my PlayerAttacking is now similar to If the comet is onscreen.

The only big difference I see is
My code

#SelectExpand
1if (keys[KEY_1]) 2 PlayerAttack(Human);

Mike Geig's code

#SelectExpand
1UpdateComet(comets, NUM_COMETS);

We both have our calls in the ALLEGRO_EVENT_TIMER section aswell.

EDIT_ OMG I got it to work
On the bad side is when I move after attacking it plays that animation again, but I got it to work ;D

Dizzy Egg

So...do you want your animation run whilst you're holding down KEY_1, or simply run it when KEY_1 is pressed?

EDIT!

YOU GOT IT! 8-) ;D

Lasaqus7

I just edited at the same time but I kinda got it to work

I just wanted my player to move about, but if the 1 key was pressed (and released) it would play a attack animation.

As of now when I press 1 it does plays the attack animation

However when I move after that it keeps playing the attack animation instead of the moving ones. So need to fix that

But it is progress

Dizzy Egg

Cool :P

EDIT:

Human.Attacking = true;
if (Human.Attacking) // Is my player attacking, then do the code below

..hmmmmm ;)

Lasaqus7

You right

I changed to this

#SelectExpand
1if (keys[KEY_1]) 2Human.Attacking = true; 3 4if (Human.Attacking) 5PlayerAttack(Human);

Where before I was doing

#SelectExpand
1if (keys[KEY_1]) 2PlayerAttack(Human);

Then putting Human.Attacking = true; in my function.

It was probably suggested way earlier than now I just didn't get it in the right place

EDIT:- If press 1 while moving he plays his attack animation all the time, until i release left or right and repress it :(

Dizzy Egg

I imagine there's some confusery in your event keydown if/else type code! If you like you can post a whole bunch of code here, it seems we're getting on ok! I can do no more tonight as I am inebriated, but tomorrow I will be able to quest on with you, we'll figure it out bro 8-)

Lasaqus7

My key events are as follows:-

#SelectExpand
1ALLEGRO_EVENT ev; 2 al_wait_for_event(event_queue, &ev); 3 4 if (ev.type == ALLEGRO_EVENT_TIMER) 5 { 6 render = true; 7 8 //UPDATE=========================================== 9 if (keys[UP] || keys[W]) 10 MoveHumanUp(Human); 11 else if (keys[DOWN] || keys[S]) 12 MoveHumanDown(Human); 13 else if (keys[LEFT] || keys[A]) 14 MoveHumanLeft(Human); 15 else if (keys[RIGHT] || keys[D]) 16 MoveHumanRight(Human); 17 else if (keys[SPACE]) 18 { 19 20 } 21if (state == MENU) 22 { 23 } 24 else if (state == PLAYING) 25 { 26 } 27 else if (state == COMBATSCREEN) 28 { 29 } 30 else if (state == COMBATIDLE) 31 { 32 if (threshold > CheckDistance(Human.x, Human.y, Orc.x, Orc.y)) 33 { 34 ChangeState(state, COMBATCHASING); 35 } 36 37 if (keys[KEY_1]) 38 { 39 Human.Attacking = true; 40 41 } 42 43 if (Human.Attacking) 44 PlayerAttack(Human); 45 46 } 47else if (ev.type == ALLEGRO_EVENT_KEY_DOWN) 48 { 49 switch (ev.keyboard.keycode) 50 { 51 case ALLEGRO_KEY_ESCAPE: 52 keys[ESCAPE] = true; 53 break; 54 case ALLEGRO_KEY_SPACE: 55 if (canPressKey = true) 56 { 57 keys[SPACE] = true; 58 canPressKey = false; 59 60 keyPressed = !keyPressed; 61 } 62 break; 63 case ALLEGRO_KEY_UP: 64 keys[UP] = true; 65 break; 66 case ALLEGRO_KEY_DOWN: 67 keys[DOWN] = true; 68 break; 69 case ALLEGRO_KEY_LEFT: 70 keys[LEFT] = true; 71 break; 72 case ALLEGRO_KEY_RIGHT: 73 keys[RIGHT] = true; 74 break; 75 case ALLEGRO_KEY_W: 76 keys[W] = true; 77 break; 78 case ALLEGRO_KEY_S: 79 keys[S] = true; 80 break; 81 case ALLEGRO_KEY_A: 82 keys[A] = true; 83 break; 84 case ALLEGRO_KEY_D: 85 keys[D] = true; 86 break; 87 case ALLEGRO_KEY_C: 88 if (canPressKeyC = true) 89 { 90 keys[C] = true; 91 canPressKeyC = false; 92 93 ckeyPressed = !ckeyPressed; 94 } 95 break; 96 case ALLEGRO_KEY_1: 97 keys[KEY_1] = true; 98 break; 99 } 100 } 101 else if (ev.type == ALLEGRO_EVENT_KEY_UP) 102 { 103 switch (ev.keyboard.keycode) 104 { 105 case ALLEGRO_KEY_ESCAPE: 106 done = true; 107 break; 108 case ALLEGRO_KEY_SPACE: 109 canPressKey = true; 110 keys[SPACE] = false; 111 break; 112 case ALLEGRO_KEY_UP: 113 keys[UP] = false; 114 break; 115 case ALLEGRO_KEY_DOWN: 116 keys[DOWN] = false; 117 break; 118 case ALLEGRO_KEY_LEFT: 119 keys[LEFT] = false; 120 break; 121 case ALLEGRO_KEY_RIGHT: 122 keys[RIGHT] = false; 123 break; 124 case ALLEGRO_KEY_W: 125 keys[W] = false; 126 break; 127 case ALLEGRO_KEY_S: 128 keys[S] = false; 129 break; 130 case ALLEGRO_KEY_A: 131 keys[A] = false; 132 break; 133 case ALLEGRO_KEY_D: 134 keys[D] = false; 135 break; 136 case ALLEGRO_KEY_C: 137 keys[C] = false; 138 break; 139 case ALLEGRO_KEY_1: 140 keys[KEY_1] = false; 141 break; 142 } 143 }

Edgar Reynaldo
Lasaqus7 said:

#SelectExpand
1 case ALLEGRO_KEY_SPACE: 2 if (canPressKey = true) { 3 keys[SPACE] = true; 4 canPressKey = false; 5 keyPressed = !keyPressed; 6 } 7 break; 8//... 9 case ALLEGRO_KEY_C: 10 if (canPressKeyC = true) { 11 keys[C] = true; 12 canPressKeyC = false; 13 ckeyPressed = !ckeyPressed; 14 } 15 break;

You are checking against true in both cases, which will always evaluate to true.

See my response to you in an earlier thread :
https://www.allegro.cc/forums/thread/615373/1013171#target

For example, here you should have used this :
if (true == canPressKeyC) {
or this :
if (canPressKeyC) {
instead of this :
if (true = canPressKeyC) {(which would have given you an error)
or this :
if (canPressKeyC = true) {(which always performs an assignment and evaluates to true)

Lasaqus7

So a == rather than a single =

Ok i'll get that changed now. I did read that, didn't fully understand what was being discussed, I was happy that it started working and then started working on another area.

Thanks Edgar

taron 

See

taron  said:

Animation::IDLE would be the correct syntax.

Also you'd have to add int animationState or something inside the Animation struct to track which animation is being played, I forgot to add that.

So you can/could do
animationState = Animation::IDLE; ...

switch (animationState)
{
   case Animation::IDLE:
        ...
   break;
   case Animation::MOVE:
        ...
   break;
}
// or
if (animationState == Animation::IDLE)
{
   ...
}

Enums are actually quite simple.
Much like structs, unions and classes you can also give them a name instead of making them anonymous.

#SelectExpand
1enum Numbers 2{ 3 ZERO, // enums start at 0 4 ONE, 5 TWO 6}; 7 8Numbers number = Numbers::ONE; 9std::cout << number << '\n'; // Will print '1' 10int i = number; // Implicit cast to integer is allowed 11std::cout << i << '\n'; 12 13enum Values 14{ 15 A = 5, // You can assign values explicitly if you so desire 16 B = 2 17}; 18 19std::cout << Values::A << ' ' << Values::B << '\n'; 20// enums aren't contained in their own scope 21std::cout << A << '\n'; // Same as Values::A 22 // Which is why I made it an anonymous enum inside of the struct. 23// C++11 adds a solution for this (Supported in VS 2013 iirc) 24enum class NewEnum 25{ 26 C, 27 D 28}; 29 30std::cout << (int)NewEnum::C << std::endl; // Have to cast explicitly to an int now 31// std::cout << NewEnum::C << std::endl; // Won't compile, can't find overloaded operator << for type of NewEnum 32// std::cout << C << std::endl; // Won't be able to find identifier 'C', scope is explicit now. 33NewEnum newEnum = NewEnum::D;

If you want to make use of enums in new code, you should probably default to using enum class instead of simply enum.

Lasaqus7

@Edgar

Edgar said:

For example, here you should have used this :
<if (true == canPressKeyC) {
or this :
if (canPressKeyC) {

This didn't work for me after I made the change, so i reverted back to the original as that is working as intended, not sure why but it is working.

@Taron
What I think I will do rather than trying to re-work my code at this stage, is that once I'm done, I'll start a fresh project only using code for the enum/structs for the animation and play about with it there, I would like to try and get that working.

Thread #615392. Printed from Allegro.cc