Files
CubeGame/src/helpers/entities.cpp
T
milkwx3 04d1969084
Build / build (push) Has been cancelled
Added day&night cycle. Also fixed world loading
2026-07-07 22:02:10 +03:00

370 lines
15 KiB
C++

#include <stdint.h>
#include <stdbool.h>
#include "common.hpp"
#include <cstring>
#include <list>
#include <raymath.h>
#include <iostream>
#include <rlgl.h>
#include <vector>
#include <algorithm>
#define PIXUNIT 1.0f / 16.0f
#ifndef SERVER
extern Camera camera;
extern Font fnt;
extern Texture2D terrain;
Texture2D playerTex;
Texture2D bomb;
Sound nekit_idle;
void EntitiesInit() {
playerTex = LoadTexture(Pathify("player.png"));
bomb = LoadTexture(Pathify("bomb.png"));
nekit_idle = LoadSound(Pathify("sound/nekit/idle.ogg"));
}
extern bool online;
extern Vector3 player_position;
extern Vector3 player_velocity;
void TakeDamage(float amount);
void SetBlockNetwork(World &world, int bx, int by, int bz, int t);
#else
bool online = true;
#endif
std::list<Entity> entities;
Entity NewEntity() {
Entity ent;
ent.id = entities.size();
ent.type = 0;
ent.yaw = 0;
ent.free = false;
return ent;
}
void AddEntity(Entity ent) {
entities.push_back(ent);
}
static void UpdateEntityPhysics(World &world, Entity& ent, float dt) {
Vector3 velocityTgt = Vector3Add(ent.velocity, {0, -dt * 20.0f, 0});
Vector3 tgt = Vector3Add(ent.position, Vector3Scale(velocityTgt, dt));
Vector3 final = ent.position;
if(!GetBlock(world, (int)tgt.x, (int)final.y, (int)final.z)) {
final.x = tgt.x;
}
if(!GetBlock(world, (int)final.x, (int)tgt.y, (int)final.z)) {
final.y = tgt.y;
}
else {
velocityTgt.y = 0;
}
if(!GetBlock(world, (int)final.x, (int)final.y, (int)tgt.z)) {
final.z = tgt.z;
}
ent.velocity = velocityTgt;
ent.position = final;
}
void UpdateEntities(World &world, float dt) {
if(entities.size() > 0) {
int idx = 0;
for(Entity& ent : entities) {
ent.smoothing = 0;
if(ent.type != 1) {
ent.lifetime += dt;
}
else {
ent.lifetime += dt * ent.data[1] / 255.0f;
if(ent.data[1]-4 >= 0) {
ent.data[1]-=4;
}
}
if(ent.damage_flash != 0) {
ent.damage_flash--;
}
if(ent.type == 2) {
Vector3 target = Vector3Zero();
#ifndef SERVER
target = player_position;
#endif
Vector3 direction = Vector3Normalize(Vector3Subtract(target, ent.position));
float degYaw = -atan2f(direction.z, direction.x) * RAD2DEG + 90;
if(GetRandomValue(0, 2000) == 0) {
MS_PlaySound(nekit_idle, GetRandomValue(75,125)/100.0f, 1.0f, ent.position);
}
ent.velocity = Vector3Add(ent.velocity, (Vector3){direction.x * 20.0f, 0, direction.z * 20.0f}*dt);
if(GetBlock(world, (int)ent.position.x, (int)ent.position.y-1, (int)ent.position.z) && GetRandomValue(0, 100) == 0) {
ent.velocity.y += 10.0f;
}
UpdateEntityPhysics(world, ent, dt);
if(Vector3Distance(target, ent.position) < 1.5f && ent.data[2] > 80) {
player_velocity += (Vector3){direction.x, 0, direction.z} * 30.0f;
player_velocity += {0, 2, 0};
ent.data[2] = 0;
TakeDamage(10.0f);
}
if(ent.health < 0.1f) {
ent.free = true;
}
if(ent.data[2] < 90)
ent.data[2]++;
ent.yaw = (unsigned short)(degYaw/360.0f*65535);
}
/*if(ent.type == 3) {
Vector3 velocityTgt = Vector3Clamp(Vector3Add(ent.velocity, {0, -dt * 20.0f, 0}), {-30.0f, -30.0f, -30.0f}, {30.0f, 30.0f, 30.0f});
Vector3 tgt = Vector3Add(ent.position, Vector3Scale(velocityTgt, dt));
Vector3 final = ent.position;
if(!GetBlock(world, (int)tgt.x, (int)final.y, (int)final.z)) {
final.x = tgt.x;
}
if(!GetBlock(world, (int)final.x, (int)tgt.y, (int)final.z)) {
final.y = tgt.y;
}
else {
velocityTgt.y = -velocityTgt.y / 2.0f;
velocityTgt = Vector3Scale(velocityTgt, 0.9f);
}
if(!GetBlock(world, (int)final.x, (int)final.y, (int)tgt.z)) {
final.z = tgt.z;
}
Entity* entp = &ent;
entp->yaw = 0;
entp->position = final;
entp->velocity = velocityTgt;
if(ent.lifetime > 5.0f) {
int radius = 3;
for (int x = -radius; x < radius; x++)
{
for (int y = -radius; y < radius; y++)
{
for (int z = -radius; z < radius; z++)
{
if(Vector3Distance({final.x + x, final.y + y, final.z + z}, final) <= radius) {
if(!CheckOOBWorld(final.x + x, final.y + y, final.z + z)) {
#ifndef SERVER
SetBlockNetwork(world, final.x + x, final.y + y, final.z + z, 0);
#endif
}
}
}
}
}
entp->free = true;
}
idx++;
}*/
if(ent.type == 4) {
Vector3 velocityTgt = Vector3Clamp(Vector3Add(ent.velocity, {0, -dt * 20.0f, 0}), {-30.0f, -30.0f, -30.0f}, {30.0f, 30.0f, 30.0f});
Vector3 tgt = Vector3Add(ent.position, Vector3Scale(velocityTgt, dt));
Vector3 final = ent.position;
bool hit = false;
if(!GetBlock(world, (int)tgt.x, (int)final.y, (int)final.z)) {
final.x = tgt.x;
}
else {
hit = true;
}
if(!GetBlock(world, (int)final.x, (int)tgt.y, (int)final.z)) {
final.y = tgt.y;
}
else {
hit = true;
}
if(!GetBlock(world, (int)final.x, (int)final.y, (int)tgt.z)) {
final.z = tgt.z;
}
else {
hit = true;
}
Entity* entp = &ent;
if(hit) {
SetBlockNetwork(world, (int)ent.position.x, (int)ent.position.y, (int)ent.position.z, ent.data[1]);
entp->free = true;
}
entp->yaw = 0;
entp->position = final;
entp->velocity = velocityTgt;
idx++;
}
}
auto match = [&](const Entity ent){
return ent.free;
};
auto it = std::find_if(entities.begin(), entities.end(), match);
if (it != entities.end()) {
entities.erase(it);
}
}
}
float globalCounter = 0;
#ifndef SERVER
void DrawEntities(float dt) {
globalCounter += dt;
for(Entity& ent : entities) {
ent.smoothing += dt;
if(ent.smoothing > TPS_DIV) {
ent.smoothing = 0;
}
Vector3 pos_lerped = Vector3Lerp(ent.position, Vector3Add(ent.position, ent.velocity*TPS_DIV), ent.smoothing * TPS);
if(ent.type == 0 || ent.type == 2) {
Color color = ColorLerp(WHITE, RED, ent.damage_flash / 50.0f);
Vector3 posLerp = Vector3Add(pos_lerped, {-0.5f, -0.1f, -0.5f});
float time = (ent.lifetime + ent.smoothing) * 4.0f;
float armWave0 = sinf(time * PI);
float armWave1 = -abs(cosf(time * PI));
float headWave = cosf(time * PI);
posLerp = Vector3Add(posLerp, {0, abs(sinf(time * PI)) * 0.1f, 0});
Vector3 headPivot = Vector3Add(posLerp, (Vector3){0, 16*PIXUNIT, 0});
float yaw = ent.yaw / 65535.0f * 360.0f;
rlColor4f(color.r, color.g, color.b, color.a);
rlPushMatrix();
rlTranslatef(posLerp.x, posLerp.y, posLerp.z); // move to model origin
rlRotatef(yaw, 0, 1, 0); // rotate around Y
rlTranslatef(-posLerp.x, -posLerp.y, -posLerp.z); // move back (optional depending on your pivots)
//
rlPushMatrix();
rlTranslatef(headPivot.x, headPivot.y, headPivot.z);
rlRotatef(25.0f * armWave0, 1, 0, 0);
rlRotatef(25.0f * headWave, 0, 0, 1);
// Head
DrawCubeTexture(playerTex, {0, 4*PIXUNIT, 0}, 8*PIXUNIT, 8*PIXUNIT, 8*PIXUNIT, WHITE, 8, 8, 8, 8);
rlPopMatrix();
Vector3 leftPivot = Vector3Add(posLerp, (Vector3){-6*PIXUNIT, 1.25f - 5*PIXUNIT, 0});
Vector3 rightPivot = Vector3Add(posLerp, (Vector3){6*PIXUNIT, 1.25f - 5*PIXUNIT, 0});
rlPushMatrix();
rlTranslatef(leftPivot.x, leftPivot.y, leftPivot.z);
rlRotatef(45.0f * armWave0, 1, 0, 0);
rlRotatef(45.0f * armWave1, 0, 0, 1);
DrawCubeTexture(playerTex, (Vector3){0, -6*PIXUNIT, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 44,20,4,4);
rlPopMatrix();
rlPushMatrix();
rlTranslatef(rightPivot.x, rightPivot.y, rightPivot.z);
rlRotatef(-45.0f * armWave0, 1, 0, 0);
rlRotatef(-45.0f * armWave1, 0, 0, 1);
DrawCubeTexture(playerTex, (Vector3){0, -6*PIXUNIT, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 44,20,4,4);
rlPopMatrix();
Vector3 body = Vector3Add(posLerp, {0, 1.25f - 10*PIXUNIT, 0});
rlPushMatrix();
rlTranslatef(body.x, body.y, body.z);
DrawCubeTexture(playerTex, Vector3Zero(), 8*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 20, 20, 8, 4);
rlPopMatrix();
leftPivot = Vector3Add(posLerp, (Vector3){-2*PIXUNIT, 1.25f - 14*PIXUNIT, 0});
rightPivot = Vector3Add(posLerp, (Vector3){2*PIXUNIT, 1.25f - 14*PIXUNIT, 0});
rlPushMatrix();
rlTranslatef(leftPivot.x, leftPivot.y, leftPivot.z);
rlRotatef(-45.0f * armWave0, 1, 0, 0);
DrawCubeTexture(playerTex, {0*PIXUNIT, -8*PIXUNIT, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 4, 20, 4, 4);
rlPopMatrix();
rlPushMatrix();
rlTranslatef(rightPivot.x, rightPivot.y, rightPivot.z);
rlRotatef(45.0f * armWave0, 1, 0, 0);
DrawCubeTexture(playerTex, {0*PIXUNIT, -8*PIXUNIT, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 4, 20, 4, 4);
rlPopMatrix();
rlPopMatrix();
}
if(ent.type == 1) {
Color color = WHITE;
Vector3 posLerp = Vector3Add(ent.position, {-0.5f, -0.1f, -0.5f});
float time = ent.lifetime * 4.0f;
float armWave0 = sinf(time * PI);
float armWave1 = -abs(cosf(time * PI));
float headWave = cosf(time * PI);
posLerp = Vector3Add(posLerp, {0, abs(sinf(time * PI)) * 0.1f, 0});
Vector3 headPivot = Vector3Add(posLerp, (Vector3){0, 16*PIXUNIT, 0});
float yaw = -ent.yaw / 65535.0f * 360.0f - 90;
rlPushMatrix();
rlTranslatef(posLerp.x, posLerp.y, posLerp.z);
rlRotatef(yaw, 0, 1, 0);
rlTranslatef(-posLerp.x, -posLerp.y, -posLerp.z);
//
rlPushMatrix();
rlTranslatef(headPivot.x, headPivot.y, headPivot.z);
rlRotatef(25.0f * armWave0, 1, 0, 0);
rlRotatef(25.0f * headWave, 0, 0, 1);
// Head
DrawCubeTexture(playerTex, {0, 4*PIXUNIT, 0}, 8*PIXUNIT, 8*PIXUNIT, 8*PIXUNIT, WHITE, 8, 8, 8, 8);
rlPopMatrix();
Vector3 leftPivot = Vector3Add(posLerp, (Vector3){-6*PIXUNIT, 1.25f - 5*PIXUNIT, 0});
Vector3 rightPivot = Vector3Add(posLerp, (Vector3){6*PIXUNIT, 1.25f - 5*PIXUNIT, 0});
rlPushMatrix();
rlTranslatef(leftPivot.x, leftPivot.y, leftPivot.z);
rlRotatef(45.0f * armWave0, 1, 0, 0);
rlRotatef(45.0f * armWave1, 0, 0, 1);
DrawCubeTexture(playerTex, (Vector3){0, -6*PIXUNIT, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 44,20,4,4);
rlPopMatrix();
rlPushMatrix();
rlTranslatef(rightPivot.x, rightPivot.y, rightPivot.z);
rlRotatef(-45.0f * armWave0, 1, 0, 0);
rlRotatef(-45.0f * armWave1, 0, 0, 1);
DrawCubeTexture(playerTex, (Vector3){0, -6*PIXUNIT, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 44,20,4,4);
rlPopMatrix();
Vector3 body = Vector3Add(posLerp, {0, 1.25f - 10*PIXUNIT, 0});
rlPushMatrix();
rlTranslatef(body.x, body.y, body.z);
DrawCubeTexture(playerTex, Vector3Zero(), 8*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 20, 20, 8, 4);
rlPopMatrix();
leftPivot = Vector3Add(posLerp, (Vector3){-2*PIXUNIT, 1.25f - 14*PIXUNIT, 0});
rightPivot = Vector3Add(posLerp, (Vector3){2*PIXUNIT, 1.25f - 14*PIXUNIT, 0});
rlPushMatrix();
rlTranslatef(leftPivot.x, leftPivot.y, leftPivot.z);
rlRotatef(-45.0f * armWave0, 1, 0, 0);
DrawCubeTexture(playerTex, {0*PIXUNIT, -8*PIXUNIT, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 4, 20, 4, 4);
rlPopMatrix();
rlPushMatrix();
rlTranslatef(rightPivot.x, rightPivot.y, rightPivot.z);
rlRotatef(45.0f * armWave0, 1, 0, 0);
DrawCubeTexture(playerTex, {0*PIXUNIT, -8*PIXUNIT, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 4, 20, 4, 4);
rlPopMatrix();
rlPopMatrix();
Vector3 dir = Vector3Subtract(camera.position, ent.position);
rlPushMatrix();
rlTranslatef(ent.position.x, ent.position.y + 1.5f, ent.position.z);
rlRotatef(atan2f(dir.x, dir.z) * RAD2DEG, 0.0f, 1.0f, 0.0f);
rlRotatef(90.0f, 1.0f, 0.0f, 0.0f);
char name[12];
sprintf(name, "Player %d", (int)ent.data[0]);
DrawText3D(fnt, name, {-MeasureTextEx(fnt, name, PIXUNIT * 4, 0).x * 1.5f, 0, 0}, PIXUNIT * 4, PIXUNIT, 1, true, WHITE);
rlPopMatrix();
}
if(ent.type == 3) {
DrawCube(pos_lerped, 1, 1, 1, RED);
}
if(ent.type == 4) {
DrawCubeBlock(terrain, pos_lerped, 1,1,1, GetBlockDefinition(ent.data[1]), WHITE);
}
}
}
#endif