package main import rl "vendor:raylib" import "core:path/filepath" import "core:strings" import "core:fmt" vec3 :: [3]f32 vec3i :: [3]i32 vec2 :: [2]f32 vec2i :: [2]i32 vec3right := vec3{1, 0, 0} vec3left := vec3{-1, 0, 0} vec3up := vec3{0, 1, 0} vec3down := vec3{0, -1, 0} vec3forward := vec3{0, 0, 1} vec3backward := vec3{0, 0, -1} WSize := [2]f32{} WSizei := [2]i32{} WSizeLast := vec2i{} WindowShouldExit := false NeedTutorial := true KeyboardOnly := false Overlay_Opacity : f32 = 0 Resources :: struct { Fonts: struct { UI: rl.Font, Title: rl.Font, }, Models: struct { PlayerModel: rl.Model, SnakeHeadTop: rl.Model, SnakeHeadJaw: rl.Model, SnakeBody: rl.Model, Background: rl.Model, }, Sfx: struct { Drums: rl.Sound, Lightning: rl.Sound, LightningHit: rl.Sound, Rocket: rl.Sound, PlayerHit: rl.Sound, PlayerSwoosh: rl.Sound, PlayerDead: rl.Sound, SnakeGrowl: rl.Sound, SnakeRoarBlast: rl.Sound, SnakeEarthHit: rl.Sound, SnakeSegmentExplode: rl.Sound, SnakeBeam: rl.Sound, }, Music: struct { First: rl.Music, Second: rl.Music, } } Res : Resources res_paths := map[typeid]string{ rl.Music = "music", rl.Sound = "sfx", rl.Model = "models", } get_path :: proc(name: string, $T: typeid) -> cstring{ p := filepath.join([]string{"./assets", res_paths[T], name}) cstr := strings.clone_to_cstring(p) return cstr } load_model :: proc(name: string) -> rl.Model { p := get_path(name, rl.Model) mdl := rl.LoadModel(p) return mdl } load_sfx :: proc(name: string, volume: f32 = 1) -> rl.Sound { p := get_path(name, rl.Sound) snd := rl.LoadSound(p) rl.SetSoundVolume(snd, volume) return snd } load_music :: proc(name: string, volume: f32 = 1) -> rl.Music { p := get_path(name, rl.Music) snd := rl.LoadMusicStream(p) rl.SetMusicVolume(snd, volume) return snd } current_music : rl.Music change_track :: proc(music: rl.Music) { rl.StopMusicStream(current_music) current_music = music rl.PlayMusicStream(current_music) } Cursor : rl.Texture load_resources :: proc() { Res.Fonts.Title = rl.LoadFontEx("./assets/fonts/norse.otf", 96*2, nil, 2048) Res.Fonts.UI = rl.LoadFontEx("./assets/fonts/PTSerif-Regular.ttf", 96, nil, 2048) Res.Models = { PlayerModel = load_model("chariot.glb"), SnakeHeadTop = load_model("snake_head_top.obj"), SnakeHeadJaw = load_model("snake_jaw.obj"), SnakeBody = load_model("snake_body.obj"), Background = load_model("background.obj"), } Res.Sfx = { Drums = load_sfx("drums.ogg"), Lightning = load_sfx("lightning.ogg", 0.5), LightningHit = load_sfx("lightning-hit.ogg", 0.3), Rocket = load_sfx("rocket.ogg", 0.5), PlayerHit = load_sfx("player-hit.ogg", 0.5), PlayerSwoosh = load_sfx("player-swoosh.ogg"), PlayerDead = load_sfx("player-dead.ogg"), SnakeGrowl = load_sfx("snake-growl.ogg", 0.7), SnakeRoarBlast = load_sfx("snake-roar-blast.ogg", 0.8), SnakeBeam = load_sfx("snake-beam.ogg"), SnakeSegmentExplode = load_sfx("snake-segment-explode.ogg", 0.8), SnakeEarthHit = load_sfx("snake-earth-hit.ogg", 0.6), } Res.Music.First = load_music("alexander-nakarada-mjolnir.mp3", 0.7) Res.Music.Second = load_music("alexander-nakarada-the-northern-path.mp3", 0.7) } main :: proc() { // rl.SetConfigFlags(rl.ConfigFlags{.MSAA_4X_HINT, .FULLSCREEN_MODE, .VSYNC_HINT, .WINDOW_RESIZABLE}) rl.SetConfigFlags(rl.ConfigFlags{.VSYNC_HINT, .WINDOW_RESIZABLE}) rl.InitWindow(800, 600, "Ragnarøkkr") rl.InitAudioDevice() rl.SetWindowMinSize(800, 600) rl.HideCursor() Cursor = rl.LoadTexture("./assets/gfx/crosshair.png") load_resources() WSizei = {rl.GetScreenWidth(), rl.GetScreenHeight()} WSize = {f32(WSizei.x), f32(WSizei.y)} game := game_init() stack_push(game) menu := menu_init(game) stack_push(menu) for !WindowShouldExit { if rl.IsWindowResized() { WSizei = {rl.GetScreenWidth(), rl.GetScreenHeight()} WSize = {f32(WSizei.x), f32(WSizei.y)} } rl.UpdateMusicStream(current_music) state := stack_top() delta := rl.GetFrameTime() timers_process(delta) tweens_process(delta) state->update(delta) rl.BeginDrawing() rl.ClearBackground(rl.SKYBLUE) state->draw() rl.DrawRectangleV({}, WSize, rl.Color{0, 0, 0, u8(Overlay_Opacity * 255)}) pos := rl.GetMousePosition() rl.DrawTextureEx(Cursor, pos - {16, 16} * 3, 0, 3, rl.WHITE) rl.EndDrawing() } } Fullscreen := false toggle_fullscreen :: proc() { monitor := rl.GetCurrentMonitor() rl.ToggleBorderlessWindowed() WSizei = {rl.GetScreenWidth(), rl.GetScreenHeight()} WSize = {f32(WSizei.x), f32(WSizei.y)} Fullscreen = !Fullscreen // rl.ToggleFullscreen() }