From 3c0a3b8413ee58a3e5678075c862e95f7c8395c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=95=D0=B3=D0=BE=D1=80=20=D0=9B=D1=8C=D0=B2=D0=BE=D0=B2?= Date: Mon, 27 Mar 2023 11:25:27 +0300 Subject: =?UTF-8?q?=D0=9D=D0=B0=D1=87=D0=B0=D0=BB=D1=8C=D0=BD=D1=8B=D0=B9?= =?UTF-8?q?=20=D0=BA=D0=BE=D0=BC=D0=BC=D0=B8=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backupmain.c | 620 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 620 insertions(+) create mode 100644 backupmain.c (limited to 'backupmain.c') diff --git a/backupmain.c b/backupmain.c new file mode 100644 index 0000000..dd8cf50 --- /dev/null +++ b/backupmain.c @@ -0,0 +1,620 @@ +#ifdef _WIN32 // грубый способ определения; на деле разница не в ОС, а в компиляторe + #include + #include + #include +#else + #include + #include + #include +#endif + +#include +#include +#include +#include + +/* TILESIZE (и SQRTTILE) лучше не трогать - или быть +готовым гадать, где 32 заменить, а где не надо */ +/* При изменении размера окна не забыть поменять +скайбокс (или добавить масштабируемость) */ + +#define PI 3.1415926535 // значение числа пи +#define DEG 0.01745329 // знаечние 1 градуса в радианах + +#include "./var.conf" +#include "levels/level_test.dat" + +#define TILESIZE 32 // размер одной клетки карты; также "реальная" высота стены +#define SQRTTILE 5 // двоичный логарифм TILESIZE - используется для побитовых операций + +#if (MAPX > MAPY) // дальность прорисовки + #define DOF MAPX +#else + #define DOF MAPY +#endif + +SDL_Texture *skyT, *wallT, *spriT; + +typedef struct { float x, y; } vec; + +float dist(float x1, float y1, float x2, float y2) +{ + return ( sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)) ); +} + +void rotateVector(vec *v, float ang) +{ + /* Матрица поворота в левосторонней системе координат: */ + // | cos(a) sin(a) | + // | -sin(a) cos(a) | + float xr = (v->x)*cos(ang) - (v->y)*sin(ang); + float yr = (v->x)*sin(ang) + (v->y)*cos(ang); + v->x = xr; + v->y = yr; +} + +void sortSprites(int order[], float dist[], int amount) +{ + double factor = 1.24733095; + int step = amount-1; + double tmp; + while(step >= 1) + { + for(int i = 0; i+step < amount; i++) + { + if(dist[i] > dist[i+step]) + { + tmp = dist[i]; + dist[i] = dist[i+step]; + dist[i+step] = tmp; + + tmp = (double)order[i]; + order[i] = order[i+step]; + order[i+step] = (int)tmp; + } + } + step /= factor; + } +} + +void scalePPM(int *img) +{ + ; +} + +int processEvents(SDL_Window *window, struct player *P, int map[], int *mpbool, clock_t *prevframe) +{ + // Вычисление FPS + clock_t frame; + float fps; + + frame = clock(); + fps = CLOCKS_PER_SEC/(double)(frame - *prevframe); + *prevframe = frame; + printf("%d\t\t\r", (int)fps); + + int done = 0; + SDL_Event event; + + int xoff = 0; + if((P->dx)>0) {xoff = 20;} else {xoff = -20;} + + int yoff = 0; + if((P->dy)>0) {yoff = 20;} else {yoff = -20;} + + int px64 = (int)(P->x) >> SQRTTILE; + int py64 = (int)(P->y) >> SQRTTILE; + + int pxadd = (int)(P->x + xoff) >> SQRTTILE, pyadd = (int)(P->y + yoff) >> SQRTTILE; + int pxsub = (int)(P->x - xoff) >> SQRTTILE, pysub = (int)(P->y - yoff) >> SQRTTILE; + + while(SDL_PollEvent(&event)) + { + switch(event.type) + { + case SDL_WINDOWEVENT_CLOSE: + { + if(window) + { + SDL_DestroyWindow(window); + window = NULL; + done = 1; + } + } + break; + + case SDL_KEYDOWN: + { + switch(event.key.keysym.sym) + { + case SDLK_ESCAPE: + done = 1; + break; + case SDLK_m: // карта + *mpbool = !*mpbool; + break; + case SDLK_e: // взаимодействие + int xeoff = 0; if((P->th)<(PI/4) || (P->th)>(7*PI/4)) {xeoff = 25;} + else if((P->th)>(3*PI/4) && (P->th)<(5*PI/4)){xeoff = -25;} + + int yeoff = 0; if((P->th)>(PI/4) && (P->th)<(3*PI/4)) {yeoff = 25;} + else if((P->th)>(5*PI/4) && (P->th)<(7*PI/4)) {yeoff = -25;} + + int exadd = ((int)P->x + xeoff) >> SQRTTILE, eyadd = ((int)P->y + yeoff) >> SQRTTILE; + + if(map[eyadd*MAPX + exadd] == 4) // дверь + map[eyadd*MAPX + exadd] = 0; + } + } + break; + + case SDL_QUIT: + done = 1; + break; + } + } + + const Uint8 *state = SDL_GetKeyboardState(NULL); + if(state[SDL_SCANCODE_A]) + P->th -= (RADSPD/fps); + + if(state[SDL_SCANCODE_W]) { + if(map[py64*MAPX + pxadd]==0) {P->x += P->dx;} + if(map[pyadd*MAPX + px64]==0) {P->y += P->dy;} + // P->x += P->dx; + // P->y += P->dy; + } + if(state[SDL_SCANCODE_S]) { + if(map[py64*MAPX + pxsub]==0) {P->x -= P->dx;} + if(map[pysub*MAPX + px64]==0) {P->y -= P->dy;} + // P->x -= P->dx; + // P->y -= P->dy; + } + if(state[SDL_SCANCODE_D]) + P->th += (RADSPD/fps); + + if(P->th < 0) + P->th = 2*PI - 0.0001; + if(P->th > 2*PI) + P->th = 0.0; + + P->dx = cos(P->th)*(SPEED/fps); + P->dy = sin(P->th)*(SPEED/fps); + + return done; +} + +void drawMinimap(SDL_Renderer *renderer, int map[], struct player P) +{ + for(int y = 0; y 0) + { + SDL_SetRenderDrawColor(renderer, 255, 255, 255, 128); + } else { + SDL_SetRenderDrawColor(renderer, 0, 0, 0, 128); + } + + SDL_Rect wall = {x*TILESIZE/MAPSCALE, y*TILESIZE/MAPSCALE, (TILESIZE-4)/MAPSCALE, (TILESIZE-4)/MAPSCALE}; + SDL_RenderFillRect(renderer, &wall); + } + + SDL_Vertex arrow[3]; + arrow[0].position.x = (P.x+7*cos(P.th-PI/2))/MAPSCALE; + arrow[0].position.y = (P.y+7*sin(P.th-PI/2))/MAPSCALE; + arrow[0].color.r = 255; + arrow[0].color.g = 220; + arrow[0].color.b = 0; + arrow[0].color.a = 128; + + arrow[1].position.x = (P.x+7*cos(P.th+PI/2))/MAPSCALE; + arrow[1].position.y = (P.y+7*sin(P.th+PI/2))/MAPSCALE; + arrow[1].color.r = 255; + arrow[1].color.g = 220; + arrow[1].color.b = 0; + arrow[1].color.a = 128; + + arrow[2].position.x = (P.x+20*cos(P.th))/MAPSCALE; + arrow[2].position.y = (P.y+20*sin(P.th))/MAPSCALE; + arrow[2].color.r = 255; + arrow[2].color.g = 220; + arrow[2].color.b = 0; + arrow[2].color.a = 128; + + SDL_RenderGeometry(renderer, NULL, arrow, 3, NULL, 0); +} + +void drawSky(SDL_Surface *surface, struct player P) +{ + void *tpixels = NULL; + int pitch = 0; + SDL_LockTexture(skyT, NULL, &tpixels, &pitch); + Uint32 *edited = (Uint32 *)malloc(WIDTH*HEIGHT/2*sizeof(Uint32)); + for(int y = 1; y < HEIGHT/2; y++) + for(int x = 0; x < WIDTH; x++) + { + int xo = (int)(-P.th*WIDTH/(FOV*DEG)) - x; + if(xo < 0) {xo += WIDTH;} + xo %= WIDTH; + int index = (y*WIDTH + xo)*3; + char red = sky[index]; + char green = sky[index +1]; + char blue = sky[index +2]; + edited[y*WIDTH + x] = SDL_MapRGB(surface->format, red, green, blue); + } + memcpy(tpixels, edited, sizeof(WIDTH*HEIGHT/2*sizeof(Uint32))); + SDL_UnlockTexture(skyT); + free(edited); +} + +void drawRays(SDL_Renderer *renderer, SDL_Surface *surface, struct player P, int map[], int mapF[], int mapC[], float zbuffer[]) +{ + int mx, my, mp, dof, texture_iv = 4, texture_ih = 4, texture_i; + float rx, ry, ra, xo, yo, px, py, hlen, vlen, sinra, cosra, hx = 0, hy = 0, vx = 0, vy = 0, rdist; + void *tpixels = NULL; + int pitch = 0; + SDL_LockTexture(wallT, NULL, &tpixels, &pitch); + Uint32 *pixels = (Uint32 *)malloc(WIDTH*HEIGHT*sizeof(Uint32)); + + ra=P.th-FOV/2*DEG; + if(ra<0) + ra += 2*PI; + if(ra>2*PI) + ra -= 2*PI; + + px = P.x; + py = P.y; + float antan; + for(int r = 0; r>SQRTTILE)<0.001) + { + ry = (((int)py>>SQRTTILE)<>SQRTTILE; + my = (int)(ry)>>SQRTTILE; + mp = my*MAPX+mx; + + if(mp > 0 && mp < MAPX*MAPY && map[mp]>0){ + hx = rx; + hy = ry; + hlen = dist(px, py, hx, hy); + texture_ih = map[mp]-1; + break; + } else { + rx += xo; + ry += yo; + dof++; + } + } + // ----- по вертикальным ----- + dof = 0; + vlen = 100000; + cosra = cos(ra); + antan=-tan(ra); + if(cosra<-0.001) // "влево" + { + rx = (((int)px>>SQRTTILE)<0.001) + { + rx = (((int)px>>SQRTTILE)<>SQRTTILE; + my = (int)(ry)>>SQRTTILE; + mp = my*MAPX+mx; + + if(mp > 0 && mp < MAPX*MAPY && map[mp]>0){ + vx = rx; + vy = ry; + vlen = dist(px, py, vx, vy); + texture_iv = map[mp]-1; + break; + } else { + rx += xo; + ry += yo; + dof++; + } + } + + float shade = 1; + + if(vlen < hlen) + { + rx = vx; ry = vy; rdist = vlen; texture_i = texture_iv; + } + else { + rx = hx; ry = hy; rdist = hlen; shade = 0.6; texture_i = texture_ih; + } + + // ----- Рисуем стены ----- + + float corran = P.th - ra; + if(corran<0) + corran += 2*PI; + if(corran>2*PI) + corran -= 2*PI; + rdist *= cos(corran); // рыбий глаз + + float lineh = (TILESIZE*HEIGHT)/rdist; + float ty_step = 32.0 / lineh; + float ty_offset = 0; + + if(lineh>HEIGHT){ + ty_offset = (lineh-HEIGHT)/2.0; + lineh=HEIGHT; + } + float lineo = HEIGHT/2 - lineh/2; + + float ty = ty_offset*ty_step; // Текстурирование + float tx = 0; + if(vlen > hlen) { + tx = (int)(rx/(TILESIZE/32)) % 32; + if(ra < 180*DEG) {tx = 31-tx;} + } else { + tx = (int)(ry/(TILESIZE/32)) % 32; + if(ra>90*DEG && ra < 270*DEG) {tx = 31-tx;} + } + + int y = 0; + for(y = lineo; yformat, red, green, blue); + } + + // ----- рисуем пол ----- + for(y = lineo+lineh; yformat, red, green, blue); + + // ----- рисуем потолок ----- + mp = mapC[( (int)(ty/32.0)*MAPX + (int)(tx/32.0) )%(MAPX*MAPY)]; + + if(mp > 0) + { + index = (((int)(ty)&31)*32 + ((int)(tx)&31))*3 + (mp-1)*32*32*3; + // index %= sizeof(textures)/sizeof(textures[0]); + red = textures[index]*0.7; + green = textures[index+1]*0.7; + blue = textures[index+2]*0.7; + + for(int i = 0; iformat, red, green, blue); + } + } + + for(int p = 0; p < PIXELSIZE; p++){ + zbuffer[(int)(r*PIXELSIZE)+p] = rdist; + } + + ra += (double)FOV/((double)WIDTH/(double)PIXELSIZE)*DEG; + if(ra<0) + ra += 2*PI; + if(ra>2*PI) + ra -= 2*PI; + } + + memcpy(tpixels, pixels, (size_t)(surface->pitch * surface->h)); + SDL_UnlockTexture(wallT); + free(pixels); +} + +void drawSprites(SDL_Renderer *renderer, SDL_Surface *surface, struct player P, float zbuffer[]) +{ + void *tpixels = NULL; + int pitch = 0; + SDL_LockTexture(spriT, NULL, &tpixels, &pitch); + Uint32 *pixels = (Uint32 *)malloc(WIDTH*HEIGHT*sizeof(Uint32)); + + int spnum = sizeof(sp)/sizeof(sp[0]); + int sp_order[spnum]; + float sp_dist[spnum]; + for(int i = 0; i < spnum; i++) + { + sp_order[i] = i; + sp_dist[i] = ( (P.x - sp[i].x)*(P.x - sp[i].x) + (P.y - sp[i].y)*(P.y - sp[i].y) ); + } + sortSprites(sp_order, sp_dist, spnum); + + for(int i = 0; i < spnum; i++) + { + double relX = sp[sp_order[i]].x - P.x; // относительные координаты спрайта + double relY = sp[sp_order[i]].y - P.y; + /* трансформируем координаты в экранные засчет + умножения на обратную матрицу камеры */ + // | нпY -нпX | + // -1/(плX * нпY - нпX * плY) * | | + // | -плY плX | + // где (напX, напY) - вектор направления, (плX, плY) - вектор плоскости камеры + // __ ___ + // |пл| = |нап| * tg(FOV/2) + // |нап| = HEIGHT + // нап = (HEIGHT, 0) + // пл = (0, HEIGHT*tg(FOV/2)) + // vec dir = {HEIGHT, 0}; + // vec plane = {0, HEIGHT*tan(FOV/2*DEG)}; + vec dir = {TILESIZE, 0}; + vec plane = {0, TILESIZE*tan(FOV/2*DEG)}; + + rotateVector(&dir, P.th); + rotateVector(&plane, P.th); + + double invDet = 1.0 / (plane.x * dir.y - plane.y * dir.x); + + // | нпY -нпХ | | x_отн | | x_тр | + // 1/(плХ * нпY - нпХ * плY) * | | * | | = | | + // | плY плX | | y_отн | | y_тр | + // x_тр - координата X в плоскости камеры, y_тр - фактор масштабирования + double trX = invDet * (dir.y * relX - dir.x * relY); // трансформируем координаты в координаты камеры + double trY = invDet * ((-plane.y) * relX + plane.x * relY); + + int screenX = (int)((WIDTH/2) * (1 + trX / trY)); + + int sp_height = abs((int)(HEIGHT / trY)); + int startY = HEIGHT/2 - sp_height/2; if(startY < 0) {startY = 0;} + int endY = HEIGHT/2 + sp_height/2; if(endY >= HEIGHT){endY = HEIGHT-1;} + + int sp_width = abs((int)(WIDTH / trY)); // возможно, тут WIDTH? + int startX = screenX - sp_width/2; if(startX < 0) {startX = 0;} + int endX = screenX + sp_width/2; if(endX >= WIDTH){endX = WIDTH-1;} + + for(int s = startX; s < endX; s++) + { + int tx = (int)(32 * (s - (screenX - sp_width/2)) * 32 / sp_width) /32; + + if(trY > 0 && s > 0 && s < WIDTH && trY*TILESIZE < zbuffer[s]) + { + for(int y = startY; y < endY; y++) + { + int d = (y*2 - HEIGHT + sp_height)*(32/2); + int ty = (d * 32 / sp_height) /32; + + int mp = 4; + int index = (((int)(ty)&31)*32 + ((int)(tx)&31))*3 + (mp-1)*32*32*3; + int red = textures[index]; + int green = textures[index+1]; + int blue = textures[index+2]; + + for(int i = 0; iformat, red, green, blue); + } + + } + } + } + } + memcpy(tpixels, pixels, (size_t)(surface->pitch * surface->h)); + SDL_UnlockTexture(spriT); + free(pixels); +} + +int main(int argc, char *argv[]) +{ + SDL_Window *window = NULL; + SDL_Renderer *renderer = NULL; + SDL_Surface *surface = NULL; + // SDL_Texture *texture = NULL; + + SDL_Init(SDL_INIT_VIDEO); + + window = SDL_CreateWindow("Raycast", + SDL_WINDOWPOS_CENTERED, + SDL_WINDOWPOS_CENTERED, + WIDTH, + HEIGHT, + 0); + + renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); + SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND); + + surface = SDL_GetWindowSurface(window); + // SDL_SetSurfaceRLE(surface, 1); + // texture = SDL_CreateTexture(renderer, SDL_GetWindowPixelFormat(window), SDL_TEXTUREACCESS_STREAMING, WIDTH, HEIGHT); + skyT = SDL_CreateTexture(renderer, SDL_GetWindowPixelFormat(window), SDL_TEXTUREACCESS_STREAMING, WIDTH, HEIGHT); + wallT = SDL_CreateTexture(renderer, SDL_GetWindowPixelFormat(window), SDL_TEXTUREACCESS_STREAMING, WIDTH, HEIGHT); + spriT = SDL_CreateTexture(renderer, SDL_GetWindowPixelFormat(window), SDL_TEXTUREACCESS_STREAMING, WIDTH, HEIGHT); + + clock_t prevframe = clock(); + clock_t *pnt_pframe = &prevframe; + + int done = 0; // bool завершения программы + int mpbool = 0; // bool вкл/выкл карты + + // void *tpixels = NULL; + // int pitch = 0; + float zbuffer[WIDTH*PIXELSIZE+1] = {0}; + while(!done) + { + // --- ПРОВЕРКА СОБЫТИЙ --- + if(processEvents(window, &P, layoutW, &mpbool, pnt_pframe) == 1) + done = 1; + + // --- РЕНДЕР --- + SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); // фон + SDL_RenderClear(renderer); + + // SDL_LockTexture(texture, NULL, &tpixels, &pitch); + drawSky(surface, P); + drawRays(renderer, surface, P, layoutW, layoutF, layoutC, zbuffer); + drawSprites(renderer, surface, P, zbuffer); + // SDL_UnlockTexture(texture); + + SDL_RenderCopy(renderer, skyT, NULL, NULL); + SDL_RenderCopy(renderer, wallT, NULL, NULL); + SDL_RenderCopy(renderer, spriT, NULL, NULL); + // SDL_RenderCopy(renderer, texture, NULL, NULL); + + if(mpbool) + drawMinimap(renderer, layoutW, P); + + SDL_RenderPresent(renderer); + // SDL_Delay(DELAY); + } + + SDL_DestroyWindow(window); + SDL_DestroyRenderer(renderer); + // SDL_DestroyTexture(texture); + + SDL_Quit(); + printf("!%d!", errno); + return 0; +} \ No newline at end of file -- cgit v1.2.3