DEADSOFTWARE

Delete old GameItems
[cavedroid.git] / core / src / ru / deadsoftware / cavedroid / game / model / block / Block.kt
1 package ru.deadsoftware.cavedroid.game.model.block
3 import com.badlogic.gdx.graphics.g2d.Sprite
4 import com.badlogic.gdx.graphics.g2d.SpriteBatch
5 import com.badlogic.gdx.math.Rectangle
6 import com.badlogic.gdx.utils.TimeUtils
7 import ru.deadsoftware.cavedroid.game.model.item.Item
8 import kotlin.contracts.ExperimentalContracts
9 import kotlin.contracts.contract
11 @OptIn(ExperimentalContracts::class)
12 sealed class Block {
14 abstract val params: CommonBlockParams
16 val width: Float get() = 16f - params.collisionMargins.left - params.collisionMargins.right
17 val height: Float get() = 16f - params.collisionMargins.top - params.collisionMargins.bottom
19 private val spriteWidth: Float get() = 16f - params.spriteMargins.left - params.spriteMargins.right
20 private val spriteHeight: Float get() = 16f - params.spriteMargins.top - params.spriteMargins.bottom
22 private var animation: Array<Sprite>? = null
24 private var _sprite: Sprite? = null
25 get() {
26 return animation?.get(currentAnimationFrame) ?: field
27 }
29 val sprite: Sprite
30 get() = requireNotNull(_sprite) { "null sprite for block '${params.key}'" }
32 private val currentAnimationFrame: Int
33 get() {
34 return params.animationInfo?.let { animInfo ->
35 ((TimeUtils.millis() / ANIMATION_FRAME_DURATION_MS) % animInfo.framesCount).toInt()
36 } ?: 0
37 }
39 override fun hashCode(): Int {
40 return params.key.hashCode()
41 }
43 override fun equals(other: Any?): Boolean {
44 return params.key == (other as Item).params.key
45 }
47 fun initialize() {
48 initAnimation()
49 initSprite()
50 }
52 private fun initAnimation() {
53 animation = params.animationInfo?.let { animInfo ->
54 requireNotNull(params.texture) { "Cannot derive animation frames from null sprite" }
55 Array(animInfo.framesCount) { y ->
56 val width = 16 - params.spriteMargins.left - params.spriteMargins.right
57 val height = 16 - params.spriteMargins.top - params.spriteMargins.bottom
58 Sprite(params.texture, params.spriteMargins.left, 16 * y + params.spriteMargins.top, width, height)
59 .apply { flip(false, true) }
60 }
61 }
62 }
64 private fun initSprite() {
65 _sprite = animation?.get(0) ?: params.texture?.let { tex ->
66 val width = 16 - params.spriteMargins.left - params.spriteMargins.right
67 val height = 16 - params.spriteMargins.top - params.spriteMargins.bottom
68 Sprite(tex, params.spriteMargins.left, params.spriteMargins.top, width, height)
69 .apply { flip(false, true) }
70 }
71 }
73 fun requireSprite() = requireNotNull(sprite)
75 fun draw(spriter: SpriteBatch, x: Float, y: Float) {
76 sprite.apply {
77 setBounds(
78 /* x = */ x + params.spriteMargins.left,
79 /* y = */ y + params.spriteMargins.top,
80 /* width = */ spriteWidth,
81 /* height = */ spriteHeight
82 )
83 draw(spriter)
84 }
85 }
87 fun isFluid(): Boolean {
88 contract { returns(true) implies (this@Block is Fluid) }
89 return this is Fluid
90 }
92 fun isWater(): Boolean {
93 contract { returns(true) implies (this@Block is Water) }
94 return this is Water
95 }
97 fun isLava(): Boolean {
98 contract { returns(true) implies (this@Block is Lava) }
99 return this is Lava
102 fun isSlab(): Boolean {
103 contract { returns(true) implies (this@Block is Slab) }
104 return this is Slab
107 fun getRectangle(x: Int, y: Int): Rectangle {
108 return Rectangle(
109 /* x = */ x * 16f + params.collisionMargins.left,
110 /* y = */ y * 16f + params.collisionMargins.top,
111 /* width = */ width,
112 /* height = */ height
118 data class Normal(
119 override val params: CommonBlockParams,
120 ) : Block()
122 data class Slab(
123 override val params: CommonBlockParams,
124 val fullBlockKey: String,
125 ): Block()
127 sealed class Fluid: Block() {
128 abstract val state: Int
131 data class Water(
132 override val params: CommonBlockParams,
133 override val state: Int,
134 ) : Fluid()
136 data class Lava(
137 override val params: CommonBlockParams,
138 override val state: Int,
139 ) : Fluid()
141 /* Legacy accessors below */
143 // collision margins
144 @Deprecated(LEGACY_ACCESSOR_DEPRECATION) val left: Int get() = params.collisionMargins.left
145 @Deprecated(LEGACY_ACCESSOR_DEPRECATION) val right: Int get() = params.collisionMargins.left
146 @Deprecated(LEGACY_ACCESSOR_DEPRECATION) val top: Int get() = params.collisionMargins.left
147 @Deprecated(LEGACY_ACCESSOR_DEPRECATION) val bottom: Int get() = params.collisionMargins.left
149 @Deprecated(LEGACY_ACCESSOR_DEPRECATION) val hp: Int get() = params.hitPoints
150 @Deprecated(LEGACY_ACCESSOR_DEPRECATION) val collision: Boolean get() = params.hasCollision
151 @Deprecated(LEGACY_ACCESSOR_DEPRECATION) val animated: Boolean get() = params.animationInfo != null
152 @Deprecated(LEGACY_ACCESSOR_DEPRECATION) val frames: Int get() = params.animationInfo?.framesCount ?: 0
153 @Deprecated(LEGACY_ACCESSOR_DEPRECATION) val drop: String get() = params.dropInfo?.itemKey ?: "none"
154 @Deprecated(LEGACY_ACCESSOR_DEPRECATION) fun hasDrop() = params.dropInfo != null
155 @Deprecated(LEGACY_ACCESSOR_DEPRECATION) fun toJump() = params.hasCollision && params.collisionMargins.top < 8
156 @Deprecated(LEGACY_ACCESSOR_DEPRECATION) fun hasCollision() = params.hasCollision
157 @Deprecated(LEGACY_ACCESSOR_DEPRECATION) fun isBackground() = params.isBackground
158 @Deprecated(LEGACY_ACCESSOR_DEPRECATION) fun isTransparent() = params.isTransparent
159 @Deprecated(LEGACY_ACCESSOR_DEPRECATION) fun getTexture() = sprite
162 companion object {
163 private const val LEGACY_ACCESSOR_DEPRECATION = "legacy accessors will be removed"
164 private const val ANIMATION_FRAME_DURATION_MS = 100L