I have 2 issues in this code.
The first is:
5006: An ActionScript file can not have more than one externally visible definition: Sprayer, bugs
I've put multiple Actionscripts together to create this, i've seperated out the classes and am hoping to play this on a frame from a symbol.
and the second relates to:
Error #1006: hitTestObject is not a function
For this i'm trying to get the aagun/Sprayer to lose health then lives if the bugs touch it, but i'm not sure why it's saying it's not a function. Am I using the wrong words?
Thanks for your help, here's the code
package Shooter{
import flash.display.*;
import flash.events.*;
import flash.utils.getTimer;
class Sprayer extends MovieClip{
const speed:Number = 150.0;
var lastTime:int; // animation time
function Sprayer() {
// initial location of gun
this.x = 275;
this.y = 340;
// movement
addEventListener(Event.ENTER_FRAME,moveGun);
}
function moveGun(event:Event) {
// get time difference
var timePassed:int = getTimer()-lastTime;
lastTime += timePassed;
// current position
var newx = this.x;
// move to the left
if (MovieClip(parent).leftArrow) {
newx -= speed*timePassed/1000;
}
// move to the right
if (MovieClip(parent).rightArrow) {
newx += speed*timePassed/1000;
}
// check boundaries
if (newx < 10) newx = 10;
if (newx > 540) newx = 540;
// reposition
this.x = newx;
}
// remove from screen and remove events
function deleteGun() {
parent.removeChild(this);
removeEventListener(Event.ENTER_FRAME,moveGun);
}
}
}
package BigBug{
import flash.display.*;
import flash.events.*;
import flash.utils.Timer;
import flash.text.TextField;
import flash.display.MovieClip;
class bugs extends MovieClip {
var dx:Number; // speed and direction
var lastTime:int; // animation time
function bugs(side:String, speed:Number, altitude:Number) {
if (side == "left") {
this.x = -50; // start to the left
dx = speed; // fly left to right
this.scaleX = 1; // reverse
} else if (side == "right") {
this.x = -50; // start to the right
dx = -speed; // fly right to left
this.scaleX = 1; // not reverse
}
this.y = altitude; // vertical position
// choose a random plane
this.gotoAndStop(Math.floor(Math.random()*4+1));
// set up animation
addEventListener(Event.ENTER_FRAME,movePlane);
lastTime = getTimer();
}
function movePlane(event:Event) {
// get time passed
var timePassed:int = getTimer()-lastTime;
lastTime += timePassed;
// move plane
this.x += dx*timePassed/2000;
// check to see if off screen
if ((dx < 0) && (x < -50)) {
deletePlane();
} else if ((dx > 0) && (x > 350)) {
deletePlane();
}
}
}
}
package Missiles{
import flash.display.*;
import flash.events.*;
import flash.utils.Timer;
import flash.text.TextField;
import flash.display.MovieClip;
class Bullets extends MovieClip {
var dx:Number; // vertical speed
var lastTime:int;
function Bullets(x,y:Number, speed: Number) {
// set start position
this.x = x;
this.y = y;
// get speed
dx = speed;
// set up animation
lastTime = getTimer();
addEventListener(Event.ENTER_FRAME,moveBullet);
}
function moveBullet(event:Event) {
// get time passed
var timePassed:int = getTimer()-lastTime;
lastTime += timePassed;
// move bullet
this.x += dx*timePassed/1000;
// bullet past top of screen
if (this.x < 0) {
deleteBullet();
}
}
// delete bullet from stage and plane list
function deleteBullet() {
MovieClip(parent).removeBullet(this);
parent.removeChild(this);
removeEventListener(Event.ENTER_FRAME,moveBullet);
}
}
}
package MainGame{
import flash.display.*;
import flash.events.*;
import flash.utils.Timer;
import flash.text.TextField;
import flash.display.MovieClip;
import Missiles.Bullets;
import Shooter.Sprayer;
import BigBug.bugs;
public class AirRaid extends MovieClip {
private var aagun:Sprayer;
private var airplanes:Array;
private var buggood:Array;
private var bullets:Array;
public var leftArrow, rightArrow:Boolean;
private var nextGbug:Timer;
private var nextPlane:Timer;
private var shotsLeft:int;
private var shotsHit:int;
public function startAirRaid() {
// init score
shotsLeft = 20;
shotsHit = 0;
showGameScore();
// create gun
aagun = new Sprayer();
addChild(aagun);
// create object arrays
buggood = new Array();
airplanes = new Array();
bullets = new Array();
// listen for keyboard
stage.addEventListener(KeyboardEvent.KEY_DOWN,keyDownFunction);
stage.addEventListener(KeyboardEvent.KEY_UP,keyUpFunction);
// look for collisions
addEventListener(Event.ENTER_FRAME,checkForHits);
// start planes flying
setNextPlane();
setNextGbug();
}
public function setNextPlane() {
nextPlane = new Timer(1000+Math.random()*1000,1);
nextPlane.addEventListener(TimerEvent.TIMER_COMPLETE,newPlane);
nextPlane.start();
}
public function newPlane(event:TimerEvent) {
// random side, speed and altitude
if (Math.random() > .5) {
var side:String = "left";
} else {
side = "right";
}
var altitude:Number = Math.random()*50+20;
var speed:Number = Math.random()*150+150;
// create plane
var p:bugs = new bugs(side,speed,altitude);
addChild(p);
airplanes.push(p);
// set time for next plane
setNextPlane();
}
public function setNextGbug() {
nextGbug = new Timer(1000+Math.random()*1000,1);
nextGbug.addEventListener(TimerEvent.TIMER_COMPLETE,newGbug);
nextGbug.start();
}
public function newGbug(event:TimerEvent) {
// random side, speed and altitude
if (Math.random() > .5) {
var side:String = "left";
} else {
side = "right";
}
var altitude:Number = Math.random()*50+20;
var speed:Number = Math.random()*150+150;
// create Gbug
var p:Good_bug = new Good_bug(side,speed,altitude);
addChild(p);
buggood.push(p);
// set time for next Gbug
setNextGbug();
}
// check for collisions
public function checkForHits(event:Event) {
for(var bulletNum:int=bullets.length-1;bulletNum>=0;bulletNum--){
for (var airplaneNum:int=airplanes.length-1;airplaneNum>=0;airplaneNum--) {
if (bullets[bulletNum].hitTestObject(airplanes[airplaneNum])) {
airplanes[airplaneNum].planeHit();
bullets[bulletNum].deleteBullet();
shotsHit++;
showGameScore();
break;
}
}
for(var bulletNum:int=bullets.length-1;bulletNum>=0;bulletNum--){
for (var Good_bugNum:int=buggood.length-1;Good_bugNum>=0;Good_bugNum--) {
if (bullets[bulletNum].hitTestObject(buggood[Good_bugNum])) {
buggood[Good_bugNum].GbugHit();
bullets[bulletNum].deleteBullet();
shotsHit--;
showGameScore();
break;
}
}
}
if ((shotsLeft == 0) && (bullets.length == 0)) {
endGame();
}
}
if ((shotsLeft == 0) && (bullets.length == 0)) {
endGame();
}
}
// key pressed
public function keyDownFunction(event:KeyboardEvent) {
if (event.keyCode == 37) {
leftArrow = true;
} else if (event.keyCode == 39) {
rightArrow = true;
} else if (event.keyCode == 32) {
fireBullet();
}
}
// key lifted
public function keyUpFunction(event:KeyboardEvent) {
if (event.keyCode == 37) {
leftArrow = false;
} else if (event.keyCode == 39) {
rightArrow = false;
}
}
// new bullet created
public function fireBullet() {
if (shotsLeft <= 0) return;
var b:Bullets = new Bullets(aagun.x,aagun.y,-300);
addChild(b);
bullets.push(b);
shotsLeft--;
showGameScore();
}
public function showGameScore() {
showScore.text = String("Score: "+shotsHit);
showShots.text = String("Shots Left: "+shotsLeft);
}
// take a plane from the array
public function removePlane(plane:bugs) {
for(var i in airplanes) {
if (airplanes[i] == plane) {
airplanes.splice(i,1);
break;
}
}
}
// take a Gbug from the array
public function removeGbug(Gbug:Good_bug) {
for(var i in buggood) {
if (buggood[i] == Gbug) {
buggood.splice(i,1);
break;
}
}
}
// take a bullet from the array
public function removeBullet(bullet:Bullets) {
for(var i in bullets) {
if (bullets[i] == bullet) {
bullets.splice(i,1);
break;
}
}
}
// game is over, clear movie clips
public function endGame() {
// remove planes
for(var i:int=airplanes.length-1;i>=0;i--) {
airplanes[i].deletePlane();
}
for(var i:int=buggood.length-1;i>=0;i--) {
buggood[i].deleteGbug();
}
airplanes = null;
buggood = null;
aagun.deleteGun();
aagun = null;
stage.removeEventListener(KeyboardEvent.KEY_DOWN,keyDownFunction);
stage.removeEventListener(KeyboardEvent.KEY_UP,keyUpFunction);
removeEventListener(Event.ENTER_FRAME,checkForHits);
nextPlane.stop();
nextPlane = null;
nextGbug.stop();
nextGbug = null;
gotoAndStop("gameover");
}
}
}
1.
5006: An ActionScript file can not have more than one externally visible definition: Sprayer, bugs
As it says exactly: you can't have more than one public definition in a file. You have to either split the code to several files or move definitions, that you don't need public, out of the package.
This would be Ok in one file:
package
{
import flash.display.MovieClip;
// public is the default access modifier
public class Test1 extends MovieClip
{
public function Test1()
{
trace("test1");
var t2:Test2 = new Test2();
var t3:Test3 = new Test3();
}
}
}
// Test2 and Test3 are defined outside of the package, otherwise it wouldn't compile.
// These definitions will only be visible to code in this file.
import flash.display.MovieClip;
class Test2 extends MovieClip
{
public function Test2()
{
trace("test2");
}
}
class Test3 extends MovieClip
{
public function Test3()
{
trace("test3");
}
}
2.
Error #1006: hitTestObject is not a function
This usually means that hitTestObject() is not defined on the object (or it's ancestors) you are trying to call it from (although there could be different kinds of errors for that).
hitTestObject() is accessed in two ways in your code: airplanes.hitTestObject() and bullets[bulletNum].hitTestObject(). You will have to debug your code to see what is actually airplanes and bullets[bulletNum], what types they are and whether they inherit hitTestObject() method. You could at least trace() them.
So I'm currently attempting to make a prototype for a Bullet Hell game and I've run into a bit of a dead end.
So far I can move my player perfectly, the boss moves back and forth as he is supposed to, however the projectiles have some funny behaviour. Basically, when the boss moves left/right, so do the projectiles as if they are stuck to him. They move on the y as they are supposed to, except they stop just short of the player and move no further, so I'm hoping anyone can take a look at my code and give me a hand with what's going on.
Note: Ignore the rotation stuff, that's for later implementation, I was just laying the ground work.
Projectile.as
package
{
import flash.display.Stage;
import flash.display.MovieClip;
import flash.events.Event;
public class Projectile extends MovieClip
{
private var stageRef:Stage;
private var _xVel:Number = 0;
private var _yVel:Number = 0;
private var rotationInRadians = 0;
private const SPEED:Number = 10;
public function Projectile(stageRef:Stage, x:Number, y:Number, rotationInDegrees:Number)
{
this.stageRef = stageRef;
this.x = x;
this.y = y;
this.rotation = rotationInDegrees;
this.rotationInRadians = rotationInDegrees * Math.PI / 180;
}
public function update():void
{
this.y += SPEED;;
if(x > stageRef.stageWidth || x < 0 || y > stageRef.stageHeight || y < 0)
{
//this.removeChild(this); <- Causing a crash, will fix later
}
}
}
}
Boss.as
package
{
import flash.display.MovieClip;
import flash.display.Stage;
import flash.events.Event;
import flash.utils.Timer;
import flash.events.TimerEvent;
public class Boss extends MovieClip
{
private var stageRef:Stage;
private var _vx:Number = 3;
private var _vy:Number = 3;
private var fireTimer:Timer;
private var canFire:Boolean = true;
private var projectile:Projectile;
public var projectileList:Array = [];
public function Boss(stageRef:Stage, X:int, Y:int)
{
this.stageRef = stageRef;
this.x = X;
this.y = Y;
fireTimer = new Timer(300, 1);
fireTimer.addEventListener(TimerEvent.TIMER, fireTimerHandler, false, 0, true);
}
public function update():void
{
this.x += _vx;
if(this.x <= 100 || this.x >= 700)
{
_vx *= -1;
}
fireProjectile();
projectile.update();
}
public function fireProjectile():void
{
if(canFire)
{
projectile = new Projectile(stageRef, this.x / 200 + this._vx, this.y, 90);
addChild(projectile);
canFire = false;
fireTimer.start();
}
}
private function fireTimerHandler(event:TimerEvent) : void
{
canFire = true;
}
}
}
Edit: Current suggestions have been to do the following:
stage.addChild(projectile); and this.parent.addChild(projectile); both which have the projectile firing from the top left corner (0, 0) and not constantly firing from the current center of the Boss.
The other issue, which has been untouched, is the fast that the projectile stops moving after a certain point and remains on the screen.
Another Edit:
After commenting out the code with the timer I have found that the projectile stops moving entirely. The reason why it was stopping after a certain amount of time was due to the timer, when the timer elapsed the projectile stopped and another would fire.
So now I need the projectile to constantly fire and move until it hits the edge of the screen, any ideas?
The problem is you are 'addChild'ing your projectiles to your Boss as opposed the stage (or the same display level as your Boss). When your Boss moves, your projectiles will move relative to him (ie, when he moves sideways, so will they).
When your boss fires a projectile, use a custom event to trigger a fireProjectile method in the Class that is your Boss' display parent. Instantiate your projectiles there and addChild them to the same object to which you addChild your Boss (possibly the stage?).
Alternatively, if you don't want to use a custom event, in your current fireProjectile method change the addChild line to:
this.parent.addChild(projectile);
This will add projectiles to the parent object of your Boss. Although that line seems, slightly, like cheating to me.
Building a top down shooter, and after fixing some bugs an making everything work i am left with only one more.
error 1118: Implicit coercion of a value with static type flash.display:DisplayObject to a possibly unrelated type flash.display:MovieClip.
This is the Level.as where all the object are loaded
package {
import flash.display.Sprite;
import flash.display.MovieClip;
import flash.display.Stage;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
import flash.events.MouseEvent;
import flash.events.TimerEvent;
import flash.filters.BlurFilter;
import flash.utils.Timer;
import flash.text.TextField;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.media.SoundMixer;
import flash.utils.*;
import flash.display.Shape;
import flash.display.DisplayObject
/**
*
*/
public class Level extends Sprite
{
//these booleans will check which keys are down
public var leftIsPressed:Boolean = false;
public var rightIsPressed:Boolean = false;
public var upIsPressed:Boolean = false;
public var downIsPressed:Boolean = false;
//how fast the character will be able to go
public var speed:Number = 5;
public var vx:Number = 0;
public var vy:Number = 0;
//how much time before allowed to shoot again
public var cTime:int = 0;
//the time it has to reach in order to be allowed to shoot (in frames)
public var cLimit:int = 12;
//whether or not the user is allowed to shoot
public var shootAllow:Boolean = true;
//how much time before another enemy is made
public var enemyTime:int = 0;
//how much time needed to make an enemy
//it should be more than the shooting rate
//or else killing all of the enemies would
//be impossible :O
public var enemyLimit:int = 16;
//the spaceAuto's score
public var score:int = 0;
//this movieclip will hold all of the bullets
public var bulletContainer:MovieClip = new MovieClip();
//whether or not the game is over
public var gameOver:Boolean = false;
public var SpaceAuto:spaceAuto = new spaceAuto;
// publiek toegangkelijke verwijzing naar deze class
public static var instance:Level;
public var particleContainer:MovieClip = new MovieClip();
// constructor code
public function Level()
{
instance = this;
SpaceAuto.x = 135;
SpaceAuto.y = 350;
addChild(this.SpaceAuto);
addChild(this.bulletContainer);
Project.instance.stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
Project.instance.stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
Project.instance.stage.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
Project.instance.stage.addEventListener(Event.ENTER_FRAME, generateParticles);
//checking if there already is another particlecontainer there
if(!contains(particleContainer))
{
//this movieclip will hold all of the particles
addChild(this.particleContainer);
}
}
function keyDownHandler(e:KeyboardEvent):void {
switch(e.keyCode) {
case Keyboard.LEFT : leftIsPressed = true; break;
case Keyboard.RIGHT : rightIsPressed = true; break;
case Keyboard.UP : upIsPressed = true; break;
case Keyboard.DOWN : downIsPressed = true; break;
}
if(e.keyCode == 32 && shootAllow)
{
//making it so the user can't shoot for a bit
shootAllow = false;
//declaring a variable to be a new Bullet
var newBullet:Bullet = new Bullet();
//changing the bullet's coordinates
newBullet.x = SpaceAuto.x + SpaceAuto.width/2 - newBullet.width/2;
newBullet.y = SpaceAuto.y;
//then we add the bullet to stage
bulletContainer.addChild(newBullet);
}
}
function keyUpHandler(e:KeyboardEvent):void {
switch(e.keyCode) {
case Keyboard.LEFT : leftIsPressed = false; break;
case Keyboard.RIGHT : rightIsPressed = false; break;
case Keyboard.UP : upIsPressed = false; break;
case Keyboard.DOWN : downIsPressed = false; break;
}
}
function enterFrameHandler(e:Event):void {
vx = -int(leftIsPressed)*speed + int(rightIsPressed)*speed;
vy = -int(upIsPressed)*speed + int(downIsPressed)*speed;
SpaceAuto.x += vx;
SpaceAuto.y += vy;
if(cTime < cLimit)
{
cTime ++;
trace("++")
}
else
{
//if it has, then allow the user to shoot
shootAllow = true;
//and reset cTime
cTime = 0;
}
//adding enemies to stage
if(enemyTime < enemyLimit)
{
//if time hasn't reached the limit, then just increment
enemyTime ++;
}
else
{
//defining a variable which will hold the new enemy
var newEnemy = new Enemy();
//making the enemy offstage when it is created
newEnemy.y = -1 * newEnemy.height;
//making the enemy's x coordinates random
//the "int" function will act the same as Math.floor but a bit faster
newEnemy.x = int(Math.random()*(stage.stageWidth - newEnemy.width));
//then add the enemy to stage
addChild(newEnemy);
//and reset the enemyTime
enemyTime = 0;
}
//updating the score text
txtScore.text = 'Score: '+score;
if (gameOver == true)
{
loadScreenThree();
}
}
function generateParticles(event:Event):void
{
//so we don't do it every frame, we'll do it randomly
if(Math.random()*10 < 2){
//creating a new shape
var mcParticle:Shape = new Shape();
//making random dimensions (only ranges from 1-5 px)
var dimensions:int = int(Math.random()*5)+1;
//add color to the shape
mcParticle.graphics.beginFill(0x999999/*The color for shape*/,1/*The alpha for the shape*/);
//turning the shape into a square
mcParticle.graphics.drawRect(dimensions,dimensions,dimensions,dimensions);
//change the coordinates of the particle
mcParticle.x = int(Math.random()*stage.stageWidth);
mcParticle.y = -10;
//adding the particle to stage
particleContainer.addChild(mcParticle);
}
//making all of the particles move down stage
for(var i:int=particleContainer.numChildren - 1; i>=0; i--){
//getting a certain particle
var theParticle:DisplayObject = particleContainer.getChildAt(i);
//it'll go half the speed of the character
theParticle.y += speed*.5;
//checking if the particle is offstage
if(theParticle.y >= 400){
//remove it
particleContainer.removeChild(theParticle);
}
}
}
/**
* eventhandler voor als je op de tweede knop klikt
*/
private function loadScreenThree():void
{
// eerst opruimen!
cleanListeners();
// dan naar ander scherm
Project.instance.switchScreen( "derde" );
}
private function cleanListeners():void
{
stage.removeEventListener(Event.ENTER_FRAME, generateParticles);
stage.removeEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
stage.removeEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
stage.removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
}
}}
Where it goes wrong is in the Enemy Class in the eFrame Function. Here a loop runs trough the array bulletContainer from Level.as. A new variable is made and it should consist of the bullet that is in the loop out of the bulletContainer, and here comes the error in place
package{
//we have to import certain display objects and events
import Level;
import flash.display.MovieClip;
import flash.events.*;
import flash.display.Sprite;
//this just means that Enemy will act like a MovieClip
public class Enemy extends MovieClip
{
//VARIABLES
//this will act as the root of the document
//so we can easily reference it within the class
private var _root:Object;
//how quickly the enemy will move
private var speed:int = 5;
//this function will run every time the Bullet is added
//to the stage
public function Enemy()
{
//adding events to this class
//functions that will run only when the MC is added
addEventListener(Event.ADDED, beginClass);
//functions that will run on enter frame
addEventListener(Event.ENTER_FRAME, eFrame);
}
private function beginClass(event:Event):void
{
_root = Sprite(root);
}
private function eFrame(event:Event):void
{
//moving the bullet up screen
y += speed;
//making the bullet be removed if it goes off stage
if(this.y > 400)
{
removeEventListener(Event.ENTER_FRAME, eFrame);
this.parent.removeChild(this);
}
//checking if it is touching any bullets
//we will have to run a for loop because there will be multiple bullets
for(var i:int = 0;i<Level.instance.bulletContainer.numChildren;i++)
{
//numChildren is just the amount of movieclips within
//the bulletContainer.
trace("LOOOOOOOOOP");
trace(Level.instance.bulletContainer.getChildAt(i));
//we define a variable that will be the bullet that we are currently
//hit testing.
var bulletTarget:Sprite = Level.instance.bulletContainer.getChildAt(i);
//now we hit test
if(hitTestObject(bulletTarget))
{
//remove this from the stage if it touches a bullet
removeEventListener(Event.ENTER_FRAME, eFrame);
this.parent.removeChild(this);
//also remove the bullet and its listeners
Level.instance.bulletContainer.removeChild(bulletTarget);
//bulletTarget.removeListeners();
//up the score
Level.instance.score += 5;
}
}
//hit testing with the user
if(hitTestObject(Level.instance.SpaceAuto))
{
//losing the game
trace("DOOOOOD");
removeListeners();
this.parent.removeChild(this);
this.removeEventListener(Event.ENTER_FRAME, eFrame);
Level.instance.gameOver = true;
}
}
public function removeListeners():void
{
this.removeEventListener(Event.ENTER_FRAME, eFrame);
}
}}
i have tried make it Sprite or anything else but i just dont know how to fix this so it wil take the bullet so i van see if it hits the Enemy
var bulletTarget:Sprite = Level.instance.bulletContainer.getChildAt(i);
getChildAt will return a DisplayObject type, and hitTestObject requires a parameter with DisplayObject type.
So try this in your Enemy's eFrame function.
var bulletTarget:DisplayObject = Level.instance.bulletContainer.getChildAt(i);
Still programming an iPad game in Actionscript 3, I am encountering a problem that keeps me from advancing any further. I use blitting for animation, and as such, all my object use blitting for rendering. All objects are children of a game class which has a bitmapData canvas on which are rendered the game elements.
That's for how it should work. So far, there are no compilation or runtime errors, but for some reason I can't get any user input event from any object apart from the game itself. I have checked the event flow as well as the layering of the objects, but so far all I could find out is that for some reason the main canvas is the only element that can be targeted for events. Because players need to be able to touch them, two game elements are concerned: Twinkys and Racquets.
I have tried changing the layering of the elements, in order of instanciation and rendering, hiding some, changing event types (using mouse event instead of touch events) and toggling the mouseEnabled property of the game class with no positive result. All I can be sure of is that the game class is intercepting all events targeted at its children, making it impossible to play. I hope someone can see what I've done wrong.
Game class:
package Game
{
import Game.*;
import Game.Worlds.Level1.Level1;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.display3D.IndexBuffer3D;
import flash.events.Event;
import flash.events.TouchEvent;
import flash.ui.Multitouch;
import flash.ui.MultitouchInputMode;
public class Game extends Sprite
{
/** Hold each racquet so as to retrieve them when collision detection is needed. **/
internal var racquetList:Vector.<Racquet>= new Vector.<Racquet>(2,true);
/** Hold each Zwig so as to retrieve them when collision detection is needed. **/
internal var zwigColliderList:Vector.<Collider>= new Vector.<Collider>(2,true);
/** Object that contains the coordinates for the Twinkys in the counter. **/
internal var twinkyScore0:Object= {firstX:727,firstY:950,secondX:710,secondY:911,
thirdX:690,thirdY:872,fourthX:674,fourthY:840,
fifthX:657,fifthY:808};
internal var twinkyScore1:Object= {firstX:41,firstY:74,secondX:58,secondY:113,
thirdX:78,thirdY:152,fourthX:94,fourthY:184,
fifthX:111,fifthY:216};
/** Speed decay coefficient. The closer to 1 the less speed decays. **/
private var friction:Number= .96;
/** Maximum speed cap for twinkys. The higher the number the grater the maximal speed. **/
private var speedMax:Number= 10;
/** Important positions for the placement of game elements.
* LianaHeight is the height at which the liana on the players' HUDs is ending their zone and on which the racquet travels.
* TwinkyHeight is the height at which the players stop controlling their Twinkys.
* YMargin is the vertical margin for the Twinkys. Used to place them at the end of the tube when added.
* XMargin is the horizontal margin for the Twinkys. Used to place them at the end of the tube when added. **/
private var positions:Object= {LianaHeight:165,TwinkyHeight:265,YMargin:8.0,XMargin:200.0};
private var _mRef:ZwigsIpad;
Multitouch.inputMode= MultitouchInputMode.TOUCH_POINT;
private var _Canvas:BitmapData= new BitmapData(ZwigsIpad.BORDERS.right,ZwigsIpad.BORDERS.bottom,false);
private var _Background:Background;
private var _HUD1:HUD;
private var _HUD2:HUD;
private var _Score:Score;
private var _Zwig1:Zwig;
private var _Zwig2:Zwig;
private var _Racquet1:Racquet;
private var _Racquet2:Racquet;
private var _Twinky1:Twinky;
private var _Twinky2:Twinky;
/** Create the first level. It will create the stage and add the background, HUDs, Zwigs, Racquets and Twinkys, and manages the game until the end. **/
public function Game(m:ZwigsIpad)
{
this._mRef= m;
this.addEventListener(Event.ADDED_TO_STAGE,init);
}
private function init(e:Event):void
{
this.removeEventListener(Event.ADDED_TO_STAGE,init);
// Add game canvas on which all assets are rendered
addChild(new Bitmap(this._Canvas));
// Get informations from Level1
// LATER make it dependant from what level was chosen (switch case)
this.positions.LianaHeight= Level1.LIANA_HEIGHT;
this.positions.TwinkyHeight= Level1.TWINKY_HEIGHT;
this.positions.YMargin= Level1.TWINKY_MARGIN_Y;
this.positions.XMargin= Level1.TWINKY_MARGIN_X;
this.friction= Level1.TWINKY_FRICTION;
this.speedMax= Level1.TWINKY_SPEED_MAX;
// Add background
this._Background= new Background(this._Canvas,0);
addChild(this._Background);
// Add HUD
this._HUD1= new HUD(this._Canvas);
this._HUD2= new HUD(this._Canvas,true,1);
addChild(this._HUD1);
addChild(this._HUD2);
// Add scoring
this._Score= new Score(this,this._mRef);
addChild(this._Score);
// Add zwigs
this._Zwig1= new Zwig(this._Canvas);
this._Zwig2= new Zwig(this._Canvas,true,1);
addChild(this._Zwig1);
addChild(this._Zwig2);
// Add zwigs' colliders to vector
this.zwigColliderList[0]= this._Zwig1.collider;
this.zwigColliderList[1]= this._Zwig2.collider;
// Add racquets
this._Racquet1= new Racquet(this.positions,this._Canvas);
this._Racquet2= new Racquet(this.positions,this._Canvas,false,1);
addChild(this._Racquet1);
addChild(this._Racquet2);
// Add racquets to vector
this.racquetList[0]= this._Racquet1;
this.racquetList[1]= this._Racquet2;
// Add twinkys
this._Twinky1= new Twinky(this,this._Score,this,this.positions,this.friction,this.speedMax,this._Canvas,0);
this._Twinky2= new Twinky(this,this._Score,this,this.positions,this.friction,this.speedMax,this._Canvas,1,false,1);
addChild(this._Twinky1);
addChild(this._Twinky2);
this.addEventListener(Event.ENTER_FRAME,renderLevel);
}
private function renderLevel(e:Event):void
{
this._Canvas.lock();
this._Background.render();
this._HUD1.render();
this._HUD2.render();
this._Score.render();
this._Zwig1.render();
this._Zwig2.render();
this._Racquet1.render();
this._Racquet2.render();
this._Twinky1.render();
this._Twinky2.render();
this._Canvas.unlock();
}
}
}
Twinky class:
package Game
{
import Game.Game;
import Game.Score;
import com.greensock.TweenMax;
import com.greensock.easing.*;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.TouchEvent;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.ui.Multitouch;
import flash.ui.MultitouchInputMode;
/** The Twinky is the main player controlled class. **/
internal class Twinky extends Sprite
{
private var _mRef:Game;
private var _sRef:Score;
private var player:uint;
Multitouch.inputMode= MultitouchInputMode.TOUCH_POINT;
private var _touchMoveID:int= 0;
private var _speedX:Number= 0;
private var _speedY:Number= 0;
private var xOffset:Number;
private var yOffset:Number;
private var currentX:Number;
private var currentY:Number;
private var oldX:Number;
private var oldY:Number;
private var dragging:Boolean= false;
private var launched:Boolean= false;
private var _point:Point= new Point();
private var positions:Object;
private var friction:Number;
private var speedMax:Number;
private var canvas:BitmapData;
private var isAtBottom:Boolean;
private var skin:uint;
private var _image:BitmapData;
private var _idleArray:Array= new Array();
private var i:uint= 0;
// Yellow twinky
[Embed (source= "Assets/Players/twinky1.png")]
private const Twinky1idle:Class;
private var _twinky1idleArray:Array;
// Red twinky
[Embed (source= "Assets/Players/twinky2.png")]
private const Twinky2idle:Class;
private var _twinky2idleArray:Array;
private const twinkyWidth:uint= 64;
private const twinkyHeight:uint= 64;
private var t1i001:Rectangle= new Rectangle(0,0,twinkyWidth,twinkyHeight);
private var t2i001:Rectangle= new Rectangle(0,0,twinkyWidth,twinkyHeight);
/** Create Twinky. Twinkys must be flicked to the same colored Zwig to
* feed it and die when they lost momentum. **/
public function Twinky(daddy:Game,score:Score,m:Game,positions:Object,friction:Number,speedMax:Number,canvas:BitmapData,player:uint,isAtBottom:Boolean=true,skin:uint=0)
{
// Get score and game object reference
this._sRef= score;
this._mRef= daddy;
this.positions= positions;
this.friction= friction;
this.speedMax= speedMax;
this.canvas= canvas;
this.player= player;
this.isAtBottom= isAtBottom;
this.skin= skin;
this._twinky1idleArray= [t1i001];
this._twinky2idleArray= [t2i001];
this.addEventListener(Event.ADDED_TO_STAGE,init,false,0,true);
}
private function init(e:Event):void
{
this.removeEventListener(Event.ADDED_TO_STAGE,init);
// Get skin
switch (this.skin)
{
case 0:
this._image= new this.Twinky1idle().bitmapData;
this._idleArray= this._twinky1idleArray;
break;
case 1:
this._image= new this.Twinky2idle().bitmapData;
this._idleArray= this._twinky2idleArray;
break;
default:
this._image= new this.Twinky1idle().bitmapData;
this._idleArray= this._twinky1idleArray;
break;
}
// Give position
if (this.isAtBottom)
{
this.x= this.positions.XMargin;
this.y= ZwigsIpad.BORDERS.bottom - this.positions.YMargin;
// Animate entrance
TweenMax.from(this,1,{x:this.x-70,y:this.y-12,rotation:-180,alpha:.5});
}
else
{
this.x= ZwigsIpad.BORDERS.right - this.positions.XMargin;
this.y= this.positions.YMargin;
// Animate entrance
TweenMax.from(this,1,{x:this.x+70,y:this.y+12,rotation:-180,alpha:.5});
}
this._point.x= this.x;
this._point.y= this.y;
aText.appendText("\n position: "+this.x+" "+this.y);
// Detect touched
this.addEventListener(TouchEvent.TOUCH_BEGIN,touchDown);
// Always detect untouched
this._mRef.addEventListener(TouchEvent.TOUCH_END,touchUp);
// Always do kinetics
this._mRef.addEventListener(Event.ENTER_FRAME,freeMove);
}
/** Render the Twinky at its current coordinates by redrawing it. **/
internal function render():void
{
this._point.x= this.x - this._idleArray[i].width * .5;
this._point.y= this.y - this._idleArray[i].height * .5;
this.canvas.copyPixels(this._image,this._idleArray[0/*i*/],this._point);
// When idle finished restart, else pursue with animation
/*if (i==this._idleArray.length - 1)
i= 0;
else
i++;*/
}
// TWINKY AND RACQUET DO NOT DETECT TOUCH EVENTS because the main canvas covers them
// Start dragging when touched
private function touchDown(e:TouchEvent):void
{
aText.appendText("\n Twinky touched!");
if (this._touchMoveID != 0)
return;
this._touchMoveID= e.touchPointID;
this.dragging= true;
// Get the mouse's offset on the object
this.xOffset= e.localX;
this.yOffset= e.localY;
this._mRef.addEventListener(TouchEvent.TOUCH_MOVE,touchMove);
}
private function touchMove(e:TouchEvent):void
{
if (e.touchPointID != this._touchMoveID)
return;
// Move twinky to where the mouse is
this.x= e.stageX - this.xOffset;
this.y= e.stageY - this.yOffset;
// Don't go farther than borders
if (this.x <= this.width * .5)
{
this.x= (this.width * .5) + .1;
}
if (this.x >= ZwigsIpad.BORDERS.right - (this.width * .5))
{
this.x= ZwigsIpad.BORDERS.right - (this.width * .5) - .1;
}
if (this.y <= this.height * .5)
{
this.y= (this.height * .5) + .1;
}
if (this.y >= ZwigsIpad.BORDERS.bottom - (this.height * .5))
{
this.y= ZwigsIpad.BORDERS.bottom - (this.height * .5) - .1;
}
// Be undraggable if zone is left
if (this.isAtBottom)
{
if (this.y < (ZwigsIpad.BORDERS.bottom - this.positions.TwinkyHeight))
{
this._touchMoveID= 0;
this.dragging= false;
this._mRef.removeEventListener(TouchEvent.TOUCH_MOVE,touchMove);
return;
}
}
else
{
if (this.y > this.positions.TwinkyHeight)
{
this._touchMoveID= 0;
this.dragging= false;
this._mRef.removeEventListener(TouchEvent.TOUCH_MOVE,touchMove);
return;
}
}
// Refresh coordinates for display
this._point.x= this.x;
this._point.y= this.y;
e.updateAfterEvent();
}
private function touchUp(e:TouchEvent):void
{
if (e.touchPointID != this._touchMoveID)
return;
this._touchMoveID= 0;
this.dragging= false;
this._mRef.removeEventListener(TouchEvent.TOUCH_MOVE,touchMove);
}
private function freeMove(e:Event):void
{
// Be undraggable if liana crossed
if (this.isAtBottom)
{
if (this.y < (ZwigsIpad.BORDERS.bottom - this.positions.TwinkyHeight))
{
this.removeEventListener(TouchEvent.TOUCH_BEGIN,touchDown);
this._mRef.removeEventListener(Event.ENTER_FRAME,touchUp);
this.dragging= false;
this.launched= true;
}
}
else
{
if (this.y > this.positions.TwinkyHeight)
{
this.removeEventListener(TouchEvent.TOUCH_BEGIN,touchDown);
this._mRef.removeEventListener(Event.ENTER_FRAME,touchUp);
this.dragging= false;
this.launched= true;
}
}
// Move the twinky and calculate its speed if player is dragging it
if (this.dragging)
{
aText.appendText("\n Twinky dragged!");
this.oldX= currentX;
this.oldY= currentY;
currentX= this.x;
currentY= this.y;
// Calculate speed in X and Y axis
this._speedX= this.currentX - this.oldX;
this._speedY= this.currentY - this.oldY;
// Cap maximal speed
if (this._speedX > this.speedMax)
this._speedX= this.speedMax;
if (this._speedY > this.speedMax)
this._speedY= this.speedMax;
}
// Otherwise move the twinky using its speed
else
{
this.x+= this._speedX;
this.y+= this._speedY;
}
// Detect collision with zwigs
for (i= 0 ; i < this._mRef.zwigColliderList.length ; i++)
{
var cemp:Collider= this._mRef.zwigColliderList[i] as Collider;
if (this.hitTestObject(cemp))
{
this.removeEventListener(TouchEvent.TOUCH_BEGIN,touchDown);
this._mRef.removeEventListener(TouchEvent.TOUCH_END,touchUp);
this._mRef.removeEventListener(Event.ENTER_FRAME,freeMove);
this._sRef.die(this,this.player,true,i);
return;
}
}
// Detect collision with borders: left border
if (this.x <= this.width / 2)
{
// Don't go any further
this.x= (this.width / 2) + .1;
// Reverse speed to bounce
this._speedX*= -1;
}
// Right border
if (this.x >= ZwigsIpad.BORDERS.right - (this.width / 2))
{
this.x= ZwigsIpad.BORDERS.right - (this.width / 2) - .1;
this._speedX*= -1;
}
// Top border
if (this.y <= this.height / 2)
{
this.y= (this.height / 2) + .1;
this._speedY*= -1;
}
// Bottom border
if (this.y >= ZwigsIpad.BORDERS.bottom - (this.height / 2))
{
this.y= ZwigsIpad.BORDERS.bottom - (this.height / 2) - .1;
this._speedY*= -1;
}
// Detect collision with racquets
for (var i:uint= 0 ; i < this._mRef.racquetList.length ; i++)
{
var temp:Racquet= this._mRef.racquetList[i] as Racquet;
if (this.hitTestObject(temp))
{
this._speedY*= -1;
this.y+= this._speedY;
}
}
// Speed decay
this._speedX*= this.friction;
this._speedY*= this.friction;
// Set speed to 0 if speed is smaller than .5
if (Math.abs(this._speedX) < .5) this._speedX= 0;
if (Math.abs(this._speedY) < .5) this._speedY= 0;
// If speed is null and it has been launched, kill twinky
if (this._speedX == 0 && this._speedY == 0 && this.launched)
{
this.removeEventListener(TouchEvent.TOUCH_BEGIN,touchDown);
this._mRef.removeEventListener(TouchEvent.TOUCH_END,touchUp);
this._mRef.removeEventListener(Event.ENTER_FRAME,freeMove);
TweenMax.to(this, 1.5, {alpha:0, ease:Linear.easeNone});
this._sRef.die(this,this.player);
return;
}
// Refresh coordinates for display
this._point.x= this.x;
this._point.y= this.y;
}
}
}
Racquet class:
package Game
{
import Game.Worlds.Level1.Level1;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.TouchEvent;
import flash.geom.Point;
import flash.ui.Multitouch;
import flash.ui.MultitouchInputMode;
internal class Racquet extends Sprite
{
Multitouch.inputMode= MultitouchInputMode.TOUCH_POINT;
private var _touchMoveID:int= 0;
private var xOffset:Number;
private var dragging:Boolean= false;
private var positions:Object;
private var canvas:BitmapData;
private var isAtBottom:Boolean;
private var skin:uint;
private var _image:BitmapData;
private var _point:Point= new Point();
// Yellow racquet
[Embed (source= "Assets/Players/racq1.png")]
private const Racquet1:Class;
// Red racquet
[Embed (source= "Assets/Players/racq2.png")]
private const Racquet2:Class;
public function Racquet(positions:Object,canvas:BitmapData,isAtBottom:Boolean=true,skin:uint=0)
{
this.positions= positions;
this.canvas= canvas;
this.isAtBottom= isAtBottom;
this.skin= skin;
this.addEventListener(Event.ADDED_TO_STAGE,init,false,0,true);
}
private function init(e:Event):void
{
this.removeEventListener(Event.ADDED_TO_STAGE,init);
// Get skin
switch (this.skin)
{
case 0:
//this._image= new R.Racquet1().bitmapData;
this._image= new this.Racquet1().bitmapData;
break;
case 1:
//this._image= new R.Racquet2().bitmapData;
this._image= new this.Racquet2().bitmapData;
break;
default:
this._image= new this.Racquet1().bitmapData;
break;
}
// Give position
if (this.isAtBottom)
{
this.x= ZwigsIpad.BORDERS.centerX;
this.y= ZwigsIpad.BORDERS.bottom - this.positions.LianaHeight;
}
else
{
this.x= ZwigsIpad.BORDERS.centerX;
this.y= this.positions.LianaHeight;
}
this._point.x= this.x;
this._point.y= this.y;
this.addEventListener(TouchEvent.TOUCH_BEGIN,touchDown,false,0,true);
this.parent.addEventListener(TouchEvent.TOUCH_END,touchUp,false,0,true);
}
internal function render():void
{
this._point.x= this.x - this._image.rect.width * .5;
this._point.y= this.y - this._image.rect.height * .5;
this.canvas.copyPixels(this._image,this._image.rect,this._point);
}
private function touchDown(e:TouchEvent):void
{
aText.appendText("\n Racquet touched!");
if(this._touchMoveID != 0)
return;
this._touchMoveID= e.touchPointID;
this.xOffset= e.localX;
this.parent.addEventListener(TouchEvent.TOUCH_MOVE,touchMove,false,0,true);
}
private function touchMove(e:TouchEvent):void
{
if(e.touchPointID != this._touchMoveID)
return;
Multitouch.inputMode= MultitouchInputMode.TOUCH_POINT;
this._point.x= e.stageX - this.xOffset;
if (this._point.x <= ZwigsIpad.BORDERS.left + (this._image.width*.5))
this._point.x= ZwigsIpad.BORDERS.left + (this._image.width*.5);
else if (this._point.x >= ZwigsIpad.BORDERS.right - (this._image.width*.5))
this._point.x= ZwigsIpad.BORDERS.right - (this._image.width*.5);
}
private function touchUp(e:TouchEvent):void
{
if(e.touchPointID != this._touchMoveID)
return;
this._touchMoveID= 0;
this.parent.removeEventListener(TouchEvent.TOUCH_MOVE,touchMove);
}
}
}
Touch events will only fire when you touch a sprite's graphics. But all your graphics are drawn onto a single bitmap so your various sprites have nothing to interact with.
Flash provides a display list and does a good job of rendering it, so you shouldn't need to build your own complicated structures like this.
You should consider making each sprite contain its own graphics and things will just work out easier. If performance is a huge concern, I suggest getting it working first, and then play around with different optimisation strategies afterwards (e.g. cacheAsBitmap, clipping/scrolling with scrollRect etc.)
I have a class that I use to display text on stage, with some number effects. It works pretty well, but when I chain it like this
public function onAdd(e:Event) {
//stuff
addChild(new messager("Welcome."));
addChild(new messager("WASD to move, mouse to shoot."));
addChild(new messager("Kill zombies for XP and collect ammo boxes.",waveOne));
}
public function waveOne(){
addChild(new messager("Good luck and have fun.",newWave));
}
The text (Good luck and have fun) is not displayed, but newWave is called. The reason why I don't call waveOne in onAdd is so that it doesn't happen too quick - my class just throws the text at the user once every 50 frames (which is intended, for later when you kill enemies and the text needs to catch up).
Here is my class (with the effects removed):
package {
import flash.display.MovieClip;
import flash.events.*;
import flash.utils.Timer;
public class Messager extends MovieClip{
var actualText:String;
var callback:Function;
var upTo:int = 0;
static var waitingFor:int = 0;
public function Messager(text:String,callback:Function=null) {
this.callback = callback;
actualText = text;
x = 320 - actualText.length * 6.5;
y = 0 - waitingFor * 60;
addEventListener(Event.ENTER_FRAME, onEnterFrame);
waitingFor++;
}
public function onEnterFrame(e:Event) {
y+= 1;
if(y > 60){
waitingFor--;
}
if(y > 200){
alpha -= 0.03;
if(alpha <= 0){
if(callback != null){
callback();
}
removeEventListener(Event.ENTER_FRAME, onEntFrm);
this.parent.removeChild(this);
}
}
}
}
It is set to linkage with a movieclip that has a textfield.
Thanks for any help.
y = 0 - waitingFor * 60; Maybe y of the last Mesager is a big negative number? Have you tried to trace waitingFor?