Skip to content

Commit

Permalink
add damage functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
Quillraven committed Mar 24, 2024
1 parent 050043b commit f43a2ad
Show file tree
Hide file tree
Showing 15 changed files with 183 additions and 64 deletions.
Binary file added assets/audio/hurt.wav
Binary file not shown.
Binary file removed assets/audio/jump.mp3
Binary file not shown.
Binary file added assets/audio/jump.wav
Binary file not shown.
3 changes: 2 additions & 1 deletion assets/maps/objects.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
</properties>
<image width="32" height="32" source="../graphics/object/frog.png"/>
<objectgroup draworder="index" id="2">
<object id="3" type="FixtureDef" x="7" y="11" width="18" height="20">
<object id="3" type="FixtureDef" x="7" y="10" width="18" height="23">
<properties>
<property name="isSensor" type="bool" value="true"/>
<property name="userData" value="hitbox"/>
Expand Down Expand Up @@ -44,6 +44,7 @@
<properties>
<property name="GameObject" propertytype="GameObject" value="SAW"/>
<property name="bodyType" propertytype="BodyType" value="KinematicBody"/>
<property name="damage" type="int" value="1"/>
<property name="entityTags" propertytype="EntityTag" value="FOLLOW_TRACK"/>
<property name="hasAnimation" type="bool" value="true"/>
<property name="speed" type="float" value="3"/>
Expand Down
9 changes: 7 additions & 2 deletions assets/maps/test.tmx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.10" tiledversion="1.10.2" orientation="orthogonal" renderorder="right-down" width="30" height="10" tilewidth="16" tileheight="16" infinite="0" nextlayerid="6" nextobjectid="13">
<map version="1.10" tiledversion="1.10.2" orientation="orthogonal" renderorder="right-down" width="30" height="10" tilewidth="16" tileheight="16" infinite="0" nextlayerid="6" nextobjectid="14">
<properties>
<property name="musicAsset" value="TUTORIAL"/>
<property name="name" value="Tutorial"/>
Expand All @@ -17,9 +17,14 @@
</data>
</layer>
<objectgroup id="3" name="objects">
<object id="3" gid="243" x="209" y="94" width="32" height="32"/>
<object id="3" gid="243" x="103" y="97" width="32" height="32"/>
<object id="4" gid="244" x="333" y="75" width="38" height="38"/>
<object id="11" gid="244" x="269" y="105" width="38" height="38"/>
<object id="13" gid="244" x="158" y="63" width="38" height="38">
<properties>
<property name="entityTags" propertytype="EntityTag" value=""/>
</properties>
</object>
</objectgroup>
<objectgroup id="5" name="tracks">
<object id="10" x="320" y="57">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ enum class MusicAsset(val path: String) {
}

enum class SoundAsset(val path: String) {
JUMP("audio/jump.mp3"),
JUMP("audio/jump.wav"),
HURT("audio/hurt.wav"),
}

enum class SkinAsset(val path: String) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.quillraven.github.quillyjumper.component

import com.github.quillraven.fleks.Component
import com.github.quillraven.fleks.ComponentType

