Commit 2f6a8d46 authored by deregges's avatar deregges

added doc for GameActivity, fancied up stats display

parent a6bfc828
......@@ -22,52 +22,77 @@ import splitties.systemservices.sensorManager
import kotlin.math.PI
class GameActivity : AppCompatActivity(), SensorEventListener {
// PROPERTIES //
// rotation sensitivity, already processed to the factor to be applied to the rotation angles
private val rotationSensitivity = Settings.calcRotationSensitivity()
// the screen size
val size by lazy {
PointF().apply {
DisplayMetrics().also { windowManager.defaultDisplay.getRealMetrics(it) }
.let { set(it.widthPixels.toFloat(), it.heightPixels.toFloat()) }
}
}
// the ticks that have passed since start
var ticks = 0
private set
// the current background move speed (px per tick)
var speed: Float = Preferences.difficulty.initialSpeed
// the already collected coins for highscore
var collectedCoins = 0
// the already defeated bosses for highscore
var defeatedBosses = 0
// the current state of the game (start: for touch true, else false)
private var paused = Preferences.inputMethod == Constants.InputMethod.TOUCH
private val pathManager: PathManager by lazy {
PathManager(this)
}
// the current background to be drawn
private var background = Color.BLACK
// holds/manages the path elements
private val pathManager: PathManager by lazy { PathManager(this) }
// the player sprite
val player: Player by lazy {
Player(pathManager).also {
it.setPos(size.x / 2, size.y / 2)
}
}
val size by lazy {
PointF().apply {
DisplayMetrics().also { windowManager.defaultDisplay.getRealMetrics(it) }
.let { set(it.widthPixels.toFloat(), it.heightPixels.toFloat()) }
}
}
var speed: Float = Preferences.difficulty.initialSpeed
private var background = Color.BLACK
val highscore
get() = collectedCoins * Constants.pointsCoinSimple + (ticks * Constants.pointsPerTick).toInt() + defeatedBosses * Constants.pointsPerBoss
// the game looper
private var gameThread: GameThread? = null
// the drawing surface, which is inflated as the content
private val surface: SurfaceView by lazy {
DelegatingSurfaceView(this, this::draw).apply { isFocusable = true }
}
// METHODS //
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(surface)
// force screen on while game runs
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
}
override fun onPause() {
super.onPause()
sensorManager.unregisterListener(this)
// stop gamethread from running
gameThread?.interrupt()
gameThread = null
}
override fun onResume() {
super.onResume()
// register rotation sensor when needed
when (Preferences.inputMethod) {
Constants.InputMethod.ROTATION, Constants.InputMethod.ROTATION2D -> sensorManager.registerListener(
this,
......@@ -76,12 +101,18 @@ class GameActivity : AppCompatActivity(), SensorEventListener {
)
else -> Unit
}
// restart game thread
gameThread = GameThread(this)
}
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) = Unit
override fun onSensorChanged(event: SensorEvent) {
// convert quaternion to rotation angles
// orientation[0] = compass rotation
// orientation[1] = up/down rotation
// orientation[2] = left/right rotation
// all values range from -1 to 1
val rotMatrix = FloatArray(9).also { SensorManager.getRotationMatrixFromVector(it, event.values) }
val orientation = FloatArray(3).also { SensorManager.getOrientation(rotMatrix, it) }
orientation[0] /= PI.toFloat()
......@@ -111,11 +142,24 @@ class GameActivity : AppCompatActivity(), SensorEventListener {
}
}
/**
* Stops the game and displays corresponding dialog with last score
*/
fun gameEnd() {
gameThread?.interrupt()
EndGameDialog.show(this, highscore)
gameThread = null
EndGameDialog.show(this, getScore())
}
/**
* update, to be called by GameThread:
* IF not paused:
* update player
* update pathmanager
* increase speed
* change background color
* increase tick
*/
fun update() {
fun blink() {
if (ticks % (Constants.targetFPS * Constants.blinkMs / 1000).toInt() == 0) {
......@@ -142,6 +186,11 @@ class GameActivity : AppCompatActivity(), SensorEventListener {
}
}
/**
* handles touch event
* 1) TOUCH input: check and set player or pause
* 2) ROTATION input: pause / unpause
*/
@SuppressLint("ClickableViewAccessibility" /* performClick would be useless */)
override fun onTouchEvent(event: MotionEvent): Boolean {
if (Preferences.inputMethod == Constants.InputMethod.TOUCH) {
......@@ -178,6 +227,10 @@ class GameActivity : AppCompatActivity(), SensorEventListener {
return true
}
/**
* to be called by GameThread
* lock canvas and let it redraw (see @draw(Canvas))
*/
fun draw() {
val canvas = surface.holder.lockCanvas()
if (canvas != null) {
......@@ -193,17 +246,25 @@ class GameActivity : AppCompatActivity(), SensorEventListener {
}
}
/**
* to be called by draw()
* draw background
* draw path
* draw player
* draw stats
* draw invincible bar
*/
private fun draw(canvas: Canvas) {
// this is background color
canvas.drawColor(background)
pathManager.draw(canvas)
player.draw(canvas, player.getPaint())
canvas.drawText("Lives: " + player.lives, 0f, 40f, Paint().apply {
canvas.drawText("Lives: ${"\u2764".repeat(player.lives)}", 20f, 60f, Paint().apply {
color = Color.CYAN
textSize = 50f
})
canvas.drawText("Score: $highscore", 0f, 80f, Paint().apply {
canvas.drawText("Score: ${getScore()}", 20f, 130f, Paint().apply {
color = Color.CYAN
textSize = 50f
})
......@@ -216,4 +277,10 @@ class GameActivity : AppCompatActivity(), SensorEventListener {
Paint().apply { color = Color.RED })
}
}
/**
* calculated current score
*/
fun getScore() =
collectedCoins * Constants.pointsCoinSimple + (ticks * Constants.pointsPerTick).toInt() + defeatedBosses * Constants.pointsPerBoss
}
......@@ -86,7 +86,7 @@ class PathManager(val game: GameActivity) : Serializable {
//adds a new path on top of the newest path, if the newest path wasn't a RectPath, a RectPath will be drawn
paths.add(
when (if (paths.last() is RectPath)
if (game.defeatedBosses < game.highscore / 5000 && !boss) 4.apply { boss = true } else (0..3).random()
if (game.defeatedBosses < game.getScore() / 5000 && !boss) 4.apply { boss = true } else (0..3).random()
else 0) {
0 -> RectPath(this, Constants.playerRadius * 4.2f, 400f, PointF(upper.x, upper.y - 75))
1 -> ArcPath(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment