mirror of
https://github.com/cmclark00/mintris.git
synced 2025-05-18 02:35:21 +01:00
Add title screen with falling tetrominos and fix game resume functionality
This commit is contained in:
parent
a56f08afb9
commit
9fbffc00d0
6 changed files with 401 additions and 76 deletions
|
@ -15,6 +15,7 @@ import com.mintris.databinding.ActivityMainBinding
|
||||||
import com.mintris.game.GameHaptics
|
import com.mintris.game.GameHaptics
|
||||||
import com.mintris.game.GameView
|
import com.mintris.game.GameView
|
||||||
import com.mintris.game.NextPieceView
|
import com.mintris.game.NextPieceView
|
||||||
|
import com.mintris.game.TitleScreen
|
||||||
import android.view.HapticFeedbackConstants
|
import android.view.HapticFeedbackConstants
|
||||||
import com.mintris.model.GameBoard
|
import com.mintris.model.GameBoard
|
||||||
import com.mintris.audio.GameMusic
|
import com.mintris.audio.GameMusic
|
||||||
|
@ -27,6 +28,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
private lateinit var gameHaptics: GameHaptics
|
private lateinit var gameHaptics: GameHaptics
|
||||||
private lateinit var gameBoard: GameBoard
|
private lateinit var gameBoard: GameBoard
|
||||||
private lateinit var gameMusic: GameMusic
|
private lateinit var gameMusic: GameMusic
|
||||||
|
private lateinit var titleScreen: TitleScreen
|
||||||
|
|
||||||
// Game state
|
// Game state
|
||||||
private var isSoundEnabled = true
|
private var isSoundEnabled = true
|
||||||
|
@ -43,12 +45,36 @@ class MainActivity : AppCompatActivity() {
|
||||||
gameBoard = GameBoard()
|
gameBoard = GameBoard()
|
||||||
gameHaptics = GameHaptics(this)
|
gameHaptics = GameHaptics(this)
|
||||||
gameView = binding.gameView
|
gameView = binding.gameView
|
||||||
|
titleScreen = binding.titleScreen
|
||||||
gameMusic = GameMusic(this)
|
gameMusic = GameMusic(this)
|
||||||
|
|
||||||
// Set up game view
|
// Set up game view
|
||||||
gameView.setGameBoard(gameBoard)
|
gameView.setGameBoard(gameBoard)
|
||||||
gameView.setHaptics(gameHaptics)
|
gameView.setHaptics(gameHaptics)
|
||||||
|
|
||||||
|
// Set up title screen
|
||||||
|
titleScreen.onStartGame = {
|
||||||
|
titleScreen.visibility = View.GONE
|
||||||
|
gameView.visibility = View.VISIBLE
|
||||||
|
binding.gameControlsContainer.visibility = View.VISIBLE
|
||||||
|
startGame()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initially hide the game view and show title screen
|
||||||
|
gameView.visibility = View.GONE
|
||||||
|
binding.gameControlsContainer.visibility = View.GONE
|
||||||
|
titleScreen.visibility = View.VISIBLE
|
||||||
|
|
||||||
|
// Set up pause button to show settings menu
|
||||||
|
binding.pauseButton.setOnClickListener {
|
||||||
|
gameHaptics.performHapticFeedback(it, HapticFeedbackConstants.VIRTUAL_KEY)
|
||||||
|
gameView.pause()
|
||||||
|
gameMusic.pause()
|
||||||
|
showPauseMenu()
|
||||||
|
binding.pauseStartButton.visibility = View.GONE
|
||||||
|
binding.resumeButton.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
// Set up next piece preview
|
// Set up next piece preview
|
||||||
binding.nextPieceView.setGameView(gameView)
|
binding.nextPieceView.setGameView(gameView)
|
||||||
gameBoard.onNextPieceChanged = {
|
gameBoard.onNextPieceChanged = {
|
||||||
|
@ -62,9 +88,6 @@ class MainActivity : AppCompatActivity() {
|
||||||
updateMusicToggleUI()
|
updateMusicToggleUI()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start game immediately
|
|
||||||
startGame()
|
|
||||||
|
|
||||||
// Set up callbacks
|
// Set up callbacks
|
||||||
gameView.onGameStateChanged = { score, level, lines ->
|
gameView.onGameStateChanged = { score, level, lines ->
|
||||||
updateUI(score, level, lines)
|
updateUI(score, level, lines)
|
||||||
|
@ -99,7 +122,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
gameHaptics.performHapticFeedback(it, HapticFeedbackConstants.VIRTUAL_KEY)
|
gameHaptics.performHapticFeedback(it, HapticFeedbackConstants.VIRTUAL_KEY)
|
||||||
hideGameOver()
|
hideGameOver()
|
||||||
gameView.reset()
|
gameView.reset()
|
||||||
gameView.start()
|
startGame()
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.resumeButton.setOnClickListener {
|
binding.resumeButton.setOnClickListener {
|
||||||
|
@ -118,14 +141,14 @@ class MainActivity : AppCompatActivity() {
|
||||||
gameHaptics.performHapticFeedback(it, HapticFeedbackConstants.VIRTUAL_KEY)
|
gameHaptics.performHapticFeedback(it, HapticFeedbackConstants.VIRTUAL_KEY)
|
||||||
hidePauseMenu()
|
hidePauseMenu()
|
||||||
gameView.reset()
|
gameView.reset()
|
||||||
gameView.start()
|
startGame()
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.pauseRestartButton.setOnClickListener {
|
binding.pauseRestartButton.setOnClickListener {
|
||||||
gameHaptics.performHapticFeedback(it, HapticFeedbackConstants.VIRTUAL_KEY)
|
gameHaptics.performHapticFeedback(it, HapticFeedbackConstants.VIRTUAL_KEY)
|
||||||
hidePauseMenu()
|
hidePauseMenu()
|
||||||
gameView.reset()
|
gameView.reset()
|
||||||
gameView.start()
|
startGame()
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.pauseLevelUpButton.setOnClickListener {
|
binding.pauseLevelUpButton.setOnClickListener {
|
||||||
|
@ -250,50 +273,27 @@ class MainActivity : AppCompatActivity() {
|
||||||
showPauseMenu()
|
showPauseMenu()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun pauseGame() {
|
|
||||||
gameView.pause()
|
|
||||||
gameMusic.pause()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun resumeGame() {
|
private fun resumeGame() {
|
||||||
gameView.resume()
|
gameView.resume()
|
||||||
if (isMusicEnabled) {
|
if (isMusicEnabled) {
|
||||||
gameMusic.start()
|
gameMusic.resume()
|
||||||
}
|
}
|
||||||
|
// Force a redraw to ensure pieces aren't frozen
|
||||||
|
gameView.invalidate()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
super.onPause()
|
super.onPause()
|
||||||
if (!gameView.isGameOver()) {
|
if (gameView.visibility == View.VISIBLE) {
|
||||||
pauseGame()
|
|
||||||
showPauseMenu()
|
|
||||||
binding.pauseStartButton.visibility = View.GONE
|
|
||||||
binding.resumeButton.visibility = View.VISIBLE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated("Deprecated in Java")
|
|
||||||
override fun onBackPressed() {
|
|
||||||
if (binding.gameOverContainer.visibility == View.VISIBLE) {
|
|
||||||
hideGameOver()
|
|
||||||
gameView.reset()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (binding.pauseContainer.visibility == View.GONE) {
|
|
||||||
gameView.pause()
|
gameView.pause()
|
||||||
showPauseMenu()
|
gameMusic.pause()
|
||||||
binding.pauseStartButton.visibility = View.GONE
|
|
||||||
binding.resumeButton.visibility = View.VISIBLE
|
|
||||||
} else {
|
|
||||||
hidePauseMenu()
|
|
||||||
resumeGame()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
if (!gameView.isGameOver()) {
|
// If we're on the title screen, don't auto-resume the game
|
||||||
|
if (titleScreen.visibility == View.GONE && gameView.visibility == View.VISIBLE && binding.gameOverContainer.visibility == View.GONE && binding.pauseContainer.visibility == View.GONE) {
|
||||||
resumeGame()
|
resumeGame()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -302,4 +302,16 @@ class MainActivity : AppCompatActivity() {
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
gameMusic.release()
|
gameMusic.release()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show title screen (for game restart)
|
||||||
|
*/
|
||||||
|
private fun showTitleScreen() {
|
||||||
|
gameView.reset()
|
||||||
|
gameView.visibility = View.GONE
|
||||||
|
binding.gameControlsContainer.visibility = View.GONE
|
||||||
|
binding.gameOverContainer.visibility = View.GONE
|
||||||
|
binding.pauseContainer.visibility = View.GONE
|
||||||
|
titleScreen.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -59,6 +59,17 @@ class GameMusic(private val context: Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun resume() {
|
||||||
|
try {
|
||||||
|
Log.d("GameMusic", "Resuming music playback")
|
||||||
|
if (isEnabled && mediaPlayer?.isPlaying != true) {
|
||||||
|
mediaPlayer?.start()
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e("GameMusic", "Error resuming music", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun stop() {
|
fun stop() {
|
||||||
try {
|
try {
|
||||||
Log.d("GameMusic", "Stopping music playback")
|
Log.d("GameMusic", "Stopping music playback")
|
||||||
|
|
|
@ -664,9 +664,15 @@ class GameView @JvmOverloads constructor(
|
||||||
fun resume() {
|
fun resume() {
|
||||||
if (!isRunning) {
|
if (!isRunning) {
|
||||||
isRunning = true
|
isRunning = true
|
||||||
handler.post(gameLoopRunnable)
|
|
||||||
}
|
}
|
||||||
isPaused = false
|
isPaused = false
|
||||||
|
|
||||||
|
// Restart the game loop immediately
|
||||||
|
handler.removeCallbacks(gameLoopRunnable)
|
||||||
|
handler.post(gameLoopRunnable)
|
||||||
|
|
||||||
|
// Force an update to ensure pieces move immediately
|
||||||
|
update()
|
||||||
invalidate()
|
invalidate()
|
||||||
}
|
}
|
||||||
}
|
}
|
259
app/src/main/java/com/mintris/game/TitleScreen.kt
Normal file
259
app/src/main/java/com/mintris/game/TitleScreen.kt
Normal file
|
@ -0,0 +1,259 @@
|
||||||
|
package com.mintris.game
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.Canvas
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.graphics.Paint
|
||||||
|
import android.graphics.Typeface
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.MotionEvent
|
||||||
|
import android.view.View
|
||||||
|
import java.util.Random
|
||||||
|
import android.util.Log
|
||||||
|
|
||||||
|
class TitleScreen @JvmOverloads constructor(
|
||||||
|
context: Context,
|
||||||
|
attrs: AttributeSet? = null,
|
||||||
|
defStyleAttr: Int = 0
|
||||||
|
) : View(context, attrs, defStyleAttr) {
|
||||||
|
|
||||||
|
private val paint = Paint()
|
||||||
|
private val glowPaint = Paint()
|
||||||
|
private val titlePaint = Paint()
|
||||||
|
private val promptPaint = Paint()
|
||||||
|
private val cellSize = 30f
|
||||||
|
private val random = Random()
|
||||||
|
private var width = 0
|
||||||
|
private var height = 0
|
||||||
|
private val tetrominosToAdd = mutableListOf<Tetromino>()
|
||||||
|
|
||||||
|
// Callback for when the user touches the screen
|
||||||
|
var onStartGame: (() -> Unit)? = null
|
||||||
|
|
||||||
|
// Define tetromino shapes (I, O, T, S, Z, J, L)
|
||||||
|
private val tetrominoShapes = arrayOf(
|
||||||
|
// I
|
||||||
|
arrayOf(
|
||||||
|
intArrayOf(0, 0, 0, 0),
|
||||||
|
intArrayOf(1, 1, 1, 1),
|
||||||
|
intArrayOf(0, 0, 0, 0),
|
||||||
|
intArrayOf(0, 0, 0, 0)
|
||||||
|
),
|
||||||
|
// O
|
||||||
|
arrayOf(
|
||||||
|
intArrayOf(1, 1),
|
||||||
|
intArrayOf(1, 1)
|
||||||
|
),
|
||||||
|
// T
|
||||||
|
arrayOf(
|
||||||
|
intArrayOf(0, 1, 0),
|
||||||
|
intArrayOf(1, 1, 1),
|
||||||
|
intArrayOf(0, 0, 0)
|
||||||
|
),
|
||||||
|
// S
|
||||||
|
arrayOf(
|
||||||
|
intArrayOf(0, 1, 1),
|
||||||
|
intArrayOf(1, 1, 0),
|
||||||
|
intArrayOf(0, 0, 0)
|
||||||
|
),
|
||||||
|
// Z
|
||||||
|
arrayOf(
|
||||||
|
intArrayOf(1, 1, 0),
|
||||||
|
intArrayOf(0, 1, 1),
|
||||||
|
intArrayOf(0, 0, 0)
|
||||||
|
),
|
||||||
|
// J
|
||||||
|
arrayOf(
|
||||||
|
intArrayOf(1, 0, 0),
|
||||||
|
intArrayOf(1, 1, 1),
|
||||||
|
intArrayOf(0, 0, 0)
|
||||||
|
),
|
||||||
|
// L
|
||||||
|
arrayOf(
|
||||||
|
intArrayOf(0, 0, 1),
|
||||||
|
intArrayOf(1, 1, 1),
|
||||||
|
intArrayOf(0, 0, 0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Tetromino class to represent falling pieces
|
||||||
|
private class Tetromino(
|
||||||
|
var x: Float,
|
||||||
|
var y: Float,
|
||||||
|
val shape: Array<IntArray>,
|
||||||
|
val speed: Float,
|
||||||
|
val scale: Float,
|
||||||
|
val rotation: Int = 0
|
||||||
|
)
|
||||||
|
|
||||||
|
private val tetrominos = mutableListOf<Tetromino>()
|
||||||
|
|
||||||
|
init {
|
||||||
|
// Title text settings
|
||||||
|
titlePaint.apply {
|
||||||
|
color = Color.WHITE
|
||||||
|
textSize = 120f
|
||||||
|
textAlign = Paint.Align.CENTER
|
||||||
|
typeface = Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD)
|
||||||
|
isAntiAlias = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// "Touch to start" text settings
|
||||||
|
promptPaint.apply {
|
||||||
|
color = Color.WHITE
|
||||||
|
textSize = 40f
|
||||||
|
textAlign = Paint.Align.CENTER
|
||||||
|
typeface = Typeface.create(Typeface.SANS_SERIF, Typeface.NORMAL)
|
||||||
|
isAntiAlias = true
|
||||||
|
alpha = 180
|
||||||
|
}
|
||||||
|
|
||||||
|
// General paint settings for tetrominos (white)
|
||||||
|
paint.apply {
|
||||||
|
color = Color.WHITE
|
||||||
|
style = Paint.Style.FILL
|
||||||
|
isAntiAlias = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Glow paint settings for tetrominos
|
||||||
|
glowPaint.apply {
|
||||||
|
color = Color.WHITE
|
||||||
|
style = Paint.Style.FILL
|
||||||
|
isAntiAlias = true
|
||||||
|
alpha = 60
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
|
||||||
|
super.onSizeChanged(w, h, oldw, oldh)
|
||||||
|
width = w
|
||||||
|
height = h
|
||||||
|
|
||||||
|
// Clear existing tetrominos
|
||||||
|
tetrominos.clear()
|
||||||
|
|
||||||
|
// Initialize some tetrominos
|
||||||
|
repeat(20) {
|
||||||
|
val tetromino = createRandomTetromino()
|
||||||
|
tetrominos.add(tetromino)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createRandomTetromino(): Tetromino {
|
||||||
|
val x = random.nextFloat() * (width - 150) + 50 // Keep away from edges
|
||||||
|
val y = -cellSize * 4 - (random.nextFloat() * height / 2)
|
||||||
|
val shapeIndex = random.nextInt(tetrominoShapes.size)
|
||||||
|
val shape = tetrominoShapes[shapeIndex]
|
||||||
|
val speed = 1f + random.nextFloat() * 2f
|
||||||
|
val scale = 0.8f + random.nextFloat() * 0.4f
|
||||||
|
val rotation = random.nextInt(4) * 90
|
||||||
|
|
||||||
|
return Tetromino(x, y, shape, speed, scale, rotation)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDraw(canvas: Canvas) {
|
||||||
|
try {
|
||||||
|
super.onDraw(canvas)
|
||||||
|
|
||||||
|
// Draw background
|
||||||
|
canvas.drawColor(Color.BLACK)
|
||||||
|
|
||||||
|
// Add any pending tetrominos
|
||||||
|
tetrominos.addAll(tetrominosToAdd)
|
||||||
|
tetrominosToAdd.clear()
|
||||||
|
|
||||||
|
// Update and draw falling tetrominos
|
||||||
|
val tetrominosToRemove = mutableListOf<Tetromino>()
|
||||||
|
|
||||||
|
for (tetromino in tetrominos) {
|
||||||
|
tetromino.y += tetromino.speed
|
||||||
|
|
||||||
|
// Remove tetrominos that have fallen off the screen
|
||||||
|
if (tetromino.y > height) {
|
||||||
|
tetrominosToRemove.add(tetromino)
|
||||||
|
tetrominosToAdd.add(createRandomTetromino())
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
// Save canvas state before rotation
|
||||||
|
canvas.save()
|
||||||
|
|
||||||
|
// Translate to the tetromino's position
|
||||||
|
canvas.translate(tetromino.x, tetromino.y)
|
||||||
|
|
||||||
|
// Scale according to the tetromino's scale factor
|
||||||
|
canvas.scale(tetromino.scale, tetromino.scale)
|
||||||
|
|
||||||
|
// Rotate around the center of the tetromino
|
||||||
|
val centerX = tetromino.shape.size * cellSize / 2
|
||||||
|
val centerY = tetromino.shape.size * cellSize / 2
|
||||||
|
canvas.rotate(tetromino.rotation.toFloat(), centerX, centerY)
|
||||||
|
|
||||||
|
// Draw the tetromino
|
||||||
|
for (row in tetromino.shape.indices) {
|
||||||
|
for (col in 0 until tetromino.shape[row].size) {
|
||||||
|
if (tetromino.shape[row][col] == 1) {
|
||||||
|
// Draw larger glow effect
|
||||||
|
glowPaint.alpha = 30
|
||||||
|
canvas.drawRect(
|
||||||
|
col * cellSize - 8,
|
||||||
|
row * cellSize - 8,
|
||||||
|
(col + 1) * cellSize + 8,
|
||||||
|
(row + 1) * cellSize + 8,
|
||||||
|
glowPaint
|
||||||
|
)
|
||||||
|
|
||||||
|
// Draw medium glow
|
||||||
|
glowPaint.alpha = 60
|
||||||
|
canvas.drawRect(
|
||||||
|
col * cellSize - 4,
|
||||||
|
row * cellSize - 4,
|
||||||
|
(col + 1) * cellSize + 4,
|
||||||
|
(row + 1) * cellSize + 4,
|
||||||
|
glowPaint
|
||||||
|
)
|
||||||
|
|
||||||
|
// Draw main block
|
||||||
|
canvas.drawRect(
|
||||||
|
col * cellSize,
|
||||||
|
row * cellSize,
|
||||||
|
(col + 1) * cellSize,
|
||||||
|
(row + 1) * cellSize,
|
||||||
|
paint
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore canvas state
|
||||||
|
canvas.restore()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e("TitleScreen", "Error drawing tetromino", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove tetrominos that fell off the screen
|
||||||
|
tetrominos.removeAll(tetrominosToRemove)
|
||||||
|
|
||||||
|
// Draw title
|
||||||
|
val titleY = height * 0.4f
|
||||||
|
canvas.drawText("mintris", width / 2f, titleY, titlePaint)
|
||||||
|
|
||||||
|
// Draw "touch to start" prompt
|
||||||
|
canvas.drawText("touch to start", width / 2f, height * 0.6f, promptPaint)
|
||||||
|
|
||||||
|
// Request another frame
|
||||||
|
invalidate()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e("TitleScreen", "Error in onDraw", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTouchEvent(event: MotionEvent): Boolean {
|
||||||
|
if (event.action == MotionEvent.ACTION_DOWN) {
|
||||||
|
onStartGame?.invoke()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return super.onTouchEvent(event)
|
||||||
|
}
|
||||||
|
}
|
10
app/src/main/res/drawable/ic_pause.xml
Normal file
10
app/src/main/res/drawable/ic_pause.xml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:tint="@android:color/white">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M6,19h4L10,5L6,5v14zM14,5v14h4L18,5h-4z"/>
|
||||||
|
</vector>
|
|
@ -31,54 +31,81 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="@drawable/glow_border" />
|
android:background="@drawable/glow_border" />
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
|
<!-- Title Screen -->
|
||||||
|
<com.mintris.game.TitleScreen
|
||||||
|
android:id="@+id/titleScreen"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<!-- HUD Container - Score, Level, Lines -->
|
<!-- HUD Container - Score, Level, Lines -->
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/hudContainer"
|
android:id="@+id/gameControlsContainer"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
android:layout_margin="16dp"
|
android:orientation="vertical">
|
||||||
android:orientation="vertical"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
<LinearLayout
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
android:id="@+id/hudContainer"
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/scoreText"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textColor="@color/white"
|
android:layout_margin="16dp"
|
||||||
android:textSize="24sp"
|
android:layout_gravity="end"
|
||||||
android:fontFamily="sans-serif-light"
|
android:orientation="vertical">
|
||||||
tools:text="Score: 0" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/currentLevelText"
|
android:id="@+id/scoreText"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textColor="@color/white"
|
android:textColor="@color/white"
|
||||||
android:textSize="24sp"
|
android:textSize="24sp"
|
||||||
android:fontFamily="sans-serif-light"
|
android:fontFamily="sans-serif-light"
|
||||||
tools:text="Level: 1" />
|
tools:text="Score: 0" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/linesText"
|
android:id="@+id/currentLevelText"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textColor="@color/white"
|
android:textColor="@color/white"
|
||||||
android:textSize="24sp"
|
android:textSize="24sp"
|
||||||
android:fontFamily="sans-serif-light"
|
android:fontFamily="sans-serif-light"
|
||||||
tools:text="Lines: 0" />
|
tools:text="Level: 1" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/linesText"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="24sp"
|
||||||
|
android:fontFamily="sans-serif-light"
|
||||||
|
tools:text="Lines: 0" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- Next Piece Preview -->
|
||||||
|
<com.mintris.game.NextPieceView
|
||||||
|
android:id="@+id/nextPieceView"
|
||||||
|
android:layout_width="80dp"
|
||||||
|
android:layout_height="80dp"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
android:layout_gravity="end" />
|
||||||
|
|
||||||
|
<!-- Settings button -->
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/pauseButton"
|
||||||
|
android:layout_width="48dp"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:layout_gravity="start"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
android:background="?attr/selectableItemBackgroundBorderless"
|
||||||
|
android:contentDescription="@string/settings"
|
||||||
|
android:padding="12dp"
|
||||||
|
android:src="@drawable/ic_pause" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<!-- Next Piece Preview -->
|
|
||||||
<com.mintris.game.NextPieceView
|
|
||||||
android:id="@+id/nextPieceView"
|
|
||||||
android:layout_width="80dp"
|
|
||||||
android:layout_height="80dp"
|
|
||||||
android:layout_margin="16dp"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/hudContainer" />
|
|
||||||
|
|
||||||
<!-- Game Over overlay -->
|
<!-- Game Over overlay -->
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/gameOverContainer"
|
android:id="@+id/gameOverContainer"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue