package demonchime import "base:runtime" import "core:fmt" import "core:log" import "core:math/rand" import "core:mem" import hm "core:container/handle_map" import "phys" import "fw" Handle :: hm.Handle32 Vec2 :: fw.Vec2 Vec2i :: fw.Vec2i Color :: fw.Color Rect :: fw.Rect state: struct { debug_mode: bool, camera_target: Vec2, camera_pos: Vec2, last_fixed_update: f64, enemy_list: [dynamic]^Enemy, bullet_list: hm.Dynamic_Handle_Map(Bullet, Handle), platform_list: hm.Dynamic_Handle_Map(Platform, Handle), prop_list: hm.Dynamic_Handle_Map(Prop, Handle), rope_list: hm.Dynamic_Handle_Map(Rope, Handle), wiggle_prop_list: hm.Dynamic_Handle_Map(Wiggle_Prop, Handle), } rng: rand.Generator logger: log.Logger init :: proc() { fw.init({ win_name = "Demonchime", win_size = SCREEN_SIZE_INT * 3, screen_size = SCREEN_SIZE_INT, renderer_backend = .OpenGL, }) context.random_generator = rand.xoshiro256_random_generator() init_keybinds() init_player() open_room(.Carrabassett0) } frame :: proc() { update_keybinds() if fw.is_keybind_just_down(actions.toggle_debug_mode) { state.debug_mode = !state.debug_mode } if fw.is_keybind_just_down(actions.toggle_fullscreen) { // rl.ToggleBorderlessWindowed() // rl.ToggleFullscreen() } dt := f32(fw.get_delta_time()) if fw.get_time() - state.last_fixed_update > FIXED_UPDATE_RATE { state.last_fixed_update = fw.get_time() for cb in fixed_update_callbacks { cb(FIXED_UPDATE_RATE) } } for cb in update_callbacks { cb(dt) } state.camera_pos = dt_lerp( state.camera_pos, state.camera_target, CAMERA_ACCEL, ) fw.set_camera_pos(state.camera_pos) fw.draw_rect( {0, 0}, {f32(current_room.width), f32(current_room.height)}, color = get_room(current_room.id).background_color, ) for cb in draw_callbacks { cb() } draw_room(current_room.id) for cb in fg_draw_callbacks { cb() } fw.draw_rect_gradient( {0, 0}, {ROOM_FADE_SIZE, f32(current_room.height)}, tl_color = fw.BLACK, tr_color = fw.TRANSPARENT, bl_color = fw.BLACK, br_color = fw.TRANSPARENT, ) fw.draw_rect_gradient( {f32(current_room.width) - ROOM_FADE_SIZE, 0}, {ROOM_FADE_SIZE, f32(current_room.height)}, tl_color = fw.TRANSPARENT, tr_color = fw.BLACK, bl_color = fw.TRANSPARENT, br_color = fw.BLACK, ) fw.draw_rect_gradient( {0, 0}, {f32(current_room.width), ROOM_FADE_SIZE}, tl_color = fw.BLACK, tr_color = fw.BLACK, bl_color = fw.TRANSPARENT, br_color = fw.TRANSPARENT, ) fw.draw_rect_gradient( {0, f32(current_room.height) - ROOM_FADE_SIZE}, {f32(current_room.width), ROOM_FADE_SIZE}, tl_color = fw.TRANSPARENT, tr_color = fw.TRANSPARENT, bl_color = fw.BLACK, br_color = fw.BLACK, ) if state.debug_mode { // Draw all collisions body_it: int color := Color{1, 0.25, 0.5, 0.25} body_iter := hm.iterator_make(&phys.world.bodies) for _, body in hm.iterate(&body_iter) { rect := phys.get_rect(body) rect.start += phys.get_position(body) fw.draw_rect(rect.start, rect.size, color = color, lines = true) fw.draw_rect(rect.start, rect.size, color = color) } } // fps_text := fmt.caprintf( // "FPS: %v", // rl.GetFPS(), // allocator = context.temp_allocator, // ) // rl.DrawText(fps_text, 5, 5, 8, rl.GREEN) // // if state.debug_mode { // rl.DrawText("Debug Mode", 5, 5 + 8, 8, rl.YELLOW) // } } cleanup :: proc() { deinit_player() clear_enemies() delete(state.enemy_list) hm.dynamic_destroy(&state.bullet_list) hm.dynamic_destroy(&state.platform_list) hm.dynamic_destroy(&state.prop_list) hm.dynamic_destroy(&state.wiggle_prop_list) clear_ropes() hm.dynamic_destroy(&state.rope_list) phys.destroy_world() fw.deinit() } main :: proc() { when ODIN_DEBUG { track: mem.Tracking_Allocator mem.tracking_allocator_init(&track, context.allocator) context.allocator = mem.tracking_allocator(&track) defer { if len(track.allocation_map) > 0 { fmt.eprintf( "=== %v allocations not freed: ===\n", len(track.allocation_map), ) total := 0 for _, entry in track.allocation_map { fmt.eprintf( "- %v bytes @ %v (%v, mode %v)\n", entry.size, entry.location, entry.err, entry.mode, ) total += entry.size } fmt.eprintf("=== a total of %v bytes unfreed ===\n", total) } mem.tracking_allocator_destroy(&track) } } logger = log.create_console_logger() context.logger = logger defer log.destroy_console_logger(logger) init() for fw.next_frame() { frame() if fw.is_keybind_just_down(actions.exit) { break } } cleanup() }