summaryrefslogtreecommitdiff
path: root/bbbackup.c
diff options
context:
space:
mode:
authorЕгор Львов <workregor@mail.ru>2023-03-27 11:25:27 +0300
committerЕгор Львов <workregor@mail.ru>2023-03-27 11:25:27 +0300
commit3c0a3b8413ee58a3e5678075c862e95f7c8395c6 (patch)
tree8ca9eba9378f921636788fee7664c2bd63bc40ff /bbbackup.c
Начальный коммит
Diffstat (limited to 'bbbackup.c')
-rw-r--r--bbbackup.c518
1 files changed, 518 insertions, 0 deletions
diff --git a/bbbackup.c b/bbbackup.c
new file mode 100644
index 0000000..9eb88a1
--- /dev/null
+++ b/bbbackup.c
@@ -0,0 +1,518 @@
+#include <SDL2/SDL.h>
+#include <SDL2/SDL_image.h>
+#include <SDL2/SDL_timer.h>
+
+#include <stdio.h>
+#include <math.h>
+#include <errno.h>
+#include <time.h>
+
+#include "textures/textures.ppm"
+
+#define SPEED 1.5 // скорость движения игрока
+#define RADSPD 0.05 // скорость поворота игрока
+#define FOV 60 // поле зрения, в градусах
+// #define DELAY 1 // задержка между рендером
+#define MAPX 16 // размер (массива) карты по X
+#define MAPY 16 // размер (массива) карты по Y
+#define PI 3.1415926535 // значение числа пи
+#define DEG 0.01745329 // знаечние 1 градуса в радианах
+#define HEIGHT 512 // высота экрана; также расстояние до умозрительного "экрана"
+#define WIDTH 960 // ширина экрана
+#define PIXELSIZE 4 // размер "пикселя"
+#define TILESIZE 32 // размер одной клетки карты; также "реальная" высота стены
+#define SQRTTILE 5 // двоичный логарифм TILESIZE - используется для побитовых операций
+#define MAPSCALE 2 // масштаб миникарты
+
+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 *mpbool, clock_t *prevframe)
+{
+ // Вычисление FPS
+ clock_t frame;
+ float fps;
+
+ frame = clock();
+ fps = CLOCKS_PER_SEC/(double)(frame - *prevframe);
+ *prevframe = frame;
+ printf("%d\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: // взаимодействие
+ if(map[pyadd*MAPX + pxadd] == 4) // дверь
+ map[pyadd*MAPX + pxadd] = 0;
+ }
+ }
+ break;
+
+ case SDL_QUIT:
+ done = 1;
+ break;
+ }
+ }
+
+ const Uint8 *state = SDL_GetKeyboardState(NULL);
+ if(state[SDL_SCANCODE_A])
+ P->th -= RADSPD;
+
+
+ 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)*(75/fps);
+ P->dy = sin(P->th)*(75/fps);
+
+ return done;
+}
+
+void drawLevel(SDL_Renderer *renderer, int map[], struct player P)
+{
+ for(int y = 0; y<MAPY; y++)
+ for(int x = 0; x<MAPX; x++)
+ {
+ if(map[y*MAPX + x] > 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/MAPSCALE-2, TILESIZE/MAPSCALE-2};
+ SDL_RenderFillRect(renderer, &wall);
+ }
+}
+
+void drawPlayer(SDL_Renderer *renderer, struct player P)
+{
+ 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 drawRays(SDL_Renderer *renderer, SDL_Surface *surface, struct player P, int map[], int mapF[], int mapC[])
+{
+ int mx, my, mp, dof, texture_iv, texture_ih, texture_i, pitch;
+ float rx, ry, ra, xo, yo, px, py, hlen, vlen, sinra, hx, hy, vx, vy, rdist;
+ void *tpixels;
+ Uint32 *pixels = (Uint32 *)surface->pixels;
+ SDL_PixelFormat *format = surface->format;
+ SDL_Texture *texture = SDL_CreateTexture(renderer, format->format, SDL_TEXTUREACCESS_STREAMING, WIDTH, HEIGHT);
+
+ ra=P.th-30*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<WIDTH/PIXELSIZE; r++)
+ {
+ // ----- по горизонтальным -----
+ hlen = 100000;
+ dof = 0;
+ sinra = sin(ra);
+ if(sinra<-0.001) // "вверх"
+ {
+ antan=-1.0/tan(ra);
+ ry = (((int)py>>SQRTTILE)<<SQRTTILE)-0.0001;
+ rx = (py-ry)*antan+px;
+ yo = -TILESIZE;
+ xo = -yo*antan;
+ } else {
+ if(sinra>0.001)
+ {
+ antan=-1.0/tan(ra);
+ ry = (((int)py>>SQRTTILE)<<SQRTTILE)+TILESIZE;
+ rx = (py-ry)*antan+px;
+ yo = TILESIZE;
+ xo = -yo*antan;
+ }
+ else
+ {
+ rx = px;
+ ry = py;
+ dof = 16;
+ }}
+
+ while(dof<16)
+ {
+ mx = (int)(rx)>>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;
+ dof = 16;
+ } else {
+ rx += xo;
+ ry += yo;
+ dof++;
+ }
+ }
+ // ----- по вертикальным -----
+ dof = 0;
+ vlen = 100000;
+ float cosra = cos(ra);
+ if(cosra<-0.001) // "влево"
+ {
+ antan=-tan(ra);
+ rx = (((int)px>>SQRTTILE)<<SQRTTILE)-0.0001;
+ ry = (px-rx)*antan+py;
+ xo = -TILESIZE;
+ yo = -xo*antan;
+ } else {
+ if(cosra>0.001)
+ {
+ antan=-tan(ra);
+ rx = (((int)px>>SQRTTILE)<<SQRTTILE)+TILESIZE;
+ ry = (px-rx)*antan+py;
+ xo = TILESIZE;
+ yo = -xo*antan;
+ }
+ else
+ {
+ rx = px;
+ ry = py;
+ dof = 16;
+ }}
+
+ while(dof<16)
+ {
+ mx = (int)(rx)>>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;
+ dof = 16;
+ } 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;
+ 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;
+ for(y = 0; y<lineh; y++, ty+=ty_step)
+ {
+ int index = ((int)ty*32 + (int)tx)*3+(texture_i*32*32*3);
+ int red = textures[index]*shade;
+ int green = textures[index+1]*shade;
+ int blue = textures[index+2]*shade;
+
+ // SDL_SetRenderDrawColor(renderer, red, green, blue, 255);
+ // SDL_Rect px = {r*4, lineo+y, 4, 1};
+ // SDL_RenderFillRect(renderer, &px);
+ if(SDL_MUSTLOCK(surface)) {SDL_LockSurface(surface);}
+ for(int i = 0; i<PIXELSIZE; i++)
+ pixels[(int)(lineo+y)*WIDTH + r*PIXELSIZE +i] = SDL_MapRGB(format, red, green, blue);
+ }
+
+ // ----- рисуем пол -----
+ for(y = lineo+lineh; y<HEIGHT; y++)
+ {
+ float dy = y - (HEIGHT/2.0);
+ tx = P.x + cos(ra)*(0.4941406*HEIGHT)*32/(dy*cos(corran));
+ ty = P.y + sin(ra)*(0.4941406*HEIGHT)*32/(dy*cos(corran));
+ int mp = mapF[(int)(ty/32.0)*MAPX + (int)(tx/32.0)]*32*32;
+
+ int index = (((int)(ty)&31)*32 + ((int)(tx)&31))*3 + mp*3;
+ int red = textures[index]*0.7;
+ int green = textures[index+1]*0.7;
+ int blue = textures[index+2]*0.7;
+
+ // SDL_SetRenderDrawColor(renderer, red, green, blue, 255);
+ // SDL_Rect line = {r*4, y, 4, 4};
+ // SDL_RenderFillRect(renderer, &line);
+ for(int i = 0; i<PIXELSIZE; i++)
+ pixels[y*WIDTH + r*4 +i] = SDL_MapRGB(format, red, green, blue);
+
+ mp = mapC[(int)(ty/32.0)*MAPX + (int)(tx/32.0)]*32*32;
+ index = (((int)(ty)&31)*32 + ((int)(tx)&31))*3 + mp*3;
+ red = textures[index]*0.7;
+ green = textures[index+1]*0.7;
+ blue = textures[index+2]*0.7;
+
+ // SDL_SetRenderDrawColor(renderer, red, green, blue, 255);
+ // SDL_Rect line_c = {r*4, HEIGHT-y, 4, 4};
+ // SDL_RenderFillRect(renderer, &line_c);
+ for(int i = 0; i<PIXELSIZE; i++)
+ pixels[(HEIGHT-y)*WIDTH + r*4 +i] = SDL_MapRGB(format, red, green, blue);
+
+ if(SDL_MUSTLOCK(surface)) {SDL_UnlockSurface(surface);}
+ }
+
+ ra += (double)FOV/((double)WIDTH/(double)PIXELSIZE)*DEG;
+ if(ra<0)
+ ra += 2*PI;
+ if(ra>2*PI)
+ ra -= 2*PI;
+ }
+
+ SDL_LockTexture(texture, NULL, &tpixels, &pitch);
+ memcpy(tpixels, pixels, (size_t)(surface->pitch * surface->h));
+ SDL_UnlockTexture(texture);
+ tpixels = NULL;
+ SDL_RenderCopy(renderer, texture, NULL, NULL);
+}
+
+void Render(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Texture *texture, SDL_Window *window, int map[], int mapF[], int mapC[], struct player P, int *mpbool)
+{
+ SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); // фон
+ SDL_RenderClear(renderer);
+ drawRays(renderer, surface, P, map, mapF, mapC);
+
+ if(*mpbool) {
+ drawLevel(renderer, map, P);
+ drawPlayer(renderer, P);
+ }
+
+ // SDL_UpdateWindowSurface(window);
+ SDL_RenderPresent(renderer);
+ // SDL_Delay(DELAY);
+}
+
+int main(void)
+{
+ 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_UNDEFINED,
+ SDL_WINDOWPOS_UNDEFINED,
+ WIDTH,
+ HEIGHT,
+ 0);
+
+ renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
+ SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
+
+ surface = SDL_GetWindowSurface(window);
+ texture = SDL_CreateTextureFromSurface(renderer, surface);
+
+ struct player P = {50, 50, 0, 0, PI/2};
+
+ clock_t prevframe = clock();
+ clock_t *pnt_pframe = &prevframe;
+
+ int layoutW[MAPX*MAPY] =
+ {
+ /* 10 12 14 */
+ 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,//0
+ 3,0,0,3,3,0,0,0,0,0,0,0,0,0,0,3,//1
+ 3,0,0,3,3,0,3,0,0,3,0,0,3,0,0,3,//2
+ 3,0,0,3,3,0,0,0,0,0,0,0,0,0,0,3,//3
+ 3,0,0,3,3,0,3,0,0,3,0,0,3,0,0,3,//4
+ 3,0,0,3,3,0,0,0,0,0,0,0,0,0,0,3,//5
+ 3,0,0,3,3,3,3,3,3,3,3,3,3,0,0,3,//6
+ 3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,//7
+ 3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,//8
+ 3,3,4,3,3,0,2,0,2,0,2,0,2,0,0,3,//9
+ 3,0,0,0,3,3,3,3,3,4,3,3,3,0,0,3,//10
+ 3,3,0,3,3,0,0,0,0,0,0,3,3,0,0,3,//11
+ 3,0,0,0,3,0,3,3,3,3,0,3,3,0,0,3,//12
+ 3,3,0,3,3,0,3,3,3,3,3,3,3,0,0,3,//13
+ 3,0,0,0,3,0,0,0,0,0,0,0,4,0,0,3,//14
+ 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,//15
+ /*0,1,2,3,4,5,6,7,8,9, 11 13 15*/
+ };
+
+ int layoutF[MAPX*MAPY] =
+ {
+ /* 10 12 14 */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,//0
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,//1
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,//2
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,//3
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,//4
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,//5
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,//6
+ 1,1,1,0,0,0,0,0,0,0,0,0,0,2,2,2,//7
+ 1,1,1,0,0,0,0,0,0,0,0,0,0,2,2,2,//8
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,//9
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,//10
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,//11
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,//12
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,//13
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,//14
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,//15
+ /*0,1,2,3,4,5,6,7,8,9, 11 13 15*/
+ };
+
+ int layoutC[MAPX*MAPY] =
+ {
+ /* 10 12 14 */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,//0
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,//1
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,//2
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,//3
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,//4
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,//5
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,//6
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,//7
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,//8
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,//9
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,//10
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,//11
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,//12
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,//13
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,//14
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,//15
+ /*0,1,2,3,4,5,6,7,8,9, 11 13 15*/
+ };
+
+ int done = 0; // bool завершения программы
+ int mpbool = 0; // bool вкл/выкл карты
+
+ while(!done)
+ {
+ // проверка событий
+ if(processEvents(window, &P, layoutW, &mpbool, pnt_pframe) == 1)
+ done = 1;
+ //rendering
+ Render(renderer, surface, texture, window, layoutW, layoutF, layoutC, P, &mpbool);
+ }
+
+ SDL_DestroyWindow(window);
+ SDL_DestroyRenderer(renderer);
+
+ SDL_Quit();
+ printf("!%d!", errno);
+ return 0;
+} \ No newline at end of file