315 lines
11 KiB
C
315 lines
11 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <math.h>
|
|
#include <stdbool.h>
|
|
#include <unistd.h>
|
|
#include <termios.h>
|
|
#include <limits.h>
|
|
#include <time.h>
|
|
|
|
#include "hash.h"
|
|
#include "structure.h"
|
|
#include "base.h"
|
|
#include "entities.h"
|
|
#include "proj.h"
|
|
#include "move.h"
|
|
|
|
// ---------------------------------------------------------------------------------------------------- //
|
|
double sensitivity = 0.06;
|
|
double fov = 90.0;
|
|
double creative_speed = 0.3;
|
|
double speed = 8.0;
|
|
double vtmult = 1.5;
|
|
double min_dist = 0.4;
|
|
double friction = 0.3;
|
|
double gravity_factor = 9.8;
|
|
// ---------------------------------------------------------------------------------------------------- //
|
|
|
|
bool is_clipping = false;
|
|
int clip_dps = 500;
|
|
|
|
int njumps;
|
|
double fx;
|
|
double fy;
|
|
double fz;
|
|
bool updateForces = false;
|
|
|
|
int player_hp;
|
|
|
|
bool stop_evetything;
|
|
|
|
double camx;
|
|
double camy;
|
|
double camz;
|
|
|
|
double camvx;
|
|
double camvy;
|
|
double camvz;
|
|
double rot_hz;
|
|
double rot_vt;
|
|
|
|
double tan_fov;
|
|
|
|
int draw_type;
|
|
int fade_dmg;
|
|
|
|
bool has_changed;
|
|
int collisionVal = 0;
|
|
|
|
double room_width;
|
|
double room_depth;
|
|
|
|
double sq2;
|
|
|
|
void init_csts() {
|
|
camx = 2.0;
|
|
camy = 5.0;
|
|
camz = 2.0;
|
|
camvx = 0.0;
|
|
camvy = 0.0;
|
|
camvz = 0.0;
|
|
rot_hz = 0.0;
|
|
rot_vt = 0.0;
|
|
draw_type = 0;
|
|
player_hp = 1000;
|
|
fade_dmg = 0;
|
|
room_width = 16.0;
|
|
room_depth = 16.0;
|
|
sq2 = sqrt(2);
|
|
njumps = 3;
|
|
stop_evetything = false;
|
|
tan_fov = tan((fov * 3.14159 / 180.0) / 2.0);
|
|
}
|
|
|
|
void set_player_coords(int old_chx, int old_chy) {
|
|
for(int k = 0; k < current_room->tps_size; k++) {
|
|
if(current_room->tps[k]->dest_chx == old_chx && current_room->tps[k]->dest_chy == old_chy) {
|
|
if(true) {
|
|
camx = current_room->tps[k]->hitbox->x + current_room->tps[k]->hitbox->w/2.0;
|
|
camy = current_room->tps[k]->hitbox->y + current_room->tps[k]->hitbox->h +1.5;
|
|
camz = current_room->tps[k]->hitbox->z + current_room->tps[k]->hitbox->d/2.0;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
pt_2d surface[3];
|
|
pt_2d directors[2];
|
|
pt_2d normal;
|
|
double p1, p2, p3;
|
|
void getSF(cube_0* cb, int sf) {
|
|
if(sf == 0 || sf == 1) {
|
|
project_to_cube(cb->x + (sf==0)*(cb->w), cb->y , cb->z , &p1, &p2, &p3, cb);
|
|
surface[0] = (pt_2d){.x = p1, .y = p2, .z = p3};
|
|
project_to_cube(cb->x + (sf==0)*(cb->w), cb->y + cb->h, cb->z , &p1, &p2, &p3, cb);
|
|
surface[1] = (pt_2d){.x = p1, .y = p2, .z = p3};
|
|
project_to_cube(cb->x + (sf==0)*(cb->w), cb->y , cb->z + cb->d, &p1, &p2, &p3, cb);
|
|
surface[2] = (pt_2d){.x = p1, .y = p2, .z = p3};
|
|
} else if(sf == 2 || sf == 3) {
|
|
project_to_cube(cb->x , cb->y + (sf==2)*(cb->h), cb->z , &p1, &p2, &p3, cb);
|
|
surface[0] = (pt_2d){.x = p1, .y = p2, .z = p3};
|
|
project_to_cube(cb->x + cb->w, cb->y + (sf==2)*(cb->h), cb->z , &p1, &p2, &p3, cb);
|
|
surface[1] = (pt_2d){.x = p1, .y = p2, .z = p3};
|
|
project_to_cube(cb->x , cb->y + (sf==2)*(cb->h), cb->z + cb->d, &p1, &p2, &p3, cb);
|
|
surface[2] = (pt_2d){.x = p1, .y = p2, .z = p3};
|
|
} else {
|
|
project_to_cube(cb->x , cb->y , cb->z + (sf==4)*(cb->d), &p1, &p2, &p3, cb);
|
|
surface[0] = (pt_2d){.x = p1, .y = p2, .z = p3};
|
|
project_to_cube(cb->x + cb->w, cb->y , cb->z + (sf==4)*(cb->d), &p1, &p2, &p3, cb);
|
|
surface[1] = (pt_2d){.x = p1, .y = p2, .z = p3};
|
|
project_to_cube(cb->x , cb->y + cb->h, cb->z + (sf==4)*(cb->d), &p1, &p2, &p3, cb);
|
|
surface[2] = (pt_2d){.x = p1, .y = p2, .z = p3};
|
|
}
|
|
}
|
|
|
|
void getDirectors() {
|
|
directors[0] = (pt_2d){.x = surface[1].x - surface[0].x, .y = surface[1].y - surface[0].y, .z = surface[1].z - surface[0].z};
|
|
directors[1] = (pt_2d){.x = surface[2].x - surface[0].x, .y = surface[2].y - surface[0].y, .z = surface[2].z - surface[0].z};
|
|
}
|
|
|
|
void getNormal() {
|
|
normal.x = directors[0].y*directors[1].z - directors[1].y*directors[0].z;
|
|
normal.y = -directors[0].z*directors[1].x + directors[1].z*directors[0].x;
|
|
normal.z = directors[0].x*directors[1].y - directors[1].x*directors[0].y;
|
|
double norm = sqrt(normal.x*normal.x + normal.y*normal.y + normal.z*normal.z);
|
|
normal.x /= norm;
|
|
normal.y /= norm;
|
|
normal.z /= norm;
|
|
}
|
|
|
|
void normalize(pt_2d* p) {
|
|
double norm = sqrt(p->x*p->x + p->y*p->y + p->z*p->z);
|
|
p->x /= norm;
|
|
p->y /= norm;
|
|
p->z /= norm;
|
|
}
|
|
|
|
void updateF(cube_0* cb, double dtime) {
|
|
for(int d = 0; d < 6; d++) {
|
|
cb->x -= min_dist;
|
|
cb->y -= min_dist;
|
|
cb->z -= min_dist;
|
|
cb->w += 2*min_dist;
|
|
cb->h += 2*min_dist;
|
|
cb->d += 2*min_dist;
|
|
getSF(cb, d);
|
|
cb->x += min_dist;
|
|
cb->y += min_dist;
|
|
cb->z += min_dist;
|
|
cb->w -= 2*min_dist;
|
|
cb->h -= 2*min_dist;
|
|
cb->d -= 2*min_dist;
|
|
getDirectors();
|
|
getNormal();
|
|
if(d%2==1) {
|
|
normal.x *= -1.0;
|
|
normal.y *= -1.0;
|
|
normal.z *= -1.0;
|
|
}
|
|
pt_2d vt = (pt_2d){.x = camx-camvx*dtime - surface[0].x, .y = camy-camvy*dtime - surface[0].y, .z = camz-camvz*dtime - surface[0].z};
|
|
pt_2d vtdt = (pt_2d){.x = camx - surface[0].x, .y = camy - surface[0].y, .z = camz - surface[0].z};
|
|
normalize(&vtdt);
|
|
normalize(&vt);
|
|
if(
|
|
(dot3D(vt, normal) <= 0.0 && dot3D(vtdt, normal) >= 0.0) ||
|
|
(dot3D(vt, normal) >= 0.0 && dot3D(vtdt, normal) <= 0.0)
|
|
) {
|
|
printf("%d\n", d);
|
|
double normv = sqrt(camvx*camvx + camvy*camvy + camvz*camvz);
|
|
|
|
double alpha = acos(dot3D(normal, (pt_2d){.x = camvx, .y = camvy, .z = camvz})/normv);
|
|
double beta = 3.1415926535 - 2*alpha;
|
|
double nu = sqrt(2)*normv*sqrt(1-cos(beta));
|
|
|
|
pt_2d u = (pt_2d){.x = normal.x*nu, .y = normal.y*nu, .z = normal.z*nu};
|
|
|
|
camvx += u.x;
|
|
camvy += u.y;
|
|
camvz += u.z;
|
|
|
|
camvx /= 1.41;
|
|
camvy /= 1.41;
|
|
camvz /= 1.41;
|
|
|
|
is_clipping = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool is_colliding(float dtime) {
|
|
for(int k = 0; k < current_room->map_size; k++) {
|
|
double dist = distance_pt_cube_0_3d_infinite(camx, camy, camz, current_room->map[k]);
|
|
if(dist <= min_dist) {
|
|
if(updateForces) {
|
|
updateF(current_room->map[k], (double)dtime);
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
for(int k = 0; k < current_room->tps_size; k++) {
|
|
double dist = distance_pt_cube_0_3d_infinite(camx, camy, camz, current_room->tps[k]->hitbox);
|
|
if(dist <= min_dist) {
|
|
if(updateForces) {
|
|
updateF(current_room->tps[k]->hitbox, (double)dtime);
|
|
}
|
|
int old_chx = player_chx;
|
|
int old_chy = player_chy;
|
|
player_chx = current_room->tps[k]->dest_chx;
|
|
player_chy = current_room->tps[k]->dest_chy;
|
|
current_room = hashtbl_find_opt(visited, player_chx, player_chy);
|
|
set_player_coords(old_chx, old_chy);
|
|
resetProj();
|
|
return true;
|
|
}
|
|
}
|
|
for(int k = 0; k < current_room->ent_len; k++) {
|
|
double dist = distance_pt_cube_0_3d_infinite(camx, camy, camz, current_room->ents[k]->pos);
|
|
if(dist <= min_dist) {
|
|
if(current_room->ents[k]->onHit != NULL) {
|
|
(*current_room->ents[k]->onHit)(dtime, current_room->ents[k]->hitpoints, ¤t_room->ents[k]->damage, current_room->ents[k], &(*(current_room->ents[k]->pos)));
|
|
if(*(current_room->ents[k]->hitpoints) <= 0) {
|
|
if(current_room->ents[k]->onDeath != NULL) {
|
|
(*current_room->ents[k]->onDeath)(dtime);
|
|
}
|
|
remove_entity(current_room->ents, ¤t_room->ent_memlen, ¤t_room->ent_len, k);
|
|
} else {
|
|
if(updateForces) {
|
|
updateF(current_room->ents[k]->pos, (double)dtime);
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void movePlayerG(float dtime) {
|
|
updateForces = true;
|
|
fx = 0.0;
|
|
fy = 0.0;
|
|
fz = 0.0;
|
|
|
|
camvy -= gravity_factor*dtime;
|
|
bool isfalling = camvy < 0.0;
|
|
|
|
double delx = camvx*dtime;
|
|
double dely = camvy*dtime;
|
|
double delz = camvz*dtime;
|
|
camx += delx;
|
|
camy += dely;
|
|
camz += delz;
|
|
is_clipping = true;
|
|
if(is_colliding(dtime)) {
|
|
if(is_clipping) {
|
|
player_hp -= (dtime)*clip_dps;
|
|
}
|
|
//printf("HIT\n");
|
|
//printf("[%lf, %lf, %lf]\n{%lf, %lf, %lf}\n\n", fx, fy, fz, camvx, camvy, camvz);
|
|
}
|
|
camx -= delx;
|
|
camy -= dely;
|
|
camz -= delz;
|
|
//printf("%lf | %lf | %lf\n", fx, fy, fz);
|
|
|
|
updateForces = false;
|
|
camvx += fx*dtime;
|
|
camvy += fy*dtime;
|
|
camvz += fz*dtime;
|
|
//printf("%lf | %lf | %lf\n\n", camvx, camvy, camvz);
|
|
if(isfalling && camvy > 0.0) {
|
|
njumps = 3;
|
|
}
|
|
camx += camvx*dtime;
|
|
camy += camvy*dtime;
|
|
camz += camvz*dtime;
|
|
|
|
camvx *= (1.0 - friction*((double)(dtime)));
|
|
camvz *= (1.0 - friction*((double)(dtime)));
|
|
}
|
|
|
|
void teleport_on_edge() {
|
|
if(camx >= room_width) {
|
|
camx -= 2.0*room_width;
|
|
player_chx += 1;
|
|
current_room = hashtbl_find_opt(visited, player_chx, player_chy);
|
|
resetProj();
|
|
} else if(camx <= -room_width) {
|
|
camx += 2.0*room_width;
|
|
player_chx -= 1;
|
|
current_room = hashtbl_find_opt(visited, player_chx, player_chy);
|
|
resetProj();
|
|
} else if(camz >= room_depth) {
|
|
camz -= 2.0*room_depth;
|
|
player_chy += 1;
|
|
current_room = hashtbl_find_opt(visited, player_chx, player_chy);
|
|
resetProj();
|
|
} else if(camz <= -room_depth) {
|
|
camz += 2.0*room_depth;
|
|
player_chy -= 1;
|
|
current_room = hashtbl_find_opt(visited, player_chx, player_chy);
|
|
resetProj();
|
|
}
|
|
} |