序言
作为一个android开发人员,时常想开发一个小游戏娱乐一下大家,今天就说说,我是怎么样一天写出一个简单的“飞机大战”的.

体验地址:http://www.wandoujia.com/apps/edu.njupt.zhb.planegame

源码:https://github.com/nuptboyzhb/newplanegame

游戏分析

玩过“飞机大战”游戏的都知道,飞机大战中的主要“角色”有:
1.玩家飞机
2.敌方飞机
3.玩家飞机发送的子弹
4.敌方Boss飞机发送的子弹
我们须要控制的有
1.绘制屏幕内的角色
2.控制角色的逻辑。比方:敌方飞机与我方飞机的碰撞检測,我方飞机发射的子弹与敌方飞机之间的碰撞检測,敌方Boss飞机发射的子弹与我方飞机直接的碰撞检測等等。
资源:
要完毕一个游戏,还要有资源的载入。比方飞机,子弹等图片的载入等,音效的载入。
游戏背景的绘制
事实上是一张图,这张图能够首尾相接。也即是“卷轴”,原理就是卡马克卷轴算法的原理。
以下分析代码区

事实上,抛开android平台,不论什么一个平台,做这样一个游戏。都须要这些逻辑。针对android平台。我们看一下,SurfaceView的绘制框架。

直接贴代码:

package edu.njupt.zhb.game.view;

