AS3 Frogger Pixel Perfect Collision - actionscript-3

I have created a simple AS3 frogger game and used .hitTestObject to test if the frog hits any of the obstacles. This is not effective as the frog hits objects that aren't touching it at all. I am new to AS3 and have no idea where to start with coding for this. Any help would be appreciated!
package {
import flash.display.*;
import flash.events.*;
import flash.utils.*;
import flash.ui.*;
import flash.events.Event;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.utils.Timer;
import flash.display.BitmapData;
import flash.display.Bitmap;
public class Main extends MovieClip
{
//set variables
public var frog_spriteInstance:frog_sprite;
public var safeZoneInstance1 : safeZone;
public var safeZoneInstance2: safeZone;
public var safeZoneInstance3 : safeZone;
public var whitecar : car1;
public var whitecar1 : car1;
public var whitecar2 : car1;
public var truck1 : truck_sprite;
public var truck2: truck_sprite;
public var redcar : car_sprite;
public var redcar2 : car_sprite;
public var redcar3 : car_sprite;
public var log1 : log_sprite;
public var log2 : log_sprite;
public var log3 : log_sprite;
public var letters : Letters;
public var letters2 : Letters_2;
public var letters3 : Letters_3;
public var letters4 : Letters_4;
public var health : HealthBar;
public var firstletter : firstLetter;
public var secondletter : secondLetter;
public var thirdletter : thirdLetter;
public var fourthletter : fourthLetter;
var mysound:Sound = new (mySound);
public function Main()
{
// constructor code
safeZoneInstance1 = new safeZone();
stage.addChild(safeZoneInstance1);
safeZoneInstance1.x = 300;
safeZoneInstance1.y=545
safeZoneInstance2 = new safeZone();
stage.addChild(safeZoneInstance2);
safeZoneInstance2.x = 300;
safeZoneInstance2.y=300
safeZoneInstance3 = new safeZone();
stage.addChild(safeZoneInstance3);
safeZoneInstance3.x = 300;
safeZoneInstance3.y=100
whitecar = new car1();
stage.addChild(whitecar);
whitecar.x = 300;
whitecar.y = 500
whitecar1 = new car1();
stage.addChild(whitecar1);
whitecar1.x = 550;
whitecar1.y = 480
whitecar2 = new car1();
stage.addChild(whitecar2);
whitecar2.x = 50;
whitecar2.y = 480
truck1 = new truck_sprite();
stage.addChild (truck1);
truck1.x = 1000;
truck1.y = 430
truck2 = new truck_sprite();
stage.addChild (truck2);
truck2.x = 300;
truck2.y = 430
redcar = new car_sprite();
stage.addChild (redcar);
redcar.x = 300;
redcar.y = 340
redcar2 = new car_sprite();
stage.addChild (redcar2);
redcar2.x = 100;
redcar2.y = 375
redcar3 = new car_sprite();
stage.addChild (redcar3);
redcar3.x = 500;
redcar3.y = 375
log1 = new log_sprite();
stage.addChild(log1);
log1.x = 300;
log1.y = 230
log2 = new log_sprite();
stage.addChild(log2);
log2.x = 100;
log2.y = 150
log3 = new log_sprite();
stage.addChild(log3);
log3.x = 500;
log3.y = 150
letters = new Letters();
letters.x = randomRange(100,500) ;
letters.y = randomRange(100,500);
stage.addChild(letters);
letters2 = new Letters_2();
letters2.x = randomRange(100,500) ;
letters2.y = randomRange(100,500);
stage.addChild(letters2);
letters3 = new Letters_3();
letters3.x = randomRange(100,500) ;
letters3.y = randomRange(100,500);
stage.addChild(letters3);
letters4 = new Letters_4();
letters4.x = randomRange(100,500) ;
letters4.y = randomRange(100,500);
stage.addChild(letters4);
frog_spriteInstance = new frog_sprite();
stage.addChild(frog_spriteInstance);
frog_spriteInstance.x=300;
frog_spriteInstance.y=550;
health = new HealthBar();
stage.addChild(health);
health.x = 130;
health.y = 20;
health.width = 100;
stage.addEventListener(KeyboardEvent.KEY_DOWN, moveFrog);
stage.addEventListener(Event.ENTER_FRAME, movecars);
stage.addEventListener(Event.ENTER_FRAME, movetrucks);
stage.addEventListener(Event.ENTER_FRAME, moveredcars);
stage.addEventListener(Event.ENTER_FRAME, movelogs);
stage.addEventListener(Event.ENTER_FRAME,checkforcollision);
mysound.play();
}
public function moveFrog(e:KeyboardEvent)
{
// get the key pressed and then move the player
{
if (e.keyCode == Keyboard.UP)
{
frog_spriteInstance.rotation = 0;
frog_spriteInstance.y -= 50;
}
if (e.keyCode == Keyboard.DOWN)
{
frog_spriteInstance.rotation = 180;
frog_spriteInstance.y += 50;
}
if (e.keyCode == Keyboard.LEFT)
{
frog_spriteInstance.rotation = -90;
frog_spriteInstance.x -= 50;
}
if (e.keyCode == Keyboard.RIGHT)
{
frog_spriteInstance.rotation = 90;
frog_spriteInstance.x += 50;
}
}
}
function movecars(event:Event)
{
//move cars across screen and when they disappear, reappear at the other side
whitecar.x -= 3;
if (whitecar.x<-100){
whitecar.x=650;
}
whitecar1.x -= 3;
if (whitecar1.x<-100){
whitecar1.x=650;
}
whitecar2.x -= 3;
if (whitecar2.x<-100){
whitecar2.x=650;
}
}
function movelogs(event:Event)
{
//move logs across screen and when they disappear, reappear at the other side
log1.x -= 5;
if (log1.x<-100){
log1.x=650;
}
log2.x -= 5;
if (log2.x<-100){
log2.x=650;
}
log3.x -= 5;
if (log3.x<-100){
log3.x=650;
}
}
function movetrucks(event:Event)
{
//move trucks across screen and when they disappear, reappear at the other side
truck1.x +=3;
if (truck1.x>650){
truck1.x=-100;
}
truck2.x +=3;
if (truck2.x>650){
truck2.x=-100;
}
}
function moveredcars(event:Event)
{
//move red cars across screen and when they disappear, reappear at the other side
redcar.x +=3;
if (redcar.x>650){
redcar.x=-100;
}
redcar2.x +=3;
if (redcar2.x>650){
redcar2.x=-100;
}
redcar3.x +=3;
if (redcar3.x>650){
redcar3.x=-100;
}
}
function checkforcollision(event:Event)
{
//check for collisions
if (frog_spriteInstance.hitTestObject(log1) || (frog_spriteInstance.hitTestObject(log2) || (frog_spriteInstance.hitTestObject(log3) || (frog_spriteInstance.hitTestObject(whitecar) || (frog_spriteInstance.hitTestObject(whitecar1) || (frog_spriteInstance.hitTestObject(whitecar2) || (frog_spriteInstance.hitTestObject(log2) || (frog_spriteInstance.hitTestObject(truck1) || (frog_spriteInstance.hitTestObject(truck2) || (frog_spriteInstance.hitTestObject(redcar) || (frog_spriteInstance.hitTestObject(redcar2) || (frog_spriteInstance.hitTestObject(redcar3))))))))))))){
//reset frog if hits an obstacle
stage.addChild(frog_spriteInstance);
frog_spriteInstance.x=300;
frog_spriteInstance.y=550;
//reduce health bar
health.width -= 10;
}
//remove event listeners when health is empty
if (health.width == 0){
stage.removeEventListener(Event.ENTER_FRAME, movecars);
stage.removeEventListener(KeyboardEvent.KEY_DOWN, moveFrog);
stage.removeEventListener(Event.ENTER_FRAME, movetrucks);
stage.removeEventListener(Event.ENTER_FRAME, moveredcars);
stage.removeEventListener(Event.ENTER_FRAME, movelogs);
}
//add letters to bottom of screen when hit correctly
if (frog_spriteInstance.hitTestObject(letters)){
stage.addChild(frog_spriteInstance);
frog_spriteInstance.x=300;
frog_spriteInstance.y=550;
stage.removeChild(letters);
firstletter = new firstLetter();
stage.addChild(firstletter);
firstletter.x=345;
firstletter.y=600;
}
if (frog_spriteInstance.hitTestObject(letters2)){
stage.addChild(frog_spriteInstance);
frog_spriteInstance.x=300;
frog_spriteInstance.y=550;
stage.removeChild(letters2);
secondletter = new secondLetter();
stage.addChild(secondletter);
secondletter.x=206;
secondletter.y=600;
}
if (frog_spriteInstance.hitTestObject(letters3)){
stage.addChild(frog_spriteInstance);
frog_spriteInstance.x=300;
frog_spriteInstance.y=550;
stage.removeChild(letters3);
thirdletter = new thirdLetter();
stage.addChild(thirdletter);
thirdletter.x=273;
thirdletter.y=600;
}
if (frog_spriteInstance.hitTestObject(letters4)){
stage.addChild(frog_spriteInstance);
frog_spriteInstance.x=300;
frog_spriteInstance.y=550;
stage.removeChild(letters4);
health.width -= 10;
fourthletter = new fourthLetter();
stage.addChild(fourthletter);
fourthletter.x=25;
fourthletter.y=620;
}
}
function randomRange(minNum:Number, maxNum:Number):Number
{
//random generator for letter positioning
return (Math.floor(Math.random() * (maxNum - minNum + 1)) + minNum);
}
}
}
Also my code is pretty dodgy so any suggestions on improvement are very welcome.

