Reputation: 65
I'm trying to make my first game in Actionscript 3. Its a simple artillery game where you have a gun at bottom left corner and AIs flying across the screen which you have to shoot down. Now, in a classing shooter game how this is achieved is either by firing a bullet from the gun and doing a hitTest of that bullet with the AI movieClip or by simply removing(or playing the death animation) the AI movieclip. But here's the problem. I dont wanna do either of them. I want to show a gun with a rapid fire rate and hence no bullets. And I also don't want the player to click exactly ON the AI movieclip to destroy them (just the gun/turret pointing at the correct direction should be enough). So here's what I tried.
This image should help picture the whole thing.
Tried attaching a 'line' to the turret and checking for collision with AI clip. This obviously failed because of the bounding box problem when the line is slanting.
I tried putting multiple tiny movieClips ON the line and iterate through them in a loop and checking for any collision with the AI. This method partially worked, but it was too slow and didn't seem like the 'correct' method.
I draw 2 hypothetical lines. One between p1 and p2 and other connecting p3 and p4 (please see the image above). p3----p4's lenght = AI.width and is a horizontal line running right through the center of the AI MovieClip. Upon mouseClick I check for any intersection between these two lines. Now if I have multiple AIs on the screen, Again i need to iterate through each of them, draw a fresh p3-----p4 and check for intersection with p1-----p2.
I'm using method 3 right now and I have a feeling that once I start adding more stuff to the game, framerate will take a hit. I'm sure there should a more simple/optimized method of doing this (maybe something brutally simple). Attaching some relevant code.
shipGame.as
var baseAI:BaseAI;
var AIList:Array= new Array;
public function shipGame():void{
trace("still connected!!");
/*
irrelevant code..
*/
stage.addEventListener(Event.ENTER_FRAME, updateGame);
var a:MovieClip = new MovieClip;
aiTimer = setInterval(StartAI, 2000);
}
public function StartAI():void {
baseAI = new BaseAI(this);
AIList.push(baseAI);
}
public function updateGame(event:Event):void {
/*
code to rotate the turret here..
*/
for (var i:int = 0; i < AIList.length; i++)
{
if (AIList[i].myx < 100) {
AIList[i].basicAI.parent.removeChild(AIList[i].basicAI);
AIList.splice(i, 1);
}
}
if (mouseDn) {
basicTurret.gotoAndPlay(2);// Fire animation
for (var j:int = 0; j < AIList.length; j++)
{
if ( intersection(AIList[j])) // intersection(bai:BaseAI) returns boolean. Works fine.
{
AIList[j].shot = true;
}
}
}
}
BaseAI.as
var main:shipGame;
var myy:Number;
var myy:Number;
public function BaseAI(doc:shipGame):void{
main = doc;
basicAI = new BasicAI(); // BasicAI is a movieClip in the library
main.addChild(basicAI);
basicAI.x = 400;
basicAI.y = Math.abs(Math.random() * (280)) + 20;
myy = basicAI.y;
basicAI.addEventListener(Event.ENTER_FRAME, keepMoving);
}
public function keepMoving(evt:Event):void {
basicAI.x -= 5;
myx = basicAI.x;
if (shot && alive) {
alive = false;
basicAI.gotoAndPlay(2);
}
}
Upvotes: 2
Views: 688
Reputation: 11139
All your current methods are essentially relying on Flash's renderer to know where the ships and bullet-lines are. But in your case, since you have a relatively simple geometric relationship between the moving parts, it would be much faster to handle the problem analytically.
Consider the case where a ship is sitting precisely on your gun's line of fire. In this case the gun, ship and bottom of the screen form a right triangle. If we define theta
to be the angle between the gun and the bottom of the screen, then the following will hold:
tangent(theta) = ship.y / ship.x
where x
and y
are measured rightwards and upwards from the gun. Now you can generalize this and use it for your hit testing. When the gun is fired, first find theta
. Then for each ship, you can easily determine how far vertically or horizontally the ship is from the line of fire, by doing something like this:
var theta = /*determine theta based on where the mouse was clicked*/
var tanTheta = tangent(theta);
for each (ship) {
var gunX = ship.y / tanTheta;
if ( abs(gunX - ship.x) < ship.width/2 ) {
// a hit occurred
}
}
That's just pseudocode but hopefully you get the idea. Anyway that's how I would do it - this will scale hugely faster than anything you do with real hit testing, and for the described case it should work just as well.
Upvotes: 3