}
}
-player_create :: (scene: ^Entity_Manager, pos := Vector2.{400, 200}, controls := player_1_controls) -> ^Entity {
+#local Player :: struct [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};
controls : Player_Controls;
facing := Facing.Up;
- create :: (scene: ^Entity_Manager, pos := Vector2.{400, 200}, controls := player_1_controls) -> ^Entity {
- this := scene->make();
- this.pos = pos;
- this.size = .{32, 32};
- this.flags |= .Solid;
-
- player_comp := scene->create_component(PlayerComponent);
- player_comp.holding = Entity_Nothing;
- player_comp.controls = controls;
- player_comp.color = .{1,1,1};
- this->add(player_comp);
-
- update_comp := scene->create_component(UpdateComponent);
- update_comp.func = update;
- this->add(update_comp);
-
- render_comp := scene->create_component(RenderComponent);
- render_comp.func = render;
- this->add(render_comp);
-
- return this;
- }
-
update :: (use this: ^Entity, dt: f32) {
speed :: 128.0f;
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;
- }
+ // Highlight the object that you are going to interact with
- 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;
+ //
+ // Try to interact with nearby objects
+ //
+ if is_key_just_up(player.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);
- if Rect.intersects(ent_rect, Entity.get_rect(it)) {
- pos -= delta;
- break;
+ for objects {
+ interact_comp := it->get(InteractableComponent);
+ interact_comp.interact(it, this);
}
}
- }
-
- render :: (use this: ^Entity) {
- player := this->get(PlayerComponent);
- immediate_set_color(player.color);
-
- rect := Entity.get_rect(this);
- immediate_image(^player_assets.texture, rect.x, rect.y, rect.w, rect.h);
- }
-}
-
-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_draw;
- }
-
- return this;
-}
-
-wall_draw :: (use this: ^Entity) {
- immediate_set_color(.{1,1,1});
-
- r := Entity.get_rect(this);
- immediate_rectangle(r.x, r.y, r.w, r.h);
-}
-
-/*
- get_rect :: Entity.get_rect
-
- update :: (use this: ^Player, dt: f32) {
- speed :: 128.0f;
-
- delta: Vector2;
- if is_key_down(controls.left) { delta.x -= speed * dt; facing = .Left; }
- if is_key_down(controls.right) { delta.x += speed * dt; facing = .Right; }
- if is_key_down(controls.up) { delta.y -= speed * dt; facing = .Up; }
- if is_key_down(controls.down) { delta.y += speed * dt; 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);
-
- // Highlight the object that you are going to interact with
//
// Try to pick up nearby objects
//
- if is_key_just_up(controls.pick_up) {
- if holding != Entity_Nothing {
- holding_object := scene->get(holding);
+ if is_key_just_up(player.controls.pick_up) {
+ if player.holding != Entity_Nothing {
+ holding_object := scene->get(player.holding);
holding_object.flags |= .Carryable;
- /* :ENT_INFO
- obj_get_rect := ENT_INFO(holding_object).get_rect;
- if obj_get_rect != null_proc {
- r := get_rect(holding_object);
+ 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(facing) * d;
- }
- */
- holding = Entity_Nothing;
+ d := Vector2.{(size.x + r.w) / 2 + 4, (size.y + r.h) / 2 + 4};
+ holding_object.pos = pos + facing_to_direction_vector(player.facing) * d;
+ player.holding = Entity_Nothing;
} else {
area := Rect.{pos.x - size.x, pos.y - size.y, size.x * 2, size.y * 2};
target_object := objects[i];
target_object.flags ^= .Carryable; // This only works because we assume that it is Carryable, otherwise this would make it carryable.
- this.holding = target_object.id;
+ player.holding = target_object.id;
break;
}
}
}
- //
- // Try to interact with nearby objects
- //
- if is_key_just_up(controls.interact) {
- area := Rect.{pos.x - size.x, pos.y - size.y, size.x * 2, size.y * 2};
- objects := scene->query_by_flags(area, .Interactable);
- defer memory.free_slice(^objects);
-
- for objects {
- /* :ENT_INFO
- if interact := ENT_INFO(it).interact; interact != null_proc {
- interact(it, this);
- }
- */
- }
- }
-
//
// Adjust the position of the entity you are carrying
// to be above the players head.
//
- if holding != Entity_Nothing {
- holding_object := scene->get(holding);
- /* :ENT_INFO
- obj_get_rect := ENT_INFO(holding_object).get_rect;
- if obj_get_rect != null_proc {
- r := obj_get_rect(holding_object);
- holding_object.pos = pos - .{0, (size.y + r.h) / 2};
- }
- */
+ 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};
}
}
- // This should be made generic and work for all kinds of entities
- try_move :: (use this: ^Player, delta: Vector2, obsticles: [] ^Entity) {
+ try_move :: (use this: ^Entity, delta: Vector2, obsticles: [] ^Entity) {
pos += delta;
- ent_rect := get_rect(this);
+ 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 == this.holding do continue;
+ if it.id == holding do continue;
- /* :ENT_INFO
- vtable := ENT_INFO(it);
- if Rect.intersects(ent_rect, vtable.get_rect(it)) {
+ if Rect.intersects(ent_rect, Entity.get_rect(it)) {
pos -= delta;
break;
}
- */
}
}
+ render :: (use this: ^Entity) {
+ player := this->get(PlayerComponent);
+ immediate_set_color(player.color);
+
+ rect := Entity.get_rect(this);
+ immediate_image(^player_assets.texture, rect.x, rect.y, rect.w, rect.h);
+ }
+}
+
+#local Wall :: struct [Entity_Schematic.{create}] {
+ create :: (scene) => wall_create(scene, .{0,0}, .{0,0});
+
+ draw :: (use this: ^Entity) {
+ immediate_set_color(.{1,1,1});
+
+ r := Entity.get_rect(this);
+ immediate_rectangle(r.x, r.y, r.w, r.h);
+ }
+}
+
+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.draw;
+ }
+
+ return this;
}
-*/
player_assets: struct {
["assets/images/player.png"] texture: Texture;
}
-Door :: struct {
- use entity: Entity;
-
- [Entity_Store.Skip] openness := 0.0f;
- target_openness := 0.0f;
+#local Door :: struct [Entity_Schematic.{create}] {
+ create :: (scene) => door_create(scene, .{0, 0}, .{0, 0});
- init_data :: struct {
- pos := Vector2.{0, 0};
- size := Vector2.{10, 10};
+ update :: (use this: ^Entity, dt: f32) {
+ door := this->get(DoorComponent);
+ if door.openness != door.target_openness {
+ move_towards(^door.openness, door.target_openness, dt * 2);
+ }
}
- init :: (use this: ^Door, data: init_data) {
- this.pos = data.pos;
- this.size = data.size;
+ render :: (use this: ^Entity) {
+ immediate_set_color(.{0.7, 0.7, 0.1});
- this.flags |= .Interactable;
- this.flags |= .Solid;
+ r := Entity.get_rect(this);
+ immediate_rectangle(r.x, r.y, r.w, r.h);
}
- get_rect :: (use this: ^Door) => {
- size_x := size.x * (1 - openness);
+ 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 };
}
- update :: (use this: ^Door, dt: f32) {
- if openness != target_openness {
- move_towards(^openness, target_openness, dt * 2);
+ 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();
}
}
+}
- interact :: (use this: ^Door, interactor: ^Entity) {
- // Doors only open if interacted with by a player
- //if_entity_is(interactor, Player) {
- target_openness = 0.8f - target_openness;
- //}
- }
+DoorComponent :: struct {
+ use base: Component;
- draw :: (use this: ^Door) {
- immediate_set_color(.{0.7, 0.7, 0.1});
+ target_openness := 0.0f;
+ openness := 0.0f;
- r := this->get_rect();
- immediate_rectangle(r.x, r.y, r.w, r.h);
+ toggle_open :: (use this: ^DoorComponent) {
+ target_openness = 0.8f - 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, UpdateComponent) { comp.func = Door.update; }
+ 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;
+}