package demonchime import "base:runtime" import "core:c" import "core:c/libc" import "core:fmt" import "core:log" import "core:mem" import "core:math/linalg" import rl "vendor:raylib" import "phys" Vec2 :: [2]f32 Rect :: struct { start: Vec2, size: Vec2, } ROOM_FADE_SIZE :: 8 state: struct { debug_mode: bool, camera_target: Vec2, camera: rl.Camera2D, prop_list: Entity_List(Prop), wiggle_prop_list: Entity_List(Wiggle_Prop), platform_list: Entity_List(Platform), bullet_list: Entity_List(Bullet), } logger: log.Logger raylib_log :: proc "c" ( msg_type: rl.TraceLogLevel, fmt: cstring, args: ^c.va_list, ) { context = runtime.default_context() context.logger = logger msg_bytes: [1028]u8 libc.vsnprintf(raw_data(msg_bytes[:]), 1028, fmt, args) msg := string(msg_bytes[:]) #partial switch msg_type { case .DEBUG: log.debug(msg) case .INFO: log.info(msg) case .WARNING: log.warn(msg) case .ERROR: log.error(msg) case .FATAL: log.fatal(msg) } } init :: proc() { state.camera.zoom = 1 init_keybinds() init_draw() init_player() open_room(.Carrabassett0) } frame :: proc() { if is_keybind_just_down(actions.toggle_debug_mode) { state.debug_mode = !state.debug_mode } dt := rl.GetFrameTime() for cb in update_callbacks { cb(dt) } state.camera.target = dt_lerp( state.camera.target, state.camera_target, CAMERA_ACCEL, ) draw_new_frame() cam := state.camera cam.target = linalg.round(cam.target) rl.BeginMode2D(cam) renderer.tint = get_room(current_room.id).background_color draw_rect({ {0, 0}, {f32(current_room.width), f32(current_room.height)}, }) renderer.tint = {1, 1, 1, 1} for cb in draw_callbacks { cb() } draw_room(current_room.id) rl.DrawRectangleGradientH( 0, 0, ROOM_FADE_SIZE, current_room.height, rl.BLACK, rl.BLANK, ) rl.DrawRectangleGradientH( current_room.width - ROOM_FADE_SIZE, 0, ROOM_FADE_SIZE, current_room.height, rl.BLANK, rl.BLACK, ) rl.DrawRectangleGradientV( 0, 0, current_room.width, ROOM_FADE_SIZE, rl.BLACK, rl.BLANK, ) rl.DrawRectangleGradientV( 0, current_room.height - ROOM_FADE_SIZE, current_room.width, ROOM_FADE_SIZE, rl.BLANK, rl.BLACK, ) if state.debug_mode { // Draw all collisions body_it: int renderer.tint = {1, 0.25, 0.5, 0.25} for body in phys.iterate_bodies(&body_it) { rect := phys.get_rect(body) rect.start += phys.get_position(body) draw_linerect(transmute(Rect)rect) draw_rect(transmute(Rect)rect) } renderer.tint = {1, 1, 1, 1} } rl.EndMode2D() 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) } draw_end_frame() } cleanup :: proc() { deinit_player() delete_entity_list(state.platform_list) delete_entity_list(state.bullet_list) delete_entity_list(state.prop_list) delete_entity_list(state.wiggle_prop_list) phys.destroy_world() } 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) rl.SetTraceLogCallback(raylib_log) rl.InitWindow(SCREEN_WIDTH * 3, SCREEN_HEIGHT * 3, "Demonchime") rl.SetWindowState({.WINDOW_RESIZABLE}) rl.SetTargetFPS(240) init() for !rl.WindowShouldClose() { frame() free_all(context.temp_allocator) } cleanup() }