Commit 8f76ed98 authored by deregges's avatar deregges

Removed GameOptions, back to static

Added orientation input option (WIP)
Added debug suffix to debug version builds
Updated Android build tools
Increased app version (version 1.0.2 build references previous commit nevertheless)
parent 6556f924
......@@ -38,6 +38,9 @@ android {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
versionNameSuffix "-debug"
}
}
compileOptions {
sourceCompatibility = '1.8'
......
......@@ -8,11 +8,12 @@ import android.view.SurfaceHolder
import android.view.SurfaceView
import io.ender.pathchaser.paths.PathManager
import io.ender.pathchaser.util.Constants
import io.ender.pathchaser.util.Preferences
import io.ender.pathchaser.util.intersects
import java.io.Serializable
@SuppressLint("ViewConstructor")
class Game(@Transient private val gameActivity: GameActivity, val options: GameOptions) : SurfaceView(gameActivity),
class Game(@Transient private val gameActivity: GameActivity) : SurfaceView(gameActivity),
SurfaceHolder.Callback, Serializable {
var ticks = 0
private set
......@@ -28,7 +29,7 @@ class Game(@Transient private val gameActivity: GameActivity, val options: GameO
DisplayMetrics().also { gameActivity.windowManager.defaultDisplay.getRealMetrics(it) }
.let { set(it.widthPixels.toFloat(), it.heightPixels.toFloat()) }
}
var speed: Float = options.difficulty.initialSpeed
var speed: Float = Preferences.difficulty.initialSpeed
private var background = Color.BLACK
private val highscore
get() = collectedCoins * Constants.pointsCoinSimple + (ticks * Constants.pointsPerTick).toInt()
......@@ -53,27 +54,29 @@ class Game(@Transient private val gameActivity: GameActivity, val options: GameO
@SuppressLint("ClickableViewAccessibility" /* performClick would be useless */)
override fun onTouchEvent(event: MotionEvent): Boolean {
when (event.action) {
MotionEvent.ACTION_DOWN, MotionEvent.ACTION_MOVE -> {
if (paused) {
if (player.intersects(Path().apply {
addRect(
event.x,
event.y + Constants.playerOffset.y,
event.x + 1,
event.y + 1 + Constants.playerOffset.y,
Path.Direction.CW
)
})) {
if (Preferences.inputMethod == Constants.InputMethod.TOUCH) {
when (event.action) {
MotionEvent.ACTION_DOWN, MotionEvent.ACTION_MOVE -> {
if (paused) {
if (player.intersects(Path().apply {
addRect(
event.x,
event.y + Constants.playerOffset.y,
event.x + 1,
event.y + 1 + Constants.playerOffset.y,
Path.Direction.CW
)
})) {
player.setTouchPos(event.x, event.y)
paused = false
}
} else {
player.setTouchPos(event.x, event.y)
paused = false
}
} else {
player.setTouchPos(event.x, event.y)
}
}
MotionEvent.ACTION_UP -> {
paused = true
MotionEvent.ACTION_UP -> {
paused = true
}
}
}
return true
......@@ -84,7 +87,7 @@ class Game(@Transient private val gameActivity: GameActivity, val options: GameO
player.update()
pathManager.update()
if (ticks % 30 == 0)
speed += options.difficulty.speedPerSecond
speed += Preferences.difficulty.speedPerSecond
if (player.invincible)
blink()
......@@ -118,8 +121,6 @@ class Game(@Transient private val gameActivity: GameActivity, val options: GameO
}
}
data class GameOptions(val difficulty: Constants.Difficulty) : Serializable
private fun blink() {
if (ticks % (Constants.targetFPS * Constants.blinkMs / 1000).toInt() == 0) {
val iteration =
......@@ -139,4 +140,17 @@ class Game(@Transient private val gameActivity: GameActivity, val options: GameO
EndGameDialog.show(gameActivity, highscore)
}
}
fun orientationUpdate(orientation: FloatArray) {
when (Preferences.inputMethod) {
Constants.InputMethod.ROTATION -> {
player.delta.x = orientation[2]
player.delta.y = orientation[1]
}
Constants.InputMethod.ROTATION2D -> {
player.delta.x = orientation[2]
}
Constants.InputMethod.TOUCH -> Unit
}
}
}
package io.ender.pathchaser
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import io.ender.pathchaser.util.Constants
import io.ender.pathchaser.util.Preferences
import splitties.systemservices.sensorManager
import kotlin.math.PI
class GameActivity : AppCompatActivity() {
class GameActivity : AppCompatActivity(), SensorEventListener {
private var gameThread: GameThread? = null
lateinit var game: Game
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
game = Game(this, Game.GameOptions(Preferences.difficulty))
game = Game(this)
setContentView(game)
}
......@@ -19,8 +26,34 @@ class GameActivity : AppCompatActivity() {
super.onPause()
gameThread?.interrupt()
gameThread = null
sensorManager.unregisterListener(this)
}
override fun onResume() {
super.onResume()
when (Preferences.inputMethod) {
Constants.InputMethod.ROTATION, Constants.InputMethod.ROTATION2D -> sensorManager.registerListener(
this,
sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR),
SensorManager.SENSOR_DELAY_GAME
)
else -> Unit
}
gameThread = GameThread(game)
}
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) = Unit
override fun onSensorChanged(event: SensorEvent) {
val rotMatrix = FloatArray(9).also { SensorManager.getRotationMatrixFromVector(it, event.values) }
val orientation = FloatArray(3).also { SensorManager.getOrientation(rotMatrix, it) }
orientation[0] /= PI.toFloat()
orientation[1] *= 2 / PI.toFloat()
orientation[2] *= 2 / PI.toFloat()
game.orientationUpdate(orientation)
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putSerializable("game", game)
......@@ -31,11 +64,6 @@ class GameActivity : AppCompatActivity() {
game = savedInstanceState.get("game") as Game
}
override fun onResume() {
super.onResume()
gameThread = GameThread(game)
}
override fun onWindowFocusChanged(hasFocus: Boolean) { // fullscreen trick
super.onWindowFocusChanged(hasFocus)
if (hasFocus) {
......
......@@ -4,12 +4,11 @@ import io.ender.pathchaser.util.Constants
class GameThread(private val game: Game) : Thread() {
companion object {
private const val targetTime = (1000 / Constants.targetFPS)
private const val targetTime = 1000 / Constants.targetFPS
}
init {
name = "PathChaser Game thread"
computeFrame()
start()
}
......@@ -42,8 +41,6 @@ class GameThread(private val game: Game) : Thread() {
}
val waitTime = targetTime - (System.currentTimeMillis() - start)
if (waitTime > 0) {
sleep(waitTime)
}
if (waitTime > 0) sleep(waitTime)
}
}
......@@ -4,12 +4,13 @@ import android.graphics.*
import io.ender.pathchaser.collectibles.Shields
import io.ender.pathchaser.paths.PathManager
import io.ender.pathchaser.util.Constants
import io.ender.pathchaser.util.Preferences
import io.ender.pathchaser.util.contains
import io.ender.pathchaser.util.intersects
import kotlin.concurrent.thread
class Player(pm: PathManager) : Sprite(pm) {
var lives = pm.game.options.difficulty.lives
var lives = Preferences.difficulty.lives
set(value) {
if (!invincible)
if (lives > 1) {
......@@ -27,8 +28,9 @@ class Player(pm: PathManager) : Sprite(pm) {
set(value) {
invincibleStart = if (value) pm.game.ticks else -1
}
lateinit var pos: PointF
val shields: MutableCollection<Shields> = mutableSetOf()
val pos: PointF = PointF(0f, 0f)
val delta: PointF = PointF(0f, 0f)
init {
setPos(0f, 0f)
......@@ -39,7 +41,7 @@ class Player(pm: PathManager) : Sprite(pm) {
addCircle(x, y, Constants.playerRadius, Path.Direction.CW)
for (sh in shields)
sh.offset(x - pos.x, y - pos.y)
pos = PointF(x, y)
pos.set(x, y)
}
fun setTouchPos(x: Float, y: Float) = setPos(x + Constants.playerOffset.x, y + Constants.playerOffset.y)
......@@ -62,7 +64,7 @@ class Player(pm: PathManager) : Sprite(pm) {
)
})
if (pm.game.options.difficulty.diffRes < Constants.Difficulty.HARD.diffRes)
if (Preferences.difficulty.diffRes < Constants.Difficulty.HARD.diffRes)
shields.removeAll { !(it.contains(unified)) }
return contains(unified)
......@@ -93,5 +95,7 @@ class Player(pm: PathManager) : Sprite(pm) {
}
shields.remove(rs)
pos.x += delta.x
pos.y += delta.y
}
}
......@@ -4,12 +4,14 @@ import android.graphics.Color
import android.graphics.Paint
import android.graphics.PointF
import io.ender.pathchaser.paths.PathManager
import io.ender.pathchaser.util.Preferences
import kotlin.math.max
class SpeedDown(pm: PathManager, p: PointF) : Collectible(pm, p) {
override fun getPaint(): Paint = Paint().apply { color = Color.BLUE }
override fun trigger() {
pm.game.speed = max(pm.game.speed - pm.game.options.difficulty.speedDownCoinStrength, pm.game.options.difficulty.initialSpeed)
pm.game.speed =
max(pm.game.speed - Preferences.difficulty.speedDownCoinStrength, Preferences.difficulty.initialSpeed)
}
}
......@@ -4,11 +4,12 @@ import android.graphics.Color
import android.graphics.Paint
import android.graphics.PointF
import io.ender.pathchaser.paths.PathManager
import io.ender.pathchaser.util.Preferences
class SpeedUp(pm: PathManager, p: PointF) : Collectible(pm, p) {
override fun getPaint(): Paint = Paint().apply { color = Color.RED }
override fun trigger() {
pm.game.speed += pm.game.options.difficulty.speedUpCoinStrength
pm.game.speed += Preferences.difficulty.speedUpCoinStrength
}
}
\ No newline at end of file
package io.ender.pathchaser.menu
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import com.xw.repo.BubbleSeekBar
import io.ender.pathchaser.R
import io.ender.pathchaser.util.Constants
import io.ender.pathchaser.util.Preferences
import io.ender.pathchaser.R
import io.ender.pathchaser.util.Utils
import kotlinx.android.synthetic.main.settings.*
import splitties.toast.longToast
import splitties.views.textResource
import kotlin.math.max
class Settings : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
......@@ -20,6 +27,7 @@ class Settings : AppCompatActivity() {
difficulty.configBuilder
.min(0f)
.max(maxDiff.toFloat())
.progress(Preferences.difficulty.ordinal.toFloat())
.autoAdjustSectionMark()
.sectionCount(maxDiff)
.sectionTextPosition(BubbleSeekBar.TextPosition.BELOW_SECTION_MARK)
......@@ -68,6 +76,31 @@ class Settings : AppCompatActivity() {
longToast(R.string.settings_highscoresCleared)
}
inputMethod.adapter = object : ArrayAdapter<Constants.InputMethod>(
this,
android.R.layout.simple_list_item_1,
Constants.InputMethod.validValues()
) {
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val res = super.getView(position, convertView, parent) as TextView
res.textResource = Constants.InputMethod.validValues()[position].display
return res
}
override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View {
val res = super.getDropDownView(position, convertView, parent) as TextView
res.textResource = Constants.InputMethod.validValues()[position].display
return res
}
}
inputMethod.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onNothingSelected(parent: AdapterView<*>?) = Unit
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
Preferences.inputMethod = Constants.InputMethod.validValues()[position]
}
}
inputMethod.setSelection(max(Constants.InputMethod.validValues().indexOf(Preferences.inputMethod), 0))
Utils.animateView(window.decorView, 0, 0.3f, 0.8f, 20_000)
}
}
\ No newline at end of file
......@@ -2,8 +2,11 @@ package io.ender.pathchaser.util
import android.graphics.Color
import android.graphics.PointF
import android.hardware.Sensor
import androidx.annotation.StringRes
import io.ender.pathchaser.R
import splitties.resources.appStr
import splitties.systemservices.sensorManager
object Constants {
const val playerRadius = 50f
......@@ -30,11 +33,23 @@ object Constants {
val speedUpCoinStrength: Float,
val speedDownCoinStrength: Float
) {
EASY(R.string.difficultyEasy, 5, 0f, 0.02f, 0.01f, Float.MAX_VALUE),
NORMAL(R.string.difficultyNormal, 3, 1f, 0.01f, 1f, 1f),
HARD(R.string.difficultyHard, 2, 2.5f, 0.02f, 1f, 1f),
EXTREME(R.string.difficultyExtreme, 1, 3f, 0.05f, 2f, 1f);
EASY(R.string.difficultyEasy, 5, 3f, 0.02f, 0.01f, Float.MAX_VALUE),
NORMAL(R.string.difficultyNormal, 3, 4f, 0.04f, 1f, 1f),
HARD(R.string.difficultyHard, 2, 5f, 0.06f, 1f, 1f),
EXTREME(R.string.difficultyExtreme, 1, 6f, 0.08f, 2f, 1f);
val diffName: String get() = appStr(diffRes)
}
enum class InputMethod(@StringRes val display: Int, private val isValid: () -> Boolean) {
TOUCH(R.string.inputMethodTouch, { true }),
ROTATION(R.string.inputMethodRotation, { sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR) != null }),
ROTATION2D(
R.string.inputMethodRotation2D,
{ sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR) != null });
companion object {
fun validValues() = values().filter { it.isValid() }
}
}
}
\ No newline at end of file
......@@ -5,10 +5,16 @@ import splitties.preferences.DefaultPreferences
object Preferences : DefaultPreferences() {
private var difficulty0 by intPref(Constants.Difficulty.NORMAL.ordinal)
var difficulty: Constants.Difficulty
get() = Constants.Difficulty.values()[difficulty0]
get() = Constants.Difficulty.values().getOrElse(difficulty0) { Constants.Difficulty.NORMAL }
set(value) {
difficulty0 = value.ordinal
}
var volume by floatPref(50f)
var lastName by stringPref("")
private var inputMethod0 by intPref(Constants.InputMethod.TOUCH.ordinal)
var inputMethod: Constants.InputMethod
get() = Constants.InputMethod.values().getOrElse(inputMethod0) { Constants.InputMethod.TOUCH }
set(value) {
inputMethod0 = value.ordinal
}
}
\ No newline at end of file
......@@ -31,12 +31,23 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:gravity="center"
android:text="@string/settings_titleInputMethod"
android:textSize="25sp"/>
<Spinner
android:id="@+id/inputMethod"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/btnClearHighscores"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/settings_btnClearHighscores"
android:layout_marginTop="30dp"/>
</LinearLayout>
\ No newline at end of file
......@@ -24,4 +24,8 @@
<string name="endGameHighscore">HIGHSCORE!!! Platz:</string>
<string name="creditsTitle">CREDITS</string>
<string name="creators">Erstellt von Daniel Drießen und Nico Eckes</string>
<string name="settings_titleInputMethod">Eingabe</string>
<string name="inputMethodTouch">Berührung</string>
<string name="inputMethodRotation">Neigung (3D)</string>
<string name="inputMethodRotation2D">Neigung (2D)</string>
</resources>
......@@ -7,7 +7,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.0-alpha06'
classpath 'com.android.tools.build:gradle:3.5.0-alpha07'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
......
......@@ -15,4 +15,4 @@ org.gradle.jvmargs=-Xmx1536m
kotlin.code.style=official
android.useAndroidX=true
android.enableJetifier=true
appVersion=1.0.1
\ No newline at end of file
appVersion=1.0.2
\ No newline at end of file
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