1.整体实现思路
在我设计的整个游戏中,把飞机大战这个项目总共可以分为三个对象:第一个是飞机,飞机又可以分为我方飞机,敌方飞机和敌方boss飞机;第二个是背景,为了体现出飞机的飞行,需要用到背景的滚动,而实现背景的滚动又要使用第一个跟第二个背景的衔接,才能完美实现飞行效果;第三个是子弹,既然是飞机大战,肯定需要双方飞机的射击大战,所以在绘制子弹后,便要考虑到子弹与飞机的碰撞,就会考虑到x,y轴的变化,长度和宽度,以及碰撞的效果。其他的便是优化你的程序,比如给这个游戏加一个bgm,比如我方飞机加一些道具。
2.如何绘制循环滚动的背景图片
定义y轴y1,y2,当第一张图片大于等于屏幕长度时,移动到第二张图片的顶部
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.如何绘制飞机
创建飞机类MyPlane
可以在类中添加你所需要的效果(比如击中闪烁无敌等)
最后别忘了在MySurfaceView中的run方法中调用
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);
}
}
4.如何绘制子弹
创建子弹Bullet类:可以在里面定义子弹的属性跟玩家飞机子弹和boss机子弹
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飞机面积范围时产生碰撞效果,boss血量减少
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;
}
飞机与飞机碰撞:
当玩家飞机的上方范围接触到BOSS飞机底端范围实现碰撞,血量减少
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;
}
6.如何绘制爆炸效果
创建一个爆炸类(boom)
在Mysurfaceview,玩家飞机子弹接触Boss飞机范围后实现爆炸效果
爆炸效果由图片剪裁形成
public Boom(Bitmap bitmap, int x, int y, int totalFrame) {
super();
this.bitmap = bitmap;
this.x = x;
this.y = y;
this.totalFrame = totalFrame;
frameW = bitmap.getWidth()/totalFrame;
frameH = bitmap.getHeight();
}
public void draw(Canvas canvas, Paint paint){
canvas.save();
canvas.clipRect(x,y,x+frameW,y+frameH);
canvas.drawBitmap(bitmap,x-currentFrame*frameW,y,paint);
canvas.restore();
logic();
}
if (bossPlane.isCollison(bulletVector.elementAt(i))) {
gameSoundPool.playSound(3);
Boom boom = new Boom(BitmapFactory.decodeResource(getResources(), mipmap.boom), bossPlane.getX()+bossPlane.getFrameW()/3, bossPlane.getY()+bossPlane.getFrameH()/4, 7);
boomVector.add(boom);
}
7.如何添加音效
在res中创建一个raw来放置音频文件,在MySurfaceView中用switch语句调用
public class GameSoundPool {
private SoundPool soundPool;
private int s1;
private int s2;
private int s3;
public GameSoundPool(Context context){
this.soundPool = new SoundPool(2, AudioManager.STREAM_MUSIC,0);
s1 = soundPool.load(context,R.raw.shoot,1);
s2 = soundPool.load(context,R.raw.explosion2,1);
s3 = soundPool.load(context,R.raw.bgm_zhandou2,1);
}
public void playSound(int s) {
switch (s){
case 1:
soundPool.play(s1,1,1,1,1,1.0f);
break;
case 2:
soundPool.play(s2,1,1,1,1,1.0f);
break;
case 3:
soundPool.play(s3,1,1,1,1,1.0f);
break;
}
}
}
8.哪些地方用到封装,继承,多态,方法重载,接口等
封装:每个子类中都实现了不同属性的封装
继承:MyPlane与BossPlane类的位置方法在MySurfaceView中体现了继承
多态:不同种飞机的不同血量范围
重载:玩家飞机与boss飞机相撞
接口:添加音效
9.我的收获与感悟
收获:最大的收获估计就是从之前的一点不懂,到现在能够懂一点,我感觉这是我最大的收获。
其次的话,应该是对编程开始感兴趣了,通过这次项目,让自己了解到,原来自己也是可以在老师的指导下,可以完成自己的项目,不至于像以前一样,无从下手。
感悟:这次的项目,我个人感觉这是一个适合新手来试试编程的水的项目,因为这一个项目,基本可以让你复习并且巩固你java的基础,而且,感觉这个项目的拓展性很强,让你可以运用自己的创新性思维,用程序来实现你的想法,然后制作你自己喜欢的游戏,充分体验编程的乐趣。