summaryrefslogtreecommitdiff
path: root/kon/konsector.h
diff options
context:
space:
mode:
authorKonAki <konaki@anokonaki.org>2026-10-11 04:51:06 +0800
committerKonAki <konaki@anokonaki.org>2026-10-11 04:51:06 +0800
commit64a416a3fa0b5097afe723557ca71fc99606d3d9 (patch)
tree6d5eea1ddec0ed709ab9a4ebdc1de9bb002c81ce /kon/konsector.h
parentd3b6458db0c189d23100331c0e9e5001ff96c2f1 (diff)
add sector module: room maps in a text format with entities
Diffstat (limited to 'kon/konsector.h')
-rw-r--r--kon/konsector.h133
1 files changed, 133 insertions, 0 deletions
diff --git a/kon/konsector.h b/kon/konsector.h
new file mode 100644
index 0000000..58a4ecb
--- /dev/null
+++ b/kon/konsector.h
@@ -0,0 +1,133 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * konsector.h
+ *
+ * Copyright (c) 2026 KonAki
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef KONSECTOR_H
+#define KONSECTOR_H
+
+#include <stddef.h>
+
+#include "konmath.h"
+
+/*** definition ***/
+
+/* a map is rooms seen from above. every room (sector) is a polygon of vertices with a floor and a ceiling height, and every
+ edge of the polygon is a wall. where two sectors share an edge it is an opening instead of a wall, and if their heights
+ differ there is a step or a lintel there. the plan is x going east and z going south, y is up like everywhere else.
+ a room cannot sit on top of another one */
+
+#define KON_NAME_LENGTH 24
+#define KON_ENTITY_PROPS 8
+
+typedef struct kon_sectorEdge {
+ int portal; /* the sector on the other side, -1 for a wall with nothing behind it */
+ int texture; /* index into the map's textures, -1 uses the sector's wall texture */
+} kon_sectorEdge_t;
+
+typedef struct kon_sector {
+ int first, count; /* where its corners start in indices and edges, and how many there are */
+ float floor, ceiling;
+ float light; /* 0 to 1, how bright the room is, 1 */
+ int floorTexture, ceilingTexture, wallTexture; /* -1 for none */
+} kon_sector_t;
+
+typedef struct kon_entityProp {
+ char key[16];
+ char value[32];
+} kon_entityProp_t;
+
+/* things placed in the map that are not walls: where you start, doors, buttons, lights. the engine only reads them,
+ what a kind does is up to the game. name and target are how things point at each other, a button with the target "door1"
+ is meant for the entity named "door1" */
+typedef struct kon_entity {
+ char kind[KON_NAME_LENGTH];
+ char name[KON_NAME_LENGTH];
+ char target[KON_NAME_LENGTH];
+ kon_vec3_t position;
+ float angle; /* radians, 0 faces north (towards -z) and it turns clockwise from above like the camera yaw */
+ int sector; /* the sector it is in, -1 if the position is outside every sector */
+ int propCount;
+ kon_entityProp_t props[KON_ENTITY_PROPS];
+} kon_entity_t;
+
+typedef struct kon_sectorMap {
+ int vertexCount;
+ kon_vec2_t *vertices; /* x, z */
+
+ /* the corners of a sector are indices[first] to indices[first + count - 1], counter clockwise seen from above.
+ edge n runs from corner n to corner n + 1 and the last one closes the loop */
+ int sectorCount;
+ kon_sector_t *sectors;
+ int indexCount;
+ int *indices;
+ kon_sectorEdge_t *edges;
+
+ int entityCount;
+ kon_entity_t *entities;
+
+ int textureCount;
+ char (*textures)[KON_NAME_LENGTH]; /* names only, the game decides what picture goes with each */
+} kon_sectorMap_t;
+
+/*** loading ***/
+
+/* reads a map from text. returns NULL and fills error (if it is not NULL) with something like "line 12: sector 2 has a ceiling below its floor".
+ a clockwise sector is turned around, anything else wrong is an error */
+kon_sectorMap_t *kon_sectorParse(const char *text, char *error, size_t errorSize);
+kon_sectorMap_t *kon_sectorLoad(const char *path, char *error, size_t errorSize);
+void kon_sectorFree(kon_sectorMap_t *map);
+
+/* the same text format, so a map can be edited in the game and saved. returns 0 on success */
+int kon_sectorSave(const kon_sectorMap_t *map, const char *path);
+
+/*** looking things up ***/
+
+/* the sector that holds the point, or -1. hint is a sector to try first (and its neighbours), pass -1 if you have none.
+ moving things should pass the sector they were in last frame, that makes this a few comparisons instead of a search */
+int kon_sectorAt(const kon_sectorMap_t *map, float x, float z, int hint);
+
+/* where corner n of a sector is */
+kon_vec2_t kon_sectorCorner(const kon_sectorMap_t *map, int sector, int n);
+
+/* the texture of an edge, the sector's own wall texture when the edge has none */
+int kon_sectorWallTexture(const kon_sectorMap_t *map, int sector, int edge);
+
+/* -1 if the name is not used in the map */
+int kon_sectorTextureIndex(const kon_sectorMap_t *map, const char *name);
+
+/*** entities ***/
+
+/* the first entity with this name, or -1 */
+int kon_entityFind(const kon_sectorMap_t *map, const char *name);
+
+/* fills out with the indices of every entity named like this, up to max, and returns how many there are in total.
+ this is how a button finds what it is for: ask for the entities named like its target */
+int kon_entityTargets(const kon_sectorMap_t *map, const char *name, int *out, int max);
+
+/* props are the key=value pairs written after the entity in the file. they are text, these read them as numbers */
+const char *kon_entityString(const kon_entity_t *entity, const char *key, const char *fallback);
+float kon_entityFloat(const kon_entity_t *entity, const char *key, float fallback);
+int kon_entityInt(const kon_entity_t *entity, const char *key, int fallback);
+
+#endif