summaryrefslogtreecommitdiff
path: root/composeApp/src/commonMain/kotlin/coffee/liz/ecs/grid/Grid.kt
blob: f4eef43634b149d11599914a4387f57b380f3b77 (plain)
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
package coffee.liz.ecs.grid

import coffee.liz.ecs.Entity
import coffee.liz.ecs.Rect
import coffee.liz.ecs.Vec2

data class Grid(
    val dimensions: Vec2,
    val grid: MutableList<MutableList<MutableSet<Entity>>> =
        MutableList(dimensions.y.toInt()) {
            MutableList(dimensions.x.toInt()) { mutableSetOf() }
        },
) {
    fun at(position: Vec2): MutableSet<Entity> {
        if (!Rect(Vec2(0f, 0f), dimensions).contains(position)) {
            throw IllegalArgumentException()
        }
        return grid[position.y.toInt()][position.x.toInt()]
    }

    fun add(entity: Entity) {
        if (!entity.has(GridPosition::class)) {
            throw IllegalArgumentException("Entity must have a GridPosition component to be added to the grid")
        }
        val position = entity.get(GridPosition::class).position
        at(position).add(entity)
    }

    fun reassignCellEntities(entities: Collection<Entity>) {
        val remainingEntities = entities.filter { it.has(GridPosition::class) }.toMutableSet()
        for (y in grid.indices) {
            for (x in grid[y].indices) {
                val vec = Vec2(x.toFloat(), y.toFloat())
                val entities = at(vec)
                entities.retainAll(
                    entities
                        .filter {
                            if (!it.has(GridPosition::class)) {
                                return@filter false
                            }
                            val currentPosition = it.get(GridPosition::class).position
                            (vec == currentPosition).also { stillInCell ->
                                if (!stillInCell) {
                                    at(currentPosition).add(it)
                                }
                            }
                        }.toSet(),
                )
                remainingEntities.removeAll(entities)
            }
        }
        remainingEntities.forEach { add(it) }
    }
}