/**
*
* @author Zheng Haibo
* @webset: http://www.mobctrl.net
* @android开发联盟QQ群:272209595
*/
public class PlaneView extends SurfaceView implements Callback, Runnable { private SurfaceHolder surfaceHolder;
private long sleep_time = 16;//绘制周期
private int screenHeight;
private int screenWidth;
private Thread thread;
private Canvas canvas;
private Paint paint;
private GameScreen currentScreen;
private int level = 0;
private int backgroundSpeed = 1; public PlaneView(Context context) {
super(context);
System.out.println("debug:PlaneView()");
surfaceHolder = this.getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setFormat(PixelFormat.TRANSLUCENT);
paint = new Paint();
paint.setAntiAlias(true);
paint.setDither(true);
} @Override
public void surfaceCreated(SurfaceHolder holder) {
System.out.println("debug:surfaceCreated");
setZOrderOnTop(false);
isGameOver = false;
if (isPause) {
return;
}
screenHeight = this.getHeight();
screenWidth = this.getWidth();
initPlane();
thread = new Thread(this);
thread.start();
} @Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
System.out.println("debug:surfaceChanged");
} @Override
public void surfaceDestroyed(SurfaceHolder holder) {
System.out.println("debug:surfaceDestroyed");
if (lift > 0) {
planeViewCallback.onGamePause();
}
isPause = true;
} @Override
public void run() {
while (!isGameOver) {//控制绘制周期
if (isPause) {
try {
Thread.sleep(sleep_time);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
continue;
}
long starttime = System.currentTimeMillis();
drawScreen();
long time = System.currentTimeMillis() - starttime;
if (time < sleep_time) {
try {
Thread.sleep(sleep_time - time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} /**
* 绘制场景
*/
private void drawScreen() {
canvas = surfaceHolder.lockCanvas();
if (null == canvas) {
return;
}
//清除
canvas.drawColor(Color.WHITE, PorterDuff.Mode.CLEAR);
paint.setAlpha(255);
gameLogic();
gameDraw();
if (null != canvas) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
} /**
* 游戏逻辑
*/
private void gameLogic() {
//TO DO 控制游戏逻辑
...
} private void gameDraw() {
//先绘制游戏背景
drawBackground(backgroundSpeed * frameSeq);
if (currentScreen == GameScreen.NORMAL) {
synchronized (planes) {
drawPlanes();
drawBullets();
drawMasterPlane();
}
} else if (currentScreen == GameScreen.BOSS) {
drawBullets();
drawBossPlane();
drawBossBullets();
drawMasterPlane();
}
} private void drawBossPlane() {
if (null != bossPlane) {
if (bossPlane.isClicked()) {// draw blast img
bossPlane.onBlastDraw(canvas, paint);
if (bossPlane.isBlastFrameEnd()) {
bossPlane.setClicked(false);
}
}
bossPlane.onDraw(canvas, paint);
}
} @Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
System.out.println("debug:onDraw");
} @Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
System.out.println("debug:onDetachedFromWindow...");
isPause = false;
isGameOver = true;
//释放资源
for (PlaneRes plane : planesRes) {
plane.getBitmap().recycle();
}
for (BulletRes bulletRes : bulletsRes) {
bulletRes.getBitmap().recycle();
}
} /**
* 用户交互
*/
@Override
public boolean onTouchEvent(MotionEvent e) {
int x = (int) e.getX();
int y = (int) e.getY();
switch (e.getAction()) {
case MotionEvent.ACTION_DOWN:
if (masterPlane.isContainPoint(x, y)) {
isMove = true;
}
break;
case MotionEvent.ACTION_MOVE:
if (isMove) {
synchronized (masterPlane) {
masterPlane.updatePosition(x, y);//控制玩家飞机的移动
}
}
break;
case MotionEvent.ACTION_UP:
isMove = false;
break;
}
return true;
}
}

对于背景的绘制。事实上是循环绘制一张图:本游戏的绘制逻辑:

private void drawBackground(int yOffset) {
yOffset %= screenHeight;
if (yOffset == 0) {
canvas.drawBitmap(backgroundBmp, 0, 0, paint);
} else {
canvas.drawBitmap(backgroundBmp, new Rect(0,
screenHeight - yOffset, screenWidth, screenHeight),
new Rect(0, 0, screenWidth, yOffset + 1), paint);
canvas.drawBitmap(backgroundBmp, new Rect(0, 0, screenWidth,
screenHeight - yOffset), new Rect(0, yOffset, screenWidth,
screenHeight), paint);
}
}

然后,我们仅仅须要在一个布局上,将PlaneView加入进去就可以:

如:

planeView = new PlaneView(this);
planeView.setPlaneViewCallback(this);
planeView.setGameOverCallback(this);
planeView.isMediaOpen = this.isMediaOpen;
LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
rl_plane.addView(planeView, lp);

未完待续。

。。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbnVwdDEyMzQ1Njc4OQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />

android:怎样用一天时间,写出“飞机大战”这种游戏!(无框架-SurfaceView绘制)的更多相关文章

  1. 用javascript写星际飞机大战游戏

    在github里看到了个不错的脚本游戏,决定亲自动手来写,效果如下 下面是代码的思路分享 把整个代码理解消化确实不容易,但是如果你坚持看完相信你一定会有收获 如果没兴趣可以直接点击下面的链接 复制代码 ...

  2. 微信5.0 Android版飞机大战破解无敌模式手记

    微信5.0 Android版飞机大战破解无敌模式手记 转载: http://www.blogjava.net/zh-weir/archive/2013/08/14/402821.html 微信5.0 ...

  3. 500行代码,教你用python写个微信飞机大战

    这几天在重温微信小游戏的飞机大战,玩着玩着就在思考人生了,这飞机大战怎么就可以做的那么好,操作简单,简单上手. 帮助蹲厕族.YP族.饭圈女孩在无聊之余可以有一样东西让他们振作起来!让他们的左手 / 右 ...

  4. 应用MVP模式写出可维护的优美Android应用

    在Android开发中,我们常常会动辄写出数千行的Java类,而当一个Activity有4.5千行的时候,想找一个逻辑在哪儿就会显得异常痛苦了.比如想在数据加载错误的时候,显示一个提示信息,上上下下得 ...

  5. fir.im Weekly - 如何写出零 bug 的代码

    神兽护体,代码无bug.经常看到代码注释的各种形状,这是一种程序员情怀.那么,如何能写出零 Bug 的代码呢,来看看@码农翻身 的这篇手册--零Bug的代码是怎么炼成的. 写零 Bug 一定少不了代码 ...

  6. 【转】Android开发笔记(序)写在前面的目录

    原文:http://blog.csdn.net/aqi00/article/details/50012511 知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面希望通过分享自己的经 ...

  7. 如何写出高质量的技术博客 这边文章出自http://www.jianshu.com/p/ae9ab21a5730 觉得不错直接拿过来了 好东西要大家分享嘛

        如何写出高质量的技术博客?答案是:如果你想,就一定能写出高质量的技术博客.看起来很唯心,但这就是事实.有足够愿力去做一件目标明确,有良好反馈系统的事情往往很简单.就是不停地训练,慢慢地,你自己 ...

  8. setTimeout和setInterval的区别以及如何写出效率高的倒计时

    1.setTimeout和setInterval都属于js中的定时器,可以规定延迟时间再执行某个操作,不同的是setTimeout在规定时间后执行完某个操作就停止了,而setInterval则可以一直 ...

  9. 如何用java写出无副作用的代码

    搞java的同学们可能对无副作用这个概念比较陌生,这是函数式编程中的一个概念,无副作用的意思就是: 一个函数(java里是方法)的多次调用中,只要输入参数的值相同,输出结果的值也必然相同,并且在这个函 ...

随机推荐

  1. 浏览器被“hao123.3377.com”主页劫持的解决办法

    问题描述: 浏览器被一个叫做hao123.3377的类似hao123网址导航的家伙,强行贴上.狗皮膏药一样. 问题解决: 尝试了网上说的包括下载360什么的,都不咋好用.后来发现是在激活win10(盗 ...

  2. Spark RDD/Core 编程 API入门系列之简单移动互联网数据(五)

    通过对移动互联网数据的分析,了解移动终端在互联网上的行为以及各个应用在互联网上的发展情况等信息. 具体包括对不同的应用使用情况的统计.移动互联网上的日常活跃用户(DAU)和月活跃用户(MAU)的统计, ...

  3. MVC系列学习(五)-传递数据 与 接收数据

    1.控制器向视图传递数据 a.使用ViewData b.使用ViewBag c.使用Model 方式二: d.使用TempData 2.为什么在控制器中设置了一些属性,在视图中可以接受 3.Actio ...

  4. MYSQL创建用户和授权方法(测试mysql5.7)

    一.创建用户:  命令:CREATE USER 'username'@'host' IDENTIFIED BY 'password'; 说明:username - 你将创建的用户名, host - 指 ...

  5. 话说:Hibernate二级缓存

    Hibernate缓存分类: 一.Session缓存(又称作事务缓存):Hibernate内置的,不能卸除. 缓存范围:缓存只能被当前Session对象访问.缓存的生命周期依赖于Session的生命周 ...

  6. Python随笔-切片

    Python为取list部分元素提供了切片操作,list[begin:end]获取list的[begin,end)区间元素. 可以用负数索引. tuple.str都是list的一种,所以也适用. 可以 ...

  7. CF832B Petya and Exam

    思路: 模拟. 实现: #include <iostream> using namespace std; string a, b; ]; bool solve() { ) return f ...

  8. Burn Down Chart(2018.6.4~2018.6.10)

    Burn Down Chart (2018.6.4~2018.6.10) 娄雨禛[前端部分] 曾子轩[后端部分+燃尽图] 前端 1. 娄雨禛+李鑫 1)在总工程中完成跳转,实现图片显示,并发布到Git ...

  9. [Windows Server 2003] ASP.net安装方法

    ★ 欢迎来到[护卫神·V课堂],网站地址:http://v.huweishen.com★ 护卫神·V课堂 是护卫神旗下专业提供服务器教学视频的网站,每周更新视频.★ 本节我们将带领大家:安装ASP.n ...

  10. 【译】x86程序员手册05 - 2.3寄存器

    2.3 Registers 寄存器 The 80386 contains a total of sixteen registers that are of interest to the applic ...