敌方坦克发射
创建AutoShot
/**
* 自动射击的能力
*/
interface AutoShot {
//自动射击的功能
fun autoShot(): View?
}
Enemy实现这个接口,重写autoShot方法(Tank中有相同代码,抄一抄)
class Enemy(override var x: Int, override var y: Int) :Moveable, AutoMoveable,Blockable,AutoShot {
......
override fun autoShot(): View? {
return Bullet(currentDirection, { bulletWidth, bulletHeight ->
var tankX = x
var tankY = y
var tankWidth = width
var tankHeight = height
var bulletX = 0
var bulletY = 0
//计算子弹真实的坐标
//如果坦克向上:bulletX = tankX+(tankWidth-bulletWidth)/2
//bulletY = tankY - bulletHeight/2
when (currentDirection) {
Direction.up -> {
bulletX = tankX + (tankWidth - bulletWidth) / 2
bulletY = tankY - bulletHeight / 2
}
Direction.down -> {
bulletX = tankX + (tankWidth - bulletWidth) / 2
bulletY = tankY + tankHeight - bulletHeight / 2
}
Direction.left -> {
bulletX = tankX - bulletWidth / 2
bulletY = tankY + (tankHeight - bulletHeight) / 2
}
Direction.right -> {
bulletX = tankX + (tankWidth - bulletWidth / 2)
bulletY = tankY + (tankHeight - bulletHeight) / 2
}
}
Pair(bulletX, bulletY)
})
}
}
GameWindow中onRefresh中增加
//检测自动射击
views.filter { it is AutoShot }.forEach{
it as AutoShot
var shot:View? = it.autoShot()
shot?.let {
views.add(shot)
}
}
现在运行程序,敌方坦克发射速度很快,现在增加时间控制
class Enemy(override var x: Int, override var y: Int) :Moveable, AutoMoveable,Blockable,AutoShot {
......
//上次射击时间
private var lastShotTime = 0L
//射击频率
private var shotFrequency = 800
private var lastMoveTime = 0L
private var moveFrequency = 50
override fun autoMove() {
//频率检查
var current = System.currentTimeMillis()
if(current - lastMoveTime < moveFrequency) return
lastMoveTime = current
if(currentDirection == badDirection){
//要往错误方向走,不允许
//改变自己方向
currentDirection = rdmDirection(badDirection)
}
//坦克的坐标移动
//根据方向改变坐标
when (currentDirection) {
Direction.up -> y -= speed
Direction.down -> y += speed
Direction.left -> x -= speed
Direction.right -> x += speed
}
//越界判断
if (x < 0) x = 0
if (x > Config.gameWidth - width) {
x = Config.gameWidth - width
}
if (y < 0) y = 0
if (y > Config.gameHeight - height) {
y = Config.gameHeight - height
}
}
......
override fun autoShot(): View? {
var current = System.currentTimeMillis()
if(current - lastShotTime < shotFrequency) return null
lastShotTime = current
......
}
}
双方坦克互相伤害
修改Tank
class Tank(override var x: Int, override var y: Int) : Moveable,Blockable,Sufferable {
......
override var blood: Int = 20
override fun notifySuffer(attackable: Attackable): Array<View>? {
blood -= attackable.attackPower
return arrayOf(Blast(x,y))
}
......
}
修改敌方坦克
class Enemy(override var x: Int, override var y: Int) :Moveable, AutoMoveable,Blockable,AutoShot,Sufferable {
......
override var blood: Int = 2
......
override fun notifySuffer(attackable: Attackable): Array<View>? {
blood -= attackable.attackPower
return arrayOf(Blast(x,y))
}
}
现在运行会发现,各种爆炸,原因是,子弹击中自己后,爆炸了,现在Attackable加一个所有者的属性
interface Attackable : View {
//所有者
var owner:View
......
}
Bullet报错了,修改
class Bullet(override var owner: View,override val currentDirection: Direction, create: (width: Int, height: Int) -> Pair<Int, Int>
) : AutoMoveable,Destroyable,Attackable {
......
}
Tank,Enemy中的autoShot方法修改为
override fun autoShot(): View? {
......
return Bullet(this,currentDirection, { bulletWidth, bulletHeight ->
......
})
}
GameWindow的onRefresh中,让攻击方和发射方不相同
//检测有攻击能力和被攻击能力的物体间是否发生了碰撞
//1)过滤具备攻击能力的
views.filter { it is Attackable }.forEach{attack->
attack as Attackable
//2)具备受攻击能力的(攻击方的源,不可以是发射方)
views.filter { (it is Sufferable) and (attack.owner != it) }.forEach sufferTag@ {suffer->
......
}
}
敌方坦克销毁
class Enemy(override var x: Int, override var y: Int) :Moveable, AutoMoveable,Blockable,AutoShot,Sufferable,Destroyable {
......
override fun isDestroyed(): Boolean = blood<=0
}
现在运行程序,敌方坦克互相伤害,然后不战而胜…
但这样确实缺少了游戏乐趣,我们让敌方坦克不能相互伤害,修改Enemy
class Enemy(override var x: Int, override var y: Int) :Moveable, AutoMoveable,Blockable,AutoShot,Sufferable,Destroyable {
......
override fun notifySuffer(attackable: Attackable): Array<View>? {
//如果攻击方是敌方,挨打不掉血
if(attackable.owner is Enemy) return null
blood -= attackable.attackPower
return arrayOf(Blast(x,y))
}
......
}