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 我写的一些示例。
所以我被告知要在 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 我写的一些示例。