[feat]: initial commit
This commit is contained in:
commit
7b48f34e94
24 changed files with 1354 additions and 0 deletions
173
source/game.odin
Normal file
173
source/game.odin
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
This file is the starting point of your game.
|
||||
|
||||
Some important procedures are:
|
||||
- game_init_window: Opens the window
|
||||
- game_init: Sets up the game state
|
||||
- game_update: Run once per frame
|
||||
- game_should_close: For stopping your game when close button is pressed
|
||||
- game_shutdown: Shuts down game and frees memory
|
||||
- game_shutdown_window: Closes window
|
||||
|
||||
The procs above are used regardless if you compile using the `build_release`
|
||||
script or the `build_hot_reload` script. However, in the hot reload case, the
|
||||
contents of this file is compiled as part of `build/hot_reload/game.dll` (or
|
||||
.dylib/.so on mac/linux). In the hot reload cases some other procedures are
|
||||
also used in order to facilitate the hot reload functionality:
|
||||
|
||||
- game_memory: Run just before a hot reload. That way game_hot_reload.exe has a
|
||||
pointer to the game's memory that it can hand to the new game DLL.
|
||||
- game_hot_reloaded: Run after a hot reload so that the `g` global
|
||||
variable can be set to whatever pointer it was in the old DLL.
|
||||
|
||||
NOTE: When compiled as part of `build_release`, `build_debug` or `build_web`
|
||||
then this whole package is just treated as a normal Odin package. No DLL is
|
||||
created.
|
||||
*/
|
||||
|
||||
// NOTE: `fmt.ctprintf` uses the temp allocator. The temp allocator is
|
||||
// cleared at the end of the frame by the main application, meaning inside
|
||||
// `main_hot_reload.odin`, `main_release.odin` or `main_web_entry.odin`.
|
||||
|
||||
package game
|
||||
|
||||
import "engine"
|
||||
import rl "vendor:raylib"
|
||||
|
||||
GAME_WIDTH :: 640
|
||||
GAME_HEIGHT :: 270
|
||||
|
||||
Game_Memory :: struct {
|
||||
render_target: rl.RenderTexture,
|
||||
render_scale: f32,
|
||||
run: bool,
|
||||
}
|
||||
g: ^Game_Memory
|
||||
|
||||
update :: proc() {
|
||||
if rl.IsKeyPressed(.ESCAPE) {
|
||||
g.run = false
|
||||
}
|
||||
|
||||
g.render_scale = min(
|
||||
f32(rl.GetScreenWidth()) / f32(GAME_WIDTH),
|
||||
f32(rl.GetScreenHeight()) / f32(GAME_HEIGHT),
|
||||
)
|
||||
|
||||
rl.SetMouseOffset(
|
||||
-i32((f32(rl.GetScreenWidth()) - (f32(GAME_WIDTH) * g.render_scale)) * 0.5),
|
||||
-i32((f32(rl.GetScreenHeight()) - (f32(GAME_HEIGHT) * g.render_scale)) * 0.5),
|
||||
)
|
||||
rl.SetMouseScale(1 / g.render_scale, 1 / g.render_scale)
|
||||
|
||||
engine.update()
|
||||
}
|
||||
|
||||
draw :: proc() {
|
||||
rl.BeginTextureMode(g.render_target)
|
||||
rl.ClearBackground(rl.BLACK)
|
||||
engine.draw()
|
||||
rl.EndTextureMode()
|
||||
|
||||
rl.BeginDrawing()
|
||||
rl.ClearBackground(rl.BLACK)
|
||||
rl.DrawTexturePro(
|
||||
g.render_target.texture,
|
||||
{0, 0, f32(g.render_target.texture.width), f32(-g.render_target.texture.height)},
|
||||
{
|
||||
(f32(rl.GetScreenWidth()) - (f32(GAME_WIDTH) * g.render_scale)) * 0.5,
|
||||
(f32(rl.GetScreenHeight()) - (f32(GAME_HEIGHT) * g.render_scale)) * 0.5,
|
||||
f32(GAME_WIDTH) * g.render_scale,
|
||||
f32(GAME_HEIGHT) * g.render_scale,
|
||||
},
|
||||
{0, 0},
|
||||
0,
|
||||
rl.WHITE,
|
||||
)
|
||||
rl.EndDrawing()
|
||||
}
|
||||
|
||||
@(export)
|
||||
game_update :: proc() {
|
||||
update()
|
||||
draw()
|
||||
free_all(context.temp_allocator)
|
||||
}
|
||||
|
||||
@(export)
|
||||
game_init_window :: proc() {
|
||||
rl.SetConfigFlags({.WINDOW_RESIZABLE, .VSYNC_HINT})
|
||||
rl.InitWindow(1280, 720, "Untitle Roguelike")
|
||||
rl.SetWindowPosition(200, 200)
|
||||
rl.SetTargetFPS(60)
|
||||
rl.SetExitKey(nil)
|
||||
}
|
||||
|
||||
@(export)
|
||||
game_init :: proc() {
|
||||
g = new(Game_Memory)
|
||||
|
||||
g^ = Game_Memory {
|
||||
render_target = rl.LoadRenderTexture(GAME_WIDTH, GAME_HEIGHT),
|
||||
run = true,
|
||||
}
|
||||
engine.init()
|
||||
game_hot_reloaded(g)
|
||||
}
|
||||
|
||||
@(export)
|
||||
game_should_run :: proc() -> bool {
|
||||
when ODIN_OS != .JS {
|
||||
if rl.WindowShouldClose() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return g.run
|
||||
}
|
||||
|
||||
@(export)
|
||||
game_shutdown :: proc() {
|
||||
free(g)
|
||||
engine.unload()
|
||||
}
|
||||
|
||||
@(export)
|
||||
game_shutdown_window :: proc() {
|
||||
rl.CloseWindow()
|
||||
}
|
||||
|
||||
@(export)
|
||||
game_memory :: proc() -> rawptr {
|
||||
return g
|
||||
}
|
||||
|
||||
@(export)
|
||||
game_memory_size :: proc() -> int {
|
||||
return size_of(Game_Memory)
|
||||
}
|
||||
|
||||
@(export)
|
||||
game_hot_reloaded :: proc(mem: rawptr) {
|
||||
g = (^Game_Memory)(mem)
|
||||
|
||||
// Here you can also set your own global variables. A good idea is to make
|
||||
// your global variables into pointers that point to something inside `g`.
|
||||
}
|
||||
|
||||
@(export)
|
||||
game_force_reload :: proc() -> bool {
|
||||
return rl.IsKeyPressed(.F5)
|
||||
}
|
||||
|
||||
@(export)
|
||||
game_force_restart :: proc() -> bool {
|
||||
return rl.IsKeyPressed(.F6)
|
||||
}
|
||||
|
||||
// In a web build, this is called when browser changes size. Remove the
|
||||
// `rl.SetWindowSize` call if you don't want a resizable game.
|
||||
game_parent_window_size_changed :: proc(w, h: int) {
|
||||
rl.SetWindowSize(i32(w), i32(h))
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue