Android植物大战僵尸教程学习总结(三)

来源:互联网 发布:全力以赴歌曲网络歌手 编辑:程序博客网 时间:2024/04/30 11:05

植物都处理好了,那接下来先是阳光。

阳光,是由向日葵产生的。所以,我们回到Flower类。这边的话,跟之前的思考方式是一样的,不过加了一个时间的限定,毕竟,阳光产生要冷却的。

private long lastBirthTime;


构造方法里添加:

lastBirthTime = System.currentTimeMillis();

drawSelf方法里添加
if ((System.currentTimeMillis() - lastBirthTime) > 8000) {lastBirthTime = System.currentTimeMillis();giveBirth2Sun();}
然后是
private void giveBirth2Sun() {GameView.getInstance().giveBirth2Sun(locationX, locationY);}
回到GameView,这边很简单,新建一个gameLayout3

已经驾轻就熟了

</pre><pre name="code" class="java"><pre name="code" class="java">public void giveBirth2Sun(int locationX, int locationY) {synchronized (surfaceHolder) {gamelayout3.add(new Sun(locationX, locationY));}}

此时,我们新建Sun类(别忘了全局静态变量的配置和图片资源的配置)

Sun类,想一想,继承BaseModel,接口TouchAble

这里呢,我们用到了枚举Enum

关于Enum

1. 枚举类型定义的一般形式为:
enum 枚举名{ 枚举值表 };
在枚举值表中应罗列出所有可用值。这些值也称为枚举元素。
例如:
该枚举名为weekday,枚举值共有7个,即一周中的七天。凡被说明为weekday类型变量的取值只能是七天中的某一天。
2. 枚举变量的说明
如同结构体(struct)和共用体(union)一样,枚举变量也可用不同的方式说明,即先定义后说明,同时定义说明或直接说明。
设有变量a,b,c被说明为上述的weekday,可采用下述任一种方式:
1
2
3
4
5
6
enum weekday{sun,mon,tue,wed,thu,fri,sat};
enum weekdaya,b,c;
//或者为:
enum weekday{sun,mon,tue,wed,thu,fri,sat}a,b,c;
//或者为:
enum{sun,mon,tue,wed,thu,fri,sat}a,b,c;
通过枚举,我们可以定义阳光的两种状态,一种是显示,一种是移动
public enum SunState {SHOW, MOVE}
先来看构造方法,跟之前卡片的有些类似,只是这个时候需将sunstate对象设置为SHOW

public Sun(int locationX, int locationY) {this.locationX = locationX;this.locationY = locationY;touchArea = new Rect(locationX, locationY, locationX+ Config.sun.getWidth(), locationY + Config.sun.getHeight());lastBirthTime = System.currentTimeMillis();state = SunState.SHOW;isAlive = true;}
我们先从SHOW状态入手

drawSelf方法

public void drawself(Canvas canvas, Paint paint) {if (isAlive) {if (state == SunState.SHOW) {if ((System.currentTimeMillis()-lastBirthTime)>5000) {isAlive=false;}}canvas.drawBitmap(Config.sun, locationX, locationY, paint);}
这边呢,给了一个额外的判定,就是阳光存在5s就会消失(不然你不点,阳光会重复产生的)


onTouch方法

public boolean onTouch(MotionEvent event) {int x = (int) event.getX();int y = (int) event.getY();if (touchArea.contains(x, y)) {state = SunState.MOVE;xWayDistance = locationX - Config.sunDisapperX;yWayDistance = locationY - 0;xSpeed = xWayDistance / 10f;ySpeed = yWayDistance / 10f;}return false;}

这边就涉及到状态的转换了,点击事件触发了,阳光就切换成了MOVE状态。并自动的计算出了距离(消失处),然后算出速度(这里的sunDisappearX是不是很眼熟呢?这是之前设置好的阳光消失的位置)


自然地,在drawSelf方法里添上对应的方法

else {locationX-=xSpeed;locationY-=ySpeed;if (locationY<=0) {isAlive=false;}}
与if形成对应关系


至此为止,阳光也写好了。

接下来就写僵尸了。为了让僵尸的产生与阳光的产生显得更相似一些,我们先来创建一个ZombieManager,继承BaseModel。里面的方法与Flower的差不多,但是不涉及显示自身的一些参数(你是看不到生僵尸的XX的尴尬

public class ZombieManager extends BaseModel {private boolean isAlive;private long lastBirthTime;public ZombieManager() {isAlive = true;lastBirthTime=System.currentTimeMillis();}@Overridepublic void drawself(Canvas canvas, Paint paint) {if ((System.currentTimeMillis()-lastBirthTime)>8000) {lastBirthTime=System.currentTimeMillis();giveBirth2Zombie();}}private void giveBirth2Zombie() {GameView.getInstance().apply4AddZombie();}}
回到GameView,写apply4AddZombie方法。记得先新建ZombieManager的实例,并在ondraw方法里写入 对象.drawSelf,不然可是不会产生僵尸的(这个地方我总是忘记,总是出不来僵尸)

接下来开始写apply4AddZombie方法

public void apply4AddZombie() {synchronized (surfaceHolder) {int raceWay = 0;raceWay = (int) (Math.random() * 5);switch (raceWay) {case 0:gameLayout4Zombie0.add(new Zombie(Config.DeviceWidth,Config.raceWayPointY[0] - Config.heightDistanceLong,raceWay));break;case 1:gameLayout4Zombie1.add(new Zombie(Config.DeviceWidth,Config.raceWayPointY[1] - Config.heightDistanceLong,raceWay));break;
这边,利用Math.random方法来产生随机数,记得强转类型(这边我用的是5而不是4,因为3~3.99都会因为强转变成3,蛋疼的4实在是几乎出不来)

接下来,我们写Zombie类,这个跟之前的植物是一样的。不多说,就是加了个速度。画的时候不断更新就好

public void drawself(Canvas canvas, Paint paint) {if (isAlive) {canvas.drawBitmap(Config.zombieMoveFrames[frames], locationX,locationY, paint);frames = (++frames) % 29;locationX -= xSpeed;}}


别忘了僵尸层的存放,以及ondraw方法,还有deadlist去除

这样,僵尸也画好了


最后,开始写碰撞了

还是在Zombie类

checkCollision();
drawSelf里,只要isAlive==true;

每次判断是否发生碰撞

private void checkCollision() {GameView.getInstance().checkCollision(this, raceWay);}
这个时候,我们忘了一件事。对,在Flower,Pea,以及Zombie中重写getModelWidth方法
public int getModelWidth() {return Config.zombieMoveFrames[0].getWidth();}
另外两个同理

好了,同样的,回到GameView。

public void checkCollision(Zombie zombie, int raceWay) {synchronized (surfaceHolder) {switch (raceWay) {case 0:for (BaseModel model : gameLayout4plant0) {if (Math.abs((model.getLocationX() + model.getModelWidth() / 2)- (zombie.getLocationX() + zombie.getModelWidth() / 2)) < (model.getModelWidth() + zombie.getModelWidth()) / 3) {if (model instanceof Plant) {model.setAlive(false);} else {zombie.setAlive(false);}}}break;
剩下的几层是一样的。这边呢,是根据raceWay来判断的,首先你需要确定僵尸产生的跑到位置。然后遍历这一层上的植物(给植物分5个layout就是这个原因)  接下来就是矩形检测了,这边的意思就是两个矩形的X轴中点位置相减比两个矩形的宽之和的三分之一小就算发生碰撞。(还是比较好理解的) 判断,是植物的话,就让植物死亡。否则,僵尸死亡(豌豆威力有点大尴尬)。

至此,就结束了。总之,这个教程给的还不够完善,因为还有许多可以改进的地方。不过已经3点半了,没想到打个总结打了这么久。睡醒了,明天继续在上面添加一些有意思的内容。附件呢,还是传一下吧。



还有,就是学到了几个使用eclipse的小技巧:

(1)用LogCat调试时,在发生问题非预期情况而又不失error时,可以通过在某些地方加Log.i(String  Tag,String  Message)并在Filter里设置好你所想输出的Tag来检查情况(不设Filter的话就怕乱七八糟的内容太多,反正我是绝大多数看不懂)

(2)ctrl+o可以快速调出查找(可以快速切换至该类的方法或参数的一行),真方便

(3)选中某个类或者变量之类的,按ctrl+alt+H,可以调出被调用的关系(这个我也不知道到底是什么,就这么叫吧),在关系复杂的时候,用这个真的很自然地就能理好顺序了


以上,纯属一个小白的个人理解,有不对的地方,还请大拿不吝赐教。

好吧,附件上传不了,太大了

http://pan.baidu.com/s/18Phs6(百度网盘)




0 0
原创粉丝点击