diff --git a/src/entity.odin b/src/entity.odin new file mode 100644 index 0000000..f5f9eb2 --- /dev/null +++ b/src/entity.odin @@ -0,0 +1,36 @@ +package game + +import rl "vendor:raylib" + +// ------------------------------------------------------------------------------ +// Generic base structure shared by all world objects. +// Fields are populated selectively based on entity type. +// ------------------------------------------------------------------------------ + +Entity_Type :: enum { + Player, + Enemy, + Ball, +} + +Shape_Type :: enum { + Rectangle, + Circle, +} + +Entity :: struct { + type: Entity_Type, + active: bool, + pos: rl.Vector2, + shape: Shape_Type, + // width / height or diameter / diameter + size: rl.Vector2, + // Fixed input speed (paddles) + speed: f32, + // 2D momentum & direction (ball / physics) + vel: rl.Vector2, +} + +// ------------------------------------------------------------------------------ +// TODO: Entity Dispatchers +// ------------------------------------------------------------------------------ diff --git a/src/entity_ball.odin b/src/entity_ball.odin new file mode 100644 index 0000000..7188da2 --- /dev/null +++ b/src/entity_ball.odin @@ -0,0 +1,33 @@ +package game + +import rl "vendor:raylib" + +init_ball :: proc() -> Entity { + ball_radius: f32 = 25 + + return Entity{ + type = .Ball, + active = true, + pos = rl.Vector2{(VIEWPORT_WIDTH / 2), (VIEWPORT_HEIGHT / 2) - (ball_radius / 2)}, + vel = rl.Vector2{400,0}, + shape = .Circle, + size = rl.Vector2{15, 15} + } +} + +update_ball :: proc(ball: ^Entity, field_bounds: rl.Rectangle, dt: f32) { + ball.pos += ball.vel * dt + + if ball.pos.x >= (field_bounds.x + field_bounds.width) - ball.size.x { + ball.vel.x = -ball.vel.x + } + + if ball.pos.x <= field_bounds.x + ball.size.x { + ball.vel.x = -ball.vel.x + } + +} + +render_ball :: proc(ball: Entity, field_bounds: rl.Rectangle) { + rl.DrawCircleV(ball.pos, ball.size.x, rl.MAROON) +} diff --git a/src/entity_enemy.odin b/src/entity_enemy.odin new file mode 100644 index 0000000..9738809 --- /dev/null +++ b/src/entity_enemy.odin @@ -0,0 +1,18 @@ +package game + +import rl "vendor:raylib" + +init_enemy :: proc() -> Entity { + return Entity{ + type = .Enemy, + active = true, + pos = rl.Vector2{0,0}, + speed = 800, + shape = .Rectangle, + size = rl.Vector2{30, 150} + } +} + +render_enemy :: proc(enemy: Entity, field_bounds: rl.Rectangle) { + rl.DrawRectangleV(enemy.pos, enemy.size, rl.BLACK) +} diff --git a/src/entity_player.odin b/src/entity_player.odin new file mode 100644 index 0000000..3a3117e --- /dev/null +++ b/src/entity_player.odin @@ -0,0 +1,32 @@ +package game + +import "core:math" +import rl "vendor:raylib" + +init_player :: proc() -> Entity { + return Entity{ + type = .Player, + active = true, + pos = rl.Vector2{0,0}, + speed = 800, + shape = .Rectangle, + size = rl.Vector2{30, 150} + } +} + + +update_player :: proc(player: ^Entity, input: Input_Event, bounds: rl.Rectangle, dt: f32,) { + // move direction is captured and calculated + normalized from input manager + // Apply Movement (Frame-rate independent) + player.pos.y += input.move_dir.y * player.speed * dt + + // 3. Clamp Position within Field Bounds + min_y := bounds.y + 3 // Padding offset inside border + max_y := bounds.y + bounds.height - player.size.y - 3 + + player.pos.y = math.clamp(player.pos.y, min_y, max_y) +} + +render_player :: proc(player: Entity, field_bounds: rl.Rectangle) { + rl.DrawRectangleV(player.pos, player.size, rl.BLACK) +} \ No newline at end of file