1.整体实现思路
在做这个游戏刚开始第一天时,不知如何着手,思路很乱,不能统观全局,抓不住其中要点,窥不透真义.几天下来,在江哥的引导下,基本完成了简单的功能,现在回顾一下过程中的心得以及遇到的问题:首先创建四个类,BOSS类和我方机子弹类,BOSS类,我方机类,类中定义各自的横竖x y坐标属性,值得注意的是,在写构造的时候,子弹的构造需要传入参数,因为子弹英雄机和敌机发出来的。再定义两种子弹移动方法。移动方法很好写,子弹垂直方向发,x——就行了。再在main中调用就行了。在这个过程中最重要的创建几个类来实现程序的运行。
2.如何绘制循环滚动的背景图片
首先,先创建一个背景类,然后定义图片的布局,创建一个图片类,并设置图片的大小和坐标,然后调用图片采用的布局方式,显示图片,创建数组然后添加图片,重要的是如何实现图片的滚动,使用while循环来写,然后实现图片的切换,设置一定的时间在几毫秒之间。最后实行while循环使一张图片来回播放,由于间隔时间较短所以肉眼很难分清是图片的滚动循环。
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
class BackGround {
private int y1;
private int y2;
private Bitmap bitmap;
public BackGround(Bitmap bitmap){
this.bitmap = bitmap;
y1=0;
y2=y1-bitmap.getHeight();
}
public void draw(Canvas canvas,Paint paint){
logic();
canvas.drawBitmap(bitmap,0,y1,paint);
canvas.drawBitmap(bitmap,0,y2,paint);
}
public void logic() {
y1+=10;
y2+=10;
if (y1>=MySurfaceView.height){
y1=y2-bitmap.getHeight();//移动到第二张图片的顶部
}
if (y2>=MySurfaceView.height){
y2=y1-bitmap.getHeight();
}
}
}
3.如何绘制飞机
首先绘制BOSS类飞机,首先定义飞机的坐标,定义飞机的宽度和高度,然后定义飞机的速度和计数器,然后 定义飞机时间的间隔最后定义飞机的血量,给飞机定义一个初始血量为Hp,然后用Canvas的方法调用到飞机的图片,最后再在主类中调用Myplane中的draw。
我方飞机:
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.view.MotionEvent;
public class Myplane {
private Bitmap bitmap;
private Bitmap bitmapHp;
private int x,y;
private int width,height;
private boolean noCollision;
private int noCollisionCount;
private int hp =3;
public Myplane(Bitmap bitmap, Bitmap bitmapHp){
this.bitmap = bitmap;
this.bitmapHp = bitmapHp;
x = MySurfaceView.width/2-bitmap.getWidth()/2;
y = MySurfaceView.height-bitmap.getHeight();
width = bitmap.getWidth();
height = bitmap.getHeight();
}
public void draw(Canvas canvas,Paint paint){
if(hp<=0){
MySurfaceView.GAME_STATE = 2;
}
if (noCollision){
noCollisionCount++;
if (noCollisionCount%10==0){
canvas.drawBitmap(bitmap,x,y,paint);//飞机闪烁
}
if (noCollisionCount>100){//无敌时间
noCollision = false;
noCollisionCount = 0;
}
}else {
//非无敌状态
canvas.drawBitmap(bitmap,x,y,paint);
}
for (int i = 0; i<hp; i++){
canvas.drawBitmap(bitmapHp,i*bitmapHp.getWidth(),MySurfaceView.height-bitmapHp.getHeight(),paint);
}
}
public void touchEvent(MotionEvent event){
if (event.getAction()==MotionEvent.ACTION_MOVE){
float ex = (int) event.getX();
float ey = (int) event.getY();
if (ex>x&&ex<x+width&&ey>y&&ey<y+height){
x = (int) ex-width/2;
y = (int) ey-height/2;
if(y<0){
y=0;
}
if(y+height>MySurfaceView.height){
y=MySurfaceView.height-height;
}
}
}
}
public boolean isCollision(Bullet bullet){
if (noCollision){
return false;
}else{
if (bullet.getX()>x&&bullet.getX()<x+width&&bullet.getY()>y&&bullet.getY()<y+height){
noCollision = true;
if (hp>0){
hp--;
}
return true;
}
}
return false;
}
public boolean isCollision(BossPlane bossPlane) {
if (noCollision){
return false;
}else{
if(bossPlane.getY()+bossPlane.getFrameH()>y&&bossPlane.getY()+bossPlane.getFrameH()<y+height){
if(x<bossPlane.getX()&&x+width>bossPlane.getX()){
noCollision = true;
if (hp>0){
hp--;
}
return true;
}
if (x>bossPlane.getX()&&x+width<bossPlane.getX()+bossPlane.getFrameW()){
noCollision = true;
if (hp>0){
hp--;
}
return true;
}
if (x>bossPlane.getX()&&+x+width>bossPlane.getX()+bossPlane.getFrameW()){
noCollision = true;
if (hp>0){
hp--;
}
return true;
}
}
}
return false;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getWidth() {
return width;
}
}
敌方飞机:
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.Log;
public class BossPlane {
private Bitmap bitmap;
private int x,y;
private int frameW,frameH;
private int speed=5;//boos飞机的速度
private int crazySpeed=50;//疯狂速度
private int count;//计数器
private int time=500;//疯狂模式间隔
private boolean isCrazy;
private int bossHp = 10000;
public BossPlane(Bitmap bitmap) {
this.bitmap = bitmap;
this.frameW = bitmap.getWidth()/10;
this.frameH = bitmap.getHeight();
x=MySurfaceView.width/2-frameH/2;
}
public void draw(Canvas canvas, Paint paint){
canvas.save();
canvas.clipRect(x,y,x+frameW,y+frameH);
canvas.drawBitmap(bitmap,x,y,paint);
canvas.restore();
logic();
}
public void logic(){
count++;
if (isCrazy){
y = y+crazySpeed;
crazySpeed--;
if (y==0){
isCrazy = false;
crazySpeed = 50;
}
}else {
if (count%time==0){
isCrazy=true;
}
x = x+speed;
if (x>MySurfaceView.width-frameH){
speed = -speed;
}
if (x<0){
speed = -speed;
}
}
}
public boolean isCollision(Bullet bullet){
if(bullet.getX()>x&&bullet.getX()+bullet.getBitmap().getWidth()<x+frameW&&bullet.getY()>y&&bullet.getY()<y+frameH){
bossHp--;
bullet.setDead(true);
if (bossHp<0){
MySurfaceView.GAME_STATE = 1;
}
return true;
}
return false;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getFrameW() {
return frameW;
}
public int getFrameH() {
return frameH;
}}
4.如何绘制子弹
子弹和飞机本质上几乎相同,所以考虑到把它们都继承自Entity类。不同的是子弹是跟飞机位置有联系的,它从飞机的头部发射出来,之后才能脱离飞机的控制自由运动。子弹不能像飞机一样随意出现在屏幕上,当标志说明子弹没有出现时,将其坐标设定为飞机头部所在坐标;当标志说明子弹已经出现时,则在子弹现有坐标的基础上Y轴增加,每次的增加量是子弹的速度。另外子弹和飞机都是受系统控制自己运动,所以都要放在update()函数中,并且由于update()函数刷新很快,需要设定一定的时延。
import android.graphics.Canvas;
import android.graphics.Paint;
public class Bullet {
private Bitmap bitmap;
private int x, y;
private int speed = 10;
private boolean isDead;
private int type;
public Bullet(Bitmap bitmap, int x, int y,int type) {
this.bitmap = bitmap;
this.x = x;
this.y = y;
this.type = type;
}
public Bullet() {
}
public void draw(Canvas canvas, Paint paint) {
canvas.drawBitmap(bitmap, x, y, paint);
logic();
}
public void logic() {
switch (type){
//玩家子弹
case 0:
y -= speed+5;
if (y < 0) {
isDead = true;
}
break;
//Boss子弹
case 1:
y += speed+8;
if (y < 0) {
isDead = true;
}
break;
default:
break;
} }
5.如何判断碰撞(子弹与飞机碰撞,飞机与飞机碰撞)
当飞机的坐标和子弹的坐标重合一样的时候,就会实现玩家飞机血量的减少,来体现玩家飞机已经碰撞上了子弹,当子弹碰到飞机的整个坐标(包括宽度和高度)就会发生碰撞,当BOSS机的坐标与玩家飞机坐标相互重合或者相交就会使得飞机与飞机相撞,就会实现玩家的血量下降!
//我方飞机与boss子弹
public boolean isCollision(Bullet bullet) {
if (noCollision) {
return false;
}
if (bullet.getX() > x && bullet.getX() < x + width && bullet.getY() > y && bullet.getY() < y + height) {
noCollision = true;
if (Hp > 0) {
Hp--;
}
return true;
}
return false;
}
6.如何绘制爆炸效果
首先,创建一个boom类,当子弹坐标与飞机坐标相互重合,就会产生碰撞,最终实现爆炸效果,爆炸效果由一组图片完成,他会参照背景图片一样的方式来实现,由第一张图片迅速闪过到最后一张图片,从而产生爆炸效果。
public boolean isCollision(Bullet bullet) {
if (noCollision) {
return false;
}
if (bullet.getX() > x && bullet.getX() < x + width && bullet.getY() > y && bullet.getY() < y + height) {
noCollision = true;
if (Hp > 0) {
Hp--;
}
return true;
}
return false;
}
7.如何添加音效
首先,创建一个gamesoundpool类,先让他实例化,然后赋予他音频文件,
import android.content.Context;
import android.media.AudioManager;
import android.media.SoundPool;
public class GameSoundPool {
private SoundPool soundPool;
private int s1;
private int s2;
public GameSoundPool(Context context){
this.soundPool = new SoundPool(2,AudioManager.STREAM_MUSIC,0);
this.soundPool = new SoundPool(1,AudioManager.STREAM_MUSIC,0);
s1 = soundPool.load(context,R.raw.shoot,1);
s2 = soundPool.load(context,R.raw.button,1);
}
public void playSound(){
soundPool.play(s1,1,1,1,1,1.0f);
soundPool.play(s2,1,1,1,1,1.0f);
}
}
8.哪些地方用到封装,继承,多态,方法重载,接口等
继承和接口就MySurfaceView中实现,这个类要继承SurfaceView,还要实现SurfaceHolder.Callback,Runnable的接口。