entity dir
This commit is contained in:
@@ -37,6 +37,17 @@ errorret_t sceneOverworldInit(void) {
|
||||
}
|
||||
|
||||
void sceneOverworldUpdate(void) {
|
||||
// Move camera to player.
|
||||
const entity_t *start = &testMap.entities[0];
|
||||
const entity_t *end = &testMap.entities[testMap.entityCount];
|
||||
while(start < end) {
|
||||
if(start->type == ENTITY_TYPE_PLAYER) {
|
||||
SCENE_OVERWORLD.camera.lookat.target[0] = start->position[0];
|
||||
SCENE_OVERWORLD.camera.lookat.target[1] = start->position[1];
|
||||
break;
|
||||
}
|
||||
start++;
|
||||
}
|
||||
}
|
||||
|
||||
void sceneOverworldRender(void) {
|
||||
@@ -69,6 +80,7 @@ void sceneOverworldRenderMap(const map_t *map) {
|
||||
assertNotNull(map, "Map pointer cannot be NULL");
|
||||
|
||||
// Draw base layer
|
||||
sceneOverworldRenderMapLayer(map, &map->base);
|
||||
|
||||
// Draw entities
|
||||
const entity_t *start = &map->entities[0];
|
||||
@@ -78,8 +90,10 @@ void sceneOverworldRenderMap(const map_t *map) {
|
||||
sceneOverworldRenderEntity(start);
|
||||
start++;
|
||||
}
|
||||
spriteBatchFlush();
|
||||
|
||||
// Draw overlay layer.
|
||||
sceneOverworldRenderMapLayer(map, &map->overlay);
|
||||
}
|
||||
|
||||
void sceneOverworldRenderEntity(const entity_t *entity) {
|
||||
@@ -88,7 +102,7 @@ void sceneOverworldRenderEntity(const entity_t *entity) {
|
||||
assertTrue(entity->type != ENTITY_TYPE_NULL, "Cannot have NULL entity type");
|
||||
|
||||
vec4 uv;
|
||||
tilesetTileGetUV(&TILESET_ENTITIES, 0, uv);
|
||||
tilesetPositionGetUV(&TILESET_ENTITIES, entity->direction, 0, uv);
|
||||
|
||||
// For now, just draw a placeholder quad.
|
||||
spriteBatchPush(
|
||||
@@ -101,7 +115,30 @@ void sceneOverworldRenderEntity(const entity_t *entity) {
|
||||
);
|
||||
}
|
||||
|
||||
void sceneOverworldRenderMapLayer(const map_t *map, const maplayer_t *layer) {
|
||||
assertNotNull(layer, "Map layer pointer cannot be NULL");
|
||||
|
||||
for(uint32_t y = 0; y < map->height; y++) {
|
||||
for(uint32_t x = 0; x < map->width; x++) {
|
||||
const tile_t *tile = &layer->tiles[y * map->width + x];
|
||||
if(tile->id == 0) continue;
|
||||
|
||||
spriteBatchPush(
|
||||
NULL,
|
||||
x * TILESET_ENTITIES.tileWidth,
|
||||
y * TILESET_ENTITIES.tileHeight,
|
||||
(x + 1) * TILESET_ENTITIES.tileWidth,
|
||||
(y + 1) * TILESET_ENTITIES.tileHeight,
|
||||
COLOR_RED,
|
||||
0, 0, 1, 1
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
spriteBatchFlush();
|
||||
}
|
||||
|
||||
void sceneOverworldDispose(void) {
|
||||
// Dispose of the overworld scene.
|
||||
if(testAsset) assetUnlock(testAsset, testAssetRef);
|
||||
}
|
||||
}
|
@@ -45,6 +45,14 @@ void sceneOverworldRenderMap(const map_t *map);
|
||||
*/
|
||||
void sceneOverworldRenderEntity(const entity_t *entity);
|
||||
|
||||
/**
|
||||
* Render a map layer in the overworld scene.
|
||||
*
|
||||
* @param map Pointer to the map the layer belongs to.
|
||||
* @param layer Pointer to the map layer to render.
|
||||
*/
|
||||
void sceneOverworldRenderMapLayer(const map_t *map, const maplayer_t *layer);
|
||||
|
||||
/**
|
||||
* Dispose of the overworld scene.
|
||||
*/
|
||||
|
@@ -7,4 +7,5 @@
|
||||
target_sources(${DUSK_TARGET_NAME}
|
||||
PRIVATE
|
||||
physicscircle.c
|
||||
physicsbox.c
|
||||
)
|
@@ -6,4 +6,5 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "physicscircle.h"
|
||||
#include "physicscircle.h"
|
||||
#include "physicsbox.h"
|
47
src/physics/physicsbox.c
Normal file
47
src/physics/physicsbox.c
Normal file
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "physicsbox.h"
|
||||
|
||||
void physicsBoxCheckBox(
|
||||
const physicsbox_t a,
|
||||
const physicsbox_t b,
|
||||
physicsboxboxresult_t *out
|
||||
) {
|
||||
float_t dx = (b.min[0] + b.max[0]) / 2.0f - (a.min[0] + a.max[0]) / 2.0f;
|
||||
float_t dy = (b.min[1] + b.max[1]) / 2.0f - (a.min[1] + a.max[1]) / 2.0f;
|
||||
float_t combinedHalfWidths = (a.max[0] - a.min[0]) / 2.0f + (b.max[0] - b.min[0]) / 2.0f;
|
||||
float_t combinedHalfHeights = (a.max[1] - a.min[1]) / 2.0f + (b.max[1] - b.min[1]) / 2.0f;
|
||||
|
||||
if (fabsf(dx) < combinedHalfWidths && fabsf(dy) < combinedHalfHeights) {
|
||||
out->hit = true;
|
||||
float_t overlapX = combinedHalfWidths - fabsf(dx);
|
||||
float_t overlapY = combinedHalfHeights - fabsf(dy);
|
||||
|
||||
if (overlapX < overlapY) {
|
||||
if (dx > 0) {
|
||||
out->normal[0] = 1.0f;
|
||||
out->normal[1] = 0.0f;
|
||||
} else {
|
||||
out->normal[0] = -1.0f;
|
||||
out->normal[1] = 0.0f;
|
||||
}
|
||||
out->depth = overlapX;
|
||||
} else {
|
||||
if (dy > 0) {
|
||||
out->normal[0] = 0.0f;
|
||||
out->normal[1] = 1.0f;
|
||||
} else {
|
||||
out->normal[0] = 0.0f;
|
||||
out->normal[1] = -1.0f;
|
||||
}
|
||||
out->depth = overlapY;
|
||||
}
|
||||
} else {
|
||||
out->hit = false;
|
||||
}
|
||||
}
|
33
src/physics/physicsbox.h
Normal file
33
src/physics/physicsbox.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "dusk.h"
|
||||
|
||||
typedef struct physicsbox_s {
|
||||
vec2 min;
|
||||
vec2 max;
|
||||
} physicsbox_t;
|
||||
|
||||
typedef struct physicsboxboxresult_s {
|
||||
bool_t hit;
|
||||
vec2 normal;
|
||||
float_t depth;
|
||||
} physicsboxboxresult_t;
|
||||
|
||||
/**
|
||||
* Check for collision between two boxes.
|
||||
*
|
||||
* @param a The first box.
|
||||
* @param b The second box.
|
||||
* @param out Pointer to the result structure to populate.
|
||||
*/
|
||||
void physicsBoxCheckBox(
|
||||
const physicsbox_t a,
|
||||
const physicsbox_t b,
|
||||
physicsboxboxresult_t *out
|
||||
);
|
@@ -9,4 +9,5 @@ target_sources(${DUSK_TARGET_NAME}
|
||||
entity.c
|
||||
npc.c
|
||||
player.c
|
||||
direction.c
|
||||
)
|
53
src/rpg/entity/direction.c
Normal file
53
src/rpg/entity/direction.c
Normal file
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "direction.h"
|
||||
#include "assert/assert.h"
|
||||
|
||||
float_t directionToAngle(const direction_t dir) {
|
||||
switch(dir) {
|
||||
case DIRECTION_NORTH: return (M_PI_2);
|
||||
case DIRECTION_SOUTH: return -(M_PI_2);
|
||||
case DIRECTION_EAST: return 0;
|
||||
case DIRECTION_WEST: return (M_PI);
|
||||
default: return 0; // Should never happen
|
||||
}
|
||||
}
|
||||
|
||||
void directionGetCoordinates(
|
||||
const direction_t dir,
|
||||
int8_t *x, int8_t *y
|
||||
) {
|
||||
assertNotNull(x, "X coordinate pointer cannot be NULL");
|
||||
assertNotNull(y, "Y coordinate pointer cannot be NULL");
|
||||
|
||||
switch(dir) {
|
||||
case DIRECTION_NORTH:
|
||||
*x = 0;
|
||||
*y = -1;
|
||||
break;
|
||||
|
||||
case DIRECTION_SOUTH:
|
||||
*x = 0;
|
||||
*y = 1;
|
||||
break;
|
||||
|
||||
case DIRECTION_EAST:
|
||||
*x = 1;
|
||||
*y = 0;
|
||||
break;
|
||||
|
||||
case DIRECTION_WEST:
|
||||
*x = -1;
|
||||
*y = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
assertUnreachable("Invalid direction");
|
||||
break;
|
||||
}
|
||||
}
|
41
src/rpg/entity/direction.h
Normal file
41
src/rpg/entity/direction.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "dusk.h"
|
||||
|
||||
typedef enum {
|
||||
DIRECTION_SOUTH = 0,
|
||||
DIRECTION_EAST = 1,
|
||||
DIRECTION_WEST = 2,
|
||||
DIRECTION_NORTH = 3,
|
||||
|
||||
DIRECTION_UP = DIRECTION_NORTH,
|
||||
DIRECTION_DOWN = DIRECTION_SOUTH,
|
||||
DIRECTION_LEFT = DIRECTION_WEST,
|
||||
DIRECTION_RIGHT = DIRECTION_EAST,
|
||||
} direction_t;
|
||||
|
||||
/**
|
||||
* Converts a direction to an angle in float_t format.
|
||||
*
|
||||
* @param dir The direction to convert.
|
||||
* @return The angle corresponding to the direction.
|
||||
*/
|
||||
float_t directionToAngle(const direction_t dir);
|
||||
|
||||
/**
|
||||
* Gets the relative coordinates for a given direction.
|
||||
*
|
||||
* @param dir The direction to get coordinates for.
|
||||
* @param x Pointer to store the x coordinate.
|
||||
* @param y Pointer to store the y coordinate.
|
||||
*/
|
||||
void directionGetCoordinates(
|
||||
const direction_t dir,
|
||||
int8_t *x, int8_t *y
|
||||
);
|
@@ -6,33 +6,98 @@
|
||||
*/
|
||||
|
||||
#include "entity.h"
|
||||
#include "rpg/world/map.h"
|
||||
#include "assert/assert.h"
|
||||
#include "util/memory.h"
|
||||
#include "display/tileset/tileset_entities.h"
|
||||
#include "time/time.h"
|
||||
#include "util/math.h"
|
||||
|
||||
entitycallback_t ENTITY_CALLBACKS[ENTITY_TYPE_COUNT] = {
|
||||
{ NULL, NULL }, // ENTITY_TYPE_NULL
|
||||
{ playerInit, playerUpdate }, // ENTITY_TYPE_PLAYER
|
||||
{ npcInit, npcUpdate}, // ENTITY_TYPE_NPC
|
||||
};
|
||||
|
||||
void entityInit(entity_t *entity, const entitytype_t type) {
|
||||
void entityInit(entity_t *entity, const entitytype_t type, map_t *map) {
|
||||
assertNotNull(entity, "Entity pointer cannot be NULL");
|
||||
assertNotNull(map, "Map pointer cannot be NULL");
|
||||
assertTrue(type < ENTITY_TYPE_COUNT, "Invalid entity type");
|
||||
assertTrue(type != ENTITY_TYPE_NULL, "Cannot have NULL entity type");
|
||||
assertNotNull(ENTITY_CALLBACKS[type].init, "Entity type has no init function");
|
||||
|
||||
memoryZero(entity, sizeof(entity_t));
|
||||
entity->type = type;
|
||||
entity->map = map;
|
||||
|
||||
ENTITY_CALLBACKS[type].init(entity);
|
||||
// Init. I did use a callback struct but it was not flexible enough.
|
||||
switch(type) {
|
||||
case ENTITY_TYPE_PLAYER:
|
||||
playerInit(entity);
|
||||
break;
|
||||
|
||||
case ENTITY_TYPE_NPC:
|
||||
npcInit(entity);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void entityUpdate(entity_t *entity) {
|
||||
assertNotNull(entity, "Entity pointer cannot be NULL");
|
||||
assertTrue(entity->type < ENTITY_TYPE_COUNT, "Invalid entity type");
|
||||
assertTrue(entity->type != ENTITY_TYPE_NULL, "Cannot have NULL entity type");
|
||||
assertNotNull(ENTITY_CALLBACKS[entity->type].update, "enttype lacks update");
|
||||
|
||||
ENTITY_CALLBACKS[entity->type].update(entity);
|
||||
// Handle movement logic
|
||||
switch(entity->type) {
|
||||
case ENTITY_TYPE_PLAYER:
|
||||
playerMovement(entity);
|
||||
break;
|
||||
|
||||
case ENTITY_TYPE_NPC:
|
||||
npcUpdate(entity);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Apply velocity
|
||||
if(entity->velocity[0] != 0.0f || entity->velocity[1] != 0.0f) {
|
||||
entity->position[0] += entity->velocity[0] * TIME.delta;
|
||||
entity->position[1] += entity->velocity[1] * TIME.delta;
|
||||
|
||||
// Hit test on other entities.
|
||||
entity_t *start = entity->map->entities;
|
||||
entity_t *end = &entity->map->entities[entity->map->entityCount];
|
||||
|
||||
// Our hitbox
|
||||
physicscircle_t self;
|
||||
glm_vec2_copy(entity->position, self.position);
|
||||
self.radius = TILESET_ENTITIES.tileWidth / 2.0f;
|
||||
|
||||
physicscircle_t other;
|
||||
other.radius = self.radius;
|
||||
|
||||
// TODO: what if multiple collisions?
|
||||
do {
|
||||
if(start == entity) continue;
|
||||
if(start->type == ENTITY_TYPE_NULL) continue;
|
||||
glm_vec2_copy(start->position, other.position);
|
||||
|
||||
physicscirclecircleresult_t result;
|
||||
physicsCircleCheckCircle(self, other, &result);
|
||||
|
||||
if(result.hit) {
|
||||
entity->position[0] -= result.normal[0] * result.depth;
|
||||
entity->position[1] -= result.normal[1] * result.depth;
|
||||
break;
|
||||
}
|
||||
} while((start++) != end);
|
||||
|
||||
// Friction (and dampening)
|
||||
entity->velocity[0] *= ENTITY_FRICTION * TIME.delta;
|
||||
entity->velocity[1] *= ENTITY_FRICTION * TIME.delta;
|
||||
if(mathAbs(entity->velocity[0]) < ENTITY_MIN_VELOCITY) {
|
||||
entity->velocity[0] = 0.0f;
|
||||
}
|
||||
if(mathAbs(entity->velocity[1]) < ENTITY_MIN_VELOCITY) {
|
||||
entity->velocity[1] = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
@@ -6,15 +6,15 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
// #include "direction.h"
|
||||
#include "direction.h"
|
||||
#include "rpg/entity/player.h"
|
||||
#include "npc.h"
|
||||
#include "physics/physics.h"
|
||||
|
||||
typedef struct {
|
||||
void (*init)(entity_t *entity);
|
||||
void (*update)(entity_t *entity);
|
||||
} entitycallback_t;
|
||||
#define ENTITY_FRICTION 0.9f
|
||||
#define ENTITY_MIN_VELOCITY 0.05f
|
||||
|
||||
typedef struct map_s map_t;
|
||||
|
||||
typedef enum {
|
||||
ENTITY_TYPE_NULL,
|
||||
@@ -25,9 +25,9 @@ typedef enum {
|
||||
} entitytype_t;
|
||||
|
||||
typedef struct entity_s {
|
||||
// uint32_t id;// Completely unique ID for this entity.
|
||||
map_t *map;
|
||||
entitytype_t type;
|
||||
// direction_t dir;
|
||||
direction_t direction;
|
||||
|
||||
vec2 position;
|
||||
vec2 velocity;
|
||||
@@ -38,15 +38,14 @@ typedef struct entity_s {
|
||||
};
|
||||
} entity_t;
|
||||
|
||||
extern entitycallback_t ENTITY_CALLBACKS[ENTITY_TYPE_COUNT];
|
||||
|
||||
/**
|
||||
* Initializes an entity structure.
|
||||
*
|
||||
* @param entity Pointer to the entity structure to initialize.
|
||||
* @param type The type of the entity.
|
||||
* @param map Pointer to the map the entity belongs to.
|
||||
*/
|
||||
void entityInit(entity_t *entity, const entitytype_t type);
|
||||
void entityInit(entity_t *entity, const entitytype_t type, map_t *map);
|
||||
|
||||
/**
|
||||
* Updates an entity.
|
||||
|
@@ -7,9 +7,7 @@
|
||||
|
||||
#include "entity.h"
|
||||
#include "assert/assert.h"
|
||||
#include "time/time.h"
|
||||
#include "input/input.h"
|
||||
|
||||
#include "display/scene/overworld/sceneoverworld.h"
|
||||
#include "display/tileset/tileset_entities.h"
|
||||
|
||||
@@ -17,36 +15,48 @@ void playerInit(entity_t *entity) {
|
||||
assertNotNull(entity, "Entity pointer cannot be NULL");
|
||||
}
|
||||
|
||||
void playerUpdate(entity_t *entity) {
|
||||
void playerMovement(entity_t *entity) {
|
||||
assertNotNull(entity, "Entity pointer cannot be NULL");
|
||||
|
||||
// testing only
|
||||
float_t move = TIME.delta * 64.0f; // tiles per second
|
||||
// Update velocity.
|
||||
vec2 dir = {
|
||||
inputAxis(INPUT_ACTION_LEFT, INPUT_ACTION_RIGHT),
|
||||
inputAxis(INPUT_ACTION_UP, INPUT_ACTION_DOWN)
|
||||
inputAxis(INPUT_ACTION_DOWN, INPUT_ACTION_UP)
|
||||
};
|
||||
if(dir[0] == 0 && dir[1] == 0) return;
|
||||
|
||||
glm_vec2_normalize(dir);
|
||||
entity->position[0] += move * dir[0];
|
||||
entity->position[1] -= move * dir[1];
|
||||
|
||||
SCENE_OVERWORLD.camera.lookat.target[0] = entity->position[0];
|
||||
SCENE_OVERWORLD.camera.lookat.target[1] = entity->position[1];
|
||||
|
||||
// Can we move?
|
||||
physicscircle_t npc = {
|
||||
.position = { 32.0f, 32.0f },
|
||||
.radius = TILESET_ENTITIES.tileWidth / 2.0f
|
||||
};
|
||||
|
||||
physicscircle_t self;
|
||||
glm_vec2_copy(entity->position, self.position);
|
||||
self.radius = npc.radius;
|
||||
|
||||
physicscirclecircleresult_t result;
|
||||
physicsCircleCheckCircle(self, npc, &result);
|
||||
if(result.hit) {
|
||||
entity->position[0] -= result.normal[0] * result.depth;
|
||||
entity->position[1] -= result.normal[1] * result.depth;
|
||||
entity->velocity[0] += PLAYER_SPEED * dir[0];
|
||||
entity->velocity[1] += PLAYER_SPEED * dir[1];
|
||||
|
||||
// Update direction.
|
||||
if(dir[0] > 0) {
|
||||
if(entity->direction == DIRECTION_RIGHT) {
|
||||
entity->direction = DIRECTION_RIGHT;
|
||||
} else {
|
||||
if(dir[1] < 0) {
|
||||
entity->direction = DIRECTION_UP;
|
||||
} else if(dir[1] > 0) {
|
||||
entity->direction = DIRECTION_DOWN;
|
||||
} else {
|
||||
entity->direction = DIRECTION_RIGHT;
|
||||
}
|
||||
}
|
||||
} else if(dir[0] < 0) {
|
||||
if(entity->direction == DIRECTION_LEFT) {
|
||||
entity->direction = DIRECTION_LEFT;
|
||||
} else {
|
||||
if(dir[1] < 0) {
|
||||
entity->direction = DIRECTION_UP;
|
||||
} else if(dir[1] > 0) {
|
||||
entity->direction = DIRECTION_DOWN;
|
||||
} else {
|
||||
entity->direction = DIRECTION_LEFT;
|
||||
}
|
||||
}
|
||||
} else if(dir[1] < 0) {
|
||||
entity->direction = DIRECTION_UP;
|
||||
} else if(dir[1] > 0) {
|
||||
entity->direction = DIRECTION_DOWN;
|
||||
}
|
||||
}
|
@@ -8,6 +8,8 @@
|
||||
#pragma once
|
||||
#include "dusk.h"
|
||||
|
||||
#define PLAYER_SPEED 64.0f
|
||||
|
||||
typedef struct entity_s entity_t;
|
||||
|
||||
typedef struct {
|
||||
@@ -22,8 +24,8 @@ typedef struct {
|
||||
void playerInit(entity_t *entity);
|
||||
|
||||
/**
|
||||
* Updates a player entity.
|
||||
* Handles movement logic for the player entity.
|
||||
*
|
||||
* @param entity Pointer to the entity structure to update.
|
||||
* @param entity Pointer to the player entity structure.
|
||||
*/
|
||||
void playerUpdate(entity_t *entity);
|
||||
void playerMovement(entity_t *entity);
|
@@ -13,12 +13,17 @@ map_t testMap;
|
||||
|
||||
void rpgInit() {
|
||||
mapInit(&testMap);
|
||||
testMap.width = 2;
|
||||
testMap.height = 2;
|
||||
for(uint32_t i = 0; i < testMap.width * testMap.height; i++) {
|
||||
testMap.base.tiles[i].id = 1;
|
||||
}
|
||||
|
||||
entity_t *ent = mapEntityAdd(&testMap);
|
||||
entityInit(ent, ENTITY_TYPE_PLAYER);
|
||||
entityInit(ent, ENTITY_TYPE_PLAYER, &testMap);
|
||||
|
||||
entity_t *npc = mapEntityAdd(&testMap);
|
||||
entityInit(npc, ENTITY_TYPE_NPC);
|
||||
entityInit(npc, ENTITY_TYPE_NPC, &testMap);
|
||||
npc->position[0] = 32.0f;
|
||||
npc->position[1] = 32.0f;
|
||||
}
|
||||
|
@@ -22,7 +22,7 @@ typedef struct {
|
||||
tile_t tiles[MAP_TILE_COUNT_MAX];
|
||||
} maplayer_t;
|
||||
|
||||
typedef struct {
|
||||
typedef struct map_s {
|
||||
entity_t entities[MAP_ENTITY_COUNT_MAX];
|
||||
uint8_t entityCount;
|
||||
|
||||
|
@@ -42,4 +42,12 @@ uint32_t mathNextPowTwo(uint32_t value);
|
||||
* @param upper The upper bound.
|
||||
* @return The clamped value.
|
||||
*/
|
||||
#define mathClamp(x, lower, upper) (mathMin(upper, mathMax(lower, x)))
|
||||
#define mathClamp(x, lower, upper) (mathMin(upper, mathMax(lower, x)))
|
||||
|
||||
/**
|
||||
* Returns the absolute value of a number.
|
||||
*
|
||||
* @param amt The number to get the absolute value of.
|
||||
* @return The absolute value of the number.
|
||||
*/
|
||||
#define mathAbs(amt) ((amt) < 0 ? -(amt) : (amt))
|
Reference in New Issue
Block a user