Animating with a for loop part 2 - actionscript-3

I have another question thats has been bugging me. It's kinda a follow up from my other question "Animating with a for loop?" Ok so I have that down, but how could I animate each ball to go randomly around the stage and not follow each other?
Here is my code:
ball is pulled from an external class named Ball.
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.text.TextField;
import flash.ui.Keyboard;
public class Dummy extends Sprite
{
private var balls:Array;
private var ball:Ball;
private var ballNum: Number = 10;
private var ax:Number = 4;
public function Dummy()
{
init();
}
private function init():void
{
balls = new Array();
for(var i:Number = 0; i < ballNum; i++)
{
ball = new Ball(Math.random() * 30);
ball.x = Math.random() * stage.stageWidth;
ball.y = Math.random() * stage.stageHeight;
addChild(ball);
balls.push(ball);
}
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
protected function onEnterFrame(event:Event):void
{
for(var i:int = 0; i < balls.length; i++)
{
balls[i].x += ax;
}
}
}
}

Give each ball object a different direction and use that to move the ball instead of the ax value.
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.text.TextField;
import flash.ui.Keyboard;
public class Dummy extends Sprite
{
private var balls:Array;
private var ball:Ball;
private var ballNum: Number = 10;
private var directions:Array = [new Point(-1,-1),new Point(0,-1),new Point(1,-1),
new Point(-1,0),new Point(1,0),
new Point(-1,1),new Point(0,1),new Point(1,1)];
public function Dummy()
{
init();
}
private function init():void
{
balls = new Array();
for(var i:Number = 0; i < ballNum; i++)
{
ball = new Ball(Math.random() * 30);
ball.x = Math.random() * stage.stageWidth;
ball.y = Math.random() * stage.stageHeight;
ball.direction = directions[Math.floor(Math.random()*directions.length)];
addChild(ball);
balls.push(ball);
}
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
protected function onEnterFrame(event:Event):void
{
for(var i:int = 0; i < balls.length; i++)
{
balls[i].x += balls[i].direction.x;
balls[i].y += balls[i].direction.y;
}
}
}
}

Give your Ball class properties for speed, and a method move() that will adjust their respective coordinates, and probably will be enhanced to check for collisions sometimes later, so that your balls could rebound of walls for example.
// Ball class additions follow
private var vx:Number;
private var vy:Number;
public function Ball() {
// ... original constructor here
var angle:Number=Math.random(2.0*Math.PI); // random angle
var vel:Number= MAX_VELOCITY*(0.5+0.5*Math.random()); // random velocity module
// define this constant^
vx=vel*Math.cos(angle);
vy=vel*Math.sin(angle); // composites of velocity
}
public function move():void {
this.x+=vx;
this.y+=vy;
}
// main class
protected function onEnterFrame(event:Event):void
{
for(var i:int = 0; i < balls.length; i++)
{
balls[i].move();
}
}

Related

AS3 - Space Shooter Enemy Shots

