How can I set the damage level of enemy - actionscript-3

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.

Related

How can I change Nested Class in actionscript 3

I'm working off an actionscript 3 code that pulls information from other actionscript 3's. The main code is Herbfight and it references 4 others (Bullets, bugs, Goodbugs and Sprayer). Below I'm trying to combine them all into one actionscript. The reason for this is that I want to pull it in as a symbol rather then having the flash file relate to the class.
The problem is it says I can't have nested classes. Any thoughts on how i can fix this? Below is my attempt to combine the code.
Thanks,
J
package {
import flash.display.;
import flash.events.;
import flash.utils.Timer;
import flash.text.TextField;
import flash.text.*;
import flash.utils.getTimer;
import flash.geom.Point;
public class herbfight_v004 extends MovieClip {
private var aagun:Sprayer;
private var airplanes:Array;
private var goodbug:Array;
private var bullets:Array;
private var upArrow, downArrow:Boolean;
private var nextPlane:Timer;
private var nextGbugs:Timer;
private var shotsLeft:int;
private var shotsHit:int;
private var Sprayer:MovieClip
private var Bullets:MovieClip
private var bugs:MovieClip
private var GooodBugs:MovieClip
public function startherbfight_v004() {
// init score
shotsLeft = 20;
shotsHit = 0;
showGameScore();
// create gun
aagun = new Sprayer();
addChild(aagun);
// create object arrays
airplanes = new Array();
bullets = new Array();
goodbug = new Array();
// listen for keyboard
stage.addEventListener(KeyboardEvent.KEY_DOWN,keyDownFunction);
stage.addEventListener(KeyboardEvent.KEY_UP,keyUpFunction);
// look for collisions
addEventListener(Event.ENTER_FRAME,checkForHits);
// start planes flying
setNextPlane();
setNextGbugs();
public function Sprayer() {
{
// animation time// initial location of gun
this.x = 410;
this.y = 380;
// movement
addEventListener(Event.ENTER_FRAME,moveGun);
}
public function moveGun(event:Event) {
// get time difference
var timePassed:int = getTimer()-lastTime;
lastTime += timePassed;
// current position
var newy = this.y;
// move to the left
if (MovieClip(parent).upArrow) {
newy -= speed*timePassed/1000;
}
// move to the right
if (MovieClip(parent).downArrow) {
newy += speed*timePassed/1000;
}
// check boundaries
if (newy < 65) newy = 65;
if (newy > 380) newy = 380;
// reposition
this.y = newy;
}
// remove from screen and remove events
public function deleteGun() {
parent.removeChild(this);
removeEventListener(Event.ENTER_FRAME,moveGun);
}
}
public function bugs(side:String, speed:Number, altitude:Number) {
{
if (side == "left") {
this.x = -50; // start to the left
dx = speed; // fly left to right
this.scaleX = 1; // reverse
} else if (side == "right") {
this.x = -50; // start to the right
dx = -speed; // fly right to left
this.scaleX = 1; // not reverse
}
this.y = altitude; // vertical position
// choose a random plane
this.gotoAndStop(Math.floor(Math.random()*4+1));
// set up animation
addEventListener(Event.ENTER_FRAME,movePlane);
lastTime = getTimer();
}
public function movePlane(event:Event) {
// get time passed
var timePassed:int = getTimer()-lastTime;
lastTime += timePassed;
// move plane
this.x += dx*timePassed/2000;
// check to see if off screen
if ((dx < 0) && (x < -50)) {
deletePlane();
} else if ((dx > 0) && (x > 350)) {
deletePlane();
}
}
// plane hit, show explosion
public function planeHit() {
removeEventListener(Event.ENTER_FRAME,movePlane);
MovieClip(parent).removePlane(this);
gotoAndPlay("explode");
}
// delete plane from stage and plane list
public function deletePlane() {
removeEventListener(Event.ENTER_FRAME,movePlane);
MovieClip(parent).removePlane(this);
parent.removeChild(this);
}
}
public function Bullets(x,y:Number, speed: Number) {
{
// set start position
this.x = x;
this.y = y;
// get speed
dx = speed;
// set up animation
lastTime = getTimer();
addEventListener(Event.ENTER_FRAME,moveBullet);
}
public function moveBullet(event:Event) {
// get time passed
var timePassed:int = getTimer()-lastTime;
lastTime += timePassed;
// move bullet
this.x += dx*timePassed/1000;
// bullet past top of screen
if (this.x < 0) {
deleteBullet();
}
}
// delete bullet from stage and plane list
public function deleteBullet() {
MovieClip(parent).removeBullet(this);
parent.removeChild(this);
removeEventListener(Event.ENTER_FRAME,moveBullet);
}
}
public function GoodBugs(side:String, speed:Number, altitude:Number) {
{
if (side == "left") {
this.x = -50; // start to the left
dx = speed; // fly left to right
this.scaleX = -1; // reverse
} else if (side == "right") {
this.x = -50; // start to the right
dx = -speed; // fly right to left
this.scaleX = -1; // not reverse
}
this.y = altitude; // vertical position
// choose a random Gbugs
this.gotoAndStop(Math.floor(Math.random()*2+1));
// set up animation
addEventListener(Event.ENTER_FRAME,moveGbugs);
lastTime = getTimer();
}
public function moveGbugs(event:Event) {
// get time passed
var timePassed:int = getTimer()-lastTime;
lastTime += timePassed;
// move Gbugs
this.x += dx*timePassed/2000;
// check to see if off screen
if ((dx < 0) && (x < -50)) {
deleteGbugs();
} else if ((dx > 0) && (x > 350)) {
deleteGbugs();
}
}
// Gbugs hit, show explosion
public function GbugsHit() {
removeEventListener(Event.ENTER_FRAME,moveGbugs);
MovieClip(parent).removeGbugs(this);
gotoAndPlay("explode");
}
// delete Gbugs from stage and Gbugs list
public function deleteGbugs() {
removeEventListener(Event.ENTER_FRAME,moveGbugs);
MovieClip(parent).removeGbugs(this);
parent.removeChild(this);
}
}
public function setNextPlane() {
nextPlane = new Timer(1000+Math.random()*1000,1);
nextPlane.addEventListener(TimerEvent.TIMER_COMPLETE,newPlane);
nextPlane.start();
}
public function newPlane(event:TimerEvent) {
// random side, speed and altitude
if (Math.random() > .2) {
var side:String = "left";
} else {
side = "right";
}
var altitude:Number = Math.random()*280+80;
var speed:Number = Math.random()*150+150;
// create plane
var p:bugs = new bugs(side,speed,altitude);
addChild(p);
airplanes.push(p);
// set time for next plane
setNextPlane();
}
public function setNextGbugs() {
nextGbugs = new Timer(1000+Math.random()*1000,1);
nextGbugs.addEventListener(TimerEvent.TIMER_COMPLETE,newGbugs);
nextGbugs.start();
}
public function newGbugs(event:TimerEvent) {
// random side, speed and altitude
if (Math.random() > .2) {
var side:String = "left";
} else {
side = "right";
}
var altitude:Number = Math.random()*280+80;
var speed:Number = Math.random()*150+150;
// create Gbugs
var p:GoodBugs = new GoodBugs(side,speed,altitude);
addChild(p);
goodbug.push(p);
// set time for next Gbugs
setNextGbugs();
}
// check for collisions
public function checkForHits(event:Event) {
for(var bulletNum:int=bullets.length-1;bulletNum>=0;bulletNum--){
for (var airplaneNum:int=airplanes.length-1;airplaneNum>=0;airplaneNum--) {
if (bullets[bulletNum].hitTestObject(airplanes[airplaneNum])) {
airplanes[airplaneNum].planeHit();
bullets[bulletNum].deleteBullet();
shotsHit++;
showGameScore();
break;
}
}
}
for(var bulletNum:int=bullets.length-1;bulletNum>=0;bulletNum--){
for (var GoodBugsNum:int= goodbug.length-1; GoodBugsNum>=0; GoodBugsNum--) {
if (bullets[bulletNum].hitTestObject(goodbug [GoodBugsNum])) {
goodbug [GoodBugsNum]. GbugsHit();
bullets[bulletNum].deleteBullet();
shotsHit--;
showGameScore();
break;
}
}
}
if ((shotsLeft == 0) && (bullets.length == 0)) {
endGame();
}
}
// key pressed
public function keyDownFunction(event:KeyboardEvent) {
if (event.keyCode == 38) {
upArrow = true;
} else if (event.keyCode == 40) {
downArrow = true;
} else if (event.keyCode == 32) {
fireBullet();
}
}
// key lifted
public function keyUpFunction(event:KeyboardEvent) {
if (event.keyCode == 38) {
upArrow = false;
} else if (event.keyCode == 40) {
downArrow = false;
}
}
// new bullet created
public function fireBullet() {
if (shotsLeft <= 0) return;
var b:Bullets = new Bullets(aagun.x,aagun.y,-300);
addChild(b);
bullets.push(b);
shotsLeft--;
showGameScore();
}
public function showGameScore() {
showScore.text = String("Score: "+shotsHit);
showShots.text = String("Shots Left: "+shotsLeft);
}
// take a plane from the array
public function removePlane(plane:bugs) {
for(var i in airplanes) {
if (airplanes[i] == plane) {
airplanes.splice(i,1);
break;
}
}
}
// take a plane from the array
public function removeGbugs(Gbugs:GoodBugs) {
for(var i in goodbug) {
if (goodbug[i] == Gbugs) {
goodbug.splice(i,1);
break;
}
}
}
// take a bullet from the array
public function removeBullet(bullet:Bullets) {
for(var i in bullets) {
if (bullets[i] == bullet) {
bullets.splice(i,1);
break;
}
}
}
// game is over, clear movie clips
public function endGame() {
// remove planes
for(var i:int=airplanes.length-1;i>=0;i--) {
airplanes[i].deletePlane();
}
for(var i:int= goodbug.length-1;i>=0;i--) {
goodbug [i].deleteGbugs();
}
airplanes = null;
goodbug = null
aagun.deleteGun();
aagun = null;
stage.removeEventListener(KeyboardEvent.KEY_DOWN,keyDownFunction);
stage.removeEventListener(KeyboardEvent.KEY_UP,keyUpFunction);
removeEventListener(Event.ENTER_FRAME,checkForHits);
nextPlane.stop();
nextPlane = null;
nextGbugs.stop();
nextGbugs = null;
gotoAndStop("gameover");
}
}
}

AS3 Generating differnet Enemies and bullets hitTest Problems

I'm creating a 2d side scrolling shooter with 4 different types of Enemies and 3 different types of bullets. I'm using a factory class to create the enemies and a for loop inside a for loop to do hit testing. When I run my code for some reason when one enemy get's hit some of my other enemies die. Could someone please help me locate and fix my problem.
Here's one of the Enemy classes. The other 3 are identical except with different var values.
package char {
import flash.display.MovieClip;
import flash.events.Event;
import flash.display.Stage;
public class Enemy1 extends MovieClip {
private var _type:String;
private var _health:Number;
private var _vx:Number;
private var _vy:Number;
private var _stage:Stage;
private static var _instance:Enemy1;
public function Enemy1() {
init();
}
private function init():void {
//Vars
_vx = -5;
_vy = Math.random()*5;
_health = 1;
_stage = Main.getStage();
_instance = this;
//Listeners
addEventListener(Event.ADDED_TO_STAGE, onAdded);
addEventListener(Event.ENTER_FRAME, enemyLoop);
addEventListener(Event.REMOVED_FROM_STAGE, onRemoved);
}
//When Added
private function onAdded(event:Event):void{
//Set position
this.x = _stage.stageWidth;
this.y = Math.random() * _stage.stageHeight;
//trace("Enemy created");
dispatchEvent(new Event("enemyCreated", true));
}
//Loop
private function enemyLoop(event:Event):void {
//Move
x += _vx;
y += _vy;
//Boundaries
if ( this.y <= 0 + this.height/2){
this.y = this.height/2;
_vy *= -1;
}
if ( this.y >= _stage.stageHeight - this.width/2){
this.y = _stage.stageHeight - this.width/2;
_vy *= -1;
}
//Health cheack
if ( _health <= 0){
if (this.parent) {
this.parent.removeChild(this);
Main.setScore(10);
}
}
//Leaves screen
if (this.x <= -this.width){
if (this.parent) {
this.parent.removeChild(this);
}
}
}
public function isHit(type:String):void{
//trace(this + " is hit by " + type);
if(type == "power"){
_health -= 1;
trace(_health);
}
else if(type == "quick"){
_health -= 1;
trace(_health);
}
else if(type == "strong"){
_health -= 1;
trace(_health);
}
}
public function getHealth():Number{
return _health;
}
public function getEnemy1():Enemy1{
return _instance;
}
//When Removed
private function onRemoved(event:Event):void {
removeEventListener(Event.ADDED_TO_STAGE, onAdded);
removeEventListener(Event.ENTER_FRAME, enemyLoop);
removeEventListener(Event.REMOVED_FROM_STAGE, onRemoved);
//trace("enemy removed");
}
}
}
And here's my main class that checks for all the hitTests
package screen {
import flash.display.MovieClip;
import flash.events.Event;
import com.greensock.TweenLite;
import com.greensock.easing.*;
import char.Player;
import char.EnemyFactory;
public class Level1 extends MovieClip {
//Consts
private const ENEMY_CHANCE:Number = 0.025;
//Vars
private var _player:Player;
private var _enemyBudget:Number = 20;
private static var _bullets:Array = [];
private static var _enemies:Array = [];
public function Level1() {
init();
}
private function init():void {
//Vars
this.alpha = 0;
_enemyBudget = 20;
//Event listeners
addEventListener(Event.ENTER_FRAME, levelLoop);
addEventListener(Event.ADDED_TO_STAGE, onAdded);
addEventListener(Event.REMOVED_FROM_STAGE, onRemoved);
//Add This
Main.getInstance().addChild(this);
}
private function onAdded(event:Event):void {
TweenLite.to(this, 0.5, {alpha:1});
_player = new Player();
trace("Level 1 reaady");
}
private function levelLoop(event:Event):void{
//Health bar
_healthBar.scaleX = Main.getPlayerHealth() / 100;
//enemy creation
if(_enemyBudget <= 20 && _enemyBudget > 10){
if (ENEMY_CHANCE > Math.random()){
var randomEnemy:Number = Math.random()* 1.2;
//trace(randomEnemy);
if(randomEnemy <= 0.5){
//trace("Enemy 1");
var enemy1:MovieClip = char.EnemyFactory.makeEnemy("weak");
Main.getInstance().addChild(enemy1);
_enemyBudget -= 1;
}
else if(randomEnemy > 0.5 && randomEnemy <= 0.8){
//trace("Enemy 2");
var enemy2:MovieClip = char.EnemyFactory.makeEnemy("quick");
Main.getInstance().addChild(enemy2);
_enemyBudget -= 3;
}
else if(randomEnemy > 0.8 && randomEnemy <= 1){
//trace("Enemy 3");
var enemy3:MovieClip = char.EnemyFactory.makeEnemy("strong");
Main.getInstance().addChild(enemy3);
_enemyBudget -= 3;
}
else if(randomEnemy > 1 && randomEnemy <= 1.2){
//trace("Enemy 4");
var enemy4:MovieClip = char.EnemyFactory.makeEnemy("power");
Main.getInstance().addChild(enemy4);
_enemyBudget -= 4;
}
}
}
else if(_enemyBudget <= 10 && _enemyBudget > 0){
if (ENEMY_CHANCE > Math.random()){
var randomEnemy:Number = Math.random();
if(randomEnemy <= 0.5){
//trace("Enemy 1");
var enemy1:MovieClip = char.EnemyFactory.makeEnemy("weak");
Main.getInstance().addChild(enemy1);
_enemyBudget -= 1;
}
else if(randomEnemy > 0.5 && randomEnemy <= 0.8){
//trace("Enemy 2");
var enemy2:MovieClip = char.EnemyFactory.makeEnemy("quick");
Main.getInstance().addChild(enemy2);
_enemyBudget -= 3;
}
else if(randomEnemy > 0.8 && randomEnemy <= 1){
//trace("Enemy 3");
var enemy3:MovieClip = char.EnemyFactory.makeEnemy("strong");
Main.getInstance().addChild(enemy3);
_enemyBudget -= 3;
}
}
}
else if(_enemyBudget <= 0){
if(_enemies == []){
trace("Game End");
}
}
if( Main.getPlayerHealth() <= 0){
trace("Player Dead. End Game");
}
for (var i:int = 0; i < _enemies.length; i++){
for(var j:int = 0; j < _bullets.length; j++){
if(_bullets[j] != null && _enemies[i] != null){
//Check if bullet hits enemy
if(_bullets[j].hitTestObject(_enemies[i])){
//removes bullet
if (_bullets[j].parent) {
_bullets[j].parent.removeChild(_bullets[j]);
}
//Tells enemy he's hit
if(_enemies[i] != null){
_enemies[i].isHit(_bullets[j].getType());
}
//Checks enemy health
if(_enemies[i].getHealth() <= 0){
if(_enemies[i] == null){
_enemies.splice(i, 1);
i--;
}
}
//Removes bullet from array
if(_bullets[j] == null){
_bullets.splice(j, 1);
j--;
}
}
//Check if player hit
if(_enemies[i] != null && _player != null){
if(_enemies[i].hitTestObject(_player)){
if (_enemies[i].parent) {
_enemies[i].parent.removeChild(_enemies[i]);
Main.setPlayerHealth(-10);
}
}
if(_enemies[i] == null){
_enemies.splice(i, 1);
i--;
}
}
}
}
}
}
private function onRemoved(event:Event):void{
removeEventListener(Event.ENTER_FRAME, levelLoop);
removeEventListener(Event.ADDED_TO_STAGE, onAdded);
removeEventListener(Event.REMOVED_FROM_STAGE, onRemoved);
}
//Get instance
public static function addBullet(bullet:MovieClip):void {
_bullets.push(MovieClip(bullet));
}
public static function addEnemy(enemy:MovieClip):void{
_enemies.push(MovieClip(enemy));
//trace(enemy + " was added to enemy array.");
}
}
}
And here's the function inside the Bullet class that return's it's type.
public function getType():String{
return TYPE;
}
It's hard to say with certainty, this would be easy to confirm by stepping through the code in a debugger.
But what looks suspicious to me is that you're iterating over arrays of enemies/bullets, and in the middle of doing that, you delete elements from the array and decrement the counter variables. Generally, when you need to iterate over something and potentially remove elements from the thing you're iterating over, you should do that iteration in a backwards fashion. That way changing the length and contents of the array in the middle of the loop is harmless.
for (var i:int = enemeies.length -1; i >= 0; i--)
{
// do your stuff and remove elements from the
// enemies array at will ... just splice the current
// element at index i out here, don't decrement i as
// you've done in your code above it will get decremented
// by the for loop
}

Making a simple chase AI in AS3

im attempting to make a simple game where zombies spawn out randomly from the edges of the screen and once they have spawned, they will get the last position of the player and keep moving towards that direction until they hit the stage and gets removed. However, i seem to be having a problem with the chase code. Even after reading tons of articles that offer the same chunk of code, im still unable to make it work (IM DOING IT WRONG ARRGH).
This is the main class
package
{
import flash.display.*;
import flash.events.*;
import flash.utils.*;
import flash.ui.*;
public class main extends MovieClip
{
private var left,right,up,down,fire,mouseRight,mouseLeft:Boolean;
private var speedX,speedY,mobPosX,mobPosY:int;
private var num:Number;
private var wizard:Player;
private var crosshair:Crosshair;
private var mobArray,magicArray:Array;
public function main()
{
//Hide mouse for crosshair
Mouse.hide();
crosshair = new Crosshair();
addChild(crosshair);
crosshair.x = stage.stageWidth;
crosshair.y = stage.stageHeight;
//Set initial speed
speedX = 0;
speedY = 0;
//Wizard stuff
fire = false;
wizard = new Player();
addChild(wizard);
wizard.x = stage.stageWidth / 2;
wizard.y = stage.stageHeight / 2;
//Mob stuff
mobArray = new Array();
magicArray = new Array();
//Initialize bool so movement doesn't get stuck on startup
up = false;
down = false;
left = false;
right = false;
}
public function startGame()
{
addEventListener(Event.ENTER_FRAME,update);
stage.addEventListener(KeyboardEvent.KEY_DOWN,keyDownHandler);
stage.addEventListener(KeyboardEvent.KEY_UP,keyUpHandler);
stage.addEventListener(MouseEvent.CLICK, myClick);
}
private function keyDownHandler(evt:KeyboardEvent)
{
if (evt.keyCode == 37)
{
left = true;
}
if (evt.keyCode == 38)
{
up = true;
}
if (evt.keyCode == 39)
{
right = true;
}
if (evt.keyCode == 40)
{
down = true;
}
if (evt.keyCode == 67)
{
trace(mobArray.length);
}
}
private function keyUpHandler(evt:KeyboardEvent)
{
if (evt.keyCode == 37)
{
left = false;
speedX = 0;
}
if (evt.keyCode == 38)
{
up = false;
speedY = 0;
}
if (evt.keyCode == 39)
{
right = false;
speedX = 0;
}
if (evt.keyCode == 40)
{
down = false;
speedY = 0;
}
}
function myClick(eventObject:MouseEvent)
{
fire = true;
}
public function update(evt:Event)
{
//UI
crosshair.x = mouseX;
crosshair.y = mouseY;
//Start player
if (left && right == false)
{
speedX = -8;
}
if (up && down == false)
{
speedY = -8;
}
if (down && up == false)
{
speedY = 8;
}
if (right && left == false)
{
speedX = 8;
}
wizard.x += speedX;
wizard.y += speedY;
for (var i = mobArray.length - 1; i >= 0; i--)
{
//Start mob //if X is zero and Y > 10, spawn.
var m:Zombie = new Zombie();
m.chase((Math.atan2(mobArray[i].y - wizard.y,mobArray[i].x - wizard.x)/Math.PI * 180)); //applies trigo
num = Math.random();
if (num < 0.1)
{
//when x = 0
mobPosX = 10;
mobPosY = Math.floor(Math.random() * 590) + 10;
}
else if (num < 0.3)
{
//when y = 0
mobPosX = Math.floor(Math.random() * 790) + 10;
mobPosY = 10;
}
else if (num < 0.6)
{
mobPosX = 800;
mobPosY = Math.floor(Math.random() * 590) + 10;
//when x width of screen
}
else if (num < 0.9)
{
//y is height of screen
mobPosX = Math.floor(Math.random() * 790) + 10;
mobPosY = 590;
}
m.x = mobPosX;
m.y = mobPosY;
mobArray.push(m);
addChild(m);
}
}
private function gameOver()
{
removeEventListener(Event.ENTER_FRAME,update);
stage.removeEventListener(KeyboardEvent.KEY_DOWN,keyDownHandler);
stage.removeEventListener(KeyboardEvent.KEY_UP,keyUpHandler);
}
}//end class
}//end package
This is the zombie class
package
{
import flash.display.*;
import flash.events.*;
public class Zombie extends MovieClip
{
private var zombSpd:Number;
private var angle:Number;
public function Zombie()
{
zombSpd = 10;
}
public function chase(chaseAngle:Number)
{
angle = chaseAngle;
}
public function update()
{
this.x+=Math.cos(angle*Math.PI/180)*zombSpd;
this.y+=Math.sin(angle*Math.PI/180)*zombSpd;
}
}//end class
}//end package
Thank you :)
I just reread your code and see that you must read and learn more about programming before trying to create a game like this.
the reason your zombies are not spawning are because you never get inside the for loop. mob array length will be zero to start with, so the for loop will never happen.
take that for loop out and create a function to spawn enemies in your main class. you can use the code you use in your for loop as the code for this function example:
function spawn():void{
//code directly from your for loop, with a small change
num = Math.random();
if (num < 0.1)
{
//when x = 0
mobPosX = 10;
mobPosY = Math.floor(Math.random() * 590) + 10;
}
else if (num < 0.3)
{
//when y = 0
mobPosX = Math.floor(Math.random() * 790) + 10;
mobPosY = 10;
}
else if (num < 0.6)
{
mobPosX = 800;
mobPosY = Math.floor(Math.random() * 590) + 10;
//when x width of screen
}
else if (num < 0.9)
{
//y is height of screen
mobPosX = Math.floor(Math.random() * 790) + 10;
mobPosY = 590;
}
var m:Zombie = new Zombie();
m.x = mobPosX;
m.y = mobPosY;
m.chase((Math.atan2(m.y - wizard.y,m.x - wizard.x)/Math.PI * 180)); //applies trigo
mobArray.push(m);
addChild(m);
}
now in your update function you must determine when you want enemies to spawn. you can do this by using a counter. Ill let you figure that part out, but if you want zombies to spawn continuously, (where your forloop in the update function was) add this:
//use a counter variable to determine when to execute spawn
spawn();
//loop through all zombies
for(var i:int = 0; i < mobArray.length; i++){
mobArray[i].update();
}
Steering behavior example at AdvanceEDActionScriptAnimation with abstracted interfaces and marshaling implementation.
Github:https://github.com/yangboz/as3SteeringBehavior

