I am creating a game in AS3, and in the class file for an enemy's bullet, I have this code.
public class enemy2Bullet extends MovieClip
{
public function enemy2Bullet()
{
stop();
//Setup an event listener to see if the bullet is added to the stage.
addEventListener(Event.ADDED_TO_STAGE, onAdd);
}
private function onAdd(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, onAdd);
//Now that our object is on the stage, run our custom code.
init();
}
private function init():void
{
if (Math.random() <= 0.5)
{
addEventListener(Event.ENTER_FRAME, bullet2Loop)
}
else
{
addEventListener(Event.ENTER_FRAME, bullet2Loop2)
}
}
private function bullet2Loop(e:Event):void
{
if (currentLabel != "destroyed")
{
this.x += 8;
}
if (currentLabel == "destroyedComplete")
{
destroyEnemy2Bullet();
}
}
private function bullet2Loop2(e:Event):void
{
if (currentLabel != "destroyed")
{
this.x -= 8;
}
if (currentLabel == "destroyedComplete")
{
destroyEnemy2Bullet();
}
}
public function destroyEnemy2Bullet():void
{
{
//Remove the object from stage
stage.removeChild(this);
//Remove any event listeners
removeEventListener(Event.ENTER_FRAME, bullet2Loop);
}
}
}
After compiling, the game runs, but the bullet only shoots in 1 direction.
How can I make it such that the bullets are shot from both left and right, and stay in that direction?
Here's my enemy2 function.
private function enemy2Control():void
{
if (getTimer() - lastSpawnTime2 > 3000 && aEnemy2Array.length < 3)
{
var newEnemy2:MovieClip = new mcEnemy2;
newEnemy2.x = Math.random() * 800;
newEnemy2.y = 0;
aEnemy2Array.push(newEnemy2);
stage.addChild(newEnemy2);
lastSpawnTime2 = getTimer();
}
//Control enemy's bullets
for (var i:int = aEnemy2Array.length - 1; i >= 0; i--)
{
if (enemy2LastFire + 750 / (aEnemy2Array.length) < getTimer())
{
var currentEnemy2:mcEnemy2 = aEnemy2Array[i];
if (Math.random() < 0.06)
{
var newEnemy2Bullet:enemy2Bullet = new enemy2Bullet();
newEnemy2Bullet.x = currentEnemy2.x;
newEnemy2Bullet.y = currentEnemy2.y;
enemy2BulletArray.push(newEnemy2Bullet);
stage.addChild(newEnemy2Bullet);
enemy2LastFire = getTimer();
}
}
for (var j:int = enemy2BulletArray.length - 1; j >= 0; j--)
{
var currentEnemy2Bullet:enemy2Bullet = enemy2BulletArray[j];
if (currentEnemy2Bullet.y >= stage.stageHeight)
{
enemy2BulletArray.splice(j, 1);
currentEnemy2Bullet.destroyEnemy2Bullet();
}
if (currentEnemy2Bullet.hitTestObject(playerCore))
{
playerHP -= 1;
currentEnemy2Bullet.gotoAndPlay(2);
enemy2BulletArray.splice(j, 1);
}
}
}
}
Any help would be appreciated.
A few things:
• You can replace currentEnemy2Bullet with j and just delete the whole var currentEnemy2Bullet:enemy2Bullet = enemy2BulletArray[j]; statement.
• init() is never called. But it's best if you do the direction calculation and use newEnemy2Bullet.addEventListener(Event.ENTER_FRAME, whatever) within the actual initialization of newEnemy2Bullet.
• Truth to be told, your code is fairly messy and can be simplified. For example, you can just determine the direction of the bullet by giving the class a variable, give it a value on initialization, and have the loop update its position based on that variable.
Related
I'm having some troubles with the game I'm making. My character shoots bullets, but when it comes to shooting them in different directions it does not work properly. When it shoots the bullets follow the character's direction. Below I post the code.
var Bulli:Array = new Array();
var ShootTimer:Timer = new Timer(0);
stage.addEventListener(MouseEvent.MOUSE_DOWN, startShootTimer);
stage.addEventListener(MouseEvent.MOUSE_UP, stopShootTimer);
ShootTimer.addEventListener(TimerEvent.TIMER, shootBullo);
stage.addEventListener(Event.ENTER_FRAME, mainLoop);
function startShootTimer(e:MouseEvent):void
{
ShootTimer.start();
}
function stopShootTimer(e:MouseEvent):void
{
ShootTimer.stop();
}
function shootBullo(e:TimerEvent):void
{
var bullo:Bullo = new Bullo();
bullo.x = Jumbo.x;
bullo.y = Jumbo.y - 50;
if(destra)
{
bullo.dir = destra;
}
else
{
bullo.dir = sinistra;
}
addChild(bullo);
Bulli.push(bullo);
}
function mainLoop (e:Event):void
{
for (var b:int = 0; b < Bulli.length; b++)
{
if (Bulli[b].dir == destra)
{
Bulli[b].x += 10;
}
else
{
Bulli[b].x -= 10;
}
}
}
Don't add that listener to Stage, instead add it to each unique bullo...
//# not to Stage...
//stage.addEventListener(Event.ENTER_FRAME, mainLoop);
Try this (untested but may be useful for some ideas):
function shootBullo(e:TimerEvent):void
{
var bullo:Bullo = new Bullo();
bullo.x = Jumbo.x;
bullo.y = Jumbo.y - 50;
if(destra) { bullo.dir = destra; }
else { bullo.dir = sinistra; }
bullo.addEventListener(Event.ENTER_FRAME, mainLoop);
}
function mainLoop (e:Event):void //the "e" of this function parameter is each unique "Bullo"
{
//# currentTarget is whichever "bullo" is talking to this Event (via Listener).
if (e.currentTarget.dir == destra)
{ e.currentTarget.x += 10; }
else { e.currentTarget.x -= 10; }
}
when my player touches the floor, he is unable to move because he is on the floor and being incremented up.
In the main class I have the movement
private function processMovement():void
{
if (touchingGround)
{
if (upKey)
{
character.jumpUp();
}
if (leftKey)
{
character.moveLeft();
}
if (rightKey)
{
character.moveRight();
}
if (!leftKey && !rightKey && !upKey)
{
character.dontMove();
}
}
}
Then in the character class you will see this.
public class player extends OnGround
{
public var canJumpAn:Boolean;
public var attackAn:Boolean;
public var jumpheight:Number = 18;
public function player()
{
addEventListener(Event.ADDED_TO_STAGE, onAdd);
}
private function onAdd(e: Event): void
{
removeEventListener(Event.ADDED_TO_STAGE, onAdd);
}
public function moveLeft():void
{
//decrease VELOCITY
xV -= 2;
if (xV > -7)
{
xV = -7;
}
this.gotoAndStop("run");
//add this to the Mc . x pos baby.
this.x += xV;
this.scaleX = -1;
charIsrunning = true;
}
public function moveRight():void
{
//increase VELOCITY
xV += 2;
if (xV > 7)
{
xV = 7;
}
this.gotoAndStop("run");
//add this to the Mc . x pos baby.
this.x += xV;
this.scaleX = 1;
charIsrunning = true;
}
public function dontMove():void
{
//if no button presses then do this
this.gotoAndStop("stop");
//slowd down ball
xV *= friction;
charIsrunning = false;
isDefending = false;
//stop the ball if you're not moving
if (xV > - 1 && xV < 1)
{
xV = 0;
}
}
override public function positionOnLand():void
{
isJumping = false;
///=gotoAndStop(1);
}
public function defend():void
{
isDefending = true;
this.gotoAndStop("defend");
charIsrunning = false;
}
public function attack():void
{
this.gotoAndStop("attack");
}
public function jumpUp():void
{
if (!isJumping)
{
isJumping = true;
this.gotoAndStop("jump");
//
}
}
}
}
OnGround is another class that player extends, as you can see.
public class OnGround extends MovieClip
{
public var grav:Number;
public var friction:Number;
public var xV:Number;
public var yV:Number;
protected var charIsrunning:Boolean;
protected var isDefending:Boolean;
protected var isJumping:Boolean;
public function OnGround()
{
addEventListener(Event.ADDED_TO_STAGE, init)
charIsrunning = false;
isDefending = false;
//gotoAndStsop("jump");
}
private function init(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
//gravity
grav = 0.6;
//y velocity
yV = 0;
//x velocity
xV = 0;
//
friction = 0.9;
addEventListener(Event.ENTER_FRAME, fall);
}
private function fall(e:Event):void
{
//add grav to y VELOCITY
yV += grav;
trace(yV);
this.y += yV
}
public function incrementUp():void
{
this.y -= 0.1;
//trace("incrementing");
}
public function keepOnGround():void
{
//trace("onGroundBitch");
grav = 0;
yV = 0;
positionOnLand();
}
public function positionOnLand():void
{
//overide
}
}
}
This is a function that's in the main class
for (var c:int = 0; c < childrenOnStage; c++)
{
if (getChildAt(c).name == "player")
{
if (ground.level1Ground.hitTestPoint(getChildAt(c).x + 13, getChildAt(c).y, true) || ground.level1Ground.hitTestPoint(getChildAt(c).x - 13, getChildAt(c).y, true))
{
getChildAt(c).y --;
//OnGround(getChildAt(c)).incrementUp();
OnGround(getChildAt(c)).keepOnGround();
touchingGround = true;
}
else
{
touchingGround = false;
}
The problem is that when the player touches the ground then it's y position is incremented until it isn't touching the ground and then it's suppose to be kept on the ground by turning grav to = 0 and y velocity to 0.
This means gravity is turned off and the players y position will not shift up (when I jump)
or when go down to be kept on ground.
I would appreciate it if someone can lend me a hand or point me in the correct direction.
I'm not sure why you'd have a gravity value per object unless you really intend to have different object instances have individual gravities.
If not I'd reference a gravity constant instead.
Is anti-gravity a feature of the game? if not then I'd avoid setting gravity to 0. It may 'work' (to an extent) but it's not a good model/abstraction of reality.
Rather, what I would do is seperate the force applied and the current momentum:
The (downward) force of gravity is applied at all times.
When you're standing on the ground an upward force equal and opposite to gravity is applied.
When you jump, add a one-off instance of upward force.
Use the current forces to change the current momentum and use the current momentum to change the position.
Thanks in advance...
I am having little bit doubt in my logic for setting the Damage level to the enemy in game. Following is my Enemy Class
package scripts.enemy
{
import flash.display.MovieClip;
import flash.events.*;
import flash.display.Stage;
public class Enemy1 extends MovieClip
{
private var BG:MovieClip;
private var speed:Number = 0.5;
private var ease:Number = .005;
private var rad:Number = 57.2957795;
public function Enemy1(BG:MovieClip) : void
{
var RandomX:Array = new Array(-150,-200,-250,-300,-350,-400,-450,-500,-550,150,200,250,300,350,400,450,500,550);
var RandomY:Array = new Array(-150,-200,-250,-300,-350,-400,150,200,250,300,350,400);
var r:int = (Math.random() * 18);
var s:int = (Math.random() * 12);
x = RandomX[r];
y = RandomY[s];
this.BG = BG;
addEventListener(Event.ENTER_FRAME, moveEnemy); //false, 0, true);.
}
private function moveEnemy(e:Event):void
{
var dx:Number = x - 10;
var dy:Number = y - 10;
this.x -= dx * ease;
this.y -= dy * ease;
this.rotation = (Math.atan2(dy,dx) * rad) + 180;
}
}
}
And Here is some of code that giving me trouble from my Main class
// ......... Function for Checking the Collision between Bullet And Enemy...........
private function checkCollision(mc:MovieClip):Boolean
{
var test:Point = mc.localToGlobal( new Point());
for (var i = 0; i < enemies1.length; i++)
{
tempEnemy1 = enemies1[i];
if (kill == true)
{
if (tempEnemy1.hitTestPoint(test.x,test.y,true))
{
enemies1.splice(i, 1);
bg_mc.removeChild(tempEnemy1);
createDead(Dead1,deadArray1,tempEnemy1.x,tempEnemy1.y,tempEnemy1.rotation);
Score += 10;
Scr_txt.text = String(Score);
bugsKill += 1;
kill = false;
return true;
}
}
}
if (Level >= 2)
{
for (var j = 0; j < enemies2.length; j++)
{
tempEnemy2 = enemies2[j];
if (kill == true)
{
if (tempEnemy2.hitTestPoint(test.x,test.y,true))
{
bug2HitCount -= 1;
if (bug2HitCount == 0)
{
enemies2.splice(j, 1);
bg_mc.removeChild(tempEnemy2);
createDead(Dead2,deadArray2,tempEnemy2.x,tempEnemy2.y,tempEnemy2.rotation);
Score += 20;
Scr_txt.text = String(Score);
bugsKill += 1;
kill = false;
//bug2HitCount = bug2HitRate;
return true;
}
kill = false;
return true;
}
}
}
}
return false;
}
private function removeElement(removeList:Array):void
{
for (var i = 0; i < removeList.length; i++)
{
bg_mc.removeChild(removeList[i]);
}
}
//...........Function Checking the Collission Between Bunker And Enemy..............
private function collideEnemy(deadArray:Array,enemyArray:Array,rate:Number):void
{
var enemy:MovieClip;
for (var i = 0; i < enemyArray.length; i++)
{
enemy = enemyArray[i];
if (enemy.hitTestObject(bunker_mc))
{
life_mc.scaleX -= rate;
if (life_mc.scaleX <= 0.05)
{
stage.removeEventListener(Event.ENTER_FRAME,updateCollission);
Timer1.stop();
Mouse.show();
stage.removeEventListener(MouseEvent.MOUSE_UP,mouseUpFun);
stage.removeEventListener(Event.ENTER_FRAME,updateStage);
stage.removeEventListener(MouseEvent.MOUSE_DOWN,mouseDownFun);
(player.parent).removeChild(player);
(bunker_mc.parent).removeChild(bunker_mc);
(life_mc.parent).removeChild(life_mc);
(sniper_mc.parent).removeChild(sniper_mc);
removeElement(bullets);
EndFun();
gunFire = false;
gotoAndStop("end");
Level = 1;
}
}
}
}
//...........function of Timer Complete Event.....................
private function TimerEnd(e:TimerEvent):void
{
EndBug();
gotoAndStop("end");
}
//...........function of Timer Complete Event.....................
private function EndBug():void
{
HelpTimer = new Timer(1000,1);
HelpTimer.addEventListener(TimerEvent.TIMER_COMPLETE,HelpFun);
HelpTimer.start();
stage.removeEventListener(Event.ENTER_FRAME,updateStage);
stage.removeEventListener(Event.ENTER_FRAME,updateCollission);
function HelpFun(Event:TimerEvent)
{
stage.removeEventListener(MouseEvent.MOUSE_UP,mouseUpFun);
stage.removeEventListener(MouseEvent.MOUSE_DOWN,mouseDownFun);
gunFire = false;
bg_mc.removeChild(player);
bg_mc.removeChild(bunker_mc);
(life_mc.parent).removeChild(life_mc);
bg_mc.removeChild(sniper_mc);
EndFun();
Score = 0;
Level += 1;
totalBugs += 5;
}
}
//..................Function for ending the Game And removing the Reamining Enemies.................
private function EndFun():void
{
Mouse.show();
removeElement(dustArray);
if (Level == 1)
{
removeElement(enemies1);
removeElement(deadArray1);
gotoAndStop("level2");
}
if (Level == 2)
{
removeElement(enemies1);
removeElement(deadArray1);
removeElement(enemies2);
removeElement(deadArray2);
gotoAndStop("level3");
}
if (Level == 3)
{
......
}
.....................
.....................
}
}
}
In this code I have added a new type of Enemy in Level 2 and I have also written code for its HitTest property..In which each enemy of level 2 requires more than 1 bullet to kill.. But when I shoot a bullet to one enemy and then I shoot another bullet to another enemy of same type the another enemy gets killed. It means that the second enemy is getting killed in only 1 single bullet.. So how can I solve this issue..?
Please Help.. Thanks in advance..
The problem in your code lies within the checkCollision function. It basically goes over the first for loop and ignores the second. But it's best if you just assign the enemies health by adding a health parameter within your Enemy class and have each bullet decrease their health by 1. That way, you can just go through your array and remove any enemies that reach 0 health.
EDIT: I just looked over your code again and realized it's the bug2HitCount that's screwing everything up.
I get this error when I try my code:
ArgumentError: Error #2025: The supplied DisplayObject must be a child of the caller.
at flash.display::DisplayObjectContainer/removeChild()
at Main_MouseFollow/onEnterFrame()[C:\Users\Ida\Documents\flash kursen\Space shooter del2\Main_MouseFollow.as:120]
line 120 is
removeChild(_bullets[j]);
Here is the entire code. I am new to Flash, so how can I fix this error?
package
{
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
public class Main_MouseFollow extends MovieClip
{
private var _bullets:Array;
private var _robotScore:Number;
private var _playerScore:Number;
public function Main_MouseFollow()
{
//Add event listeners
addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
stage.addEventListener("bulletCreated", onBulletCreated);
_bullets = new Array();
_robotScore = 0;
_playerScore = 0;
}
private function onAddedToStage(event:Event):void
{
addEventListener(Event.ENTER_FRAME, onEnterFrame);
addEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage);
}
private function onRemovedFromStage(event:Event):void
{
removeEventListener(Event.ENTER_FRAME, onEnterFrame);
removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
removeEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage);
}
private function onBulletCreated(event:Event)
{
_bullets.push(MovieClip(event.target));
}
private function onEnterFrame(event:Event):void
{
bulletDisplay.text = "Bullets on the stage: " + String(_bullets.length);
for (var i:int = 0; i < _bullets.length; i++)
{
switch (_bullets[i].bulletType)
{
case "circle" :
//Check for a collision with the player
if (player.hitTestPoint(_bullets[i].x,_bullets[i].y,true))
{
//Remove the bullet from the stage
removeChild(_bullets[i]);
//Remove bullet from array
_bullets.splice(i,1);
//Subtract 1 from the counter to compensate
//for the removed element
i--;
//Update the robot's score
_robotScore++;
//Update the robot's score display on the stage
robotScoreDisplay.text = String(_robotScore);
}
break;
case "star" :
//Check for a collision with the robot
if (robot.hitTestPoint(_bullets[i].x,_bullets[i].y,true))
{
//Remove the bullet from the stage
removeChild(_bullets[i]);
//Remove bullet from array
_bullets.splice(i, 1);
//Subtract 1 from the counter to compensate
//for the removed element
i--;
//Update the enemy's score
_playerScore++;
//Update the player's score display on the stage
playerScoreDisplay.text = String(_playerScore);
}
break;
}
}
//Bullet stage Boundaries:
for (var j:int = 0; j < _bullets.length; j++)
{
//Top
if (_bullets[j].y + _bullets[j].height / 2 < 0)
{
removeChild(_bullets[j]);
_bullets.splice(j, 1);
j--;
}
//Bottom
else if (_bullets[j].y - _bullets[j].height / 2 > stage.stageHeight)
{
removeChild(_bullets[j]);
_bullets.splice(j, 1);
j--;
}
//Left
else if (_bullets[j].x + _bullets[j].width / 2 < 0)
{
removeChild(_bullets[j]);
_bullets.splice(j, 1);
j--;
}
//Right
else if (_bullets[j].x - _bullets[j].width / 2 > stage.stageWidth)
{
removeChild(_bullets[j]);
_bullets.splice(j, 1);
j--;
}
}
}
}
}
try to remove child in more safety way:
replace (in all 4 cases):
removeChild(_bullets[j]);
with:
if(_bullets[j].parent)
_bullets[j].parent.removeChild(_bullets[j]);
this will removes the error. If there aren't any other problems in logic this will fix the whole issue.
First off since that's my first post, hail to everyone in this community. I already found a ton of information that helped me tackle the problems i encountered so far. Now i ran into a problem I am unable to solve. I am making a "Pang" type of game, probably some of you have seen or played some sort of variation. So to the point. I am currently trying to make an object, linked to a class, bounce on the stage. I decided to try and use easeIn and easeOut tweens.
I declare the tweens inside the main document class:
public static var upTween:Tween;
public static var downTween:Tween;
and use a for loop to assign their value to all objects part of an array:
public function bounce(event:Event):void
{
for (var i:uint = 0; i < bubbles1.length; i++)
{
upTween = new Tween(bubbles1[i], "y", Strong.easeOut, bubbles1[i].y, 250, 2, true);
downTween = new Tween(bubbles1[i], "y", Strong.easeIn, bubbles1[i].y, stage.stageHeight - 50 - bubbles1[i].height, 2, true);
}
}
Now when i try to start the tweens from inside the Bubble.as class i get a null object reference.
Perhaps a little bit more info that would be helpful. I am instantiating the object in a public function from within the main class as follows:
public function makeBubble(size:Number, xCoordinate:Number, yCoordinate:Number, xDir:Number):void
{
if (size == 1)
{
bubble = new Bubble(stage);
bubble.x = xCoordinate;
bubble.y = yCoordinate;
bubble.xDirection = xDir;
bubbles1.push(bubble);
stage.addChild(bubble);
}
Here is the full Bubble.as class:
package com.zdravko.pong
{
import flash.display.MovieClip;
import flash.display.Stage;
import flash.events.Event;
public class Bubble extends MovieClip
{
private var stageRef:Stage;
var xDirection:Number;
var yDirection:Number;
var bubble2:Bubble2;
public function Bubble(stageRef:Stage)
{
// constructor code
this.stageRef = stageRef;
addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
}
function loop(event:Event):void
{
if(this.x >= stage.stageWidth - this.width)
{
this.x = stage.stageWidth - this.width - 5;
xDirection *= -1;
}
if(this.x <= 0)
{
this.x = 5;
xDirection *= -1;
}
if(this.y >= stage.stageHeight - 50 - this.height)
{
this.y = stage.stageHeight - 50 - this.height;
Engine.upTween.start();
}
if(this.y <= 250)
{
this.y = 250;
Engine.downTween.start();
}
this.x += xDirection;
if(hitTestObject(Engine.player) && Player.invul == false)
{
decreaseEnergy(.4);
Player.invul = true;
Player.invulTimer.start();
}
}
public function decreaseEnergy(dmg:Number):void
{
Engine.energy.scaleX -= dmg;
}
public function takeHit() : void
{
makeBubble(2, this.x + 50, this.y + 30, 8, 8);
makeBubble(2, this.x - 20, this.y - 30, -8, 8);
removeSelf();
Engine.playerScore += 500;
Engine.score.scoreBox.text = Engine.playerScore;
}
private function removeSelf() : void
{
removeEventListener(Event.ENTER_FRAME, loop);
if (stageRef.contains(this))
{
stageRef.removeChild(this);
}
}
private function makeBubble(size:Number, xCoordinate:Number, yCoordinate:Number, xDir:Number, yDir:Number):void
{
bubble2 = new Bubble2(stage);
bubble2.x = xCoordinate;
bubble2.y = yCoordinate;
bubble2.xDirection = xDir;
bubble2.yDirection = yDir;
Engine.bubbles2.push(bubble2);
stageRef.addChild(bubble2);
}
}
}
Presumably the bubbles array is returning a null value. Have you tried tracing out the values from the bubbles1 array.
public function bounce(event:Event):void
{
for (var i:uint = 0; i < bubbles1.length; i++)
{
// log out the value from your array
trace("bubble " + bubbles1[i]);
}
}