A tutorial that shows how organize graphics and sprites in a fighting game, how to implement the controls and manage the various moves.
Making a Beat-Em-Up Fighting Game in Flash: Part FOUR
Many have written to me asking for me to post swf files. Save them some
time, that kind of thing. Well, if you're thinking of doing the same, don't bother. I'm doing your
a favour by forcing you to code this
puppy bit by bit. You will thank me after. Learn by doing. And when it's all done, when
you've finished all these tutorials and absorbed everything you'll have
built your
knowledge base enough to go your own way and start creating your own
little Flash beauties without relying on others. And then we won't have
any crappy Pong remakes on the net anymore, but a ton of sweet, sweet
Streets of Rage/Vigilante/Streetfighter clones. Less Pong, more top-notch hard action games. Ok, on with the show.
When making a sprite/movie clip jump, we need to consider two
important forces, gravity and upward velocity.
Now, if you jumped off the moon, which has no gravity (I think) you would go up
and up until Superman came to get you. On Earth, the force
you use to launch yourself into the air when you jump, is quickly
countered by the powerful force called gravity, and your ass is smacked
back down to the ground.
So, easy, we've just to put those physics into code. One increasing
force, and another one to counter it. In code talk, these forces can be
represented by two variables u_velocity, which translates your image UP a set amount every
frame, and gravity,
that slowly snowballs over the other one until it is the stronger force
of the two- thus sucking you back to earth. Then, you need a floor for
the guy to land on.
Now, there is more than one way to skin a, uhm... jumping routine. You need to decide upon which best fits your game.
Let's take a look at some examples.
VELOCITY-BASED
Take StreetFighter 2 for example. On every scene (exception-bonus
stage) you have only a one level ground. There's no platforms, no cliffs to fall off. If your character jumps, you
only
have to check whether or not his sprite/mc/feet have touched the ground
again, and then the jump is complete.
So you could say "IF THIS MC'S _Y VALUE IS THE SAME AS WHEN HE JUMPED,
STOP THE JUMP". Even if you get punched in mid-air, the only thing you
would have to do would be to add a little extra value to the u_velocity value,
so that the mc floats for a bit longer. The same routine would still work.
TIME-BASED
Even simpler. The pseudocode would look like.
timer=0;
IF UP PRESSED
{
jump=true;
if(timer < WHATEVER TIME YOU SET TO LAND AGAIN)
{
Do jump animation();
Check for jump_kicks_etc();
timer++:
}
else
{
jump=false;
timer=0;
}
}
Probably works for games like Yi Ar Kung Fu (okay now you know how old I am).
Most games however, require more complex code that takes into
consideration platforms you can fall
from or bump into, or ceilings and things. Depending on the speed and
height of his fall, you may even have to sweep ahead of his projectory
and check the collision before he's even anywhere near the ground,
otherwise risking getting a sprite stuck halfway into the floor.
However, within these sets
of tutorials, we're not aiming to rewrite Super Mario, just a little
fighting game, so let's keep things simple. Besides, you could Google
up a dozen Flash tutorials for jumping in a second.
No. What I'm going to show you is not much more complicated than the
velocity-based idea, and
deals with simply checking if a movie_clip under the characters feet is
has a higher _y value then stop him falling. This isn't suitable for a
Sonic game
or any platformers in general. It wouldn't work even for the real
SplatterHouse game. I simply want to recreate the
physics behind a jump, nothing advanced.
Let's begin by organising our code a little better before it turns into
illegible spaghetti. We're going to start putting our routines into functions. They're reusable and you can't live without them. So scrap all of the previous
code- literally delete all of your AS code- but leave the movieclips
where they are in the library. If you're with me up until now , I'm
assuming that you've created a jump animation within the main Rick
movie clip alongside all the other moves. Make sure to name the frame it is on 'jump'.
I also hope you know what a function is. Actually, you've been using
one all along- onEnterFrame- a
function that runs what ever code is within it at the speed of the game
framerate.
function Initialize()
{
rick_mc.step=15;
rick_mc.attack = false;
rick_mc.stance= 1;
rick_mc.crouch=false;
keydown=false;
//Add a few new variables:
rick_mc.uvel=40;
rick_mc.gravity=6;
rick_mc.jump=false;
}
In the world of
game-programming, having an Initialise function is handy for everytime
you move onto a new level. or restart the game entirely.
Next up, let's wrap the movement code up in one. Directly below stick this one in there:
function Movement()
{
if (Key.isDown (Key.RIGHT) )
{
rick_mc.stance=1;
rick_mc._x+=rick_mc.step;
rick_mc.gotoAndStop("walk");
}
else if (Key.isDown (Key.LEFT) )
{
rick_mc.stance=0;
rick_mc._x-=rick_mc.step;
rick_mc.gotoAndStop("walk");
}
else if (Key.isDown (Key.DOWN) )
{
rick_mc.gotoAndStop("crouch");
rick_mc.crouch=true;
}
else if (!Key.isDown () )
{
rick_mc.gotoAndStop("stance");
rick_mc.crouch=false;
}
// Jump check needs to be out of the else...
// if loop or character will not jump while walking.
if (Key.isDown (Key.UP))
{
rick_mc.gotoAndStop("jump");
rick_mc.jump=true;
}
if (Key.isDown (Key.CONTROL) && keydown==false)
{
rick_mc.attack=true;
}
}
All making sense so far?
As you can see, this new functions also checks for jumping, and sets a flag if UP is pressed.
Next up is our snazzy new JUMP function.
But first, we need to create a ground, or else Rick will fall for eternity. Let's make a movie clip to represent the floor.
1. Tap CTRL+F8 to make a new symbol.
2. Name it 'ground' and choose Movie Clip.
3. Create
a box using the Rectangle Tool, any size. Then click on it with the
arrow, and change the Shape height and width: H=35, W=600.
4. Come
out of the symbol and onto the main scene with Rick there, and drag an
instance of the movie clip 'ground' onto the stage, just below Ricks
feet like in the diagram.
5. It's important to name your instance, so click on it once, and
within the properties type in 'ground' (yes again) where it says
Instance Name.
function Jump()
{
if (Key.isDown (Key.LEFT) )
{
rick_mc.stance=0;
rick_mc._x-=rick_mc.step;
}
else if (Key.isDown (Key.RIGHT) )
{
rick_mc.stance=1;
rick_mc._x+=rick_mc.step;
}
if(!rick_mc.attack)
{
if (Key.isDown (Key.DOWN))
{
rick_mc.gotoAndStop("crouch");
rick_mc.crouch=true;
}
else if (!Key.isDown () )
{
rick_mc.gotoAndStop("jump");
rick_mc.crouch=false;
}
}
if (Key.isDown (Key.CONTROL) && keydown==false)
{
rick_mc.attack=true;
}
rick_mc._y-=rick_mc.uvel;
rick_mc.uvel-=rick_mc.gravity;
if(rick_mc._y+20 > ground_mc._y+65)
{
rick_mc.jump=false;
rick_mc._y=ground_mc._y+65;
rick_mc.uvel=40;
}
}
All we simply do is check that rick_mc (plus a height offset) is above the
ground_mc (plus an offset of its own) or else the jump stops. By the
way, you might be thinking "What's the point in retyping all the key.isDown
checks?" and you wouldn't be an idiot for pointing that out. In fact,
this isn't
anybodies coding practice but my own. I simply find it a lot easier to
organise and control that way. Do what works for you. If you give every
character a function
for each state he's in, you'll have far fewer headaches with debugging once your program gains in size and complexity.
But by all means, do whatever way works for you.
Finally, let's just throw in our slighty modified Attack function, and the main code loop.
As
you may have noticed, we can activate the functions by adding the
parenthesis, ( (); those things). Initialise is kept outside of the main
onEnterFrame function. Why? Because we want it to run only once and once only when
the frame loads. Right, you can run the fla now, and Rick will do a
cute little bounce for you. Admittedly, it's not spot on like the
SplatterHouse one. Firstly, in the arcade game the jump is
time-sensitive - I mean - the longer you hold down the jump the higher
he goes. Secondly, he does a kind of unique punch kick combo depending
on the height of the jump. But so what? Moving on.
In n ext
part we'll start on getting a couple of baddies in there. Creating
multiple enemies and at the same time learning about using complex data
types to hold their state/variable structures.