Beat-em up fighting tutorial (updated) Page 4/5 Previous page Next page
[ January 21, 2007 ] Kris Foxton
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.

images

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.

function Attack()
{
	if(rick_mc.jump)
	{
		rick_mc.gotoAndStop("crouchkick");
	}
	else
	{
		if (Key.isDown (Key.DOWN))
		{
			rick_mc.gotoAndStop("crouchkick");
		}
			else
		{
			rick_mc.gotoAndStop("punch");
		}
	}
}

Initialize();

onEnterFrame = function()
{
	if(!rick_mc.attack && !rick_mc.jump)
		Movement();
	
	if(rick_mc.jump)
		Jump();			
	
	if(rick_mc.attack)
		Attack();
	
	if (Key.isDown (Key.CONTROL))
		keydown=true;
	else
		keydown=false;
	
	if(rick_mc.stance==0)
		rick_mc._xscale = -100;
	else
		rick_mc._xscale = 100;
}

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.

 
 
Name: Kris Foxton
Location: Fukuoka, Japan
Age: 28
Flash experience: 1 year. A keen-to-learn newb.
Job: Famous nobody
Website: http://ydjapan.blogspot.com/
 
 
| Homepage | News | Games | Articles | Multiplayer Central | Reviews | Spotlight | Forums | Info | Links | Contact us | Advertise | Credits |

| www.smartfoxserver.com | www.gotoandplay.biz | www.openspace-engine.com |

gotoAndPlay() v 3.0.0 -- (c)2003-2008 gotoAndPlay() Team -- P.IVA 03121770048