diff --git a/assets/tiled/level_herbst.tmx b/assets/tiled/level_herbst.tmx index cb42d26..e7e07de 100644 --- a/assets/tiled/level_herbst.tmx +++ b/assets/tiled/level_herbst.tmx @@ -1,5 +1,5 @@ - + @@ -709,6 +709,16 @@ + + + + + + + + + + diff --git a/core/src/main/kotlin/com/last/commit/Game.kt b/core/src/main/kotlin/com/last/commit/Game.kt index 6a19558..28304ce 100644 --- a/core/src/main/kotlin/com/last/commit/Game.kt +++ b/core/src/main/kotlin/com/last/commit/Game.kt @@ -1,20 +1,14 @@ package com.last.commit import com.badlogic.gdx.Game -import com.badlogic.gdx.Gdx import com.badlogic.gdx.Screen import com.badlogic.gdx.graphics.g2d.BitmapFont -import com.badlogic.gdx.scenes.scene2d.ui.Skin -import com.last.commit.inventory.Inventory import com.last.commit.screen.* -import com.last.commit.stages.DialogStage /** [com.badlogic.gdx.ApplicationListener] implementation shared by all platforms. */ class Game : Game() { - lateinit var state: GameState - lateinit var loading: Screen lateinit var menu: Screen lateinit var gameplay: Screen @@ -24,7 +18,6 @@ class Game : Game() { override fun create() { font = BitmapFont() - createState() createScreens() changeScreen(Screens.LOADING) @@ -46,12 +39,4 @@ class Game : Game() { Screens.GAME -> setScreen(gameplay) } } - - fun createState() { - state = GameState( - Inventory(), - null, - DialogStage(Skin(Gdx.files.internal("ui/uiskin.json"))) - ) - } } \ No newline at end of file diff --git a/core/src/main/kotlin/com/last/commit/GameState.kt b/core/src/main/kotlin/com/last/commit/GameState.kt deleted file mode 100644 index f886d75..0000000 --- a/core/src/main/kotlin/com/last/commit/GameState.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.last.commit - -import com.last.commit.inventory.Inventory -import com.last.commit.map.MapState -import com.last.commit.stages.DialogStage - -data class GameState( - val inventory: Inventory, - var map: MapState? = null, - val dialogStage: DialogStage -) { -} \ No newline at end of file diff --git a/core/src/main/kotlin/com/last/commit/Player.kt b/core/src/main/kotlin/com/last/commit/Player.kt index b0ea038..ef7a196 100644 --- a/core/src/main/kotlin/com/last/commit/Player.kt +++ b/core/src/main/kotlin/com/last/commit/Player.kt @@ -5,9 +5,14 @@ import com.badlogic.gdx.graphics.g2d.TextureRegion import com.badlogic.gdx.math.Rectangle import com.badlogic.gdx.math.Vector2 import com.last.commit.audio.SoundEngine +import com.last.commit.inventory.Inventory +import com.last.commit.inventory.InventoryItem +import com.last.commit.map.Collectible +import com.last.commit.map.Door +import com.last.commit.map.Interactable -class Player(private val textureRegion: TextureRegion, private val gameState: GameState) : Collidable { +class Player(private val textureRegion: TextureRegion) : Collidable { private var collider: Rectangle = Rectangle(0f, 0f, 0f, 0f) var position: Vector2 = Vector2.Zero @@ -16,10 +21,13 @@ class Player(private val textureRegion: TextureRegion, private val gameState: Ga private val interactionRange = 60f private var lastStep = 0L + val inventory: Inventory; + init { val size = Math.max(textureRegion.regionWidth, textureRegion.regionHeight).toFloat() collider = Rectangle(0f, 0f, size, size) position = Vector2() + inventory = Inventory() } fun getX(): Float { @@ -125,4 +133,48 @@ class Player(private val textureRegion: TextureRegion, private val gameState: Ga getRotation() ) } + + fun canInteractWith(interactable: Interactable): Boolean { + if (interactable is Door) { + val requiredItem: String = + interactable.cell.getTile().getProperties().get("requiredItem", "", String::class.java) + val item: InventoryItem? = inventory.items.find { it.name == requiredItem } + + val result: Boolean + if (item == null) { + result = requiredItem == "" + } else { + result = requiredItem == item.name + } + return result + } else if (interactable is Collectible) { + if (interactable.requiredItem == "") { + return true + } + inventory.items.find { it.name == interactable.requiredItem } ?: return false + + return true + } + + return false; + } + + fun interactWith(interactable: Interactable): Boolean { + if (interactable is Door) { + //check Collision + if (getCollider().overlaps(interactable.getCollider())) { + return false; + } + interactable.interact() + } else if (interactable is Collectible) { + if (inventory.hasItem(interactable.name) || inventory.isFull()) { + return false + } else { + inventory.add(interactable.name) + return true + } + } + + return false + } } \ No newline at end of file diff --git a/core/src/main/kotlin/com/last/commit/map/Collectible.kt b/core/src/main/kotlin/com/last/commit/map/Collectible.kt index 1f54586..a3c5ae5 100644 --- a/core/src/main/kotlin/com/last/commit/map/Collectible.kt +++ b/core/src/main/kotlin/com/last/commit/map/Collectible.kt @@ -3,7 +3,6 @@ package com.last.commit.map import com.badlogic.gdx.math.Rectangle import com.badlogic.gdx.math.Vector2 import com.badlogic.gdx.scenes.scene2d.ui.Image -import com.last.commit.GameState import com.last.commit.audio.SoundEngine class Collectible( @@ -22,29 +21,9 @@ class Collectible( this.collider = Rectangle(pos.x, pos.y, size.x, size.y) } - override fun interact(otherCollider: Rectangle, state: GameState): Boolean { + override fun interact() { println("Interacting with item $name") SoundEngine.play("GRAB") - if (state.inventory.hasItem(this.name)) { - state.dialogStage.setTexts("You already have this item.") - state.dialogStage.show() - } else if (state.inventory.isFull()) { - state.dialogStage.setTexts("You can't carry anymore items.") - } else { - state.inventory.add(this.name) - return true - } - return false - } - - override fun canInteract(state: GameState): Boolean { - if (requiredItem == "") { - return true - } - state.inventory.items.find { it.name == requiredItem } ?: return false - - return true - } override fun getCollider(): Rectangle { diff --git a/core/src/main/kotlin/com/last/commit/map/Door.kt b/core/src/main/kotlin/com/last/commit/map/Door.kt index 26f013f..c86319c 100644 --- a/core/src/main/kotlin/com/last/commit/map/Door.kt +++ b/core/src/main/kotlin/com/last/commit/map/Door.kt @@ -2,51 +2,27 @@ package com.last.commit.map import com.badlogic.gdx.maps.tiled.TiledMapTileLayer.Cell import com.badlogic.gdx.math.Rectangle -import com.last.commit.GameState import com.last.commit.Wall import com.last.commit.audio.SoundEngine -import com.last.commit.inventory.InventoryItem class Door(gridX: Int, gridY: Int, wallCollider: Rectangle, cell: Cell) : Wall(gridX, gridY, wallCollider, cell), Interactable { + fun getRequiredItem() { - override fun canInteract(state: GameState): Boolean { - - val requiredItem: String = cell.getTile().getProperties().get("requiredItem", "", String::class.java) - - val item: InventoryItem? = state.inventory.items.find { it.name == requiredItem } - - val result: Boolean - if (item == null) { - result = requiredItem == "" - } else { - result = requiredItem == item.name - } - - if (!result) { - state.dialogStage.setTexts("This dor is blocked. You need a key") - state.dialogStage.show() - } - return result } - override fun interact(otherCollider: Rectangle, state: GameState): Boolean { + override fun interact() { println("interacting with door $this") if (isClosed) { SoundEngine.play("DOOR_OPEN") isOpen = true } else if (isOpen) { - if (getCollider().overlaps(otherCollider)) { - // can't close the door cause it is colliding with given collider - } else { - SoundEngine.play("DOOR_CLOSE") - isOpen = false - } + SoundEngine.play("DOOR_CLOSE") + isOpen = false } println("Door is now open = $isOpen") - return false } var isOpen: Boolean diff --git a/core/src/main/kotlin/com/last/commit/map/Interactable.kt b/core/src/main/kotlin/com/last/commit/map/Interactable.kt index f50fd14..f0b0f7e 100644 --- a/core/src/main/kotlin/com/last/commit/map/Interactable.kt +++ b/core/src/main/kotlin/com/last/commit/map/Interactable.kt @@ -1,12 +1,10 @@ package com.last.commit.map import com.badlogic.gdx.math.Rectangle -import com.last.commit.GameState interface Interactable { fun getCollider(): Rectangle - fun interact(otherCollider: Rectangle, state: GameState): Boolean + fun interact() - fun canInteract(state: GameState): Boolean } \ No newline at end of file diff --git a/core/src/main/kotlin/com/last/commit/map/TimeMap.kt b/core/src/main/kotlin/com/last/commit/map/TimeMap.kt index a5c0ca6..d9ea84d 100644 --- a/core/src/main/kotlin/com/last/commit/map/TimeMap.kt +++ b/core/src/main/kotlin/com/last/commit/map/TimeMap.kt @@ -6,17 +6,16 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.badlogic.gdx.maps.tiled.TiledMap import com.badlogic.gdx.maps.tiled.TmxMapLoader import com.badlogic.gdx.maps.tiled.renderers.OrthogonalTiledMapRenderer -import com.badlogic.gdx.math.Rectangle import com.badlogic.gdx.math.Vector2 import com.badlogic.gdx.scenes.scene2d.ui.Image import com.last.commit.Collidable -import com.last.commit.GameState import com.last.commit.Player import com.last.commit.audio.SoundEngine import com.last.commit.inventory.SpritesheetTextureLoader +import com.last.commit.stages.DialogStage -class TimeMap(fileName: String, val state: GameState) { +class TimeMap(fileName: String, val dialogStage: DialogStage) { private val CELL_SIZE = 64 val textureLoader = SpritesheetTextureLoader("sprites/genericItems_spritesheet_colored") @@ -47,7 +46,6 @@ class TimeMap(fileName: String, val state: GameState) { init { map = mapLoader.load(fileName) mapState = MapState(map, textureLoader) - state.map = mapState mapStates[fileName] = mapState mapRenderer = OrthogonalTiledMapRenderer(map) } @@ -63,8 +61,8 @@ class TimeMap(fileName: String, val state: GameState) { System.out.println("Teleporting to targetMap $targetMap") loadMap("tiled/$targetMap") val mapDescription = mapState.description - state.dialogStage.setTexts(4000L, "You teleported to $mapDescription") - state.dialogStage.show() + dialogStage.setTexts(4000L, "You teleported to $mapDescription") + dialogStage.show() } } @@ -79,7 +77,6 @@ class TimeMap(fileName: String, val state: GameState) { mapState = MapState(map, textureLoader) mapStates[name] = mapState } - state.map = mapState } fun getPlayerSpawn(): Vector2 { @@ -115,7 +112,7 @@ class TimeMap(fileName: String, val state: GameState) { return null } - fun interactWith(x: Float, y: Float, blockingCollider: Rectangle) { + fun interactWith(x: Float, y: Float, player: Player) { val gridX = x.toInt() / CELL_SIZE val gridY = y.toInt() / CELL_SIZE @@ -123,13 +120,18 @@ class TimeMap(fileName: String, val state: GameState) { val interactable: Interactable = this.findInteractableAtPosition(gridX, gridY) ?: return //else continue - if (interactable.canInteract(state)) { + if (player.canInteractWith(interactable)) { println("Interacting with element at $gridX:$gridY") - val collected = interactable.interact(blockingCollider, state) - if (collected && interactable is Collectible) { - state.map?.collectibles?.remove(interactable) + val interacted = player.interactWith(interactable); + if (interacted && interactable is Collectible) { + mapState.collectibles.remove(interactable) + } else if (!interacted && interactable is Collectible) { + dialogStage.setTexts("You cannot use this at the moment.") + dialogStage.show() } } else { + dialogStage.setTexts("You cannot interact with this now.") + dialogStage.show() println("Cannot interact with $gridX:$gridY") } } diff --git a/core/src/main/kotlin/com/last/commit/screen/FirstScreen.kt b/core/src/main/kotlin/com/last/commit/screen/FirstScreen.kt index 9ee7425..27b80d7 100644 --- a/core/src/main/kotlin/com/last/commit/screen/FirstScreen.kt +++ b/core/src/main/kotlin/com/last/commit/screen/FirstScreen.kt @@ -19,6 +19,7 @@ import com.last.commit.Player import com.last.commit.config.GameConfig import com.last.commit.map.Interactable import com.last.commit.map.TimeMap +import com.last.commit.stages.DialogStage import com.last.commit.stages.PromptStage import com.last.commit.stages.UIStage import kotlin.math.floor @@ -26,8 +27,6 @@ import kotlin.math.floor /** First screen of the application. Displayed after the application is created. */ class FirstScreen(private val parent: Game) : Screen, InputProcessor { - val gameState = parent.state - val viewportSize = 1200f private var isColliding = false @@ -39,30 +38,28 @@ class FirstScreen(private val parent: Game) : Screen, InputProcessor { lateinit var map: TimeMap val playerTexture = Texture("sprites/characters.png") - val player = Player(TextureRegion(playerTexture, 300, 44, 35, 43), gameState) + val player = Player(TextureRegion(playerTexture, 300, 44, 35, 43)) var shapeRenderer = ShapeRenderer() val highlightColor = Color(0f, 0f, 1f, 0.5f) lateinit var uiStage: UIStage lateinit var promptStage: PromptStage + lateinit var dialogStage: DialogStage val inputProcessors = InputMultiplexer() - init { - - } - override fun show() { val gameConfig = this.loadGameConfig() val randomMap = gameConfig.getRandomMap() - map = TimeMap(randomMap, gameState) + dialogStage = DialogStage(Skin(Gdx.files.internal("ui/uiskin.json"))) + map = TimeMap(randomMap, dialogStage) this.spawnPlayer() this.updateCamera() - uiStage = UIStage("sprites/genericItems_spritesheet_colored", gameState) + uiStage = UIStage("sprites/genericItems_spritesheet_colored", player, map) shapeRenderer.setAutoShapeType(true) promptStage = PromptStage(Skin(Gdx.files.internal("ui/uiskin.json"))) @@ -107,7 +104,7 @@ class FirstScreen(private val parent: Game) : Screen, InputProcessor { viewport.apply() resume() - inputProcessors.addProcessor(gameState.dialogStage) + inputProcessors.addProcessor(dialogStage) inputProcessors.addProcessor(promptStage) inputProcessors.addProcessor(this) Gdx.input.inputProcessor = inputProcessors @@ -122,9 +119,9 @@ class FirstScreen(private val parent: Game) : Screen, InputProcessor { override fun render(delta: Float) { uiStage.act(delta) - gameState.dialogStage.act(delta) + dialogStage.act(delta) promptStage.act(delta) - if (gameState.inventory.checkVictoryCondition()) { + if (player.inventory.checkVictoryCondition()) { promptStage.visible = true promptStage.clearText() promptStage.addText("You won!") @@ -153,7 +150,7 @@ class FirstScreen(private val parent: Game) : Screen, InputProcessor { } promptStage.draw() uiStage.draw() - gameState.dialogStage.draw() + dialogStage.draw() } fun renderInteractables(interactables: List) { @@ -262,7 +259,7 @@ class FirstScreen(private val parent: Game) : Screen, InputProcessor { // Resize your screen here. The parameters represent the new window size. uiStage.resize(width, height) promptStage.resize(width, height) - gameState.dialogStage.resize(width, height) + dialogStage.resize(width, height) viewport.update(width, height) viewport.apply() camera.update() @@ -292,7 +289,7 @@ class FirstScreen(private val parent: Game) : Screen, InputProcessor { fun openDoor() { val playerDirection: Vector2 = player.getAbsoluteDirection() - map.interactWith(playerDirection.x, playerDirection.y, player.getCollider()) + map.interactWith(playerDirection.x, playerDirection.y, player) } fun toWorldCoordinates(x: Float, y: Float): Vector2 { @@ -333,7 +330,7 @@ class FirstScreen(private val parent: Game) : Screen, InputProcessor { val mouseCoordinates: Vector2 = toWorldCoordinates(screenX.toFloat(), screenY.toFloat()) val playerDirection: Vector2 = player.getAbsoluteDirection() - map.interactWith(playerDirection.x, playerDirection.y, player.getCollider()) + map.interactWith(playerDirection.x, playerDirection.y, player) return false } diff --git a/core/src/main/kotlin/com/last/commit/stages/UIStage.kt b/core/src/main/kotlin/com/last/commit/stages/UIStage.kt index 93d15da..00a747f 100644 --- a/core/src/main/kotlin/com/last/commit/stages/UIStage.kt +++ b/core/src/main/kotlin/com/last/commit/stages/UIStage.kt @@ -6,10 +6,11 @@ import com.badlogic.gdx.scenes.scene2d.Stage import com.badlogic.gdx.scenes.scene2d.ui.Image import com.badlogic.gdx.scenes.scene2d.ui.Label import com.badlogic.gdx.utils.viewport.ExtendViewport -import com.last.commit.GameState +import com.last.commit.Player import com.last.commit.inventory.SpritesheetTextureLoader +import com.last.commit.map.TimeMap -class UIStage(path: String, val state: GameState) : Stage(ExtendViewport(512f, 512f)) { +class UIStage(path: String, val player: Player, val map: TimeMap) : Stage(ExtendViewport(512f, 512f)) { val textureLoader = SpritesheetTextureLoader(path) private val labelStyle = Label.LabelStyle(BitmapFont(), Color.BLACK) var mapLabel = Label("unknown time", labelStyle) @@ -18,7 +19,7 @@ class UIStage(path: String, val state: GameState) : Stage(ExtendViewport(512f, 5 fun refresh() { super.clear() - state.inventory.items.forEachIndexed { index, inventoryItem -> + player.inventory.items.forEachIndexed { index, inventoryItem -> val image = Image(textureLoader.getTexture(inventoryItem.name)) image.x = index * 32f image.width = 32f @@ -33,9 +34,9 @@ class UIStage(path: String, val state: GameState) : Stage(ExtendViewport(512f, 5 } override fun act(delta: Float) { - if (state.inventory.updated) { + if (player.inventory.updated) { this.refresh() - state.inventory.updated = false + player.inventory.updated = false } this.addFpsLabel(delta) this.addMapDescriptionLabel() @@ -58,9 +59,9 @@ class UIStage(path: String, val state: GameState) : Stage(ExtendViewport(512f, 5 } private fun addMapDescriptionLabel() { - if (state.map != null) { + if (map.mapState != null) { this.actors.removeValue(this.mapLabel, true) - this.mapLabel = Label(state.map!!.description, labelStyle) + this.mapLabel = Label(map.mapState!!.description, labelStyle) mapLabel.x = 0f mapLabel.y = this.viewport.worldHeight - mapLabel.height addActor(mapLabel)