Collision detection for loop problem, only one array item tested?

[I apologise if this isn't really an in depth question, but I wanted to solve this once and for all]
I was trying to get look into quadtrees, but already ran into trouble getting collision detection without any optimization working properly. Did a search and found a pretty neat example:
http://wonderfl.net/c/kyLx
(onenterframeC part mostly)
Trying to imitate this, it won't work the same.
Only some collisions are detected between particular objects. When the objects are not moving it seems to work alot better for some reason.
I really can't figure out whats the problem, the code is essentially the same as the sample. I did not blindy copy pasted it, I understands whats happening except for this part:
if (j <= i)
continue;
J would never become bigger that I right? The line also completely removes any working collisions for me.
Here is what I did:
[view result here: http://martinowullems.com/collision.swf
Main class
package
{
import com.martino.objects.Square;
import com.martino.world.TestWorld;
import flash.display.MovieClip;
import flash.events.Event;
import net.hires.debug.Stats;
/**
* ...
* #author Martino Wullems
*/
public class CollisionTest extends MovieClip
{
var world:TestWorld;
public function CollisionTest()
{
addEventListener(Event.ADDED_TO_STAGE, onStage);
}
private function onStage(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, onStage);
SetupWorld();
addChild(new Stats());
}
private function SetupWorld():void
{
world = new TestWorld();
addChild(world);
addObjects(50);
}
private function addObjects(amount:int):void
{
for (var i:int = 0; i < amount; ++i) {
var square:Square = new Square(14);
world.addObject(square);
square.x = Math.random() * stage.stageWidth;
square.y = Math.random() * stage.stageHeight;
square.speedX = (Math.random() * 1) + 1;
square.speedY = (Math.random() * 1) + 1;
}
}
}
}
TestWorld
package com.martino.world
{
import com.martino.objects.Ball;
import com.martino.objects.CollisionObject;
import flash.display.MovieClip;
import flash.events.Event;
/**
* ...
* #author Martino Wullems
*/
public class TestWorld extends MovieClip
{
public var objects:Array;
public function TestWorld()
{
initWorld();
}
private function initWorld():void
{
objects = new Array();
addEventListener(Event.ENTER_FRAME, loopWorld);
}
private function loopWorld(e:Event):void
{
for (var i:int = 0; i < objects.length; i++) {
MoveObject(objects[i]);
CheckCollision(i, objects[i]);
}
}
private function CheckCollision(i:int, object:CollisionObject):void
{
//for (var j:int = i + 1; i < objects.length; j++) {
for (var j:int = 0; j < objects.length; j++) {
//if (j <= i)
//continue;
var objectB:CollisionObject = objects[j];
//hittest
if (object.hitTestObject(objectB)) {
object.isHit = true;
objectB.isHit = true;
}else {
object.isHit = false;
objectB.isHit = false;
}
/////////////////
// CHECK X Y //
////////////////
/*if (object.x + object.width < objectB.x) {
} else if (object.x > objectB.x + objectB.width) {
object.isHit = objectB.isHit = false;
} else if (object.y + object.height < objectB.y) {
object.isHit = objectB.isHit = false;
} else if (object.y > objectB.y + objectB.height) {
object.isHit = objectB.isHit = false;
} else {
object.isHit = objectB.isHit = true;
}*/
object.debugDraw();
objectB.debugDraw();
}
}
private function MoveObject(object:CollisionObject):void
{
object.x += object.speedX;
object.y += object.speedY;
////////////////////
//check boundaries//
////////////////////
if (object.x > stage.stageWidth)
{
object.speedX *= -1;
}else if (object.x < 0)
{
object.speedX *= -1;
}else if (object.y > stage.stageHeight)
{
object.speedY *= -1;
}else if (object.y < 0)
{
object.speedY *= -1;
}
}
public function addObject(object:CollisionObject):void
{
objects.push(object);
addChild(object);
}
}
}
CollisionObject
package com.martino.objects
{
import flash.display.Sprite;
import flash.events.MouseEvent;
/**
* ...
* #author Martino Wullems
*/
public class CollisionObject extends Sprite
{
public var size:int;
public var speedX:int = 0;
public var speedY:int = 0;
public var graphic:Sprite;
var sleeping:Boolean = false;
public var isHit:Boolean = false;
public function CollisionObject()
{
addEventListener(MouseEvent.MOUSE_DOWN, grab);
addEventListener(MouseEvent.MOUSE_UP, letGo);
}
private function grab(e:MouseEvent):void
{
startDrag();
speedX = 0;
speedY = 0;
}
private function letGo(e:MouseEvent):void
{
stopDrag();
}
public function Collision():void{
}
//////////////////////
// setter and getter//
//////////////////////
public function set isHit(value:Boolean):void {
_isHit = value;
graphic.visible = _isHit;
hitGraphic.visible = !_isHit;
}
public function get isHit():Boolean {
return _isHit;
}
}
}
Square
package com.martino.objects
{
import flash.display.Sprite;
/**
* ...
* #author Martino Wullems
*/
public class Square extends CollisionObject
{
public var hitGraphic:Sprite;
public function Square(Size:int)
{
size = Size;
drawSquare();
}
private function drawSquare():void
{
graphic = new Sprite();
graphic.graphics.beginFill(0xFF0000);
graphic.graphics.drawRect(0, 0, size, size);
graphic.graphics.endFill();
addChild(graphic);
hitGraphic = new Sprite();
hitGraphic.graphics.beginFill(0x0066FF);
hitGraphic.graphics.drawRect(0, 0, size, size);
hitGraphic.graphics.endFill();
addChild(hitGraphic);
hitGraphic.visible = false;
}
override public function Collision():void {
trace("I collided with a friend (inside joke)");
}
public override function debugDraw():void {
if (isHit) {
graphic.visible = false;
hitGraphic.visible = true;
}else {
graphic.visible = true;
hitGraphic.visible = false;
}
}
}
}
Any help would greatly be appreciated, want to get further on this !
EDIT: Changed some stuff, there is progress but stuff still is unclear to me !
Changed some things in TestWorld.as:
package com.martino.world
{
import com.martino.objects.Ball;
import com.martino.objects.CollisionObject;
import flash.display.MovieClip;
import flash.events.Event;
/**
* ...
* #author Martino Wullems
*/
public class TestWorld extends MovieClip
{
public var objects:Array;
public function TestWorld()
{
initWorld();
}
private function initWorld():void
{
objects = new Array();
addEventListener(Event.ENTER_FRAME, loopWorld);
}
private function loopWorld(e:Event):void
{
var object:*;
for (var i:int = 0; i < objects.length; i++) {
MoveObject(objects[i]);
//CheckCollision(i);// doesn't work here for some reason [case 1]
}
CheckCollision(0); //[case 2]
}
private function CheckCollision(i:int):void
{
//test collision
for (var i:int = 0; i < objects.length; i++){ //only use in case 2
var elementA:CollisionObject;
var elementB:CollisionObject;
elementA = objects[i];
for (var j:int = i + 1; j < objects.length; j++) {
if (j <= i){
continue; //j resets each I loop and therefor sets collision to false while it could be true
}
elementB = objects[ j ]// as ObjSprite;
if (elementA.hitTestObject(elementB)) {
elementA.isHit = elementB.isHit = true;
}
}
} //[case 2]
}
private function MoveObject(object:CollisionObject):void
{
object.x += object.vx;
object.y += object.vy;
////////////////////
//check boundaries//
////////////////////
if (object.x > stage.stageWidth)
{
object.vx *= -1;
}else if (object.x < 0)
{
object.vx *= -1;
}else if (object.y > stage.stageHeight)
{
object.vy *= -1;
}else if (object.y < 0)
{
object.vy *= -1;
}
object.isHit = false;// where do we check when it isn't colliding? this seems messy!
}
public function addObject(object:CollisionObject):void
{
objects.push(object);
addChild(object);
}
}
}
Also added a setter and getter in collisionobject (so section before the edit).
Not sure why I can't put the checkcollision inside the loop on the enter frame function? (when I do no collisions are shown). And placing "isHit = false" inside moveobjects to reset a check for a hit also seems pretty messy.
I can't seem to find out when the objects aren't colliding to reset them I guess.
Making an else statement on the hittest to check if there is no collision doesn't work, seems logical since there could be collisions with more than just 2 items in the hittestcheck.
Any idea's ?
I had to look at the original source to understand this. It is below, for reference.
This line
if (j <= i) continue;
is a permutation check; it basically makes sure that each combination only gets checked once, instead of multiple times. However, for this, you need to have two For loops - an inner one and an outer one.
You've done the same thing with the following line:
for (var j:int = i + 1; i < objects.length; j++) {
Try using that for loop instead of the one that starts from zero. Leave the "if j <= i" line commented, though. I think that will solve your problem. (Those two statements can't coexist in this loop; if used together, they'll cause the problems you're describing.)
Good luck.
Original source from website:
for (i = 0; i < myrects.length; i++) {
elementA = myrects[ i ] as ObjMyRect;
for (j = 0; j < myrects.length; j++) {
if (j <= i)
continue;
elementB = myrects[ j ] as ObjMyRect;
if (elementA.rect.x + elementA.rect.width < elementB.rect.x) {
} else if (elementA.rect.x > elementB.rect.x + elementB.rect.width) {
} else if (elementA.rect.y + elementA.rect.height < elementB.rect.y) {
} else if (elementA.rect.y > elementB.rect.y + elementB.rect.height) {
} else {
elementA.isHit = elementB.isHit = true;
}
}
}
(For what it's worth, I think that this guy's code actually checks objects against themselves for collision - he should change the "if j <= i" line to "if j < i". You solved this problem with your original for loop.)
Couple of things, after looking at his code, and reviewing your code.
This part IS necessary to make sure you don't waste time going through the loop and re-checking items that have already been compared.
if (j <= i)
continue;
Imagine you have 3 items in the array, and compare item 3 to item 0. Then you compare item 3 to item 1, and item 3, to item 2. THEN you compare item 2 to... item 3? You've already done that. You want to compare item 2 to anything lesser than itself so you avoid duplicates.
Your code is close to his, but you've swapped out his version of the hitTest (which uses position + dimension) with the already-defined hitTestObject. I'm only seeing one hit-test on the first square. Something seems off in that... I'd drop some trace statements in there and see what's up.
Last, when you uncomment his code, does it work?

Can anyone help with the collision detect for my platformer? (Actionscript 3.0)

Im currently working on making a flash platformer engine...but my collision detect needs some serious help. Whenever my character 'jumps', and lands on the collision object, he goes about halfway through it for a split second, then goes back to the top (where I want him to be). If I continue to jump multiple times, the shadow of him, if you will, that appears for a split second goes further and further into the collision object, eventually making him fall all the way through it. Here's the code for my main class, and if you need me to clarify anything, please ask.
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.display.Stage;
import Player;
import HitObject;
public class TestGame extends MovieClip {
private var _hitObject:HitObject;
private var _player:Player;
private var _leftArrow:Boolean;
private var _rightArrow:Boolean;
private var _upArrow:Boolean;
private var _hit:Boolean;
private var _fall:Boolean;
private var _jump:Boolean = true;
private var _velR:Number = 0;
private var _velL:Number = 0;
private var _scale:Number = .1;
private var _jumpCount:Number = 0;
private var _i:Number = .5;
private var _i2:Number = 7;
private var _i3:Number = 0;
private var _adjustHit:Number;
private var _jumpRL:Number;
private var _jumpVel:Number;
public function TestGame() {
_hitObject = new HitObject();
_player = new Player();
addChild(_hitObject);
addChild(_player);
_hitObject.x = (stage.width * 0.5) + 50;
_hitObject.y = (stage.height * 0.5) + 150;
_hitObject.scaleY = 3;
_hitObject.alpha = .5;
_player.scaleX = _scale;
_player.scaleY = _scale;
_player.x += 200;
_player.y += 250;
stage.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
}
private function enterFrameHandler(e:Event) {
if(_player.hitTestObject(_hitObject)) {
_adjustHit = _hitObject.y - _hitObject.height/2 - _player.height/2;
_player.y = _adjustHit;
_hit = true;
_jump = false;
if(_i3 > 8) {
_jump = true;
}
_jumpCount = 0;
_i2 = 7;
_fall = false;
_i3++;
}
else if(!_player.hitTestObject(_hitObject) && !_upArrow) {
_fall = true;
}
if(_fall) {
_player.y += _i;
_i += .5;
if(_i < 3) {
_i = 3;
}
_hit = false;
}
if(_upArrow && _hit && _jump) {
if(_velR > 0) {
_jumpRL = _velR;
_jumpVel = _velR;
}
else if(_velL > 0) {
_jumpRL = -_velL;
_jumpVel = _velL;
}
else {
_jumpVel = 1;
if(_player.scaleX == .1) {
_jumpRL = 1;
}
else {
_jumpRL = -1;
}
}
_player.y -= _i2 + _jumpVel/2;
_player.x += _jumpRL/2;
_jumpCount += _i2;
_i2 -= .5;
_fall = false;
if(_i2 < -3) {
_jumpCount = 61;
}
if(_jumpCount > 60) {
_i2 = 7;
_jump = false;
_fall = true;
_jumpCount = 0;
}
_i3 = 0;
}
if(_rightArrow) {
_player.startRun();
_player.scaleX = _scale;
_velL = 0;
_player.x += _velR;
if(_velR < 20) {
_velR += 2;
}
if(_velR > 20) {
_velR = 20;
}
}
else if(_leftArrow) {
_player.startRun();
_player.scaleX = -_scale;
_velR = 0;
_player.x -= _velL;
if(_velL < 20) {
_velL += 2;
}
if(_velL > 20) {
_velL = 20;
}
}
if(_velR > 0) {
_player.x += _velR;
_velR -= .7;
}
else if(_velL > 0) {
_player.x -= _velL;
_velL -= .7;
}
if(_velR < 0 || _velL < 0) {
_velR = 0;
_velL = 0;
}
}
private function keyDownHandler(e:KeyboardEvent):void {
if(e.keyCode == 39) {
_rightArrow = true;
}
if(e.keyCode == 37) {
_leftArrow = true;
}
if(e.keyCode == 38) {
_upArrow = true;
}
}
private function keyUpHandler(e:KeyboardEvent):void {
_upArrow = false;
_rightArrow = false;
_leftArrow = false;
}
}
}
For anyone having this problem, make sure you are applying a force in response to collision in addition to repositioning out of collision. This case sounds like maybe the velocity is being compounded by gravity, meaning you keep moving the object back but it's velocity isn't being zeroed out, so it moves further and further into the floor with each update step.
Applying normal force will cancel gravity and fix this.
If you just want easy-to-use collision detection, take a look at the Collision Detection Kit for Actionscript 3. I've used it before and it beats every other collision detection framework I've ever used.
From what you have said it sounds like at time 't' the player has not hit the object as yet but at time 't+1' the player has moved 10px (for example) so now appears stuck in the object until your collision handler moves the player to the correct spot.
Also with the jumping up and down perhaps the player has not been moved back correctly after a collision before his position increments which is why over time the player eventually falls through if you keep jumping.
Be careful about comparing numbers. I see a if (_player.scaleX == .1). Numbers in AS3 are called Floating Point numbers in other languages. Due to the way Floating Point numbers are handled by the computer they can give misleading results. Sometimes a value like 1.0 is really 0.999998 and if thats the case a compare statement will always fail.
As a tip you might want to change some of the values to CONST as you have a lot of hardcoded values, some which are related and could be changed easier by making them a CONST.