Advertisement
TheBirkIsReal

Untitled

Apr 29th, 2019
207
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.68 KB | None | 0 0
  1. draw_level :: proc(level: ^Level) {
  2.     fov_x := math.to_radians(65.0);
  3.     fov_step := fov_x / f32(WIDTH);
  4.  
  5.     buffer: [dynamic]struct{int, int};
  6.  
  7.     for x := 0; x < WIDTH; x += 1 {
  8.         camera_x := 2.0 * f32(x) / f32(sb.width) - 1.0;
  9.         dir := math.Vec2{
  10.             player.dir.x + player.camera_plane.x * camera_x,
  11.             player.dir.y + player.camera_plane.y * camera_x,
  12.         };
  13.  
  14.         map_x := int(player.x);
  15.         map_y := int(player.y);
  16.  
  17.         delta := math.Vec2{abs(1/dir.x), abs(1/dir.y)};
  18.         dist := math.Vec2{};
  19.         step_x, step_y: int;
  20.         side: int; // 0 NS, 1 EW
  21.  
  22.         if dir.x > 0 {
  23.             step_x = 1;
  24.             dist.x = (f32(map_x) + 1.0 - player.x) * delta.x;
  25.         } else {
  26.             step_x = -1;
  27.             dist.x = (player.x - f32(map_x)) * delta.x;
  28.         }
  29.  
  30.         if dir.y > 0 {
  31.             step_y = 1;
  32.             dist.y = (f32(map_y) + 1.0 - player.y) * delta.y;
  33.         } else {
  34.             step_y = -1;
  35.             dist.y = (player.y - f32(map_y)) * delta.y;
  36.         }
  37.  
  38.         ray_cast:
  39.         for {
  40.             if dist.x < dist.y {
  41.                 dist.x += delta.x;
  42.                 map_x += step_x;
  43.                 side = 0;
  44.             } else {
  45.                 dist.y += delta.y;
  46.                 map_y += step_y;
  47.                 side = 1;
  48.             }
  49.  
  50.             if map_x < 0 || map_x >= level.width || map_y < 0 || map_y >= level.height {
  51.                 side = -1;
  52.                 break ray_cast;
  53.             }
  54.  
  55.             w := level.world[map_x+map_y*level.width];
  56.             if w == SOLID_EMPTY_WALL do continue;
  57.             if w > Wall.None {
  58.                 break ray_cast;
  59.             }
  60.         }
  61.  
  62.         if side < 0 do continue;
  63.  
  64.         distance: f32;
  65.         if side == 0 do distance = (f32(map_x) - player.x + (1.0 - f32(step_x)) / 2.0) / dir.x;
  66.         else         do distance = (f32(map_y) - player.y + (1.0 - f32(step_y)) / 2.0) / dir.y;
  67.  
  68.         zbuffer[x] = distance;
  69.  
  70.         height := int(f32(sb.height) / distance);
  71.  
  72.         camera_center := int(player.camera_center);
  73.         start := camera_center - height/2;
  74.         if start < 0 do start = 0;
  75.  
  76.         end := camera_center + height/2;
  77.         if end >= sb.height do end = sb.height-1;
  78.  
  79.  
  80.         wall_x: f32;
  81.         if side == 0 do wall_x = player.y + distance * dir.y;
  82.         else         do wall_x = player.x + distance * dir.x;
  83.         wall_x -= math.floor(wall_x);
  84.  
  85.         wall_sprite := wall_id[level.world[map_x+map_y*level.width]];
  86.  
  87.         texture_x := int(wall_x * f32(wall_sprite.width));
  88.         if side == 0 && dir.x > 0 do texture_x = wall_sprite.width - texture_x - 1;
  89.         if side == 1 && dir.y < 0 do texture_x = wall_sprite.width - texture_x - 1;
  90.         texture_y_step := f32(wall_sprite.height) / f32(height);
  91.  
  92.         for y := start; y < end; y += 1 {
  93.             d := y * 256 - (int(player.camera_center)*2)*128 + height * 128;
  94.             texture_y := ((d * wall_sprite.height) / height) / 256;
  95.  
  96.  
  97.             color := wall_sprite.pixels[texture_x+texture_y*wall_sprite.width];
  98.             if color != 0xFFC800C8 do sb.pixels[x+y*sb.width] = color;
  99.         }
  100.  
  101.         clear(&buffer);
  102.     }
  103.  
  104.     for i := 0; i < len(level.draw_sprites); i += 1 {
  105.         spr := &level.draw_sprites[i];
  106.         // only used for comparisons, so we keep them squared
  107.         spr.distance = ((player.x - spr.x) * (player.x - spr.x)) + ((player.y - spr.y) * (player.y - spr.y));
  108.     }
  109.     sort.quick_sort_proc(level.draw_sprites[:], proc(a, b: Draw_Sprite) -> int {
  110.         return int(b.distance) - int(a.distance);
  111.     });
  112.  
  113.     for i := 0; i < len(level.draw_sprites); i += 1 {
  114.         spr := &level.draw_sprites[i];
  115.         pos := spr.pos - player.pos;
  116.  
  117.         inv_det := 1.0 / (player.camera_plane.x * player.dir.y - player.dir.x * player.camera_plane.y);
  118.         transform_x := inv_det * (player.dir.y * pos.x - player.dir.x * pos.y);
  119.         transform_y := inv_det * (-player.camera_plane.y * pos.x + player.camera_plane.x * pos.y);
  120.  
  121.         vertical_offset_screen := int(spr.vertical_offset / transform_y);
  122.  
  123.         screen_x := int((f32(sb.width) / 2) * (1 + transform_x / transform_y));
  124.  
  125.         height := int(abs(f32(sb.height) / transform_y) * spr.scale_y);
  126.  
  127.         camera_center := int(player.camera_center);
  128.         y_start := camera_center - height/2 + vertical_offset_screen;
  129.         if y_start < 0 do y_start = 0;
  130.  
  131.         y_end := camera_center + height/2 + vertical_offset_screen;
  132.         if y_end >= sb.height do y_end = sb.height-1;
  133.  
  134.         width := int(abs(f32(sb.height) / transform_y) * spr.scale_x);
  135.         x_start := -width / 2 + screen_x;
  136.         if x_start < 0 do x_start = 0;
  137.  
  138.         x_end := width / 2 + screen_x;
  139.         if x_end >= sb.width do x_end = sb.width-1;
  140.  
  141.         for x := x_start; x < x_end; x += 1 {
  142.             texture_x := int(256 * (x - (-width / 2 + screen_x)) * spr.sprite.width / width) / 256;
  143.  
  144.             if transform_y > 0 && x > 0 && x <= sb.width && transform_y < zbuffer[x] {
  145.                 for y := y_start; y < y_end; y += 1 {
  146.                     d := (y - vertical_offset_screen) * 256 - (int(player.camera_center)*2)*128 + height * 128;
  147.                     texture_y := ((d * spr.sprite.height) / height) / 256;
  148.  
  149.                     color := spr.sprite.pixels[texture_x+texture_y*spr.sprite.width];
  150.                     if color != 0xFFC800C8 do sb.pixels[x+y*sb.width] = color;
  151.                 }
  152.             }
  153.         }
  154.     }
  155.  
  156.     clear(&level.draw_sprites);
  157. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement