diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6d86594..e1c1db6 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -17,6 +17,7 @@ android:required="true" /> + 0) { this.hp -= decrease if (this.hp <= 0) { diff --git a/app/src/main/java/net/imshit/aircraftwar/element/aircraft/hero/HeroAircraft.kt b/app/src/main/java/net/imshit/aircraftwar/element/aircraft/hero/HeroAircraft.kt index 2352bbc..10a46e4 100644 --- a/app/src/main/java/net/imshit/aircraftwar/element/aircraft/hero/HeroAircraft.kt +++ b/app/src/main/java/net/imshit/aircraftwar/element/aircraft/hero/HeroAircraft.kt @@ -7,10 +7,7 @@ import net.imshit.aircraftwar.element.shoot.hero.HeroShootStrategyFactory import net.imshit.aircraftwar.logic.game.Games class HeroAircraft( - game: Games, - maxHp: Int, - power: Int, - shootNum: Int + game: Games, maxHp: Int, power: Int, shootNum: Int, private val controller: HeroController ) : AbstractAircraft( game = game, initialX = game.width / 2f, @@ -22,7 +19,9 @@ class HeroAircraft( ) { override val image = game.images.aircraftHero override fun forward(timeMs: Int) { - // 英雄机由触控控制,不通过forward函数移动 + this.controller.calcForward(timeMs) + this.x = this.controller.x + this.y = this.controller.y } private val shootStrategyFactory = HeroShootStrategyFactory(game) @@ -40,6 +39,11 @@ class HeroAircraft( return this.shootStrategy.shoot(this.x, this.y, this.speedY, this.power) } + override fun decreaseHp(decrease: Int) { + super.decreaseHp(decrease) + this.controller.onHit() + } + fun increaseHp(increment: Int) { if (increment > 0) { this.hp += increment diff --git a/app/src/main/java/net/imshit/aircraftwar/element/aircraft/hero/HeroController.kt b/app/src/main/java/net/imshit/aircraftwar/element/aircraft/hero/HeroController.kt new file mode 100644 index 0000000..3201a62 --- /dev/null +++ b/app/src/main/java/net/imshit/aircraftwar/element/aircraft/hero/HeroController.kt @@ -0,0 +1,122 @@ +package net.imshit.aircraftwar.element.aircraft.hero + +import android.content.Context +import android.hardware.Sensor +import android.hardware.SensorEvent +import android.hardware.SensorEventListener +import android.hardware.SensorManager +import android.os.VibrationEffect +import android.os.VibratorManager +import android.view.MotionEvent +import android.view.View +import kotlin.math.absoluteValue +import kotlin.math.pow +import kotlin.math.sign + +class HeroController(private val context: Context) : SensorEventListener, View.OnTouchListener { + var x = 0f + private set + var y = 0f + private set + private var vx = 0f + private var vy = 0f + + private var isTouching = false + private var touchX = 0f + private var touchY = 0f + + private var gravityAx = 0f + private var gravityAy = 0f + + private lateinit var game: View + private val sensorManager = + this.context.getSystemService(Context.SENSOR_SERVICE) as SensorManager + private val gravitySensor = this.sensorManager.run { + getDefaultSensor(Sensor.TYPE_GRAVITY) ?: getDefaultSensor(Sensor.TYPE_ACCELEROMETER) + } + private val vibrator = + (this.context.getSystemService(Context.VIBRATOR_MANAGER_SERVICE) as VibratorManager).defaultVibrator + + fun init(game: View) { + this.game = game + this.x = game.width / 2f + this.y = game.height / 2f + // 触摸屏 + game.setOnTouchListener(this) + } + + fun start() { + gravitySensor?.let { + sensorManager.registerListener( + this, it, SensorManager.SENSOR_DELAY_NORMAL + ) + } + } + + fun stop() { + if (gravitySensor != null) { + sensorManager.unregisterListener(this) + } + } + + fun calcForward(timeMs: Int) { + if (isTouching) { + val diffX = (touchX - x) / game.width * 20 + val diffY = (touchY - y) / game.width * 20 + vx = 0.05f * (diffX.absoluteValue).pow(2) * diffX.sign + vy = 0.05f * (diffY.absoluteValue).pow(2) * diffY.sign + } else { + vx += gravityAx * 0.01f + vy += gravityAy * 0.01f + } + x += vx * timeMs + y += vy * timeMs + if (x < 0f) { + x = 0f + vx = 0f + } else if (x > game.width) { + x = game.width.toFloat() + vx = 0f + } + if (y < 0f) { + y = 0f + vy = 0f + } else if (y > game.height) { + y = game.height.toFloat() + vy = 0f + } + } + + fun onHit() { + vibrator.vibrate( + VibrationEffect.createPredefined(VibrationEffect.EFFECT_DOUBLE_CLICK) + ) + } + + // 处理重力事件 + override fun onSensorChanged(event: SensorEvent?) { + this.gravityAx = -(event?.values?.get(0) ?: 0.0f) + this.gravityAy = event?.values?.get(1) ?: 0.0f + } + + override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {} + + // 处理触摸事件 + override fun onTouch(v: View?, event: MotionEvent?): Boolean { + v?.performClick() + event?.let { + when (it.action) { + MotionEvent.ACTION_UP -> { + isTouching = false + } + + else -> { + isTouching = true + touchX = it.x + touchY = it.y + } + } + } + return true + } +} \ No newline at end of file diff --git a/app/src/main/java/net/imshit/aircraftwar/logic/game/Games.kt b/app/src/main/java/net/imshit/aircraftwar/logic/game/Games.kt index ea2eef4..6c7e32c 100644 --- a/app/src/main/java/net/imshit/aircraftwar/logic/game/Games.kt +++ b/app/src/main/java/net/imshit/aircraftwar/logic/game/Games.kt @@ -6,10 +6,6 @@ import android.graphics.Canvas import android.graphics.Color import android.graphics.Paint import android.graphics.Typeface -import android.hardware.Sensor -import android.hardware.SensorEvent -import android.hardware.SensorEventListener -import android.hardware.SensorManager import android.os.Handler import android.os.Message import android.util.AttributeSet @@ -28,6 +24,7 @@ import net.imshit.aircraftwar.element.AbstractFlyingObject import net.imshit.aircraftwar.element.aircraft.enemy.BossEnemy import net.imshit.aircraftwar.element.aircraft.enemy.Enemies import net.imshit.aircraftwar.element.aircraft.hero.HeroAircraft +import net.imshit.aircraftwar.element.aircraft.hero.HeroController import net.imshit.aircraftwar.element.animation.DyingAnimation import net.imshit.aircraftwar.element.bullet.Bullets import net.imshit.aircraftwar.element.bullet.EnemyBullet @@ -40,8 +37,6 @@ import net.imshit.aircraftwar.logic.music.BasicMusicStrategy import net.imshit.aircraftwar.logic.music.BgmType import net.imshit.aircraftwar.logic.music.MusicStrategies import net.imshit.aircraftwar.logic.music.MuteMusicStrategy -import kotlin.math.max -import kotlin.math.min sealed class Games( context: Context, attrs: AttributeSet?, soundMode: Boolean, private val handler: Handler? @@ -71,22 +66,8 @@ sealed class Games( const val SCORE_Y = SCORE_SIZE + 10f } - class AccelerateSensorListener(val callback: (Float, Float, Float) -> Unit) : - SensorEventListener { - override fun onSensorChanged(event: SensorEvent?) { - val ax = event?.values?.get(0) ?: 0.0f - val ay = event?.values?.get(1) ?: 0.0f - val az = event?.values?.get(2) ?: 0.0f - callback(ax, ay, az) - } - - override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {} - } - // utils - private lateinit var sensorManager: SensorManager - private var gravitySensor: Sensor? = null - private lateinit var gravitySensorListener: AccelerateSensorListener + private val heroController = HeroController(context) lateinit var images: ImageManager private var logicJob: Job? = null @@ -114,10 +95,10 @@ sealed class Games( private var boss: BossEnemy? = null // bundle of variables + private val heroList = mutableListOf() private val autoElementLists = - listOf(animations, props, enemyBullets, heroBullets, enemyAircrafts) + listOf(animations, props, enemyBullets, heroBullets, enemyAircrafts, heroList) private val enemyListenerLists = listOf>(enemyAircrafts, enemyBullets) - private val heroList = mutableListOf() private val drawingElementLists = listOf(enemyBullets, heroBullets, enemyAircrafts, props, animations, heroList) private val lifeBarElementLists = listOf(heroList, enemyAircrafts) @@ -157,32 +138,14 @@ sealed class Games( } } - private fun initHeroController() { - // 触摸屏 - setOnTouchListener { view, motionEvent -> - view.performClick() - this.heroAircraft.x = motionEvent.x - this.heroAircraft.y = motionEvent.y - true - } - // 重力感应 - sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager - with(sensorManager) { - gravitySensor = - getDefaultSensor(Sensor.TYPE_GRAVITY) ?: getDefaultSensor(Sensor.TYPE_ACCELEROMETER) - } - gravitySensorListener = AccelerateSensorListener { ax, ay, _ -> - this.heroAircraft.x = min(max(0f, this.heroAircraft.x - ax), this.width.toFloat()) - this.heroAircraft.y = min(max(0f, this.heroAircraft.y + ay), this.height.toFloat()) - } - } - open fun init() { this.images = ImageManager(context.applicationContext, width) - this.heroAircraft = HeroAircraft(game = this, maxHp = 1000, power = 50, shootNum = 1) + this.heroAircraft = HeroAircraft( + game = this, maxHp = 1000, power = 50, shootNum = 1, controller = this.heroController + ) this.heroList.add(this.heroAircraft) this.holder.addCallback(this) - initHeroController() + this.heroController.init(this) this.musicStrategy.setBgm(BgmType.NORMAL) } @@ -190,11 +153,7 @@ sealed class Games( if (!isGameOver) { this.isStopped = false this.musicStrategy.setBgm(BgmType.NORMAL) - gravitySensor?.let { - sensorManager.registerListener( - gravitySensorListener, it, SensorManager.SENSOR_DELAY_NORMAL - ) - } + this.heroController.start() this.logicJob?.cancel() this.logicJob = launch { while (!isStopped) { @@ -211,9 +170,7 @@ sealed class Games( private fun stop() { this.isStopped = true this.musicStrategy.setBgm(BgmType.NONE) - if (gravitySensor != null) { - sensorManager.unregisterListener(gravitySensorListener) - } + this.heroController.stop() this.logicJob?.cancel() this.logicJob = null }