:beer
name="Beer"
+texture_path="./assets/images/beer-1.png"
weight=12.34
+:Wall
+entity.id = 10
+entity.flags = 2
+entity.pos.x = 178.0000
+entity.pos.y = 312.0000
+entity.size.x = 355.0000
+entity.size.y = 28.0000
+
+:Wall
+entity.id = 11
+entity.flags = 2
+entity.pos.x = 447.0000
+entity.pos.y = 165.0000
+entity.size.x = 31.0000
+entity.size.y = 328.0000
+
:Player
-entity.id = 1
+entity.id = 12
entity.flags = 2
-entity.pos.x = 891.5230
-entity.pos.y = 279.3731
+entity.pos.x = 237.4579
+entity.pos.y = 133.2012
entity.size.x = 32.0000
entity.size.y = 32.0000
-holding = 4
+holding = 0
controls.up = 87
controls.down = 83
controls.left = 65
controls.interact = 70
controls.pick_up = 71
color.r = 1.0000
-color.g = 0.0000
+color.g = 1.0000
color.b = 1.0000
color.a = 1.0000
-facing = 3
-
-:Player
-entity.id = 2
-entity.flags = 2
-entity.pos.x = 328.9612
-entity.pos.y = 309.7936
-entity.size.x = 32.0000
-entity.size.y = 32.0000
-holding = 0
-controls.up = 265
-controls.down = 264
-controls.left = 263
-controls.right = 262
-controls.interact = 44
-controls.pick_up = 46
-color.r = 1.0000
-color.g = 0.0000
-color.b = 0.0000
-color.a = 1.0000
facing = 4
:Door
-entity.id = 3
+entity.id = 13
entity.flags = 7
-entity.pos.x = 290.0374
-entity.pos.y = 211.0090
-entity.size.x = 370.0000
-entity.size.y = 24.0000
-target_openness = 0.8000
-
-:Item_Entity
-entity.id = 4
-entity.flags = 0
-entity.pos.x = 891.5230
-entity.pos.y = 259.3731
-entity.size.x = 10.0000
-entity.size.y = 8.0000
-color.r = 1.0000
-color.g = 0.0000
-color.b = 1.0000
-color.a = 1.0000
+entity.pos.x = 353.0000
+entity.pos.y = 312.0000
+entity.size.x = 156.0000
+entity.size.y = 30.0000
+target_openness = 0.0000
:Item_Entity
-entity.id = 5
+entity.id = 14
entity.flags = 4
-entity.pos.x = 167.6909
-entity.pos.y = 283.5205
-entity.size.x = 13.0000
-entity.size.y = 10.0000
-color.r = 1.0000
-color.g = 0.0000
-color.b = 1.0000
-color.a = 1.0000
-
-:Wall
-entity.id = 6
-entity.flags = 2
-entity.pos.x = 501.0000
-entity.pos.y = 291.0000
-entity.size.x = 62.0000
-entity.size.y = 180.0000
-
-:Wall
-entity.id = 7
-entity.flags = 2
-entity.pos.x = 275.0000
-entity.pos.y = 391.0000
-entity.size.x = 461.0000
-entity.size.y = 34.0000
-
-:Wall
-entity.id = 8
-entity.flags = 2
-entity.pos.x = 74.0000
-entity.pos.y = 313.0000
-entity.size.x = 65.0000
-entity.size.y = 222.0000
+entity.pos.x = 269.4578
+entity.pos.y = 133.2012
+entity.size.x = 24.0000
+entity.size.y = 24.0000
+item = "beer"
-:Wall
-entity.id = 9
-entity.flags = 2
-entity.pos.x = 686.0000
-entity.pos.y = 302.0000
-entity.size.x = 50.0000
-entity.size.y = 363.0000
#load "utils/any_utils"
#load "utils/asset_loader"
#load "utils/input"
+#load "utils/logger"
#load "utils/vecmath"
#load "stb_image"
name: str;
weight := 10.0f;
- color := Color.{ 1, 1, 0 };
+ color := Color.{ 1, 1, 0 };
+ texture_path : str;
}
Item_Store :: struct {
items: Map(str, ^Item);
load_items_from_file :: item_store_load_items_from_file;
+ get_item :: item_store_get_item;
}
item_store_make :: () -> Item_Store {
err, input_file := os.open(path, .Read);
if err != .None {
- printf("Failed to open file: {}\n", path);
+ debug_log(.Error, "Failed to open file: {}", path);
return;
}
defer os.close(^input_file);
|> string.strip_whitespace();
if items->has(item_id) {
- printf("Duplicate definition for item with id '{}', on line: {}.\n", item_id);
- return;
+ debug_log(.Warning, "Duplicate definition for item with id '{}', on line: {}.", item_id);
}
item_id = string.alloc_copy(item_id, allocator=item_allocator);
member := get_any_for_member(ptr_to_any(current_item), var_name);
if member.data == null {
- printf("'{}' is not a valid member of Item on line {}.\n", var_name, line_number);
+ debug_log(.Warning, "'{}' is not a valid member of Item on line {}.", var_name, line_number);
continue;
}
if !conv.parse_any(member.data, member.type, line) {
- printf("Unable to parse '{}' for type '{}' on line {}.\n", line, member.type, line_number);
+ debug_log(.Warning, "Unable to parse '{}' for type '{}' on line {}.", line, member.type, line_number);
continue;
}
}
}
+item_store_get_item :: (use this: ^Item_Store, id: str) -> ^Item {
+ return items[id];
+}
Item_Entity :: struct {
use entity: Entity;
[Editor_Custom_Field.{render_item_picker}]
item: str;
- color: Color;
init_data :: struct {
pos := Vector2.{0, 0};
- color := Color.{1, 0, 1, 1};
}
init :: (use this: ^Item_Entity, data: init_data) {
this.pos = data.pos;
this.size = .{16, 16};
- this.color = data.color;
this.flags |= .Carryable;
}
get_rect :: Entity.get_rect
draw :: (use this: ^Item_Entity) {
- immediate_set_color(this.color);
+ item_data := item_store->get_item(item);
+ immediate_set_color(item_data.color);
r := this->get_rect();
- immediate_rectangle(r.x, r.y, r.w, r.h);
+ texture, loaded := texture_lookup(item_data.texture_path);
+ if !loaded {
+ immediate_rectangle(r.x, r.y, r.w, r.h);
+ } else {
+ immediate_image(^texture, r.x, r.y, r.w, r.h);
+ }
}
}
@CompilerFeatures // Maybe there should be data stored in the Type_Info_Struct about
// the functions/methods that are defined in the structs scope. I don't know if that
// would be worthwhile or if it would just be bulking up the type info data.
- #if #defined(entity_type.destroy) { info.destroy = entity_type.destroy; if DEBUG do printf("{} has '{}'.\n", entity_type, "destroy"); }
- #if #defined(entity_type.update) { info.update = entity_type.update; if DEBUG do printf("{} has '{}'.\n", entity_type, "update"); }
- #if #defined(entity_type.draw) { info.draw = entity_type.draw; if DEBUG do printf("{} has '{}'.\n", entity_type, "draw"); }
- #if #defined(entity_type.get_rect) { info.get_rect = entity_type.get_rect; if DEBUG do printf("{} has '{}'.\n", entity_type, "get_rect"); }
- #if #defined(entity_type.interact) { info.interact = entity_type.interact; if DEBUG do printf("{} has '{}'.\n", entity_type, "interact"); }
+ #if #defined(entity_type.destroy) { info.destroy = entity_type.destroy; if DEBUG do debug_log(.Debug, "{} has '{}'.", entity_type, "destroy"); }
+ #if #defined(entity_type.update) { info.update = entity_type.update; if DEBUG do debug_log(.Debug, "{} has '{}'.", entity_type, "update"); }
+ #if #defined(entity_type.draw) { info.draw = entity_type.draw; if DEBUG do debug_log(.Debug, "{} has '{}'.", entity_type, "draw"); }
+ #if #defined(entity_type.get_rect) { info.get_rect = entity_type.get_rect; if DEBUG do debug_log(.Debug, "{} has '{}'.", entity_type, "get_rect"); }
+ #if #defined(entity_type.interact) { info.interact = entity_type.interact; if DEBUG do debug_log(.Debug, "{} has '{}'.", entity_type, "interact"); }
entity_types[entity_type] = info;
}
}
interact :: (use this: ^Door, interactor: ^Entity) {
- printf("The door at {} was interacted with by a {}!\n", pos, interactor.type);
-
// Doors only open if interacted with by a player
if_entity_is(interactor, Player) {
target_openness = 0.8f - target_openness;
io.write(dest, output);
}
- case #default {
- msg := conv.format(output_buffer, "Unhandled output case: {}\n", it.type);
- // assert(false, msg);
- printf("ERROR: {}\n", msg);
+ case #default do switch it.type {
+ case str {
+ output := conv.format_va(output_buffer, "{} = {\"}\n", .[.{^name, str}, member_any]);
+ io.write(dest, output);
+ }
+
+ case #default {
+ msg := conv.format(output_buffer, "Unhandled output case: {}\n", it.type);
+ debug_log(.Error, msg);
+ }
}
}
}
entity_manager_load_from_file :: (use this: ^Entity_Manager, filename: str) {
err, input_file := os.open(filename, .Read);
if err != .None {
- printf("Failed to open file: {}\n", filename);
+ debug_log(.Error, "Failed to open file: {}", filename);
return;
}
defer os.close(^input_file);
}
if entity_info == null {
- printf("Unknown entity kind '{}' on line {}.\n", entity_kind, line_number);
+ debug_log(.Error, "Unknown entity kind '{}' on line {}.", entity_kind, line_number);
current_entity = null;
continue;
}
member := get_any_for_member(any.{current_entity, current_entity.type}, var_name);
if member.data == null {
entity_info := cast(^Type_Info_Struct) get_type_info(current_entity.type);
- printf("'{}' is not a valid member of '{}' on line {}.\n", var_name, entity_info.name, line_number);
+ debug_log(.Warning, "'{}' is not a valid member of '{}' on line {}.", var_name, entity_info.name, line_number);
continue;
}
if !conv.parse_any(member.data, member.type, line) {
- printf("Unable to parse '{}' for type '{}' on line {}.\n", line, member.type, line_number);
+ debug_log(.Warning, "Unable to parse '{}' for type '{}' on line {}.", line, member.type, line_number);
continue;
}
}
item_store: Item_Store;
game_init :: () {
- // player_texture = texture_make(#cstr "./assets/images/player.png");
+ // player_texture = texture_lookup(#cstr "./assets/images/player.png");
// This process of queueing the asset bucket should
// be made automatic somehow...
queue_assets(^player_assets);
-
load_assets();
scene = entity_manager_create();
item_store->load_items_from_file("scenes/default.items");
#if DEBUG {
- println("Registered Entity types:");
+ debug_log(.Debug, "Registered Entity types:");
for scene.entity_types.entries {
info := cast(^type_info.Type_Info_Struct) type_info.get_type_info(it.key);
- printf(" {}\n", info.name);
+ debug_log(.Debug, " {}", info.name);
}
}
}
+#local quick_save_file := "scenes/quick_save.scene";
+
game_update :: (dt: f32) {
if is_key_just_up(GLFW_KEY_F8) {
- scene->save_to_file("scenes/quick_save.scene");
+ debug_log(.Info, "Saving to '{}'.", quick_save_file);
+ scene->save_to_file(quick_save_file);
}
if is_key_just_up(GLFW_KEY_F9) {
- scene->load_from_file("scenes/quick_save.scene");
+ debug_log(.Info, "Loading from '{}'.", quick_save_file);
+ scene->load_from_file(quick_save_file);
}
if editor_shown() {
filename: str;
}
-texture_make :: #match {}
-#match texture_make (filename: str) -> (Texture, bool) {
+texture_lookup :: #match {}
+#match texture_lookup (filename: str) -> (Texture, bool) {
+ if texture_cache->has(filename) {
+ return texture_cache[filename], true;
+ }
+
buffer: [512] u8;
memory.copy(~~ buffer, filename.data, math.min(filename.count, 511));
- return texture_make(cast(cstr) buffer);
+ return texture_lookup(cast(cstr) buffer);
}
-#match texture_make (path: cstr) -> (Texture, bool) {
+#match texture_lookup (path: cstr) -> (Texture, bool) {
filename := string.from_cstr(path);
if texture_cache->has(filename) {
return texture_cache[filename], true;
}
draw :: () {
- immediate_clear(.{0.1, 0.1, 0.1});
+ immediate_clear(.{0.15, 0.15, 0.2});
defer ui_end_frame();
defer input_post_update();
defer {
main :: (args) => {
if !glfwInit() {
- println("Failed to initialize GLFW");
+ debug_log(.Critical, "Failed to initialize GLFW!");
os.exit(1);
}
if path_tag != null {
path := *cast(^str) path_tag.data;
- if texture, success := texture_make(path); success {
+ if texture, success := texture_lookup(path); success {
*out_texture = texture;
} else {
- printf("[ERROR] Failed to load texture '{}' for asset queued here: {}:{},{}.\n", path, location.file, location.line, location.column);
+ debug_log(.Error, "Failed to load texture '{}' for asset queued here: {}:{},{}.\n", path, location.file, location.line, location.column);
}
} else {
- printf("[ERROR] Texture path not found for texture asset load here: {}:{},{}.\n", location.file, location.line, location.column);
+ debug_log(.Error, "Texture path not found for texture asset load here: {}:{},{}.\n", location.file, location.line, location.column);
}
}
case #default {
- printf("[WARN] Asset loader does not know how to load a '{}'.\n", type);
+ debug_log(.Warning, "Asset loader does not know how to load a '{}'.\n", type);
}
}
}
--- /dev/null
+//
+// This may become an in-game or external file logger in the future,
+// but for now this is just for logging to the command line.
+
+use package core
+
+Log_Level :: enum {
+ Debug;
+ Info;
+ Warning;
+ Error;
+ Critical;
+}
+
+debug_log :: (level: Log_Level, format: str, args: ..any) {
+ debug_log_va(level, format, ~~args);
+}
+
+debug_log_va :: (level: Log_Level, format: str, args: [] any) {
+ buf: [2048] u8;
+ output := conv.format_va(buf, format, args);
+ printf("[{}] {}\n", level_string(level), output);
+}
+
+#local level_string :: (level: Log_Level) => {
+ switch level {
+ case .Debug do return "DEBUG";
+ case .Info do return "INFO ";
+ case .Warning do return "WARN ";
+ case .Error do return "ERROR";
+ case .Critical do return "CRIT ";
+ }
+
+ return " ";
+}