370 lines
15 KiB
C++
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 |