aboutsummaryrefslogtreecommitdiff
path: root/src/main.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.zig')
-rwxr-xr-xsrc/main.zig157
1 files changed, 157 insertions, 0 deletions
diff --git a/src/main.zig b/src/main.zig
new file mode 100755
index 0000000..2b5f7f2
--- /dev/null
+++ b/src/main.zig
@@ -0,0 +1,157 @@
+const sf = struct {
+ pub usingnamespace @import("sfml");
+ pub usingnamespace graphics;
+ pub usingnamespace window;
+};
+
+const isKeyPressed = sf.window.keyboard.isKeyPressed;
+
+const std = @import("std");
+usingnamespace @import("raycast.zig");
+usingnamespace @import("renderConstants.zig");
+usingnamespace @import("map.zig");
+
+const screenWidth = 1280;
+const screenHeight = 960;
+
+fn renderWall(
+ window: sf.graphics.RenderWindow,
+ sprite: sf.graphics.Sprite,
+ col: i32, // which column
+ top: f32, // top of wall
+ height: f32, // how tall
+ texfrac: f32, // how far along the texture
+ texture: u8, // which texture index
+) !void {
+ const hFact = screenWidth / planeWidth;
+ const vFact = screenHeight / planeHeight;
+ const xpos = @intToFloat(f32, col) * hFact;
+ const length = height * vFact;
+ const starty = (screenHeight + vFact * planeHeight) / 2 - top * vFact;
+ const tind = @as(c_int, texture) * @floatToInt(c_int, 1 + wallTextureDim);
+
+ sprite.setPosition(.{ .x = xpos, .y = starty });
+ sprite.setScale(.{ .x = hFact, .y = length / wallTextureDim });
+ sprite.setTextureRect(.{ .top = 0, .left = tind + @floatToInt(c_int, texfrac * wallTextureDim), .width = 1, .height = wallTextureDim });
+ window.draw(sprite, null);
+}
+
+pub fn main() !void {
+ const PI = std.math.pi;
+
+ // Setup player and map
+ //--------------------------------------------------------------------------
+
+ var player = Player.new(15.75, 1.5, // pos
+ PI / 2.0, // ang
+ @intToFloat(f32, planeWidth), @intToFloat(f32, planeHeight));
+
+ var gpa = std.heap.GeneralPurposeAllocator(.{}){};
+ defer _ = gpa.deinit();
+
+ var map = try Map.new(32, 32, &gpa.allocator);
+ defer map.deinit();
+
+ var y: u32 = 0;
+ while (y < 32) : (y += 1) {
+ map.cells.items[y * 32 + 00] = Cell{ .height = MAX_HEIGHT };
+ map.cells.items[y * 32 + 31] = Cell{ .height = MAX_HEIGHT };
+ map.cells.items[31 * 32 + y] = Cell{ .height = MAX_HEIGHT };
+ map.cells.items[00 * 32 + y] = Cell{ .height = MAX_HEIGHT };
+ }
+
+ map.cells.items[y * 15 + 15] = Cell{ .height = MAX_HEIGHT, .wall_texture = 1 };
+ map.cells.items[y * 15 + 14] = Cell{ .height = MAX_HEIGHT / 1.5, .wall_texture = 1 };
+
+ // Initialise SFML
+ //--------------------------------------------------------------------------
+
+ var window = try sf.RenderWindow.create(.{ .x = screenWidth, .y = screenHeight }, 32, "zirc", sf.window.Style.none);
+ defer window.destroy();
+
+ window.setFramerateLimit(30);
+
+ var backRect = try sf.RectangleShape.create(.{ .x = screenWidth, .y = screenHeight / 2 });
+ defer backRect.destroy();
+
+ backRect.setPosition(.{ .x = 0, .y = screenHeight / 2 });
+ backRect.setFillColor(sf.Color.fromRGB(50, 50, 50));
+
+ // Load the background skybox, really `skycylinder', and assign it to a
+ // sprite -- it's set to repeating so that it goes on forever. We need to
+ // scale the sprite so that drawing 1/4 of backTextureWidth fills the screen
+ // horizontally, and drawing backTextureHeight fills half of the screen
+ // vertically.
+ var backTexture = try sf.Texture.createFromFile("back.png");
+ defer backTexture.destroy();
+
+ backTexture.setSmooth(false); // looks worse => better!
+ backTexture.setRepeated(true);
+
+ var backSprite = try sf.Sprite.createFromTexture(backTexture);
+ defer backSprite.destroy();
+
+ backSprite.setScale(.{ .x = 4.0 * @intToFloat(f32, screenWidth) / backTextureWidth, .y = @intToFloat(f32, screenHeight) / (2 * backTextureHeight) });
+
+ // Load brick texture!
+ var wallTexture = try sf.Texture.createFromFile("walls.png");
+ defer wallTexture.destroy();
+ wallTexture.setSmooth(false); // looks worse => better!
+
+ var wallSprite = try sf.Sprite.createFromTexture(wallTexture);
+ defer wallSprite.destroy();
+
+ // Start your engines!
+ //--------------------------------------------------------------------------
+
+ while (window.isOpen()) {
+ while (window.pollEvent()) |event| {
+ if (event == .closed) window.close();
+ }
+
+ if (isKeyPressed(.Escape)) window.close();
+
+ const rotation = 2.0 * PI / 100.0;
+ if (isKeyPressed(.R)) player.ang += rotation;
+ if (isKeyPressed(.T)) player.ang -= rotation;
+
+ player.acc_x = 0;
+ player.acc_y = 0;
+ const acc_mag = 50;
+ if (isKeyPressed(.Right)) {
+ player.acc_x += std.math.cos(player.ang - PI / 2.0) * acc_mag;
+ player.acc_y += std.math.sin(player.ang - PI / 2.0) * acc_mag;
+ }
+ if (isKeyPressed(.Left)) {
+ player.acc_x -= std.math.cos(player.ang - PI / 2.0) * acc_mag;
+ player.acc_y -= std.math.sin(player.ang - PI / 2.0) * acc_mag;
+ }
+ if (isKeyPressed(.Up) or isKeyPressed(.F)) {
+ player.acc_x += std.math.cos(player.ang) * acc_mag;
+ player.acc_y += std.math.sin(player.ang) * acc_mag;
+ }
+ if (isKeyPressed(.Down) or isKeyPressed(.S)) {
+ player.acc_x -= std.math.cos(player.ang) * acc_mag;
+ player.acc_y -= std.math.sin(player.ang) * acc_mag;
+ }
+
+ window.clear(sf.Color.fromRGB(100, 100, 100));
+
+ const back_scroll = @floatToInt(i32, -backTextureWidth * player.ang / (2 * PI));
+ backSprite.setTextureRect(sf.IntRect{
+ .left = back_scroll, // fix location of texture in the sky
+ .top = 0,
+ // scaling ensures that the next two paint it across the width of
+ // the screen, and for half the height of the screen
+ .width = backTextureWidth / 4.0, // 1/4 of texture per screen
+ .height = backTextureHeight, // full height of texture visible
+ });
+ window.draw(backSprite, null);
+
+ try player.renderMapUsing(window, wallSprite, map, renderWall);
+
+ window.display();
+
+ player.tick();
+ }
+}