I already have the graphic with image on the screen and I wanted to it to move when I pressed the arrows on keyboard.
But it seems the listener is not running and there is no error.
Here is the code:
package
{
import flash.display.Loader;
import flash.display.Sprite;
import flash.events.Event;
import flash.display.BitmapData;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
import flash.net.URLRequest;
/**.
* ....
* #author Kaoru
*/
[SWF(width = '800', height = '600', backgroundColor = '#000000', frameRate = '24')]
public class GameManager extends Sprite
{
var myBitmap:BitmapData;
var imgLoader:Loader;
var circle:Sprite;
public function GameManager():void
{
circle = new Sprite();
imgLoader = new Loader();
imgLoader.load(new URLRequest("../lib/fira_front.png"));
imgLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, drawImage);
addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
}
private function drawImage(e:Event):void
{
myBitmap = new BitmapData(imgLoader.width, imgLoader.height, false);
myBitmap.draw(imgLoader);
circle.graphics.beginBitmapFill(myBitmap, null, true);
circle.graphics.drawCircle(50, 50, 10);
circle.graphics.endFill();
addChild(circle);
}
private function onKeyDown(e:KeyboardEvent):void
{
if (e.keyCode == Keyboard.LEFT)
{
circle.x += 5;
}
else if (e.keyCode == Keyboard.RIGHT)
{
circle.x -= 5;
}
if (e.keyCode == Keyboard.UP)
{
circle.y += 5;
}
else if (e.keyCode == Keyboard.DOWN)
{
circle.y -= 5;
}
}
}
}
You need to add it to stage like so,
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
I have modified your code like so:
Always check for ADDED_TO_STAGE first and then proceed,
public function GameManager():void
{
addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
}
private function onAddedToStage(e:Event):void
{
circle = new Sprite();
imgLoader = new Loader();
imgLoader.load(new URLRequest("../lib/fira_front.png"));
imgLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, drawImage);
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); //This line is modified
removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
}
Have you tried to add your listener on the stage directly ?
So that this
public function GameManager():void
{
circle = new Sprite();
imgLoader = new Loader();
imgLoader.load(new URLRequest("../lib/fira_front.png"));
imgLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, drawImage);
addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
}
Becomes this
public function GameManager():void
{
circle = new Sprite();
imgLoader = new Loader();
imgLoader.load(new URLRequest("../lib/fira_front.png"));
imgLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, drawImage);
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
}
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.
so I'm new to AS3, and have struggled to get to this point, so sorry for any errors or nooby mistakes.
All I want now, is for my game to restart after 2 minutes has passed. Does anyone know how I can do this? I'm at a complete loss.
Here is my code:
package
{
import flash.display.Sprite;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
import Ship;
import Coin;
import CoinB;
import flash.events.Event;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.utils.getTimer;
public class Main extends Sprite
{
// constructor code
private var Player1:Ship;
private var Coin1:Coin;
private var Coin2:Coin;
private var Coin3:CoinB;
private var Coin4:CoinB;
private var score:int = 0;
private var container;
/*private var timer:Timer;*/
public function Main():void
{
//Sets the position of player
//adds player to stage
this.Player1 = new Ship(259,365);
addChild(this.Player1);
Cont.visible = false;
{
addChild(interval_timer);
/*addChild(frame_timer);*/
/*frame_timer.y = 50;*/
var time_count:Timer = new Timer(1000);
time_count.addEventListener(TimerEvent.TIMER, show_time);
stage.addEventListener(Event.ENTER_FRAME,on_enter_frame);
time_count.start();
}
//adds event listeners
stage.addEventListener(KeyboardEvent.KEY_DOWN, hit);
stage.addEventListener(Event.ENTER_FRAME, death);
stage.addEventListener(KeyboardEvent.KEY_DOWN, retry);
//add a Coin here
Coin1 = new Coin(stage.stageWidth / 2,stage.stageHeight / 2,75,10);
stage.addChild(Coin1);
Coin2 = new Coin(stage.stageWidth / 2,stage.stageHeight / 2,125,-5);
stage.addChild(Coin2);
Coin3 = new CoinB(stage.stageWidth / 2,stage.stageHeight / 2,25,15);
stage.addChild(Coin3);
this.addEventListener(Event.ENTER_FRAME, fire);
}
public function show_time(event:TimerEvent)
{
interval_timer.text = event.target.currentCount;
}
public function on_enter_frame(event:Event)
{
var elapsed = getTimer();
public function fire(e:Event)
{
if (Player1.hitTestObject(Coin1))
{
score += 50;
Score.text = score.toString();
}
if (Player1.hitTestObject(Coin2))
{
score += 10;
Score.text = score.toString();
}
}
public function death(e:Event)
{
if (Player1.hitTestObject(Coin3))
{
stage.removeEventListener(KeyboardEvent.KEY_DOWN, hit);
score = 0;
Score.text = score.toString();
/* gameOver.visible = true;*/
Cont.visible = true;
this.removeChild(this.Player1);
this.Player1 = new Ship(259,365);
Coin1.visible = false;
Coin2.visible = false;
Player1.visible = false;
Coin3.visible = false;
removeChild(interval_timer);
}
}
public function hit(evt:KeyboardEvent):void
{
//this will move the player right if the "Right" arrow key is pressed.
if (evt.keyCode == Keyboard.RIGHT)
{
this.Player1.right();
this.Player1.rotation = 90;
}
//this will move the player left if the "Left" arrow key is pressed.
else if (evt.keyCode == Keyboard.LEFT)
{
this.Player1.left();
this.Player1.rotation = 270;
}
if (evt.keyCode == Keyboard.DOWN)
{
this.Player1.down();
this.Player1.rotation = 180;
}
//this will move the player up if the "Up" arrow key is pressed.
else if (evt.keyCode == Keyboard.UP)
{
this.Player1.up();
this.Player1.rotation = 0;
}
}
public function retry(evt:KeyboardEvent):void
{
//restarts game.
//adds event listener so that the player can move again
if (evt.keyCode == Keyboard.R)
Cont.visible = false;
stage.addEventListener(KeyboardEvent.KEY_DOWN, hit);
Coin1.visible = true;
Coin2.visible = true;
Player1.visible = true;
Coin3.visible = true
addChild(this.Player1);
addChild(interval_timer);
}
}
}
Any help is greatly appreciated. Thanks.
Generally speaking, you would use a Timer to trigger a function when 2 minutes is up.
Something like this:
var gameTimer:Timer = new Timer(120 * 1000); // 120 seconds * 1000 milliseconds
gameTimer.addEventListener(TimerEvent.TIMER, onGameTimerTick);
gameTimer.start();
function onGameTimerTick(e:TimerEvent):void {
//stop the timer
gameTimer.removeEventListener(TimerEvent.TIMER, onGameTimerTick);
gameTimer.stop();
restartMyGame();
}
I have a game. (Feel to download it here)
In my game, you may notice that the man doesn't move on its own. You have to click the screen once to get the man to move left and right with the arrow keys.
My Main.as:
package
{
import flash.display.MovieClip;
import flash.utils.Timer;
import flash.utils.getTimer;
import flash.events.TimerEvent;
import flash.display.Stage;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
import flash.display.DisplayObjectContainer;
import flash.text.TextField;
import flash.events.MouseEvent;
import flash.display.Graphics;
import flash.display.Sprite;
import flash.geom.ColorTransform;
import flash.text.TextFormat;
import flash.text.engine.TextBaseline;
public dynamic class Main extends MovieClip
{
// classes
private var _physics:Physics;
private var _timer:Timer;
var interval_timer:TextField = new TextField();
private var startTime:int;
private var diff:int;
private var _timer2:Timer
private var _stage:MovieClip = container;
private var _frame:int;
private var fade:Number = 1.0;
private var fadeAmount:Number = 0.01;
private var _timer3:Timer = new Timer(25);
private var retval:Boolean = false;
var survive:TextField = new TextField();
var survivedTime:Number;
var isRight:Boolean=false
var isLeft:Boolean=false
var isUp:Boolean=false
var isDown:Boolean=false
var pause:TextField = new TextField();
var pausedes:TextField = new TextField();
public function Main()
{
_physics = new Physics(container);
_physics.enable();
_timer = new Timer(500);
_timer.addEventListener(TimerEvent.TIMER, timerFunction);
_timer.start();
start.addEventListener(MouseEvent.CLICK, buttonClickHandler);
credits.addEventListener(MouseEvent.CLICK, buttonClickHandler2);
}
// the event listeners
private function update(e:Event):void
{
var currentTime:int = getTimer();
var _ballArray:Array = _physics._ballArray;
var tempBall1:Ball;
var i:int;
//check if we hit top
if (((man.x - man.width / 2) <= _physics._minX))
{
man.x += 7;
}
else if (((man.x + man.width / 2) >= _physics._maxX))
{
man.x -= 7;
}
for (i = 0; i < _ballArray.length; i++)
{
// save a reference to ball
tempBall1 = _ballArray[i] as Ball;
if(_physics.hitTestCircle(tempBall1, man))
{
man.gotoAndStop(2);
retval = true;
stage.removeEventListener(KeyboardEvent.KEY_UP, onKeyEvent);
stage.removeEventListener(KeyboardEvent.KEY_UP, upKey);
stage.removeEventListener(KeyboardEvent.KEY_DOWN, downKey);
stage.removeEventListener(Event.ENTER_FRAME, move);
}
if(retval)
{
_physics.disable();
_timer2.stop();
survivedTime = diff;
_timer3.addEventListener(TimerEvent.TIMER, darken);
_timer3.start();
stage.removeEventListener(Event.ENTER_FRAME, update);
_physics._ballArray = [];
//trace("you died!");
retval = false;
}
}
diff = currentTime*0.001 - startTime*0.001;
interval_timer.text = String(diff);
}
private function darken(e:TimerEvent):void
{
fade-= fadeAmount;
if(fade < 0.0)
{
fade = 0.0;
_timer3.removeEventListener(TimerEvent.TIMER, darken);
_timer3.stop();
endGame();
}
container.transform.colorTransform = new ColorTransform(fade, fade, fade, 1.0, 0, 0, 0, 0);
}
private function downKey(event:KeyboardEvent)
{
if(event.keyCode==39)
{
isRight=true;
}
if(event.keyCode==37)
{
isLeft=true;
}
if(event.keyCode==38)
{
isUp=true
}
if(event.keyCode==40)
{
isDown=true
}
}
private function upKey(event:KeyboardEvent){
if(event.keyCode==39){
isRight=false}
if(event.keyCode==37){
isLeft=false}
if(event.keyCode==38){
isUp=false}
if(event.keyCode==40){
isDown=false}
}
private function move(e:Event)
{
if(isRight==true)
{
man.x +=5;
}
if(isLeft==true)
{
man.x -= 5;
}
}
private function frame(e:Event):void
{
_frame = currentFrame;
if(_frame == 25)
{
startGame();
}
}
private function startGame():void
{
_physics._ballArray = [];
stage.removeEventListener(Event.ENTER_FRAME, frame);
//stage.removeEventListener(Event.ENTER_FRAME, startGame);
stage.removeEventListener(Event.ENTER_FRAME, _physics.remove);
_physics.enable();
// enable physics simulation
_timer2 = new Timer(500);
_timer2.addEventListener(TimerEvent.TIMER, timerFunction);
_timer2.start();
stage.addEventListener(Event.ENTER_FRAME, update);
interval_timer.y = 18;
interval_timer.x = 500;
addChild(interval_timer);
startTime = getTimer();
}
private function endGame()
{
var myFormat:TextFormat = new TextFormat();
myFormat.size = 23;
survive.defaultTextFormat = myFormat;
gotoAndStop(26);
survive.x = 179.45;
survive.y = 177.90;
survive.textColor = 0xFFFFFF;
survive.text = String(survivedTime + " secs");
addChild(survive);
stage.addEventListener(Event.ENTER_FRAME, _physics.remove);
stage.removeEventListener(KeyboardEvent.KEY_UP, onKeyEvent);
stage.removeEventListener(KeyboardEvent.KEY_UP, upKey);
stage.removeEventListener(KeyboardEvent.KEY_DOWN, downKey);
stage.removeEventListener(Event.ENTER_FRAME, move);
mainmenu.addEventListener(MouseEvent.CLICK, buttonClickHandler5);
retry.addEventListener(MouseEvent.CLICK, buttonClickHandler6);
_physics._ballArray = [];
}
private function onKeyEvent(e:KeyboardEvent):void
{
if (stage.frameRate == 20)
{
if (e.keyCode == 80)
{
stage.frameRate = 8;
stage.removeEventListener(Event.ENTER_FRAME, update);
pauseGame();
}
}
else if (stage.frameRate == 8)
{
if (e.keyCode == 80)
{
stage.frameRate = 20;
stage.addEventListener(Event.ENTER_FRAME, update);
unpause();
}
}
}
private function pauseGame():void
{
_physics.disable();
_timer2.stop();
stage.addEventListener(KeyboardEvent.KEY_UP, onKeyEvent);
stage.removeEventListener(KeyboardEvent.KEY_UP, upKey);
stage.removeEventListener(KeyboardEvent.KEY_DOWN, downKey);
stage.removeEventListener(Event.ENTER_FRAME, move);
var myFormat:TextFormat = new TextFormat();
var myFormat2:TextFormat = new TextFormat();
myFormat.size = 30;
myFormat2.size = 15;
pause.defaultTextFormat = myFormat;
pausedes.defaultTextFormat = myFormat2;
pause.x = 239.95;
pause.y = 165.90;
pause.textColor = 0x000000;
pausedes.x = 221.8;
pausedes.y = 205.45;
pausedes.width = 130.2;
pausedes.textColor = 0x000000;
pause.text = String("Paused");
pausedes.text = String("Press P to Unpause");
addChild(pause);
addChild(pausedes);
}
private function unpause():void
{
stage.addEventListener(KeyboardEvent.KEY_UP, onKeyEvent);
stage.addEventListener(KeyboardEvent.KEY_UP, upKey);
stage.addEventListener(KeyboardEvent.KEY_DOWN, downKey);
stage.addEventListener(Event.ENTER_FRAME, move);
_physics.enable();
_timer2.start();
removeChild(pause);
removeChild(pausedes);
}
public function timerFunction(e:TimerEvent):void
{
_physics.createBalls(1);
}
//start button
private function buttonClickHandler(event:MouseEvent):void
{
gotoAndStop(3);
ok.addEventListener(MouseEvent.CLICK, buttonClickHandler4);
_physics.disable();
_timer.stop();
_timer.removeEventListener(TimerEvent.TIMER, timerFunction);
stage.addEventListener(Event.ENTER_FRAME, _physics.remove);
_physics._ballArray = [];
}
//credits button
private function buttonClickHandler2(event:MouseEvent):void
{
gotoAndStop(2);
stage.addEventListener(Event.ENTER_FRAME, _physics.remove);
_physics.disable();
_timer.removeEventListener(TimerEvent.TIMER, timerFunction);
_timer.stop();
back.addEventListener(MouseEvent.CLICK, buttonClickHandler3);
_physics._ballArray = [];
}
//back button
private function buttonClickHandler3(event:MouseEvent):void
{
gotoAndStop(1);
_physics.enable();
_timer.addEventListener(TimerEvent.TIMER, timerFunction);
stage.removeEventListener(Event.ENTER_FRAME, _physics.remove);
_timer.start();
start.addEventListener(MouseEvent.CLICK, buttonClickHandler);
credits.addEventListener(MouseEvent.CLICK, buttonClickHandler2);
_physics._ballArray = [];
}
//ok button
private function buttonClickHandler4(event:MouseEvent):void
{
stage.addEventListener(KeyboardEvent.KEY_UP, upKey);
stage.addEventListener(KeyboardEvent.KEY_DOWN, downKey);
stage.addEventListener(Event.ENTER_FRAME, move);
stage.addEventListener(KeyboardEvent.KEY_UP, onKeyEvent);
gotoAndPlay(4);
stage.addEventListener(Event.ENTER_FRAME, frame);
_physics._ballArray = [];
//stage.addEventListener(Event.ENTER_FRAME, startGame);
}
//main menu button
private function buttonClickHandler5(event:MouseEvent):void
{
gotoAndStop(1);
container.transform.colorTransform = new ColorTransform(1, 1, 1, 1, 0, 0, 0);
removeChild(survive);
removeChild(interval_timer);
_physics.enable();
_timer.addEventListener(TimerEvent.TIMER, timerFunction);
stage.removeEventListener(Event.ENTER_FRAME, _physics.remove);
_timer.start();
start.addEventListener(MouseEvent.CLICK, buttonClickHandler);
credits.addEventListener(MouseEvent.CLICK, buttonClickHandler2);
_physics._ballArray = [];
fade = 1.0;
fadeAmount = 0.01;
}
//retry button
private function buttonClickHandler6(event:MouseEvent):void
{
container.transform.colorTransform = new ColorTransform(1, 1, 1, 1, 0, 0, 0);
removeChild(survive);
removeChild(interval_timer);
gotoAndPlay(4);
stage.addEventListener(Event.ENTER_FRAME, frame);
stage.addEventListener(KeyboardEvent.KEY_UP, upKey);
stage.addEventListener(KeyboardEvent.KEY_DOWN, downKey);
stage.addEventListener(Event.ENTER_FRAME, move);
stage.addEventListener(KeyboardEvent.KEY_UP, onKeyEvent);
_physics._ballArray = [];
fade = 1.0;
fadeAmount = 0.01;
man.x = 286.65;
man.y = 391.85;
man.gotoAndStop(1);
}
}
}
This is the file I use to make the man move. Where is the code do I change to make the game work so the man moves the after "Go!", and you don't have to click the screen.
Another question I have is: When you press "P", you can pause the game. However, you may notice after unpausing the game by pressing "P" again, the timer is off by the number of seconds you were paused. This code also is the code for the timer. What do I change in the code to make the timer run correctly, meaning that after unpausing the game, it doesn't skip the number of the seconds you were paused, instead it continues from where it left off.
This is getting too long a comment thread for this question. After you call buttonClickHandler4, your keyboard events should be functioning.
Set debug points, or trace statements, to see if buttonClickHandler4 is being called. Add the same to make sure downKey and move are being called. This should narrow down the problem.
EDIT: I figured out the problem using this link: http://www.trainingtutorials101.com/2010/10/keyboard-events-wont-work-unless-user.html
I had to use the command stage.focus = this to focus the stage on my movieclip man, so that way it could listen for keyboard events without my mouse clicking the screen.
And to remove the yellow rectangle around the man I used the command stage.stageFocusRect = false.
Thanks to #dhc and #Vesper for all of their help.
in order to increase performance of a scrollRect i must cache the vector as a bitmap, otherwise the scrollRect will be simply a less performant mask (info source).
however, i can't seem to move an object/scrollRect once i've applied cacheAsBitmap. why?
package
{
//Imports
import flash.display.Screen;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Rectangle;
//Class
[SWF(width = "800", height = "500", backgroundColor = "0x444444")]
public class ScrollRectTest extends Sprite
{
//Variables
private var background:Sprite;
private var ball:Sprite;
private var newScrollRect:Rectangle;
//Constructor
public function ScrollRectTest()
{
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
stage.frameRate = 60;
init();
}
//Initialize
private function init():void
{
background = new Sprite();
background.graphics.beginFill(0x000000, 1.0);
background.graphics.drawRect(0, 0, 200, 400);
background.graphics.endFill();
ball = new Sprite();
ball.graphics.beginFill(0xFF0000, 1.0);
ball.graphics.drawCircle(0, 0, 100);
ball.graphics.endFill();
//ball.cacheAsBitmap = true; //<-- uncomment this
ball.scrollRect = new Rectangle(background.x, background.y, background.width, background.height);
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownEventHandler);
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpEventHandler);
addChild(background);
addChild(ball);
}
//Mouse Down Event Handler
private function mouseDownEventHandler(evt:MouseEvent):void
{
addEventListener(Event.ENTER_FRAME, enterFrameEventHandler);
}
//Mouse Up Event Handler
private function mouseUpEventHandler(evt:MouseEvent):void
{
removeEventListener(Event.ENTER_FRAME, enterFrameEventHandler);
}
//Enter Frame Event Handler
private function enterFrameEventHandler(evt:Event):void
{
newScrollRect = ball.scrollRect;
newScrollRect.y -= 10;
newScrollRect.x -= 5;
ball.scrollRect = newScrollRect;
}
}
}
Even more funny:
package
{
import flash.display.Graphics;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Rectangle;
[SWF(width = "800", height = "500", backgroundColor = "0x444444")]
public class ScrollRectTest extends Sprite
{
//Variables
private var background:Sprite;
private var ball:Sprite;
private var newScrollRect:Rectangle;
//Constructor
public function ScrollRectTest()
{
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
stage.frameRate = 60;
init();
}
//Initialize
private function init():void
{
background = new Sprite();
background.graphics.beginFill(0x000000, 1.0);
background.graphics.drawRect(0, 0, 200, 400);
background.graphics.endFill();
ball = new Sprite();
ball.graphics.beginFill(0xFFFF00, 1.0);
ball.graphics.drawCircle(0, 0, 100);
ball.graphics.endFill();
var foo:Sprite = new Sprite();
var g:Graphics = foo.graphics;
g.beginFill(0xFF0000, 0.2);
g.drawRect(0, 0, 100, 100);
g.endFill();
ball.addChild(foo);
ball.cacheAsBitmap = true; //<-- uncomment this
ball.scrollRect = new Rectangle(background.x, background.y, background.width, background.height);
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownEventHandler);
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpEventHandler);
addChild(background);
addChild(ball);
}
//Mouse Down Event Handler
private function mouseDownEventHandler(evt:MouseEvent):void
{
addEventListener(Event.ENTER_FRAME, enterFrameEventHandler);
}
//Mouse Up Event Handler
private function mouseUpEventHandler(evt:MouseEvent):void
{
removeEventListener(Event.ENTER_FRAME, enterFrameEventHandler);
}
//Enter Frame Event Handler
private function enterFrameEventHandler(evt:Event):void
{
newScrollRect = ball.scrollRect;
newScrollRect.y -= 1;
newScrollRect.x -= 1;
ball.scrollRect = newScrollRect;
// ball.scaleX = 1 + Math.random() * 0.01;// uncomment this to force redraw
}
}
}
So I assume it's some kind of bug.