145 lines
3.5 KiB
Odin
145 lines
3.5 KiB
Odin
|
package main
|
||
|
|
||
|
import rl "vendor:raylib"
|
||
|
import "vendor:raylib/rlgl"
|
||
|
import "core:fmt"
|
||
|
import "core:math"
|
||
|
import "core:math/ease"
|
||
|
import "core:math/rand"
|
||
|
import "core:strings"
|
||
|
import "core:strconv"
|
||
|
|
||
|
// Virtual game field dimensions
|
||
|
GameField := vec2{400, 200}
|
||
|
|
||
|
Game :: struct {
|
||
|
using state: GameState,
|
||
|
health: u8,
|
||
|
player: Player,
|
||
|
camera: rl.Camera3D,
|
||
|
camera_offset: vec3,
|
||
|
score: u32,
|
||
|
background: rl.Texture,
|
||
|
plane: rl.Model,
|
||
|
bullets: [dynamic]Bullet,
|
||
|
snake_max_health: int,
|
||
|
snake_health: int
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
game_init :: proc(prev: ^GameState = nil) -> ^GameState {
|
||
|
state := new(Game)
|
||
|
state.previous = prev
|
||
|
state.variant = state
|
||
|
state.draw = game_draw
|
||
|
state.update = game_update
|
||
|
state.free = game_free
|
||
|
rlgl.DisableBackfaceCulling()
|
||
|
|
||
|
img := rl.GenImageChecked(1024, 1024, 128, 128, rl.Color{60, 255, 255, 255}, rl.Color{30, 220, 220, 255})
|
||
|
state.background = rl.LoadTextureFromImage(img)
|
||
|
|
||
|
state.plane = rl.LoadModel(".\\assets\\models\\background.obj")
|
||
|
rl.UnloadImage(img)
|
||
|
|
||
|
game_setup(state)
|
||
|
return state
|
||
|
}
|
||
|
|
||
|
game_setup :: proc(game: ^Game) {
|
||
|
clear(&game.bullets)
|
||
|
game.player = player_spawn({GameField.x / 2 + 50, 20, 0})
|
||
|
game.health = 100
|
||
|
|
||
|
snake_spawn({10, 10, 0}, math.PI, 70)
|
||
|
|
||
|
|
||
|
for segment in Segments {
|
||
|
game.snake_max_health += int(segment.health)
|
||
|
}
|
||
|
|
||
|
game.camera = rl.Camera3D{
|
||
|
target = game.player.pos,
|
||
|
position = game.player.pos + vec3backward * 50,
|
||
|
fovy = 60,
|
||
|
//offset = WSize/2,
|
||
|
projection = rl.CameraProjection.PERSPECTIVE,
|
||
|
up = vec3up
|
||
|
}
|
||
|
game.camera.target.x = clamp(game.camera.target.x, -GameField.x/2, GameField.x/2)
|
||
|
game.camera.target.y = clamp(game.camera.target.y, 0, GameField.y)
|
||
|
game.camera.position = game.camera.target + vec3backward * 50
|
||
|
}
|
||
|
|
||
|
|
||
|
game_gen_level :: proc(game: ^Game) {
|
||
|
|
||
|
}
|
||
|
|
||
|
game_update :: proc(state: ^GameState, delta: f32) {
|
||
|
game := transmute(^Game)state
|
||
|
using game
|
||
|
|
||
|
|
||
|
player_update(&player, game, delta)
|
||
|
#reverse for &bullet, i in bullets {
|
||
|
bullet_process(&bullet, game, delta)
|
||
|
if !bullet.alive {
|
||
|
unordered_remove(&bullets, i)
|
||
|
}
|
||
|
}
|
||
|
snake_process(game, delta)
|
||
|
target_offset := player.vel / 5
|
||
|
camera_offset = rl.Vector3MoveTowards(camera_offset, target_offset, rl.Vector3Length(target_offset - camera_offset) * 10 * delta)
|
||
|
camera.target = player.pos + camera_offset
|
||
|
camera.target.x = clamp(camera.target.x, -GameField.x/2, GameField.x/2)
|
||
|
camera.target.y = clamp(camera.target.y, 0, GameField.y)
|
||
|
camera.position = camera.target + vec3backward * 50
|
||
|
|
||
|
}
|
||
|
|
||
|
game_draw :: proc(state: ^GameState) {
|
||
|
|
||
|
game := transmute(^Game)state
|
||
|
using game
|
||
|
|
||
|
rl.BeginMode3D(camera)
|
||
|
rl.DrawModel(game.plane, {0, 0, 500}, 1000, rl.WHITE)
|
||
|
|
||
|
yy : i32 = 0
|
||
|
|
||
|
snake_draw(game)
|
||
|
player_draw(&player)
|
||
|
for bullet in bullets {
|
||
|
bullet_draw(bullet)
|
||
|
}
|
||
|
rl.EndMode3D()
|
||
|
rl.DrawText(rl.TextFormat("HEALTH: %d", snake_health), 0, 0, 20, rl.BLACK)
|
||
|
rl.DrawText(rl.TextFormat("STATE: %s", Head.state), 0, 20, 20, rl.BLACK)
|
||
|
|
||
|
|
||
|
hb_text : cstring = "Jörmungandr"
|
||
|
height := 30 * (WSize.y / 480)
|
||
|
hb_health : f32 = f32(snake_health) / f32(snake_max_health)
|
||
|
if snake_health == 0 {
|
||
|
hb_health = f32(Head.health) / f32(Head.max_health)
|
||
|
hb_text = "Jörmungandr's head"
|
||
|
}
|
||
|
rl.DrawRectangleV({0, WSize.y - height - 10}, {WSize.x, height + 10}, rl.WHITE)
|
||
|
hb_width := hb_health * WSize.x
|
||
|
rl.DrawRectangleV({WSize.x / 2 - hb_width / 2, WSize.y - height - 7}, {hb_width, height + 4}, rl.RED)
|
||
|
draw_text_centered(FontTitle, hb_text, {WSize.x / 2, WSize.y - height / 2}, height)
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
game_free :: proc(state: ^GameState) {
|
||
|
game := transmute(^Game)state
|
||
|
|
||
|
rl.UnloadTexture(game.background)
|
||
|
free(state)
|
||
|
}
|
||
|
|
||
|
|