To perform pixel perfect hit test from two arbitrary display objects you have to draw them to bitmaps and use BitmapData/hitTest().
Here is a generalized function that does this:
function hitTestShapes(object1:DisplayObject, object2:DisplayObject, threshold:uint = 1):Boolean {
var bounds1:Rectangle = object1.getBounds(object1.parent);
var matrix1:Matrix = object1.transform.matrix;
matrix1.tx = object1.x - bounds1.x;
matrix1.ty = object1.y - bounds1.y;
var bmp1:BitmapData = new BitmapData(bounds1.width, bounds1.height, true, 0);
bmp1.draw(object1, matrix1);
var bounds2:Rectangle = object2.getBounds(object2.parent);
var matrix2:Matrix = object2.transform.matrix;
matrix2.tx = object2.x - bounds2.x;
matrix2.ty = object2.y - bounds2.y;
var bmp2:BitmapData = new BitmapData(bounds2.width, bounds2.height, true, 0);
bmp2.draw(object2, matrix2);
return bmp1.hitTest(bounds1.topLeft, threshold, bmp2, bounds2.topLeft, threshold);
}
Note, though, that drawing to bitmaps is rather slow, so be careful not to over-use this kind of function or you will have performance issues. In fact, it would be a good idea to use hitTestObject() first, which is very fast and detects bounding box intersections, then only call hitTestShapes() to refine your check. In other words:
if (frog_spriteInstance.hitTestObject(log1) && hitTestShapes(frog_spriteInstance, log1)) { }
As for suggestions on your code, there's a lot of potential for de-duplicating by way of arrays, loops, and functions. For example, instead of defining all your objects as separate variables, just store them all in an array (or vector):
public var safeZones:Array = [];
public var obstacles:Array = [];
public var letters:Array = [];
To populate the arrays, you can push values into them and use a function to consolidate all your duplicate object setup code:
(Code convention note: use "UpperCamelCase" for class names.)
public function Main(){
addSafeZone(300, 545);
addSafeZone(300, 300);
addSafeZone(300, 100);
addObstacle(WhiteCar, 300, 500);
addObstacle(WhiteCar, 550, 480);
addObstacle(WhiteCar, 50, 480);
addObstacle(Truck, 1000, 430);
addObstacle(Truck, 300, 430);
addObstacle(RedCar, 300, 340);
addObstacle(RedCar, 100, 375);
addObstacle(RedCar, 500, 375);
addObstacle(Log, 300, 230);
addObstacle(Log, 100, 150);
addObstacle(Log, 500, 150);
addRandomLetters(Letters_1);
addRandomLetters(Letters_2);
addRandomLetters(Letters_3);
addRandomLetters(Letters_4);
}
private function addSafeZone(x:Number, y:Number):void {
var safeZone:SafeZone = new SafeZone();
stage.addChild(safeZone);
safeZone.x = x;
safeZone.y = y
safeZones.push(safeZone);
}
private function addObstacle(spriteClass:Class, x:Number, y:Number):void {
var obstacle:Sprite = new spriteClass();
stage.addChild(obstacle);
obstacle.x = x;
obstacle.y = y
obstacles.push(obstacle);
}
private function addRandomLetters(lettersClass:Class):void {
var lettersSprite:Sprite = new lettersClass();
lettersSprite.x = randomRange(100, 500);
lettersSprite.y = randomRange(100, 500);
stage.addChild(lettersSprite);
letters.push(lettersSprite);
}
Now you can loop over the arrays to perform all your actions. For example, to check for a hit against any obstacle:
for each(var obstacle:DisplayObject in obstacles){
if(frog.hitTestObject(obstacle) && hitTestShapes(frog, obstacle)){
// The frog hit an obstacle!
}
}
You could also combine all our "move" functions into one, which moves each obstacle based on their type:
private function moveObstacles(e:Event):void {
for each(var obstacle in obstacles){
if(obstacle is WhiteCar){
obstacle.x -= 3;
}
else if(obstacle is RedCar){
obstacle.x += 3;
}
else if(obstacle is Truck){
obstacle.x += 3;
}
else if(obstacle is Log){
obstacle.x -= 5;
}
if(obstacle.x < -100){
obstacle.x = 650;
}
else if(obstacle.x > 650){
obstacle.x = -100;
}
}
}
Lastly, you really should only need a single ENTER_FRAME handler. Just call whatever functions you want from in there. Adding multiple ENTER_FRAME handlers can get troublesome to manage. For example, just do this:
addEventListener(Event.ENTER_FRAME, update);
private function update(e:Event):void {
moveObstacles();
doOtherStuff();
anythingYouNeedToDo();
}
This way you only need to removeEventListener(Event.ENTER_FRAME, update) to stop the game, not a whole bunch of ENTER_FRAME handlers.
I haven't tested any of this code, but you get the general idea. Let me know if you have any issues with it and I can help.

Related

boundares - if object is past, delete object

I have a code below that has rocks moving from left to right, I would like to create a boundary for them that they can only move a certain way in on the stage, once they get past this point they delete. I have tried to write this up under the Wrap Rocks and Delete Rocks section, but it's not working and it's not giving me any errors. Does anyone have any thoughts that might help me?
let me know if you need to see more code:
package {
import flash.display.*;
import flash.events.*;
import flash.text.*;
import flash.utils.getTimer;
import flash.utils.Timer;
import flash.geom.Point;
public class SpaceRocks_v002 extends MovieClip {
static const shipRotationSpeed:Number = .1;
static const rockSpeedStart:Number = .03;
static const rockSpeedIncrease:Number = .02;
static const missileSpeed:Number = .2;
static const thrustPower:Number = .15;
static const shipRadius:Number = 20;
static const startingShips:uint = 3;
// game objects
private var ship:Ship;
private var rocks:Array;
private var missiles:Array;
// animation timer
private var lastTime:uint;
// arrow keys
private var rightArrow:Boolean = false;
private var leftArrow:Boolean = false;
private var upArrow:Boolean = false;
// ship velocity
private var shipMoveX:Number;
private var shipMoveY:Number;
// timers
private var delayTimer:Timer;
private var shieldTimer:Timer;
// game mode
private var gameMode:String;
private var shieldOn:Boolean;
// ships and shields
private var shipsLeft:uint;
private var shieldsLeft:uint;
private var shipIcons:Array;
private var shieldIcons:Array;
private var scoreDisplay:TextField;
// score and level
private var gameScore:Number;
private var gameLevel:uint;
// sprites
private var gameObjects:Sprite;
private var scoreObjects:Sprite;
// start the game
public function startSpaceRocks_v002():void {
// set up sprites
gameObjects = new Sprite();
addChild(gameObjects);
scoreObjects = new Sprite();
addChild(scoreObjects);
// reset score objects
gameLevel = 1;
shipsLeft = startingShips;
gameScore = 0;
createShipIcons();
createScoreDisplay();
// set up listeners
addEventListener(Event.ENTER_FRAME,moveGameObjects);
stage.addEventListener(KeyboardEvent.KEY_DOWN,keyDownFunction);
stage.addEventListener(KeyboardEvent.KEY_UP,keyUpFunction);
// start
gameMode = "delay";
shieldOn = false;
missiles = new Array();
nextRockWave(null);
newShip(null);
}
// SCORE OBJECTS
// draw number of ships left
public function createShipIcons() {
shipIcons = new Array();
for(var i:uint=0;i<shipsLeft;i++) {
var newShip:ShipIcon = new ShipIcon();
newShip.x = 20+i*15;
newShip.y = 375;
scoreObjects.addChild(newShip);
shipIcons.push(newShip);
}
}
// draw number of shields left
public function createShieldIcons() {
shieldIcons = new Array();
for(var i:uint=0;i<shieldsLeft;i++) {
var newShield:ShieldIcon = new ShieldIcon();
newShield.x = 530-i*15;
newShield.y = 375;
scoreObjects.addChild(newShield);
shieldIcons.push(newShield);
}
}
// put the numerical score at the upper right
public function createScoreDisplay() {
scoreDisplay = new TextField();
scoreDisplay.x = 480;
scoreDisplay.y = 100;
scoreDisplay.width = 20;
scoreDisplay.selectable = false;
var scoreDisplayFormat = new TextFormat();
scoreDisplayFormat.color = 0xFFFFFF;
scoreDisplayFormat.font = "Arial";
scoreDisplayFormat.align = "right";
scoreDisplayFormat.size = 15;
scoreDisplay.defaultTextFormat = scoreDisplayFormat;
scoreObjects.addChild(scoreDisplay);
updateScore();
}
// new score to show
public function updateScore() {
scoreDisplay.text = String(gameScore);
}
// remove a ship icon
public function removeShipIcon() {
scoreObjects.removeChild(shipIcons.pop());
}
// remove a shield icon
public function removeShieldIcon() {
scoreObjects.removeChild(shieldIcons.pop());
}
// remove the rest of the ship icons
public function removeAllShipIcons() {
while (shipIcons.length > 0) {
removeShipIcon();
}
}
// remove the rest of the shield icons
public function removeAllShieldIcons() {
while (shieldIcons.length > 0) {
removeShieldIcon();
}
}
// SHIP CREATION AND MOVEMENT
// create a new ship
public function newShip(event:TimerEvent) {
// if ship exists, remove it
if (ship != null) {
gameObjects.removeChild(ship);
ship = null;
}
// no more ships
if (shipsLeft < 1) {
endGame();
return;
}
// create, position, and add new ship
ship = new Ship();
ship.gotoAndStop(1);
ship.x = 400;
ship.y = 350;
ship.rotation = -180;
ship.shield.visible = false;
gameObjects.addChild(ship);
// set up ship properties
shipMoveX = 0.0;
shipMoveY = 0.0;
gameMode = "play";
// set up shields
shieldsLeft = 3;
createShieldIcons();
// all lives but the first start with a free shield
if (shipsLeft != startingShips) {
startShield(true);
}
}
// register key presses
public function keyDownFunction(event:KeyboardEvent) {
if (event.keyCode == 38) {
leftArrow = true;
} else if (event.keyCode == 40) {
rightArrow = true;
} else if (event.keyCode == 32) { // space
newMissile();
} else if (event.keyCode == 90) { // z
startShield(false);
}
}
// register key ups
public function keyUpFunction(event:KeyboardEvent) {
if (event.keyCode == 38) {
leftArrow = false;
} else if (event.keyCode == 40) {
rightArrow = false;
}
}
// animate ship
public function moveShip(timeDiff:uint) {
// rotate and thrust
if (leftArrow) {
ship.y -= 2;
} else if (rightArrow) {
ship.y+= 2;
}
// move
ship.x += shipMoveX;
ship.y += shipMoveY;
// check boundaries
if (ship.y < 65) ship.y = 65;
if (ship.y > 380) ship.y = 380;
}
// remove ship
public function shipHit() {
gameMode = "delay";
ship.gotoAndPlay("explode");
removeAllShieldIcons();
delayTimer = new Timer(2000,1);
delayTimer.addEventListener(TimerEvent.TIMER_COMPLETE,newShip);
delayTimer.start();
removeShipIcon();
shipsLeft--;
}
// turn on shield for 3 seconds
public function startShield(freeShield:Boolean) {
if (shieldsLeft < 1) return; // no shields left
if (shieldOn) return; // shield already on
// turn on shield and set timer to turn off
ship.shield.visible = true;
shieldTimer = new Timer(3000,1);
shieldTimer.addEventListener(TimerEvent.TIMER_COMPLETE,endShield);
shieldTimer.start();
// update shields remaining
if (!freeShield) {
removeShieldIcon();
shieldsLeft--;
}
shieldOn = true;
}
// turn off shield
public function endShield(event:TimerEvent) {
ship.shield.visible = false;
shieldOn = false;
}
// ROCKS
// create a single rock of a specific size
public function newRock(x,y:int, rockType:String) {
// create appropriate new class
var newRock:MovieClip;
var rockRadius:Number;
if (rockType == "Big") {
newRock = new Rock_Big();
rockRadius = 35;
} else if (rockType == "Medium") {
newRock = new Rock_Medium();
rockRadius = 20;
} else if (rockType == "Small") {
newRock = new Rock_Small();
rockRadius = 10;
}
// choose a random look
newRock.gotoAndStop(Math.ceil(Math.random()*3+1));
// set start position
newRock.x = Math.random()*0;
newRock.y = Math.random()*280+80;
// set random movement and rotation
var dx:Number = Math.random()*3;
var dy:Number = Math.random()*2;
// add to stage and to rocks list
gameObjects.addChild(newRock);
rocks.push({rock:newRock, dx:dx, dy:dy, rockType:rockType, rockRadius: rockRadius});
}
// create four rocks
public function nextRockWave(event:TimerEvent) {
rocks = new Array();
newRock(100,1,"Big");
newRock(200,1,"Big");
newRock(450,1,"Big");
newRock(350,1,"Big");
gameMode = "play";
}
// animate all rocks
public function moveRocks(timeDiff:uint) {
for(var i:int=rocks.length-1;i>=0;i--) {
// move the rocks
var rockSpeed:Number = rockSpeedStart + rockSpeedIncrease*gameLevel;
rocks[i].rock.x += rocks[i].dx*timeDiff*rockSpeed;
rocks[i].rock.y += rocks[i].dy*rockSpeed;
// wrap rocks
if ((rocks[i].rock.x > 0) && (x <-50)) {
deleteRocks();
}
else if ((rocks[i].rock.x < 0) && (x > 50)) {
deleteRocks();
}
}
}
public function rockHit(rockNum:uint) {
// create two smaller rocks
if (rocks[rockNum].rockType == "Big") {
newRock(rocks[rockNum].rock.x,rocks[rockNum].rock.y,"Medium");
newRock(rocks[rockNum].rock.x,rocks[rockNum].rock.y,"Medium");
}
// remove original rock
gameObjects.removeChild(rocks[rockNum].rock);
rocks.splice(rockNum,1);
}
public function deleteRocks(){
gameMode = "delay";
newRock.gotoAndPlay("bang");
}
// MISSILES
// create a new Missile
public function newMissile() {
// create
var newMissile:Missile = new Missile();
// set direction
newMissile.dx = Math.cos(Math.PI*ship.rotation/180);
newMissile.dy = Math.sin(Math.PI*ship.rotation/180);
// placement
newMissile.x = ship.x + newMissile.dx*shipRadius;
newMissile.y = ship.y + newMissile.dy*shipRadius;
// add to stage and array
gameObjects.addChild(newMissile);
missiles.push(newMissile);
}
// animate missiles
public function moveMissiles(timeDiff:uint) {
for(var i:int=missiles.length-1;i>=0;i--) {
// move
missiles[i].x += missiles[i].dx*missileSpeed*timeDiff;
missiles[i].y += missiles[i].dy*missileSpeed*timeDiff;
// moved off screen
if ((missiles[i].x < 0) || (missiles[i].x > 550) || (missiles[i].y < 0) || (missiles[i].y > 400)) {
gameObjects.removeChild(missiles[i]);
delete missiles[i];
missiles.splice(i,1);
}
}
}
// remove a missile
public function missileHit(missileNum:uint) {
gameObjects.removeChild(missiles[missileNum]);
missiles.splice(missileNum,1);
}
// GAME INTERACTION AND CONTROL
public function moveGameObjects(event:Event) {
// get timer difference and animate
var timePassed:uint = getTimer() - lastTime;
lastTime += timePassed;
moveRocks(timePassed);
if (gameMode != "delay") {
moveShip(timePassed);
}
moveMissiles(timePassed);
checkCollisions();
}
// look for missiles colliding with rocks
public function checkCollisions() {
// loop through rocks
rockloop: for(var j:int=rocks.length-1;j>=0;j--) {
// loop through missiles
missileloop: for(var i:int=missiles.length-1;i>=0;i--) {
// collision detection
if (Point.distance(new Point(rocks[j].rock.x,rocks[j].rock.y),
new Point(missiles[i].x,missiles[i].y))
< rocks[j].rockRadius) {
// remove rock and missile
rockHit(j);
missileHit(i);
// add score
gameScore += 10;
updateScore();
// break out of this loop and continue next one
continue rockloop;
}
}
// check for rock hitting ship
if (gameMode == "play") {
if (shieldOn == false) { // only if shield is off
if (Point.distance(new Point(rocks[j].rock.x,rocks[j].rock.y),
new Point(ship.x,ship.y))
< rocks[j].rockRadius+shipRadius) {
// remove ship and rock
shipHit();
rockHit(j);
}
}
}
}
// all out of rocks, change game mode and trigger more
if ((rocks.length == 0) && (gameMode == "play")) {
gameMode = "betweenlevels";
gameLevel++; // advance a level
delayTimer = new Timer(2000,1);
delayTimer.addEventListener(TimerEvent.TIMER_COMPLETE,nextRockWave);
delayTimer.start();
}
}
public function endGame() {
// remove all objects and listeners
removeChild(gameObjects);
removeChild(scoreObjects);
gameObjects = null;
scoreObjects = null;
removeEventListener(Event.ENTER_FRAME,moveGameObjects);
stage.removeEventListener(KeyboardEvent.KEY_DOWN,keyDownFunction);
stage.removeEventListener(KeyboardEvent.KEY_UP,keyUpFunction);
gotoAndStop("gameover");
}
}
}
thanks in advance for the help!!
first pass out the rock you want to delete
deleteRocks(rocks[i].rock);
then remove it from the stage
public function deleteRocks(rock){
gameMode = "delay";
trace("Rock Deleted");
gameObjects.removeChild(rock) ;
}
But I think there is a problem with your if condition that control the removing of rocks. check it out

Errors on end game on score

