1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
package coffee.liz.abstractionengine.game
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.IntSize
import coffee.liz.ecs.System
import coffee.liz.ecs.World
import coffee.liz.ecs.animation.AnimationSystem
import coffee.liz.ecs.animation.Animator
import coffee.liz.ecs.animation.Position
import coffee.liz.ecs.animation.SpriteSheet
import kotlin.reflect.KClass
import kotlin.time.Duration
/**
* System that renders sprites to a DrawScope.
*
* This system queries all entities with Position, SpriteSheet, and Animator components,
* then draws their current animation frame to the provided DrawScope.
*
* Depends on AnimationSystem to ensure animations are updated before rendering.
*/
class Renderer(
private val imageCache: ImageCache,
) : System {
override val dependencies: Set<KClass<out System>> = setOf(AnimationSystem::class)
override fun update(
world: World,
duration: Duration,
) {
// Rendering happens in render() method, not here
}
/**
* Renders all entities with sprites to the given DrawScope.
* This should be called from a Compose Canvas during the draw phase.
*/
fun render(
world: World,
drawScope: DrawScope,
) {
// Query all entities that can be rendered
world.query(Position::class, SpriteSheet::class, Animator::class).forEach { entity ->
val position = entity.get(Position::class) ?: return@forEach
val spriteSheet = entity.get(SpriteSheet::class) ?: return@forEach
val animator = entity.get(Animator::class) ?: return@forEach
// Get the current frame name from the animator
val frameName = animator.getCurrentFrameName() ?: return@forEach
// Look up the frame rectangle in the sprite sheet
val frameRect = spriteSheet.frames[frameName] ?: return@forEach
// Get the image from cache
val image = imageCache.getImage(spriteSheet.imagePath) ?: return@forEach
// Draw the sprite
with(drawScope) {
drawImage(
image = image,
srcOffset = IntOffset(frameRect.x, frameRect.y),
srcSize = IntSize(frameRect.width, frameRect.height),
dstOffset = IntOffset(position.x.toInt(), position.y.toInt()),
dstSize = IntSize(frameRect.width, frameRect.height),
)
}
}
}
}
|