package main import "base:runtime" import "base:intrinsics" import "core:log" import "core:mem" import "core:time" import "core:fmt" import "core:testing" import "core:strings" import "core:path/filepath" import "core:math" import "core:math/linalg" import "core:os" import "core:math/rand" import stbi "vendor:stb/image" import sa "sokol/app" import sh "sokol/helpers" import "ecs" import program_config "config" Vec2 :: ecs.Vec2 Vec3 :: ecs.Vec3 Vec4 :: ecs.Vec4 Globals :: struct { coordinator: ecs.Coordinator, input_system: ^ecs.InputSystem, physics_system: ^ecs.PhysicsSystem, camera_system: ^ecs.CameraSystem, render_system: ^ecs.RenderSystem, time_since_cube: f32, current_color: i32, } g: ^Globals default_context: runtime.Context main :: proc() { context.logger = log.create_console_logger() tracking_allocator: mem.Tracking_Allocator mem.tracking_allocator_init(&tracking_allocator, context.allocator) context.allocator = mem.tracking_allocator(&tracking_allocator) defer reset_tracking_allocator(&tracking_allocator) default_context = context sa.run({ window_title = program_config.WINDOW_TITLE, allocator = sa.Allocator(sh.allocator(&default_context)), logger = sa.Logger(sh.logger(&default_context)), init_cb = init_cb, frame_cb = frame_cb, cleanup_cb = cleanup_cb, event_cb = event_cb, }) } init_cb :: proc "c" () { context = default_context sa.show_mouse(false) sa.lock_mouse(true) g = new(Globals) g.coordinator = ecs.coordinator_create() create_scene() } frame_cb:: proc "c" () { context = default_context dt := f32(sa.frame_duration()) g.time_since_cube += dt if g.time_since_cube >= program_config.SPAWN_INTERVAL { g.time_since_cube = 0 create_cube() } ecs.physics_system_update(g.physics_system, &g.coordinator, dt) ecs.camera_system_update(g.camera_system, &g.coordinator, dt) ecs.render_system_update(g.render_system, &g.coordinator) ecs.input_system_mouse_reset(g.input_system, &g.coordinator) } cleanup_cb :: proc "c" () { context = default_context ecs.render_system_delete(g.render_system, &g.coordinator) ecs.coordinator_destroy(&g.coordinator) free(g) } event_cb :: proc "c" (event: ^sa.Event) { context = default_context ecs.input_system_update(g.input_system, &g.coordinator, event) } create_cube :: proc() { entity := ecs.coordinator_create_entity(&g.coordinator) ecs.coordinator_add_component( ecs.GravityComponent, &g.coordinator, entity, ecs.GravityComponent{ ecs.Vec3{ 0.0, program_config.GRAVITY_CONSTANT, 0.0 } }) ecs.coordinator_add_component( ecs.RigidBodyComponent, &g.coordinator, entity, ecs.RigidBodyComponent{ velocity = ecs.Vec3{ 0.0, 0.0, 0.0 }, acceleration = ecs.Vec3{ 0.0, 0.0, 0.0 }, }) ecs.coordinator_add_component( ecs.TransformComponent, &g.coordinator, entity, ecs.TransformComponent{ position = Vec3{ f32(rand.int_max(program_config.SPAWN_AREA)), 10, f32(rand.int_max(program_config.SPAWN_AREA)), }, rotation = ecs.Vec3{ 0.0, 0.0, 0.0 }, scale = ecs.Vec3{ 1.0, 1.0, 1.0 }, }) ecs.coordinator_add_component( ecs.ColorComponent, &g.coordinator, entity, ecs.ColorComponent{ color = program_config.CUBE_COLORS[g.current_color] }) g.current_color += 1 g.current_color %= i32(len(program_config.CUBE_COLORS)) ecs.coordinator_add_component( ecs.MeshComponent, &g.coordinator, entity, ecs.MeshComponent{ mesh_id = .Cube }) ecs.coordinator_add_component( ecs.MaterialComponent, &g.coordinator, entity, ecs.MaterialComponent{ material_id = .Cube }) } create_scene :: proc() { ecs.coordinator_register_component(ecs.GravityComponent, &g.coordinator) ecs.coordinator_register_component(ecs.RigidBodyComponent, &g.coordinator) ecs.coordinator_register_component(ecs.TransformComponent, &g.coordinator) ecs.coordinator_register_component(ecs.ColorComponent, &g.coordinator) ecs.coordinator_register_component(ecs.CameraComponent, &g.coordinator) ecs.coordinator_register_component(ecs.MaterialComponent, &g.coordinator) ecs.coordinator_register_component(ecs.MeshComponent, &g.coordinator) ecs.coordinator_register_component(ecs.InputComponent, &g.coordinator) g.physics_system = ecs.coordinator_register_system(ecs.PhysicsSystem, &g.coordinator) signature := ecs.signature_create() ecs.signature_set(&signature, ecs.coordinator_get_component_type(ecs.GravityComponent, &g.coordinator)) ecs.signature_set(&signature, ecs.coordinator_get_component_type(ecs.RigidBodyComponent, &g.coordinator)) ecs.signature_set(&signature, ecs.coordinator_get_component_type(ecs.TransformComponent, &g.coordinator)) ecs.coordinator_set_system_signature(ecs.PhysicsSystem, &g.coordinator, signature) g.render_system = ecs.coordinator_register_system(ecs.RenderSystem, &g.coordinator) ecs.signature_clear(&signature) ecs.signature_set(&signature, ecs.coordinator_get_component_type(ecs.TransformComponent, &g.coordinator)) ecs.signature_set(&signature, ecs.coordinator_get_component_type(ecs.ColorComponent, &g.coordinator)) ecs.signature_set(&signature, ecs.coordinator_get_component_type(ecs.MeshComponent, &g.coordinator)) ecs.signature_set(&signature, ecs.coordinator_get_component_type(ecs.MaterialComponent, &g.coordinator)) ecs.coordinator_set_system_signature(ecs.RenderSystem, &g.coordinator, signature) g.camera_system = ecs.coordinator_register_system(ecs.CameraSystem, &g.coordinator) ecs.signature_clear(&signature) ecs.signature_set(&signature, ecs.coordinator_get_component_type(ecs.CameraComponent, &g.coordinator)) ecs.signature_set(&signature, ecs.coordinator_get_component_type(ecs.InputComponent, &g.coordinator)) ecs.coordinator_set_system_signature(ecs.CameraSystem, &g.coordinator, signature) g.input_system = ecs.coordinator_register_system(ecs.InputSystem, &g.coordinator) ecs.signature_clear(&signature) ecs.signature_set(&signature, ecs.coordinator_get_component_type(ecs.InputComponent, &g.coordinator)) ecs.coordinator_set_system_signature(ecs.InputSystem, &g.coordinator, signature) user_entity := ecs.coordinator_create_entity(&g.coordinator) ecs.coordinator_add_component( ecs.CameraComponent, &g.coordinator, user_entity, ecs.CameraComponent{ position = program_config.START_POSITION, target = { 0, 0, 1 }, look = { 0, 0 }, movement_speed = program_config.MOVEMENT_SPEED, look_sensitivity = program_config.LOOK_SENSITIVITY, }) ecs.coordinator_add_component( ecs.InputComponent, &g.coordinator, user_entity, ecs.InputComponent{ key_down = {}, mouse_movement = Vec2{ 0, 0 } }) ecs.render_system_init(g.render_system, user_entity) } reset_tracking_allocator :: proc(track: ^mem.Tracking_Allocator) { if len(track.allocation_map) > 0 { fmt.eprintf("=== %v allocations not freed: ===\n", len(track.allocation_map)) for _, entry in track.allocation_map { fmt.eprintf("- %v bytes @ %v\n", entry.size, entry.location) } } if len(track.bad_free_array) > 0 { fmt.eprintf("=== %v incorrect frees: ===\n", len(track.bad_free_array)) for entry in track.bad_free_array { fmt.eprintf("- %p @ %v\n", entry.memory, entry.location) } } mem.tracking_allocator_destroy(track) }