安卓android仿天天酷跑游戏(一)

 

 玩过酷跑的人都知道游戏中有个小人,之后他女朋友被坏人抓走了,然后这个小孩就往前使劲跑,使劲跑...

 

我们看似人物在往前走,其实际是背景和陆地再往后退

比如当我们刚上火车后,火车还未开动,但是我们看到窗外一个向后行驶火车后,我们总会感觉自己再像前走,道理是一样的

理解了这点我们就可以找可以动手来做了

首先分析下,这个view可以分为4个部分,1后面的背景,2背景下面的河流,3人物行驶的陆地,4游戏人物本身

我们可以控制1后面背景速度为1向后滚动,背景2稍微快点速度为5向后滚动,3陆地速度要更快>5(随游戏等级增加)向后滚动,人物X静止不动

1、打开eclipse新建一个android工程

2、双换成技术是游戏开发中必然会用到的技术,使游戏成像流畅的进行。使用SurfaceView类可以很容易的实现这个功能。

      添加一个GameSurfaceView类,继承SurfaceView父类,实现 SurfaceHolder.Callback,Runnable这几个接口,一个接口用来处理系统消息,另一个接口用来处理线程。             SurfaceHolder用来处理所有的系统消息和绘制,缓冲Canvas也需要用它来实现。在构造函数中实例化一个SurfaceHolder类,并且添加回调函数,以处理系统消息

      时间的控制在游戏中极为重要,下面对实现Runnable接口的类填写控制时间代码。 System.currentTimeMillis():方法获取系统时间,以毫秒为单位。经过试验在虚拟机中         平均一次sleep需要10毫秒,因此基础睡眠时间定为10毫秒为基准。重绘时间定为5个基准单位,数据更新时间定为10个基准单位,每次睡眠获取时间差,减掉时间差之后         <=0即实现动作。具体代码如下

 

public class GameSurfaceView extends SurfaceView implements SurfaceHolder.Callback,Runnable{

	private SurfaceHolder mSurfaceHolder = null;
	
	/**控制时间*/
	static final long wait_time = 10;
	static final long redraw_count = 5;
	static final long redraw_time = redraw_count*wait_time;
	private long      now_time_redraw = redraw_time;
	static final long update_count  = 10;
	static final long update_time = update_count*wait_time;
	private long      now_time_update = update_time;
	
	
	
	public GameSurfaceView(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
		
		mSurfaceHolder = this.getHolder();
		mSurfaceHolder.addCallback(this);
		this.setFocusable(true);
	}
	
	//数据更新
	public void MainUpdate(){
		
	}
	
	
	@Override
	public void draw(Canvas canvas) {
		// TODO Auto-generated method stub
		//super.draw(canvas);
		
		Canvas c  =  mSurfaceHolder.lockCanvas();//锁定画布,一般在锁定后就可以通过其返回的画布对象Canvas,在其上面画图等操作了。
		
		//绘图操作....
		//
		//......
		
		//解锁显示
		mSurfaceHolder.unlockCanvasAndPost(c);

	}


	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		
		int actionType = event.getAction();
		
		if(MotionEvent.ACTION_DOWN == actionType){
			//左屏,或右屏按下
			int onTouchX = (int) event.getRawX();
			if(onTouchX < MainConfig.ScreenWidth/2){
				//作屏幕按下操作
			}else{
			//右屏幕按下操作
			}
		} 
		return super.onTouchEvent(event);
	}
	@Overridepublic void run() 
	{
		// TODO Auto-generated method stub
		while(!Thread.currentThread().isInterrupted()){
			long time = System.currentTimeMillis();
			try {Thread.sleep(wait_time);
			} catch (InterruptedException e) 
			{// TODO Auto-generated catch
				 e.printStackTrace();
			}
			long dt = System.currentTimeMillis() - time;
			now_time_redraw -=dt;
			if(now_time_redraw <= 0){
				//重绘this.draw(null);now_time_redraw = redraw_time;
			}
			now_time_update -=dt;
			if(now_time_update <= 0){
				MainUpdate();
				//更新数据
			now_time_update = update_time;
			}
		}
	}

	@Overridepublic 
	void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) 
	{// TODO Auto-generated method stub//在surface的大小发生改变时激发}
	@Overridepublic void surfaceCreated(SurfaceHolder arg0) 
	{// TODO Auto-generated method stub //在创建时激发,一般在这里调用画图的线程。//初始化
		new Thread(this).start();
	}
	@Overridepublic void surfaceDestroyed(SurfaceHolder arg0) {// TODO Auto-generated method stub //销毁时激发,一般在这里将画图的线程停止、释放。}}

 

然后我们在draw中绘制每一帧就可以了

 

我们把四部分都创建一个类,首先是背景类MainGameBg

准备一张背景图

为了实现背景图向后运动我们可以让该类实现Runnable,把他当成线程类,然后让他自己的x向后递减

通过view的getResources().getDrawable方法获取资源中的图片放入Bitmap类型的成员变量中,在run中每过30毫秒刷新一次x值,然后在GameSurfaceView中调用drawBg进行重绘

为了让背景能够流畅的滚动,我们创建2个Bitmap类型的成员,交替滚动,虽然浪费了一些内存,但是这样代码逻辑比较清楚

 

 
package com.winheng.model;

import com.example.yhgame.R;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.view.View;

public class MainGameBg implements Runnable{


	/**背景图*/
	private Bitmap bgImg = null;
	
	private Bitmap bgImg2 = null;
	
	
	/**游戏主背景运动速度*/
	static final int bgImagSpeed = 1;
	
	/**主游戏背景宽度*/
	static final int bgImagWidth= 961;
	
	/**背景1 X位置*/
	private int x1 = 0;
	
	/**背景2 X位置*/
	private int x2 = bgImagWidth;
	
	public MainGameBg(View context){
		
		bgImg = ((BitmapDrawable)context.getResources().getDrawable(R.drawable.main_bg1)).getBitmap();
		bgImg2 = ((BitmapDrawable)context.getResources().getDrawable(R.drawable.main_bg1)).getBitmap();
		
	}

	@Override
	public void run() {
		while(true){
	
			try {
				Thread.sleep(30);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			x1 -= bgImagSpeed;
			x2 -= bgImagSpeed;
			
			if(-x1 >= bgImagWidth){
				x1 = bgImagWidth-10;
				
			}
			if(-x2 >= bgImagWidth){
				x2 = bgImagWidth-10;
				
			}
		}
		
	}
	
	public void drawBg(Canvas c){
		
		Matrix mtrx = new Matrix();
		
		mtrx.postTranslate(x1, 0);
		c.drawBitmap(bgImg, mtrx, null);
		
		Matrix mtrx2 = new Matrix();
		mtrx2.postTranslate(x2, 0);
		c.drawBitmap(bgImg2, mtrx2, null);
	}
	
	
}

然后类似背景图一。添加第二个背景,这个背景速度比背景图一稍微快点

 

package com.winheng.model;

import com.example.yhgame.R;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.view.View;

public class MainGameBgS implements Runnable{

	static final int gameWidth = 480;
	
	static final int gameHeight= 320;
	
	/**背景图*/
	private Bitmap bgImg = null;
	
	private Bitmap bgImg2 = null;
	
	/**游戏主背景运动速度*/
	static final int bgImagSpeed = 5;
	
	/**主游戏背景宽度*/
	static final int bgImagWidth= 3200;
	
	/**背景1 X位置*/
	private int x1 = 0;
	
	/**背景2 X位置*/
	private int x2 = bgImagWidth;
	
	private int isdownTime = 0;
	
	public MainGameBgS(View context){
		
		bgImg = ((BitmapDrawable)context.getResources().getDrawable(R.drawable.main_bg2)).getBitmap();
		bgImg2 = ((BitmapDrawable)context.getResources().getDrawable(R.drawable.main_bg2)).getBitmap();
		
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		while(true){
			
			try {
				Thread.sleep(30);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			if(isdownTime > 0){
				isdownTime--;
				x1 -= bgImagSpeed+10;
				x2 -= bgImagSpeed+10;
			}else{
				x1 -= bgImagSpeed;
				x2 -= bgImagSpeed;
			}
			
			
			if(-x1 >= bgImagWidth){
				x1 = bgImagWidth-10;
				
			}
			if(-x2 >= bgImagWidth){
				x2 = bgImagWidth-10;
				
			}
		}
	}
	
	
	public void drawBg(Canvas c){
		
		Matrix mtrx = new Matrix();
		
		mtrx.postTranslate(x1, 0);
		c.drawBitmap(bgImg, mtrx, null);
		
		Matrix mtrx2 = new Matrix();
		mtrx2.postTranslate(x2, 0);
		c.drawBitmap(bgImg2, mtrx2, null);
	}
	
	public void isDown(){
		isdownTime = 50;
	}
}

然后添加陆地

package com.winheng.model;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.view.View;

import com.example.yhgame.R;

public class MainLand implements Runnable{

	
	
	/**背景图*/
	private Bitmap land1 = null;
	
	private Bitmap land2 = null;
	
	private Bitmap land3 = null;
	
	private Bitmap landGirl = null;
	
	/**游戏主背景运动速度*/
	private  int bgImagSpeed = 9;
	
	/**主游戏背景宽度*/
	static final int bgImagWidth= 800;
	
	/**背景1 X位置*/
	private int x1 = 0;
	
	
	/**背景 Y位置*/
	private int y = 0;
	
	private Lands lands[] = new Lands[200];
	
	private int isdownTime = 20;
	
	public MainLand(View context){
		
		land1 = ((BitmapDrawable)context.getResources().getDrawable(R.drawable.land1)).getBitmap();
		land2 = ((BitmapDrawable)context.getResources().getDrawable(R.drawable.main_land)).getBitmap();
		landGirl = ((BitmapDrawable)context.getResources().getDrawable(R.drawable.land1girl)).getBitmap();
		if(MainConfig.ScteenType ==1){
			y = 300;
		}else{
			y = 215; 
		}
		
		
		//初始化地图
		initMap();
		
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		while(true){
			
			try {
				Thread.sleep(30);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			if(isdownTime>0){
				isdownTime --;
				x1 -= (bgImagSpeed+30);
			}else{
				x1 -= bgImagSpeed;
			}
			
		}
	}

	public int drawBg(Canvas c){
		
		//地图是否用完
		if(-x1/100 >= 190){
			x1 = 0;
		}
		
		int x = 0;
		int index = 0;
		for(int i=(-x1/100);i<(-x1/100)+20;i++){
		//for(int i=0;i<22;i++){
			index++;
			if(index == 3){
				x = lands[i].getY();
				
				if(i==60){
					lands[60].setBitimg(land1);
					lands[60].setY(y);
				}
				
			}
			
			Matrix mtrx = new Matrix();
			mtrx.postTranslate(lands[i].getX() + x1, lands[i].getY());
			c.drawBitmap(lands[i].getBitimg(), mtrx, null);
		}
		
		
		
		
		return x - 80;
	}
	
	public void isDown(){
		isdownTime = 50;
	}
	
	public void initMap(){
		int i;
		for(i = 0;i < lands.length;i++){
			lands[i] = new Lands();
			lands[i].setX(i*100);
		}
		
		for(i=0;i<20;i++){
			
			lands[i].setBitimg(land1);
			
			lands[i].setY(y);
		}
		
		lands[20].setBitimg(land1);
		lands[20].setY(y+300);
		lands[21].setBitimg(land1);
		lands[21].setY(y+300);
		
		for(i=22;i<30;i++){
			
			lands[i].setBitimg(land1);
			
			lands[i].setY(y-20);
		}
		for(i=30;i<40;i++){
			
			lands[i].setBitimg(land1);
			
			lands[i].setY(y+20);
		}
		lands[40].setBitimg(land1);
		lands[40].setY(y+300);
		for(i=41;i<60;i++){
			
			lands[i].setBitimg(land1);
			
			lands[i].setY(y);
		}
		lands[60].setBitimg(landGirl);
		lands[60].setY(y-170);	// 350 - 180 170 300 -215    130
		for(i=61;i<80;i++){
			
			lands[i].setBitimg(land1);
			
			lands[i].setY(y+20);
		}
		lands[80].setBitimg(land1);
		lands[80].setY(y+300);
		for(i=81;i<100;i++){
			
			lands[i].setBitimg(land1);
			
			lands[i].setY(y-20);
		}
		for(i=100;i<110;i++){
			
			lands[i].setBitimg(land1);
			
			lands[i].setY(y);
		}
		
		lands[110].setBitimg(land1);
		lands[110].setY(y+300);
		
		for(i=111;i<120;i++){
			
			lands[i].setBitimg(land1);
			
			lands[i].setY(y);
		}
		for(i=120;i<130;i++){
			
			lands[i].setBitimg(land1);
			
			lands[i].setY(y-20);
		}
		for(i=130;i<140;i++){
			
			lands[i].setBitimg(land1);
			
			lands[i].setY(y+20);
		}
		lands[140].setBitimg(land1);
		lands[140].setY(y+300);
		for(i=141;i<160;i++){
			
			lands[i].setBitimg(land1);
			
			lands[i].setY(y);
		}
		for(i=160;i<180;i++){
			
			lands[i].setBitimg(land1);
			
			lands[i].setY(y+20);
		}
		lands[180].setBitimg(land1);
		lands[180].setY(y+300);
		for(i=181;i<200;i++){
			
			lands[i].setBitimg(land1);
			
			lands[i].setY(y-20);
		}
	}
	
}

最后是摩托车

package com.winheng.model;

import com.example.yhgame.R;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.view.View;

public class MainMoto implements Runnable{

	//人物图像
	private Bitmap moto[] = new Bitmap[4] ;
	
	//人物图像更换速度
	private int changeIndex=0;
	
	//人物跳图
	private Bitmap motoJump = null;
	
	//人物加速度图
	private Bitmap motoJump2 = null;
	//当前人物index
	private int nowIndex = 0;
	
	//人物x轴
	private int x = 90;
	
	//陆地y 
	private int landY ;
	
	//人物y轴
	private int y = 0;
	
	//2跳转动角度
	private float rot = 0;
	
	//跳上升时间 10*30 
	private int upTime = 10;
	
	private View vieContext;
	/**
	 * 1:跳
	 * 0:降落
	 * -1:正常
	 * 2:双跳
	 * */
	private int isDump = -1;
	
	private int isdownTime = 0;
	//初始化人物图像
	public MainMoto(View context){
		vieContext = context;
		moto[0] =  ((BitmapDrawable)context.getResources().getDrawable(R.drawable.moto0)).getBitmap();
		moto[1] =  ((BitmapDrawable)context.getResources().getDrawable(R.drawable.moto1)).getBitmap();
		moto[2] =  ((BitmapDrawable)context.getResources().getDrawable(R.drawable.moto2)).getBitmap();
		moto[3] =  ((BitmapDrawable)context.getResources().getDrawable(R.drawable.moto3)).getBitmap();
		
		
		motoJump =  ((BitmapDrawable)context.getResources().getDrawable(R.drawable.jump)).getBitmap();
		motoJump2=  ((BitmapDrawable)context.getResources().getDrawable(R.drawable.jump)).getBitmap();
		if(MainConfig.ScteenType == 1){
			landY = 220;
			y = 220;
			
		}else{
			landY = 135;
			y = 135;
		}
	}
	
	
	@Override
	public void run() {
		
		while(true){
			try {
				Thread.sleep(30);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			if(changeIndex >= 5){
				changeIndex = 0;
				nowIndex++;
				if(nowIndex > 3){
					nowIndex = 0;
				}
			}
			changeIndex++;
			/**
			 * 1:跳
			 * 0:降落
			 * -1:正常
			 * 2:双跳
			 * */
			//跳
			if(isDump == 1){
				y-=9;
				x+=1;
				upTime--;
			//落
			}else if(isDump == 0){
				x-=1;
				y+=10;
			//双跳
			}else if(isDump == 2){
				y-=9;
				x+=1;
				rot +=15;
				upTime--;
			}else if(isDump == -1){
				y = landY;
			}else if(isDump == 3){
				y = landY;
			}
			
			
			if(upTime<=0){
				upTime = 10;
				isDump = 0;
				
			}
		
			//下降到地上
			if(y > landY){
				y = landY;
				if(x>90)x--;
				isDump = -1;
			}
			
			if(isdownTime > 0){
				isdownTime--;
			}
			if(isdownTime <= 0 && isDump == 3){
				isDump = -1;
			}
			
		}
	}
	public void drawBg(Canvas c,int landY){
		
		
		
		//人物上车
		if(landY <= 130 ){
			moto[0] =  ((BitmapDrawable)vieContext.getResources().getDrawable(R.drawable.moto0s)).getBitmap();
			moto[1] =  ((BitmapDrawable)vieContext.getResources().getDrawable(R.drawable.moto1s)).getBitmap();
			moto[2] =  ((BitmapDrawable)vieContext.getResources().getDrawable(R.drawable.moto2s)).getBitmap();
			moto[3] =  ((BitmapDrawable)vieContext.getResources().getDrawable(R.drawable.moto3s)).getBitmap();
			
			motoJump =  ((BitmapDrawable)vieContext.getResources().getDrawable(R.drawable.jumps)).getBitmap();
			motoJump2=  ((BitmapDrawable)vieContext.getResources().getDrawable(R.drawable.jumps)).getBitmap();
			
		}else{
			this.landY = landY;
		}
		
		
		Matrix mtrx = new Matrix();
	//	mtrx.setScale(0.33f, 0.33f);
		//正常
		if(isDump == -1){
			mtrx.postTranslate(x, y);
			c.drawBitmap(moto[nowIndex], mtrx, null);
		//二跳
		}else if(isDump == 2){
			
			mtrx.postTranslate(x, y);
			mtrx.setTranslate(x, y);
			mtrx.preRotate(rot,motoJump.getWidth() / 2f,motoJump.getHeight() / 2f );
			
			c.drawBitmap(moto[nowIndex], mtrx, null);
		//加速度
		}else if(isDump == 3){
			
			mtrx.postTranslate(x, y);
			c.drawBitmap(motoJump2, mtrx, null);
		//上升,下降	
		}else{
			mtrx.postTranslate(x, y);
			
			c.drawBitmap(motoJump, mtrx, null);
			
		}
		
		
		
	}
	//跳
	public void dump(){
		
		if(isDump == 1 || isDump ==0){
			upTime = 6;
			isDump = 2;
		}else if(isDump == -1 || isDump == 3){
			isDump = 1;
		}
		
	}
	//加速度
	public void down(){
		isdownTime = 50;
		isDump = 3;
	}

}

 

 

 

 

 

 

 

 

 

 

 

 

  • 8
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值