android 实现人物行走

程序运行画面



可以通过上下左右键控制人物行走

思路

启动一个线程来不断的刷帧

在每一帧里重新绘制游戏画面

在每一帧里对鼠标点击事件作出响应,维护好游戏逻辑

需求分析

怎么实现键盘点击事件的响应。

通过Override onKeyDown函数实现。

值得注意的是

如果游戏的主画面是自定义的View,那么记得要在其初始化函数中加上setFocusable(true)

否则将不会对键盘点击事件作出响应,因为自定义的视图并没有获得焦点,因而无法对键盘点击事件作出响应。

怎么实现绘制一幅图片的特定区域。

canvas.drawBitmap函数有多个版本。

为了绘制一幅图片的指定区域,我们使用的是下面的版本

canvas.drawBitmap(Bitmap bitmap,Rect rect1,Rect rect2,Paint paint)

rect1用于指定截图区域

rect2用于指定展示区域


代码实现

MainActivity.java

package com.example.move;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.Window;
import android.view.WindowManager;

public class MainActivity extends Activity {


	GameView gameView;
	//GameViewDrawThread gameViewDrawThread;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
		//setContentView(R.layout.main);
		gameView=new GameView(this);
		
		setContentView(gameView);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}
}

GameViewDrawThread.java

package com.example.move;

import android.graphics.Canvas;
import android.view.SurfaceHolder;

class GameViewDrawThread extends Thread
{
	private int sleepSpan=100;
	private boolean flag=true;
	GameView gameView;
	SurfaceHolder surfaceHolder=null;
	public GameViewDrawThread(GameView gameView,SurfaceHolder surfaceHolder)
	{
		this.gameView=gameView;
		this.surfaceHolder=surfaceHolder;
	}
	public void run()
	{
		while(flag)
		{
			Canvas c=null;
			try
			{
				//锁定整个画布,在内存要求比较高的情况下,建议参数不要为null
				c=surfaceHolder.lockCanvas(null);
				synchronized(this.surfaceHolder)
				{
					try
					{
						gameView.onDraw(c);
					}
					catch(Exception e){};
				}
			}
			finally
			{
				if(c!=null)
				{
					if(c!=null)
					{
						surfaceHolder.unlockCanvasAndPost(c);
					}
				}
			}
			try
			{
				Thread.sleep(sleepSpan);
			}
			catch(Exception e)
			{
				e.printStackTrace();
			}
		}
	}
	public void setFlag(boolean flag)
	{	
		this.flag=flag;
	}
}

GameView.java

package com.example.move;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.view.KeyEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.Toast;

class GameView extends SurfaceView implements SurfaceHolder.Callback
{
	MainActivity activity;
	Paint paint;
	Bitmap image_sprite;
	
	GameViewDrawThread gameViewDrawThread;
	Sprite sprite;
	SurfaceHolder holder;
	//Measures
	int sprite_width=32;
	int sprite_height=48;
	int unit=48;
	int box_x=0;
	int box_y=0;
	int box_width=0;
	int box_height=0;
	int bound_left,bound_right,bound_up,bound_down;
	public GameView(MainActivity activity)
	{
		super(activity);
		this.activity=activity;
		this.sprite=new Sprite(3*unit,2*unit,sprite_width,sprite_height,0,0,0,true);
		gameViewDrawThread=new GameViewDrawThread(this,getHolder());
		gameViewDrawThread.start();
		
		holder=this.getHolder();
		holder.addCallback(this);
		initBitmap();
		setFocusable(true);
	}
	public void initBitmap()
	{
		paint=new Paint();
		image_sprite=BitmapFactory.decodeResource(getResources(),R.drawable.sprite);
	}
	protected void onDraw(Canvas canvas)
	{	
		//canvas.drawRect(0,0,box_width,box_height,paint);
		paint.setAntiAlias(true);
		canvas.drawColor(Color.WHITE);
		canvas.save();
		int cur_x=sprite.status*sprite.w;
		int cur_y=sprite.direction*sprite.h;
		
		Rect src = new Rect();// 图片
        Rect dst = new Rect();// 屏幕位置及尺寸
        //src 这个是表示绘画图片的大小
        src.left =cur_x;
        src.top = cur_y;
        src.right =cur_x+sprite_width;
        src.bottom =cur_y+sprite_height;
        // 下面的 dst 是表示 绘画这个图片的位置
        dst.left =sprite.x;
        dst.top =sprite.y;
        dst.right =sprite.x+sprite_width;   
        dst.bottom =sprite.y+sprite_height;
        canvas.drawBitmap(image_sprite, src, dst, null);//这个方法  第一个参数是图片原来的大小,第二个参数是 绘画该图片需显示多少。也就是说你想绘画该图片的某一些地方,而不是全部图片,第三个参数表示该图片绘画的位置
        
        src = null;
        dst = null;
        System.out.println(sprite.direction+" "+sprite.x+" "+sprite.y);
		/*canvas.clipRect(sprite.x,sprite.y,sprite.x+sprite_width,sprite.y+sprite_height);
		canvas.drawBitmap(image_sprite,sprite.x,sprite.y,paint);*/
		
		canvas.restore();
	}
	
	public void surfaceDestroyed(SurfaceHolder holder)
	{
		boolean retry=true;
		gameViewDrawThread.setFlag(false);//note
		while(retry)
		{
			try
			{
				gameViewDrawThread.join();//不断尝试执行此行代码,直到成功
				retry=false;
			}
			catch(InterruptedException e)
			{
				
			}
		}
	}
	@Override
	public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
		// TODO Auto-generated method stub
		
	}
	@Override
	public void surfaceCreated(SurfaceHolder arg0) {
		
		// TODO Auto-generated method stub
		box_width=this.getWidth();
		box_height=this.getHeight();
		bound_left=box_x;
		bound_right=box_x+box_width-unit;
		bound_up=box_y;
		bound_down=box_y+box_height-unit;
	}
	@Override
	public boolean onKeyDown(int key,KeyEvent event)
	{
		//Toast.makeText(activity, "HELLO", 1000);
		//System.out.println("change");
		int cur_direction=0;
		switch(key)
		{
			case KeyEvent.KEYCODE_DPAD_UP:
			sprite.y-=unit;
			if(sprite.y<bound_up)
				sprite.y=bound_up;
			cur_direction=3;
			break;
			case KeyEvent.KEYCODE_DPAD_DOWN:
			sprite.y+=unit;
			if(sprite.y>bound_down)
				sprite.y=bound_down;
			cur_direction=0;
			break;
			case KeyEvent.KEYCODE_DPAD_LEFT:
			sprite.x-=unit;
			if(sprite.x<bound_left)
				sprite.x=bound_left;
			cur_direction=1;
			break;
			case KeyEvent.KEYCODE_DPAD_RIGHT:
			sprite.x+=unit;
			if(sprite.x>bound_right)
				sprite.x=bound_right;
			cur_direction=2;
			break;
		}
		if(cur_direction!=sprite.direction)
		{
			sprite.direction=cur_direction;
			sprite.status=0;
		}
		else
		{
			sprite.status=(sprite.status+1)%4;
		}
		return super.onKeyDown(key, event);
		//return true;
	}
	
}

sprite.java

package com.example.move;

public class Sprite
{
	int x,y,w,h,direction,status,speed;
	boolean flag;
	public Sprite(int x,int y,int sw,int sh,int direction,int status,int speed,boolean flag)
	{
		this.x=x;
		this.y=y;
		this.w=sw;
		this.h=sh;
		this.direction=direction;
		this.status=status;
		this.speed=speed;
		this.flag=flag;
	}
}

使用android实现人物行走的思路和使用Html5实现人物行走的思路是相近的,代码的写法也差不多。

具体可以参考另一篇文章

HTML5 实现人物行走


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值