I'm very new to AS3 and programming in general and I've been developing a space shooter game in AS3 and have run into trouble regarding the enemy shots. The enemies fly vertically down from the top of the screen and should fire two shots (one going left and one going right) once their y coordinates equal that of the player. This works fine, except after anything from 30 seconds to 2 minutes, the following errors occur.
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at EnemyShip2/fireWeapon()[G:\Games Related\1942\src\EnemyShip2.as:78]
at EnemyShip2/loop2()[G:\Games Related\1942\src\EnemyShip2.as:65]
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at EnemyShot/removeSelf()[G:\Games Related\1942\src\EnemyShot.as:43]
at EnemyShot/loop()[G:\Games Related\1942\src\EnemyShot.as:36]
Below is the relevant code, for the enemy ship class as well as the enemy shot class.
Enemy Ship
package
{
import flash.display.Sprite;
import flash.display.Bitmap;
import flash.display.Stage;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.utils.Timer;
/**
* ...
* #author D Nelson
*/
[Embed(source = "../assets/enemyship2.png")]
//This enemy moves relatively slowly and fires horizontal shots
public class EnemyShip2 extends Bitmap
{
private var vy:Number = 3;
//private var ay:Number = .2;
private var target:HeroShip;
private var enemyShip2:EnemyShip2;
private var enemyfireTimer:Timer;
private var enemycanFire:Boolean = true;
public function EnemyShip2(target:HeroShip):void
{
this.target = target;
scaleX = 0.3;
scaleY = 0.3;
x = Math.floor(Math.random() * 550);
y = -105;
addEventListener(Event.ENTER_FRAME, loop2, false, 0, true);
enemyfireTimer = new Timer(1000, 1);
enemyfireTimer.addEventListener(TimerEvent.TIMER, handleenemyfireTimer, false, 0, true);
}
private function handleenemyfireTimer(e:TimerEvent) : void
{
//the timer runs, so a shot can be fired again
enemycanFire = true;
}
private function removeSelf2():void
{
removeEventListener(Event.ENTER_FRAME, loop2);
if (stage.contains(this))
{
stage.removeChild(this);
}
}
private function loop2 (e:Event):void
{
//vy += ay;
y += vy;
if (y > stage.stageHeight)
{
removeSelf2();
}
if (y >= target.y && (enemycanFire))
{
fireWeapon();
enemycanFire = false;
enemyfireTimer.start();
}
if (this.x > 540 || this.x < 10)
{
removeSelf2();
}
}
private function fireWeapon():void
{
stage.addChild(new EnemyShot(target, x, y, -4));
stage.addChild(new EnemyShot(target, x, y, +4));
}
}
}
Enemy Shot
package
{
import flash.display.Sprite;
import flash.display.Bitmap;
import flash.events.Event;
import flash.display.Stage;
/**
* ...
* #author D Nelson
*/
[Embed(source="../assets/enemyshot.png")]
public class EnemyShot extends Bitmap
{
private var speed:Number;
private var target:HeroShip;
private var vx:Number;
public function EnemyShot(target:HeroShip, x:Number, y:Number, vx:Number)
{
this.target = target;
this.x = x;
this.y = y;
this.vx = vx;
scaleX = 0.3;
scaleY = 0.3;
addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
}
private function loop(e:Event) : void
{
x += vx;
if (x >= 600 || x <= -50)
{
removeSelf();
}
}
private function removeSelf():void
{
removeEventListener(Event.ENTER_FRAME, loop);
if (stage.contains(this))
{
stage.removeChild(this);
}
}
}
}
Also provided is the main class, in case that is of any help.
package
{
import flash.display.Sprite;
import flash.display.MovieClip;
import flash.display.DisplayObject;
import flash.display.Stage;
import flash.events.*;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.KeyboardEvent;
import flash.events.TimerEvent;
import flash.ui.Mouse;
import flash.utils.*;
import flash.utils.ByteArray;
import flash.utils.Timer;
import flash.text.*;
import flash.media.Sound;
import flash.media.SoundChannel;
/**
* ...
* #author D Nelson
*/
public class Main extends MovieClip
{
[Embed(source = "snd/gamemusic2.mp3")]
private var MySound : Class;
private var mainsound : Sound;
private var shootsound: Sound = new ShootSound;
private var sndChannel:SoundChannel = new SoundChannel;
public var heroShip:HeroShip;
public var enemyShip1:EnemyShip1
public var enemyShip2:EnemyShip2
public var enemyShip3:EnemyShip3
public var enemyShip4:EnemyShip4
public var bossShip: BossShip
public var enemyShot: EnemyShot;
public var playerShot: PlayerShot;
private var background1:Background1;
private var background2:Background2;
public static const scrollspeed:Number = 2;
public var playerShotArray:Array = new Array()
public var enemyShotArray:Array = new Array()
public var enemies1Array:Array = new Array()
public var enemies2Array:Array = new Array()
private var fireTimer:Timer; //this creates a delay between each shot
private var canFire:Boolean = true; //this checks if a shot can be fired
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
mainsound = (new MySound) as Sound;
shootsound = (new ShootSound) as Sound;
mainsound.play();
background1 = new Background1();
background2 = new Background2();
//setting the backgrounds one below another
background1.y = 0;
background2.y = background1.height;
//add background at the lowest depth level
stage.addChildAt(background1,0);
stage.addChildAt(background2, 0);
//sets up the timer and its listener
fireTimer = new Timer(250, 1);
fireTimer.addEventListener(TimerEvent.TIMER, handlefireTimer, false, 0, true);
stage.addEventListener(KeyboardEvent.KEY_DOWN, handleCharacterShoot);
//background scrolling effect
stage.addEventListener(Event.ENTER_FRAME, backgroundScroll);
//loop for enemy1 variety
stage.addEventListener(Event.ENTER_FRAME, loop1, false, 0, true);
//loop for enemy2 variety
stage.addEventListener(Event.ENTER_FRAME, loop2, false, 0, true);
//speed of player shots
setInterval(playerShootMovement, 10);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
//entry point
heroShip = new HeroShip();
stage.addChild(heroShip);
//test values for enemies
/*enemyShip1 = new EnemyShip1();
stage.addChildAt(enemyShip1, 2);
enemyShip1.y = stage.stageWidth * 0.3;
enemyShip1.x = 300;
enemyShip2 = new EnemyShip2();
stage.addChildAt(enemyShip2, 2);
enemyShip2.y = stage.stageWidth * 0.3;
enemyShip2.x = 200;
enemyShip3 = new EnemyShip3();
stage.addChildAt(enemyShip3, 2);
enemyShip3.y = stage.stageWidth * 0.3;
enemyShip3.x = 100;
enemyShip4 = new EnemyShip4();
stage.addChildAt(enemyShip4, 2);
enemyShip4.y = stage.stageWidth * 0.3;
enemyShip4.x = 400;
bossShip = new BossShip();
stage.addChildAt(bossShip, 1);
bossShip.y = 10;
bossShip.x = 130;*/
Mouse.hide();
}
private function handlefireTimer(e:TimerEvent) : void
{
//the timer runs, so a shot can be fired again
canFire = true;
}
public function playerShoot():void
{
//if canFire is true, allow a shot to be fired, then set canFire to false and start the timer again
//else, do nothing
if (canFire)
{
//Add new line to the array
playerShotArray.push(playerShot = new PlayerShot);
//Spawn missile in ship
playerShot.y = heroShip.y;
playerShot.x = heroShip.x+11;
addChild(playerShot);
canFire = false;
fireTimer.start();
sndChannel = shootsound.play();
}
}
public function playerShootMovement():void
{
//code adapted from the Pie Throw tutorial
for (var i:int = 0; i < playerShotArray.length; i++)
{
playerShotArray[i].y -= 10;
if (playerShotArray[i].y == 850)
{
playerShotArray.shift();
}
}
}
public function handleCharacterShoot(e:KeyboardEvent):void
{
/**
* SpaceBar = 32
*/
if (e.keyCode == 32)
{
playerShoot();
}
}
public function backgroundScroll (evt:Event):void
{
background1.y += scrollspeed;
background2.y += scrollspeed;
if (background1.y >= stage.stageHeight)
{
//the background is below the visible stage area, put it above the other background
background1.y = background2.y - background2.height;
}
else if (background2.y >= stage.stageHeight)
{
background2.y = background1.y - background2.height;
}
}
//EnemyShip 1 spawning
private function loop1(e:Event):void
{
//generates probability for the ship to spawn (lower number to increase odds, decrease it to decrease odds)
if (Math.floor(Math.random() * 55) == 5)
{
var enemyShip1:EnemyShip1 = new EnemyShip1(heroShip);
enemyShip1.addEventListener(Event.REMOVED_FROM_STAGE, removeEnemy1, false, 0, true);
enemies1Array.push(enemyShip1);
stage.addChild(enemyShip1);
}
}
private function removeEnemy1(e:Event):void
{
//removes the enemy that most recently left the screen from the array
enemies1Array.splice(enemies1Array.indexOf(e.currentTarget), 1);
}
//EnemyShip2 spawning
private function loop2(e:Event):void
{
if (Math.floor(Math.random() * 40) == 5)
{
var enemyShip2:EnemyShip2 = new EnemyShip2(heroShip);
enemyShip2.addEventListener(Event.REMOVED_FROM_STAGE, removeEnemy2, false, 0, true);
enemies2Array.push(enemyShip2);
stage.addChild(enemyShip2);
}
}
private function removeEnemy2(e:Event):void
{
enemies2Array.splice(enemies2Array.indexOf(e.currentTarget), 1);
}
}
}
Initially I thought it was to do with enemies firing shots while being too far to either side of the screen, but that doesn't seem to be the case. Any help would be greatly appreciated.
You need to make sure you remove the ENTER_FRAME listeners whenever you remove the object.
Actually, my advise is to not add ENTER_FRAME handlers throughout your game objects. This gets hard to manage and leads to bugs like you've encountered. Instead, add a single ENTER_FRAME as your core game loop, and update objects by calling an update() function on a list of game objects you maintain in your main game class. When you remove an object you simply won't call update() anymore. It also becomes easy to pause the game by just removing the ENTER_FRAME handler.
For example, here's a pattern I like to use for simple games:
interface IGameObject {
update():void;
}
class Enemy extends Sprite implements IGameObject {
public update():void {
// move, fire, etc
}
}
class Player extends Sprite implements IGameObject {
public update():void {
// move, fire, etc
}
}
class Bullet extends Bitmap implements IGameObject {
public update():void {
// move, collide, etc
}
}
class Main extends Sprite {
private objects:Vector.<IGameObject> = new <IGameObject>[];
public start():void {
addEventListener(Event.ENTER_FRAME, update);
}
public stopGame():void {
removeEventListener(Event.ENTER_FRAME, update);
}
private function update(e:Event):void {
for each (var object:IGameObject in objects) {
object.update();
}
}
public addObject(object:IGameObject):void {
objects.push(object);
addChild(object as DisplayObject);
}
public removeObject(object:IGameObject):void {
objects.splice(objects.indexOf(object), 1);
removeChild(object as DisplayObject);
}
}
Add and remove objects using addObject and removeObject. You can invoke them through a reference to Main or through event handlers you dispatch from your objects.

