我正在使用动作脚本3进行汽车Flash游戏,如果我按下键盘上的“向上”,我希望道路线路更快,线路由定时器创建,其延迟由按下的键修改问题是,如果我按下按键,事件的计时器仍会刷新,并且在我停止按下之前它没有显示任何道路线。
这是关键的新闻代码:
if (upPressed)
{
speed = speed*1.02;
timerB.delay = timerB.delay/1.007;
timerA.delay = timerA.delay/1.005;
}
任何提示?提前谢谢。
答案 0 :(得分:0)
问题可能是每次更改延迟属性时Timer类重新启动的结果。
来自Adobe docs:
如果在定时器运行时设置延迟间隔,则定时器将以相同的repeatCount迭代重新启动。
http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/utils/Timer.html#delay
这基本上意味着计时器从0重新开始,但记住它重复了多少次。我意识到我的答案很长,所以我在底部提了一些参考。
解决方案:使用flash.utils.getTimer()而不是Timer对象。
http://www.adobe.com/livedocs/flash/9.0/ActionScriptLangRefV3/flash/utils/package.html#getTimer()
getTimer()函数返回一个整数,表示自.swf文件启动以来经过的毫秒数。如果每帧都检查此编号,则可以看到自上一帧以来经过了多长时间。只需添加每帧通过的毫秒数,直到该数字达到阈值,然后调用线条绘制功能并重置计数器。
当检查是否按下该键时,减少新的'myDelay'变量而不是Timer.delay属性。
var ms:int;
var timeStamp:int = flash.utils.getTimer();
var myDelay:Number;
onEnterFrame() {
// Track how much time has passed since the last frame
ms += flash.utils.getTimer() - timeStamp;
if (ms > myDelay)
{
// DRAW THE ROAD LINES
drawLines();
// RESET THE COUNTER
ms = 0;
}
//other stuff
// Record the timestamp of this frame so you can see the difference next frame
timeStamp = flash.utils.getTimer();
}
定时器重置的说明:
注意:我假设您每秒都要检查按键。如果你每帧都改变定时器的延迟属性(例如每秒24次)并且你的定时器发生的频率低于每秒24次,那么它将在它有机会发出一个事件来调用它的处理程序之前被重置。创建线条的功能。
如果你看一下下面的例子,启动和停止事件是防止它被重置的唯一方法,但即便这样,只有当延迟比两次之间的时间短时,才会调用定时器事件处理函数。改变了延迟。由于平均swf为24fps,这意味着在下一帧再次更改值之前,延迟需要短于41.6毫秒。
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.TimerEvent;
import flash.utils.Timer;
/**
* ...
* @author
*/
public class Main extends Sprite
{
var timer:Timer;
var keyPressed:Boolean = false;
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
timer = new Timer(50);
timer.addEventListener(TimerEvent.TIMER, function ():void { trace (timer.delay); } );
timer.start();
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, keyUp );
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
function onEnterFrame (e:Event)
{
if (keyPressed)
{
timer.stop();
timer.delay -= 1;
timer.start();
}
}
function keyDown (e:KeyboardEvent):void { keyPressed = true; }
function keyUp (e:KeyboardEvent):void { keyPressed = false; }
}
}
答案 1 :(得分:0)
虽然Josh的回答似乎准确描述了您的错误来源,但应该注意解决问题的正确方法是完全停止使用计时器,并在EnterFrame中运行所有逻辑处理程序。
要了解为什么这是真的,请回想一下,flash播放器以给定的帧速率运行,并且每帧只重绘一次屏幕。假设您以与帧速率相同的速度运行计时器。这意味着您将在每次重绘屏幕之间获得一个Timer事件。现在假设您将计时器加速了10%。发生的一切都是,Timer事件和帧事件不同步,因此每帧可以获得一帧9帧,而在第十帧期间,Timer将触发两次。你的路线移动速度没有快10%,它以相同的速度移动9帧,而速度移动到第10帧,这与你想要的完全不同。
解决方案是,不是试图更频繁地移动道路线,而是希望每帧移动一次,但是移动它们的距离更大或更小。正确的方法是使用EnterFrame处理程序。
答案 2 :(得分:0)
EnterFrame是每次视图刷新(粗略)时由Flash运行时触发的事件。您可以向根显示对象添加事件侦听器,并触发“update()”方法。这将取代您当前在计时器中所做的事情。
您可以在游戏上下文中详细解释为什么EnterFrame比Timer更有用: