preparing to actually start working on a 'game'
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 28 Feb 2022 19:18:50 +0000 (13:18 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 28 Feb 2022 19:18:50 +0000 (13:18 -0600)
run_tree/scenes/quick_save_new.scene
src/entity/components/movement.onyx [new file with mode: 0644]
src/entity/components/player.onyx [new file with mode: 0644]
src/entity/editor.onyx
src/entity/entities.onyx [new file with mode: 0644]
src/entity/items.onyx
src/entity/manager.onyx
src/entity/player.onyx [deleted file]
src/entity/schematics/player.onyx [new file with mode: 0644]
src/entity/store.onyx
src/game.onyx

index 19205dd67065aa2e2d50abf46fcdd7389fab6c99..fda31956bdc7efeb34c06db8861646c9559ac084 100644 (file)
@@ -2,10 +2,11 @@
 id = 10
 flags = 2
 pos.x = 176.0000
-pos.y = 312.0000
+pos.y = 88.0000
 size.x = 352.0000
 size.y = 16.0000
 :RenderComponent
+layer = 0
 color.r = 1.0000
 color.g = 1.0000
 color.b = 1.0000
@@ -15,10 +16,11 @@ color.a = 1.0000
 id = 11
 flags = 3
 pos.x = 440.0000
-pos.y = 160.0000
+pos.y = 48.0000
 size.x = 16.0000
-size.y = 320.0000
+size.y = 96.0000
 :RenderComponent
+layer = 0
 color.r = 1.0000
 color.g = 1.0000
 color.b = 1.0000
@@ -27,8 +29,8 @@ color.a = 1.0000
 [Player]
 id = 12
 flags = 2
-pos.x = 544.3174
-pos.y = 236.6171
+pos.x = 390.5043
+pos.y = 187.4996
 size.x = 32.0000
 size.y = 32.0000
 :MovementComponent
@@ -38,10 +40,11 @@ controls.left = 65
 controls.right = 68
 controls.interact = 70
 controls.pick_up = 71
-facing = 4
+facing = 2
 :PlayerComponent
 holding = 0
 :RenderComponent
+layer = 0
 color.r = 0.0000
 color.g = 1.0000
 color.b = 0.0000
@@ -51,7 +54,7 @@ color.a = 1.0000
 id = 13
 flags = 3
 pos.x = 352.0000
-pos.y = 312.0000
+pos.y = 88.0000
 size.x = 160.0000
 size.y = 16.0000
 :DoorComponent
@@ -59,54 +62,26 @@ max_openness = 0.8000
 target_openness = 0.8000
 openness = 0.8000
 :RenderComponent
+layer = 0
 color.r = 1.0000
 color.g = 1.0000
 color.b = 1.0000
 color.a = 1.0000
 
-[Item_Entity]
-id = 14
-flags = 4
-pos.x = 508.3851
-pos.y = 375.2260
-size.x = 16.0000
-size.y = 16.0000
-:RenderComponent
-color.r = 1.0000
-color.g = 1.0000
-color.b = 1.0000
-color.a = 1.0000
-:ItemComponent
-item = "beer"
-
-[Item_Entity]
-id = 15
-flags = 4
-pos.x = 555.2645
-pos.y = 298.4719
-size.x = 16.0000
-size.y = 16.0000
-:RenderComponent
-color.r = 1.0000
-color.g = 1.0000
-color.b = 1.0000
-color.a = 1.0000
-:ItemComponent
-item = "beer"
-
 [Tap]
-id = 16
+id = 14
 flags = 3
-pos.x = 576.0000
-pos.y = 160.0000
+pos.x = 32.0000
+pos.y = 16.0000
 size.x = 32.0000
 size.y = 32.0000
 :RenderComponent
-color.r = 0.1000
-color.g = 0.1000
+layer = 1
+color.r = 0.2000
+color.g = 0.2000
 color.b = 1.0000
 color.a = 1.0000
 :DispenserComponent
 item = "beer"
-max_timeout = 5.0000
+max_timeout = 2.0000
 
diff --git a/src/entity/components/movement.onyx b/src/entity/components/movement.onyx
new file mode 100644 (file)
index 0000000..a1585a3
--- /dev/null
@@ -0,0 +1,67 @@
+
+use package core
+use package glfw3
+
+
+Facing :: enum {
+    Up    :: 0x01;
+    Down  :: 0x02;
+    Left  :: 0x03;
+    Right :: 0x04;
+}
+
+facing_to_direction_vector :: macro (f: Facing) -> Vector2 {
+    switch f {
+        case .Up    do return .{0, -1};
+        case .Down  do return .{0,  1};
+        case .Left  do return .{-1, 0};
+        case .Right do return .{1,  0};
+    }
+}
+
+
+MovementComponent :: struct { 
+    use component: Component;
+    controls : Player_Controls;
+    facing   := Facing.Up;
+
+    update :: (movement: ^MovementComponent, use this: ^Entity, dt: f32) {
+        speed :: 128.0f;
+
+        delta: Vector2;
+        if is_key_down(movement.controls.left)  { delta.x -= speed * dt; movement.facing = .Left;  }
+        if is_key_down(movement.controls.right) { delta.x += speed * dt; movement.facing = .Right; }
+        if is_key_down(movement.controls.up)    { delta.y -= speed * dt; movement.facing = .Up;    }
+        if is_key_down(movement.controls.down)  { delta.y += speed * dt; movement.facing = .Down;  }
+
+        dist := math.max(size.x, size.y) * 2;
+        walls := scene->query_by_flags(.{pos.x - dist, pos.y - dist, dist * 2, dist * 2}, .Solid);
+        defer memory.free_slice(^walls);
+
+        try_move(this, .{delta.x, 0}, walls);
+        try_move(this, .{0, delta.y}, walls);
+    }
+
+    try_move :: (use this: ^Entity, delta: Vector2, obsticles: [] ^Entity) {
+        pos += delta;
+        ent_rect := Entity.get_rect(this);
+
+        holding: Entity_ID;
+        if player := this->get(PlayerComponent); player != null {
+            holding = player.holding;
+        }
+
+        for obsticles {
+            // Don't check collision on the object that you are carrying or yourself because it probably won't make sense.
+            if it == this do continue;
+            if it.id == holding do continue;
+
+            if Rect.intersects(ent_rect, Entity.get_rect(it)) {
+                pos -= delta;
+                break;
+            }
+        }
+    }
+}
+
+
diff --git a/src/entity/components/player.onyx b/src/entity/components/player.onyx
new file mode 100644 (file)
index 0000000..ea08206
--- /dev/null
@@ -0,0 +1,76 @@
+
+use package core
+use package glfw3
+
+PlayerComponent :: struct {
+    use base: Component;
+
+    holding : Entity_ID;
+
+    update :: (player: ^PlayerComponent, use this: ^Entity, dt: f32) {
+        // Highlight the object that you are going to interact with
+
+        movement := this->get(MovementComponent);
+
+        // Try to interact with nearby objects
+        //
+        if is_key_just_up(movement.controls.interact) {
+            area    := Rect.{pos.x - size.x, pos.y - size.y, size.x * 2, size.y * 2};
+            objects := scene->query_by_component(area, InteractableComponent);
+            defer memory.free_slice(^objects);
+
+            for objects {
+                interact_comp := it->get(InteractableComponent);
+                interact_comp.interact(it, this);
+            }
+        }
+
+        //
+        // Try to pick up nearby objects
+        //
+        if is_key_just_up(movement.controls.pick_up) {
+            if player.holding != Entity_Nothing {
+                holding_object := scene->get(player.holding);
+                holding_object.flags |= .Carryable;
+                r := Entity.get_rect(holding_object);
+
+                d := Vector2.{(size.x + r.w) / 2 + 4, (size.y + r.h) / 2 + 4};
+                holding_object.pos = pos + facing_to_direction_vector(movement.facing) * d;
+                player.holding = Entity_Nothing;
+
+            } else {
+                area    := Rect.{pos.x - size.x, pos.y - size.y, size.x * 2, size.y * 2};
+                objects := scene->query_by_flags(area, .Carryable);
+                defer memory.free_slice(^objects);
+
+                // This should first sort by the distance to the object
+                while i := 0; i < objects.count {
+                    defer i += 1;
+                    if objects[i] == this do continue;
+
+                    target_object := objects[i];
+                    target_object.flags ^= .Carryable; // This only works because we assume that it is Carryable, otherwise this would make it carryable.
+                    player.holding = target_object.id;
+                    break;
+                }
+
+                // Should this fire an event on the target object?
+            }
+        }
+
+        //
+        // Adjust the position of the entity you are carrying
+        // to be above the players head.
+        //
+        if player.holding != Entity_Nothing {
+            holding_object := scene->get(player.holding);
+            r := Entity.get_rect(holding_object);
+            holding_object.pos = pos - .{0, (size.y + r.h) / 2};
+        }
+    }
+
+    render :: (use this: ^Entity) {
+        rect := Entity.get_rect(this);
+        immediate_image(^Player.assets.texture, rect.x, rect.y, rect.w, rect.h);
+    }
+}
index b9de56f0d31bf7a383bf87cee439448f7cefd2d6..bd276db27f35c22311fa3ba98828f46a339514cd 100644 (file)
@@ -56,7 +56,7 @@ editor_update :: (dt: f32) {
     if active_index < 0 do return;
     mouse_pos := mouse_get_position_vector() - scene_render_offset;
 
-    if is_button_just_down(GLFW_MOUSE_BUTTON_LEFT) && mouse_pos.x < ~~window_width - sidebar_width && mouse_pos.y > menubar_height {
+    if is_button_just_down(GLFW_MOUSE_BUTTON_LEFT) && mouse_pos.x < ~~window_width - sidebar_width {
         schematic := scene.schematics.entries[active_index].value;
         entity := schematic.create(^scene);
         entity.schematic = schematic.type;
@@ -70,7 +70,7 @@ editor_update :: (dt: f32) {
 #local handle_entity_selction_and_dragging :: (dt: f32) {
     mouse_pos := mouse_get_position_vector() - scene_render_offset;
 
-    if mouse_pos.x < ~~window_width - sidebar_width && mouse_pos.y > menubar_height {
+    if mouse_pos.x < ~~window_width - sidebar_width {
         if is_button_just_down(GLFW_MOUSE_BUTTON_LEFT) || is_button_just_down(GLFW_MOUSE_BUTTON_RIGHT) {
             if active_tab == .Edit do active_index = -1;
             selected_entity_id = Entity_Nothing;
diff --git a/src/entity/entities.onyx b/src/entity/entities.onyx
new file mode 100644 (file)
index 0000000..1af81b2
--- /dev/null
@@ -0,0 +1,102 @@
+
+use package core
+use package glfw3
+
+
+#local Wall :: struct {
+    render :: (use this: ^Entity) {
+        r := Entity.get_rect(this);
+        immediate_rectangle(r.x, r.y, r.w, r.h);
+    }
+
+    #struct_tag Entity_Schematic.{
+        (scene) => wall_create(scene, .{0,0}, .{0,0})
+    }
+}
+
+wall_create :: (scene: ^Entity_Manager, pos, size: Vector2) -> ^Entity {
+    this := scene->make();
+    this.pos = pos;
+    this.size = size;
+    this.flags |= .Solid;
+
+    scene->create_and_add(this, RenderComponent) {
+        comp.func = Wall.render;
+    }
+
+    return this;
+}
+
+#local Door :: struct {
+    create :: (scene) => door_create(scene, .Zero, .Zero);
+
+    render :: (use this: ^Entity) {
+        immediate_set_color(.{0.7, 0.7, 0.1});
+
+        r := Entity.get_rect(this);
+        immediate_rectangle(r.x, r.y, r.w, r.h);
+    }
+
+    get_rect :: (use this: ^Entity) => {
+        door := this->get(DoorComponent);
+        size_x := size.x * (1 - door.openness);
+        return Rect.{ pos.x - size_x / 2, pos.y - size.y / 2, size_x, size.y };
+    }
+
+    interact :: (use this: ^Entity, interactor: ^Entity) {
+        // Doors only open if interacted with by a player
+        if interactor->has(PlayerComponent) {
+            door := this->get(DoorComponent);
+            door->toggle_open();
+        }
+    }
+
+    #struct_tag Entity_Schematic.{create}
+}
+
+DoorComponent :: struct {
+    use base: Component;
+
+    max_openness    := 0.8f;
+    target_openness := 0.0f;
+    openness        := 0.0f;
+
+    update :: (use this: ^DoorComponent, door: ^Entity, dt: f32) {
+        if openness != target_openness {
+            move_towards(^openness, target_openness, dt * 2);
+        }
+    }
+
+    toggle_open :: (use this: ^DoorComponent) {
+        target_openness = max_openness - target_openness;
+    }
+}
+
+door_create :: (scene: ^Entity_Manager, pos, size: Vector2) -> ^Entity {
+    this := scene->make();
+    this.pos  = pos;
+    this.size = size;
+
+    this.flags |= .Interactable;
+    this.flags |= .Solid;
+
+    scene->create_and_add(this, DoorComponent)         {}
+    scene->create_and_add(this, RenderComponent)       { comp.func = Door.render; }
+    scene->create_and_add(this, SizeComponent)         { comp.func = Door.get_rect; }
+    scene->create_and_add(this, InteractableComponent) { comp.interact = Door.interact; }
+
+    return this;
+}
+
+
+
+@Relocate
+move_towards :: (v: ^$T, target: T, diff: T) {
+    if math.abs(target - *v) <= diff {
+        *v = target;
+        return;
+    }
+
+    if *v < target do *v += diff;
+    if *v > target do *v -= diff;
+}
index a96a1daa5ba95d56f5a675f68af7267eb2088792..12d3d085601d2dce5d94cded3cb2d83c2af9731a 100644 (file)
@@ -97,7 +97,7 @@ item_store_get_item :: (use this: ^Item_Store, id: str) -> ^Item {
         this.size = .{0, 0};
         this.flags |= .Carryable;
 
-        scene->create_and_add(this, RenderComponent) { comp.func = render; }
+        scene->create_and_add(this, RenderComponent) { comp.func = render; comp.layer = 10; }
         scene->create_and_add(this, ItemComponent)   {}
         return this;
     }
index bf4d5fcb8eae16e90a7e3a971bd3ef6261e011be..9919b21a999a35bba6891fe1f64722030d2ab7d7 100644 (file)
@@ -278,8 +278,19 @@ entity_manager_update :: (use this: ^Entity_Manager, dt: f32) {
 }
 
 entity_manager_draw :: (use this: ^Entity_Manager) {
-    // Entities should be sorted by z-order.
-    
+
+    //
+    // This is a rather expensive check.
+    // It could probably be done solely when entities are added/removed.
+    array.sort(entities, (e1, e2) => {
+        e1_comp := e1->get(RenderComponent);
+        e2_comp := e2->get(RenderComponent);
+
+        e1_layer := e1_comp.layer if e1_comp != null else 0;
+        e2_layer := e2_comp.layer if e2_comp != null else 0;
+
+        return e1_layer - e2_layer;
+    });
 
     for entities {
         render_comp := it->get(RenderComponent);
@@ -299,9 +310,13 @@ entity_manager_draw :: (use this: ^Entity_Manager) {
 
 entity_manager_get :: (use this: ^Entity_Manager, id: Entity_ID) => entity_map[id];
 
-entity_manager_delete :: (use this: ^Entity_Manager, ent: ^Entity) {
+entity_manager_delete :: (use this: ^Entity_Manager, ent: ^Entity, delete_from_array := true) {
     map.delete(^entity_map, ent.id);
-    array.remove(^entities, ent); // This preserves the order of the entities, but does that matter?
+
+    //
+    // Not deleting the entity from the array, because this messes with the
+    // order, and becaues of that, it breaks a for-loop.
+    if delete_from_array do array.remove(^entities, ent); // This preserves the order of the entities, but does that matter?
 
     // This assuems that components cannot and will not be shared between entities.
     for^ ent.components.entries {
diff --git a/src/entity/player.onyx b/src/entity/player.onyx
deleted file mode 100644 (file)
index fdb2185..0000000
+++ /dev/null
@@ -1,295 +0,0 @@
-
-use package core
-use package glfw3
-
-Player_Controls :: struct {
-    up       : i32;
-    down     : i32;
-    left     : i32;
-    right    : i32;
-    interact : i32;
-    pick_up  : i32;
-}
-
-player_1_controls :: Player_Controls.{
-    up       = GLFW_KEY_W,
-    down     = GLFW_KEY_S,
-    left     = GLFW_KEY_A,
-    right    = GLFW_KEY_D,
-    interact = GLFW_KEY_F,
-    pick_up  = GLFW_KEY_G,
-}
-
-player_2_controls :: Player_Controls.{
-    up       = GLFW_KEY_UP,
-    down     = GLFW_KEY_DOWN,
-    left     = GLFW_KEY_LEFT,
-    right    = GLFW_KEY_RIGHT,
-    interact = GLFW_KEY_COMMA,
-    pick_up  = GLFW_KEY_PERIOD,
-}
-
-Facing :: enum {
-    Up    :: 0x01;
-    Down  :: 0x02;
-    Left  :: 0x03;
-    Right :: 0x04;
-}
-
-facing_to_direction_vector :: macro (f: Facing) -> Vector2 {
-    switch f {
-        case .Up    do return .{0, -1};
-        case .Down  do return .{0,  1};
-        case .Left  do return .{-1, 0};
-        case .Right do return .{1,  0};
-    }
-}
-
-#local Player :: struct {
-    #struct_tag Entity_Schematic.{create}
-    create :: (scene: ^Entity_Manager) => player_create(scene, .{0,0});
-}
-
-player_create :: (scene: ^Entity_Manager, pos: Vector2, controls := player_1_controls) -> ^Entity {
-    this := scene->make();
-    this.pos = pos;
-    this.size = .{32, 32};
-    this.flags |= .Solid;
-
-    scene->create_and_add(this, MovementComponent) {
-        comp.controls = controls;
-    }
-
-    scene->create_and_add(this, PlayerComponent) {
-        comp.holding = Entity_Nothing;
-    }
-
-    scene->create_and_add(this, RenderComponent) {
-        comp.func = PlayerComponent.render;
-        comp.color = .{1,1,1};
-    }
-
-    return this;
-}
-
-MovementComponent :: struct { 
-    use component: Component;
-    controls : Player_Controls;
-    facing   := Facing.Up;
-
-    update :: (movement: ^MovementComponent, use this: ^Entity, dt: f32) {
-        speed :: 128.0f;
-
-        delta: Vector2;
-        if is_key_down(movement.controls.left)  { delta.x -= speed * dt; movement.facing = .Left;  }
-        if is_key_down(movement.controls.right) { delta.x += speed * dt; movement.facing = .Right; }
-        if is_key_down(movement.controls.up)    { delta.y -= speed * dt; movement.facing = .Up;    }
-        if is_key_down(movement.controls.down)  { delta.y += speed * dt; movement.facing = .Down;  }
-
-        dist := math.max(size.x, size.y) * 2;
-        walls := scene->query_by_flags(.{pos.x - dist, pos.y - dist, dist * 2, dist * 2}, .Solid);
-        defer memory.free_slice(^walls);
-
-        try_move(this, .{delta.x, 0}, walls);
-        try_move(this, .{0, delta.y}, walls);
-    }
-
-    try_move :: (use this: ^Entity, delta: Vector2, obsticles: [] ^Entity) {
-        pos += delta;
-        ent_rect := Entity.get_rect(this);
-
-        holding: Entity_ID;
-        if player := this->get(PlayerComponent); player != null {
-            holding = player.holding;
-        }
-
-        for obsticles {
-            // Don't check collision on the object that you are carrying or yourself because it probably won't make sense.
-            if it == this do continue;
-            if it.id == holding do continue;
-
-            if Rect.intersects(ent_rect, Entity.get_rect(it)) {
-                pos -= delta;
-                break;
-            }
-        }
-    }
-}
-
-PlayerComponent :: struct {
-    use base: Component;
-
-    holding  : Entity_ID;
-
-    update :: (player: ^PlayerComponent, use this: ^Entity, dt: f32) {
-        // Highlight the object that you are going to interact with
-
-        movement := this->get(MovementComponent);
-
-        //
-        // Try to interact with nearby objects
-        //
-        if is_key_just_up(movement.controls.interact) {
-            area    := Rect.{pos.x - size.x, pos.y - size.y, size.x * 2, size.y * 2};
-            objects := scene->query_by_component(area, InteractableComponent);
-            defer memory.free_slice(^objects);
-
-            for objects {
-                interact_comp := it->get(InteractableComponent);
-                interact_comp.interact(it, this);
-            }
-        }
-
-        //
-        // Try to pick up nearby objects
-        //
-        if is_key_just_up(movement.controls.pick_up) {
-            if player.holding != Entity_Nothing {
-                holding_object := scene->get(player.holding);
-                holding_object.flags |= .Carryable;
-                r := Entity.get_rect(holding_object);
-
-                d := Vector2.{(size.x + r.w) / 2 + 4, (size.y + r.h) / 2 + 4};
-                holding_object.pos = pos + facing_to_direction_vector(movement.facing) * d;
-                player.holding = Entity_Nothing;
-
-            } else {
-                area    := Rect.{pos.x - size.x, pos.y - size.y, size.x * 2, size.y * 2};
-                objects := scene->query_by_flags(area, .Carryable);
-                defer memory.free_slice(^objects);
-
-                // This should first sort by the distance to the object
-                while i := 0; i < objects.count {
-                    defer i += 1;
-                    if objects[i] == this do continue;
-
-                    target_object := objects[i];
-                    target_object.flags ^= .Carryable; // This only works because we assume that it is Carryable, otherwise this would make it carryable.
-                    player.holding = target_object.id;
-                    break;
-                }
-
-                // Should this fire an event on the target object?
-            }
-        }
-
-        //
-        // Adjust the position of the entity you are carrying
-        // to be above the players head.
-        //
-        if player.holding != Entity_Nothing {
-            holding_object := scene->get(player.holding);
-            r := Entity.get_rect(holding_object);
-            holding_object.pos = pos - .{0, (size.y + r.h) / 2};
-        }
-    }
-
-    render :: (use this: ^Entity) {
-        rect := Entity.get_rect(this);
-        immediate_image(^player_assets.texture, rect.x, rect.y, rect.w, rect.h);
-    }
-}
-
-#local Wall :: struct {
-    render :: (use this: ^Entity) {
-        r := Entity.get_rect(this);
-        immediate_rectangle(r.x, r.y, r.w, r.h);
-    }
-
-    #struct_tag Entity_Schematic.{
-        (scene) => wall_create(scene, .{0,0}, .{0,0})
-    }
-}
-
-wall_create :: (scene: ^Entity_Manager, pos, size: Vector2) -> ^Entity {
-    this := scene->make();
-    this.pos = pos;
-    this.size = size;
-    this.flags |= .Solid;
-
-    scene->create_and_add(this, RenderComponent) {
-        comp.func = Wall.render;
-    }
-
-    return this;
-}
-
-player_assets: struct {
-    #tag "assets/images/player.png"
-    #tag Texture_Wrap.Clamp
-    texture: Texture;
-}
-
-#local Door :: struct {
-    create :: (scene) => door_create(scene, .Zero, .Zero);
-
-    render :: (use this: ^Entity) {
-        immediate_set_color(.{0.7, 0.7, 0.1});
-
-        r := Entity.get_rect(this);
-        immediate_rectangle(r.x, r.y, r.w, r.h);
-    }
-
-    get_rect :: (use this: ^Entity) => {
-        door := this->get(DoorComponent);
-        size_x := size.x * (1 - door.openness);
-        return Rect.{ pos.x - size_x / 2, pos.y - size.y / 2, size_x, size.y };
-    }
-
-    interact :: (use this: ^Entity, interactor: ^Entity) {
-        // Doors only open if interacted with by a player
-        if interactor->has(PlayerComponent) {
-            door := this->get(DoorComponent);
-            door->toggle_open();
-        }
-    }
-
-    #struct_tag Entity_Schematic.{create}
-}
-
-DoorComponent :: struct {
-    use base: Component;
-
-    max_openness    := 0.8f;
-    target_openness := 0.0f;
-    openness        := 0.0f;
-
-    update :: (use this: ^DoorComponent, door: ^Entity, dt: f32) {
-        if openness != target_openness {
-            move_towards(^openness, target_openness, dt * 2);
-        }
-    }
-
-    toggle_open :: (use this: ^DoorComponent) {
-        target_openness = max_openness - target_openness;
-    }
-}
-
-door_create :: (scene: ^Entity_Manager, pos, size: Vector2) -> ^Entity {
-    this := scene->make();
-    this.pos  = pos;
-    this.size = size;
-
-    this.flags |= .Interactable;
-    this.flags |= .Solid;
-
-    scene->create_and_add(this, DoorComponent)         {}
-    scene->create_and_add(this, RenderComponent)       { comp.func = Door.render; }
-    scene->create_and_add(this, SizeComponent)         { comp.func = Door.get_rect; }
-    scene->create_and_add(this, InteractableComponent) { comp.interact = Door.interact; }
-
-    return this;
-}
-
-
-
-@Relocate
-move_towards :: (v: ^$T, target: T, diff: T) {
-    if math.abs(target - *v) <= diff {
-        *v = target;
-        return;
-    }
-
-    if *v < target do *v += diff;
-    if *v > target do *v -= diff;
-}
diff --git a/src/entity/schematics/player.onyx b/src/entity/schematics/player.onyx
new file mode 100644 (file)
index 0000000..40490f2
--- /dev/null
@@ -0,0 +1,67 @@
+
+use package core
+use package glfw3
+
+Player_Controls :: struct {
+    up       : i32;
+    down     : i32;
+    left     : i32;
+    right    : i32;
+    interact : i32;
+    pick_up  : i32;
+}
+
+player_1_controls :: Player_Controls.{
+    up       = GLFW_KEY_W,
+    down     = GLFW_KEY_S,
+    left     = GLFW_KEY_A,
+    right    = GLFW_KEY_D,
+    interact = GLFW_KEY_F,
+    pick_up  = GLFW_KEY_G,
+}
+
+player_2_controls :: Player_Controls.{
+    up       = GLFW_KEY_UP,
+    down     = GLFW_KEY_DOWN,
+    left     = GLFW_KEY_LEFT,
+    right    = GLFW_KEY_RIGHT,
+    interact = GLFW_KEY_COMMA,
+    pick_up  = GLFW_KEY_PERIOD,
+}
+
+
+Player :: struct {
+    #struct_tag Entity_Schematic.{
+        (scene: ^Entity_Manager) => Player.create(scene, .{0,0})
+    }
+
+    create :: (scene: ^Entity_Manager, pos: Vector2, controls := player_1_controls) -> ^Entity {
+        this := scene->make();
+        this.pos = pos;
+        this.size = .{32, 32};
+        this.flags |= .Solid;
+
+        scene->create_and_add(this, MovementComponent) {
+            comp.controls = controls;
+        }
+
+        scene->create_and_add(this, PlayerComponent) {
+            comp.holding = Entity_Nothing;
+        }
+
+        scene->create_and_add(this, RenderComponent) {
+            comp.func = PlayerComponent.render;
+            comp.color = .{1,1,1};
+        }
+
+        return this;
+    }
+
+    #persist assets: struct {
+        #tag "assets/images/player.png"
+        #tag Texture_Wrap.Clamp
+        texture: Texture;
+    }
+}
+
+
index e8daed4a7945f67b70ad2f57df1b9d0d192fba17..77be0bb58c0680d145b0b1d04043c51628b49f66 100644 (file)
@@ -92,9 +92,9 @@ entity_manager_load_from_file :: (use this: ^Entity_Manager, filename: str) {
     defer os.close(^input_file);
     reader := io.reader_make(^input_file);
 
-    for entities do this->delete(it);
-    map.clear(^entity_map);
+    for entities do this->delete(it, false);
     array.clear(^entities);
+    map.clear(^entity_map);
     next_entity_id = 0;
 
     use type_info;
index 5f551497947c9b3f035658eb55a82f5ca800fe53..db904b4c91ea051162763ae04ea5bfde3c7855fe 100644 (file)
@@ -18,7 +18,7 @@ game_init :: () {
 
     // This process of queueing the asset bucket should
     // be made automatic somehow...
-    queue_assets(^player_assets);
+    queue_assets(^Player.assets);
 
     load_assets();