Huge refactor, Adding more code to engine from the game

This commit is contained in:
sam
2026-03-19 22:32:26 +05:45
parent 493338d91b
commit 09941e3e1d
10 changed files with 799 additions and 39 deletions
+243
View File
@@ -0,0 +1,243 @@
package edit2d
import "base:intrinsics"
import "core:encoding/cbor"
import "base:runtime"
import im "shared:odin-imgui"
import "shared:odin-imgui/imgui_impl_glfw"
import "shared:odin-imgui/imgui_impl_opengl3"
import gl "vendor:OpenGL"
import "core:fmt"
import "vendor:glfw"
import "core:reflect"
engine_state :: struct
{
window : glfw.WindowHandle,
draw : Draw,
restart, pause : bool,
substep_count : u32,
//Must be set before calling ion_init
width, height : i32,
title : cstring,
time : f32,
tex_line : u32,
drop_callback : glfw.DropProc,
input : input_state,
}
MAX_KEYS :: 512
input_state :: struct
{
mouse_wheel : [2]f64,
mouse : [2]f64,
mouse_prev : [2]f64,
curr, prev : [MAX_KEYS]bool,
}
//This function defines if the game's structs are defines as requirements
//Doing the checking in the beggining makes writing helper code more reliable
engine_check_types :: proc($Game: typeid)
{
assert(intrinsics.type_has_field(Game, "levels"), "game should contan levels")
assert(intrinsics.type_has_field(Game, "engine"), "game should contan engine")
level_type := reflect.struct_field_by_name(Game, "levels")
engine_type := reflect.struct_field_by_name(Game, "engine")
assert(engine_type.is_using, "You should be using the engine")
assert(engine_type.type.id == typeid_of(engine_game), "Engine Should be engine_game")
level_variant := level_type.type.variant
assert(reflect.is_dynamic_map(level_type.type), "Level should be map of names and level files")
level_map_type := level_type.type.variant.(runtime.Type_Info_Map)
assert(level_map_type.key.id == typeid_of(string), "Level key should be name")
//Level should also have engine
level_engine_type := reflect.struct_field_by_name(level_map_type.value.id, "engine")
assert(level_engine_type.is_using, "Should be using engine")
assert(level_engine_type.type.id == typeid_of(engine_world), "Should be using engine")
entities_type := reflect.struct_field_by_name(level_map_type.value.id, "entities")
entity_defs_type := reflect.struct_field_by_name(level_map_type.value.id, "entity_defs")
assert(reflect.is_dynamic_array(entities_type.type))
assert(reflect.is_dynamic_array(entity_defs_type.type))
entities_arr := entities_type.type.variant.(runtime.Type_Info_Dynamic_Array)
entity_defs_arr := entity_defs_type.type.variant.(runtime.Type_Info_Dynamic_Array)
entity_engine := reflect.struct_field_by_name(entities_arr.elem.id, "engine")
defs_engine := reflect.struct_field_by_name(entity_defs_arr.elem.id, "engine")
assert(entity_engine.is_using, "Should be using")
assert(defs_engine.is_using, "Should be using")
assert(entity_engine.type.id == typeid_of(engine_entity))
assert(defs_engine.type.id == typeid_of(engine_entity_def))
}
/*
This will only be called once to initilize the engine
initilize graphics library, glfw, callbacks
*/
engine_init :: proc($GameType : typeid, state: ^engine_state)
{
engine_check_types(GameType)
assert(glfw.Init() == true)
glfw.WindowHint(glfw.SCALE_TO_MONITOR, 1)
state.window = glfw.CreateWindow(state.width, state.height, state.title, nil, nil)
assert(state.window != nil)
glfw.MakeContextCurrent(state.window)
glfw.SwapInterval(1)
gl.load_up_to(4, 5, glfw.gl_set_proc_address)
im.CHECKVERSION()
im.CreateContext()
io := im.GetIO()
io.ConfigFlags += {
.NavEnableKeyboard,
.NavEnableGamepad,
.DpiEnableScaleFonts,
}
im.StyleColorsClassic()
style := im.GetStyle()
style.ChildBorderSize = 0.
style.ChildRounding = 6
style.TabRounding = 6
style.FrameRounding = 6
style.GrabRounding = 6
style.WindowRounding = 6
style.PopupRounding = 6
imgui_impl_glfw.InitForOpenGL(state.window, true)
imgui_impl_opengl3.Init("#version 150")
state.draw.cam = camera_init()
display_w, display_h := glfw.GetFramebufferSize(state.window)
state.draw.cam.width = display_w
state.draw.cam.height = display_h
state.draw.cam.zoom = 15
state.draw.show_ui = true
draw_create(&state.draw, &state.draw.cam)
cbor.tag_register_type({
marshal = proc(_: ^cbor.Tag_Implementation, e: cbor.Encoder, v: any) -> cbor.Marshal_Error {
cbor._encode_u8(e.writer, 201, .Tag) or_return
return nil;
},
unmarshal = proc(_: ^cbor.Tag_Implementation, d: cbor.Decoder, _: cbor.Tag_Number, v: any) -> (cbor.Unmarshal_Error) {
return nil
},
}, 201, rawptr)
}
update_frame :: proc(state: ^engine_state)
{
state.input.mouse_wheel = {}
glfw.PollEvents()
keyboard_update(state)
gl.ClearColor(0.4, 0.5, 0.6, 1.0)
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
cam := &state.draw.cam
cam.width, cam.height = glfw.GetWindowSize(state.window)
state.width , state.height = glfw.GetFramebufferSize(state.window)
gl.Viewport(0, 0, state.width, state.height)
imgui_impl_opengl3.NewFrame()
imgui_impl_glfw.NewFrame()
im.NewFrame()
}
end_frame :: proc(state: ^engine_state)
{
im.Render()
imgui_impl_opengl3.RenderDrawData(im.GetDrawData())
glfw.SwapBuffers(state.window)
}
cleanup :: proc(state: ^engine_state)
{
imgui_impl_opengl3.Shutdown()
imgui_impl_glfw.Shutdown()
}
engine_should_close :: proc(state : ^engine_state) -> b32
{
return glfw.WindowShouldClose(state.window)
}
keyboard_update :: proc(state: ^engine_state)
{
state.input.mouse_prev = state.input.mouse
state.input.mouse.x, state.input.mouse.y = glfw.GetCursorPos(state.window)
state.input.prev = state.input.curr
//Update current states
for key in glfw.KEY_SPACE ..< MAX_KEYS
{
state.input.curr[key] = glfw.GetKey(state.window, i32(key)) == glfw.PRESS
}
for key in 0..<glfw.KEY_SPACE
{
state.input.curr[key] = glfw.GetMouseButton(state.window, i32(key)) == glfw.PRESS
}
}
is_key_down :: #force_inline proc(state: ^engine_state, key : i32) -> bool{
return state.input.curr[key]
}
is_key_pressed :: #force_inline proc(state: ^engine_state, key : i32) -> bool{
return state.input.curr[key] && !state.input.prev[key]
}
is_key_released :: #force_inline proc(state: ^engine_state, key : i32) -> bool{
return !state.input.curr[key] && state.input.prev[key]
}