#include #include #include #include #include #include #define SPEED 7 #define RADSPD 0.2 #define DELAY 40 #define MAPX 8 #define MAPY 8 #define PI 3.1415926535 #define DEG 0.01745329 #define HEIGHT 512 #define WIDTH 1232 #define TILESIZE 64 //#define SQRTTILE 6 struct player { float x; float y; float dx; float dy; float th; }; float dist(float x1, float y1, float x2, float y2) { return ( sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)) ); } int processEvents(SDL_Window *window, struct player *P, int map[]) { int done = 0; SDL_Event event; 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; } } break; case SDL_QUIT: done = 1; break; } } const Uint8 *state = SDL_GetKeyboardState(NULL); if(state[SDL_SCANCODE_A]) P->th -= RADSPD; 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) >> 6; int py64 = (int)(P->y) >> 6; int pxadd = (int)(P->x + xoff) >> 6, pyadd = (int)(P->y + yoff) >> 6; int pxsub = (int)(P->x - xoff) >> 6, pysub = (int)(P->y - yoff) >> 6; 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;} } 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;} } if(state[SDL_SCANCODE_D]) P->th += RADSPD; if(P->th < 0) P->th = 2*PI - 0.00001; if(P->th > 2*PI) P->th = 0.0; P->dx = cos(P->th)*SPEED; P->dy = sin(P->th)*SPEED; return done; } void drawLevel(SDL_Renderer *renderer, int map[], struct player P) { for(int y = 0; y2*PI) ra -= 2*PI; px = P.x; py = P.y; float antan; for(int r = 0; r<90; r++) { // ----- по горизонтальным ----- hlen = 100000; dof = 0; sinra = sin(ra); if(sinra<-0.001) // "вверх" { antan=-1.0/tan(ra); ry = (((int)py>>6)<<6)-0.0001; rx = (py-ry)*antan+px; yo = -64; xo = -yo*antan; } else { if(sinra>0.001) { antan=-1.0/tan(ra); ry = (((int)py>>6)<<6)+64; rx = (py-ry)*antan+px; yo = 64; xo = -yo*antan; } else { rx = px; ry = py; dof = 8; }} while(dof<8) { mx = (int)(rx)>>6; my = (int)(ry)>>6; mp = my*MAPX+mx; if(mp > 0 && mp < MAPX*MAPY && map[mp]==1){ hx = rx; hy = ry; hlen = dist(px, py, hx, hy); dof = 8; } else { rx += xo; ry += yo; dof++; } } //SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255); //SDL_RenderDrawLineF(renderer, P.x, P.y, rx, ry); // ---------- // ----- по вертикальным ----- dof = 0; vlen = 100000; float cosra = cos(ra); if(cosra<-0.001) // "влево" { antan=-tan(ra); rx = (((int)px>>6)<<6)-0.0001; ry = (px-rx)*antan+py; xo = -64; yo = -xo*antan; } else { if(cosra>0.001) { antan=-tan(ra); rx = (((int)px>>6)<<6)+64; ry = (px-rx)*antan+py; xo = 64; yo = -xo*antan; } else { rx = px; ry = py; dof = 8; }} while(dof<8) { mx = (int)(rx)>>6; my = (int)(ry)>>6; mp = my*MAPX+mx; if(mp > 0 && mp < MAPX*MAPY && map[mp]==1){ vx = rx; vy = ry; vlen = dist(px, py, vx, vy); dof = 8; } else { rx += xo; ry += yo; dof++; } } if(vlen < hlen) { rx = vx; ry = vy; rdist = vlen; SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); } else { rx = hx; ry = hy; rdist = hlen; SDL_SetRenderDrawColor(renderer, 200, 0, 0, 255); } SDL_RenderDrawLineF(renderer, P.x, P.y, rx, ry); // ----- Рисуем стены ----- float corran = P.th - ra; if(corran<0) corran += 2*PI; if(corran>2*PI) corran -= 2*PI; rdist *= cos(corran); // рыбий глаз //rdist += 20; float lineh = (64*HEIGHT)/rdist; if(lineh>HEIGHT) lineh=HEIGHT; float lineo = HEIGHT/2 - lineh/2; SDL_Rect line = {64*MAPX+r*8, lineo, 8, lineh}; SDL_RenderFillRect(renderer, &line); ra += DEG; if(ra<0) ra += 2*PI; if(ra>2*PI) ra -= 2*PI; } } void Render(SDL_Renderer *renderer, int map[], struct player P) { SDL_SetRenderDrawColor(renderer, 128, 128, 128, 255); // фон SDL_RenderClear(renderer); SDL_SetRenderDrawColor(renderer, 90, 90, 100, 255); // пол SDL_Rect floor = {0, HEIGHT/2, WIDTH, HEIGHT/2}; SDL_RenderFillRect(renderer, &floor); drawLevel(renderer, map, P); drawRays(renderer, P, map); drawPlayer(renderer, P); SDL_RenderPresent(renderer); SDL_Delay(DELAY); } int main(void) { SDL_Window *window; SDL_Renderer *renderer; SDL_Init(SDL_INIT_VIDEO); window = SDL_CreateWindow("Raycast", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WIDTH, HEIGHT, 0); renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); struct player P = {100, 100, 0, 0, PI/2}; // int mapT = 64; int layout[MAPX*MAPY] = { 1,1,1,1,1,1,1,1, 1,0,1,0,0,0,0,1, 1,0,1,0,0,0,0,1, 1,0,1,0,0,0,0,1, 1,0,0,0,0,0,0,1, 1,0,0,0,0,1,0,1, 1,0,0,0,0,0,0,1, 1,1,1,1,1,1,1,1 }; int done = 0; // bool завершения программы while(!done) { // проверка событий if(processEvents(window, &P, layout) == 1) done = 1; //rendering Render(renderer, layout, P); } SDL_DestroyWindow(window); SDL_DestroyRenderer(renderer); SDL_Quit(); printf("!%d!", errno); return 0; }