summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 127dbff)
raw | patch | inline | side by side (parent: 127dbff)
author | fredboy <fredboy@protonmail.com> | |
Sat, 20 Apr 2024 08:14:44 +0000 (15:14 +0700) | ||
committer | fredboy <fredboy@protonmail.com> | |
Sat, 20 Apr 2024 08:22:46 +0000 (15:22 +0700) |
15 files changed:
index 97e4106ceb6fc15230ae1549ed739c5e24d69f99..48b612fa88543a925313c8310f3a5290cd41408e 100644 (file)
"top": 8,
"sprite_top": 8,
"meta": "slab",
- "transparent": true
+ "transparent": true,
+ "full_block": "bricks"
},
"bricks": {
"hp": 600,
diff --git a/core/src/ru/deadsoftware/cavedroid/game/GameItems.java b/core/src/ru/deadsoftware/cavedroid/game/GameItems.java
index eeeeb115da03fad2112abe5b96682373251d083f..8392efdb786602ca0e874d11ce185895ca74c494 100644 (file)
import com.badlogic.gdx.utils.ArrayMap;
import com.badlogic.gdx.utils.GdxRuntimeException;
import com.badlogic.gdx.utils.JsonValue;
-import ru.deadsoftware.cavedroid.game.objects.Block;
+import ru.deadsoftware.cavedroid.game.model.block.*;
import ru.deadsoftware.cavedroid.game.objects.Item;
import ru.deadsoftware.cavedroid.misc.Assets;
import ru.deadsoftware.cavedroid.misc.utils.AssetLoader;
return isWater(getBlock(id));
}
+ @Deprecated
public static boolean isWater(Block block) {
- return block.getMeta().equals("water");
+ return block instanceof Block.Water;
}
+ @Deprecated
public static boolean isLava(int id) {
return isLava(getBlock(id));
}
+ @Deprecated
public static boolean isLava(Block block) {
- return block.getMeta().equals("lava");
+ return block instanceof Block.Lava;
}
+ @Deprecated
public static boolean isSlab(int id) {
- return getBlock(id).getMeta().equals("slab");
+ return getBlock(id) instanceof Block.Slab;
}
public static boolean fluidCanFlowThere(int thisId, int thatId) {
public static void load(AssetLoader assetLoader) {
JsonValue json = Assets.jsonReader.parse(assetLoader.getAssetHandle("json/game_items.json"));
- TreeSet<Block> blocksSet = new TreeSet<>(Comparator.comparingInt(Block::getId));
+ TreeSet<Block> blocksSet = new TreeSet<>(Comparator.comparingInt(a -> a.getParams().getId()));
TreeSet<Item> itemsSet = new TreeSet<>(Comparator.comparingInt(Item::getId));
boolean animated = Assets.getBooleanFromJson(block, "animated", false);
int frames = Assets.getIntFromJson(block, "frames", 0);
int id = Assets.getIntFromJson(block, "id", count);
+ int dropCount = Assets.getIntFromJson(block, "drop_count", 1);
String fullBlock = Assets.getStringFromJson(block, "full_block", null);
blocksIds.put(key, id);
count++;
}
- Block newBlock = new Block(
+ BlockMargins collMargins = new BlockMargins(left, top, right, bottom);
+ BlockMargins spriteMargins = new BlockMargins(clipX, clipY, clipWidth, clipHeight);
+ BlockDropInfo dropInfo = new BlockDropInfo(drop, dropCount);
+ BlockAnimationInfo animInfo = null;
+ if (animated) {
+ animInfo = new BlockAnimationInfo(frames);
+ }
+
+ CommonBlockParams params = new CommonBlockParams(
id,
key,
- left,
- top,
- right,
- bottom,
+ collMargins,
hp,
- drop,
+ dropInfo,
collision,
background,
transparent,
requiresBlock,
- fluid,
- meta,
+ animInfo,
texture,
- animated,
- frames,
- clipX,
- clipY,
- clipWidth,
- clipHeight,
- fullBlock
+ spriteMargins
);
+
+ Block newBlock = switch (meta) {
+ case "water" -> new Block.Water(params, 5);
+ case "lava" -> new Block.Lava(params, 5);
+ case "slab" -> new Block.Slab(params, fullBlock);
+ default -> new Block.Normal(params);
+ };
+
+ newBlock.initialize();
blocksSet.add(newBlock);
} catch (GdxRuntimeException e) {
Gdx.app.error(TAG, e.getMessage());
}
}
- blocksSet.forEach((block -> blocks.put(block.getKey(), block)));
+ blocksSet.forEach((block -> blocks.put(block.getParams().getKey(), block)));
itemsSet.forEach((item -> items.put(item.getKey(), item)));
}
diff --git a/core/src/ru/deadsoftware/cavedroid/game/GameRenderer.java b/core/src/ru/deadsoftware/cavedroid/game/GameRenderer.java
index ca9cf8b392c231dfc564ef3120eff9ba90469ec2..06e9b624fae8fd2570fae96e342eeb8fe0e2e646 100644 (file)
import ru.deadsoftware.cavedroid.game.mobs.Mob;
import ru.deadsoftware.cavedroid.game.mobs.MobsController;
import ru.deadsoftware.cavedroid.game.mobs.Player;
-import ru.deadsoftware.cavedroid.game.objects.Block;
+import ru.deadsoftware.cavedroid.game.model.block.Block;
import ru.deadsoftware.cavedroid.game.objects.Drop;
import ru.deadsoftware.cavedroid.game.objects.DropController;
import ru.deadsoftware.cavedroid.game.objects.Item;
diff --git a/core/src/ru/deadsoftware/cavedroid/game/actions/updateblock/UpdateGrassAction.kt b/core/src/ru/deadsoftware/cavedroid/game/actions/updateblock/UpdateGrassAction.kt
index a50c541c9d5df9738e1fd767e1df406cfc775b92..a9397c9ef0e58d0aa26edc9d222cdb3a5141b26f 100644 (file)
override fun update(x: Int, y: Int) {
val blockOnTop = gameWorld.getForeMapBlock(x, y - 1)
- if (blockOnTop.collision || blockOnTop.fluid) {
+ if (blockOnTop.collision || blockOnTop.isFluid()) {
gameWorld.setForeMap(x, y, GameItems.getBlockId("dirt"))
}
}
diff --git a/core/src/ru/deadsoftware/cavedroid/game/actions/useitem/PlaceBlockItemToBackgroundAction.kt b/core/src/ru/deadsoftware/cavedroid/game/actions/useitem/PlaceBlockItemToBackgroundAction.kt
index 43eefc98e156bf73d6eb13b8da1338889b4aff9b..e4af8df316ebf58d83e10ecdc28da1aabc3980a6 100644 (file)
override fun perform(item: Item, x: Int, y: Int) {
val block = item.toBlock()
requireNotNull(block) { "error: trying to place non block item" }
- gameWorld.placeToBackground(x, y, block.id)
+ gameWorld.placeToBackground(x, y, block.params.id)
}
companion object {
diff --git a/core/src/ru/deadsoftware/cavedroid/game/actions/useitem/PlaceBlockItemToForegroundAction.kt b/core/src/ru/deadsoftware/cavedroid/game/actions/useitem/PlaceBlockItemToForegroundAction.kt
index 473250e1fd8046508c19043c7c3a3c7a6f79c4d6..978eb00aaf421f7c41f00338a8a2c804e15f99b5 100644 (file)
override fun perform(item: Item, x: Int, y: Int) {
val block = item.toBlock()
requireNotNull(block) { "error: trying to place non block item" }
- gameWorld.placeToForeground(x, y, block.id)
+ gameWorld.placeToForeground(x, y, block.params.id)
}
companion object {
diff --git a/core/src/ru/deadsoftware/cavedroid/game/model/block/Block.kt b/core/src/ru/deadsoftware/cavedroid/game/model/block/Block.kt
--- /dev/null
@@ -0,0 +1,154 @@
+package ru.deadsoftware.cavedroid.game.model.block
+
+import com.badlogic.gdx.graphics.g2d.Sprite
+import com.badlogic.gdx.graphics.g2d.SpriteBatch
+import com.badlogic.gdx.math.Rectangle
+import com.badlogic.gdx.utils.TimeUtils
+import kotlin.contracts.ExperimentalContracts
+import kotlin.contracts.contract
+
+@OptIn(ExperimentalContracts::class)
+sealed class Block {
+
+ abstract val params: CommonBlockParams
+
+ val width: Float get() = 16f - params.collisionMargins.left - params.collisionMargins.right
+ val height: Float get() = 16f - params.collisionMargins.top - params.collisionMargins.bottom
+
+ private val spriteWidth: Float get() = 16f - params.spriteMargins.left - params.spriteMargins.right
+ private val spriteHeight: Float get() = 16f - params.spriteMargins.top - params.spriteMargins.bottom
+
+ private var animation: Array<Sprite>? = null
+
+ private var sprite: Sprite? = null
+ get() {
+ return animation?.get(currentAnimationFrame) ?: field
+ }
+
+ private val currentAnimationFrame: Int
+ get() {
+ return params.animationInfo?.let { animInfo ->
+ ((TimeUtils.millis() / ANIMATION_FRAME_DURATION_MS) % animInfo.framesCount).toInt()
+ } ?: 0
+ }
+
+ fun initialize() {
+ initAnimation()
+ initSprite()
+ }
+
+ private fun initAnimation() {
+ animation = params.animationInfo?.let { animInfo ->
+ requireNotNull(params.texture) { "Cannot derive animation frames from null sprite" }
+ Array(animInfo.framesCount) { y ->
+ val width = 16 - params.spriteMargins.left - params.spriteMargins.right
+ val height = 16 - params.spriteMargins.top - params.spriteMargins.bottom
+ Sprite(params.texture, params.spriteMargins.left, 16 * y + params.spriteMargins.top, width, height)
+ .apply { flip(false, true) }
+ }
+ }
+ }
+
+ private fun initSprite() {
+ sprite = animation?.get(0) ?: params.texture?.let { tex ->
+ val width = 16 - params.spriteMargins.left - params.spriteMargins.right
+ val height = 16 - params.spriteMargins.top - params.spriteMargins.bottom
+ Sprite(tex, params.spriteMargins.left, params.spriteMargins.top, width, height)
+ .apply { flip(false, true) }
+ }
+ }
+
+ fun requireSprite() = requireNotNull(sprite)
+
+ fun draw(spriter: SpriteBatch, x: Float, y: Float) {
+ sprite?.apply {
+ setBounds(
+ /* x = */ x + params.spriteMargins.left,
+ /* y = */ y + params.spriteMargins.top,
+ /* width = */ spriteWidth,
+ /* height = */ spriteHeight
+ )
+ draw(spriter)
+ }
+ }
+
+ fun isFluid(): Boolean {
+ contract { returns(true) implies (this@Block is Fluid) }
+ return this is Fluid
+ }
+
+ fun isWater(): Boolean {
+ contract { returns(true) implies (this@Block is Water) }
+ return this is Water
+ }
+
+ fun isLava(): Boolean {
+ contract { returns(true) implies (this@Block is Lava) }
+ return this is Lava
+ }
+
+ fun isSlab(): Boolean {
+ contract { returns(true) implies (this@Block is Slab) }
+ return this is Slab
+ }
+
+ fun getRectangle(x: Int, y: Int): Rectangle {
+ return Rectangle(
+ /* x = */ x * 16f + params.collisionMargins.left,
+ /* y = */ y * 16f + params.collisionMargins.top,
+ /* width = */ width,
+ /* height = */ height
+ )
+ }
+
+
+
+ data class Normal(
+ override val params: CommonBlockParams,
+ ) : Block()
+
+ data class Slab(
+ override val params: CommonBlockParams,
+ val fullBlockKey: String,
+ ): Block()
+
+ abstract class Fluid: Block() {
+ abstract val statesCount: Int
+ }
+
+ data class Water(
+ override val params: CommonBlockParams,
+ override val statesCount: Int
+ ) : Fluid()
+
+ data class Lava(
+ override val params: CommonBlockParams,
+ override val statesCount: Int
+ ) : Fluid()
+
+ /* Legacy accessors below */
+
+ // collision margins
+ @Deprecated(LEGACY_ACCESSOR_DEPRECATION) val left: Int get() = params.collisionMargins.left
+ @Deprecated(LEGACY_ACCESSOR_DEPRECATION) val right: Int get() = params.collisionMargins.left
+ @Deprecated(LEGACY_ACCESSOR_DEPRECATION) val top: Int get() = params.collisionMargins.left
+ @Deprecated(LEGACY_ACCESSOR_DEPRECATION) val bottom: Int get() = params.collisionMargins.left
+
+ @Deprecated(LEGACY_ACCESSOR_DEPRECATION) val hp: Int get() = params.hitPoints
+ @Deprecated(LEGACY_ACCESSOR_DEPRECATION) val collision: Boolean get() = params.hasCollision
+ @Deprecated(LEGACY_ACCESSOR_DEPRECATION) val animated: Boolean get() = params.animationInfo != null
+ @Deprecated(LEGACY_ACCESSOR_DEPRECATION) val frames: Int get() = params.animationInfo?.framesCount ?: 0
+ @Deprecated(LEGACY_ACCESSOR_DEPRECATION) val drop: String get() = params.dropInfo?.itemKey ?: "none"
+ @Deprecated(LEGACY_ACCESSOR_DEPRECATION) fun hasDrop() = params.dropInfo != null
+ @Deprecated(LEGACY_ACCESSOR_DEPRECATION) fun toJump() = params.hasCollision && params.collisionMargins.top < 8
+ @Deprecated(LEGACY_ACCESSOR_DEPRECATION) fun hasCollision() = params.hasCollision
+ @Deprecated(LEGACY_ACCESSOR_DEPRECATION) fun isBackground() = params.isBackground
+ @Deprecated(LEGACY_ACCESSOR_DEPRECATION) fun isTransparent() = params.isTransparent
+ @Deprecated(LEGACY_ACCESSOR_DEPRECATION) fun getTexture() = sprite
+
+
+ companion object {
+ private const val LEGACY_ACCESSOR_DEPRECATION = "legacy accessors will be removed"
+ private const val ANIMATION_FRAME_DURATION_MS = 100L
+ }
+}
\ No newline at end of file
diff --git a/core/src/ru/deadsoftware/cavedroid/game/model/block/BlockAnimationInfo.kt b/core/src/ru/deadsoftware/cavedroid/game/model/block/BlockAnimationInfo.kt
--- /dev/null
@@ -0,0 +1,5 @@
+package ru.deadsoftware.cavedroid.game.model.block
+
+data class BlockAnimationInfo(
+ val framesCount: Int
+)
diff --git a/core/src/ru/deadsoftware/cavedroid/game/model/block/BlockDropInfo.kt b/core/src/ru/deadsoftware/cavedroid/game/model/block/BlockDropInfo.kt
--- /dev/null
@@ -0,0 +1,6 @@
+package ru.deadsoftware.cavedroid.game.model.block
+
+data class BlockDropInfo(
+ val itemKey: String,
+ val count: Int,
+)
diff --git a/core/src/ru/deadsoftware/cavedroid/game/model/block/BlockMargins.kt b/core/src/ru/deadsoftware/cavedroid/game/model/block/BlockMargins.kt
--- /dev/null
@@ -0,0 +1,15 @@
+package ru.deadsoftware.cavedroid.game.model.block
+
+data class BlockMargins(
+ val left: Int,
+ val top: Int,
+ val right: Int,
+ val bottom: Int
+) {
+
+ init {
+ assert(left + right < 16)
+ assert(top + bottom < 16)
+ }
+
+}
diff --git a/core/src/ru/deadsoftware/cavedroid/game/model/block/CommonBlockParams.kt b/core/src/ru/deadsoftware/cavedroid/game/model/block/CommonBlockParams.kt
--- /dev/null
@@ -0,0 +1,22 @@
+package ru.deadsoftware.cavedroid.game.model.block
+
+import com.badlogic.gdx.graphics.Texture
+
+data class CommonBlockParams(
+ @Deprecated(ID_DEPRECATION_MESSAGE) val id: Int,
+ val key: String,
+ val collisionMargins: BlockMargins,
+ val hitPoints: Int,
+ val dropInfo: BlockDropInfo?,
+ val hasCollision: Boolean,
+ val isBackground: Boolean,
+ val isTransparent: Boolean,
+ val requiresBlock: Boolean,
+ val animationInfo: BlockAnimationInfo?,
+ val texture: Texture?,
+ val spriteMargins: BlockMargins,
+) {
+ companion object {
+ private const val ID_DEPRECATION_MESSAGE = "numeric id's will be removed"
+ }
+}
diff --git a/core/src/ru/deadsoftware/cavedroid/game/objects/Block.kt b/core/src/ru/deadsoftware/cavedroid/game/objects/Block.kt
+++ /dev/null
@@ -1,151 +0,0 @@
-@file:Suppress("DeprecatedCallableAddReplaceWith")
-
-package ru.deadsoftware.cavedroid.game.objects
-
-import com.badlogic.gdx.graphics.Texture
-import com.badlogic.gdx.graphics.g2d.Sprite
-import com.badlogic.gdx.graphics.g2d.SpriteBatch
-import com.badlogic.gdx.math.Rectangle
-import ru.deadsoftware.cavedroid.game.GameItems
-
-private const val ANIMATION_FRAME_DURATION = 100L
-private const val DEPRECATION_MESSAGE =
- "Deprecated since moved to Kotlin. Use generated getter or kotlin property access."
-
-/**
- * @param left margin from left edge
- * @param top margin from top edge
- * @param right margin from right edge
- * @param bottom margin from bottom edge
- * @param hp hit points
- * @param drop id of an item the block will drop when destroyed
- * @param collision true if block has collision
- * @param background true if block should be drawn behind player
- * @param transparent true if block is transparent and renderer should draw a block behind it
- * @param requiresBlock true if block should break when there is no block with collision under it
- * @param fluid true if fluid
- * @param meta extra info for storing
- * @param texture block's texture
- * @param animated indicates if block has animation
- * @param frames number of animation frames. ignored if animated is false
- * @param spriteLeft block's sprite x on texture
- * @param spriteTop block's sprite y on texture
- * @param spriteRight block's sprite right edge on texture
- * @param spriteBottom block's sprite bottom on texture
- * @param fullBlockKey for slabs. block for two slabs of one kind
- */
-data class Block(
- val id: Int,
- val key: String,
- val left: Int,
- val top: Int,
- val right: Int,
- val bottom: Int,
- val hp: Int,
- val drop: String,
- val collision: Boolean,
- val background: Boolean,
- val transparent: Boolean,
- val requiresBlock: Boolean,
- val fluid: Boolean,
- val meta: String,
- private val texture: Texture?,
- val animated: Boolean,
- val frames: Int,
- private val spriteLeft: Int,
- private val spriteTop: Int,
- private val spriteRight: Int,
- private val spriteBottom: Int,
- val fullBlockKey: String?,
-) {
-
- val width = 16 - right - left
- val height = 16 - top - bottom
-
- private val spriteWidth = 16 - spriteLeft - spriteRight
- private val spriteHeight = 16 - spriteTop - spriteBottom
-
- private val sprite: Sprite?
- get() {
- return if (animated) {
- animation[currentFrame()]
- } else {
- field
- }
- }
-
-
- private val animation: Array<Sprite>
-
- init {
- if (frames !in 0..Int.MAX_VALUE) {
- throw IllegalArgumentException("Animation frames must be in range [0, ${Int.MAX_VALUE}]")
- }
-
- animation = if (animated) {
- if (texture == null) {
- throw IllegalArgumentException("Cannot derive animation frames from null sprite")
- }
- Array(frames) { y ->
- Sprite(texture, spriteLeft, 16 * y + spriteTop, spriteWidth, spriteHeight).apply {
- flip(false, true)
- }
- }
- } else {
- emptyArray()
- }
-
- sprite = if (animated) { animation[0] } else {
- if (texture != null) {
- Sprite(texture, spriteLeft, spriteTop, spriteWidth, spriteHeight).apply {
- flip(false, true)
- }
- } else {
- null
- }
- }
- }
-
- private fun currentFrame() = if (animated) {
- ((System.currentTimeMillis() / ANIMATION_FRAME_DURATION) % frames).toInt()
- } else {
- 0
- }
-
- fun requireSprite() = sprite ?: throw IllegalStateException("Sprite is null")
-
- fun draw(spriter: SpriteBatch, x: Float, y: Float) {
- requireSprite().apply {
- setBounds(x + spriteLeft, y + spriteTop, spriteWidth.toFloat(), spriteHeight.toFloat())
- draw(spriter)
- }
- }
-
- fun getRectangle(x: Int, y: Int) =
- Rectangle(x * 16f + left, y * 16f + this.top, width.toFloat(), height.toFloat())
-
- fun hasDrop() = drop != "none"
-
- fun toJump() = top < 8 && collision
-
- fun getItem() = GameItems.getItem(GameItems.getBlockKey(id))
-
- @Deprecated(DEPRECATION_MESSAGE)
- fun hasCollision() = collision
-
- @Deprecated(DEPRECATION_MESSAGE)
- fun isBackground() = background
-
- @Deprecated(DEPRECATION_MESSAGE)
- fun isTransparent() = transparent
-
- @Deprecated(DEPRECATION_MESSAGE)
- fun isFluid() = fluid
-
- @Deprecated(DEPRECATION_MESSAGE)
- fun requiresBlock() = requiresBlock
-
- @Deprecated("Was renamed to Sprite to comply with variable type.", ReplaceWith("requireSprite()"))
- fun getTexture() = sprite
-
-}
\ No newline at end of file
diff --git a/core/src/ru/deadsoftware/cavedroid/game/objects/Item.kt b/core/src/ru/deadsoftware/cavedroid/game/objects/Item.kt
index a4c41b0424d62342a42ff00838f2bada8e594623..a2dbfc55bece093129d9a8d5103606705b95d54c 100644 (file)
import com.badlogic.gdx.graphics.g2d.Sprite
import ru.deadsoftware.cavedroid.game.GameItems
+import ru.deadsoftware.cavedroid.game.model.block.Block
import ru.deadsoftware.cavedroid.misc.utils.SpriteOrigin
data class Item(
diff --git a/core/src/ru/deadsoftware/cavedroid/game/world/GameWorld.java b/core/src/ru/deadsoftware/cavedroid/game/world/GameWorld.java
index 797e670033ebe4f2abadad58fa96b41cf88b8576..d4a66bcb8ad622ca43193d9df7f9cdb95d24d020 100644 (file)
import ru.deadsoftware.cavedroid.game.GameItems;
import ru.deadsoftware.cavedroid.game.GameScope;
import ru.deadsoftware.cavedroid.game.mobs.MobsController;
+import ru.deadsoftware.cavedroid.game.model.block.Block;
import ru.deadsoftware.cavedroid.game.model.world.generator.WorldGeneratorConfig;
-import ru.deadsoftware.cavedroid.game.objects.Block;
import ru.deadsoftware.cavedroid.game.objects.DropController;
import javax.annotation.CheckForNull;
setForeMap(x, y, value);
} else if (GameItems.isSlab(value) && getForeMap(x, y) == value) {
final Block block = GameItems.getBlock(value);
- if (block.getFullBlockKey() != null) {
- setForeMap(x, y, GameItems.getBlockId(block.getFullBlockKey()));
+ if (block instanceof Block.Slab) {
+ setForeMap(x, y, GameItems.getBlockId(((Block.Slab) block).getFullBlockKey()));
}
}
}
diff --git a/core/src/ru/deadsoftware/cavedroid/game/world/GameWorldBlocksLogicControllerTask.kt b/core/src/ru/deadsoftware/cavedroid/game/world/GameWorldBlocksLogicControllerTask.kt
index 20f992a59fb0b3d07a1b26d47ddd547acf5aec70..c515330d8b51261d55249ab746b25c0c2f2ea3fb 100644 (file)
package ru.deadsoftware.cavedroid.game.world
-import com.badlogic.gdx.Gdx
-import com.badlogic.gdx.utils.TimeUtils
import com.badlogic.gdx.utils.Timer.Task
import ru.deadsoftware.cavedroid.game.GameScope
import ru.deadsoftware.cavedroid.game.actions.getRequiresBlockAction
private fun updateBlock(x: Int, y: Int) {
val block = gameWorld.getForeMapBlock(x, y)
- val blockKey = block.key
+ val blockKey = block.params.key
val action = updateBlockActions[blockKey]
- ?: updateBlockActions.getRequiresBlockAction().takeIf { block.requiresBlock }
+ ?: updateBlockActions.getRequiresBlockAction().takeIf { block.params.requiresBlock }
action?.update(x, y)
}