DEADSOFTWARE

New blocks structure
[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 kotlin.contracts.ExperimentalContracts
8 import kotlin.contracts.contract
10 @OptIn(ExperimentalContracts::class)
11 sealed class Block {
13 abstract val params: CommonBlockParams
15 val width: Float get() = 16f - params.collisionMargins.left - params.collisionMargins.right
16 val height: Float get() = 16f - params.collisionMargins.top - params.collisionMargins.bottom
18 private val spriteWidth: Float get() = 16f - params.spriteMargins.left - params.spriteMargins.right
19 private val spriteHeight: Float get() = 16f - params.spriteMargins.top - params.spriteMargins.bottom
21 private var animation: Array<Sprite>? = null
23 private var sprite: Sprite? = null
24 get() {
25 return animation?.get(currentAnimationFrame) ?: field
26 }
28 private val currentAnimationFrame: Int
29 get() {
30 return params.animationInfo?.let { animInfo ->
31 ((TimeUtils.millis() / ANIMATION_FRAME_DURATION_MS) % animInfo.framesCount).toInt()
32 } ?: 0
33 }
35 fun initialize() {
36 initAnimation()
37 initSprite()
38 }
40 private fun initAnimation() {
41 animation = params.animationInfo?.let { animInfo ->
42 requireNotNull(params.texture) { "Cannot derive animation frames from null sprite" }
43 Array(animInfo.framesCount) { y ->
44 val width = 16 - params.spriteMargins.left - params.spriteMargins.right
45 val height = 16 - params.spriteMargins.top - params.spriteMargins.bottom
46 Sprite(params.texture, params.spriteMargins.left, 16 * y + params.spriteMargins.top, width, height)
47 .apply { flip(false, true) }
48 }
49 }
50 }
52 private fun initSprite() {
53 sprite = animation?.get(0) ?: params.texture?.let { tex ->
54 val width = 16 - params.spriteMargins.left - params.spriteMargins.right
55 val height = 16 - params.spriteMargins.top - params.spriteMargins.bottom
56 Sprite(tex, params.spriteMargins.left, params.spriteMargins.top, width, height)
57 .apply { flip(false, true) }
58 }
59 }
61 fun requireSprite() = requireNotNull(sprite)
63 fun draw(spriter: SpriteBatch, x: Float, y: Float) {
64 sprite?.apply {
65 setBounds(
66 /* x = */ x + params.spriteMargins.left,
67 /* y = */ y + params.spriteMargins.top,
68 /* width = */ spriteWidth,
69 /* height = */ spriteHeight
70 )
71 draw(spriter)
72 }
73 }
75 fun isFluid(): Boolean {
76 contract { returns(true) implies (this@Block is Fluid) }
77 return this is Fluid
78 }
80 fun isWater(): Boolean {
81 contract { returns(true) implies (this@Block is Water) }
82 return this is Water
83 }
85 fun isLava(): Boolean {
86 contract { returns(true) implies (this@Block is Lava) }
87 return this is Lava
88 }
90 fun isSlab(): Boolean {
91 contract { returns(true) implies (this@Block is Slab) }
92 return this is Slab
93 }
95 fun getRectangle(x: Int, y: Int): Rectangle {
96 return Rectangle(
97 /* x = */ x * 16f + params.collisionMargins.left,
98 /* y = */ y * 16f + params.collisionMargins.top,
99 /* width = */ width,
100 /* height = */ height
106 data class Normal(
107 override val params: CommonBlockParams,
108 ) : Block()
110 data class Slab(
111 override val params: CommonBlockParams,
112 val fullBlockKey: String,
113 ): Block()
115 abstract class Fluid: Block() {
116 abstract val statesCount: Int
119 data class Water(
120 override val params: CommonBlockParams,
121 override val statesCount: Int
122 ) : Fluid()
124 data class Lava(
125 override val params: CommonBlockParams,
126 override val statesCount: Int
127 ) : Fluid()
129 /* Legacy accessors below */
131 // collision margins
132 @Deprecated(LEGACY_ACCESSOR_DEPRECATION) val left: Int get() = params.collisionMargins.left
133 @Deprecated(LEGACY_ACCESSOR_DEPRECATION) val right: Int get() = params.collisionMargins.left
134 @Deprecated(LEGACY_ACCESSOR_DEPRECATION) val top: Int get() = params.collisionMargins.left
135 @Deprecated(LEGACY_ACCESSOR_DEPRECATION) val bottom: Int get() = params.collisionMargins.left
137 @Deprecated(LEGACY_ACCESSOR_DEPRECATION) val hp: Int get() = params.hitPoints
138 @Deprecated(LEGACY_ACCESSOR_DEPRECATION) val collision: Boolean get() = params.hasCollision
139 @Deprecated(LEGACY_ACCESSOR_DEPRECATION) val animated: Boolean get() = params.animationInfo != null
140 @Deprecated(LEGACY_ACCESSOR_DEPRECATION) val frames: Int get() = params.animationInfo?.framesCount ?: 0
141 @Deprecated(LEGACY_ACCESSOR_DEPRECATION) val drop: String get() = params.dropInfo?.itemKey ?: "none"
142 @Deprecated(LEGACY_ACCESSOR_DEPRECATION) fun hasDrop() = params.dropInfo != null
143 @Deprecated(LEGACY_ACCESSOR_DEPRECATION) fun toJump() = params.hasCollision && params.collisionMargins.top < 8
144 @Deprecated(LEGACY_ACCESSOR_DEPRECATION) fun hasCollision() = params.hasCollision
145 @Deprecated(LEGACY_ACCESSOR_DEPRECATION) fun isBackground() = params.isBackground
146 @Deprecated(LEGACY_ACCESSOR_DEPRECATION) fun isTransparent() = params.isTransparent
147 @Deprecated(LEGACY_ACCESSOR_DEPRECATION) fun getTexture() = sprite
150 companion object {
151 private const val LEGACY_ACCESSOR_DEPRECATION = "legacy accessors will be removed"
152 private const val ANIMATION_FRAME_DURATION_MS = 100L