diff --git a/.gitignore b/.gitignore index 1966e35..995d264 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ wolf +wolf_debug +build/* \ No newline at end of file diff --git a/doom1.wad b/doom1.wad new file mode 100644 index 0000000..27b28af Binary files /dev/null and b/doom1.wad differ diff --git a/draw.cpp b/draw.cpp new file mode 100644 index 0000000..36e46b5 --- /dev/null +++ b/draw.cpp @@ -0,0 +1,159 @@ +#include "draw.h" +#include +#include "gif.h" +#include "jdebug.h" +#include +#include + +// Funcions de pintat + +namespace draw +{ + SDL_Window *sdl_window; + SDL_Renderer *sdl_renderer; + SDL_Texture *sdl_texture; + + Uint32 *palette; + Uint8 screen[320*240]; + float depth_buffer[320*240]; + + void init() + { + SDL_Init(SDL_INIT_VIDEO); + sdl_window = SDL_CreateWindow("WOLF", 640, 480, 0); + SDL_SetWindowPosition(sdl_window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); + sdl_renderer = SDL_CreateRenderer(sdl_window, NULL); + sdl_texture = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 320, 240); + SDL_SetTextureScaleMode(sdl_texture, SDL_SCALEMODE_NEAREST); + debug::init(sdl_renderer); + } + + surface_t *newsurf(int w, int h) + { + surface_t *surf = (surface_t*)malloc(sizeof(surface_t)); + surf->w = w; + surf->h = h; + surf->pixels = (uint8_t*)malloc(w*h); + return surf; + } + + surface_t *loadgif(const char* filename) + { + FILE *f = fopen(filename, "rb"); + fseek(f, 0, SEEK_END); + int filesize = ftell(f); + fseek(f, 0, SEEK_SET); + Uint8 *buffer = (Uint8*)malloc(filesize); + fread(buffer, filesize, 1, f); + fclose(f); + surface_t *surf = (surface_t*)malloc(sizeof(surface_t)); + surf->pixels = LoadGif(buffer, &surf->w, &surf->h); + free(buffer); + return surf; + } + + Uint32 *loadpal(const char* filename) + { + FILE *f = fopen(filename, "rb"); + fseek(f, 0, SEEK_END); + int filesize = ftell(f); + fseek(f, 0, SEEK_SET); + Uint8 *buffer = (Uint8*)malloc(filesize); + fread(buffer, filesize, 1, f); + fclose(f); + Uint32 *pal = LoadPalette(buffer); + free(buffer); + return pal; + } + + void setpal(Uint32* pal) + { + palette = pal; + } + + void putp(int x, int y, Uint8 color) + { + if (x<0 || y<0 || x>=320 || y>=240) return; + screen[x+y*320]=color; + } + + void putpd(int x, int y, Uint8 color, float depth) + { + if (x<0 || y<0 || x>=320 || y>=240) return; + screen[x+y*320]=color; + depth_buffer[x+y*320]=depth; + } + + void putps(int x, int y, Uint8 color, float depth) + { + if (x<0 || y<0 || x>=320 || y>=240 || color==0) return; + if (depth_buffer[x+y*320]>=depth) + { + screen[x+y*320]=color; + depth_buffer[x+y*320]=depth; + } + } + + Uint8 getp(surface_t *surf, int x, int y) + { + return surf->pixels[x+y*surf->w]; + } + + void line(int x1, int y1, int x2, int y2, Uint8 color) + { + float dx = float(x2-x1); + float dy = float(y2-y1); + float steps = SDL_max(SDL_fabsf(dx), SDL_fabsf(dy)); + + if (steps==0) { putp(x1,y1,color); return; } + + float incx = dx / steps; + float incy = dy / steps; + + float x = (float)x1; + float y = (float)y1; + + for (int i=0; i<=int(steps); ++i) + { + putp(int(x+0.5f),int(y+0.5f),color); + x += incx; + y += incy; + } + + } + + void render() + { + // Send to texture and render + Uint32 *pixels; + int pitch; + SDL_LockTexture(sdl_texture, NULL, (void**)&pixels, &pitch); + for (int i=0; i<(320*240); ++i) + { + pixels[i] = 0xFF000000 | palette[screen[i]]; + + // [DEBUG] Visualització del depth buffer + //pixels[i] = 0xFF000000 | palette[SDL_min(int(depth_buffer[i]),255)]; + } + SDL_UnlockTexture(sdl_texture); + SDL_RenderTexture(sdl_renderer, sdl_texture, NULL, NULL); + } + + void flip() + { + SDL_RenderPresent(sdl_renderer); + } + + namespace map + { + void putp(int x, int y, Uint8 color) + { + draw::putp(160+(x/8), 120+(y/8), color); + } + + void line(int x1, int y1, int x2, int y2, Uint8 color) + { + draw::line(160+(x1/8), 120+(y1/8), 160+(x2/8), 120+(y2/8), color); + } + } +} \ No newline at end of file diff --git a/draw.h b/draw.h new file mode 100644 index 0000000..d5e2ecd --- /dev/null +++ b/draw.h @@ -0,0 +1,32 @@ +#pragma once +#include + +// Funcions de pintat + +namespace draw +{ + struct surface_t + { + uint8_t *pixels; + uint16_t w, h; + }; + + void init(); + surface_t *newsurf(int w, int h); + surface_t *loadgif(const char* filename); + uint32_t *loadpal(const char* filename); + void setpal(uint32_t* pal); + void putp(int x, int y, uint8_t color); + void putpd(int x, int y, uint8_t color, float depth); + void putps(int x, int y, uint8_t color, float depth); + uint8_t getp(surface_t *surf, int x, int y); + void line(int x1, int y1, int x2, int y2, uint8_t color); + void render(); + void flip(); + + namespace map + { + void putp(int x, int y, uint8_t color); + void line(int x1, int y1, int x2, int y2, uint8_t color); + } +} diff --git a/gif.c b/gif.h similarity index 99% rename from gif.c rename to gif.h index 8c19b14..9685352 100644 --- a/gif.c +++ b/gif.h @@ -2,6 +2,7 @@ #include #include #include +#include #define EXTENSION_INTRODUCER 0x21 #define IMAGE_DESCRIPTOR 0x2C diff --git a/jdebug.cpp b/jdebug.cpp index 0a7c94f..5c43ec0 100644 --- a/jdebug.cpp +++ b/jdebug.cpp @@ -4,20 +4,23 @@ namespace debug { Uint8 bmp[448] {0x42, 0x4D, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x01, 0x00, 0x00, 0x12, 0x0B, 0x00, 0x00, 0x12, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x18, 0xF3, 0x83, 0x83, 0xCF, 0x83, 0x87, 0x00, 0x00, 0xF3, 0x39, 0x39, 0xCF, 0x79, 0xF3, 0x00, 0x00, 0x01, 0xF9, 0x39, 0xCF, 0x61, 0xF9, 0x00, 0x00, 0x33, 0xF9, 0x03, 0xE7, 0x87, 0x81, 0x00, 0x00, 0x93, 0x03, 0x3F, 0xF3, 0x1B, 0x39, 0x00, 0x00, 0xC3, 0x3F, 0x9F, 0x39, 0x3B, 0x39, 0x00, 0x41, 0xE3, 0x03, 0xC3, 0x01, 0x87, 0x83, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xE7, 0x01, 0xC7, 0x81, 0x01, 0x83, 0x00, 0x00, 0xE7, 0x1F, 0x9B, 0xE7, 0x1F, 0x39, 0x00, 0x00, 0xE7, 0x8F, 0x39, 0xE7, 0x87, 0xF9, 0x00, 0x00, 0xC3, 0xC7, 0x39, 0xE7, 0xC3, 0xC3, 0x00, 0x00, 0x99, 0xE3, 0x39, 0xE7, 0xF1, 0xE7, 0x00, 0x00, 0x99, 0xF1, 0xB3, 0xC7, 0x39, 0xF3, 0x00, 0x00, 0x99, 0x01, 0xC7, 0xE7, 0x83, 0x81, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x83, 0xE7, 0x83, 0xEF, 0x39, 0x39, 0x00, 0x00, 0x39, 0xE7, 0x39, 0xC7, 0x11, 0x11, 0x00, 0x00, 0xF9, 0xE7, 0x39, 0x83, 0x01, 0x83, 0x00, 0x00, 0x83, 0xE7, 0x39, 0x11, 0x01, 0xC7, 0x00, 0x00, 0x3F, 0xE7, 0x39, 0x39, 0x29, 0x83, 0x00, 0x00, 0x33, 0xE7, 0x39, 0x39, 0x39, 0x11, 0x00, 0x00, 0x87, 0x81, 0x39, 0x39, 0x39, 0x39, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x39, 0x39, 0x83, 0x3F, 0x85, 0x31, 0x00, 0x00, 0x39, 0x31, 0x39, 0x3F, 0x33, 0x23, 0x00, 0x00, 0x29, 0x21, 0x39, 0x03, 0x21, 0x07, 0x00, 0x00, 0x01, 0x01, 0x39, 0x39, 0x39, 0x31, 0x00, 0x00, 0x01, 0x09, 0x39, 0x39, 0x39, 0x39, 0x00, 0x00, 0x11, 0x19, 0x39, 0x39, 0x39, 0x39, 0x00, 0x00, 0x39, 0x39, 0x83, 0x03, 0x83, 0x03, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xC1, 0x39, 0x81, 0x83, 0x31, 0x01, 0x00, 0x00, 0x99, 0x39, 0xE7, 0x39, 0x23, 0x3F, 0x00, 0x00, 0x39, 0x39, 0xE7, 0xF9, 0x07, 0x3F, 0x00, 0x00, 0x31, 0x01, 0xE7, 0xF9, 0x0F, 0x3F, 0x00, 0x00, 0x3F, 0x39, 0xE7, 0xF9, 0x27, 0x3F, 0x00, 0x00, 0x9F, 0x39, 0xE7, 0xF9, 0x33, 0x3F, 0x00, 0x00, 0xC1, 0x39, 0x81, 0xF9, 0x39, 0x3F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x39, 0x03, 0xC3, 0x07, 0x01, 0x3F, 0x00, 0x00, 0x39, 0x39, 0x99, 0x33, 0x3F, 0x3F, 0x00, 0x00, 0x01, 0x39, 0x3F, 0x39, 0x3F, 0x3F, 0x00, 0x00, 0x39, 0x03, 0x3F, 0x39, 0x03, 0x03, 0x00, 0x00, 0x39, 0x39, 0x3F, 0x39, 0x3F, 0x3F, 0x00, 0x00, 0x93, 0x39, 0x99, 0x33, 0x3F, 0x3F, 0x00, 0x00, 0xC7, 0x03, 0xC3, 0x07, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00}; + SDL_Renderer *ren; SDL_Texture* dbgtex; static char dbg_str[1200]; static char *cursor = nullptr; void init(SDL_Renderer *renderer) { + ren = renderer; dbgtex = SDL_CreateTextureFromSurface(renderer, SDL_LoadBMP_IO(SDL_IOFromMem(bmp, 448), 1)); cursor = dbg_str; SDL_SetTextureBlendMode(dbgtex, SDL_BLENDMODE_ADD); } - void render(SDL_Renderer *renderer) + void render() { - int x = 0, y = 0, cc = 0; + //int x = 0, y = 0, + int cc = 0; SDL_FRect src {0, 0, 8, 8}, dst {0, 0, 8, 8}; while (cc<1200 && dbg_str[cc] != 0) { char chr = dbg_str[cc++]; @@ -31,7 +34,7 @@ namespace debug src.x = ((chr-22)%6)*8; src.y = ((chr-22)/6)*8; } - SDL_RenderTexture(renderer, dbgtex, &src, &dst); + SDL_RenderTexture(ren, dbgtex, &src, &dst); dst.x += 8; if (dst.x >= 320) { dst.x=0; dst.y += 8; diff --git a/jdebug.h b/jdebug.h index f53291b..9df8829 100644 --- a/jdebug.h +++ b/jdebug.h @@ -4,7 +4,7 @@ namespace debug { void init(SDL_Renderer *renderer); - void render(SDL_Renderer *renderer); + void render(); void println(const char *label, int value); void print(int value); diff --git a/lagueirtofile b/lagueirtofile new file mode 100644 index 0000000..cf440f4 --- /dev/null +++ b/lagueirtofile @@ -0,0 +1,5 @@ +libs = -lSDL3 +cppflags = -D DEBUG -g -Wall +executable = wolf_debug +sourcepath = . +buildpath = build diff --git a/main.cpp b/main.cpp index 3d53542..ae4f73e 100644 --- a/main.cpp +++ b/main.cpp @@ -1,14 +1,20 @@ #include -#include "gif.c" #include +#include #include "jdebug.h" +#include "util.h" +#include "draw.h" +#include "wad.h" -#define M_PI 3.14159265358979323846 -#define DEG_TO_RAD (M_PI/180.0f) -#define RAD_TO_DEG (180.0f/M_PI) +#define FOV 190 + +struct wall { + Uint16 v1, v2; + vec2 normal; + float u1, u2; + int portal; +}; -struct vec2 { float x, y; }; -struct wall { Uint16 v1, v2; vec2 normal; float u1, u2; int portal; }; struct sector { float floor_height; float ceiling_height; @@ -16,15 +22,6 @@ struct sector { std::vector verts; }; -SDL_Window *sdl_window; -SDL_Renderer *sdl_renderer; -SDL_Texture *sdl_texture; - -Uint32 *palette; -Uint8 *gif; -Uint8 *spr; -Uint8 screen[320*240]; -float depth_buffer[320*240]; std::vector sectors; int current_sector; @@ -43,113 +40,9 @@ float bobbing = 0.0f; float dt; -// Returns 1 if the lines intersect, otherwise 0. In addition, if the lines -// intersect the intersection point may be stored in the floats i_x and i_y. -const bool get_line_intersection(vec2 p0, vec2 p1, vec2 p2, vec2 p3, vec2 *i) -{ - vec2 s1, s2; - s1.x = p1.x - p0.x; s1.y = p1.y - p0.y; - s2.x = p3.x - p2.x; s2.y = p3.y - p2.y; - - float s, t; - s = (-s1.y * (p0.x - p2.x) + s1.x * (p0.y - p2.y)) / (-s2.x * s1.y + s1.x * s2.y); - t = ( s2.x * (p0.y - p2.y) - s2.y * (p0.x - p2.x)) / (-s2.x * s1.y + s1.x * s2.y); - - if (s >= 0 && s <= 1 && t >= 0 && t <= 1) - { - // Collision detected - if (i != NULL) - { - i->x = p0.x + (t * s1.x); - i->y = p0.y + (t * s1.y); - - } - return true; - } - - return false; // No collision -} - -inline const float distance(vec2 p1, vec2 p2) -{ - const float xx = p2.x-p1.x; - const float yy = p2.y-p1.y; - return SDL_sqrtf(xx*xx+yy*yy); -} - -inline const void normalize(vec2 *v) -{ - const float length = SDL_sqrtf(v->x*v->x + v->y*v->y); - if (length > 0.0f) { - v->x /= length; - v->y /= length; - } -} - -inline const float dot(vec2 v1, vec2 v2) -{ - return v1.x*v2.x + v1.y*v2.y; -} - -void putp(int x, int y, Uint8 color) -{ - if (x<0 || y<0 || x>=320 || y>=240) return; - screen[x+y*320]=color; -} - -void putpd(int x, int y, Uint8 color, float depth) -{ - if (x<0 || y<0 || x>=320 || y>=240) return; - screen[x+y*320]=color; - depth_buffer[x+y*320]=depth; -} - -void putps(int x, int y, Uint8 color, float depth) -{ - if (x<0 || y<0 || x>=320 || y>=240 || color==0) return; - if (depth_buffer[x+y*320]>=depth) - { - screen[x+y*320]=color; - depth_buffer[x+y*320]=depth; - } -} - -void line(int x1, int y1, int x2, int y2, Uint8 color) -{ - float dx = float(x2-x1); - float dy = float(y2-y1); - float steps = SDL_max(SDL_fabsf(dx), SDL_fabsf(dy)); - - if (steps==0) { putp(x1,y1,color); return; } - - float incx = dx / steps; - float incy = dy / steps; - - float x = (float)x1; - float y = (float)y1; - - for (int i=0; i<=int(steps); ++i) - { - putp(int(x+0.5f),int(y+0.5f),color); - x += incx; - y += incy; - } - -} - -namespace map -{ - void putp(int x, int y, Uint8 color) - { - ::putp(160+(x/8), 120+(y/8), color); - } - - void line(int x1, int y1, int x2, int y2, Uint8 color) - { - ::line(160+(x1/8), 120+(y1/8), 160+(x2/8), 120+(y2/8), color); - } -} - +Uint32 *palette; +draw::surface_t *gif; +draw::surface_t *spr; void createMap() { @@ -245,13 +138,13 @@ void drawColumn(sector &s, int screen_column, int start, int end, float a_inc, v const int tex_height = 64; const float sector_height = s.ceiling_height - s.floor_height; - map::putp(result.x, result.y, 6); + draw::map::putp(result.x, result.y, 6); float dist = stright_dist * SDL_cosf(a_inc*DEG_TO_RAD); const vec2 AB = {s.verts[w->v2].x-s.verts[w->v1].x, s.verts[w->v2].y-s.verts[w->v1].y}; const vec2 AP = {result.x-s.verts[w->v1].x, result.y-s.verts[w->v1].y}; float v = dot(AP,AB) / dot(AB,AB); v *= w->u2; v = (v-int(v))*tex_height; - float wall_height = (sector_height*277)/dist; // [64=altura sector] + float wall_height = (sector_height*FOV)/dist; // [64=altura sector] float wall_cut = 0.0f; float dpix = tex_height/wall_height; // [64=crec que altura sector] float cpix = 0; @@ -265,11 +158,11 @@ void drawColumn(sector &s, int screen_column, int start, int end, float a_inc, v // Pinta el sostre for (int y=start; y> 1)); + 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 = abs(int(actual_dist * SDL_cosf(angle*DEG_TO_RAD) - position.x)) % tex_height; - int ty = abs(int(actual_dist * SDL_sinf(angle*DEG_TO_RAD) - position.y)) % tex_height; - putpd(screen_column, y, gif[tx+ty*tex_height], -straight_dist); + int tx = SDL_abs(int(actual_dist * SDL_cosf(angle*DEG_TO_RAD) - position.x)) % tex_height; + int ty = SDL_abs(int(actual_dist * SDL_sinf(angle*DEG_TO_RAD) - position.y)) % tex_height; + draw::putpd(screen_column, y, gif->pixels[tx+ty*tex_height], -straight_dist); } @@ -278,21 +171,21 @@ void drawColumn(sector &s, int screen_column, int start, int end, float a_inc, v // Pinta la pared for (int i=0; i=end) break; - putpd(screen_column, wall_start+i, gif[(int(v)%tex_height)+int(cpix)*tex_height], stright_dist); + draw::putpd(screen_column, wall_start+i, gif->pixels[(int(v)%tex_height)+int(cpix)*tex_height], stright_dist); cpix += dpix; } } else { if (sectors[w->portal].ceiling_height < s.ceiling_height) { float upper_height = s.ceiling_height - sectors[w->portal].ceiling_height; - float upper_wall_height = (upper_height*277)/dist; + float upper_wall_height = (upper_height*FOV)/dist; upper_wall_height -= wall_cut; if (upper_wall_height>0.0f) { // Pinta la pared for (int i=0; i=end) break; - putpd(screen_column, wall_start+i, gif[(int(v)%tex_height)+int(cpix)*tex_height], stright_dist); + draw::putpd(screen_column, wall_start+i, gif->pixels[(int(v)%tex_height)+int(cpix)*tex_height], stright_dist); cpix += dpix; } wall_start += upper_wall_height; @@ -300,7 +193,7 @@ void drawColumn(sector &s, int screen_column, int start, int end, float a_inc, v } } float lower_height = sectors[w->portal].floor_height - s.floor_height; - float lower_wall_height = (lower_height*277)/dist; + 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); @@ -313,7 +206,7 @@ void drawColumn(sector &s, int screen_column, int start, int end, float a_inc, v // Pinta la pared for (int i=0; i=end) break; - putpd(screen_column, wall_end+i, gif[(int(v)%tex_height)+int(cpix)*tex_height], stright_dist); + draw::putpd(screen_column, wall_end+i, gif->pixels[(int(v)%tex_height)+int(cpix)*tex_height], stright_dist); cpix += dpix; } //wall_start += upper_wall_height; @@ -325,11 +218,11 @@ void drawColumn(sector &s, int screen_column, int start, int end, float a_inc, v // Pinta el piso int paint_end = wall_start+wall_height-1; for (int y=paint_end+1; y> 1)); + 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 = abs(int(actual_dist * SDL_cosf(angle*DEG_TO_RAD) + position.x)) % tex_height; - int ty = abs(int(actual_dist * SDL_sinf(angle*DEG_TO_RAD) + position.y)) % tex_height; - putpd(screen_column, y, gif[tx+ty*tex_height], straight_dist); + int tx = SDL_abs(int(actual_dist * SDL_cosf(angle*DEG_TO_RAD) + position.x)) % tex_height; + int ty = SDL_abs(int(actual_dist * SDL_sinf(angle*DEG_TO_RAD) + position.y)) % tex_height; + draw::putpd(screen_column, y, gif->pixels[tx+ty*tex_height], straight_dist); } //line(screen_column, 120-(wall_height), screen_column, 120+(wall_height), 5); } @@ -380,65 +273,17 @@ bool tryMove(float angle, float speed) return moved; } -float is_enemy_in_fov(double Ax, double Ay, double orientation_deg, - double Bx, double By) { - // Convert orientation angle to radians - double orientation_rad = orientation_deg * DEG_TO_RAD; - - // Compute view direction vector from angle - double view_dx = SDL_cosf(orientation_rad); - double view_dy = SDL_sinf(orientation_rad); - - // Vector from A to B - double to_enemy_dx = Bx - Ax; - double to_enemy_dy = By - Ay; - - // Normalize both vectors - double len = SDL_sqrtf(to_enemy_dx * to_enemy_dx + to_enemy_dy * to_enemy_dy); - if (len == 0) return 0.0; // Same position - - to_enemy_dx /= len; - to_enemy_dy /= len; - - // Compute signed angle using atan2 of perp-dot and dot - double dot = view_dx * to_enemy_dx + view_dy * to_enemy_dy; - double cross = view_dx * to_enemy_dy - view_dy * to_enemy_dx; - - float angle_rad = SDL_atan2f(cross, dot); - return angle_rad * RAD_TO_DEG; // Signed angle in degrees -} - int main(int argc, char *argv[]) { - SDL_Init(SDL_INIT_VIDEO); - sdl_window = SDL_CreateWindow("WOLF", 640, 480, 0); - SDL_SetWindowPosition(sdl_window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); - sdl_renderer = SDL_CreateRenderer(sdl_window, NULL); - sdl_texture = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 320, 240); + wad::init("doom1.wad"); - debug::init(sdl_renderer); + draw::init(); - FILE *f = fopen("walls.gif", "rb"); - fseek(f, 0, SEEK_END); - int filesize = ftell(f); - fseek(f, 0, SEEK_SET); - Uint8 *buffer = (Uint8*)malloc(filesize); - fread(buffer, filesize, 1, f); - fclose(f); - Uint16 w, h; - gif = LoadGif(buffer, &w, &h); - palette = LoadPalette(buffer); - free(buffer); - - f = fopen("player1.gif", "rb"); - fseek(f, 0, SEEK_END); - filesize = ftell(f); - fseek(f, 0, SEEK_SET); - buffer = (Uint8*)malloc(filesize); - fread(buffer, filesize, 1, f); - fclose(f); - spr = LoadGif(buffer, &w, &h); - free(buffer); + gif = wad::loadFlat("FLOOR4_8"); //draw::loadgif("walls.gif"); + //palette = draw::loadpal("walls.gif"); + palette = wad::loadPalette(0); + draw::setpal(palette); + spr = draw::loadgif("player1.gif"); // [DEBUG] Paleta per al depth buffer //for(int i=0;i<256;++i) palette[i] = (255-i) | ((255-i)<<8) | ((255-i)<<16); @@ -538,14 +383,14 @@ int main(int argc, char *argv[]) debug::print("angle:");debug::print(orientation);debug::newline(); vec2 enemy = {256.0f, 256.0f}; - map::putp(enemy.x, enemy.y, 9); + 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*277)/dist; + 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); @@ -558,7 +403,7 @@ int main(int argc, char *argv[]) for (int j=0;j>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); } - SDL_UnlockTexture(sdl_texture); - SDL_RenderTexture(sdl_renderer, sdl_texture, NULL, NULL); + draw::render(); fps_count++; if (SDL_GetTicks()-fps_time>=1000) @@ -617,9 +456,9 @@ int main(int argc, char *argv[]) debug::println("height:", real_height); debug::println("ceil_height:", sectors[0].ceiling_height); debug::println("floor_height:", sectors[0].floor_height); - debug::render(sdl_renderer); + debug::render(); - SDL_RenderPresent(sdl_renderer); + draw::flip(); } return 0; diff --git a/util.cpp b/util.cpp new file mode 100644 index 0000000..a871a76 --- /dev/null +++ b/util.cpp @@ -0,0 +1,80 @@ +#include "util.h" +#include + +// Funcions de càlcul + +// Returns 1 if the lines intersect, otherwise 0. In addition, if the lines +// intersect the intersection point may be stored in the floats i_x and i_y. +const bool get_line_intersection(vec2 p0, vec2 p1, vec2 p2, vec2 p3, vec2 *i) +{ + vec2 s1, s2; + s1.x = p1.x - p0.x; s1.y = p1.y - p0.y; + s2.x = p3.x - p2.x; s2.y = p3.y - p2.y; + + float s, t; + s = (-s1.y * (p0.x - p2.x) + s1.x * (p0.y - p2.y)) / (-s2.x * s1.y + s1.x * s2.y); + t = ( s2.x * (p0.y - p2.y) - s2.y * (p0.x - p2.x)) / (-s2.x * s1.y + s1.x * s2.y); + + if (s >= 0 && s <= 1 && t >= 0 && t <= 1) + { + // Collision detected + if (i != NULL) + { + i->x = p0.x + (t * s1.x); + i->y = p0.y + (t * s1.y); + + } + return true; + } + + return false; // No collision +} + +const float distance(vec2 p1, vec2 p2) +{ + const float xx = p2.x-p1.x; + const float yy = p2.y-p1.y; + return SDL_sqrtf(xx*xx+yy*yy); +} + +const void normalize(vec2 *v) +{ + const float length = SDL_sqrtf(v->x*v->x + v->y*v->y); + if (length > 0.0f) { + v->x /= length; + v->y /= length; + } +} + +const float dot(vec2 v1, vec2 v2) +{ + return v1.x*v2.x + v1.y*v2.y; +} + +float is_enemy_in_fov(double Ax, double Ay, double orientation_deg, double Bx, double By) { + // Convert orientation angle to radians + double orientation_rad = orientation_deg * DEG_TO_RAD; + + // Compute view direction vector from angle + double view_dx = SDL_cosf(orientation_rad); + double view_dy = SDL_sinf(orientation_rad); + + // Vector from A to B + double to_enemy_dx = Bx - Ax; + double to_enemy_dy = By - Ay; + + // Normalize both vectors + double len = SDL_sqrtf(to_enemy_dx * to_enemy_dx + to_enemy_dy * to_enemy_dy); + if (len == 0) return 0.0; // Same position + + to_enemy_dx /= len; + to_enemy_dy /= len; + + // Compute signed angle using atan2 of perp-dot and dot + double dot = view_dx * to_enemy_dx + view_dy * to_enemy_dy; + double cross = view_dx * to_enemy_dy - view_dy * to_enemy_dx; + + float angle_rad = SDL_atan2f(cross, dot); + return angle_rad * RAD_TO_DEG; // Signed angle in degrees +} + diff --git a/util.h b/util.h new file mode 100644 index 0000000..72e1eb2 --- /dev/null +++ b/util.h @@ -0,0 +1,13 @@ +#pragma once + +#define M_PI 3.14159265358979323846 +#define DEG_TO_RAD (M_PI/180.0f) +#define RAD_TO_DEG (180.0f/M_PI) + +struct vec2 { float x, y; }; + +const bool get_line_intersection(vec2 p0, vec2 p1, vec2 p2, vec2 p3, vec2 *i); +const float distance(vec2 p1, vec2 p2); +const void normalize(vec2 *v); +const float dot(vec2 v1, vec2 v2); +float is_enemy_in_fov(double Ax, double Ay, double orientation_deg, double Bx, double By); \ No newline at end of file diff --git a/wad.cpp b/wad.cpp new file mode 100644 index 0000000..da9bb03 --- /dev/null +++ b/wad.cpp @@ -0,0 +1,154 @@ +#include "wad.h" +#include +#include +#include +#include +#include +#include + +namespace wad { + + char file[13]; + filelump_t *directory; + uint32_t numlumps; + + struct patch_t { + + }; + + std::unordered_map flats; + std::unordered_map textures; + std::unordered_map patches; + std::vector patch_names; + //char (*patch_names)[8]; + + void init(const char *filename) { + + strcpy(file, filename); + FILE *f = fopen(filename, "rb"); + + char header[4]; fread(header, 4, 1, f);// printf("header: %*.s\n", 4, header); + uint32_t infotableofs; + fread(&numlumps, 4, 1, f);// printf("num lumps: %i\n", numlumps); + fread(&infotableofs, 4, 1, f);// printf("directory offset: %i\n\n", infotableofs); + directory = (filelump_t*)malloc(sizeof(filelump_t)*numlumps); + fseek(f, infotableofs, SEEK_SET); + for (int i=0; ipixels[x+y*64] = flat[i++]; + + free(flat); + flats[name] = surf; + return surf; + } + + draw::surface_t *loadTexture(const char *name) + { + if (textures.find(name) != textures.end()) return textures[name]; + + uint8_t *textures_lump = load("TEXTURE1"); + int num_textures_in_lump = ((uint32_t*)textures_lump)[0]; + uint32_t *offsets = &((uint32_t*)textures_lump)[1]; + int i = 0; + while (i +#include "draw.h" + +namespace wad { + + struct filelump_t { + uint32_t filepos; + uint32_t size; + char name[8]; + }; + + void init(const char *filename); + uint8_t *load(const char *name); + + uint32_t *loadPalette(int index); + + draw::surface_t *loadFlat(const char *name); + draw::surface_t *loadTexture(const char *name); + draw::surface_t *loadPatch(const char *name); +} \ No newline at end of file