data class Damage(var amount: Int) : Component<Damage> {
override fun type() = Damage

companion object : ComponentType<Damage>()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.quillraven.github.quillyjumper.component

import com.github.quillraven.fleks.Component
import com.github.quillraven.fleks.ComponentType

data class DamageTaken(var amount: Int) : Component<DamageTaken> {
override fun type() = DamageTaken

companion object : ComponentType<DamageTaken>()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.quillraven.github.quillyjumper.component

import com.github.quillraven.fleks.Component
import com.github.quillraven.fleks.ComponentType

data class Invulnerable(var time: Float) : Component<Invulnerable> {
override fun type() = Invulnerable

companion object : ComponentType<Invulnerable>()
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.quillraven.github.quillyjumper.screen

import com.badlogic.gdx.Gdx
import com.badlogic.gdx.Input
import com.badlogic.gdx.graphics.OrthographicCamera
import com.badlogic.gdx.graphics.g2d.Batch
import com.badlogic.gdx.scenes.scene2d.Stage
Expand All @@ -13,9 +12,6 @@ import com.quillraven.github.quillyjumper.GameProperties
import com.quillraven.github.quillyjumper.MapAsset
import com.quillraven.github.quillyjumper.Quillyjumper.Companion.GRAVITY
import com.quillraven.github.quillyjumper.audio.AudioService
import com.quillraven.github.quillyjumper.component.EntityTag
import com.quillraven.github.quillyjumper.component.Life
import com.quillraven.github.quillyjumper.event.EntityDamageEvent
import com.quillraven.github.quillyjumper.event.GameEventDispatcher
import com.quillraven.github.quillyjumper.event.GameEventListener
import com.quillraven.github.quillyjumper.event.MapChangeEvent
Expand Down Expand Up @@ -86,44 +82,6 @@ class GameScreen(
}

override fun render(delta: Float) {
// TODO remove debug stuff
when {
Gdx.input.isKeyJustPressed(Input.Keys.NUM_0) -> {
world.family { all(EntityTag.PLAYER) }.forEach {
it[Life].current = 0f
GameEventDispatcher.fire(EntityDamageEvent(it, it[Life]))
}
}

Gdx.input.isKeyJustPressed(Input.Keys.NUM_1) -> {
world.family { all(EntityTag.PLAYER) }.forEach {
it[Life].current = 1f
GameEventDispatcher.fire(EntityDamageEvent(it, it[Life]))
}
}

Gdx.input.isKeyJustPressed(Input.Keys.NUM_2) -> {
world.family { all(EntityTag.PLAYER) }.forEach {
it[Life].current = 2f
GameEventDispatcher.fire(EntityDamageEvent(it, it[Life]))
}
}

Gdx.input.isKeyJustPressed(Input.Keys.NUM_3) -> {
world.family { all(EntityTag.PLAYER) }.forEach {
it[Life].current = 3f
GameEventDispatcher.fire(EntityDamageEvent(it, it[Life]))
}
}

Gdx.input.isKeyJustPressed(Input.Keys.NUM_4) -> {
world.family { all(EntityTag.PLAYER) }.forEach {
it[Life].current = 4f
GameEventDispatcher.fire(EntityDamageEvent(it, it[Life]))
}
}
}

world.update(delta)
}

Expand All @@ -148,6 +106,8 @@ class GameScreen(
add(TrackSystem())
add(JumpPhysicSystem())
add(PhysicSystem())
add(DamageSystem())
add(InvulnerableSystem())
add(StateSystem())
add(AnimationSystem())
add(CameraSystem())
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.quillraven.github.quillyjumper.system

import com.github.quillraven.fleks.Entity
import com.github.quillraven.fleks.IteratingSystem
import com.github.quillraven.fleks.World.Companion.family
import com.github.quillraven.fleks.World.Companion.inject
import com.quillraven.github.quillyjumper.SoundAsset
import com.quillraven.github.quillyjumper.audio.AudioService
import com.quillraven.github.quillyjumper.component.DamageTaken
import com.quillraven.github.quillyjumper.component.EntityTag
import com.quillraven.github.quillyjumper.component.Invulnerable
import com.quillraven.github.quillyjumper.component.Life
import com.quillraven.github.quillyjumper.event.EntityDamageEvent
import com.quillraven.github.quillyjumper.event.GameEventDispatcher
import ktx.log.logger

class DamageSystem(
private val audioService: AudioService = inject(),
) : IteratingSystem(family { all(DamageTaken, Life).none(Invulnerable) }) {

override fun onTickEntity(entity: Entity) {
val (damageAmount) = entity[DamageTaken]
val lifeCmp = entity[Life]
lifeCmp.current = (lifeCmp.current - damageAmount).coerceAtLeast(0f)
log.debug { "Entity $entity takes $damageAmount damage. New life=${lifeCmp.current}" }
audioService.play(SoundAsset.HURT)
GameEventDispatcher.fire(EntityDamageEvent(entity, lifeCmp))

if (entity has EntityTag.PLAYER) {
// player becomes invulnerable after taking damage
entity.configure { it += Invulnerable(1.5f) }
}
}

companion object {
private val log = logger<DamageSystem>()
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,7 @@ import com.github.quillraven.fleks.IteratingSystem
import com.github.quillraven.fleks.World.Companion.family
import com.github.quillraven.fleks.World.Companion.inject
import com.quillraven.github.quillyjumper.PhysicWorld
import com.quillraven.github.quillyjumper.component.Graphic
import com.quillraven.github.quillyjumper.component.Move
import com.quillraven.github.quillyjumper.component.Physic
import com.quillraven.github.quillyjumper.component.Track
import com.quillraven.github.quillyjumper.component.*
import ktx.log.logger
import ktx.math.component1
import ktx.math.component2
Expand Down Expand Up @@ -65,9 +62,84 @@ class PhysicSystem(
)
}

override fun beginContact(contact: Contact) = Unit
private val Fixture.entity: Entity?
get() {
val userData = this.body.userData
if (userData is Entity) {
return userData
}
return null
}

private val Contact.entityA: Entity?
get() = fixtureA.entity

private val Contact.entityB: Entity?
get() = fixtureB.entity

private fun Fixture.isHitbox(): Boolean = "hitbox" == userData

override fun beginContact(contact: Contact) {
val fixtureA = contact.fixtureA
val fixtureB = contact.fixtureB
val entityA = contact.entityA
val entityB = contact.entityB
if (entityA == null || entityB == null) {
// ignore collision between non entity bodies
return
}

override fun endContact(contact: Contact) = Unit
if (isDamageCollision(entityA, entityB, fixtureA, fixtureB)) {
handleDamageBeginContact(entityA, entityB)
} else if (isDamageCollision(entityB, entityA, fixtureB, fixtureA)) {
handleDamageBeginContact(entityB, entityA)
}
}

override fun endContact(contact: Contact) {
val fixtureA = contact.fixtureA
val fixtureB = contact.fixtureB
val entityA = contact.entityA
val entityB = contact.entityB
if (entityA == null || entityB == null) {
// ignore collision between non entity bodies
return
}

if (isDamageCollision(entityA, entityB, fixtureA, fixtureB)) {
handleDamageEndContact(entityA, entityB)
} else if (isDamageCollision(entityB, entityA, fixtureB, fixtureA)) {
handleDamageEndContact(entityB, entityA)
}
}

// update target's DamageTaken component amount. This will also add the component, if it is not added yet
private fun handleDamageBeginContact(damageSource: Entity, damageTarget: Entity) = with(world) {
log.debug { "Begin Damage collision between $damageSource and $damageTarget" }

val (damageAmount) = damageSource[Damage]
damageTarget.configure {
val damageTakenCmp = it.getOrAdd(DamageTaken) { DamageTaken(0) }
damageTakenCmp.amount += damageAmount
}
}

// remove damage from target and if there is no damage left then remove DamageTaken component
private fun handleDamageEndContact(damageSource: Entity, damageTarget: Entity) = with(world) {
log.debug { "End Damage collision between $damageSource and $damageTarget" }

damageTarget.getOrNull(DamageTaken)?.let { damageTakenCmp ->
val (damageAmount) = damageSource[Damage]
damageTakenCmp.amount -= damageAmount
if (damageTakenCmp.amount <= 0) {
damageTarget.configure { it -= DamageTaken }
}
}
}

private fun isDamageCollision(entityA: Entity, entityB: Entity, fixtureA: Fixture, fixtureB: Fixture): Boolean {
return entityA has Damage && entityB has Life && fixtureA.isHitbox() && fixtureB.isHitbox()
}

override fun preSolve(contact: Contact, oldManifold: Manifold) {
val bodyA = contact.fixtureA.body
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ class TiledService(
}
}

gdxError("There is no related track for $mapObjectId")
gdxError("There is no related track for MapObject $mapObjectId")
}

private fun spawnGameObjectEntity(mapObject: MapObject) {
Expand Down Expand Up @@ -160,7 +160,7 @@ class TiledService(
it += Graphic(sprite(gameObject, AnimationType.IDLE.atlasKey, body.position))

// EntityTags
val tagsStr = tile.property<String>("entityTags", "")
val tagsStr = mapObject.propertyOrNull<String>("entityTags") ?: tile.property<String>("entityTags", "")
if (tagsStr.isNotBlank()) {
val tags = tagsStr.split(",").map(EntityTag::valueOf)
it += tags
Expand Down Expand Up @@ -191,6 +191,11 @@ class TiledService(
val timeToMaxSpeed = tile.property<Float>("timeToMaxSpeed", 0f)
it += Move(max = speed, timeToMax = timeToMaxSpeed.coerceAtLeast(0.1f))
}
// Damage
val damage = tile.property<Int>("damage", 0)
if (damage > 0) {
it += Damage(damage)
}

log.debug {
"""Spawning entity with:
Expand All @@ -203,6 +208,7 @@ class TiledService(
| Jump: $jumpHeight
| Life: $life
| Move: $speed
| Damage: $damage
""".trimMargin()
}
}
Expand Down
5 changes: 5 additions & 0 deletions tiled-project.tiled-project
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@
"type": "string",
"value": "DynamicBody"
},
{
"name": "damage",
"type": "int",
"value": 0
},
{
"name": "entityTags",
"propertyType": "EntityTag",
Expand Down
20 changes: 10 additions & 10 deletions tiled-project.tiled-session
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
"height": 4300,
"width": 2
},
"activeFile": "assets/maps/objects.tsx",
"activeFile": "assets/maps/test.tmx",
"expandedProjectPaths": [
"assets/maps",
".",
"assets",
"lwjgl3/build",
"."
"assets/maps",
"lwjgl3/build"
],
"fileStates": {
"": {
Expand Down Expand Up @@ -46,11 +46,11 @@
"expandedObjectLayers": [
3
],
"scale": 11,
"selectedLayer": 1,
"scale": 3,
"selectedLayer": 2,
"viewCenter": {
"x": 140.13636363636363,
"y": 80.04545454545456
"x": 230.83333333333331,
"y": 72.49999999999999
}
}
},
Expand All @@ -68,11 +68,11 @@
"assets/maps/objects.tsx"
],
"project": "tiled-project.tiled-project",
"property.type": "BodyType",
"property.type": "int",
"recentFiles": [
"assets/maps/objects.tmx",
"assets/maps/test.tmx",
"assets/maps/objects.tsx",
"assets/maps/test.tmx",
"assets/maps/terrain.tsx",
"assets/maps/terrain_extruded.tsx"
],
Expand Down

0 comments on commit f43a2ad

Please sign in to comment.