summaryrefslogtreecommitdiff
path: root/kon/konworld.h
blob: 4be1d1cd3a09be00604db760cc63928f488237e6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/* SPDX-License-Identifier: MIT */
/*
 * konworld.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 KONWORLD_H
#define KONWORLD_H

#include "konmath.h"
#include "kontile.h"
#include "kon3d.h"
#include "konsector.h"

/*** definition ***/

/* one place to ask "can I stand here, can I walk there" for everything a 3d game is built from: the rooms of a sector map,
   a terrain, a tilemap, and any shapes you add yourself. x and z are the plan, y is up. a world only points at the maps and the
   terrain, they stay yours and can change between frames. nothing here knows what a door or a monster is, a door is a box that
   the game moves */

#define KON_NO_GROUND (-1.0e30f)

typedef enum kon_colliderType {
	KON_COLLIDER_NONE = 0,
	KON_COLLIDER_BOX,      /* min and max, sides line up with the axes */
	KON_COLLIDER_CYLINDER, /* standing on the ground, center is the middle of its bottom */
	KON_COLLIDER_SPHERE,   /* blocks only, you can't stand on one */
	KON_COLLIDER_PLANE     /* everything behind the plane is solid. a plane that faces mostly up is a floor, a ramp if it is tilted */
} kon_colliderType_t;

typedef struct kon_collider {
	int type;
	int enabled; /* 0 and it is ignored, 1 */
	int user;    /* yours, like the entity this belongs to */
	kon_vec3_t min, max;       /* box */
	kon_vec3_t center;         /* cylinder, sphere */
	float radius, height;      /* cylinder, sphere (no height) */
	kon_vec3_t normal;         /* plane, the side it faces, length 1. points p with dot(normal, p) < offset are solid */
	float offset;
} kon_collider_t;

kon_collider_t kon_colliderBox(kon_vec3_t min, kon_vec3_t max);
kon_collider_t kon_colliderCylinder(kon_vec3_t bottom, float radius, float height);
kon_collider_t kon_colliderSphere(kon_vec3_t center, float radius);
kon_collider_t kon_colliderPlane(kon_vec3_t point, kon_vec3_t normal);

typedef struct kon_world {
	const kon_sectorMap_t *sectors;  /* any of these three can be NULL */
	const kon_terrain_t *terrain;
	const kon_tilemap_t *tiles;      /* one unit per tile like the rest of kon3d */
	const uint8_t *solid;            /* indexed by tile id like kon_tilemapMove */
	int solidCount;
	float tileHeight;                /* how tall the solid tiles are, 1 */

	kon_collider_t *colliders;
	int colliderCount, colliderCap;

	float gravity;   /* 20 */
	float stepHeight; /* the biggest step you walk up without jumping, 0.35 */
	float maxSlope;  /* rise over run you can climb on terrain, 1 is 45 degrees */
} kon_world_t;

/* a thing that walks. position is where the feet are, the body is a cylinder going up from there */
typedef struct kon_body {
	kon_vec3_t position;
	float radius, height; /* 0.2 and 1.0 are fine for a person in this scale */
	float vy;             /* up speed, only jumps and falls change it */
	int onGround;
	int sector;           /* the room it is in, -1 if none, kept up to date by kon_worldMove */
	int touching;         /* the collider it was pushed by in the last move, -1 if none. a monster hitting a door, say */
} kon_body_t;

/*** the world ***/

void kon_worldInit(kon_world_t *world);
void kon_worldFree(kon_world_t *world);

/* returns the index, or -1 if there is no memory. the index stays the same until the collider is removed */
int kon_worldAdd(kon_world_t *world, kon_collider_t collider);

/* NULL if the index is not a collider. change it any time, a door opens by raising min.y */
kon_collider_t *kon_worldCollider(kon_world_t *world, int index);
void kon_worldRemove(kon_world_t *world, int index);

/* the height of the highest thing to stand on at x, z that is not more than a step above feet, or KON_NO_GROUND outside the world.
   hint is the sector you were in, -1 if you have none. sector gets the room the point is in, it can be NULL */
float kon_worldGround(const kon_world_t *world, float x, float z, float feet, int hint, int *sector);

/*** bodies ***/

void kon_bodyInit(kon_body_t *body, float x, float y, float z, float radius, float height);
void kon_bodyJump(kon_body_t *body, float speed);

/* puts the feet on the ground under them right away */
void kon_worldPlace(const kon_world_t *world, kon_body_t *body);

/* moves by dx, dz and slides along whatever is in the way: walls, shapes, steps that are too high, slopes that are too steep, the edge
   of the world. then gravity: steps up are taken at once and drops are falls. dt is seconds */
void kon_worldMove(kon_world_t *world, kon_body_t *body, float dx, float dz, double dt);

#endif