becs/examples/example1/example1.c
2026-01-22 22:35:20 +08:00

129 lines
4.6 KiB
C

#define BECS_MAX_ENTITIES 100000
#define BECS_MAX_COMPONENTS 4
#define BECS_IMPLEMENTATION
#include "../../becs.h"
#include <stdlib.h>
#include <stdio.h>
#include "external/raylib/src/raylib.h"
// Component structs
typedef struct {
float x, y;
} Position;
typedef struct {
float vx, vy;
} Velocity;
typedef struct {
float ax, ay;
} Acceleration;
typedef struct {
float radius;
float lifetime;
} ParticleData;
// Function to spawn a particle
void SpawnParticle(BECS_ECS *ecs, BECS_ComponentID posID, BECS_ComponentID velID, BECS_ComponentID accID, BECS_ComponentID dataID, float x, float y) {
BECS_Entity entity = BECS_EntityCreate(ecs);
if (entity == BECS_NULL_ENTITY) return;
Position *pos = (Position *)BECS_ComponentAdd(ecs, entity, posID);
pos->x = x;
pos->y = y;
Velocity *vel = (Velocity *)BECS_ComponentAdd(ecs, entity, velID);
vel->vx = GetRandomValue(-100, 100);
vel->vy = GetRandomValue(-200, -50);
Acceleration *acc = (Acceleration *)BECS_ComponentAdd(ecs, entity, accID);
acc->ax = 0.0f;
acc->ay = 100.0f; // Gravity
ParticleData *data = (ParticleData *)BECS_ComponentAdd(ecs, entity, dataID);
data->radius = 5.0f;
data->lifetime = 2.0f;
}
int main(void) {
// Initialize ECS
size_t componentSizes[4] = {sizeof(Position), sizeof(Velocity), sizeof(Acceleration), sizeof(ParticleData)};
size_t memSize = BECS_GetMinMemoryArenaSize(componentSizes, 4);
printf("%lu\n", memSize);
char *memory = (char *)malloc(memSize);
BECS_ECS ecs = BECS_InitECS(memory, memSize);
// Register components
BECS_ComponentID posID = BECS_ComponentRegister(&ecs, sizeof(Position), BECS_MAX_ENTITIES);
BECS_ComponentID velID = BECS_ComponentRegister(&ecs, sizeof(Velocity), BECS_MAX_ENTITIES);
BECS_ComponentID accID = BECS_ComponentRegister(&ecs, sizeof(Acceleration), BECS_MAX_ENTITIES);
BECS_ComponentID dataID = BECS_ComponentRegister(&ecs, sizeof(ParticleData), BECS_MAX_ENTITIES);
InitWindow(1600, 800, "2D Particle System with BECS");
while (!WindowShouldClose()) {
float dt = GetFrameTime();
// Update lifetimes and despawn
for (BECS_Entity entity = 0; entity < BECS_MAX_ENTITIES; entity++) {
if (!BECS_IsEntityAlive(&ecs, entity)) continue;
if (BECS_ComponentHas(&ecs, entity, dataID)) {
ParticleData *data = (ParticleData *)BECS_ComponentGet(&ecs, entity, dataID);
data->lifetime -= dt;
if (data->lifetime <= 0.0f) {
BECS_EntityDestroy(&ecs, entity);
}
}
}
// Spawn particle on mouse click
if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) {
Vector2 mousePos = GetMousePosition();
for (uint32_t i = 0; i < 10; i++)
{
SpawnParticle(&ecs, posID, velID, accID, dataID, mousePos.x, mousePos.y);
}
}
// Physics system: update position and velocity
for (BECS_Entity entity = 0; entity < BECS_MAX_ENTITIES; entity++) {
if (!BECS_IsEntityAlive(&ecs, entity)) continue;
if (BECS_ComponentHas(&ecs, entity, posID) &&
BECS_ComponentHas(&ecs, entity, velID) &&
BECS_ComponentHas(&ecs, entity, accID)) {
Position *pos = (Position *)BECS_ComponentGet(&ecs, entity, posID);
Velocity *vel = (Velocity *)BECS_ComponentGet(&ecs, entity, velID);
Acceleration *acc = (Acceleration *)BECS_ComponentGet(&ecs, entity, accID);
vel->vx += acc->ax * dt;
vel->vy += acc->ay * dt;
pos->x += vel->vx * dt;
pos->y += vel->vy * dt;
}
}
BeginDrawing();
ClearBackground(BLACK);
// Render system: draw particles
for (BECS_Entity entity = 0; entity < BECS_MAX_ENTITIES; entity++) {
if (!BECS_IsEntityAlive(&ecs, entity)) continue;
if (BECS_ComponentHas(&ecs, entity, posID) && BECS_ComponentHas(&ecs, entity, dataID)) {
Position *pos = (Position *)BECS_ComponentGet(&ecs, entity, posID);
ParticleData *data = (ParticleData *)BECS_ComponentGet(&ecs, entity, dataID);
float alpha = data->lifetime / 2.0f;
Color color = {255, 255, 255, (unsigned char)(alpha * 255)};
DrawCircle((int)pos->x, (int)pos->y, data->radius, color);
}
}
DrawText(TextFormat("Particles: %u", ecs.entityCount), 10, 10, 20, WHITE);
EndDrawing();
}
CloseWindow();
free(memory);
return 0;
}