OK I"ve managed to fix most of the error, the main remaining ones are when I try to make the game end when it hits 50... This is now the error I get and when I go into the next level the ship disappears, but the game plays with an invisible ship....
ArgumentError: Error #2025: The supplied DisplayObject must be a child of the caller.
at flash.display::DisplayObjectContainer/removeChild()
at SpaceRocks_v008/newShip()[/Users/Jess/Documents/UNI/INFT6303_game_design/Ass_3/Flash_V2/SpaceRocks_v008.as:168]
at SpaceRocks_v008/startSpaceRocks_v008()[/Users/Jess/Documents/UNI/INFT6303_game_design/Ass_3/Flash_V2/SpaceRocks_v008.as:84]
at SpaceRocks_v008/frame2()
Cannot display source code at this location.
package {
import flash.display.*;
import flash.events.*;
import flash.text.*;
import flash.utils.getTimer;
import flash.utils.Timer;
import flash.geom.Point;
public class SpaceRocks_v008 extends MovieClip {
static const shipRotationSpeed:Number = .1;
static const rockSpeedStart:Number = .03;
static const rockSpeedIncrease:Number = .02;
static const missileSpeed:Number = .2;
static const thrustPower:Number = .15;
static const shipRadius:Number = 20;
static const startingShips:uint = 3;
// game objects
private var ship:Ship;
private var rocks:Array;
private var missiles:Array;
// animation timer
private var lastTime:uint;
// arrow keys
private var rightArrow:Boolean = false;
private var leftArrow:Boolean = false;
private var upArrow:Boolean = false;
// ship velocity
private var shipMoveX:Number;
private var shipMoveY:Number;
// timers
private var delayTimer:Timer;
private var shieldTimer:Timer;
// game mode
private var gameMode:String;
private var shieldOn:Boolean;
// ships and shields
private var shipsLeft:uint;
private var shieldsLeft:uint;
private var shipIcons:Array;
private var shieldIcons:Array;
private var scoreDisplay:TextField;
// score and level
private var gameScore1:Number;
private var gameLevel:uint;
// sprites
private var gameObjects:Sprite;
private var scoreObjects:Sprite;
// start the game
public function startSpaceRocks_v008() {
// set up sprites
gameObjects = new Sprite();
addChild(gameObjects);
scoreObjects = new Sprite();
addChild(scoreObjects);
// reset score objects
gameLevel = 1;
shipsLeft = startingShips;
gameScore1 = 0;
createShipIcons();
createScoreDisplay();
// set up listeners
addEventListener(Event.ENTER_FRAME,moveGameObjects);
stage.addEventListener(KeyboardEvent.KEY_DOWN,keyDownFunction);
stage.addEventListener(KeyboardEvent.KEY_UP,keyUpFunction);
// start
gameMode = "delay";
shieldOn = false;
missiles = new Array();
nextRockWave(null);
newShip(null);
}
// SCORE OBJECTS
// draw number of ships left
public function createShipIcons() {
shipIcons = new Array();
for(var i:uint=0;i<shipsLeft;i++) {
var newShip:ShipIcon = new ShipIcon();
newShip.x = 460+i*30;
newShip.y = 328;
scoreObjects.addChild(newShip);
shipIcons.push(newShip);
}
}
// draw number of shields left
public function createShieldIcons() {
shieldIcons = new Array();
for(var i:uint=0;i<shieldsLeft;i++) {
var newShield:ShieldIcon = new ShieldIcon();
newShield.x = 520-i*30;
newShield.y = 210;
scoreObjects.addChild(newShield);
shieldIcons.push(newShield);
}
}
// put the numerical score at the upper right
public function createScoreDisplay() {
scoreDisplay = new TextField();
scoreDisplay.x = 460;
scoreDisplay.y = 68;
scoreDisplay.width = 40;
scoreDisplay.selectable = false;
var scoreDisplayFormat = new TextFormat();
scoreDisplayFormat.color = 0xFFFFFF;
scoreDisplayFormat.font = "Arial";
scoreDisplayFormat.align = "right";
scoreDisplayFormat.size = 15;
scoreDisplay.defaultTextFormat = scoreDisplayFormat;
scoreObjects.addChild(scoreDisplay);
updateScore();
}
// new score to show
public function updateScore() {
scoreDisplay.text = String(gameScore1);
}
// remove a ship icon
public function removeShipIcon() {
scoreObjects.removeChild(shipIcons.pop());
}
// remove a shield icon
public function removeShieldIcon() {
scoreObjects.removeChild(shieldIcons.pop());
}
// remove the rest of the ship icons
public function removeAllShipIcons() {
while (shipIcons.length > 0) {
removeShipIcon();
}
}
// remove the rest of the shield icons
public function removeAllShieldIcons() {
while (shieldIcons.length > 0) {
removeShieldIcon();
}
}
// SHIP CREATION AND MOVEMENT
// create a new ship
public function newShip(event:TimerEvent) {
// if ship exists, remove it
if (ship != null) {
gameObjects.removeChild(ship);
ship = null;
}
// no more ships
if (shipsLeft < 1) {
endGame();
return;
}
//upper scrore reached
if (gameScore1 >= 50) {
trace("high")
endGame();
return;
}
// create, position, and add new ship
ship = new Ship();
ship.gotoAndStop(1);
ship.x = 400;
ship.y = 350;
ship.rotation = -180;
ship.shield.visible = false;
gameObjects.addChild(ship);
// set up ship properties
shipMoveX = 0.0;
shipMoveY = 0.0;
gameMode = "play";
// set up shields
shieldsLeft = 3;
createShieldIcons();
// all lives but the first start with a free shield
if (shipsLeft != startingShips) {
startShield(true);
}
}
// register key presses
public function keyDownFunction(event:KeyboardEvent) {
if (event.keyCode == 38) {
leftArrow = true;
} else if (event.keyCode == 40) {
rightArrow = true;
} else if (event.keyCode == 32) { // space
newMissile();
} else if (event.keyCode == 37) { // left arrow
startShield(false);
}
}
// register key ups
public function keyUpFunction(event:KeyboardEvent) {
if (event.keyCode == 38) {
leftArrow = false;
} else if (event.keyCode == 40) {
rightArrow = false;
}
}
// animate ship
public function moveShip(timeDiff:uint) {
// rotate and thrust
// rotate and thrust
if (leftArrow) {
ship.y -= 2;
} else if (rightArrow) {
ship.y+= 2;
}
// move
ship.x += shipMoveX;
ship.y += shipMoveY;
// wrap around screen
if (ship.y < 65) ship.y = 65;
if (ship.y > 380) ship.y = 380;
}
// remove ship
public function shipHit() {
gameMode = "delay";
ship.gotoAndPlay("explode");
removeAllShieldIcons();
delayTimer = new Timer(1000,1);
delayTimer.addEventListener(TimerEvent.TIMER_COMPLETE,newShip);
delayTimer.start();
removeShipIcon();
shipsLeft--;
}
// turn on shield for 3 seconds
public function startShield(freeShield:Boolean) {
if (shieldsLeft < 1) return; // no shields left
if (shieldOn) return; // shield already on
// turn on shield and set timer to turn off
ship.shield.visible = true;
shieldTimer = new Timer(3000,1);
shieldTimer.addEventListener(TimerEvent.TIMER_COMPLETE,endShield);
shieldTimer.start();
// update shields remaining
if (!freeShield) {
removeShieldIcon();
shieldsLeft--;
}
shieldOn = true;
}
// turn off shield
public function endShield(event:TimerEvent) {
ship.shield.visible = false;
shieldOn = false;
}
// ROCKS
// create a single rock of a specific size
public function newRock(x,y:int, rockType:String) {
// create appropriate new class
var newRock:MovieClip;
var rockRadius:Number;
if (rockType == "Big") {
newRock = new Rock_Big();
rockRadius = 35;
} else if (rockType == "Medium") {
newRock = new Rock_Medium();
rockRadius = 30;
} else if (rockType == "Small") {
newRock = new Rock_Small();
rockRadius = 25;
}
// choose a random look
newRock.gotoAndStop(Math.ceil(Math.random()*3));
// set start position
newRock.x = Math.random()*0;
newRock.y = Math.random()*280+80;
// set random movement and rotation
var dx:Number = Math.random()*3;
var dy:Number = Math.random()*2;
// add to stage and to rocks list
gameObjects.addChild(newRock);
rocks.push({rock:newRock, dx:dx, dy:dy, rockType:rockType, rockRadius: rockRadius});
}
// create four rocks
public function nextRockWave(event:TimerEvent) {
rocks = new Array();
newRock(100,1,"Big");
newRock(200,1,"Big");
newRock(450,1,"Big");
newRock(350,1,"Big");
gameMode = "play";
}
// animate all rocks
public function moveRocks(timeDiff:uint) {
for(var i:int=rocks.length-1;i>=0;i--) {
// move the rocks
var rockSpeed:Number = rockSpeedStart + rockSpeedIncrease*gameLevel;
rocks[i].rock.x += rocks[i].dx*timeDiff*rockSpeed;
rocks[i].rock.y += 0
// wrap rocks
if ((rocks[i].rock.x) > 400){
deleteRocks(i);
}
else if ((rocks[i].rock.y) > 401){
deleteRocks(i);
}
}
}
public function rockHit(rockNum:uint) {
// create two smaller rocks
if (rocks[rockNum].rockType == "Big") {
newRock(rocks[rockNum].rock.x,rocks[rockNum].rock.y,"Medium");
newRock(rocks[rockNum].rock.x,rocks[rockNum].rock.y,"Medium");
} else if (rocks[rockNum].rockType == "Medium") {
newRock(rocks[rockNum].rock.x,rocks[rockNum].rock.y,"Small");
newRock(rocks[rockNum].rock.x,rocks[rockNum].rock.y,"Small");
}
// remove original rock
rocks[rockNum].rock.gotoAndPlay("bang");
//gameObjects.removeChild(rocks[rockNum].rock);
rocks.splice(rockNum,1);
}
public function deleteRocks(rockNum:uint) {
//remove rock from game
gameObjects.removeChild(rocks[rockNum].rock);
rocks.splice(rockNum,1);
}
// MISSILES
// create a new Missile
public function newMissile() {
// create
var newMissile:Missile = new Missile();
// set direction
newMissile.dx = Math.cos(Math.PI*ship.rotation/180);
newMissile.dy = Math.sin(Math.PI*ship.rotation/180);
// placement
newMissile.x = ship.x + newMissile.dx*shipRadius;
newMissile.y = ship.y + newMissile.dy*shipRadius;
// add to stage and array
gameObjects.addChild(newMissile);
missiles.push(newMissile);
}
// animate missiles
public function moveMissiles(timeDiff:uint) {
for(var i:int=missiles.length-1;i>=0;i--) {
// move
missiles[i].x += missiles[i].dx*missileSpeed*timeDiff;
missiles[i].y += missiles[i].dy*missileSpeed*timeDiff;
// moved off screen
if ((missiles[i].x < 0) || (missiles[i].x > 550) || (missiles[i].y < 0) || (missiles[i].y > 400)) {
gameObjects.removeChild(missiles[i]);
delete missiles[i];
missiles.splice(i,1);
}
}
}
// remove a missile
public function missileHit(missileNum:uint) {
gameObjects.removeChild(missiles[missileNum]);
missiles.splice(missileNum,1);
}
// GAME INTERACTION AND CONTROL
public function moveGameObjects(event:Event) {
// get timer difference and animate
var timePassed:uint = getTimer() - lastTime;
lastTime += timePassed;
moveRocks(timePassed);
if (gameMode != "delay") {
moveShip(timePassed);
}
moveMissiles(timePassed);
checkCollisions();
}
// look for missiles colliding with rocks
public function checkCollisions() {
// loop through rocks
rockloop: for(var j:int=rocks.length-1;j>=0;j--) {
// loop through missiles
missileloop: for(var i:int=missiles.length-1;i>=0;i--) {
// collision detection
if (Point.distance(new Point(rocks[j].rock.x,rocks[j].rock.y),
new Point(missiles[i].x,missiles[i].y))
< rocks[j].rockRadius) {
// remove rock and missile
rockHit(j);
missileHit(i);
// add score
gameScore1 += 10;
updateScore();
// break out of this loop and continue next one
continue rockloop;
}
}
// check for rock hitting ship
if (gameMode == "play") {
if (shieldOn == false) { // only if shield is off
if (Point.distance(new Point(rocks[j].rock.x,rocks[j].rock.y),
new Point(ship.x,ship.y))
< rocks[j].rockRadius+shipRadius) {
// remove ship and rock
shipHit();
rockHit(j);
}
}
}
}
if (gameScore1 >= 50) {
shipsLeft = 0;
if (shipsLeft < 1) {
endGame();
return;
}
}
// all out of rocks, change game mode and trigger more
if ((rocks.length == 0) && (gameMode == "play")) {
gameMode = "betweenlevels";
gameLevel++; // advance a level
delayTimer = new Timer(2000,1);
delayTimer.addEventListener(TimerEvent.TIMER_COMPLETE,nextRockWave);
delayTimer.start();
}
}
public function endGame() {
// remove all objects and listeners
removeChild(gameObjects);
removeChild(scoreObjects);
gameObjects = null;
scoreObjects = null;
removeEventListener(Event.ENTER_FRAME,moveGameObjects);
stage.removeEventListener(KeyboardEvent.KEY_DOWN,keyDownFunction);
stage.removeEventListener(KeyboardEvent.KEY_UP,keyUpFunction);
gotoAndStop("gameover");
}
}
}

