Input and Update with sum type
This commit is contained in:
parent
6d9dbfc5f8
commit
1ec3c577fe
250
game.odin
250
game.odin
@ -9,8 +9,11 @@ Rect :: rl.Rectangle
|
||||
|
||||
SCREEN_WIDTH : i32 = 1000
|
||||
SCREEN_HEIGHT : i32 = 800
|
||||
BW := f32(SCREEN_WIDTH)
|
||||
BH := f32(SCREEN_HEIGHT)
|
||||
|
||||
SCALE: f32 = 0.5
|
||||
|
||||
SCALE: f32 = 0.37
|
||||
SHIP_W: f32 = 70 * SCALE
|
||||
SHIP_H: f32 = 100 * SCALE
|
||||
|
||||
@ -31,21 +34,42 @@ Asteroid :: struct {
|
||||
rot: f32,
|
||||
}
|
||||
|
||||
GameState :: struct {
|
||||
dt: f32,
|
||||
ship_pos: Vec2,
|
||||
ship_angle: f32,
|
||||
ship_vel: Vec2,
|
||||
bullets: [dynamic]Bullet,
|
||||
asteroids: [dynamic]Asteroid,
|
||||
Player :: struct {
|
||||
pos: Vec2,
|
||||
points: [4]Vec2,
|
||||
angle: f32,
|
||||
vel: Vec2
|
||||
}
|
||||
|
||||
get_ship_shape :: proc(s : GameState) -> (Vec2, Vec2, Vec2, Vec2) {
|
||||
v1 := rl.Vector2Rotate({ SHIP_H*0.5, 0}, s.ship_angle) + s.ship_pos
|
||||
v2 := rl.Vector2Rotate({-SHIP_H*0.5, -SHIP_W*0.5}, s.ship_angle) + s.ship_pos
|
||||
v3 := rl.Vector2Rotate({-SHIP_H*0.5*0.5, 0}, s.ship_angle) + s.ship_pos
|
||||
v4 := rl.Vector2Rotate({-SHIP_H*0.5, SHIP_W*0.5}, s.ship_angle) + s.ship_pos
|
||||
return v1, v2, v3, v4
|
||||
PlayerSpinningPart :: struct {
|
||||
points: [2]Vec2,
|
||||
rotation_speed: f32,
|
||||
vel: Vec2,
|
||||
}
|
||||
|
||||
Death :: struct {
|
||||
flying_parts: [4]PlayerSpinningPart
|
||||
}
|
||||
|
||||
PlayerState :: union #no_nil {
|
||||
Player,
|
||||
Death,
|
||||
}
|
||||
|
||||
GameState :: struct {
|
||||
dt: f32,
|
||||
player_state: PlayerState,
|
||||
bullets: [dynamic]Bullet,
|
||||
asteroids: [dynamic]Asteroid,
|
||||
bullet_pop_idxs: [dynamic]int,
|
||||
asteroid_pop_idxs: [dynamic]int,
|
||||
}
|
||||
|
||||
update_ship_shape :: proc(p : ^Player) {
|
||||
p.points[0] = rl.Vector2Rotate({ SHIP_H*0.5, 0}, p.angle) + p.pos
|
||||
p.points[1] = rl.Vector2Rotate({-SHIP_H*0.5, -SHIP_W*0.5}, p.angle) + p.pos
|
||||
p.points[2] = rl.Vector2Rotate({-SHIP_H*0.5*0.5, 0}, p.angle) + p.pos
|
||||
p.points[3] = rl.Vector2Rotate({-SHIP_H*0.5, SHIP_W*0.5}, p.angle) + p.pos
|
||||
}
|
||||
|
||||
swap_n_pop :: proc(bullets: ^[dynamic]$T, idx: int) {
|
||||
@ -58,25 +82,127 @@ swap_n_pop :: proc(bullets: ^[dynamic]$T, idx: int) {
|
||||
}
|
||||
}
|
||||
|
||||
player_input :: proc(s: ^GameState) {
|
||||
switch &player in s.player_state {
|
||||
case Player:
|
||||
if rl.IsKeyDown(.D) {
|
||||
player.angle += ANGULAR_SPEED * s.dt
|
||||
}
|
||||
if rl.IsKeyDown(.A) {
|
||||
player.angle -= ANGULAR_SPEED * s.dt
|
||||
}
|
||||
if rl.IsKeyDown(.W) {
|
||||
player.vel.x += math.cos(player.angle) * THRUST_SPEED * s.dt
|
||||
player.vel.y += math.sin(player.angle) * THRUST_SPEED * s.dt
|
||||
}
|
||||
if rl.IsKeyPressed(.SPACE) {
|
||||
b_vel := Vec2{ math.cos(player.angle) , math.sin(player.angle) } * BULLET_SPEED
|
||||
append(&s.bullets, Bullet{player.points[0], b_vel})
|
||||
}
|
||||
case Death:
|
||||
if rl.IsKeyDown(.ENTER) {
|
||||
// restart game
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update :: proc(s: ^GameState) {
|
||||
switch &player in s.player_state {
|
||||
case Player:
|
||||
update_ship_shape(&player)
|
||||
player.pos += player.vel * (5000 * s.dt)
|
||||
ship_collision := false
|
||||
for i := 0; i < len(s.asteroids); i += 1 {
|
||||
s.asteroids[i].rect.x += s.asteroids[i].vel.x
|
||||
s.asteroids[i].rect.y += s.asteroids[i].vel.y
|
||||
for j := 0; j < len(player.points); j += 1 {
|
||||
if rl.CheckCollisionPointRec(player.points[j], s.asteroids[i].rect) {
|
||||
ship_collision = true
|
||||
}
|
||||
}
|
||||
}
|
||||
for i := 0; i < len(s.bullets); i += 1 {
|
||||
if ( s.bullets[i].pos.x < 0 || s.bullets[i].pos.x > BW
|
||||
|| s.bullets[i].pos.y < 0 || s.bullets[i].pos.y > BH) {
|
||||
append(&s.bullet_pop_idxs, i)
|
||||
}
|
||||
s.bullets[i].pos += s.bullets[i].vel
|
||||
for j := 0; j < len(s.asteroids); j += 1 {
|
||||
if rl.CheckCollisionCircleRec(s.bullets[i].pos, BULLET_RADIUS, s.asteroids[j].rect) {
|
||||
append(&s.bullet_pop_idxs, i)
|
||||
append(&s.asteroid_pop_idxs, j)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bpi_len := len(s.bullet_pop_idxs)
|
||||
for i := 0; i < bpi_len; i += 1 {
|
||||
swap_n_pop(&s.bullets, s.bullet_pop_idxs[i])
|
||||
}
|
||||
if bpi_len > 0 {
|
||||
clear(&s.bullet_pop_idxs)
|
||||
}
|
||||
api_len := len(s.asteroid_pop_idxs)
|
||||
for i := 0; i < api_len; i += 1 {
|
||||
swap_n_pop(&s.asteroids, s.asteroid_pop_idxs[i])
|
||||
}
|
||||
if bpi_len > 0 {
|
||||
clear(&s.asteroid_pop_idxs)
|
||||
}
|
||||
|
||||
if ship_collision {
|
||||
// Randomize everything
|
||||
s.player_state = Death {
|
||||
|
||||
}
|
||||
} else {
|
||||
if player.pos.x + SHIP_W < 0 { player.pos.x = BW + SHIP_W}
|
||||
if player.pos.x - SHIP_W > BW { player.pos.x = -SHIP_W}
|
||||
if player.pos.y + SHIP_H < 0 { player.pos.y = BH + SHIP_H}
|
||||
if player.pos.y - SHIP_H > BH { player.pos.y = -SHIP_H}
|
||||
}
|
||||
|
||||
case Death:
|
||||
}
|
||||
}
|
||||
|
||||
draw2d :: proc(s: ^GameState) {
|
||||
switch &player in s.player_state {
|
||||
case Player:
|
||||
// Draw ship
|
||||
rl.DrawLineEx(player.points[0], player.points[1], 1, rl.WHITE)
|
||||
rl.DrawLineEx(player.points[1], player.points[2], 1, rl.WHITE)
|
||||
rl.DrawLineEx(player.points[2], player.points[3], 1, rl.WHITE)
|
||||
rl.DrawLineEx(player.points[3], player.points[0], 1, rl.WHITE)
|
||||
case Death:
|
||||
}
|
||||
for i := 0; i < len(s.asteroids); i += 1 {
|
||||
rl.DrawRectangleLinesEx(s.asteroids[i].rect, 1, rl.WHITE)
|
||||
}
|
||||
|
||||
for i := 0; i < len(s.bullets); i += 1 {
|
||||
rl.DrawCircleLinesV(s.bullets[i].pos, BULLET_RADIUS, rl.WHITE)
|
||||
}
|
||||
}
|
||||
|
||||
main :: proc() {
|
||||
rl.SetTraceLogLevel(.ERROR)
|
||||
rl.InitWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Asteroids")
|
||||
|
||||
start_pos := Vec2{BW / 2 - SHIP_W / 2, BH / 2 - SHIP_H / 2}
|
||||
s := GameState{
|
||||
rl.GetFrameTime(),
|
||||
{0,0},
|
||||
-math.PI / 2,
|
||||
{0,0},
|
||||
Player {
|
||||
start_pos,
|
||||
[4]Vec2{{0,0},{0,0},{0,0},{0,0}},
|
||||
-math.PI / 2,
|
||||
{0,0}
|
||||
},
|
||||
make([dynamic]Bullet, 0, 64),
|
||||
make([dynamic]Asteroid, 0, 64),
|
||||
make([dynamic]int, 0, 64),
|
||||
make([dynamic]int, 0, 64),
|
||||
}
|
||||
s.ship_pos = {600, 350}
|
||||
|
||||
bw := f32(SCREEN_WIDTH)
|
||||
bh := f32(SCREEN_HEIGHT)
|
||||
|
||||
bullet_pop_idxs := make([dynamic]int, 0, 64)
|
||||
asteroid_pop_idxs := make([dynamic]int, 0, 64)
|
||||
|
||||
get_rand_angle :: proc(min: i32, max: i32) -> f32 {
|
||||
return f32(rl.GetRandomValue(min, max)) * rl.DEG2RAD
|
||||
@ -84,7 +210,7 @@ main :: proc() {
|
||||
|
||||
for i := 0; i < 5; i += 1 {
|
||||
rand_angle := get_rand_angle(-50, 50)
|
||||
rand_pos := Vec2{ f32(rl.GetRandomValue(0, i32(bw))), -50 }
|
||||
rand_pos := Vec2{ f32(rl.GetRandomValue(0, i32(BW))), -50 }
|
||||
rand_size := f32(rl.GetRandomValue(25, 60))
|
||||
rand_vy := f32(rl.GetRandomValue(1, 2)) * 0.5
|
||||
asteroid := Asteroid {
|
||||
@ -98,82 +224,14 @@ main :: proc() {
|
||||
for !rl.WindowShouldClose() {
|
||||
s.dt = rl.GetFrameTime()
|
||||
|
||||
v1, v2, v3, v4 := get_ship_shape(s)
|
||||
player_input(&s)
|
||||
|
||||
if rl.IsKeyDown(.D) {
|
||||
s.ship_angle += ANGULAR_SPEED * s.dt
|
||||
}
|
||||
if rl.IsKeyDown(.A) {
|
||||
s.ship_angle -= ANGULAR_SPEED * s.dt
|
||||
}
|
||||
if rl.IsKeyDown(.W) {
|
||||
s.ship_vel.x += math.cos(s.ship_angle) * THRUST_SPEED * s.dt
|
||||
s.ship_vel.y += math.sin(s.ship_angle) * THRUST_SPEED * s.dt
|
||||
}
|
||||
if rl.IsKeyPressed(.SPACE) {
|
||||
b_vel := Vec2{ math.cos(s.ship_angle) , math.sin(s.ship_angle) } * BULLET_SPEED
|
||||
append(&s.bullets, Bullet{v1,b_vel})
|
||||
}
|
||||
|
||||
s.ship_pos += s.ship_vel * (5000 * s.dt)
|
||||
|
||||
for i := 0; i < len(s.asteroids); i += 1 {
|
||||
s.asteroids[i].rect.x += s.asteroids[i].vel.x
|
||||
s.asteroids[i].rect.y += s.asteroids[i].vel.y
|
||||
}
|
||||
|
||||
for i := 0; i < len(s.bullets); i += 1 {
|
||||
if ( s.bullets[i].pos.x < 0 || s.bullets[i].pos.x > bw
|
||||
|| s.bullets[i].pos.y < 0 || s.bullets[i].pos.y > bh) {
|
||||
append(&bullet_pop_idxs, i)
|
||||
}
|
||||
s.bullets[i].pos += s.bullets[i].vel
|
||||
for j := 0; j < len(s.asteroids); j += 1 {
|
||||
if rl.CheckCollisionCircleRec(s.bullets[i].pos, BULLET_RADIUS, s.asteroids[j].rect) {
|
||||
fmt.println(s.bullets[i], s.asteroids[j])
|
||||
append(&bullet_pop_idxs, i)
|
||||
append(&asteroid_pop_idxs, j)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bpi_len := len(bullet_pop_idxs)
|
||||
for i := 0; i < bpi_len; i += 1 {
|
||||
swap_n_pop(&s.bullets, bullet_pop_idxs[i])
|
||||
}
|
||||
if bpi_len > 0 {
|
||||
clear(&bullet_pop_idxs)
|
||||
}
|
||||
api_len := len(asteroid_pop_idxs)
|
||||
for i := 0; i < api_len; i += 1 {
|
||||
swap_n_pop(&s.asteroids, asteroid_pop_idxs[i])
|
||||
}
|
||||
if bpi_len > 0 {
|
||||
clear(&asteroid_pop_idxs)
|
||||
}
|
||||
|
||||
|
||||
if s.ship_pos.x + SHIP_W < 0 { s.ship_pos.x = bw + SHIP_W}
|
||||
if s.ship_pos.x - SHIP_W > bw { s.ship_pos.x = -SHIP_W}
|
||||
if s.ship_pos.y + SHIP_H < 0 { s.ship_pos.y = bh + SHIP_H}
|
||||
if s.ship_pos.y - SHIP_H > bh { s.ship_pos.y = -SHIP_H}
|
||||
update(&s)
|
||||
|
||||
rl.BeginDrawing()
|
||||
rl.ClearBackground(rl.BLACK)
|
||||
|
||||
// Draw ship
|
||||
rl.DrawLineEx(v1, v2, 1, rl.WHITE)
|
||||
rl.DrawLineEx(v2, v3, 1, rl.WHITE)
|
||||
rl.DrawLineEx(v3, v4, 1, rl.WHITE)
|
||||
rl.DrawLineEx(v4, v1, 1, rl.WHITE)
|
||||
|
||||
for i := 0; i < len(s.asteroids); i += 1 {
|
||||
rl.DrawRectangleLinesEx(s.asteroids[i].rect, 1, rl.WHITE)
|
||||
}
|
||||
|
||||
for i := 0; i < len(s.bullets); i += 1 {
|
||||
rl.DrawCircleLinesV(s.bullets[i].pos, BULLET_RADIUS, rl.WHITE)
|
||||
}
|
||||
draw2d(&s)
|
||||
|
||||
rl.EndDrawing()
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user