本文章属于原创性文章,珍惜他人劳动成果,转载请注明出处: http://www.pm-road.com/index.php/2014/11/06/169/
前言:最 近闲来无事,而且也是因为刚接触安卓不久,所以萌生了以后在开发web 项目的过程中同样开发安卓手游,因前一段时间项目需要独立完成了一款功能型手机app ,该App比较简单,全是按钮操作,也就是Activity之间的相互传值与过渡,所以对安卓的基本知识有了一定了解,在我的印象当中,感觉安卓手游是比 较困难的,但是有困难就要克服,所以有了开发游戏的念头。
在安卓游戏开发源码(三)中,已经把控制的飞机显示出来,结果如下:
接下来,就要把敌人的战机也开发出来,并可以向下发射子弹。
在上一次的代码中,找到MainActivity.java文件,在其属性中添加:一个新的属性:
// 敌机的图片
private List<ImageButton> enemyPlanes;
在initView()方法中,添加一个新的方法,用来初始化敌机
//初始化敌机
initEnemyPlane();
然后把这个方法声明出来:
/**
* 初始化敌机
*/
private void initEnemyPlane(){
// 生成敌机数量,这里在Util中新增了一个方法
int enemyCount = CommonUtil.getEnemyPlaneCount();
enemyPlanes = new ArrayList<ImageButton>();
for (int i = 0; i < enemyCount; i++) {
ImageButton enemyPlaneImg = new ImageButton(context);
enemyPlaneImg.setBackgroundResource(R.drawable.enemyplane);
//敌机的横坐标也是随机的
int x = new Random().nextInt(windowWidth);
enemyPlaneImg.setX(x);
enemyPlaneImg.setY(0);
this.addContentView(enemyPlaneImg, new LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
enemyPlanes.add(enemyPlaneImg);
}
}
在commonUtil.java中增加新的属性和方法,用来随机得到敌机数量
/** 出现最大的战机数 */
public static final int MAX_ENEMY_PLANE = 4;
/**
* 随机得到飞机的数量
* @return
*/
public static final int getEnemyPlaneCount(){
Random random = new Random();
//随机出现战机的数量
int enemyPlaneCount = random.nextInt(CommonUtil.MAX_ENEMY_PLANE);
//如果随机的数量是0 ,则一直循环,直到非0
while(enemyPlaneCount == 0){
enemyPlaneCount = random.nextInt(CommonUtil.MAX_ENEMY_PLANE);
}
return enemyPlaneCount;
}
至此,在页面展示出来之后,敌机也一些展示了出来。接下来我们要做的便是使敌机发射子弹。
在MainActivity.java中找到initBean方法,在方法中添加:如下代码,作用就是把敌机的图片set到surfaceView界面中
// 所有敌机
surfaceView.setEnemyPlanes(enemyPlanes);
surfaceView.setWindowHeight(windowHeight);
surfaceView.setWindowWidth(windowWidth);
打开MySurfaceView.java类,在其中添加属性: 为其增加get set 方法
// 敌机的图片
private List<ImageButton> enemyPlanes;
public List<ImageButton> getEnemyPlanes() {
return enemyPlanes;
}
public void setEnemyPlanes(List<ImageButton> enemyPlanes) {
this.enemyPlanes = enemyPlanes;
}
在MySurfaceView.java 中的threadRun 方法中新增一个方法:enemyPlaneShot()如:
/**
* 执行线程
*/
private void threadRun() {
// 你控制的飞机发射
planeShot(yourPlane, false,null);
Log.i(CommonUtil.VIEW_TAG, “控制的飞机射击”);
// 敌人的飞机开火
enemyPlaneShot();
}
增加enemyPlaneShot ()方法
/**
* 敌人的战机开始
*/
private void enemyPlaneShot() {
for (int i = 0,size = enemyPlanes.size(); i < size; i++) {
EnemyPlane enemyPlane = new EnemyPlane();
enemyPlane.setShot(true);
enemyPlane.setLife(CommonUtil.ENEMY_PLAN_LIFE);
// 敌机的位置随机出现横坐标
enemyPlane.setX(enemyPlanes.get(i).getX());
enemyPlane.setY(enemyPlanes.get(i).getY());
// 敌机图片
enemyPlane.setSrcPic(R.drawable.myplane);
// 敌人的飞机发射 ,该方法原来不是这样的,已经新增了参数
planeShot(enemyPlane, true,enemyPlanes.get(i));
}
}
更改以后的planeShot 方法:
/**
* 飞机发射
*
* @param plane
* @param imageButton 敌机的图片
*/
private void planeShot(Plane plane, boolean isEnemyPlane, ImageButton enemyPlanImg) {
// 控制飞机线程
planeRunnable = new PlaneRunnable(context, holder);
// 将控制的飞机绑定到该线程中
planeRunnable.setPlane(plane);
// 屏幕高度
planeRunnable.setWindowHeight(windowHeight);
planeRunnable.setWindowWidth(windowWidth);
planeRunnable
.setPlaneImg(getResources().getDrawable(plane.getSrcPic()));
planeRunnable.setEnemyPlanes(enemyPlanImg);
planeRunnable.setHandler(handler);
// 是否为敌机
planeRunnable.setEnemyPlane(isEnemyPlane);
shotThread = new Thread(planeRunnable);
// 控制的飞机 开始射击
shotThread.start();
}
到现在,PlaneRunnable 中也要增加其它的方法和变量,否则程序一直是报错状态
打开PlaneRunnable.java,在里面加入新的属性:
private boolean enemyPlane = false;// 是否为敌机
// 窗口的大小
private int windowHeight;
private int windowWidth;
// 敌机的图片
private ImageButton enemyPlaneImg;
private Handler handler;
然后将run方法重新判断,使敌机和你控制的飞机区分开来:
@Override
public void run() {
Canvas canvas = null;
while (plane.isShot()) {
canvas = holder.lockCanvas();
canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
Paint paint = new Paint();
paint.setColor(Color.BLUE);
// 如果为敌机,则这架飞机应该往下走,把敌机画出
if (isEnemyPlane()) {
canvas.drawText(CommonUtil.BULLET, plane.getX()
+ planeHalfWidth, plane.getY()+planeImg.getIntrinsicHeight(), paint);
plane.setY(plane.getY() + 10);
// 这里这么直接写会报错,线程非安全,原因是不能在子线程中直接更新UI
// enemyPlaneImg.setY(plane.getY());
Message msg = handler.obtainMessage();
msg.arg1 = 1;
msg.obj = enemyPlaneImg;
msg.arg2 = (int) plane.getY();
handler.sendMessage(msg);
} else {
canvas.drawText(CommonUtil.BULLET, plane.getX()
+ planeHalfWidth, plane.getY(), paint);
}
holder.unlockCanvasAndPost(canvas);
// 发射子弹
shotOneBullet();
// 如果敌机飞到了最下面,那该线程停止射击
if (plane.getY() >= windowHeight) {
plane.setShot(false);
break;
}
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Log.i(CommonUtil.THREAD_TAG, “plane停止射击”);
}
在BulletRunnable.java中,也要增加相应的属性:
private boolean enemyBullet = false;
// 窗口的大小
private int windowHeight;
private int windowWidth;
然后修改run方法,这样做的目的只是为了方便区分敌机和你控制的飞机,以及它们发射的子弹:
@Override
public void run() {
Canvas canvas = null;
while (bullet.isFly()) {
canvas = holder.lockCanvas();
canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
Paint paint = new Paint();
paint.setColor(Color.BLUE);
// 判断是敌机还是我方战机
if (!isEnemyBullet()) {
// 我方战机子弹往上走
canvas.drawText(CommonUtil.BULLET, bullet.getX(),
bullet.getY() – 70, paint);
} else {
// 敌方战机子弹往下走
canvas.drawText(CommonUtil.BULLET, bullet.getX(),
bullet.getY() + 30, paint);
}
holder.unlockCanvasAndPost(canvas);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (!isEnemyBullet()) {
bullet.setY(bullet.getY() – 70);
} else {
bullet.setY(bullet.getY() + 30);
}
if (bullet.getY() <= 0) {
// 如果当前线程的Y超过了屏幕,则将该线程回收
bullet.setFly(false);
// 爆炸效果
boom();
break;
}
if (bullet.getY() >= windowHeight) {
// 如果子弹的Y超过了屏幕底部,则将该线程回收
bullet.setFly(false);
break;
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.i(CommonUtil.THREAD_TAG, “子弹飞行中”);
}
Log.i(CommonUtil.THREAD_TAG, “子弹线程结束”);
}
到目前为止,程序已经可以有敌机、你控制的飞机,所有的飞机都在发射子弹(只不过子弹碰到飞机之后,不会爆炸,而且敌机的移动不是很流畅,还有很多问题需要修改,下次游戏代码:《飞机大战》安卓游戏开发源码(终)),现在效果图如下:
本文章属于原创性文章,珍惜他人劳动成果,转载请注明出处: http://www.pm-road.com/index.php/2014/11/06/169/