User interaction with Leapmotion AS3 library

I can connect the device and attach a custom cursor to one finger, but I can´t use any of the gestures to over/click a button or drag a sprite around, etc.
I´m using Starling in the project. To run this sample just create a Main.as, setup it with Starling and call this class.
My basic code:
package
{
import com.leapmotion.leap.Controller;
import com.leapmotion.leap.events.LeapEvent;
import com.leapmotion.leap.Finger;
import com.leapmotion.leap.Frame;
import com.leapmotion.leap.Gesture;
import com.leapmotion.leap.Hand;
import com.leapmotion.leap.InteractionBox;
import com.leapmotion.leap.Pointable;
import com.leapmotion.leap.ScreenTapGesture;
import com.leapmotion.leap.Vector3;
import starling.display.Shape;
import starling.display.Sprite;
import starling.events.Event;
import starling.events.TouchEvent;
/**
* ...
* #author miau
*/
public class LeapController extends Sprite
{
private var _controller:Controller;
private var _cursor:Shape;
private var _screenTap:ScreenTapGesture;
private var _displayWidth:uint = 800;
private var _displayHeight:uint = 600;
public function LeapController()
{
addEventListener(Event.ADDED_TO_STAGE, _startController);
}
private function _startController(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, _startController);
//adding controller
_controller = new Controller();
_controller.addEventListener( LeapEvent.LEAPMOTION_INIT, onInit );
_controller.addEventListener( LeapEvent.LEAPMOTION_CONNECTED, onConnect );
_controller.addEventListener( LeapEvent.LEAPMOTION_DISCONNECTED, onDisconnect );
_controller.addEventListener( LeapEvent.LEAPMOTION_EXIT, onExit );
_controller.addEventListener( LeapEvent.LEAPMOTION_FRAME, onFrame );
//add test button
_testButton.x = stage.stageWidth / 2 - _testButton.width / 2;
_testButton.y = stage.stageHeight / 2 - _testButton.height / 2;
addChild(_testButton);
_testButton.touchable = true;
_testButton.addEventListener(TouchEvent.TOUCH, doSomething);
//draw ellipse as a cursor
_cursor = new Shape();
_cursor.graphics.lineStyle(6, 0xFFE24F);
_cursor.graphics.drawEllipse(0, 0, 80, 80);
addChild(_cursor);
}
private function onFrame(e:LeapEvent):void
{
trace("ON FRAME STARTED");
var frame:Frame = e.frame;
var interactionBox:InteractionBox = frame.interactionBox;
// Get the first hand
if(frame.hands.length > 0){
var hand:Hand = frame.hands[0];
var numpointables:int = e.frame.pointables.length;
var pointablesArray:Array = new Array();
if(frame.pointables.length > 0 && frame.pointables.length < 2){
//trace("number of pointables: "+frame.pointables[0]);
for(var j:int = 0; j < frame.pointables.length; j++){
//var pointer:DisplayObject = pointablesArray[j];
if(j < numpointables){
var pointable:Pointable = frame.pointables[j];
var normal:Vector3 = pointable.tipPosition;
var normalized:Vector3 = interactionBox.normalizePoint(normal);
//pointable.isFinger = true;
_cursor.x = normalized.x * _displayWidth;
_cursor.y = _displayHeight - (normalized.y * _displayHeight);
_cursor.visible = true;
}else if (j == 0) {
_cursor.visible = false;
}
}
}
}
}
private function onExit(e:LeapEvent):void
{
trace("ON EXIT STARTED");
}
private function onDisconnect(e:LeapEvent):void
{
trace("ON DISCONNECT STARTED");
}
private function onConnect(e:LeapEvent):void
{
trace("ON CONNECT STARTED");
_controller.enableGesture( Gesture.TYPE_SWIPE );
_controller.enableGesture( Gesture.TYPE_CIRCLE );
_controller.enableGesture( Gesture.TYPE_SCREEN_TAP );
_controller.enableGesture( Gesture.TYPE_KEY_TAP );
}
private function onInit(e:LeapEvent):void
{
trace("ON INIT STARTED");
}
private function doSomething(e:TouchEvent):void
{
trace("I WAS TOUCHED!!!");
}
}
}
If a good code Samaritan can update this code to perform a screen tap gesture (or any interacion with any object), I will really appreciate this a lot.
Regards!
controller.enableGesture(Gesture.TYPE_SWIPE);
controller.enableGesture(Gesture.TYPE_SCREEN_TAP);
if(controller.config().setFloat("Gesture.Swipe.MinLength", 200.0) && controller.config().setFloat("Gesture.Swipe.MinVelocity", 500)) controller.config().save();
if(controller.config().setFloat("Gesture.ScreenTap.MinForwardVelocity", 30.0) && controller.config().setFloat("Gesture.ScreenTap.HistorySeconds", .5) && controller.config().setFloat("Gesture.ScreenTap.MinDistance", 1.0)) controller.config().save();
//etc...
Then catch it in the frame event listener:
private function onFrame( event:LeapEvent ):void
{
var frame:Frame = event.frame;
var gestures:Vector.<Gesture> = frame.gestures();
for ( var i:int = 0; i < gestures.length; i++ )
{
var gesture:Gesture = gestures[ i ];
switch ( gesture.type )
{
case Gesture.TYPE_SCREEN_TAP:
var screentap:ScreenTapGesture = ScreenTapGesture ( gesture);
trace ("ScreenTapGesture-> x: " + Math.round(screentap.position.x ) + ", y: "+ Math.round( screentap.position.y));
break;
case Gesture.TYPE_SWIPE:
var screenSwipe:SwipeGesture = SwipeGesture(gesture);
if(gesture.state == Gesture.STATE_START) {
//
}
else if(gesture.state == Gesture.STATE_STOP) {
//
trace("SwipeGesture-> direction: "+screenSwipe.direction + ", duration: " + screenSwipe.duration);
}
break;
default:
trace( "Unknown gesture type." )
}
}
}
When the event occurs, check the coordinates translated to the stage/screen and whether a hit test returns true.
EDIT: Considering I have no idea how to reliable get the touch point x/y (or better: how to translate them to the correct screen coordinates), I would probably do something like this in my onFrame event:
private function onFrame(event:LeapEvent):void {
var frame:Frame = event.frame;
var gestures:Vector.<Gesture> = frame.gestures();
var posX:Number;
var posY:Number;
var s:Shape;
if(frame.pointables.length > 0) {
var currentVector:Vector3 = screen.intersectPointable(frame.pointables[0], true); //get normalized vector
posX = 1920 * currentVector.x - stage.x; //NOTE: I hardcoded the screen res value, you can get it like var w:int = leap.locatedScreens()[0].widthPixels();
posY = 1080 * ( 1 - currentVector.y ) - stage.y; //NOTE: I hardcoded the screen res value, you can get it like var h:int = leap.locatedScreens()[0].heightPixels();
}
for(var i:int = 0; i < gestures.length; i++) {
var gesture:Gesture = gestures[i];
if(gesture.type == Gesture.TYPE_SCREEN_TAP) {
if(posX >= _button1.x &&
posX <= _button1.x + _button1.width &&
posY >= _button1.y &&
posY <= _button1.y + _button1.height) {
s = new Shape();
s.graphics.beginFill(0x00FF00);
s.graphics.drawCircle(0, 0, 10);
s.graphics.endFill();
s.x = posX;
s.y = posY;
stage.addChild(s);
trace("Lisa tocada!");
}
else {
s = new Shape();
s.graphics.beginFill(0xFF0000);
s.graphics.drawCircle(0, 0, 10);
s.graphics.endFill();
s.x = posX;
s.y = posY;
stage.addChild(s);
trace("Fallaste! Intentalo otra vez, tiempo: "+new Date().getTime());
}
}
}
}

