1,整体实现思路
- 首先,我们要创建一个MySurfaceView()类,然后继承了SurfaceView类和SurfaceHolder.Callback和Runnable接口并实现它们的方法,Callback借口的作用是回调,实现surfaceCreated(),surfaceDestroyed(),surfaceChanged()三个抽象方法
创建SurfaceHolder 的对象surfaceHolder,创建画布类Canvas的对象canvas用private修饰。 - 在MySurfaceView方法中写一个init()方法,在init()方法里初始化surfaceHolder;再添加回调函数surfaceHolder = add.getHolder(),设置可聚焦和屏幕常亮。
- 在surfaceCreated方法中启动一下线程,在run()方法里写surfaceHolder.lockCanvas();锁定画布,再写上surfaceHolder.unlockCanvasAndPost(),解锁画布,显示到屏幕上,其余的功能比如添加背景图,子弹,飞机,爆炸效果 ,新建类 在run方法里调用
- 在最后写一个onTouchEvent方法,永远监听屏幕触摸事件
2.如何绘制循环滚动的背景图片
新建一个BackGround类,定义两张图片的y坐标,定义一个bitmap;创建一个draw方法,用两次drawBitmap方法绘制两张背景图 ;传建一个logic方法,让y坐标每次加10;通过y坐标,用if语句判断一下当第一张背景图移除屏幕时,第二张就立刻移动到第一张图片的顶部
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 ,敌方飞机创建一个BossPlane类,他们的代码是基本一样的,定义横纵坐标x,y;利用xy坐标确定飞机在屏幕上显示的位置,我方飞机还需要设置一个touchEvent方法,让飞机能够跟着鼠标的移动而移动,绘制BossPlane时,需要用到 canvas.clipRect();画布裁剪 ,因为BossPlane有很多个图片,需要裁剪。MyPlane 还需要定义一个Hp血量,飞机撞上boss子弹的时候Hp要减减 BossPlane要有疯狂模式
4.如何绘制子弹
子弹有boss的子弹 还有myplane 的子弹,都需要用到Vector数组,在MySurfaceView中调用
for (int i = 0;i<bulletVector.size();i++){
bulletVector.elementAt(i).draw(canvas,paint);
if (bossPlane.isCollision(bulletVector.elementAt(i))){
gameSoundPool.playSound(2);
Boom boom = new Boom(BitmapFactory.decodeResource(getResources(),R.mipmap.boom),bossPlane.getX()+bossPlane.getFrameW()/4,bossPlane.getY(),7);
boomVector.add(boom);
}
}
5.如何判断碰撞
子弹与飞机碰撞:判断子弹坐标是否在飞机坐标范围内
飞机与飞机碰撞:判断一下飞机的横纵坐标
6.如何绘制爆炸效果
爆炸效果也要用到Vector 数组还要用画布的裁剪, canvas.clipRect(),一定要写save和restore方法,每次移动一帧,就给一个计数器++,让图片一帧一帧循环显示出来爆炸效果
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();
}
public void logic(){
if (currentFrame<totalFrame){
currentFrame++;
}else {
isEnd = true;
}
}
7.如何添加音效
在res下面创一个raw 包,把音乐文件复制进去,写一个GameSoundPool类,定义一个s,用soundPool.load添加音效,用soundPool.play播放 音效
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.bg_logobg,2);
}
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.哪些地方用到封装、继承、多态、方法重载、接口
封装:几乎每个类都用到了封装,定义的参数都用到了private修饰。
继承和接口:MySurfaceView用到了继承和接口,MySurfaceView继承继承了SurfaceView类和SurfaceHolder.Callback和Runnable接口。
方法重载:在子弹类里面 创建了两个名字与类名相同但参数列表不同的Bullet()方法。
多态:没有。
9.收获与感悟
以前还没实训的时候,上Java课偶尔听听,听的似懂非懂,老师给你讲的时候你好像也能听得懂但是让你自己打,就完全毫无头绪,脑子一片空白,没实训的时候听说要实训一个月还有点害怕,因为自己什么都不会,害怕老师讲的太深奥了,就更不懂Java了,就这样在害怕中实训开始了。
前两个星期复习了一下JAVA基础知识点,每天老师讲什么就截图然后照着老师的代码打,打完了就完事了,满足于只要代码不报错能运行,也学到了不少东西,但是概念性的知识点我也不能完全记住,每个知识点我都只是懂一点点。后两个星期就正式开始了与Android studio 斗智斗勇的生活,每天打代码,学习Andriod 之后,感觉代码很神奇,它在别人的程序中总是能给我惊喜,能实现一些我想象不到的功能,于是我也开始认真的去写写代码,发现代码错误后不是第一个去寻求同学的帮助而是自己先看,实在看不出来再去寻求老师或同学的帮助。
在这一个月里,我学会了自己独立思考如何写一个程序,学会了switch语句和do/while循环的使用,Scanner的使用,还知道了很多Java的基础知识点,在以后的Java课上我一定认真听讲,争取Java从入门到精通。