Going from running to standing?
Blitz3D Forums/Blitz3D Beginners Area/Going from running to standing?
| ||
look whos backXD I have been working on the basic mechanics of my game(running,jumping etc) and i'm kinda stuck with a problem with making my character switch stances. ok, so I coded a system where when the arrow keys (in this case the right key) is pressed, he plays his running animations and when let go, he switches back to his standing animation. The problem is that while his running animation work properly when they are supposed to, his standing animation doesn't play properly and gets stuck in the first frame. I think it is becuase it being apart of the main loop of the game, making his standing animation play repeatedly, causing it to never go beyond the first frame, but that's just what I think. Could someone maybe look at my code and try to see why this problem could be happening? This is the animation handling piece of the code( Movement is still very unpolished at this state ) Hope this post wasn't to much of a pain in the ass to readXD but I really could use some help with this right now. Last edited 2011 |
| ||
Currently, I believe the above snippet is essentially the same as:If (KeyDown(205)) TESTX=TESTX+.4 If (TESTX>5) TESTX=5 End If seq=1 animtype=1 animspeed=.9 Else TESTX=0 seq=2 animtype=2 animspeed=.3 EndIf Animate TEST_MODEL1,animtype,animspeed,seq,10 RotateEntity TEST_MODEL1,0,TESTYAW,0 TranslateEntity TEST_MODEL1,TESTX,0,0 EXCEPT the use of KeyHit in the original code only updates when the key is pressed. If it's held down, as in KeyDown() then it will only return a TRUE (or non-zero) value on the initial press. |
| ||
I noticed that you're having to use custom speeds for each sequence. You might as well 'bake' these speeds in your animation software (by scaling the timeline for it to grow or shrink), so you just have to handle the sequences back in B3D and not their speed as well. Then you know all sequences have 1.0 speed. |
| ||
Malice So the problem is that while kirby's (ssbm model) running animation is updated only when the right key is hit, allowing it to only update once letting the animation play correctly, while the standing animation plays only when the TESTX variable equals 0, causing the standing animation to update constently and forever, keeping the animiation from going beyond the first frame. whoo, that was a mouthful. So basically it seems that my animation playing system is faulty. I'd be okay with rewriting it, but I don't know how I can keep the animation from playing correctly if it is in the game's main loop. |
| ||
You need a better state machine.isAnimating = Animating(TEST_MODEL1) KeyRIGHT = KeyDown(205) ;Store the current values in variables so you can use them better. KeyLEFT = KeyDown(203) ;Each KeyDown\KeyHit returns a value which is '1' or '0', so you can perform math on them like subtraction, addition etc. If (KeyRight=1) And (KeyLeft=0) Then ANIM_State = 1 ;Just set up the state. EndIF If (KeyLeft=1) And (KeyRight=0) Then ;Only move left if the right key is unpressed. ;[...] EndIf If (KeyRight + KeyLeft + [...]) = 0 Then ;If none of the keys are pressed (the sum of them equals zero). ANIM_State = 0 ;Idle animation EndIf Select ANIM_State Case 0 If Not isAnimating Then Animate TEST_MODEL1,1,1.0,SEQ_idle,10 Case 1 MoveEntity [...] ;Control movement and other properties here, not at the KeyDown condition. If Not isAnimating Then Animate TEST_MODEL1,1,1.0,SEQ_walkLeft,10 Case 2 [...] End Select Last edited 2011 |
| ||
I haven't looked at your code, but I know what the problem is. There's one command I use all the time to fix this problem: Global standing = ExtractAnimSeq(entity,first_frame,last_frame) ;Name your running sequence ;Main Loop... If AnimSeq(entity) <> standing Animate entity, standing EndIf You can use that little bit above in combination with any other key downs, mouse downs, ect., and this will stop the issue of repeatedly calling "Animate" on your entity, thus only showing the first frame of animation. Kryzon's method works as well, and it looks like his applies to the code you've supplied. |
| ||
I always overlook AnimSeq; it's a great suggestion. It's definitely better than checking with Animating(), since you're comparing current sequences instead of animating or not. |
| ||
Kryzon Your right. animseq is a great function. With the use of it and ALOT of headaches, I was able to make the his animation cycles work properly when they should. This was the section of code where animseq became a hero I tried out your idea of using cases to store and use the animations, but I felt that it was a rather strange way to use the case function and I couldn't get it working right when I tried making my own version of it. Despite me actually getting kirbys animations to work right, I still have some concerns. Everything may seem fine now, but I just started to mechanics of my game. Kirby's animations work good, but he's moving in only one direction. Throughout the games steady progress, kirby will be able to do more things, such as jumping and attacking and other stuff. My concern is that will my little code be able to take on more than just 2 animations? I know theres no way to now until the progress is actually made, but I really wouldn't want to end back in the forums with the SAME exact question, so what do you guys think? Last edited 2011 Last edited 2011 |
| ||
That's why I recommended a more clean state system. You need to make it more modular because you're going to have lots of sequences and properties for a fully animated character, and it'll get very complex in the end. With a clean, modular state machine you can very easily add new states. Not only this but it allows you to make sequences progress into one another: Select animState Case JUMPING If AnimSeq(Player) <> animJumping Then Animate Player,1,1.0,animJumping,10 playerY = playerY + jumpForce jumpForce = jumpForce - gravity If jumpForce < 0.1 Then animState = FALLING ;Change animation sequence and state when player stalls in the jump. Case FALLING If AnimSeq(Player) <> animFalling Then Animate Player,1,1.0,animFalling,10 playerY = playerY + jumpForce jumpForce = jumpForce - gravity If EntityCollided(Player,3) Then animState = TOUCHDOWN ;When player reaches the ground or a platform, change his animation to "bounce" or "absorb the impact". ;[...] End Select I think the Select is the most important part. |
| ||
I find it more easy to control animations myself using SetAnimTime. Suppose the model has only one long sequence. Then you can something along the lines of the following: if keydown(30) start_f = 0: stop_f = 30: spd_f# = 1 if keydown(31) start_f = 31: stop_f = 34: spd_f# = 0.1 frm# = frm# + spd_f# if frm < start_f then frm = start_f if frm > stop_f then frm = start_f SetAnimTime ent, frm |
| ||
Warner I think the animtime technique would work for MD2 models but since i'm using b3d models it probably won't work as well. Kryzon I honestly now do see how using a module based animation system would work out better but the problem is that I don't understand it very well. I tried writing my own version of the code according to yours but when your programming, it's impossible to do anything right if you simply don't know what your doing, for example, what does the <> supposed to represent in the code? I heard somewhere a while ago that it mean "neither" but i'm not sure and it's kinda confusing me. Can you please explain the module animation system more? I just can't seem to understand it very well. |
| ||
"<>" is not equal if i remember correctly (if not smack me over the head and correct me!) |
| ||
The <> symbol just means "not equal to", "not the same thing as", "different", or if you want to get real technical, "Less than or Greater than", which just means that the expression will be true only if the variable is different than the value listed. It's a nice operator in Blitz, but I can't think of any situation of the top of my head that couldn't be re-written with the "Not" command. For example,Const x = 1 If x <> 1 ;When I type this line, I say under my breathe while I type "If x is not equal to 1" Print "This line will never get printed" EndIf could just as easily be written as Const x = 1 If Not x = 1 Print "This line will never get printed" EndIf Let me break down Kryzon's code for you. The select command is especially useful if you have a variable that is going to have a lot of different but specific values throughout your game. Think of the Select command as a giant list of "If" statements all contained in one block of code. Without the Select command, some code could look like this: Global StateOfBeing$ = "Idle" ;Here, the player changes the StateOfBeing$ variable based on gameplay If StateOfBeing$ = "Idle" ;Do some stuff here EndIf If StateOfBeing$ = "Jumping" ;Do some stuff here EndIf If StateOfBeing$ = "Attacking" ;Do some stuff here EndIf If StateOfBeing$ = "Defending" ;Do some stuff here EndIf ;This could go on for a very long time, depending on how many states you have All of those "If...EndIf" blocks can get a little ugly, so why not combine all of them using the Select command? Here's the same bit of code, but modified to use the Select command. Global StateOfBeing$ = "Idle" ;Here, the player changes the StateOfBeing$ variable based on gameplay Select StateOfBeing$ Case "Idle" ;Do some stuff here Case "Jumping" ;Do some stuff here Case "Attacking" ;Do some stuff here Case "Defending" ;Do some stuff here End Select ;This could go on for a very long time, depending on how many states you have As you can see, the code appears cleaner, and you don't have to type so many "If...EndIf"s. What I get from Kryzon's example is that you should set up your animations using this process. I would even go as far as setting up a state of being string for Kirby, then perform all of your actions, such as movement, animation ect., based off of those state of beings. Here's a rough example of what the rundown might look like: Graphics3D 640,480 ;set up gfx SetBuffer BackBuffer() ;double buffering... Const TYPE_KIRBY = 1 ;entity types for collisions Const TYPE_LEVEL = 2 ;entity types for collisions Global camera = CreateCamera() ;make a camera MoveEntity camera,0,10,-10 ;move it up and backwards Global level = CreatePlane() ;make a level EntityType level,TYPE_LEVEL ;set the collision type Global kirby = LoadAnimMesh("kirby.b3d") ;load kirby! TranslateEntity kirby,0,1,0 ;move kirby off the ground EntityType kirby,TYPE_KIRBY ;set the collision type PointEntity camera,kirby ;makes for an easy 3rd person camera EntityParent,camera,kirby ;makes for an easy 3rd person camera Global kirbyanimstand = ExtractAnimSeq(kirby,1,10) ;This is how I load animation. You might use a different process Global kirbyanimjump = ExtractAnimSeq(kirby,11,20) ;name each animation Global kirbyanimrun = ExtractAnimSeq(kirby,21,30) ;name each animation Global kirbysob$ = "standing" ;create a variable for Kirby's State of Being, set it to "standing" Collisions TYPE_KIRBY,TYPE_LEVEL,2,3 ;set collisions ;MAIN LOOP ;---------------------------- While Not KeyDown(1) GetNewKirbySOB() ;The function is below UpdateKirby() ;The Function is below PointEntity camera,kirby UpdateWorld RenderWorld Flip Wend ClearWorld End ;FUNCTIONS LIST ;--------------------------------- Function GetNewKirbySOB() ;Get's Kirby's new State of Being, changes kirbysob$ variable ;First, let's see if kirby should be running If kirbysob$ <> "jump" Or kirbysob$ <> "floating" ;kirby can only run or jump while on the ground If Not KeyDown(RIGHT_KEY) ;If we're not pushing the right key If Not KeyDown(LEFT_KEY) ;If we're not pushing the left key kirbysob$ = "standing" ;Kirby should now be standing EndIf EndIf If KeyDown(RIGHT_KEY) ;If we're pushing the right key If Not KeyDown(LEFT_KEY) ;we can't push both keys at the same time kirbysob$ = "runright" ;Kirby should now be running right EndIf EndIf If KeyDown(LEFT_KEY) ;If we're pushing the left key If Not KeyDown(RIGHT_KEY) ;we can't push both keys at the same time kirbysob$ = "runleft" ;Kirby should now be running left EndIf EndIf If KeyDown(RIGHT_KEY) And KeyDown(LEFT_KEY) ;If we are pushing both keys kirbysob$ = "standing" ;Just make Kirby stand EndIf ;Next, see if he should jump If KeyHit(SPACE_BAR) kirbysob$ = "jump" ;Kirby should now leap off the ground EndIf EndIf End Function Function UpdateKirby() ;Make Kirby do new actions based on his new State of Being Select kirbysob$ ;Open a Select Command (like multiple "if"s) Case "standing" ;If Kirby should be standing If AnimSeq(kirby) <> kirbyanimstand ;If Kirby isn't already animated to stand Animate kirby,kirbyanimstand ;Animate Kirby to stand EndIf Case "runright" ;If Kirby should be running right If AnimSeq(kirby) <> kirbyanimrun ;If Kirby isn't already animated to run Animate kirby,kirbyanimrun ;Animate Kirby to run EndIf RotateEntity kirby,0,90,0 ;Turn Kirby to the right. At least, I think this is to the right? MoveEntity kirby,0,0,1 ;Run Kirby forward (to the right) 1 unit per loop Case "runleft" ;If Kirby should be running left If AnimSeq(kirby) <> kirbyanimrun ;If Kirby isn't already animated to run Animate kirby,kirbyanimrun ;Animate Kirby to run EndIf RotateEntity kirby,0,-90,0 ;Turn Kirby to the left. At least, I think this is to the left? MoveEntity kirby,0,0,1 ;Run Kirby forward (to the left) 1 unit per loop Case "jump" ;If Kirby should be jumping If AnimSeq(kirby) <> kirbyanimjump ;If Kirby isn't already animated to jump Animate kirby,kirbyanimjump ;Animate Kirby to jump EndIf TranslateEntity kirby,0,50,0 ;Shoot Kirby up in the air! kirbysob$ = "floating" ;After Kirby's in the air, float to the ground Case "floating" ;if Kirby should be floating TranslateEntity kirby,0,-1,0 ;Gravity... If EntityCollided(kirby,TYPE_LEVEL) ;If Kirby touches the ground kirbysob$ = "standing" ;Kirby should now be standing EndIf ;As always, feel free to add any more Cases here with actions to go along with each case End Select End Function Hopefully this helps. I can get a little lengthy with my explanations, so sometimes it's more confusing than helpful to read my responses. lol. EDIT: I should also note that the above example was written from the top of my head, so it's untested and will not execute as it is now. It was more or less written for demonstration of concept, but with a couple of minor changes and an actual model to load with animation, it would (in theory), execute like it should. Last edited 2011 |
| ||
Great break-down Rob. @TaGames: using a 'Select...Case' allows you to have your code behave differently depending on the state of a certain variable (like that 'State of Being' that Rob proposed). This is especially useful since each state might have different conditions you want to check. If we're dealing with the "Floating" state, you might want to check if the player touched the ground so we change to the "Idle" or "Running" states. If the player is "Swimming", you might want to display an air-meter and start draining air from a counter, and while in this state check if the player ever leaves the water so you can hide the air-meter back and reset the air amount the player has. Every 'Case' will specify how the characters should behave, and how you should interpret what the player is currently doing. With this in mind you might actually do this (in the same function): [Store the current state of the keyboard keys in variables - like I showed in post #5] [Head to the Select which will run\select the appropriate piece of code for the current state of being] [Interpret the state of the keyboard keys accordingly and handle any other game elements based on the current state]This allows you to implement states such as "insideCart", where Kirby gets into a cart and his commands and the camera behave differently. Or you have to aim a sniper rifle and the keyboard keys now instead of controlling the character itself are controlling the crosshair of the rifle. The reason for keeping this system clean is that you won't be dealing with a simple demo where you can roughly patch things that don't work properly just to make things work - you'll have multiple levels and a multitude of states, and things can get out of hand pretty quickly if you don't start the clean route from the beginning (not only with this system but with anything else you code). |
| ||
thanks for the help and explaination. I've practically fallen in love with the module system kryzon insisted (finally learned how to do it thanks to robs explaination) thanks for all the help guys:) |