Solar Fortress Chronicles: Hours 16 – 17

Solar Fortress Chronicles: Hours 16 – 17

Note – I am rapid (wishful thinking) prototyping a retro game in my spare time and keeping a diary of what I do each hour of the project.

I have only found a few hours to work on Solar Fortress (pronounced Star Castle) in the last few days (a common refrain recently). I had planned to spend hours 16 and 17 finishing up the boss firing at the player, but I didn’t make it that far. When I went back to play the original Star Castle in MAME, I found the the boss follows the players movement and fires at him only if there is a clear opening through all three rings. My initial attempts at coding this from scratch resulted in the boss following the player, but when the player “warped” off of the screen to the other side, the boss would quickly flip and rotate to the new player location. This was not the action I wanted. I wanted the boss to move toward the player in a smooth fashion that I would speed up or slow down based on the difficulty of the level.

bosspenis.png

(kind of looks like a cat penis…)

Rotating the Boss to Point at The Player (no flipping).

So, to point the boss to the player ship, I pass the player ship location(shipx, shipy) into my update() method on the boss and find that angle that points in that direction:

<strong>var degrees:Number = (180 * (Math.atan2(shipy-y, shipx-x)) / (Math.PI)+90);
   </strong>
 

I added 90 to the number because the boss starts pointing UP but actually pointing RIGHT is 0 degrees.
I wanted the Boss to rotate toward the player, but not have to be exactly on him to stop and fire (if there is a hole in the rings). I did that like this:

<strong>if ((rotation+5)&gt;degrees) {
 	rotation -= rotationspeed;
 }else if ((rotation-5)&lt;degrees) {
 	rotation += rotationspeed;
 }</strong>

I can set the rotationspeed to greater than 1 (it’s 1 on the first level) to make the boss faster and more difficult to fool. I might even widen the 5 degree range on each

end of the degree check on high levels to make the Boss “Lock On” more often. I’ll have to play with that though to see how it effects game play.

This worked OK until the player ship moved to the lower left 90 degrees of the rings. Once there, the boss went haywire and started rotating and never finding a place to lock on to the player. It turns out that the rotation of an object in Flash ranges from -180 through 180 and the degrees returned from the function above is 0-359. I had to compensate for that with this hack, but I am still looking for a better solution:

<strong>if (degrees &gt; 180) {
 	degrees -= 360;
}</strong>
 

This now works, but a little imperfectly. The hack above aside, the Boss becomes confused when the player ship is in the lower right-hand side (sometimes) and rotates counter-clockwise to find the player when it should go clockwise. I might not work on a fix for this.

Checking to see if the Boss can fire a missile at the player
In Star Castle, the boss in the center can fire at the player (and fire he does, a massive ball of kick ass kill all) when there is an opening in each of the 3 rings that matches up for a clear shot at the player. Conversely, that is the same way the player can kill the boss, so its a match made in video game heaven.

To make this work, I first made run to www.freeactionscript.com because I remember a free .fla on the site for doing laser to wall collisions. I figured that I would project a laser like line from the center of the boss in the facing direction and if it made it through all of the walls fine, then fire a missile. But, I just didn’t have a good idea about how to build the laser and update it properly. I didn’t use the exact code from the freeactionscript version, but it gave me a very good idea: using a for loop to update my laser line on each frame tick.

So, to draw the laser line, I first create local endx and endy Number variables and set them to be the x and y of the center boss. Since this code is inside the Boss class and the Boss class extends Sprite, I just did this:

<strong>var endx:Number = x;
var endy:Number = y; </strong>

I next played with the numbers to see what length of line was a suitable test for the radius of the circle. I randomly chose 150 and am using it in my current build for a test. I created a for loop to loop from 0 to 150 and inside that loop, and x and y are updated with dx and dy. If there is no hit detected on a pixel in the Fortress (at x+dx,y+dy), then the loop continues. If there is a hit, I break out of the loop. The loop and the break were the concepts that I borrowed from Freeactionscipt.com (thanks!!!). I then draw the line.

<strong> var endx:Number = x;
 var endy:Number = y;


 for (var distance:int = 0; distance &lt; 150; distance ++ ) {

 	var dx:Number=Math.cos(2.0*Math.PI*((rotation)-90)/360.0);
 	var dy:Number=Math.sin(2.0*Math.PI*((rotation)-90)/360.0);

 	endx += dx;
	 endy += dy;
 	if (_main.fortress.hitTestPoint(endx, endy, true)) {

 		break;

 	}
 }</strong>
<strong> _main.fortressLine.graphics.clear();
 _main.fortressLine.graphics.moveTo(x,y);
 _main.fortressLine.graphics.lineStyle(1, 0xff0000);
 _main.fortressLine.graphics.lineTo(endx, endy);</strong>

This ALMOST worked perfectly the first time, but I had the endx and endy set to be INT instead on NUMBER. This was a terrible mistake that cost me at least an hour to find.

(below is the current build – arrows to move, space to fire).
If you are careful and don’t shoot the boss right away, you can see the thin red “penis” like thing extend out. That is the line projection used to detect if a missile can be fired. I haven’t added the kick ass boss missiles yet though.

0saves
If you enjoyed this post, please consider leaving a comment or subscribing to the RSS feed to have future articles delivered to your feed reader.