canvas 的 2D 移动播放器

2D Moving player with canvas

所以我被告知要在 android 中使用 canvas 创建一个仅用于学校项目的简单游戏(这意味着除了随 android),我想创建一个简单的 2d 游戏,让玩家四处走动。

我是这样做的:

public GameView(Context c) {
    // TODO Auto-generated constructor stub
super(c);
this.c=c;
this.Sprite=BitmapFactory.decodeResource(getResources(), R.drawable.walk1);
this.Sprite=Bitmap.createScaledBitmap(Sprite, Sprite.getWidth()*2, Sprite.getHeight()*2, false);
sprite2=new Sprite("Spicy",Sprite);
this.requestFocus();
this.setFocusableInTouchMode(true);
animate1();
}

我创建了一个视图 class,加载了一个简单的玩家精灵,创建了精灵 class 和一个处理程序 -

public void animate1(){
    handlerAnimation100 = new Handler();

    final Runnable r = new Runnable() {
        public void run() {
        invalidate();
            handlerAnimation100.postDelayed(this, 1);
        }
    };

    handlerAnimation100.postDelayed(r, 1);
}

游戏时间和动画每 0.001 秒失效一次。

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
sprite2.Draw(canvas);   
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    sprite2.Update(keyCode);
    invalidate();
    return false;
} 

在 onDraw 上我调用了 sprite 中的绘制函数 class 和 onkeydown 我将按下的键发送到 sprite 中的更新函数 class.

现在精灵 class 没有什么特别的:

public class Sprite {
      enum State
      {
          Walking
      }
      State mCurrentState = State.Walking;

      int mDirection = 0;
      int mSpeed = 0;
      int mPreviousKeyboardState;
    private String spriteName;
    Bitmap sprite;
     int SPRITE_SPEED = 5;
     int MOVE_LEFT = -1;
     int MOVE_RIGHT = 1;
    private float mScale = 1.0f;
    Point Position;
    public Sprite(String name,Bitmap sprite) {
        this.sprite=sprite;
        this.spriteName=name;
     Position=new Point(150,150);
    }
    public void Update(int keyboard)
    {
        int aCurrentKeyboardState = keyboard;

        UpdateMovement(aCurrentKeyboardState);

        mPreviousKeyboardState = aCurrentKeyboardState;


    }
    private void UpdateMovement(int aCurrentKeyboardState)
    {
        if (mCurrentState == State.Walking)
        {
            mSpeed = 0;
            mDirection = 0;

            if (aCurrentKeyboardState==KeyEvent.KEYCODE_A)
            {
                mSpeed = SPRITE_SPEED;
                mDirection = MOVE_LEFT;
            }
            else if(aCurrentKeyboardState==KeyEvent.KEYCODE_D)
            {
                mSpeed = SPRITE_SPEED;
                mDirection= MOVE_RIGHT;
            }
            Position.x += mDirection * mSpeed;
        }
    }
    public void Draw(Canvas c)
    {            
        c.drawBitmap(sprite, Position.x,Position.y, null);
    }
}

我只是改变图像的位置并根据按下的键移动它。


现在问题来了: 使用 handler 和 invalidate 是我能够找到的唯一选项来替换出现在游戏引擎中的 "Game time",虽然它可以工作,但它工作起来非常不稳定,如果玩家的速度很高,它看起来像跳跃像素如果它的动画很模糊并且很慢,看起来无效需要更多时间并且它不是每 0.001 秒发生一次,而是每 0.5 秒左右发生一次。

它是这样的:
速度慢(模糊且非常慢):

更快的速度(起伏不顺畅):


有没有更好的方法来做到这一点,再次只使用 android 提供的东西?

话题!然而,根据你的动画有多慢 运行 以及快速动画有多不稳定来判断处理程序并不是问题的根源,你可能正在使用绑定到 ImageView 的 canvas ?这根本不是很快。您应该考虑使用 SurfaceView(适用于较低的 API,但不是最快的)或 TextureView(超快,我不得不延迟我的线程,因为动画只是一个模糊)。这两者都以 canvas 为核心。

互联网上有很多关于如何编写这些代码的示例,您可以根据自己的目的调整它们。为了给您一个起点,您可以查看 HERE 我写的一些示例。