views:

222

answers:

1

This is the strangest problem I've faced in flash so far. I have no idea what's causing it. I can provide a .swf if someone wants to actually see it, but I'll describe it as best I can.

I'm creating bullets for a tank object to shoot. The tank is a child of the document class. The way I am creating the bullet is:

var bullet:Bullet = new Bullet();
(parent as MovieClip).addChild(bullet);

The bullet itself simply moves itself in a direction using code like this.x += 5;

The problem is the bullets will trace for their creation and destruction at the correct times, however the bullet is sometimes not visible until half way across the screen, sometimes not at all, and sometimes for the whole traversal. Oddly removing the timer I have on bullet creation seems to solve this.

The timer is implemented as such:

if(shot_timer == 0) {
shoot(); // This contains the aforementioned bullet creation method
shot_timer = 10;

My enter frame handler for the tank object controls the timer and decrements it every frame if it is greater than zero.

Can anyone suggest why this could be happening?

EDIT: As requested, full code:

Bullet.as

package {

import flash.display.MovieClip; import flash.events.Event;

public class Bullet extends MovieClip {

public var facing:int;
private var speed:int;

public function Bullet():void {
    trace("created");
    speed = 10;
    addEventListener(Event.ADDED_TO_STAGE,addedHandler);
}

private function addedHandler(e:Event):void {
    addEventListener(Event.ENTER_FRAME,enterFrameHandler);
    removeEventListener(Event.ADDED_TO_STAGE,addedHandler);
}

private function enterFrameHandler(e:Event):void {
    //0 - up, 1 - left, 2 - down, 3 - right
    if(this.x > 720 || this.x < 0 || this.y < 0 || this.y > 480) {
        removeEventListener(Event.ENTER_FRAME,enterFrameHandler);
        trace("destroyed");
        (parent as MovieClip).removeChild(this);
        return;
    }

    switch(facing) {
        case 0: this.y -= speed; break;
        case 1: this.x -= speed; break;
        case 2: this.y += speed; break;
        case 3: this.x += speed; break;
    }
}

}

}

Tank.as:

package {

import flash.display.MovieClip; import flash.events.KeyboardEvent; import flash.events.Event; import flash.ui.Keyboard;

public class Tank extends MovieClip {

private var right:Boolean = false;
private var left:Boolean = false;
private var up:Boolean = false;
private var down:Boolean = false;
private var facing:int = 0; //0 - up, 1 - left, 2 - down, 3 - right
private var horAllowed:Boolean = true;
private var vertAllowed:Boolean = true;
private const GRID_SIZE:int = 100;
private var shooting:Boolean = false;
private var shot_timer:int = 0;

private var speed:int = 2;

public function Tank():void {
    addEventListener(Event.ADDED_TO_STAGE,stageAddHandler);
    addEventListener(Event.ENTER_FRAME, enterFrameHandler);
}

private function stageAddHandler(e:Event):void {
    stage.addEventListener(KeyboardEvent.KEY_DOWN,checkKeys);
    stage.addEventListener(KeyboardEvent.KEY_UP,keyUps);
    removeEventListener(Event.ADDED_TO_STAGE,stageAddHandler);
}

public function checkKeys(event:KeyboardEvent):void {
    if(event.keyCode == 32) {
        //trace("Spacebar is down");
        shooting = true;
    }
    if(event.keyCode == 39) {
        //trace("Right key is down");
        right = true;
    }
    if(event.keyCode == 38) {
        //trace("Up key is down");  // lol
        up = true;
    }
    if(event.keyCode == 37) {
        //trace("Left key is down");
        left = true;
    }
    if(event.keyCode == 40) {
        //trace("Down key is down");
        down = true;
    }
}

public function keyUps(event:KeyboardEvent):void {
    if(event.keyCode == 32) {
        event.keyCode = 0;
        shooting = false;
        //trace("Spacebar is not down");
    }
    if(event.keyCode == 39) {
        event.keyCode = 0;
        right = false;
        //trace("Right key is not down");
    }
    if(event.keyCode == 38) {
        event.keyCode = 0;
        up = false;
        //trace("Up key is not down");
    }
    if(event.keyCode == 37) {
        event.keyCode = 0;
        left = false;
        //trace("Left key is not down");
    }
    if(event.keyCode == 40) {
        event.keyCode = 0;
        down = false;
        //trace("Down key is not down") // O.o
    }
}

public function checkDirectionPermissions(): void {
    if(this.y % GRID_SIZE < 5 || GRID_SIZE - this.y % GRID_SIZE < 5) {
        horAllowed = true;
    } else {
        horAllowed = false;
    }
    if(this.x % GRID_SIZE < 5 || GRID_SIZE - this.x % GRID_SIZE < 5) {
        vertAllowed = true;
    } else {
        vertAllowed = false;
    }

    if(!horAllowed && !vertAllowed) {
        realign();
    }
}

public function realign():void {
    if(!horAllowed) {
        if(this.x % GRID_SIZE < GRID_SIZE / 2) {
            this.x -= this.x % GRID_SIZE;
        } else {
            this.x += (GRID_SIZE - this.x % GRID_SIZE);
        }   
    }
    if(!vertAllowed) {
        if(this.y % GRID_SIZE < GRID_SIZE / 2) {
            this.y -= this.y % GRID_SIZE;
        } else {
            this.y += (GRID_SIZE - this.y % GRID_SIZE);
        }
    }
}

public function enterFrameHandler(Event):void {
    //trace(shot_timer);
    if(shot_timer > 0) {
        shot_timer--;
    }
    movement();
    firing();
}

public function firing():void {
    if(shooting) {
        if(shot_timer == 0) {
            shoot();
            shot_timer = 10;
        }
    }
}

public function shoot():void {
    var bullet = new Bullet();
    bullet.facing = facing;
    //0 - up, 1 - left, 2 - down, 3 - right
    switch(facing) {
        case 0: bullet.x = this.x; bullet.y = this.y - this.height / 2; break;
        case 1: bullet.x = this.x - this.width / 2; bullet.y = this.y; break;
        case 2: bullet.x = this.x; bullet.y = this.y + this.height / 2; break;
        case 3: bullet.x = this.x + this.width / 2; bullet.y = this.y; break;
    }
    (parent as MovieClip).addChild(bullet);
}

public function movement():void {
    //0 - up, 1 - left, 2 - down, 3 - right

    checkDirectionPermissions();

    if(horAllowed) {
        if(right) {
            orient(3);
            realign();
            this.x += speed;
        }
        if(left) {
            orient(1);
            realign();
            this.x -= speed;
        }
    }
    if(vertAllowed) {
        if(up) {
            orient(0);
            realign();
            this.y -= speed;
        }
        if(down) {
            orient(2);
            realign();
            this.y += speed;
        }
    }
}

public function orient(dest:int):void {
    //trace("facing: " + facing);
    //trace("dest: " + dest);
    var angle = facing - dest;
    this.rotation += (90 * angle);
    facing = dest;
}

}

}

The complete application is here if someone wants to attempt to replicate the error. It uses electroserver for parts of it so they may have to be commented out.

TankAttack.rar

A: 

Are these lines correct ?

public function enterFrameHandler(Event):void { //Instead of e:Event

,

var bullet = new Bullet(); // Instead of var bullet:Bullet

And

var angle = facing - dest; // Instead of var angle:int

I just want to make sure I am reading this right.

phwd
I believe so. enterFrameHandler does not need an actual event to function, and forcing types onto variables while good practice, is unnecessary. Anyone else can confirm me on this?
Ben
Alright well I kept it untouched. Gave it a run and was able to get creation and destruction of the Bullet with the timer. Tried multiple shots (which are limited by the timer), and it worked as well. The only place I could see it disappearing is the bounds. Sorry I could not recreate your problem :(
phwd
ok thanks for trying :) perhaps it's just my machine. Uploaded full source if someone desires to run it.
Ben