From d5e404ccc619155eb184cd58150b91c038c11319 Mon Sep 17 00:00:00 2001 From: harper Date: Tue, 13 Oct 2026 16:33:45 -0700 Subject: [PATCH] sync my shit --- general/components.odin | 16 ++++++- general/ecs/ecs.odin | 35 --------------- general/entities.odin | 19 -------- general/main.odin | 97 +++++++++++++++-------------------------- general/shoal | 1 + general/systems.odin | 49 ++++++++++++++++----- 6 files changed, 87 insertions(+), 130 deletions(-) delete mode 100644 general/ecs/ecs.odin create mode 160000 general/shoal diff --git a/general/components.odin b/general/components.odin index c9350db..aaa6d87 100644 --- a/general/components.odin +++ b/general/components.odin @@ -1,13 +1,25 @@ package main +import ecs "shoal/src" import rl "vendor:raylib" -Transform :: struct { +GridActorComponent :: struct { position: rl.Vector2, + size: int, + speed: f32, + can_move: bool, } +GridActor: ecs.Storage(GridActorComponent) -Weapon :: struct { +WeaponComponent :: struct { dmg: i32, rpm: f32, cooldown: bool, } +Weapon: ecs.Storage(WeaponComponent) + +EnemyComponent :: struct {} +Enemy: ecs.Storage(EnemyComponent) + +PlayerComponent :: struct {} +Player: ecs.Storage(PlayerComponent) diff --git a/general/ecs/ecs.odin b/general/ecs/ecs.odin deleted file mode 100644 index 6c2f39b..0000000 --- a/general/ecs/ecs.odin +++ /dev/null @@ -1,35 +0,0 @@ -package ecs - -import "core:fmt" - -startup_systems: [dynamic]proc() -update_systems: [dynamic]proc() -fixed_update_systems: [dynamic]proc() - - -App :: struct {} - -Component :: union { - Transform, -} - -Transform :: struct {} - -STARTUP :: 0 -UPDATE :: 1 -FIXED_UPDATE :: 2 - -add_system :: proc(schedule: int, system: proc()) { - switch schedule { - case 0: - append(&startup_systems, system) - case 1: - append(&update_systems, system) - case 2: - append(&fixed_update_systems, system) - } -} - -ping :: proc() { - -} diff --git a/general/entities.odin b/general/entities.odin index 097b079..06ab7d0 100644 --- a/general/entities.odin +++ b/general/entities.odin @@ -1,20 +1 @@ package main - -import rl "vendor:raylib" - -Entity :: union { - Player, - Enemy, -} - -Player :: struct { - transform: Transform, - sprite: rl.Texture2D, - camera: rl.Camera2D, - weapon: Weapon, -} - -Enemy :: struct { - transform: Transform, - sprite: rl.Texture2D, -} diff --git a/general/main.odin b/general/main.odin index bb16f6d..2347a31 100644 --- a/general/main.odin +++ b/general/main.odin @@ -1,82 +1,65 @@ package main import "core:fmt" +import ecs "shoal/src" import rl "vendor:raylib" -World :: struct { - entities: map[rl.Vector2]Entity, -} - -world: World -player: Player -enemy: Enemy camera: rl.Camera2D CELL_SIZE :: 20 +app: ecs.App + main :: proc() { - fmt.println("hello world") - rl.InitWindow(800, 600, "grimm gameplay prototype") - defer rl.CloseWindow() - - player = Player { - transform = Transform{position = {4, 8}}, - camera = rl.Camera2D{target = {0, 0}, zoom = 1.5}, - weapon = Weapon{dmg = 1, rpm = 450, cooldown = false}, - } - world.entities[player.transform.position] = player - enemy = Enemy { - transform = Transform{position = {8, 8}}, - } - world.entities[enemy.transform.position] = enemy - - for !rl.WindowShouldClose() { - update() - rl.BeginDrawing() - rl.ClearBackground(rl.PURPLE) - rl.BeginMode2D(player.camera) - draw() - rl.EndMode2D() - rl.EndDrawing() - } + ecs.add_plugin(&app, ecs.DefaultPlugin) + ecs.add_system(&app, ecs.STARTUP, setup_entities) + ecs.add_system(&app, ecs.UPDATE, player_move) + ecs.add_system(&app, ecs.UPDATE, run_particle_system) + ecs.add_system(&app, ecs.UPDATE, run_timers) + ecs.add_system(&app, ecs.DRAW, draw_player) + ecs.add_system(&app, ecs.UPDATE, update_grid_actor) + ecs.run(&app) } -update :: proc() { +setup_entities :: proc() { + player := ecs.spawn_entity(&app) + ecs.add_component(player, &Player) + ecs.add_component(player, &Weapon) + ecs.add_component(player, &GridActor) + ecs.add_component(player, &ecs.Sprite) + ecs.add_component(player, &ecs.Transform) +} + +player_move :: proc() { + e, player := ecs.single(&Player) + grid_actor := ecs.get_component(e, &GridActor) + if rl.IsKeyPressed(rl.KeyboardKey.W) { - move(&player.transform, 0, -1) + move(grid_actor, 0, -1) } if rl.IsKeyPressed(rl.KeyboardKey.A) { - move(&player.transform, -1, 0) + move(grid_actor, -1, 0) } if rl.IsKeyPressed(rl.KeyboardKey.S) { - move(&player.transform, 0, 1) + move(grid_actor, 0, 1) } if rl.IsKeyPressed(rl.KeyboardKey.D) { - move(&player.transform, 1, 0) + move(grid_actor, 1, 0) } - - if rl.IsKeyPressed(rl.KeyboardKey.SPACE) { - move(&enemy.transform, 1, 0) - } - - run_timers() } -draw :: proc() { +draw_player :: proc() { + e, player := ecs.single(&Player) + transform := ecs.get_component(e, &ecs.Transform) rl.DrawRectangle( - i32(player.transform.position.x * CELL_SIZE), - i32(player.transform.position.y * CELL_SIZE), + i32(transform.translation.x), + i32(transform.translation.y), CELL_SIZE, CELL_SIZE, rl.WHITE, ) - rl.DrawRectangle( - i32(enemy.transform.position.x * CELL_SIZE), - i32(enemy.transform.position.y * CELL_SIZE), - CELL_SIZE, - CELL_SIZE, - rl.BLUE, - ) +} +draw_grid :: proc() { for x in 0 ..< 26 { for y in 0 ..< 26 { rl.DrawRectangleLines( @@ -88,14 +71,4 @@ draw :: proc() { ) } } - - if rl.IsMouseButtonDown(rl.MouseButton.LEFT) { - pos := rl.GetScreenToWorld2D(rl.GetMousePosition(), player.camera) - pos_x := int(pos.x / CELL_SIZE) * CELL_SIZE - pos_y := int(pos.y / CELL_SIZE) * CELL_SIZE - shoot(player.transform, {f32(pos_x), f32(pos_y)}) - } - - run_particle_system() - } diff --git a/general/shoal b/general/shoal new file mode 160000 index 0000000..de088f6 --- /dev/null +++ b/general/shoal @@ -0,0 +1 @@ +Subproject commit de088f69e6619b2bdccbf48a4f648111a2a5e494 diff --git a/general/systems.odin b/general/systems.odin index f619693..906fe56 100644 --- a/general/systems.odin +++ b/general/systems.odin @@ -3,39 +3,64 @@ package main import "core:fmt" import "core:math" import "core:math/rand" +import ecs "shoal/src" import rl "vendor:raylib" -move :: proc(t: ^Transform, x, y: f32) { - next_position := Transform { +can_move_signal := ecs.Signal { + callbacks = {reset_grid_actor_can_move}, +} + +move :: proc(t: ^GridActorComponent, x, y: f32) { + next_position := GridActorComponent { position = {t.position.x + x, t.position.y + y}, } - if e, occupied := world.entities[next_position.position]; !occupied { - delete_key(&world.entities, t.position) - defer world.entities[t.position] = e - t.position = next_position.position + + for i, v in ecs.slice(&GridActor) { + if v.position != next_position.position { + t.position = next_position.position + } } } -shoot :: proc(t: Transform, pos: rl.Vector2) { +reset_grid_actor_can_move :: proc(args: ..any) { + t.can_move = true +} + +update_grid_actor :: proc() { + for e, grid_actor in ecs.slice(&GridActor) { + transform := ecs.get_component(e, &ecs.Transform) + transform.translation = grid_actor.position * CELL_SIZE + } + +} + +shoot :: proc(t: ecs.TransformComponent, weapon: ^WeaponComponent, pos: rl.Vector2) { pos_centered := center_to_grid(pos) - t_centered := center_to_grid(t.position) + t_centered := center_to_grid(t.translation) spray: rl.Vector2 = { pos.x + rand.float32_range(0, CELL_SIZE), pos.y + rand.float32_range(0, CELL_SIZE), } line_particle := LineParticle { - pos1 = t.position * CELL_SIZE + 10, + pos1 = t.translation * CELL_SIZE + 10, pos2 = spray, tint = rl.WHITE, lifetime = 0.2, } - if player.weapon.cooldown == true {return} - player.weapon.cooldown = true - start_timer(60 / player.weapon.rpm, proc() {player.weapon.cooldown = false}) + if weapon.cooldown == true {return} + weapon.cooldown = true + start_timer(60 / weapon.rpm, reset_weapon_cooldown) spawn_particle(line_particle) } +reset_weapon_cooldown :: proc() { + for i, v in ecs.slice(&Player) { + weapon := ecs.get_component(i, &Weapon) + weapon.cooldown = false + } +} + center_to_grid :: proc(pos: rl.Vector2) -> rl.Vector2 { pos_x, pos_y: f32 pos_x = pos.x + CELL_SIZE / 2