how to reference a hit test object between .as files [AS3]

i'm trying to make a top down shooter game, and have been following tutorials here: http://gamedev.michaeljameswilliams.com/2008/09/17/avoider-game-tutorial-1/
and here: as3gametuts.com/2013/07/10/top-down-rpg-shooter-4-shooting/
i've managed to get shooting and movement, but i need to get a hit test object to register when the bullet (defined in its own seperate as class file) and the enemy (also defined in seperate file) come into contact. code below:
Enemy code:
package
{
import flash.display.MovieClip;
public class Enemy extends MovieClip
{
public function Enemy()
{
x = 100;
y = -15;
}
public function moveDownABit():void
{
y = y + 3;
}
}
}
Bullet code:
package
{
import flash.display.Stage;
import flash.display.MovieClip;
import flash.events.Event;
import flash.utils.Timer;
import flash.events.TimerEvent;
public class Bullet extends MovieClip
{
private var stageRef:Stage;
private var speed:Number = 10;
private var xVel:Number = 0;
private var yVel:Number = 0;
private var rotationInRadians = 0;
public var enemy:Enemy;
public function Bullet(stageRef:Stage, X:int, Y:int, rotationInDegrees:Number):void
{
this.stageRef = stageRef;
this.x = X;
this.y = Y;
this.rotation = rotationInDegrees;
this.rotationInRadians = rotationInDegrees * Math.PI / 180;
}
public function bullethit():void{
if (Bullet.hitTestObject(enemy)){
gameTimer.stop();
}
}
public function loop():void
{
xVel = Math.cos(rotationInRadians) * speed;
yVel = Math.sin(rotationInRadians) * speed;
x += xVel;
y += yVel;
if(x > stageRef.stageWidth || x < 0 || y > stageRef.stageHeight || y < 0)
{
this.parent.removeChild(this);
}
}
}
}
Main.as document class code:
package
{
import flash.display.Stage;
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.utils.Timer;
import flash.events.TimerEvent;
public class Main extends MovieClip
{
public var player:Player;
public var bulletList:Array = []; //new array for the bullets
public var enemy:Enemy;
public var gameTimer:Timer;
public function Main():void
{
player = new Player(stage, 320, 240);
stage.addChild(player);
enemy = new Enemy();
addChild( enemy );
gameTimer = new Timer( 25 );
gameTimer.addEventListener( TimerEvent.TIMER, moveEnemy );
gameTimer.start();
stage.addEventListener(MouseEvent.CLICK, shootBullet, false, 0, true);
stage.addEventListener(Event.ENTER_FRAME, loop, false, 0, true); //add an EventListener for the loop
}
public function moveEnemy( timerEvent:TimerEvent ):void
{
enemy.moveDownABit();
}
public function loop(e:Event):void //create the loop function
{
if(bulletList.length > 0) //if there are any bullets in the bullet list
{
for(var i:int = bulletList.length-1; i >= 0; i--) //for each one
{
bulletList[i].loop(); //call its loop() function
}
}
}
public function shootBullet(e:MouseEvent):void
{
var bullet:Bullet = new Bullet(stage, player.x, player.y, player.rotation);
bullet.addEventListener(Event.REMOVED_FROM_STAGE, bulletRemoved, false, 0, true); //triggers the "bulletRemoved()" function whenever this bullet is removed from the stage
bulletList.push(bullet); //add this bullet to the bulletList array
stage.addChild(bullet);
}
public function bulletRemoved(e:Event):void
{
e.currentTarget.removeEventListener(Event.REMOVED_FROM_STAGE, bulletRemoved); //remove the event listener so we don't get any errors
bulletList.splice(bulletList.indexOf(e.currentTarget),1); //remove this bullet from the bulletList array
}
}
}
As Vesper said, you'll want to do your checks in the Main class. You've already got a game loop set up, so you can just add the check in there:
public function loop(e:Event):void //create the loop function
{
if(bulletList.length > 0) //if there are any bullets in the bullet list
{
for(var i:int = bulletList.length-1; i >= 0; i--) //for each one
{
bulletList[i].loop(); //call its loop() function
// check to see if the enemy has been hit
if(enemy.hitTestObject(bulletList[i]))
{
// the enemy has been hit by the bullet at index i
}
}
}
}
Since you currently only have a single enemy, you're just testing each bullet against that one enemy. If you had more enemies, you'd want to keep an array of references to those enemies and do a nested loop, checking to see if any of the enemies were hit by any of the bullets.

Can't remove object from stage

I have a problem. I am trying to make a copter game in Adobe Flash with ActionScript 3.0, but now the game works, but the obstacles can't be removed from stage. The obstacles are still going miles out of the stage. How can I remove the obstacles?? and same problem if you are game over, if you are game over the event end, but the last spawned obstacles you see still and aren't removed. And how can I make the obstacles go faster after a period of time??
There are standing some dutch words in it, such as 'hoeSpelen' that is for instructions text en 'af' is for the gameover text and 'tijd' = time and 'balkje' = obstacles.
I hope you can help me.
package
{
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.utils.getTimer;
import flash.events.Event;
public class iCopter extends MovieClip
{
private var copter : Copter = null;
private var gameover : GameOver = null;
private var balkje : Balkje = null;
private var tijd : int
var score = 0;
var highscore = 0;
public function onStartButton(event:MouseEvent)
{
startiCopter()
}
public function iCopter()
{
startButton.addEventListener(MouseEvent.CLICK, onStartButton);
af.visible = false
output.visible = false
hscore.visible = false
}
public function startiCopter()
{
removeChild(startButton);
removeChild(hoeSpelen);
removeChild(af);
score = 0
icopterlogo.visible = false
output.visible = true
hscore.visible = true
copter = new Copter();
copter.x = 100;
copter.y = 200;
addChild(copter);
tijd = getTimer();
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
public function onEnterFrame(event:Event)
{
var now:int = getTimer();
if (now - tijd > 1250)
{
var balkje = new Balkje();
balkje.x = 350;
balkje.y = Math.random() * 150;
addChild (balkje);
tijd = now
score = score + 10;
output.text = "score: "+score;
if (balkje.x <= -10) //don't work.
{ //don't work.
removeChild (balkje); //don't work.
} //don't work.
}
addEventListener(Event.ENTER_FRAME, botsing);
}
function botsing (event:Event)
{
for (var i = 0; i < numChildren; i++)
{
if (getChildAt(i) is Balkje || getChildAt(i) is Vloer)
{
var b = getChildAt(i) as MovieClip;
if (b.hitTestObject(copter))
{
removeChild (copter);
removeEventListener(Event.ENTER_FRAME, onEnterFrame);
var gameover = new GameOver();
addChild(af);
af.visible = true
addChild(hoeSpelen);
addChild(startButton);
if (score > highscore)
{
highscore = score
hscore.text = "highscore: "+highscore;
}
}
}
}
}
}
}
Here are the scripts for the copter and obstacle
copter:
muisKlik = mouseClick
muisDruk = mousePush
muisOmhoog = mouseUp
package
{
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.events.Event;
public class Copter extends MovieClip
{
var vy : Number = 0;
var muisKlik : Boolean = false;
public function Copter()
{
vy = 5;
addEventListener(Event.ENTER_FRAME, onEnterFrame);
addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(event:Event)
{
stage.addEventListener(MouseEvent.MOUSE_DOWN, muisDruk);
stage.addEventListener(MouseEvent.MOUSE_UP, muisOmhoog);
}
public function onEnterFrame(event:Event)
{
if (muisKlik == true)
{
y -= vy;
}
else
{
y += vy;
}
}
public function muisDruk (event:MouseEvent)
{
muisKlik = true
}
public function muisOmhoog (event:MouseEvent)
{
muisKlik = false
}
}
}
obstacle:
package
{
import flash.display.MovieClip;
import flash.events.Event;
public class Balkje extends MovieClip
{
var vx : Number = 1;
public function Balkje()
{
vx = 5;
addEventListener( Event.ENTER_FRAME, onEnterFrame );
}
public function onEnterFrame( event:Event )
{
x -= vx;
}
}
}
Not tested - probably full of errors, and I haven't done AS3 in a while:
When you initialize obstacles, pass in the stage object (not sure if this is the best practice)
package {
import flash.display.MovieClip;
import flash.events.Event;
public class Balkje extends MovieClip
{
var vx : Number = 1;
public function Balkje()
{
vx = 5;
if(!stage){
//if stage isn't populated yet, wait for it
this.addEventListner(Event.ADDED_TO_STAGE,addedToStage);
}else{
init();
}
}
private function addedToStage(e:Event):void {
this.removeEventListener(Event.ADDED_TO_STAGE,addedToStage);
init();
}
protected function init():void {
this.addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
public function onEnterFrame( event:Event )
{
x -= vx;
//check x
if(this.x + this.width <= 0 || this.x >= stage.stageWidth) {
if(this.parent) this.parent.remmoveChild(this);
removeEventListener( Event.ENTER_FRAME, onEnterFrame );
}
}
}
}
Again, not tested (is stage.stageWidth correct to get the stage width?) but you get the idea. Check the x of the object, if it is outside the visible stage remove it from its parent (I just put this.parent because you didn't add the obstacle to the stage).
Also, why do you add event listener to ENTER_FRAME in a function called by ENTER_FRAME?

CS6 Error 1046: Type was not found or was not a compile-time constant: Vector3D

I'm trying to use vectors to make an enemy track a target (player's ship). However, I keep getting Error 1046. Any advice? The error occurs on the line containing the drawForceVector function in the Game.as file.
Here is my Game.as file code:
package{
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Vector3D;
import flash.text.TextField;
public class Game extends MovieClip
{
public static var mouse :Vector3D = new Vector3D(100, 100);
public var boids :Vector.<Boid> = new Vector.<Boid>;
public var forces :Sprite;
public function Game() {
addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e :Event) :void {
var i :int, boid :Boid;
for (i = 0; i < 2; i++) {
boid = new Boid(stage.stageWidth * Math.random(), stage.stageHeight * Math.random(), 20 + Math.random() * 20);
addChild(boid);
boids.push(boid);
}
forces = new Sprite();
addChild(forces);
}
public function update():void {
var i :int;
forces.graphics.clear();
for (i = 0; i < boids.length; i++) {
boids[i].update();
drawForces(boids[i]);
}
}
private function drawForces(boid :Boid) :void {
var desired :Vector3D = boid.desired.clone();
var velocity :Vector3D = boid.velocity.clone();
var steering :Vector3D = boid.steering.clone();
velocity.normalize();
desired.normalize();
steering.normalize();
// Force vectors
drawForceVector(boid, velocity, 0x00FF00);
drawForceVector(boid, desired, 0x454545);
drawForceVector(boid, steering, 0x0000FF);
// Target
forces.graphics.lineStyle(1, 0x323232);
forces.graphics.beginFill(0x323232);
forces.graphics.drawCircle(mouse.x, mouse.y, 10);
forces.graphics.endFill();
}
private function drawForceVector(boid :Boid, force :Vector3D, color :uint, scale :Number = 100) :void { //ERROR OCCURS ON THIS LINE
forces.graphics.moveTo(boid.x + boid.width / 2, boid.y + boid.height / 2);
forces.graphics.lineStyle(2, color);
forces.graphics.lineTo(boid.x + force.x * scale, boid.y + force.y * scale);
}
}
}
Boid.as Code:
package {
import flash.display.MovieClip;
import flash.geom.Vector3D;
import flash.object.Vector3D;
public class Boid extends MovieClip
{
public static const MAX_FORCE :Number = 0.4;
public static const MAX_VELOCITY :Number = 3;
public var position :Vector3D;
public var velocity :Vector3D;
public var target :Vector3D;
public var desired :Vector3D;
public var steering :Vector3D;
public var mass :Number;
public function Boid(posX :Number, posY :Number, totalMass :Number = 20) {
position = new Vector3D(posX, posY);
velocity = new Vector3D(-1, -2);
target = new Vector3D(310, 240);
desired = new Vector3D(0, 0);
steering = new Vector3D(0, 0);
mass = totalMass;
truncate(velocity, MAX_VELOCITY);
x = position.x;
y = position.y;
graphics.beginFill(0xFF0000);
graphics.drawRect(0, 0, 20, 20);
graphics.endFill();
}
private function seek(target :Vector3D) :Vector3D {
var force :Vector3D;
desired = target.subtract(position);
desired.normalize();
desired.scaleBy(MAX_VELOCITY);
force = desired.subtract(velocity);
return force;
}
public function truncate(vector :Vector3D, max :Number) :void {
var i :Number;
i = max / vector.length;
i = i < 1.0 ? 1.0 : i;
vector.scaleBy(i);
}
public function update():void {
target = Game.mouse;
steering = seek(target);
truncate(steering, MAX_FORCE);
steering.scaleBy(1 / mass);
velocity = velocity.add(steering);
truncate(velocity, MAX_VELOCITY);
position = position.add(velocity);
x = position.x;
y = position.y;
}
}
}
Main.as Code:
package {
import flash.display.Sprite;
import flash.events.*;
[SWF(width = "600", height = "480")]
public class Main extends Sprite
{
private var game :Game = new Game();
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
stage.addEventListener(Event.ENTER_FRAME, enterFrame);
stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMove);
stage.frameRate = 30;
addChild(game);
}
private function mouseMove(e :MouseEvent) :void {
Game.mouse.x = e.stageX;
Game.mouse.y = e.stageY;
}
private function enterFrame(e :Event) :void {
game.update();
}
}
}
Thank you very much.
The target version of the player must be higher than the one you've got - Flash Player 9. As seen by the reference, it's said that Vector3D is included in: Runtime Versions: Flash Player 10, AIR 1.5. So basically you are building for so old Flash Player, that it still doesn't have this class inside it.
Simply change the target version to the latest possible one, and be sure it's higher than Flash Player 10. That will do the job! :)

AS3 Turret and bullet error

I have been struggling with a as3 and flash game that i am trying to make. Everything looks fine, but still the bullet are stuck inside the cannon. When i use my mouse to shoot, instead of going out to a location, it just get stuck inside the cannon:
Got 3 as3 documents, and one flash document:
Ships.as
package{
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Point;
public class Ship extends Sprite{
private var speed:int;
private var target:Point;
function Ship(){
speed=2+Math.random()*5;
//trace("Made a Ship!");
//set the target for the ships
target = new Point(Math.random()*500, Math.random()*500);
//target.x = Math.random()*500;
//target.y = Math.random()*500;
//addEventListener(Event.ENTER_FRAME, update);
}
function update(){
//Set the ships to point the target
var dx = target.x - x;
var dy = target.y - y;
var angle = Math.atan2(dy, dx)/Math.PI*180;
rotation = angle;
x=x+Math.cos(rotation/180*Math.PI)*speed;
y=y+Math.sin(rotation/180*Math.PI)*speed;
//New target
var hyp = Math.sqrt((dx*dx)+(dy*dy));
if(hyp < 5){
target.x = Math.random()*500;
target.y = Math.random()*500;
}
}
}
}
Game.as
package{
import flash.display.MovieClip;
import flash.events.Event;
public class Game extends MovieClip{
var ships:Array;
public function Game(){
trace("Made that game!");
addEventListener(Event.ENTER_FRAME, loop);
//set up the ship array
ships = new Array();
}
function loop(e:Event){
if(numChildren<10){
var s = new Ship();
addChild(s);
s.x = Math.random()*stage.stageWidth;
s.y = Math.random()*stage.stageHeight;
s.rotation = Math.random()*360;
//Add the ship to the list of ships
ships.push(s);
}
//Make a for loop to iterate through all the ship
for(var count=0; count<ships.length; count++){
ships[count].update();
//Add a new for loop to go through all the bullets
}
}
}
}
}
}
Turret.as
package{
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
public class Turret extends MovieClip{
//Properties goes here
var shotCooldown:int;
var bullets:Array;
const MAX_COOLDOWN = 10;
public function Turret(){
//Set the Shot Cooldown
shotCooldown = MAX_COOLDOWN;
bullets = new Array();
addEventListener(Event.ENTER_FRAME, update);
addEventListener(Event.ADDED_TO_STAGE, initialise);
}
function initialise(e:Event)
{
stage.addEventListener(MouseEvent.CLICK, fire);
}
function fire(m:MouseEvent)
{
//If we are allowed to shoot
if(shotCooldown<=0)
{
//Reset the Shot Cooldown
shotCooldown=MAX_COOLDOWN;
//Spawn a Bullet
var b = new Bullet();
b.rotation = rotation;
b.x = x;
b.y = y;
//Add the bullet to the list of bullets
bullets.push(b);
parent.addChild(b);
play();
}
}
function update(e:Event)
{
//Reduce the Shot Cooldown by 1
//shotCooldown=shotCooldown-1;
//shotCooldown-=1;
shotCooldown--;
if(parent != null)
{
var dx = parent.mouseX - x;
var dy = parent.mouseY - y;
var angle = Math.atan2(dy, dx) / Math.PI * 180;
rotation = angle;
}
}
}
}
They are stuck in place maybe because you are not moving them at all? If you are then please show me where. Try adding to the turret's enter frame event the following code:
for (var a:int = 0; bullets.length > a ; a++)
{
var temp:MovieClip;
temp = bullets[a] as Bullet;
var vel:Point = new Point();
vel.x = temp.target.x-temp.x;
vel.y = temp.target.y-temp.y;
vel.normalize(4);
temp.x += vel.x;
temp.y += vel.y;
}
And make an as file for the Bullet Class and add this:
package
{
import flash.geom.Point;
public class Bullet extends MovieClip
{
public var target:Point = new Point();
public function Bullet()
{
target.x = stage.mouseX;
target.y = stage.mouseY;
}
}
}
In Turret class bullets are added to the stage and array but doesn't have updated every frame like ships. See your own comment about updating bullets!