I am trying to remove a box that i have created on the screen.I have a box exported as
Box and a ship exported as player, they are both movie clips. this is the code:
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
public class Main extends MovieClip {
//playermovevar
private var _player:MovieClip;
private var _playerSpeed:Number=5;
private var _destinationX:int;
private var _destinationY:int;
//boxaddvar
private var boxAmount:Number=0;
private var boxLimit:Number=20;
private var _root:Object;
public function Main() {
createPlayer();
//playermovlisten
stage.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseHandlerdown);
//boxaddlisten
addEventListener(Event.ENTER_FRAME, eFrame);
_box.addEventListener(MouseEvent.CLICK, boxclick);
}
//playermoving
private function createPlayer():void {
_destinationX=stage.stageWidth/2;
_destinationY=stage.stageHeight/2;
_player = new Player();
_player.x=stage.stageWidth/2;
_player.y=stage.stageHeight/2;
stage.addChild(_player);
}
private function enterFrameHandler(event:Event):void {
_player.x += (_destinationX - _player.x) / _playerSpeed;
_player.y += (_destinationY - _player.y) / _playerSpeed;
}
private function mouseHandlerdown(event:MouseEvent):void {
_destinationX=event.stageX;
_destinationY=event.stageY;
addEventListener(MouseEvent.MOUSE_UP, mouseHandlerup);
rotatePlayer();
}
private function mouseHandlerup(event:MouseEvent):void {
}
private function rotatePlayer():void {
var radians:Number=Math.atan2(_destinationY-_player.y,_destinationX-_player.x);
var degrees:Number = radians / (Math.PI / 180) + 90;
_player.rotation=degrees;
}
//boxadding
private function eFrame(event:Event):void {
if (boxAmount<=boxLimit) {
boxAmount++;
var _box:Box=new Box ;
_box.y=Math.random()*stage.stageHeight;
_box.x=Math.random()*stage.stageWidth;
addChild(_box);
} else if (boxAmount >= boxLimit) {
removeEventListener(Event.ENTER_FRAME, eFrame);
} else {
addEventListener(Event.ENTER_FRAME, eFrame);
}
}
function boxclick(event:MouseEvent):void {
removeChild(_box);
}
}
It gives me this error:
1120: Access of undefined property _box. _box.addEventListener(MouseEvent.CLICK, boxclick);
1120: Access of undefined property _box. removeChild(_box);
anyone know whats wrong?
thanks
Not sure what results you're wanting but try this and feel free to ask any questions.
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
public class Main extends MovieClip {
//playermovevar
private var _player:Player;
private var _playerSpeed:Number=5;
private var _destinationX:int;
private var _destinationY:int;
//boxaddvar
private var boxAmount:Number=0;
private var boxLimit:Number=20;
private var _root:Object;
private var _box:Box;
private var arrayOfBoxes:Array = new Array(boxLimit);
public function Main() {
createPlayer();
//playermovlisten
stage.addEventListener(Event.ENTER_FRAME, enterFrameHandler, false, 0, true);
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseHandlerdown, false, 0, true);
//boxaddlisten
addEventListener(Event.ENTER_FRAME, eFrame, false, 0, true);
}
//playermoving
private function createPlayer():void {
_destinationX=stage.stageWidth/2;
_destinationY=stage.stageHeight/2;
_player = new Player();
_player.x=stage.stageWidth/2;
_player.y=stage.stageHeight/2;
stage.addChild(_player);
}
private function enterFrameHandler(event:Event):void {
_player.x += (_destinationX - _player.x) / _playerSpeed;
_player.y += (_destinationY - _player.y) / _playerSpeed;
}
private function mouseHandlerdown(event:MouseEvent):void {
_destinationX=event.stageX;
_destinationY=event.stageY;
addEventListener(MouseEvent.MOUSE_UP, mouseHandlerup, false, 0, true);
rotatePlayer();
}
private function mouseHandlerup(event:MouseEvent):void {
}
private function rotatePlayer():void {
var radians:Number=Math.atan2(_destinationY-_player.y,_destinationX-_player.x);
var degrees:Number = radians / (Math.PI / 180) + 90;
_player.rotation=degrees;
}
//boxadding
private function eFrame(event:Event):void {
if (boxAmount<=boxLimit) {
boxAmount++;
_box =new Box();
_box.y=Math.random()*stage.stageHeight;
_box.x=Math.random()*stage.stageWidth;
_box.addEventListener(MouseEvent.CLICK, boxclick, false, 0, true);
arrayOfBoxes.push(_box);
addChild(_box);
} else if (boxAmount >= boxLimit) {
removeEventListener(Event.ENTER_FRAME, eFrame);
} else {
addEventListener(Event.ENTER_FRAME, eFrame, false, 0, true);
}
}
function boxclick(evt:MouseEvent):void {
removeChild(evt.currentTarget as Box);
}
}
}
You forgot to close the } for the package.
Your _box variable does not exists as global attribute, but you are trying to access it globally.
:)
[edit]
Just remove this line from the top
_box.addEventListener(MouseEvent.CLICK, boxclick);
and put it after
var _box:Box=new Box ;
Then change boxclick function to:
function boxclick(event:MouseEvent):void {
var _box:Box = event.currentTarget as Box; // here is your box again
// make with _box what you want here. Like,
removeChild(_box);
}
Related
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.
I'm trying to create a button that when you click on it, the ship fires a laser, but the button isn't working. I mean I didn't get any error when debugging, however it won't allow me to click on the button, but instead it allows me to click on my ship to fire. Any help is greatly appreciated, thanks!
My Fire.as
package control {
import flash.events.Event;
import flash.display.Stage;
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.geom.Rectangle;
import flash.events.Event;
import objects.Ship;
public class Fire extends MovieClip {
private var my_x: Number;
private var my_y: Number;
private var ourShip: Ship;
var mouseDown: Boolean;
public function Fire(margin_left: Number, margin_bottom: Number, ourShip_mc: Ship) {
my_x = margin_left;
my_y = margin_bottom;
ourShip = ourShip_mc;
if (stage) {
init();
} else {
addEventListener(Event.ADDED_TO_STAGE, init);
}
}
private function init(e: Event = null): void {
if (hasEventListener(Event.ADDED_TO_STAGE)) {
removeEventListener(Event.ADDED_TO_STAGE, init);
}
this.x = my_x + this.width / 2;
this.y = stage.stageHeight - my_y - this.height / 2;
this.addEventListener(MouseEvent.CLICK, onClick);
}
private function onClick(event: MouseEvent): void {
//EVENT DISPATCHER
dispatchEvent(new Event("eventshoot", true));
trace("Fire clicked");
}
}
}
My Ship.as
package objects {
import flash.display.MovieClip;
import flash.display.Stage;
import flash.ui.Keyboard;
import flash.ui.Mouse;
import flash.utils.Timer;
import flash.display.JointStyle;
import control.Controller;
import control.Joystick;
import control.Fire;
public class Ship extends MovieClip {
var mouseDown: Boolean;
private var stageRef: Stage;
private var key: Controller;
private var speed: Number = 2.5;
private var vx: Number = 0;
private var vy: Number = 0;
private var friction: Number = 0.93;
private var maxspeed: Number = 8;
//fire related variables
private var fireTimer: Timer; //causes delay between fires
private var canFire: Boolean = true; //can you fire a laser
public var move_left: Boolean = false;
public var move_up: Boolean = false;
public var move_right: Boolean = false;
public var move_down: Boolean = false;
public function Ship(stageRef: Stage): void {
this.stageRef = stageRef;
key = new Controller(stageRef);
this.addEventListener(Event.ENTER_FRAME, ShipMove);
stage.addEventListener("eventshoot", firenow);
//setup your fireTimer and attach a listener to it.
fireTimer = new Timer(250, 1);
fireTimer.addEventListener(TimerEvent.TIMER, fireTimerHandler, false, 0, true);
addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
}
private function ShipMove(event: Event): void {
if (move_left)
vx -= speed;
else if (move_right)
vx += speed;
else
vx *= friction;
if (move_up)
vy -= speed;
else if (move_down)
vy += speed;
else
vy *= friction;
}
public function firenow(event: Event) {
fireLaser();
}
public function loop(e: Event): void {
//update position
x += vx;
y += vy;
//speed adjustment
if (vx > maxspeed)
vx = maxspeed;
else if (vx < -maxspeed)
vx = -maxspeed;
if (vy > maxspeed)
vy = maxspeed;
else if (vy < -maxspeed)
vy = -maxspeed;
//ship appearance
rotation = vx;
scaleX = (maxspeed - Math.abs(vx)) / (maxspeed * 4) + 0.75;
//stay inside screen
if (x > stageRef.stageWidth - 30) {
x = stageRef.stageWidth - 30;
vx = -vx;
} else if (x < 30) {
x = 30;
vx = -vx;
}
if (y > stageRef.stageHeight) {
y = stageRef.stageHeight;
vy = -vy;
} else if (y < 0) {
y = 0;
vy = -vy;
}
}
private function fireLaser(): void {
//if canFire is true, fire a laser
//set canFire to false and start our timer
//else do nothing.
if (canFire) {
stageRef.addChild(new LaserGreen(stageRef, x + vx, y - 10));
canFire = false;
fireTimer.start();
}
}
//HANDLERS
private function fireTimerHandler(e: TimerEvent): void {
//Timer ran, fire again.
canFire = true;
}
public function takeHit(): void {
dispatchEvent(new Event("hit"));
}
}
}
Updated, here's the Engine.as, sorry for not replying it to your comment below, the structure is messed up if I do so.
package objects {
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.display.StageScaleMode;
import flash.display.StageAlign;
import control.Joystick;
import control.Fire;
public class Engine extends MovieClip {
private var preloader: ThePreloader;
public function Engine() {
preloader = new ThePreloader(474, this.loaderInfo);
stage.addChild(preloader);
preloader.addEventListener("loadComplete", loadAssets);
preloader.addEventListener("preloaderFinished", showSponsors);
stage.addEventListener("gameSTART", fGameStart);
}
private function loadAssets(e: Event): void {
this.play();
}
private function showSponsors(e: Event): void {
stage.removeChild(preloader);
var ps: PrerollSponsors = new PrerollSponsors(stage);
ps.addEventListener("prerollComplete", showMenu);
ps.preroll();
}
private function showMenu(e: Event): void {
new MainMenu(stage).load();
}
public static var enemyList: Array = new Array();
private var ourShip: Ship;
private var joystick: Joystick;
private var fire: Fire;
private var scoreHUD: ScoreHUD;
public function fGameStart(evt: Event): void {
ourShip = new Ship(stage);
ourShip.x = stage.stageWidth / 2;
ourShip.y = stage.stageHeight / 2;
ourShip.addEventListener("hit", shipHit, false, 0, true);
stage.addChild(ourShip);
joystick = new Joystick(120, 70, ourShip);
addChild(joystick);
fire = new Fire(420, 70, ourShip);
addChild(fire);
scoreHUD = new ScoreHUD(stage);
stage.addChild(scoreHUD);
addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
}
private function loop(e: Event): void {
if (Math.floor(Math.random() * 20) == 5) {
var enemy: E1 = new E1(stage, ourShip);
enemy.addEventListener(Event.REMOVED_FROM_STAGE, removeEnemy, false, 0, true);
enemy.addEventListener("killed", enemyKilled, false, 0, true);
enemyList.push(enemy);
stage.addChild(enemy);
} else if (Math.floor(Math.random() * 80) == 5) {
var enemy2: E2 = new E2(stage, ourShip);
enemy2.addEventListener(Event.REMOVED_FROM_STAGE, removeEnemy, false, 0, true);
enemy2.addEventListener("killed", enemyKilled, false, 0, true);
enemyList.push(enemy2);
stage.addChild(enemy2);
}
}
private function enemyKilled(e: Event) {
scoreHUD.updateKills(1);
scoreHUD.updateScore(e.currentTarget.points);
}
private function removeEnemy(e: Event) {
enemyList.splice(enemyList.indexOf(e.currentTarget), 1);
}
private function shipHit(e: Event) {
scoreHUD.updateHits(1);
}
}
}
So every time the fire button (Fire.as) is clicked, it dispatched an event "eventshoot", and the ship (Ship.as) pick it up. And when the ship receive it, the ship itself fires a laser, that's the idea. But since there are prerolls, menus...stuff like that will loaded before starting the game, I can't just simply drag the fire button to the stage. The engine will load the ship, fire button, enemy, score... to the stage when game started. And I got a error 1009 when debugging "TypeError: Error #1009: Cannot access a property or method of a null object reference.", it is from:
stage.addEventListener("eventshoot", fire now);
in Ship.as
I understand that I'm getting this error because there is no fire button on stage, so my ship can't pickup the "eventshoot" event, is there a way I can make the ship only pickup that event after making sure the button is loaded to the stage to avoid the error?
While you certainly can create a class for your button, the functionality to make the ship object fire a laser should not be in the button.
Given a Ship class that looks like this:
package
{
import flash.display.MovieClip;
public class Ship extends MovieClip
{
public function fireLaser():void
{
trace("pew pew");
}
}
}
You can instantiate this class and add it to your main timeline with this code:
var ship:Ship = new Ship();
addChild(ship);
If you placed the symbol by hand you do not need to do this and instead only need to give it an instance name of ship.
To make something clickable, add an event listener to it. For example, to make the ship itself clickable:
var ship:Ship = new Ship();
addChild(ship);
ship.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
function onMouseDown(event:MouseEvent):void
{
trace("ship clicked");
}
If you have a button on the main time line with an instance name of fire, you can as easily add the listener to that button:
var ship:Ship = new Ship();
addChild(ship);
// v---this changed
fire.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
function onMouseDown(event:MouseEvent):void
{
trace("fire button clicked");
}
Last but not least, if you want to call a method on an object instead of using trace(), you can do that, too:
var ship:Ship = new Ship();
addChild(ship);
fire.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
function onMouseDown(event:MouseEvent):void
{
ship.fireLaser(); // this changed, laser fired "pew pew"
}
tl, dr;
The button itself shouldn't do anything. If the button did anything with the ship directly, it would have to know the ship. The button shouldn't know the ship. All the button does is say "I got clicked" by dispatching an event, everything else should be handled outside.
You know, just like when you wrote your question here, it's not the entire internet (including me) sitting in the keyboard buttons of your computer listening to your input. All your keyboard buttons did was saying "I got clicked". Everything else got handled outside, by your operating system, browser, etc.
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! :)
I'm trying to compile my 2D game to test it and I'm getting this error: \Main.as, Line 32 1136: Incorrect number of arguments. Expected 2.
Line 32 contains this code var enemy:Enemy = new Enemy(null);
Any help is always appreciated, thanks everyone.
Code associated with the error (I can post the rest if needed):
Main.as
package
{
import flash.display.Stage;
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
public class Main extends MovieClip
{
public var player:Player;
public var enemy:Enemy;
public var bulletList:Array = [];
public var mousePressed:Boolean = false; //keeps track of whether the mouse is currently pressed down
public var delayCounter:int = 0; //this adds delay between the shots
public var delayMax:int = 7; //change this number to shoot more or less rapidly
public var enemies:Array = [];
public function Main():void
{
player = new Player(stage, 320, 240);
stage.addChild(player);
//stage.addEventListener(MouseEvent.CLICK, shootBullet, false, 0, true); //remove this
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler, false, 0, true);
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler, false, 0, true);
stage.addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
for(var numBaddies=0; numBaddies<6;numBaddies++){
var enemy:Enemy = new Enemy(null);
enemy.x = numBaddies*50;
enemy.y = numBaddies*50
stage.addChild(enemy);
enemies.push(enemy);
}
}
public function loop(e:Event):void
{
if(mousePressed) // as long as the mouse is pressed...
{
delayCounter++; //increase the delayCounter by 1
if(delayCounter == delayMax) //if it reaches the max...
{
shootBullet(); //shoot a bullet
delayCounter = 0; //reset the delay counter so there is a pause between bullets
}
}
if(bulletList.length > 0)
{
for(var i:int = bulletList.length-1; i >= 0; i--)
{
bulletList[i].loop();
}
}
/*for(var h = 0; h<bulletList.length; ++h)
{
if(bulletList[h].hitTestObject(this)){
trace("player hit by baddie " + h);
}
}*/
for(var u:int=0; u<enemies.length; u++) {
Enemy(enemies[u]).moveTowards(player.x, player.y);
}
}
public function mouseDownHandler(e:MouseEvent):void //add this function
{
mousePressed = true; //set mousePressed to true
}
public function mouseUpHandler(e:MouseEvent):void //add this function
{
mousePressed = false; //reset this to false
}
public function shootBullet():void //delete the "e:MouseEvent" parameter
{
var bullet:Bullet = new Bullet(stage, player.x, player.y, player.rotation, enemies);
bullet.addEventListener(Event.REMOVED_FROM_STAGE, bulletRemoved, false, 0, true);
bulletList.push(bullet);
stage.addChild(bullet);
}
public function bulletRemoved(e:Event):void
{
e.currentTarget.removeEventListener(Event.REMOVED_FROM_STAGE, bulletRemoved);
bulletList.splice(bulletList.indexOf(e.currentTarget),1);
}
}
}
Enemy.as
package {
import flash.display.Stage;
import flash.display.MovieClip;
import flash.events.Event;
public class Enemy extends MovieClip {
public var bullets:Array;
public var stageRef:Stage;
private var enemyPositionX, enemyPositionY,xDistance,yDistance,myRotation:int;
public function Enemy(stageRef:Stage, bulletList:Array) {
// constructor code
bullets = bulletList;
this.stageRef = stageRef;
}
public function moveTowards(playerX:int, playerY:int){
xDistance = this.x - playerX;
yDistance = this.y - playerY;
myRotation = Math.atan2(yDistance, xDistance);
this.x -= 3 * Math.cos(myRotation);
this.y -= 3 * Math.sin(myRotation);
}
private function removeSelf():void
{
//removeEventListener(Event.ENTER_FRAME, loop);
if (stageRef.contains(this))
stageRef.removeChild(this);
}
}
}
As you said, error is pointing to:
var enemy:Enemy = new Enemy(null);
and Enemy constructor is:
public function Enemy(stageRef:Stage, bulletList:Array){
So you are missing 2nd parameter - bulletList.
here is my code to make multiple spring animation. but I am getting this error.
ball.vx and ball.vy are showing as undefined property.
I tried this code from Keith Peters' "Foundation
ActionScript 3.0 Animation
Making Things Move!"
does anyone know how to fix it?
package
{
import flash.display.Sprite;
import flash.events.Event;
public class Chain extends Sprite
{
private var ball0:Ball;
private var ball1:Ball;
private var ball2:Ball;
private var vx:Number = 0;
private var vy:Number = 0;
private var spring:Number = 0.1;
private var friction:Number = 0.8;
private var gravity:Number = 5;
public function Chain()
{
init();
}
private function init():void
{
ball0 = new Ball(20);
addChild(ball0);
ball1 = new Ball(20);
addChild(ball1);
ball2 = new Ball(20);
addChild(ball2);
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
private function onEnterFrame(event:Event):void
{
moveBall(ball0, mouseX, mouseY);
moveBall(ball1, ball0.x, ball0.y);
moveBall(ball2, ball1.x, ball1.y);
graphics.clear();
graphics.lineStyle(1);
graphics.moveTo(mouseX, mouseY);
graphics.lineTo(ball0.x, ball0.y);
graphics.lineTo(ball1.x, ball1.y);
graphics.lineTo(ball2.x, ball2.y);
}
private function moveBall(ball:Ball,
targetX:Number,
targetY:Number):void
{
ball.vx += (targetX - ball.x) * spring;
ball.vy += (targetY - ball.y) * spring;
ball.vy += gravity;
ball.vx *= friction;
ball.vy *= friction;
ball.x += ball.vx;
ball.y += ball.vy;
}
}
}
I guess, you faced this problem:
Foundation ActionScript 3.0 Animation Making Things Move! source code each folder have a Ball.as some different. ch03, ch05 Ball.as not have a property vx,vy. you should import ch06 or upper folder Ball.as they have a vx,vy as follows:
package {
import flash.display.Sprite;
public class Ball extends Sprite {
public var radius:Number;
private var color:uint;
public var vx:Number = 0;
public var vy:Number = 0;
public function Ball(radius:Number=40, color:uint=0xff0000) {
this.radius = radius;
this.color = color;
init();
}
public function init():void {
graphics.beginFill(color);
graphics.drawCircle(0, 0, radius);
graphics.endFill();
}
}
}
Can you show us Ball class? Probably vx and vx aren't declared.