catcher game lives won't update as3.0

I am trying to create a simple catcher game. I have the basic structure/logic figured out but I am facing some problems. For some reason the lives are not updating as I want them to. The only time they actually do work is when a "good" crane exits the screen at the top, then they decrease by one. But other than that (catch a "bad" crane or catch a "plus" crane) is not decreasing or increasing it by one. Similarly, the score seems to work for the "good" crane, adding the amount of score I specify, but not for the "bad" or the "plus" cranes.
What am I missing? Help!
package
{
import flash.display.*;
import flash.events.*;
import flash.text.*;
import flash.utils.*;
public class CatchingCranes extends MovieClip
{
//Define the variables
var catcher:CloudCatcher;
var nextCrane:Timer;
var objects:Array = new Array();
var score:int = 0;
var timer:Number;
var maxCount:Number = 60;
var totalLives:int = 5;
var CirclesArray:Array = [];
var spacer:int = 5;
var startPosition:int = 415;
var speed:Number = -7.0;
public function CatchingCranes()
{
createTimer();
createCatcher();
setNextCrane();
progressLevels();
addEventListener(Event.ENTER_FRAME, moveCranes);
}
//Function to indicate level progression
public function progressLevels()
{
status_mc.status_txt.text = "LEVEL ONE";
status_mc.instructions_txt.text = "COLLECT AT LEAST 500 POINTS";
if (score == 500)
{
status_mc.status_txt.text = "LEVEL TWO";
status_mc.instructions_txt.text = "COLLECT AT LEAST 750 POINTS";
goToLevelTwo();
}
if (score == 750)
{
status_mc.status_txt.text = "LEVEL THREE";
status_mc.instructions_txt.text = "COLLECT AT LEAST 1000 POINTS";
goToLevelThree();
}
if (score == 1000)
{
status_mc.status_txt.text = "CONGRATULATIONS";
status_mc.instructions_txt.text = "YOU NOW HAVE ONE WISH TO MAKE";
goToWin();
}
if (totalLives == 0)
{
status_mc.status_txt.text = "GAME OVER";
status_mc.instructions_txt.text = "CLICK TO TRY AGAIN";
goToLoose();
}
}
//Function to create a timer
public function createTimer()
{
var myTimer:Timer = new Timer(1000,maxCount);
myTimer.addEventListener(TimerEvent.TIMER, countdown);
myTimer.start();
function countdown(event:TimerEvent):void
{
timer = (maxCount)-myTimer.currentCount;
timer_txt.text = "TIME LEFT: " + String(timer);
if (timer <= 0)
{
trace("Time's Up");
myTimer.removeEventListener(TimerEvent.TIMER, countdown);
}
}
}
//Function to create the catcher
public function createCatcher()
{
catcher = new CloudCatcher();
catcher.y = 50;
catcher.x = 350;
addChild(catcher);
}
//Function to initiate the next crane production
public function setNextCrane()
{
nextCrane = new Timer(750+Math.random()*1000,1);
nextCrane.addEventListener(TimerEvent.TIMER_COMPLETE, newCrane);
nextCrane.start();
}
//Function to create a new crane
public function newCrane(event:Event)
{
//Array definition holding different kinds of cranes
var goodCranes:Array = ["ColorCrane1","ColorCrane2","ColorCrane3","ColorCrane4","ColorCrane5"];
var evilCranes:Array = ["EvilCrane"];
var silverCranes:Array = ["SilverCrane"];
var goldCranes:Array = ["GoldCrane"];
//Create a random number and check whether or not it is less than 0.9 (90 percent probability)
if (Math.random() < 0.9)
{
//Create good cranes
var r:int = Math.floor(Math.random() * goodCranes.length);
var classRef:Class = getDefinitionByName(goodCranes[r]) as Class;
var newCrane:MovieClip = new classRef();
newCrane.typestr = "good";
}
else
{
//Create a random number and check whether or not it is more than 0.9 (10 percent probability)
//Check to see if the current lives count is less than or equal to four, if it is
if (totalLives <= 4)
{
//Create cranes that provide user with an additional life
var p:int = Math.floor(Math.random() * silverCranes.length);
classRef = getDefinitionByName(silverCranes[p]) as Class;
newCrane = new classRef();
newCrane.typstr = "plus";
//Create cranes that are evil
var s:int = Math.floor(Math.random() * evilCranes.length);
classRef = getDefinitionByName(evilCranes[s]) as Class;
newCrane = new classRef();
newCrane.typstr = "bad";
}
else
{
//If lives are equal to five, only create the evil cranes
r = Math.floor(Math.random() * evilCranes.length);
classRef = getDefinitionByName(evilCranes[r]) as Class;
newCrane = new classRef();
newCrane.typstr = "bad";
}
}
//Specify the x and y location of the cranes
newCrane.x = Math.random() * 700;
newCrane.y = 500;
//Add crane
addChildAt(newCrane, 0);
objects.push(newCrane);
setNextCrane();
}
//Function to move the cranes up the stage
public function moveCranes(event:Event)
{
for (var i:int = objects.length-1; i>=0; i--)
{
//Make the catcher follow the position of the mouse
catcher.x = mouseX;
//Specify the crane's speed
objects[i].y += speed;
//If the object exits the top stage boundaries
if (objects[i].y < 0)
{
//Remove the child and take it out of the array
removeChild(objects[i]);
objects.splice(i,1);
//If that object is good
if (objects[i].typestr == "good")
{
//Remove one life from the user
totalLives = totalLives - 1;
trace(totalLives);
}
}
//Check to see if the crane collides with the cloud, if it does
if (objects[i].hitTestObject(catcher))
{
//And the crane is good
if (objects[i].typestr == "good")
{
//Add 25 to the score
score += 25;
}
//And the crane adds a life
if (objects[i].typestr == "plus")
{
//Add 10 to the score and increase lives by one
score += 10;
totalLives = totalLives + 1;
}
//And the crane is evil
if (objects[i].typestr == "bad")
{
//Take out 5 from the score and remove a life
score -= 5;
totalLives = totalLives - 1;
}
//If the score is less than zero, take it back to zero
if (score < 0)
{
score = 0;
}
//Remove the cranes and splice them from the array
removeChild(objects[i]);
objects.splice(i,1);
}
}
//Update the score display text and the lives with the correct values
score_display.text = "Score = " + score;
lives_txt.text = "Lives: " + totalLives;
}
//Functions to specify next level options and win/loose scenarios
function goToLevelTwo():void
{
}
function goToLevelThree():void
{
}
function goToWin():void
{
}
function goToLoose():void
{
}
}
}

