Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- draw_level :: proc(level: ^Level) {
- fov_x := math.to_radians(65.0);
- fov_step := fov_x / f32(WIDTH);
- buffer: [dynamic]struct{int, int};
- for x := 0; x < WIDTH; x += 1 {
- camera_x := 2.0 * f32(x) / f32(sb.width) - 1.0;
- dir := math.Vec2{
- player.dir.x + player.camera_plane.x * camera_x,
- player.dir.y + player.camera_plane.y * camera_x,
- };
- map_x := int(player.x);
- map_y := int(player.y);
- delta := math.Vec2{abs(1/dir.x), abs(1/dir.y)};
- dist := math.Vec2{};
- step_x, step_y: int;
- side: int; // 0 NS, 1 EW
- if dir.x > 0 {
- step_x = 1;
- dist.x = (f32(map_x) + 1.0 - player.x) * delta.x;
- } else {
- step_x = -1;
- dist.x = (player.x - f32(map_x)) * delta.x;
- }
- if dir.y > 0 {
- step_y = 1;
- dist.y = (f32(map_y) + 1.0 - player.y) * delta.y;
- } else {
- step_y = -1;
- dist.y = (player.y - f32(map_y)) * delta.y;
- }
- ray_cast:
- for {
- if dist.x < dist.y {
- dist.x += delta.x;
- map_x += step_x;
- side = 0;
- } else {
- dist.y += delta.y;
- map_y += step_y;
- side = 1;
- }
- if map_x < 0 || map_x >= level.width || map_y < 0 || map_y >= level.height {
- side = -1;
- break ray_cast;
- }
- w := level.world[map_x+map_y*level.width];
- if w == SOLID_EMPTY_WALL do continue;
- if w > Wall.None {
- break ray_cast;
- }
- }
- if side < 0 do continue;
- distance: f32;
- if side == 0 do distance = (f32(map_x) - player.x + (1.0 - f32(step_x)) / 2.0) / dir.x;
- else do distance = (f32(map_y) - player.y + (1.0 - f32(step_y)) / 2.0) / dir.y;
- zbuffer[x] = distance;
- height := int(f32(sb.height) / distance);
- camera_center := int(player.camera_center);
- start := camera_center - height/2;
- if start < 0 do start = 0;
- end := camera_center + height/2;
- if end >= sb.height do end = sb.height-1;
- wall_x: f32;
- if side == 0 do wall_x = player.y + distance * dir.y;
- else do wall_x = player.x + distance * dir.x;
- wall_x -= math.floor(wall_x);
- wall_sprite := wall_id[level.world[map_x+map_y*level.width]];
- texture_x := int(wall_x * f32(wall_sprite.width));
- if side == 0 && dir.x > 0 do texture_x = wall_sprite.width - texture_x - 1;
- if side == 1 && dir.y < 0 do texture_x = wall_sprite.width - texture_x - 1;
- texture_y_step := f32(wall_sprite.height) / f32(height);
- for y := start; y < end; y += 1 {
- d := y * 256 - (int(player.camera_center)*2)*128 + height * 128;
- texture_y := ((d * wall_sprite.height) / height) / 256;
- color := wall_sprite.pixels[texture_x+texture_y*wall_sprite.width];
- if color != 0xFFC800C8 do sb.pixels[x+y*sb.width] = color;
- }
- clear(&buffer);
- }
- for i := 0; i < len(level.draw_sprites); i += 1 {
- spr := &level.draw_sprites[i];
- // only used for comparisons, so we keep them squared
- spr.distance = ((player.x - spr.x) * (player.x - spr.x)) + ((player.y - spr.y) * (player.y - spr.y));
- }
- sort.quick_sort_proc(level.draw_sprites[:], proc(a, b: Draw_Sprite) -> int {
- return int(b.distance) - int(a.distance);
- });
- for i := 0; i < len(level.draw_sprites); i += 1 {
- spr := &level.draw_sprites[i];
- pos := spr.pos - player.pos;
- inv_det := 1.0 / (player.camera_plane.x * player.dir.y - player.dir.x * player.camera_plane.y);
- transform_x := inv_det * (player.dir.y * pos.x - player.dir.x * pos.y);
- transform_y := inv_det * (-player.camera_plane.y * pos.x + player.camera_plane.x * pos.y);
- vertical_offset_screen := int(spr.vertical_offset / transform_y);
- screen_x := int((f32(sb.width) / 2) * (1 + transform_x / transform_y));
- height := int(abs(f32(sb.height) / transform_y) * spr.scale_y);
- camera_center := int(player.camera_center);
- y_start := camera_center - height/2 + vertical_offset_screen;
- if y_start < 0 do y_start = 0;
- y_end := camera_center + height/2 + vertical_offset_screen;
- if y_end >= sb.height do y_end = sb.height-1;
- width := int(abs(f32(sb.height) / transform_y) * spr.scale_x);
- x_start := -width / 2 + screen_x;
- if x_start < 0 do x_start = 0;
- x_end := width / 2 + screen_x;
- if x_end >= sb.width do x_end = sb.width-1;
- for x := x_start; x < x_end; x += 1 {
- texture_x := int(256 * (x - (-width / 2 + screen_x)) * spr.sprite.width / width) / 256;
- if transform_y > 0 && x > 0 && x <= sb.width && transform_y < zbuffer[x] {
- for y := y_start; y < y_end; y += 1 {
- d := (y - vertical_offset_screen) * 256 - (int(player.camera_center)*2)*128 + height * 128;
- texture_y := ((d * spr.sprite.height) / height) / 256;
- color := spr.sprite.pixels[texture_x+texture_y*spr.sprite.width];
- if color != 0xFFC800C8 do sb.pixels[x+y*sb.width] = color;
- }
- }
- }
- }
- clear(&level.draw_sprites);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement