与按键相关的角色移动,随着角色速度的提高而提高动画速度

Posted

技术标签:

【中文标题】与按键相关的角色移动,随着角色速度的提高而提高动画速度【英文标题】:Character movement tied to keypress, increases animation speed with increased character speed 【发布时间】:2013-07-31 18:15:22 【问题描述】:

我遇到了一个棘手的问题(至少对我而言),我无法弄清楚。我有一个简笔画,我想根据他是向左还是向右移动来制作一个简单的跑步动画,但还要将动画速度与他在 x 方向移动的速度联系起来。

下面我包含了我的角色如何移动的代码(我的游戏中所有不必要的代码都被删除了)。 xspeed 也是我希望我的动画速度以某种方式联系起来的。我可以简单地将它与xspeed 的绝对值联系起来,因为它可能是负数。理想情况下,我想要 2 个动画,1 个用于向左移动,1 个用于向右移动。我想为我的stickman1在同一时间轴上制作两个动画,然后做这样的事情。

if (xspeed > 0)stickman1.gotoAndPlay(2)
if (xspeed < 0)stickman1.gotoAndPlay(5)

假设我向右移动的动画是 3 帧长,从第 2 帧开始,在第 4 帧结束,而我向左移动的动画也是 3 帧长,从第 5 帧开始,在第 7 帧结束,然后在第 4 帧和第 7 帧只是输入了一些代码,上面写着gotoAndPlay(correct frame to repeat)。尽管如此,我知道在时间线上进行任何编码总是不好的做法,所以如果可能的话,我想远离那个。然后它只会变得更糟。我不知道如何加速动画 =(。所以这就是我所在的位置,非常感谢有关这些问题的帮助,我的角色移动的完整代码如下!谢谢!

public var gameTimer:Timer;
public var stickman1:Stickman1;
public var leftBool:Boolean = false;
public var rightBool:Boolean = false;
public var accel:Number = 0.5;
public var maxspeed:Number = 8;
public var xspeed:Number = 0;

public function gameScreen():void

    this.addEventListener(Event.ENTER_FRAME, addSomeListeners, false, 0, true);
    stickman1 = new Stickman1();
    stickman1.x = 250;
    stickman1.y = 300;
    addChild(stickman1);
    gameTimer.addEventListener(TimerEvent.TIMER, onTick, false, 0, true);
    gameTimer = new Timer(25);
    gameTimer.start();


public function addSomeListeners(event:Event):void

    stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown, false, 0, true);
    stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp, false, 0, true);


public function onTick(timerEvent.TimerEvent):void

    if(rightBool==true && xspeed<maxspeed)xspeed+=2
    if(leftBool==true && xspeed>-maxspeed)xspeed-=2
    if(xspeed>0)xspeed-=accel
    if(xspeed<0)xspeed+=accel

    stickman1.x+=xspeed;
    stickman1.y+=yspeed;


public function onKeyDown(keyboardEvent.KeyboardEvent):void

    if (event.keyCode == Keyboard.LEFT)leftBool = true;
    if (event.keyCode == Keyboard.RIGHT)rightBool = true;


public function onKeyUp(keyboardEvent.KeyboardEvent):void

    if (event.keyCode == Keyboard.LEFT)leftBool = false;
    if (event.keyCode == Keyboard.RIGHT)rightBool = false;

【问题讨论】:

【参考方案1】:

您需要管理自己的动画系统,但这并不像听起来那么难:)

这样的事情应该可以工作(假设第 0 帧是站立的,而第 1-n 帧正在运行):

public var dir:int = 0; // direction you're going; -1 = left, 1 = right, 0 = not moving
public var speed:Number = 0.0; // the speed of your char
public var stickman:Stickman; // your stickman obj
public var prevTime:Number = 0.0; // used to calculate delta time in the update
public var currAnimTime:Number = 0.0; // our current animation time
public var currAnimFrame:int = 0; // our current animation frame

public function gameScreen():void

    // create our stickman
    this.stickman = new Stickman();
    this.stickman.gotoAndStop( 0 ); // stand frame
    …

    // add our listeners
    this.addEventListener( Event.ENTER_FRAME, this._onEnterFrame );
    this.addEventListener( KeyboardEvent.KEY_DOWN, this._onKeyDown );
    this.addEventListener( KeyboardEvent.KEY_UP, this._onKeyUp );

    this.prevTime = getTimer();


private function _onEnterFrame( e:Event ):void

    // calculate delta time
    var currTime:int = getTimer();
    var dt:Number   = ( currTime - this.prevTime ) * 0.001; // dt is in seconds
    this.prevTime   = currTime;

    // check if we're slowing down
    if( this.dir == 0 )
    
        this.speed *= 0.8;
        if( this.speed <= 0.01 ) // or whatever value you want
            this.speed = 0.0;
    
    else
    
        // we're running
        this.speed += 20 * dt * this.dir; // or whatever speed increase you want
        if( this.speed > 20 )
            this.speed = 20; // max speed;
    

    // if our speed is 0, just play the stand anim and return
    if( this.speed == 0 )
    
        this.gotoAndStop( 0 );
        return;
    

    // get our anim time - the seconds for a frame.
    // basically, if speed is 20, then our anim time will be
    // 1.0 (1 second) / 20.0 -> 0.05, or 0.05 seconds
    // per frame. We use seconds because dt and currAnimTime are
    // in seconds. NOTE: this is a linear transform of speed -> fps
    var animTime = 1.0 / this.speed;

    // update our current anim time
    this.currAnimTime += dt;
    while( this.currAnimTime > animTime )
    
        // increase our current anim frame
        this.currAnimFrame++;
        if( this.currAnimFrame > this.totalFrames )
            this.currAnimFrame = 1; // frame 0 is our stand anim
    

    // go to our new frame
    if( this.currAnimFrame != this.currFrame )
        this.gotoAndStop( this.currAnimFrame );

    // flip our scale based on if we're right or left
    this.scaleX = ( this.dir < 0 ) ? -1 : 1;


private function _onKeyDown( e:KeyboardEvent ):void

    // move left or right
    if( e.keyCode == Keyboard.LEFT )
        this.dir = -1;
    else if( e.keyCode == Keyboard.RIGHT )
        this.dir = 1;


private function _onKeyUp( e:KeyboardEvent ):void

    // stop
    if( e.keyCode == Keyboard.LEFT || e.keyCode == Keyboard.RIGHT )
        this.dir = 0;

基本上,您只需更改显示每一帧的时间,然后手动处理更改为正确的帧。这样一来,您的动画就会随着 char 的速度加快和减慢。

【讨论】:

编辑:我在animFPS 计算周围添加了一个Math.abs(),因为speed 可以低于0 哇,这太棒了!唯一可能您可以再次查看的另一件事是 this.animFPS 部分。在我看来,我们走得越快,animFPS 就越慢,因为它们成反比。对我来说,它看起来应该只是 Math.abs(this.speed),但也许我错过了什么?还猜测那里的某个地方也必须有一个比例常数? 我是凭脑子写的,所以里面可能有bug :D 你可以去掉animFPS 变量;它只是用来计算animTime,即每帧花费的毫秒数。基本上,随着speed 上升,animTime 应该越来越低,所以像 var animTime = 1000 / Math.abs( this.speed ); “还猜测那里一定有一个比例常数” - 是的,这里是非常线性的;你如何计算最终的animTime 取决于你想要的效果。查看缓动方程或日志函数(不是我的专业领域,抱歉) 好的,我今天要尝试实现它,至少对我来说这一切都有意义 =p

以上是关于与按键相关的角色移动,随着角色速度的提高而提高动画速度的主要内容,如果未能解决你的问题,请参考以下文章

PuTsangTo-单撸游戏开发04 给角色添加基本动画

Unity入门计划Unity2D动画-脚本与混合树实现玩家角色动画过渡

改变精灵动画速度(pygame)

使用 next.js 包含动态动画的正确方法

Mecanim Animator使用详解

Pygame - 运动加速