安卓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 stubmSurfaceHolder = this.getHolder();mSurfaceHolder.addCallback(this);this.setFocusable(true);}//数据更新public void MainUpdate(){}@Overridepublic void draw(Canvas canvas) {// TODO Auto-generated method stub//super.draw(canvas);Canvas c = mSurfaceHolder.lockCanvas();//锁定画布,一般在锁定后就可以通过其返回的画布对象Canvas,在其上面画图等操作了。//绘图操作....////......//解锁显示mSurfaceHolder.unlockCanvasAndPost(c);}@Overridepublic boolean onTouchEvent(MotionEvent event) {// TODO Auto-generated method stubint 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 stubwhile(!Thread.currentThread().isInterrupted()){long time = System.currentTimeMillis();try {Thread.sleep(wait_time);} catch (InterruptedException e) {// TODO Auto-generated catche.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();}@Overridepublic void run() {while(true){try {Thread.sleep(30);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.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();}@Overridepublic void run() {// TODO Auto-generated method stubwhile(true){try {Thread.sleep(30);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.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();}@Overridepublic void run() {// TODO Auto-generated method stubwhile(true){try {Thread.sleep(30);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.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 130for(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;//当前人物indexprivate 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;}}@Overridepublic void run() {while(true){try {Thread.sleep(30);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.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;}}
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
