我正在使用 Adobe Animate(以前称为 Flash)在 ActionScript 3 中编写吃豆人克隆,并且可以使用一些关于移动和速度的建议。根据 Pitman 的吃豆人档案,吃豆人的移动速度约为每秒 75.75 像素。在下面的代码中,您可以看到我将项目的 FPS 设置为 38(最大速度的一半),并将其每帧移动 2 个像素以实现 100% 的速度。动画很流畅并且效果很好。问题是,当我尝试 80% 的速度时,因此必须在某些帧上将像素数从 2 减少,以便“减慢”他的速度。假设我使用相同的系统对幽灵进行编程,我必须达到从 40% 到 105% 的许多其他速度,增量为 5。当您减少任何步骤(参见代码)来减慢 Pacman 速度时,会出现明显的变化口吃。我可以尝试将应用程序的 FPS 设置为 76fps,并以每帧 1 像素的速度移动,但我有一种感觉,将某些步数减少到 0 会产生类似的结果,但在更高的帧速率下可能不会那么明显。有人可以给我任何建议,让我以不同的方式行动吗?我在这里受到限制,只能按整数移动每一帧,不带分数。
import flash.display.MovieClip;
import flash.events.KeyboardEvent;
import flash.events.Event;
import flash.display.Stage;
import Configure.Config;
public final class Pacman extends MovieClip {
private static var _instance:Pacman;
private var gridx;
private var gridy;
private var config:Config;
private var decx;
private var decy;
private var offsetX;
private var offsetY;
private var dir:Number; //pacman's direction. 0=left, 1=up, 2=right, 3=down
private var stepTable:Array = [];
private var speedCycle = 0;
public var step:Number = 1;
public function Pacman(_x:Number=112, _y:Number=212) {
// constructor code
if( _instance ){
throw new Error("Singleton... use getInstance()");
}
_instance = this;
this.addEventListener( Event.ENTER_FRAME, this.enterFrameHandler );
x = _x; y= _y;
offsetX = 0;
offsetY = 24;
config = Config.getInstance();
dir = 0; //left
initStepTable();
}
public static function getInstance():Pacman{
if( !_instance ){
new Pacman();
}
return _instance;
}
private function enterFrameHandler(e:Event)
{
var _parent = MovieClip(parent);
var moved = false;
var speedStr:String;
speedStr = stepTable["80"];
step = Number(speedStr.charAt(speedCycle));
updateGridPosition()
if(config.isKeyDown(37)) {
if( canMoveLeft() ) {
x -= step;
if(decy != .5){
if(decy < .5) y += step;
if(decy > .5) y -= step;
}
rotation = 0;
//play();
moved = true;
} else {
}
}
if(config.isKeyDown(38) ) {
if( canMoveUp() ) {
y -= step;
if(decx != .5){
if(decx < .5) x+=step;
if(decx > .5) x-=step;
}
rotation = 90;
//play();
moved = true;
}
}
if(config.isKeyDown(39) ) {
if ( canMoveRight() ) {
x += step;
if(decy != .5){
if(decy < .5) y += step;
if(decy > .5) y -= step;
}
rotation = 180;
//play();
moved = true;
}
}
if(config.isKeyDown(40) ) {
if( canMoveDown() ){
y += step;
if(decx != .5){
if(decx < .5) x+=step;
if(decx > .5) x-=step;
}
rotation = 270;
//play();
moved = true;
}
}
//stop();
updateGridPosition()
_parent.changeTxtPacX( String(x ) );
_parent.changeTxtPacY( String(y) );
_parent.changeTxtPacGrid( String(gridx + ":" + gridy) );
_parent.changeTxtPacDec( String(decx + ":" + decy) );
speedCycle++; if(speedCycle > 18) speedCycle=0;
}
private function updateGridPosition(){
gridx = ( x - offsetX ) / 8;
gridy = ( y - offsetY ) / 8;
decx = gridx - Math.floor( gridx );
decy = gridy - Math.floor( gridy );
}
private function canMoveLeft():Boolean {
var leftcontent = MovieClip(parent).getGridContent( Math.floor((gridx + .375 ) - 1), Math.floor(gridy) );
if( leftcontent != "#" ) return true;
return false;
}
private function canMoveUp():Boolean {
var upcontent = MovieClip(parent).getGridContent( Math.floor(gridx), Math.floor((gridy + .375) - 1));
if( upcontent != "#" ) return true;
return false;
}
private function canMoveRight():Boolean {
var rightcontent = MovieClip(parent).getGridContent( Math.floor((gridx - .5) + 1), Math.floor(gridy) );
if ( rightcontent != "#" ) return true;
return false;
}
private function canMoveDown():Boolean {
var downcontent = MovieClip(parent).getGridContent( Math.floor(gridx), Math.floor((gridy - .5) + 1));
if( downcontent != "#" ) return true;
return false;
}
private function initStepTable():void
{
/*
Todo:
*/
stepTable["100"] = "2222222222222222222"; // 100% speed
stepTable["80"] = "2222022220222202220";
//stepTable[2] = "0222222202222222"; //Pacman speed at 2-4 (85% of 75 pixels = 64.40 pixels/sec. We get 66.36 using our speed calc)
//stepTable[3] = "1111111111111111"; //Pacman speed at 5-20
//stepTable[4] = "1111111111111111"; //Pacman speed at 21+
}
} //end class
} // end package
通常在渲染游戏时,您不应该将游戏运动、处理、物理或动画等与帧速率紧密耦合。因为帧速率可以改变,并且通常您希望其他事情基于现实世界时间。
大多数游戏框架或引擎在更新内容时通过使用可变时间步长(也称为在帧之间使用“增量时间”)来处理此问题。 Jonas Tyroller 实际上有一个关于该主题的相当深入的视频,但与语言无关:https://www.youtube.com/watch?v=yGhfUcPjXuE
我会将你的 fps 调整为平滑的值。我推荐60fps。然后处理代码中所有的加速和减速。
我不会写出所有代码,但主要部分是在运动计算中使用帧之间的时间差。因此,您可能需要弄清楚如何将这个概念融入您自己的系统中。这是重要的部分
private var prevFrameTime:Number;
private function enterFrameHandler(e:Event):void {
var currentTime:Number = getTimer();
var deltaTime:Number = (currentTime - prevFrameTime) / 1000; // Convert to seconds
// Use deltaTime in your calculations
x += step * deltaTime;
prevFrameTime = currentTime;
}