summaryrefslogtreecommitdiff
path: root/app/src/main/java/space/jakob/mines/GameView.kt
blob: 80218ceb56cce7d66aa5de0929df8dbaf8575f13 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// Mines is free software: you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the Free Software
// Foundation, either version 3 of the License, or (at your option) any later
// version.

// Mines is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
// A PARTICULAR PURPOSE. See the GNU General Public License for more details.

// You should have received a copy of the GNU General Public License along with
// Mines. If not, see <https://www.gnu.org/licenses/>.

package space.jakob.mines

import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.graphics.Rect
import android.graphics.Paint
import android.util.AttributeSet
import android.view.View
import android.util.Log

const val atlasWidth = 3
const val tileSpacing = 2.0 / 27.0

enum class AtlasEntry {
    BLANK, MASKED, UNMASKED,
    ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT,
    FLAG, UNKNOWN, MINE, TRIPPED,
}

class GameView(context: Context, attrs: AttributeSet) : View(context, attrs) {
    val atlas = BitmapFactory.decodeResource(context.resources, R.drawable.atlas);
    val tileWidth = atlas.width / 3

    var grid: Grid? = null

    var cameraX = 0.5f
    var cameraY = 0.0f
    var sightX = 5.0f
    var sightY = 5.0f

    val scaledWidth: Int
        get() = width / (sightX - cameraX).toInt()
    val scaledHeight: Int
        get() = height / (sightY - cameraY).toInt()

    private fun atlasRect(entry: AtlasEntry): Rect {
        val x = (entry.ordinal % atlasWidth) * tileWidth
        val y = (entry.ordinal / atlasWidth) * tileWidth
        return Rect(x, y, x + tileWidth, y + tileWidth)
    }

    private fun drawTile(canvas: Canvas, tile: Tile, x: Int, y: Int) {
        val xSpacing = (scaledWidth * tileSpacing).toInt()
        val ySpacing = (scaledWidth * tileSpacing).toInt()

        val dst = Rect(
            x + xSpacing,
            y + ySpacing,
            x + scaledWidth - xSpacing,
            y + scaledHeight - ySpacing
        )

        if (tile.masked) {
            canvas.drawBitmap(atlas, atlasRect(AtlasEntry.MASKED), dst, null)
        } else {
            canvas.drawBitmap(atlas, atlasRect(AtlasEntry.UNMASKED), dst, null)

            val overlay = when {
                tile.mine -> AtlasEntry.MINE
                tile.adjacentMines == 1 -> AtlasEntry.ONE
                tile.adjacentMines == 2 -> AtlasEntry.TWO
                tile.adjacentMines == 3 -> AtlasEntry.THREE
                tile.adjacentMines == 4 -> AtlasEntry.FOUR
                tile.adjacentMines == 5 -> AtlasEntry.FIVE
                tile.adjacentMines == 6 -> AtlasEntry.SIX
                tile.adjacentMines == 7 -> AtlasEntry.SEVEN
                tile.adjacentMines == 8 -> AtlasEntry.EIGHT
                else -> AtlasEntry.BLANK
            }

            canvas.drawBitmap(atlas, atlasRect(overlay), dst, null)
        }
    }

    private fun drawGrid(canvas: Canvas, grid: Grid) {
        val startX = cameraX.toInt() // Truncates the fractional component.
        val startY = cameraY.toInt()
        val howManyX = (sightX - cameraX).toInt() + 1
        val howManyY = (sightY - cameraY).toInt() + 1

        for (i in 0..howManyX) {
            for (j in 0..howManyY) {
                val tile = grid[startX + i, startY + j]

                val xOffset = (scaledWidth * (cameraX % 1)).toInt()
                val yOffset = (scaledHeight * (cameraY % 1)).toInt()

                drawTile(
                    canvas,
                    tile,
                    i * scaledWidth - xOffset,
                    j * scaledHeight - yOffset
                )
            }
        }
    }

    fun toGridCoordinates(x: Int, y: Int) = Pair(
        (x + (scaledWidth * (cameraX % 1)).toInt()) / scaledWidth + cameraX.toInt(),
        (y + (scaledHeight * (cameraY % 1)).toInt()) / scaledHeight + cameraY.toInt()
    )

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)

        grid?.let {
            drawGrid(canvas, it)
        }
    }
}