AS3 - Game Timer not calculating start time properly

I'm building a game in AS3 based off of Gary Rosenzweig's latest Actionscript 3 book. It has a game timer issue, not just mine but his demo too, that I can't figure out.
The game is like Asteroids where four rocks are placed in the corners of the stage at the beginning and then start moving randomly around the stage. The problem is the timer used is started the moment that the flash file starts not the moment the player clicks the start button. So if you are on the start screen for 5 seconds before you click play when the game actually begins the rocks are where they would be after 5 seconds of play, which could be right over the player.
I've posted the parts of the code that I think apply. Could someone please tell me how to modify this so that when the player actually starts the game the rocks start in their proper places. I'm pretty sure it's the last function that I've included that is the problem but I've included other related parts to give you a more complete picture.
package {
import flash.display.*;
import flash.events.*;
import flash.events.TouchEvent;
import flash.ui.Multitouch;
import flash.ui.MultitouchInputMode;
import flash.text.*;
import flash.utils.getTimer;
import flash.utils.Timer;
import flash.geom.Point;
import flash.net.SharedObject;
import flash.media.Sound;
import flash.media.SoundMixer;
import flash.media.SoundTransform;
import flash.media.SoundChannel;
Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT;
public class VirusDefender extends MovieClip {
static const shipRotationSpeed:Number = .1;
static const rockSpeedStart:Number = .03;
static const rockSpeedIncrease:Number = .01;
static const missileSpeed:Number = .2;
static const thrustPower:Number = .15;
static const shipRadius:Number = 20;
static const startingShips:uint = 3;
// game objects
private var ship:Ship;
private var rocks:Array;
private var missiles:Array;
// animation timer
private var lastTime:uint;
// arrow keys
private var rightArrow:Boolean = false;
private var leftArrow:Boolean = false;
private var upArrow:Boolean = false;
// ship velocity
private var shipMoveX:Number;
private var shipMoveY:Number;
// timers
private var delayTimer:Timer;
private var shieldTimer:Timer;
// game mode
private var gameMode:String;
private var shieldOn:Boolean;
// ships and shields
private var shipsLeft:uint;
private var shieldsLeft:uint;
private var shipIcons:Array;
private var shieldIcons:Array;
private var scoreDisplay:TextField;
// score and level
private var gameScore:Number;
private var gameLevel:uint;
// sprites
private var gameObjects:Sprite;
private var scoreObjects:Sprite;
var gameBackground:GameBackground = new GameBackground();
// sounds
var sndFire:fire_sound;
var sndFireChannel:SoundChannel;
var sndThruster:thruster_sound;
var sndThrusterChannel:SoundChannel;
var sndShield:shield_sound;
var sndShieldChannel:SoundChannel;
var sndExplosion:explosion_sound;
var sndExplosionChannel:SoundChannel;
var sndBubble:bubble_sound;
var sndBubbleChannel:SoundChannel;
// start the game
public function startSpaceRocks() {
// set up sprites
addChild(gameBackground);
setChildIndex(gameBackground,0); // I added this
gameObjects = new Sprite();
addChild(gameObjects);
scoreObjects = new Sprite();
addChild(scoreObjects);
// reset score objects
gameLevel = 1;
shipsLeft = startingShips;
gameScore = 0;
createShipIcons();
createScoreDisplay();
// set up listeners
trace("add moveGameObjects event listener");
addEventListener(Event.ENTER_FRAME,moveGameObjects);
leftButton.addEventListener(TouchEvent.TOUCH_OVER,leftPress);
leftButton.addEventListener(TouchEvent.TOUCH_OUT,leftRelease);
rightButton.addEventListener(TouchEvent.TOUCH_OVER,rightPress);
rightButton.addEventListener(TouchEvent.TOUCH_OUT,rightRelease);
thrusterButton.addEventListener(TouchEvent.TOUCH_OVER,thrusterPress);
thrusterButton.addEventListener(TouchEvent.TOUCH_OUT,thrusterRelease);
shieldButton.addEventListener(TouchEvent.TOUCH_OVER,shieldPress);
fireButton.addEventListener(TouchEvent.TOUCH_OVER,firePress);
// Left Button
function leftPress(event:TouchEvent):void{
leftArrow = true;
}
function leftRelease(event:TouchEvent):void{
leftArrow = false;
}
// Right button
function rightPress(event:TouchEvent):void{
rightArrow = true;
}
function rightRelease(event:TouchEvent):void{
rightArrow = false;
}
// Thruster button
function thrusterPress(event:TouchEvent):void{
sndThruster=new thruster_sound();
sndThrusterChannel=sndThruster.play();
upArrow = true;
if (gameMode == "play") ship.gotoAndStop(2);
}
function thrusterRelease(event:TouchEvent):void{
sndThrusterChannel.stop();
upArrow = false;
if (gameMode == "play") ship.gotoAndStop(1);
}
// Fire button
function firePress(event:TouchEvent):void{
sndFire=new fire_sound();
sndFireChannel=sndFire.play();
newMissile();
}
// Shield button
function shieldPress(event:TouchEvent):void{
startShield(false);
}
// start
gameMode = "delay";
trace("gameMode - delay");
shieldOn = false;
missiles = new Array();
trace("nextRockWave fired");
nextRockWave(null);
newShip(null);
}
// SCORE OBJECTS
// draw number of ships left
public function createShipIcons() {
shipIcons = new Array();
for(var i:uint=0;i<shipsLeft;i++) {
var newShip:ShipIcon = new ShipIcon();
newShip.x = 165+i*25; //165
newShip.y = 273; //273
scoreObjects.addChild(newShip);
shipIcons.push(newShip);
}
}
// draw number of shields left
public function createShieldIcons() {
shieldIcons = new Array();
for(var i:uint=0;i<shieldsLeft;i++) {
var newShield:ShieldIcon = new ShieldIcon();
newShield.x = 310-i*25; //530
newShield.y = 273; //15
scoreObjects.addChild(newShield);
shieldIcons.push(newShield);
}
}
// put the numerical score at the upper right
public function createScoreDisplay() {
updateScore();
}
// new score to show
public function updateScore() {
score.text = addCommaInNumber(gameScore);
}
// remove a ship icon
public function removeShipIcon() {
scoreObjects.removeChild(shipIcons.pop());
}
// remove a shield icon
public function removeShieldIcon() {
scoreObjects.removeChild(shieldIcons.pop());
}
// remove the rest of the ship icons
public function removeAllShipIcons() {
while (shipIcons.length > 0) {
removeShipIcon();
}
}
// remove the rest of the shield icons
public function removeAllShieldIcons() {
while (shieldIcons.length > 0) {
removeShieldIcon();
}
}
// SHIP CREATION AND MOVEMENT
// create a new ship
public function newShip(event:TimerEvent) {
// if ship exists, remove it
if (ship != null) {
gameObjects.removeChild(ship);
ship = null;
}
// no more ships
if (shipsLeft < 1) {
endGame();
return;
}
// create, position, and add new ship
ship = new Ship();
ship.gotoAndStop(1);
ship.x = 240; //275
ship.y = 160; //200
ship.rotation = -90;
ship.shield.visible = false;
gameObjects.addChild(ship);
// set up ship properties
shipMoveX = 0.0;
shipMoveY = 0.0;
gameMode = "play";
// set up shields
shieldsLeft = 3;
createShieldIcons();
// all lives but the first start with a free shield
if (shipsLeft != startingShips) {
startShield(true);
sndShield=new shield_sound();
sndShieldChannel=sndShield.play();
}
}
// animate ship
public function moveShip(timeDiff:uint) {
// rotate and thrust
if (leftArrow) {
ship.rotation -= shipRotationSpeed*timeDiff;
} else if (rightArrow) {
ship.rotation += shipRotationSpeed*timeDiff;
} else if (upArrow) {
shipMoveX += Math.cos(Math.PI*ship.rotation/180)*thrustPower;
shipMoveY += Math.sin(Math.PI*ship.rotation/180)*thrustPower;
}
// move
ship.x += shipMoveX;
ship.y += shipMoveY;
// wrap around screen
if ((shipMoveX > 0) && (ship.x > 470)) {
ship.x -= 490;
}
if ((shipMoveX < 0) && (ship.x < -20)) {
ship.x += 500;
}
if ((shipMoveY > 0) && (ship.y > 320)) {
ship.y -= 340;
}
if ((shipMoveY < 0) && (ship.y < -20)) {
ship.y += 340;
}
}
// remove ship
public function shipHit() {
gameMode = "delay";
ship.gotoAndPlay("explode");
sndExplosion=new explosion_sound();
sndExplosionChannel=sndExplosion.play();
removeAllShieldIcons();
delayTimer = new Timer(2000,1);
delayTimer.addEventListener(TimerEvent.TIMER_COMPLETE,newShip);
delayTimer.start();
removeShipIcon();
shipsLeft--;
}
// turn on shield for 3 seconds
public function startShield(freeShield:Boolean) {
if (shieldsLeft < 1) return; // no shields left
if (shieldOn) return; // shield already on
// turn on shield and set timer to turn off
ship.shield.visible = true;
sndShield=new shield_sound();
sndShieldChannel=sndShield.play();
shieldTimer = new Timer(3000,1);
shieldTimer.addEventListener(TimerEvent.TIMER_COMPLETE,endShield);
shieldTimer.start();
// update shields remaining
if (!freeShield) {
removeShieldIcon();
shieldsLeft--;
}
shieldOn = true;
}
// turn off shield
public function endShield(event:TimerEvent) {
ship.shield.visible = false;
shieldOn = false;
}
// ROCKS
// create a single rock of a specific size
public function newRock(x,y:int, rockType:String) {
trace("newRock fired");
// create appropriate new class
var newRock:MovieClip;
var rockRadius:Number;
if (rockType == "Big") {
newRock = new Rock_Big();
rockRadius = 35;
} else if (rockType == "Medium") {
newRock = new Rock_Medium();
rockRadius = 20;
} else if (rockType == "Small") {
newRock = new Rock_Small();
rockRadius = 10;
}
// choose a random look
newRock.gotoAndStop(Math.ceil(Math.random()*3));
// set start position
newRock.x = x;
newRock.y = y;
// set random movement and rotation
var dx:Number = Math.random()*2.0-1.0;
var dy:Number = Math.random()*2.0-1.0;
var dr:Number = Math.random();
// add to stage and to rocks list
gameObjects.addChild(newRock);
setChildIndex(gameObjects,1); // I added this
rocks.push({rock:newRock, dx:dx, dy:dy, dr:dr, rockType:rockType, rockRadius: rockRadius});
}
// create four rocks
public function nextRockWave(event:TimerEvent) {
rocks = new Array();
newRock(30,30,"Big"); //100 100
newRock(30,290,"Big"); // 100 300
newRock(450,30,"Big"); // 450 100
newRock(450,290,"Big"); // 450 300
gameMode = "play";
}
// animate all rocks
public function moveRocks(timeDiff:uint) {
for(var i:int=rocks.length-1;i>=0;i--) {
// move the rocks
var rockSpeed:Number = rockSpeedStart + rockSpeedIncrease*gameLevel;
rocks[i].rock.x += rocks[i].dx*timeDiff*rockSpeed;
rocks[i].rock.y += rocks[i].dy*timeDiff*rockSpeed;
// rotate rocks
rocks[i].rock.rotation += rocks[i].dr*timeDiff*rockSpeed;
// wrap rocks
if ((rocks[i].dx > 0) && (rocks[i].rock.x > 470)) {
rocks[i].rock.x -= 490;
}
if ((rocks[i].dx < 0) && (rocks[i].rock.x < -20)) {
rocks[i].rock.x += 490;
}
if ((rocks[i].dy > 0) && (rocks[i].rock.y > 325)) {
rocks[i].rock.y -= 345;
}
if ((rocks[i].dy < 0) && (rocks[i].rock.y < -25)) {
rocks[i].rock.y += 345;
}
}
}
public function rockHit(rockNum:uint) {
// create two smaller rocks
sndBubble=new bubble_sound();
sndBubbleChannel=sndBubble.play();
if (rocks[rockNum].rockType == "Big") {
newRock(rocks[rockNum].rock.x,rocks[rockNum].rock.y,"Medium");
newRock(rocks[rockNum].rock.x,rocks[rockNum].rock.y,"Medium");
} else if (rocks[rockNum].rockType == "Medium") {
newRock(rocks[rockNum].rock.x,rocks[rockNum].rock.y,"Small");
newRock(rocks[rockNum].rock.x,rocks[rockNum].rock.y,"Small");
}
// remove original rock
gameObjects.removeChild(rocks[rockNum].rock);
rocks.splice(rockNum,1);
}
// MISSILES
// create a new Missile
public function newMissile() {
// create
var newMissile:Missile = new Missile();
// set direction
newMissile.dx = Math.cos(Math.PI*ship.rotation/180);
newMissile.dy = Math.sin(Math.PI*ship.rotation/180);
// placement
newMissile.x = ship.x + newMissile.dx*shipRadius;
newMissile.y = ship.y + newMissile.dy*shipRadius;
// add to stage and array
gameObjects.addChild(newMissile);
missiles.push(newMissile);
}
// animate missiles
public function moveMissiles(timeDiff:uint) {
for(var i:int=missiles.length-1;i>=0;i--) {
// move
missiles[i].x += missiles[i].dx*missileSpeed*timeDiff;
missiles[i].y += missiles[i].dy*missileSpeed*timeDiff;
// moved off screen
if ((missiles[i].x < 0) || (missiles[i].x > 485) || (missiles[i].y < 0) || (missiles[i].y > 325)) {
gameObjects.removeChild(missiles[i]);
delete missiles[i];
missiles.splice(i,1);
}
}
}
// remove a missile
public function missileHit(missileNum:uint) {
gameObjects.removeChild(missiles[missileNum]);
missiles.splice(missileNum,1);
}
// GAME INTERACTION AND CONTROL
public function moveGameObjects(event:Event) {
// get timer difference and animate
var timePassed:uint = getTimer() - lastTime;
lastTime += timePassed;
moveRocks(timePassed);
if (gameMode != "delay") {
moveShip(timePassed);
}
moveMissiles(timePassed);
checkCollisions();
}
// look for missiles colliding with rocks
public function checkCollisions() {
// loop through rocks
rockloop: for(var j:int=rocks.length-1;j>=0;j--) {
// loop through missiles
missileloop: for(var i:int=missiles.length-1;i>=0;i--) {
// collision detection
if (Point.distance(new Point(rocks[j].rock.x,rocks[j].rock.y),
new Point(missiles[i].x,missiles[i].y))
< rocks[j].rockRadius) {
// remove rock and missile
rockHit(j);
missileHit(i);
// add score
gameScore += 10;
updateScore();
// break out of this loop and continue next one
continue rockloop;
}
}
// check for rock hitting ship
if (gameMode == "play") {
if (shieldOn == false) { // only if shield is off
if (Point.distance(new Point(rocks[j].rock.x,rocks[j].rock.y),
new Point(ship.x,ship.y))
< rocks[j].rockRadius+shipRadius) {
// remove ship and rock
shipHit();
rockHit(j);
}
}
}
}
// all out of rocks, change game mode and trigger more
if ((rocks.length == 0) && (gameMode == "play")) {
gameMode = "betweenlevels";
gameLevel++; // advance a level
levelTextBox.text = "Infection: " + gameLevel;
delayTimer = new Timer(2000,1);
delayTimer.addEventListener(TimerEvent.TIMER_COMPLETE,nextRockWave);
delayTimer.start();
}
}
public function endGame() {
// remove all objects and listeners
removeChild(gameObjects);
removeChild(scoreObjects);
removeChild(gameBackground);
gameObjects = null;
scoreObjects = null;
removeEventListener(Event.ENTER_FRAME,moveGameObjects);
gameMode = "gameOver";
gotoAndStop("gameover");
}
/***** ADD COMMAS TO NUMBERS *******/
function addCommaInNumber (number : Number) : String
{
var integer : String = "" ;
var fraction : String = "" ;
var string : String = number.toString();
var array : Array = string.split(".");
var regex : RegExp = /(\d+)(\d{3})/;
integer = array[0];
while( regex.test(integer) )
{
integer = integer.replace(regex,'$1' + ',' + '$2');
}
if (array[1])
{ fraction = integer.length > 0 ? '.' + array[1] : ''; }
return integer + fraction;
}
}
}
The part of code you thought applied to your problem is incorrect.
A timer can be started along with it's declaration as :
private var myTimer:Timer = new Timer(delay, repeat);
But since you are not initiating the timer at the time of declaration (as seen in you snippet)
// timers
private var delayTimer:Timer;
private var shieldTimer:Timer;
There must be some other function where it would be initiated. Move the action of initiating the timer to whichever place you want to start the timer. For eg : into startspacerocks() function
If that is not the problem, please post the relevant code that applies to your problem.
EDIT:
Well I think your answer lies in the moveGameObjects function.
Try modifying the function as follows:
// GAME INTERACTION AND CONTROL
public function moveGameObjects(event:Event) {
//Current Time
var currentTime:uint = getTimer();
//Initiate lastTime
if(lastTime == 0) lastTime = currentTime;
// get timer difference and animate
var timePassed:uint = currentTime - lastTime;
lastTime += timePassed;
moveRocks(timePassed);
if (gameMode != "delay") {
moveShip(timePassed);
}
moveMissiles(timePassed);
checkCollisions();
}
From the code you've posted, I can't answer your question safely, but you should check, when startSpaceRocks() is called the first time. This should be in the click handler of your start button.
Beside that, your question title does not reflect the problem. There is no problem with a timer at all, there is a problem, when the "timer" is started.