Files
wolf/main.cpp

800 lines
28 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include <SDL3/SDL.h>
#include <vector>
#include <stdlib.h>
#include "jdebug.h"
#include "util.h"
#include "draw.h"
#include "wad.h"
#include <ctype.h>
#include <stdio.h>
#include <vector>
#include <unordered_map>
#include <stdexcept>
#include <algorithm>
#include "triggers.h"
#define FOV 277
std::vector<vec2> verts;
struct wall {
Uint16 v1 {0};
Uint16 v2 {0};
vec2 normal {0.0f, 0.0f};
float u1 {0.0f};
float u2 {0.0f};
float w1 {0.0f};
int portal {-1};
draw::surface_t *surf {nullptr};
draw::surface_t *upper_surf {nullptr};
draw::surface_t *lower_surf {nullptr};
};
struct sector {
float light;
float floor_height {0.0f};
float ceiling_height {64.0f};
draw::surface_t *floor_surf {nullptr};
draw::surface_t *ceil_surf {nullptr};
std::vector<wall> walls;
};
std::vector<sector> sectors;
int current_sector = 38;
int current_sector2 = 38;
vec2 position = { 1056.0f, 3616.0f };
//vec2 position = {975.0f, -3525.0f};
float orientation = 90.0f; //270.0f;
//float orientation = 180.0f;
float height = 41.0f;
float real_height = 41.0f;
float accel = 500.0f;
float speed = 0.0f;
float max_speed = 200.0f;
float rspeed = 200.0f;
float bobbing = 0.0f;
float dt;
Uint32 *palette;
//draw::surface_t *gif;
draw::surface_t *spr;
draw::surface_t *sky;
int drawColumn_count = 0;
uint8_t *colormap;
#pragma pack(push, 1)
struct sidedef {
int16_t xoffset;
int16_t yoffset;
char upper_texture[8];
char lower_texture[8];
char middle_texture[8];
int16_t sector;
};
#pragma pack(pop)
// ------------------------------------------------------------
// Área firmada de un contorno
// ------------------------------------------------------------
float signed_area(const std::vector<wall>& contour,
const std::vector<vec2>& verts)
{
float area = 0.0f;
for (size_t i = 0; i < contour.size(); i++) {
int a = contour[i].v1;
int b = contour[i].v2;
const vec2& p = verts[a];
const vec2& q = verts[b];
area += (p.x * q.y - q.x * p.y);
}
return area * 0.5f;
}
// ------------------------------------------------------------
// Extrae todos los contornos (ciclos) del sector
// ------------------------------------------------------------
std::vector<std::vector<wall>>
extract_contours(std::vector<wall> walls)
{
std::vector<std::vector<wall>> contours;
std::unordered_multimap<int,int> startMap;
for (int i = 0; i < (int)walls.size(); i++)
startMap.emplace(walls[i].v1, i);
std::vector<bool> used(walls.size(), false);
for (int i = 0; i < (int)walls.size(); i++) {
if (used[i]) continue;
std::vector<wall> contour;
int current = i;
contour.push_back(walls[current]);
used[current] = true;
int v = walls[current].v2;
while (true) {
auto range = startMap.equal_range(v);
int next = -1;
for (auto it = range.first; it != range.second; ++it) {
int idx = it->second;
if (!used[idx]) {
next = idx;
break;
}
}
if (next == -1)
break; // ciclo cerrado
contour.push_back(walls[next]);
used[next] = true;
v = walls[next].v2;
}
contours.push_back(contour);
}
return contours;
}
// ------------------------------------------------------------
// Ordena y fuerza sentido horario en contorno exterior
// ------------------------------------------------------------
void order_sector_walls_with_holes(sector& sector)
{
if (sector.walls.empty()) return;
// 1. Extraer contornos
auto contours = extract_contours(sector.walls);
// 2. Clasificar contornos por área
struct ContourInfo {
std::vector<wall> walls;
float area;
};
std::vector<ContourInfo> info;
info.reserve(contours.size());
for (auto& c : contours) {
float a = signed_area(c, verts);
info.push_back({c, a});
}
// 3. Encontrar el contorno exterior (el de mayor área absoluta)
int exteriorIndex = 0;
float maxAbsArea = std::abs(info[0].area);
for (int i = 1; i < (int)info.size(); i++) {
float absA = std::abs(info[i].area);
if (absA > maxAbsArea) {
maxAbsArea = absA;
exteriorIndex = i;
}
}
// 4. Forzar sentido horario en el contorno exterior
if (info[exteriorIndex].area < 0.0f) {
std::reverse(info[exteriorIndex].walls.begin(),
info[exteriorIndex].walls.end());
for (auto& w : info[exteriorIndex].walls)
std::swap(w.v1, w.v2);
}
// 5. Mantener agujeros en antihorario (o invertir si tu motor lo exige)
for (int i = 0; i < (int)info.size(); i++) {
if (i == exteriorIndex) continue;
// Si quieres agujeros en horario, descomenta:
/*
if (info[i].area < 0.0f) {
std::reverse(info[i].walls.begin(), info[i].walls.end());
for (auto& w : info[i].walls)
std::swap(w.v1, w.v2);
}
*/
}
// 6. Reconstruir la lista final de paredes
sector.walls.clear();
for (auto& c : info)
for (auto& w : c.walls)
sector.walls.push_back(w);
}
void loadMap(const char* name)
{
int size;
int16_t *vertices = (int16_t *)wad::load(name, "VERTEXES", &size);
const int num_vertices = size/4;
for (int i=0;i<num_vertices;++i)
verts.emplace_back(vec2{float(vertices[i*2]), -float(vertices[i*2+1])});
free(vertices);
uint8_t *sectors_lump = wad::load(name, "SECTORS", &size);
const int num_sectors = size/26;
uint8_t *s = sectors_lump;
for (int i=0;i<num_sectors;++i) {
sector sec;
sec.floor_height = *((int16_t*)s); s+=2;
sec.ceiling_height = *((int16_t*)s); s+=2;
char txt[9]; txt[8]=0;
for (int i=0;i<8;++i) txt[i] = toupper(*(s++));
sec.floor_surf = wad::loadFlat(txt);
for (int i=0;i<8;++i) txt[i] = toupper(*(s++));
sec.ceil_surf = (strcmp(txt, "F_SKY1")==0) ? nullptr : wad::loadFlat(txt);
//sec.light = *((int16_t*)s); s+=2;
sec.light = float(*((int16_t*)s))/256.0f;
s += 6;
sectors.push_back(sec);
}
free(sectors_lump);
uint8_t *sidedefs_lump = wad::load(name, "SIDEDEFS", &size);
int count = size / sizeof(struct sidedef);
struct sidedef* arr = (struct sidedef*)sidedefs_lump;
uint8_t *linedefs_lump = wad::load(name, "LINEDEFS", &size);
uint16_t *l = (uint16_t *)linedefs_lump;
size /= 14;
for (int i=0; i<size; ++i) {
const int16_t v1 = *(l++);
const int16_t v2 = *(l++);
l+=3;
const int16_t ld1 = *(l++);
const int16_t ld2 = *(l++);
const bool portal = (ld1 != -1) && (ld2 != -1);
if (ld1 != -1) {
wall w;
w.v1 = v1; w.v2 = v2;
w.portal = portal ? arr[ld2].sector : -1;
w.u1 = arr[ld1].xoffset;
w.w1 = arr[ld1].yoffset;
char txt[9]; txt[8]=0;
for (int i=0;i<8;++i) txt[i] = toupper(arr[ld1].middle_texture[i]);
if (txt[0]!='-') { w.surf = wad::loadTexture(txt); SDL_assert(w.surf); }
for (int i=0;i<8;++i) txt[i] = toupper(arr[ld1].lower_texture[i]);
if (txt[0]!='-') { w.lower_surf = wad::loadTexture(txt); SDL_assert(w.lower_surf); }
for (int i=0;i<8;++i) txt[i] = toupper(arr[ld1].upper_texture[i]);
if (txt[0]!='-') { w.upper_surf = wad::loadTexture(txt); SDL_assert(w.upper_surf); }
sectors[arr[ld1].sector].walls.push_back(w);
}
if (ld2 != -1) {
wall w;
w.v1 = v2; w.v2 = v1;
w.portal = portal ? arr[ld1].sector : -1;
w.u1 = arr[ld2].xoffset;
w.w1 = arr[ld2].yoffset;
char txt[9]; txt[8]=0;
for (int i=0;i<8;++i) txt[i] = toupper(arr[ld2].middle_texture[i]);
if (txt[0]!='-') { w.surf = wad::loadTexture(txt); SDL_assert(w.surf); }
for (int i=0;i<8;++i) txt[i] = toupper(arr[ld2].lower_texture[i]);
if (txt[0]!='-') { w.lower_surf = wad::loadTexture(txt); SDL_assert(w.lower_surf); }
for (int i=0;i<8;++i) txt[i] = toupper(arr[ld2].upper_texture[i]);
if (txt[0]!='-') { w.upper_surf = wad::loadTexture(txt); SDL_assert(w.upper_surf); }
sectors[arr[ld2].sector].walls.push_back(w);
}
}
free(linedefs_lump);
free(sidedefs_lump);
for (auto &s : sectors )
{
//order_sector_walls_with_holes(s);
for (auto &w : s.walls )
{
const int width = w.surf ? w.surf->w : w.upper_surf ? w.upper_surf->w : w.lower_surf ? w.lower_surf->w : 64;
SDL_assert(width>=0);
w.u1 /= width;
w.w1 /= width;
w.u2 = distance(verts[w.v1], verts[w.v2]) / width;
//w.v2 = distance(s.verts[w.v1], s.verts[w.v2]) / 32.0f;
vec2 norm = { verts[w.v2].x - verts[w.v1].x, verts[w.v2].y - verts[w.v1].y};
normalize(&norm);
const float tmp = norm.x; norm.x = -norm.y; norm.y = tmp;
w.normal = norm;
}
}
}
float light_zoom = 1280;
int actual_sector = -1;
int last_sector = -1;
void drawColumn(sector &s, int screen_column, int start, int end, float a_inc, vec2 origin, vec2 infi)
{
const float angle = orientation + a_inc;
vec2 normal = { SDL_cosf(angle*DEG_TO_RAD), SDL_sinf(angle*DEG_TO_RAD) };
vec2 result, tmp_result;
wall *w = nullptr;
float stright_dist=100000.0f;
for (auto &wall : s.walls)
{
if (dot(normal, wall.normal) >= 0) continue;
if (get_line_intersection(origin, infi, verts[wall.v1], verts[wall.v2], &tmp_result))
{
if ( (origin.x==tmp_result.x) && (origin.y==tmp_result.y) ) continue;
const float d = distance(position, tmp_result);// * SDL_cosf(a_inc*DEG_TO_RAD);
if (d<stright_dist) {
stright_dist = d;
result = tmp_result;
w = &wall;
}
}
}
if (w)
{
//const int tex_height = gif->h; //64;
const float sector_height = s.ceiling_height - s.floor_height;
if (sector_height == 0) return;
const int width = w->surf ? w->surf->w : w->upper_surf ? w->upper_surf->w : w->lower_surf ? w->lower_surf->w : 64;
draw::map::putp(result.x, result.y, 6);
float dist = stright_dist * SDL_cosf(a_inc*DEG_TO_RAD);
const vec2 AB = {verts[w->v2].x-verts[w->v1].x, verts[w->v2].y-verts[w->v1].y};
const vec2 AP = {result.x-verts[w->v1].x, result.y-verts[w->v1].y};
float v = dot(AP,AB) / dot(AB,AB); v = (v+w->u1) * w->u2; v = v*width; //w->surf->w; //(v-int(v))*gif->w;
float wall_height = (sector_height*FOV)/dist; // [64=altura sector]
float wall_cut = 0.0f;
float dpix = sector_height/wall_height; // [64=crec que altura sector]
float cpix = 0; //triggers::isEnabled("offsets") ? w->surf->h*w->w1 : 0;
float wall_start = 120-(wall_height/sector_height)*(sector_height-(height-s.floor_height)); // [64=els dos crec que altura sector]
if (wall_start<start) {
wall_cut = start-wall_start;
cpix += wall_cut;
wall_height -= wall_cut;
wall_start=start;
}
cpix *= dpix;
// Pinta el sostre
if (s.ceil_surf) { // No el pintes si es el cel
for (int y=start; y<wall_start-1; y++) {
float straight_dist = (FOV * (sector_height-(height-s.floor_height))) / (y - (240 >> 1));
float actual_dist = straight_dist / SDL_cosf(a_inc*DEG_TO_RAD);
int tx = SDL_abs(int(actual_dist * SDL_cosf(angle*DEG_TO_RAD) - position.x)) % s.ceil_surf->w;
int ty = SDL_abs(int(actual_dist * SDL_sinf(angle*DEG_TO_RAD) - position.y)) % s.ceil_surf->h;
float light_dist = 1.0f - (-actual_dist>light_zoom ? 1.0f : -actual_dist/light_zoom);
float light = 1.0f - (light_dist*s.light);
uint8_t pixcolor = s.ceil_surf->pixels[tx+ty*s.ceil_surf->w];
pixcolor = colormap[pixcolor + int(light*31)*256];
draw::putpd(screen_column, y, pixcolor, -straight_dist);
}
}
if (w->portal == -1)
{
// Pinta la pared
draw::surface_t *surf = w->surf;
float tex_height = (surf->h*FOV)/dist; // [64=altura sector]
if (triggers::isEnabled("offsets")) cpix += tex_height * w->w1 * dpix;
if (surf) {
for (int i=0; i<wall_height; ++i) {
if (wall_start+i>=end) break;
float light_dist = 1.0f - (dist>light_zoom ? 1.0f : dist/light_zoom);
float light = 1.0f - (light_dist*s.light);
uint8_t pixcolor = surf->pixels[(int(v)%surf->w)+(int(cpix)%surf->h)*surf->w];
pixcolor = colormap[pixcolor + int(light*31)*256];
draw::putpd(screen_column, wall_start+i, pixcolor, stright_dist);
cpix += dpix;
}
}
} else {
if ((sectors[w->portal].ceiling_height < s.ceiling_height) && sectors[w->portal].ceil_surf)
{
float upper_height = s.ceiling_height - sectors[w->portal].ceiling_height;
float upper_wall_height = (upper_height*FOV)/dist;
upper_wall_height -= wall_cut;
if (upper_wall_height>0.0f)
{
// Pinta la pared
if (w->upper_surf)
for (int i=0; i<upper_wall_height; ++i) {
if (wall_start+i>=end) break;
float light_dist = 1.0f - (dist>light_zoom ? 1.0f : dist/light_zoom);
float light = 1.0f - (light_dist*s.light);
uint8_t pixcolor = w->upper_surf->pixels[(int(v)%w->upper_surf->w)+(int(cpix)%w->upper_surf->h)*w->upper_surf->w];
pixcolor = colormap[pixcolor + int(light*31)*256];
draw::putpd(screen_column, wall_start+i, pixcolor, stright_dist);
cpix += dpix;
}
wall_start += upper_wall_height;
wall_height -= upper_wall_height;
}
}
float lower_height = sectors[w->portal].floor_height - s.floor_height;
float lower_wall_height = (lower_height*FOV)/dist;
int wall_end = wall_start+wall_height+1;
if (lower_wall_height>0.0f) wall_end -= lower_wall_height;
wall_end = SDL_min(wall_end, end);
//SDL_assert(&s != &sectors[w->portal]);
//printf("Anem al sector: %i\n", w->portal);
//SDL_assert(w->portal != last_sector);
last_sector = actual_sector;
actual_sector = w->portal;
drawColumn_count++;
if (drawColumn_count>50) {
printf("drawColumn() loop overflow. Sectors: %i adn %i\n", last_sector, actual_sector);
SDL_assert(false);
}
drawColumn(sectors[w->portal], screen_column, wall_start, wall_end, a_inc, result, infi);
if (lower_wall_height>0.0f)
{
cpix += (wall_height-lower_wall_height)*dpix;
// Pinta la pared
if (w->lower_surf)
for (int i=0; i<lower_wall_height; ++i) {
if (wall_end+i>=end) break;
float light_dist = 1.0f - (dist>light_zoom ? 1.0f : dist/light_zoom);
float light = 1.0f - (light_dist*s.light);
uint8_t pixcolor = w->lower_surf->pixels[(int(v)%w->lower_surf->w)+(int(cpix)%w->lower_surf->h)*w->lower_surf->w];
pixcolor = colormap[pixcolor + int(light*31)*256];
draw::putpd(screen_column, wall_end+i, pixcolor, stright_dist);
cpix += dpix;
}
//wall_start += upper_wall_height;
//wall_height -= upper_wall_height;
}
}
// Pinta el piso
int paint_end = wall_start+wall_height-1;
for (int y=paint_end+1; y<end-1; y++) {
float straight_dist = (FOV * (height-s.floor_height)) / (y - (240 >> 1));
float actual_dist = straight_dist / SDL_cosf(a_inc*DEG_TO_RAD);
int tx = SDL_abs(int(actual_dist * SDL_cosf(angle*DEG_TO_RAD) + position.x)) % s.floor_surf->w;
int ty = SDL_abs(int(actual_dist * SDL_sinf(angle*DEG_TO_RAD) + position.y)) % s.floor_surf->h;
float light_dist = (actual_dist>light_zoom ? 1.0f : actual_dist/light_zoom);
float light = 1.0f - SDL_clamp(s.light-light_dist, 0.0f, 1.0f);
uint8_t pixcolor = s.floor_surf->pixels[tx+ty*s.floor_surf->w];
pixcolor = colormap[pixcolor + int(light*31)*256];
draw::putpd(screen_column, y, pixcolor, straight_dist);
}
//line(screen_column, 120-(wall_height), screen_column, 120+(wall_height), 5);
}
}
bool tryMove(float angle, float speed)
{
float sign = speed > 0 ? 1.0f : -1.0f;
bool moved = false;
sector &s = sectors[current_sector];
int come_from = current_sector;
vec2 newpos = { position.x + SDL_cosf(angle*DEG_TO_RAD)*5*sign, position.y };
bool collision=false;
for (auto w : s.walls) {
if (get_line_intersection(position, newpos, verts[w.v1], verts[w.v2], NULL))
{
if (w.portal != -1) {
newpos.x = position.x + SDL_cosf(angle*DEG_TO_RAD)*dt*speed;
if (get_line_intersection(position, newpos, verts[w.v1], verts[w.v2], NULL) ) {
current_sector = w.portal;
real_height = sectors[current_sector].floor_height+41.0f;
}
} else {
collision=true;
}
break;
}
}
if (!collision)
{ moved = true; position.x += SDL_cosf(angle*DEG_TO_RAD)*dt*speed; }
newpos = { position.x, position.y + SDL_sinf(angle*DEG_TO_RAD)*5*sign };
collision=false;
for (auto w : s.walls) {
if (get_line_intersection(position, newpos, verts[w.v1], verts[w.v2], NULL))
{
if (w.portal != -1) {
newpos.y = position.y + SDL_sinf(angle*DEG_TO_RAD)*dt*speed;
if (get_line_intersection(position, newpos, verts[w.v1], verts[w.v2], NULL) )
if (w.portal != come_from) {
current_sector = w.portal;
real_height = sectors[current_sector].floor_height+41.0f;
}
} else {
collision=true;
}
break;
}
}
if (!collision)
{ moved = true; position.y += SDL_sinf(angle*DEG_TO_RAD)*dt*speed; }
return moved;
}
// angle is in degrees (0359), increasing clockwise like Doom.
// sky is your loaded surface_t containing the sky texture.
// screen_w = 320, screen_h = 240.
void draw_sky(draw::surface_t *sky, float angle_deg)
{
// Convert angle to a horizontal texture offset.
// Doom uses a bitshift, but this is equivalent:
// scroll = angle * (sky->w / 360)
float scroll_f = angle_deg * (sky->w / 360.0f);
int scroll = (int)scroll_f;
for (int y = 0; y < 240; y++)
{
// Map screen Y to sky Y.
// Doom's sky is not perspective-correct; it simply stretches vertically.
int ty = (y * sky->h) / 240;
for (int x = 0; x < 320; x++)
{
// Horizontal wrap-around
int tx = (x + scroll) % sky->w;
if (tx < 0) tx += sky->w;
uint8_t color = sky->pixels[ty * sky->w + tx];
draw::putp(x, y, color);
}
}
}
int main(int argc, char *argv[])
{
wad::init("doom1.wad");
int len;
colormap = wad::load("COLORMAP");
draw::init();
//gif = draw::loadgif("walls.gif");
//gif = wad::loadFlat("FLOOR4_8");
//gif = wad::loadTexture("BROWNPIP");
//gif = wad::loadPatch("LADDER16");
//palette = draw::loadpal("walls.gif");
palette = wad::loadPalette(0);
draw::setpal(palette);
spr = draw::loadgif("player1.gif");
sky = wad::loadTexture("SKY1");
// [DEBUG] Paleta per al depth buffer
//for(int i=0;i<256;++i) palette[i] = (255-i) | ((255-i)<<8) | ((255-i)<<16);
//createMap();
loadMap("E1M1");
SDL_Event e;
bool should_exit = false;
Uint32 millis = SDL_GetTicks();
int fps = 0;
int fps_count = 0;
int fps_time = SDL_GetTicks();
while (!should_exit)
{
dt = float(SDL_GetTicks() - millis)/1000.0f;
millis = SDL_GetTicks();
bobbing += dt*1000.0f;
height = real_height + SDL_sinf(bobbing*DEG_TO_RAD)*(speed/100.0f);
uint8_t key_pressed = SDL_SCANCODE_UNKNOWN;
while (SDL_PollEvent(&e))
{
if (e.type==SDL_EVENT_QUIT) { should_exit=true; break; }
if (e.type==SDL_EVENT_KEY_DOWN && e.key.scancode==SDL_SCANCODE_ESCAPE) { should_exit=true; break; }
if (e.type==SDL_EVENT_KEY_UP) key_pressed = e.key.scancode;
if (e.type==SDL_EVENT_MOUSE_WHEEL) {
if (e.wheel.y>0) current_sector2++; else current_sector2--;
printf("Current sector: %i\n", current_sector2);
}
}
const bool *keys = SDL_GetKeyboardState(NULL);
if (keys[SDL_SCANCODE_Q])
{
real_height += dt*100.0f;
}
if (keys[SDL_SCANCODE_A])
{
real_height -= dt*100.0f;
}
if (keys[SDL_SCANCODE_W])
{
//real_height += dt*100.0f;
sectors[0].ceiling_height -= dt*100.0f;
sectors[1].ceiling_height -= dt*100.0f;
sectors[0].floor_height -= dt*100.0f;
sectors[1].floor_height -= dt*100.0f;
}
if (keys[SDL_SCANCODE_S])
{
//real_height -= dt*100.0f;
sectors[0].ceiling_height += dt*100.0f;
sectors[1].ceiling_height += dt*100.0f;
sectors[0].floor_height += dt*100.0f;
sectors[1].floor_height += dt*100.0f;
}
if (key_pressed == SDL_SCANCODE_M) { triggers::toggle("minimap"); }
if (key_pressed == SDL_SCANCODE_O) { triggers::toggle("offsets"); }
if (keys[SDL_SCANCODE_RIGHT])
{
orientation += dt*rspeed;
}
else if (keys[SDL_SCANCODE_LEFT])
{
orientation -= dt*rspeed;
}
if (keys[SDL_SCANCODE_UP])
{
if (speed < max_speed) speed += dt*accel;
}
else if (keys[SDL_SCANCODE_DOWN])
{
if (speed > -max_speed) speed -= dt*accel;
}
else
{
if (speed > 0.0f) { speed -= dt*accel; if (speed < 0.0f) speed = 0.0f; }
if (speed < 0.0f) { speed += dt*accel; if (speed > 0.0f) speed = 0.0f; }
}
if (speed != 0.0f) if (!tryMove(orientation, speed)) speed = 0.0f;
draw::cls();
draw_sky(sky, orientation);
sector &s = sectors[current_sector];
actual_sector = current_sector;
//printf("Current sector: %i\n", current_sector);
// Clear screen
//SDL_memset4(screen, 0x00000000, (320*240)>>2);
int screen_column = 0;
for (float a_inc=-32.0f; a_inc<=32.0f; a_inc+=0.2f)
{
drawColumn_count = 0;
last_sector = -1;
const float angle = orientation + a_inc;
vec2 infi;
infi.x = position.x + SDL_cosf(angle*DEG_TO_RAD)*40000;
infi.y = position.y + SDL_sinf(angle*DEG_TO_RAD)*40000;
//printf("Column %i...\n", screen_column);
drawColumn(s, screen_column, 0, 240, a_inc, position, infi);
screen_column++;
}
debug::print("angle:");debug::print(orientation);debug::newline();
vec2 enemy = {256.0f, 256.0f};
draw::map::putp(enemy.x, enemy.y, 9);
float angle_to_enemy = is_enemy_in_fov(position.x, position.y, orientation, enemy.x, enemy.y);
if (SDL_fabsf(angle_to_enemy) <= 64.0f)
{
const float d = distance(position, enemy);// * SDL_cosf(a_inc*DEG_TO_RAD);
float dist = d * SDL_cosf(angle_to_enemy*DEG_TO_RAD);
float wall_height = (32.0f*FOV)/dist;
float wall_start = 120-(wall_height/32.0f)*(32.0f-(height-sectors[0].floor_height));
debug::println("enemy height: ", wall_height);
debug::println("enemy start: ", wall_start);
int column = int((angle_to_enemy+32.0f)/0.2f);
for (int i=0; i<wall_height;++i)
{
int tx = i * 32 / wall_height;
const int c = column - (wall_height/2)+i;
if (c>=0 && c<320) {
for (int j=0;j<wall_height;++j)
{
int ty = j * 32 / wall_height;
draw::putps(c, wall_start+j, getp(spr,tx,ty), d); //120-(wall_height/2)
}
}
}
//line(column, 0, column, 239, 0);
}
/*
float angle = SDL_atan2f(enemy.y-position.y, enemy.x-position.x)*RAD_TO_DEG;
if (SDL_abs(angle) <= 32.0f)
{
const float d = distance(position, enemy);// * SDL_cosf(a_inc*DEG_TO_RAD);
debug::print("enemy angle:");debug::print(angle);debug::newline();
debug::print("enemy dist:");debug::print(d);debug::newline();
}
*/
if (triggers::isEnabled("minimap")) {
// Draw map walls
//draw::cls();
int sec = 0;
vec2 normal = { SDL_cosf(orientation*DEG_TO_RAD), SDL_sinf(orientation*DEG_TO_RAD) };
for (auto &s : sectors)
{
//if (sec==current_sector2)
for (auto &w : s.walls) {
//if (dot(normal, w.normal) >= 0) continue;
draw::map::line(verts[w.v1].x, verts[w.v1].y, verts[w.v2].x, verts[w.v2].y, sec==current_sector?20:4, position.x, position.y);
vec2 nx {(verts[w.v2].x+verts[w.v1].x)/2, (verts[w.v2].y+verts[w.v1].y)/2};
draw::map::line(nx.x, nx.y, nx.x+w.normal.x*20, nx.y+w.normal.y*20, sec==current_sector?22:3, position.x, position.y);
}
sec++;
}
vec2 infi;
infi.x = position.x + SDL_cosf((orientation + -32.0f)*DEG_TO_RAD)*40000;
infi.y = position.y + SDL_sinf((orientation + -32.0f)*DEG_TO_RAD)*40000;
draw::map::line(position.x, position.y, infi.x, infi.y, 32, position.x, position.y);
infi.x = position.x + SDL_cosf((orientation)*DEG_TO_RAD)*40000;
infi.y = position.y + SDL_sinf((orientation)*DEG_TO_RAD)*40000;
draw::map::line(position.x, position.y, infi.x, infi.y, 42, position.x, position.y);
infi.x = position.x + SDL_cosf((orientation + 32.0f)*DEG_TO_RAD)*40000;
infi.y = position.y + SDL_sinf((orientation + 32.0f)*DEG_TO_RAD)*40000;
draw::map::line(position.x, position.y, infi.x, infi.y, 32, position.x, position.y);
// Draw map hero
vec2 lookat;
lookat.x = SDL_cosf(orientation*DEG_TO_RAD)*20;
lookat.y = SDL_sinf(orientation*DEG_TO_RAD)*20;
draw::map::line(0, 0, lookat.x, lookat.y, 20, 0, 0);
draw::map::putp(0, 0, 20);
for (int i=0;i<256;++i) {
draw::putp((i&0xf)*2, (i>>4)*2, i);
draw::putp((i&0xf)*2+1, (i>>4)*2, i);
draw::putp((i&0xf)*2+1, (i>>4)*2+1, i);
draw::putp((i&0xf)*2, (i>>4)*2+1, i);
}
}
draw::render();
fps_count++;
if (SDL_GetTicks()-fps_time>=1000)
{
fps = fps_count;
fps_count = 0;
fps_time = SDL_GetTicks();
}
debug::println("fps:", fps);
debug::println("sector:", current_sector);
debug::println("height:", real_height);
debug::println("ceil_height:", sectors[0].ceiling_height);
debug::println("floor_height:", sectors[0].floor_height);
debug::render();
draw::flip();
}
return 0;
}