我正在根据Gary Rosenzweig最新的Actionscript 3书在AS3中构建游戏。它有一个游戏计时器问题,不仅是我的,还有他的演示,我无法弄明白。
游戏就像小行星一样,在开始时将四块岩石放置在舞台的角落,然后开始在舞台周围随机移动。问题是所使用的计时器是在Flash文件启动的那一刻启动的,而不是玩家点击开始按钮的那一刻。因此,如果你在开始屏幕上持续5秒钟,然后在游戏实际开始时单击游戏,那么它们将在5秒的游戏之后出现,这可能就在玩家身上了。
我发布了我认为适用的代码部分。有人可以告诉我如何修改这个,以便当玩家真正开始游戏时,岩石开始在适当的位置。我很确定这是我所包含的最后一个功能就是问题,但我已经包含了其他相关部分,以便为您提供更完整的图片。
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;
}
}
}
答案 0 :(得分:1)
根据您发布的代码,我无法安全地回答您的问题,但您应该在第一次调用startSpaceRocks()
时进行检查。这应该在您的开始按钮的点击处理程序中。
除此之外,您的问题标题并未反映出问题。完全没有定时器的问题,当“定时器”启动时出现问题。
答案 1 :(得分:1)
您认为应用于问题的代码部分不正确。
计时器可以和它的声明一起启动:
private var myTimer:Timer = new Timer(delay, repeat);
但是因为你在声明时没有启动计时器(如你的片段所示)
// timers
private var delayTimer:Timer;
private var shieldTimer:Timer;
必须有一些其他功能才能启动。将启动计时器的操作移动到您想要启动计时器的任何位置。例如:进入 startspacerocks()功能
如果不是问题,请发布适用于您的问题的相关代码。
修改强>
我认为你的答案在于 moveGameObjects 功能。
尝试按如下方式修改功能:
// 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();
}