Towers with lights

This commit is contained in:
Carlos Sanchez 2024-09-21 23:32:37 -04:00
parent ee8d4635fa
commit e4789d6156
3 changed files with 106 additions and 46 deletions

View File

@ -86,7 +86,7 @@ void gen_circle_model(haloo3d_obj *model, uint16_t color, int vertices) {
fastface2(model, circleuv, middle, lastv, firstv); fastface2(model, circleuv, middle, lastv, firstv);
} }
void gen_flower(haloo3d_obj *model, uint16_t color) { void gen_flower_model(haloo3d_obj *model, uint16_t color) {
haloo3d_obj_resetfixed(model, 2, 5); haloo3d_obj_resetfixed(model, 2, 5);
uint16_t vs[5]; uint16_t vs[5];
uint16_t col = COMCOL(model, color); uint16_t col = COMCOL(model, color);
@ -116,7 +116,7 @@ void gen_horibox(haloo3d_obj *model, uint16_t col, mfloat_t wid, mfloat_t bot,
} }
} }
void gen_tower(haloo3d_obj *model, uint16_t color) { void gen_tower_model(haloo3d_obj *model, uint16_t color) {
haloo3d_obj_resetfixed(model, 100, 100); haloo3d_obj_resetfixed(model, 100, 100);
uint16_t col = COMCOL(model, color); uint16_t col = COMCOL(model, color);
uint16_t top = COMVERT(model, 0, 1, 0); uint16_t top = COMVERT(model, 0, 1, 0);

141
terrain.c
View File

@ -77,6 +77,12 @@
#define REDFLOWERCOL 0xFF46 // 0xFF9A #define REDFLOWERCOL 0xFF46 // 0xFF9A
#define YELLOWFLOWERCOL 0xFEE0 #define YELLOWFLOWERCOL 0xFEE0
#define TOWERCOL 0xF111 #define TOWERCOL 0xF111
#define LIGHTCOL 0xFF00
#define TOWERLIGHTMINSIZE (CHUNKSCALE * 0.1)
#define TOWERLIGHTMAXSIZE (CHUNKSCALE * 0.5)
#define TOWERLIGHTMINTRANS 0
#define TOWERLIGHTMAXTRANS 0.4
#define TOWERLIGHTRATE 1.5
#define TREEBOTTOM -0.333 #define TREEBOTTOM -0.333
#define TREETRUNKWIDTH 0.2 #define TREETRUNKWIDTH 0.2
#define SEATRANS 0.75 #define SEATRANS 0.75
@ -102,6 +108,7 @@
{ .x = 0, .y = 0, .z = -1.5 } { .x = 0, .y = 0, .z = -1.5 }
#define RANDF() ((float)rand() / RAND_MAX) #define RANDF() ((float)rand() / RAND_MAX)
#define OFLOOR(v) (floor(fabs(v)) * ((v) < 0 ? -1 : 1))
// Some globals you can mess around with potentially // Some globals you can mess around with potentially
int fps = 60; int fps = 60;
@ -109,6 +116,7 @@ int fps = 60;
#define PALETTEKEY "palette" #define PALETTEKEY "palette"
#define TREEKEY "tree" #define TREEKEY "tree"
#define CLOUDKEY "cloud" #define CLOUDKEY "cloud"
#define LIGHTKEY "light"
#define REDFLOWERKEY "redflower" #define REDFLOWERKEY "redflower"
#define YELLOWFLOWERKEY "yellowflower" #define YELLOWFLOWERKEY "yellowflower"
#define TOWERKEY "tower" #define TOWERKEY "tower"
@ -134,8 +142,65 @@ static inline mfloat_t calc_barycentric(mfloat_t *point, mfloat_t *values,
return 0; return 0;
} }
uint16_t gen_terrain(struct vec3i pos, haloo3d_obj *model, void gen_tower(haloo3d_obj *model, haloo3d_obj *tower, tecs *ecs,
haloo3d_easystore *storage) { render_context *ctx, struct vec3i chunk, struct vec3 pos) {
const float scale = 0.5;
pos.x += 0.5;
pos.y += scale;
pos.z -= 0.5;
haloo3d_obj_addobj(model, tower, pos, (struct vec3)DEFAULTLOOK,
(struct vec3)DEFAULTUP,
(struct vec3){.x = scale, .y = scale, .z = scale});
// Put a nice little light on top
pos.y += scale;
haloo3d_obj *light = haloo3d_easystore_getobj(&ecs->storage, LIGHTKEY);
ecs_eid lightid = tecs_newentity(ecs, 0);
eprintf("LIGHTING SPAWN: %d (%d,%d)\n", lightid, chunk.x, chunk.z);
ECS_SETCOMPONENT(ecs, lightid, ecs_playergarbage){};
ECS_SETCOMPONENT(ecs, lightid, ecs_towerlight){.timer = 0};
ECS_SETCOMPONENT(ecs, lightid, ecs_placement){
.up = DEFAULTUP,
.lookvec = DEFAULTLOOK,
.pos = (struct vec3){.x = chunk.x + pos.x * CHUNKSCALE,
.y = pos.y * CHUNKSCALE * LANDHEIGHT,
.z = chunk.z + pos.z * CHUNKSCALE}};
ECS_SETCOMPONENT(ecs, lightid, ecs_object){
.flatdither = 0.2,
.texture = haloo3d_easystore_gettex(&ecs->storage, PALETTEKEY),
.scale = {.x = CHUNKSCALE, .y = CHUNKSCALE, .z = CHUNKSCALE},
.lighting = NULL, //&ecs->chunklight,
.stoplighting = 0,
.model = light,
.cullbackface = 0,
.context = {ctx},
.contextcount = 1};
}
void gen_cloud(render_context *ctx, tecs *ecs, struct vec3i pos) {
haloo3d_obj *cloud = haloo3d_easystore_getobj(&ecs->storage, CLOUDKEY);
ecs_eid cloudid = tecs_newentity(ecs, 0);
ECS_SETCOMPONENT(ecs, cloudid, ecs_playergarbage){};
ECS_SETCOMPONENT(ecs, cloudid,
ecs_placement){.up = DEFAULTUP,
.lookvec = DEFAULTLOOK,
.pos = {.x = pos.x + RANDF(),
.y = CLOUDHEIGHT + 0.5 * RANDF(),
.z = pos.z - 0.9}};
ECS_SETCOMPONENT(ecs, cloudid, ecs_object){
.flatdither = CLOUDTRANSMIN + (CLOUDTRANSMAX - CLOUDTRANSMIN) * RANDF(),
.texture = haloo3d_easystore_gettex(&ecs->storage, PALETTEKEY),
.scale = {.x = 1 + RANDF(), .y = 1.0 / CLOUDSTRETCH, .z = 1},
.lighting = NULL, //&ecs->chunklight,
.stoplighting = 0,
.model = cloud,
.cullbackface = 0,
.context = {ctx},
.contextcount = 1};
}
uint16_t gen_terrain(struct vec3i pos, haloo3d_obj *model, tecs *ecs,
render_context *ctx) {
haloo3d_easystore *storage = &ecs->storage;
eprintf("Generating terrain at %d,%d\n", pos.x, pos.z); eprintf("Generating terrain at %d,%d\n", pos.x, pos.z);
haloo3d_obj *tree = haloo3d_easystore_getobj(storage, TREEKEY); haloo3d_obj *tree = haloo3d_easystore_getobj(storage, TREEKEY);
haloo3d_obj *tower = haloo3d_easystore_getobj(storage, TOWERKEY); haloo3d_obj *tower = haloo3d_easystore_getobj(storage, TOWERKEY);
@ -234,15 +299,10 @@ uint16_t gen_terrain(struct vec3i pos, haloo3d_obj *model,
(struct vec3){.x = scale, .y = vertscale, .z = scale}); (struct vec3){.x = scale, .y = vertscale, .z = scale});
} }
} }
// 0..65 if (treecount == 0 && lowy > 0.75 && !gentower) {
if (treecount == 0 && lowy > 0.15 && !gentower) {
gentower = 1; gentower = 1;
haloo3d_obj_addobj(&nl_model, tower, gen_tower(&nl_model, tower, ecs, ctx, pos,
(struct vec3){.x = triedge[0].x + 0.5, (struct vec3){.x = triedge[0].x, .y = lowy, .z = triedge[0].y});
.y = lowy + 0.5,
.z = triedge[0].y - 0.5},
(struct vec3)DEFAULTLOOK, (struct vec3)DEFAULTUP,
(struct vec3){.x = 0.5, .y = 0.5, .z = 0.5});
} }
} }
uint16_t stoplighting = model->numfaces; uint16_t stoplighting = model->numfaces;
@ -250,30 +310,12 @@ uint16_t gen_terrain(struct vec3i pos, haloo3d_obj *model,
(struct vec3)DEFAULTLOOK, (struct vec3)DEFAULTUP, (struct vec3)DEFAULTLOOK, (struct vec3)DEFAULTUP,
(struct vec3){.x = 1, .y = 1, .z = 1}); (struct vec3){.x = 1, .y = 1, .z = 1});
haloo3d_obj_free(&nl_model); haloo3d_obj_free(&nl_model);
// Generate a cloud
if (RANDF() < CLOUDCHANCE)
gen_cloud(ctx, ecs, pos);
return stoplighting; return stoplighting;
} }
void gen_cloud(render_context *ctx, tecs *ecs, struct vec3i pos) {
haloo3d_obj *cloud = haloo3d_easystore_getobj(&ecs->storage, CLOUDKEY);
ecs_eid cloudid = tecs_newentity(ecs, 0);
ECS_SETCOMPONENT(ecs, cloudid, ecs_playergarbage){};
ECS_SETCOMPONENT(ecs, cloudid, ecs_placement){
.up = DEFAULTUP,
.lookvec = DEFAULTLOOK,
.pos = {
.x = pos.x + RANDF(), .y = CLOUDHEIGHT + 0.5 * RANDF(), .z = pos.z}};
ECS_SETCOMPONENT(ecs, cloudid, ecs_object){
.flatdither = CLOUDTRANSMIN + (CLOUDTRANSMAX - CLOUDTRANSMIN) * RANDF(),
.texture = haloo3d_easystore_gettex(&ecs->storage, PALETTEKEY),
.scale = {.x = 1 + RANDF(), .y = 1.0 / CLOUDSTRETCH, .z = 1},
.lighting = NULL, //&ecs->chunklight,
.stoplighting = 0,
.model = cloud,
.cullbackface = 1,
.context = {ctx},
.contextcount = 1};
}
// Generate the entity/components/terrain for the chunk at the given // Generate the entity/components/terrain for the chunk at the given
// coordinates. // coordinates.
// NOTE: chunks are per x/y tile (terrain inside is just scaled // NOTE: chunks are per x/y tile (terrain inside is just scaled
@ -285,7 +327,7 @@ void gen_chunk(render_context *ctx, tecs *ecs, struct vec3i pos) {
sprintf(garbage.dynmodel, "e%d", id); sprintf(garbage.dynmodel, "e%d", id);
haloo3d_obj *model = haloo3d_obj *model =
haloo3d_easystore_addobj(&ecs->storage, garbage.dynmodel); haloo3d_easystore_addobj(&ecs->storage, garbage.dynmodel);
uint16_t stoplighting = gen_terrain(pos, model, &ecs->storage); uint16_t stoplighting = gen_terrain(pos, model, ecs, ctx);
ECS_SETCOMPONENT(ecs, id, ecs_playergarbage) garbage; ECS_SETCOMPONENT(ecs, id, ecs_playergarbage) garbage;
ECS_SETCOMPONENT(ecs, id, ecs_chunk){.pos = pos}; ECS_SETCOMPONENT(ecs, id, ecs_chunk){.pos = pos};
ECS_SETCOMPONENT(ecs, id, ECS_SETCOMPONENT(ecs, id,
@ -304,15 +346,12 @@ void gen_chunk(render_context *ctx, tecs *ecs, struct vec3i pos) {
.cullbackface = 1, .cullbackface = 1,
.context = {ctx}, .context = {ctx},
.contextcount = 1}; .contextcount = 1};
// Generate a cloud
if (RANDF() < CLOUDCHANCE)
gen_cloud(ctx, ecs, pos);
} }
void player_chunkload(ecs_placement *ppos, render_context *ctx, tecs *ecs) { void player_chunkload(ecs_placement *ppos, render_context *ctx, tecs *ecs) {
struct vec3i pchunk = {.x = floor(ppos->pos.x), struct vec3i pchunk = {.x = OFLOOR(ppos->pos.x),
.y = floor(ppos->pos.y), .y = OFLOOR(ppos->pos.y),
.z = floor(ppos->pos.z)}; .z = OFLOOR(ppos->pos.z)};
// This is our little array of "filled chunks" around the player. We // This is our little array of "filled chunks" around the player. We
// use this to figure out what to generate // use this to figure out what to generate
ecs_eid surround[PLBOXEDGE][PLBOXEDGE] = {0}; ecs_eid surround[PLBOXEDGE][PLBOXEDGE] = {0};
@ -328,9 +367,9 @@ void player_chunkload(ecs_placement *ppos, render_context *ctx, tecs *ecs) {
ecs_object *obj = &ECS_GETCOMPONENT(ecs, matches[i], ecs_object); ecs_object *obj = &ECS_GETCOMPONENT(ecs, matches[i], ecs_object);
// If this object is outside the view distance, we no longer have access to // If this object is outside the view distance, we no longer have access to
// it // it
if (fabs(floor(placement->pos.x) - pchunk.x) > VIEWDISTANCE || if (fabs(OFLOOR(placement->pos.x) - pchunk.x) > VIEWDISTANCE ||
fabs(floor(placement->pos.z) - pchunk.z) > VIEWDISTANCE) { fabs(OFLOOR(placement->pos.z) - pchunk.z) > VIEWDISTANCE) {
// OK, reduce the chunk refcount, since we're no longer close to it // OK, reduce the item refcount, since we're no longer close to it
obj->contextcount--; obj->contextcount--;
lostobjects++; lostobjects++;
} }
@ -396,6 +435,17 @@ void sys_rendercontext(ecs_rendercontext *erc, ecs_placement *p, tecs **ecs) {
player_chunkload(p, rc, *ecs); player_chunkload(p, rc, *ecs);
} }
void sys_towerlight(ecs_towerlight *tl, tecs **ecs, ecs_object *o) {
tl->timer += (*ecs)->delta_s;
float ang = fabs(sin(tl->timer * TOWERLIGHTRATE));
o->flatdither =
TOWERLIGHTMINTRANS + (TOWERLIGHTMAXTRANS - TOWERLIGHTMINTRANS) * ang;
for (int i = 0; i < 3; i++) {
o->scale.v[i] =
TOWERLIGHTMINSIZE + (TOWERLIGHTMAXSIZE - TOWERLIGHTMINSIZE) * ang;
}
}
// Apply rotation to lookvec of placement, overrides lookvec // Apply rotation to lookvec of placement, overrides lookvec
void sys_rotation(ecs_placement *p, ecs_rotation *r) { void sys_rotation(ecs_placement *p, ecs_rotation *r) {
YAWP2VEC(r->yaw, r->pitch, p->lookvec.v); YAWP2VEC(r->yaw, r->pitch, p->lookvec.v);
@ -692,13 +742,15 @@ int main() { // int argc, char **argv) {
gen_tree_model(treemodel); gen_tree_model(treemodel);
haloo3d_obj *cloudmodel = haloo3d_easystore_addobj(&ecs.storage, CLOUDKEY); haloo3d_obj *cloudmodel = haloo3d_easystore_addobj(&ecs.storage, CLOUDKEY);
gen_circle_model(cloudmodel, CLOUDCOL, 32); gen_circle_model(cloudmodel, CLOUDCOL, 32);
haloo3d_obj *lightmodel = haloo3d_easystore_addobj(&ecs.storage, LIGHTKEY);
gen_circle_model(lightmodel, LIGHTCOL, 16);
haloo3d_obj *redflower = haloo3d_easystore_addobj(&ecs.storage, REDFLOWERKEY); haloo3d_obj *redflower = haloo3d_easystore_addobj(&ecs.storage, REDFLOWERKEY);
gen_flower(redflower, REDFLOWERCOL); gen_flower_model(redflower, REDFLOWERCOL);
haloo3d_obj *yellowflower = haloo3d_obj *yellowflower =
haloo3d_easystore_addobj(&ecs.storage, YELLOWFLOWERKEY); haloo3d_easystore_addobj(&ecs.storage, YELLOWFLOWERKEY);
gen_flower(yellowflower, YELLOWFLOWERCOL); gen_flower_model(yellowflower, YELLOWFLOWERCOL);
haloo3d_obj *tower = haloo3d_easystore_addobj(&ecs.storage, TOWERKEY); haloo3d_obj *tower = haloo3d_easystore_addobj(&ecs.storage, TOWERKEY);
gen_tower(tower, TOWERCOL); gen_tower_model(tower, TOWERCOL);
eprintf("Setup ECS system + obj/tex storage (%d bytes)\n", tecs_size); eprintf("Setup ECS system + obj/tex storage (%d bytes)\n", tecs_size);
@ -725,6 +777,7 @@ int main() { // int argc, char **argv) {
tecs); tecs);
ECS_RUNSYSTEM3(&ecs, sys_playergarbage, ecs_playergarbage, ecs_object, ECS_RUNSYSTEM3(&ecs, sys_playergarbage, ecs_playergarbage, ecs_object,
tecs); tecs);
ECS_RUNSYSTEM3(&ecs, sys_towerlight, ecs_towerlight, tecs, ecs_object);
haloo3d_easytimer_start(&drawtimer); haloo3d_easytimer_start(&drawtimer);
ECS_RUNSYSTEM3(&ecs, sys_renderobject, ecs_placement, ecs_object, tecs); ECS_RUNSYSTEM3(&ecs, sys_renderobject, ecs_placement, ecs_object, tecs);
haloo3d_easytimer_end(&drawtimer); haloo3d_easytimer_end(&drawtimer);

View File

@ -82,6 +82,11 @@ typedef struct {
// typedef ecs_placement *ecs_placement_lock; // typedef ecs_placement *ecs_placement_lock;
typedef struct {
// The data required to animate the tower light
float timer;
} ecs_towerlight;
// Movement is applied to placement and may also be used to check for // Movement is applied to placement and may also be used to check for
// collisions and whatever // collisions and whatever
typedef struct { typedef struct {
@ -144,6 +149,7 @@ ECS_COMPONENT(ecs_input)
ECS_COMPONENT(ecs_playergarbage) ECS_COMPONENT(ecs_playergarbage)
ECS_COMPONENT(ecs_chunk) ECS_COMPONENT(ecs_chunk)
ECS_COMPONENT(ecs_placement_lock) ECS_COMPONENT(ecs_placement_lock)
ECS_COMPONENT(ecs_towerlight)
ECS_END(tecs) ECS_END(tecs)
ECS_FN_INIT(tecs) ECS_FN_INIT(tecs)
@ -162,5 +168,6 @@ ECS_CID(ecs_input, 5)
ECS_CID(ecs_playergarbage, 6) ECS_CID(ecs_playergarbage, 6)
ECS_CID(ecs_chunk, 7) ECS_CID(ecs_chunk, 7)
ECS_CID(ecs_placement_lock, 8) ECS_CID(ecs_placement_lock, 8)
ECS_CID(ecs_towerlight, 9)
#endif #endif