0
votes

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;
    }


}

}

2

2 Answers

1
votes

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.

1
votes

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();
  }