From Game Editor
Shooting Games
This page covers traditional horizontal and vertical scrolling shooters.
The basic elements of a shooter are: Player, playershot, Enemies, enemyshots, powerups, backgrounds, meters, and bombs.
Step one is to create 2 player elements: The player graphic and the player collider. The player collider is always smaller than the player graphic. This is done to allow the player to successfully avoid bullets, but still draw a nice looking-sprite. If we use a pixel collision with the player, then any wings, spoilers, guns etc. which make the ship look cool will actually make it weaker in battle.
So create an actor named collider, of Filled Region type; and resize it to fill the center of the player ship; From the actor control panel, set parent to 'player'. In the CreateActor event for collider, add the event 'EventDisable("Event Actor", EVENTMOUSEBUTTONDOWN);'. This will prevent it from catching our player's clicks.
Now add collisions with enemies and enemy bullets to the collider's script, instead of player's, and give all the mouse/key events to the player. However, the powerups will still collide with the player. This will be explained later.
First is the player movement; either use a FollowMouse or KeyDown event. If you use Keydown, be sure to specify 'x+=speed;' or 'y-=speed;' instead of using actual numbers. If you ever want to change the speed of your ship, you'll have to go thru and change each key event when using numbers, but when using the actor variable 'speed', you can adjust it easily from player's CreateActor script.
Powerups. Create only one powerup actor. Add all of the powerup animations to this actor. On the CreateActor script, specify a type; type=gtype; where gtype is a variable you set when spawning the powerup. In addition, set the proper animation for the powerup.
Powerups collide with the graphic player because we want powerups to be easy to collect; when the player touches one, we will check collide.type; This will determine what type of powerup it is and what effect it has on the player.
Now when player has just spawned, and is invincible, we simply disable collisions with collider temporarily, but not player, so player can still collect powerups during invincibility.
Shots. Create the different types of shots using inheritance as described in the advanced section on the main wiki page. Be sure to give all bullet type actors an event: Out of vision>DestroyActor("Event Actor");! If you don't the bullets will never die and your game will end up clogged and eventually crash.
Now on player>keydown> simply put: shooting=1;
And in player>draw actor, we can specify which types of bullets to spawn. For this example, we'll use the player bullet simply named 'bullet'. We will check for shooting, wait for a specified amount of time, then check the power level of player, and spawn the shot.
player>draw actor>
int i; if(shooting==1){ timeVar++; if(timeVar==5){ //this will create a shot every 5th frame, or 12 shots/sec. sAngle=90; //set starting variables for shots sPower=1; sSpeed=18; CreateActor("bullet", "bullet00", "no parent", "no path", 0, -10, false); //this creates the initial bullet stream (even when player has no power he can still shoot //this bullet). for(i=0; i<power; i++){ //where power is the powerup level of the player sAngle=90+(i*5); //creates spread angle sPower=1; sSpeed=18; CreateActor("bullet", "bullet00", "no parent", "no path", 0, -10, false); sAngle=90-(i*5); //creates the opposite angle CreateActor("bullet", "bullet00", "no parent", "no path", 0, -10, false); timeVar=0; //reset timeVar }//end for loop }//end timeVar cycle }//end shooting check
Now we have a player who can shoot, be shot, and collect powerups.
Collisions. When your bullets collide with enemy, have the enemy change to its hurt variable, take damage, and DestroyActor("Collide Actor");(to destroy player's bullet). Then, in the draw actor scripts of the actors who inherit enemy's events:
if(hurt==1){ //if enemy has been shot if(health<=0){ //we check health here, not in the collision. //Do explosiosion and dying stuff here; } else if(health>0){ timeVar++; b=100; //flash colors to indicate enemy was hurt g=100; if(timeVar==2){ after 2 frames of being hurt hurt=0; //enemy returns to normal b=255; //return colors to normal g=255; timeVar=0; //reset timeVar for use on the next collision. } }
And finally, the spawning script. I create an actor named control, instead of using global script, for two reasons;
1. its always there handy to click on with the other actors and
2. i can use the same kind of inheritance that i use with the other actors.
So control>draw actor>
timeVar++; if(timeVar==20){ sSpeed=2; sDamage=2; CreateActor("enemyship", "eship00", "no parent", "no path", rand ((view.width/2)-view.width), true);
And have the enemy..you guessed it...use sSpeed and sDamage just like the bullets it will shoot will do.
Explosions. Create an actor with an explosion animation. In this actor's DrawActor script, we'll count timeVar and DestroyActor when it's reached the end of its animation.
Have an enemy create explosions in the draw actor script. Where it checks for health<=0, we'll simply use the timeVar to count for explosions; and create however many we want. We won't call DestroyActor on the enemy until it is finished exploding!
Once you add a background, and events for enemies and bosses (bosses are also inheriting from enemy, because all enemies do the same things when shot, when created, when killed (they explode), you will have....a shooter!
While some of these methods may seem complex, they allow you to edit and expand your shooter much more easily than simpler methods. For instance, the player shot loop is set up for infinite power levels. If you gave the player a power level of 36, he will shoot bullets in a 360 degree spread! Basically, it takes care of the angles for you.
And since you set the sAngle and have the bullet inherit that, if you want one weapon type to shoot straight ahead, you can easily just set sAngle to 90, and offset the starting x position of the shot instead, thus creating parallel 'rows' of bullets.
What this inheritance can do is very powerful; Consider what happens if you change the resolution of the game? You'd have to change every instance of sSpeed. However, if you set the sSpeed variable in the createactor of any ship using the line
sSpeed=5*globalspeed;
You can simply adjust globalspeed at the beginning of the game, and every bulletspeed everywhere will be proper; so if you half the resolution of your game, you can half the speed of all the shots too.
So too, the ships themselves can use sSpeed for their own speed; where the spawner actor sets sSpeed every time it spawns a ship, using the globalspeed multiplier.
If you plan to port your games, this will make a huge difference.