Remove SDL & OpenGL dependency

Make the code compile without the need for SDL and OpenGL with
the intention of migrating towards Raylib. What is going to be needed in
the future has been commented, and the other stuff removed. It runs but
apparently does nothing.
This commit is contained in:
Dusk 2023-09-21 13:53:52 +02:00
parent ed031c9b8c
commit 821162015a
17 changed files with 305 additions and 487 deletions

9
.gitmodules vendored
View File

@ -1,9 +0,0 @@
[submodule "lib/SDL.zig"]
path = lib/SDL.zig
url = ../SDL.zig
[submodule "lib/zgl"]
path = lib/zgl
url = https://github.com/ziglibs/zgl
[submodule "lib/zlm"]
path = lib/zlm
url = https://github.com/ziglibs/zlm

View File

@ -1,5 +1,4 @@
const std = @import("std");
const Sdk = @import("lib/SDL.zig/build.zig");
pub fn build(b: *std.Build) void {
// Standard target options allows the person running `zig build` to choose
@ -19,18 +18,6 @@ pub fn build(b: *std.Build) void {
.optimize = optimize,
});
const sdk = Sdk.init(b, null);
sdk.link(exe, .dynamic);
exe.linkSystemLibrary("sdl2_ttf");
exe.linkSystemLibrary("sdl2_image");
exe.linkSystemLibrary("gl");
exe.linkSystemLibrary("epoxy");
const relative = std.Build.FileSource.relative;
exe.addModule("zgl", b.createModule(.{ .source_file = relative("lib/zgl/zgl.zig") }));
exe.addModule("zlm", b.createModule(.{ .source_file = relative("lib/zlm/zlm.zig") }));
exe.addModule("sdl2", sdk.getWrapperModule());
b.installArtifact(exe);
const run_cmd = b.addRunArtifact(exe);

@ -1 +0,0 @@
Subproject commit 36e192a74f3be878766e1aa3e6f13ba5f92650cb

@ -1 +0,0 @@
Subproject commit b40eff53f384ced9481d1c8754651976de22588c

@ -1 +0,0 @@
Subproject commit 2dc8c0db2e92529bb618ca639bb891b6187fa579

View File

@ -1,17 +1,19 @@
const Self = @This();
const SDL = @import("sdl2");
//const SDL = @import("sdl2");
activate: bool = false,
holding: bool = false,
scancode: SDL.Scancode, // SDL Keycode
//scancode: SDL.Scancode, // SDL Keycode
callback: *const anyopaque, // MUST be a function with void return
pub fn init(scancode: SDL.Scancode, callback: *const anyopaque) Self {
pub fn init(scancode: i1, callback: *const anyopaque) Self {
_ = scancode;
return Self{
.scancode = scancode,
//.scancode = scancode,
.callback = callback,
};
}
pub fn call(self: Self, state: anytype) void {
@call(.auto, @ptrCast(*const fn (@TypeOf(state)) void, self.callback), .{state});
@call(.auto, @as(*const fn (@TypeOf(state)) void, @ptrCast(self.callback)), .{state});
}

View File

@ -1,5 +1,4 @@
const std = @import("std");
const SDL = @import("sdl2");
const Grid = @import("Game/Grid.zig");
const Piece = @import("Game/Piece.zig");
@ -37,13 +36,13 @@ piece: Piece,
shadow: Piece,
action_list: ActionList = .{
.right = Action.init(SDL.Scancode.d, actionRight), // Right
.left = Action.init(SDL.Scancode.a, actionLeft), // Left
.down = Action.init(SDL.Scancode.s, actionDown), // Down
.hard = Action.init(SDL.Scancode.w, actionHard), // Instant Drop
.swap = Action.init(SDL.Scancode.space, actionSwap), // Swap Piece
.rot_r = Action.init(SDL.Scancode.right, actionRotR), // Rotate
.rot_l = Action.init(SDL.Scancode.left, actionRotL), // Rotate
.right = Action.init(0, actionRight), // Right
.left = Action.init(0, actionLeft), // Left
.down = Action.init(0, actionDown), // Down
.hard = Action.init(0, actionHard), // Instant Drop
.swap = Action.init(0, actionSwap), // Swap Piece
.rot_r = Action.init(0, actionRotR), // Rotate
.rot_l = Action.init(0, actionRotL), // Rotate
},
timer_down: Timer,
@ -168,31 +167,31 @@ pub fn tick(self: *Self) State {
}
// KEY EVENTS
var key_state = SDL.getKeyboardState();
// var key_state = SDL.getKeyboardState();
const action_fields = std.meta.fields(ActionList);
inline for (action_fields) |field| {
std.debug.print("\n{any}", .{field.name});
const action = &@field(self.action_list, field.name);
if (key_state.isPressed(action.*.scancode) and !action.*.holding) {
action.*.holding = true;
action.*.activate = true;
}
if (!key_state.isPressed(action.*.scancode)) {
action.*.holding = false;
}
// const action_fields = std.meta.fields(ActionList);
// inline for (action_fields) |field| {
// std.debug.print("\n{any}", .{field.name});
// const action = &@field(self.action_list, field.name);
// if (key_state.isPressed(action.*.scancode) and !action.*.holding) {
// action.*.holding = true;
// action.*.activate = true;
// }
// if (!key_state.isPressed(action.*.scancode)) {
// action.*.holding = false;
// }
// Action
if (action.*.activate) {
action.*.activate = false;
action.*.call(self);
}
}
// // Action
// if (action.*.activate) {
// action.*.activate = false;
// action.*.call(self);
// }
// }
// Update Shadow
{
self.shadow = movement.shadow(self.grid, self.piece);
self.shadow.color.a /= 4;
//self.shadow.color.a /= 4;
}
// Check for a top out

View File

@ -10,17 +10,17 @@ prng: std.rand.DefaultPrng,
pub fn init() Self {
var ret = Self{
.contents = undefined,
.prng = std.rand.DefaultPrng.init(@intCast(u64, std.time.milliTimestamp())),
.prng = std.rand.DefaultPrng.init(@as(u64, @intCast(std.time.milliTimestamp()))),
};
// We must fill all of the array
for (ret.contents[0..7], 0..) |_, i| {
ret.contents[i] = @intToEnum(Piece.Type, i);
ret.contents[i] = @as(Piece.Type, @enumFromInt(i));
}
// Then we shuffle
ret.prng.random().shuffle(?Piece.Type, ret.contents[0..7]);
for (ret.contents[7..14], 0..) |_, i| {
ret.contents[i + 7] = @intToEnum(Piece.Type, i);
ret.contents[i + 7] = @as(Piece.Type, @enumFromInt(i));
}
// Then we shuffle
ret.updateSeed();
@ -46,7 +46,7 @@ pub fn pop(self: *Self) Piece {
// Get more pieces if needed
if (self.contents[7] == null) {
for (self.contents[7..14], 0..) |_, i| {
self.contents[i + 7] = @intToEnum(Piece.Type, i);
self.contents[i + 7] = @as(Piece.Type, @enumFromInt(i));
}
self.updateSeed();
self.prng.random().shuffle(?Piece.Type, self.contents[7..14]);
@ -56,5 +56,5 @@ pub fn pop(self: *Self) Piece {
}
fn updateSeed(self: *Self) void {
self.prng.seed(@intCast(u64, std.time.milliTimestamp()));
self.prng.seed(@as(u64, @intCast(std.time.milliTimestamp())));
}

View File

@ -1,16 +1,15 @@
const std = @import("std");
const SDL = @import("sdl2");
const Color = @import("../color.zig");
const Self = @This();
free: bool,
color: SDL.Color,
//color: SDL.Color,
pub fn init() Self {
return Self{
.free = true,
.color = Color.dark_grey,
//.color = Color.dark_grey,
};
}

View File

@ -1,4 +1,3 @@
const SDL = @import("sdl2");
const std = @import("std");
const Grid = @import("Grid.zig");
@ -51,7 +50,7 @@ dropped: bool = false,
swapped: bool = false,
piece_type: Type,
color: SDL.Color,
//color: SDL.Color,
pub fn init(piece_type: Type) Self {
return Self{
@ -106,15 +105,15 @@ pub fn init(piece_type: Type) Self {
},
},
.color = switch (piece_type) {
Type.o => color.yellow,
Type.i => color.cyan,
Type.l => color.orange,
Type.j => color.blue,
Type.s => color.green,
Type.z => color.red,
Type.t => color.purple,
},
//.color = switch (piece_type) {
// Type.o => color.yellow,
// Type.i => color.cyan,
// Type.l => color.orange,
// Type.j => color.blue,
// Type.s => color.green,
// Type.z => color.red,
// Type.t => color.purple,
//},
};
}
@ -133,21 +132,21 @@ pub fn rotate(self: Self, dir: Rot) Self {
if (dir == Rot.right) {
// Cicle through rotation stage
new_piece.rot_stage = @intToEnum(RotStage, @mod((@enumToInt(new_piece.rot_stage) + 1), 4));
new_piece.rot_stage = @as(RotStage, @enumFromInt(@mod((@intFromEnum(new_piece.rot_stage) + 1), 4)));
// Rotate structure CW
inline for (sequences) |seq| {
inline for (seq, 0..) |_, i| {
const refi = @mod((@intCast(i32, i) - 1), 4);
const refi = @mod((@as(i32, @intCast(i)) - 1), 4);
new_piece.structure[seq[i][0]][seq[i][1]] = self.structure[seq[refi][0]][seq[refi][1]];
}
}
} else {
// Cicle through rotation stage
new_piece.rot_stage = @intToEnum(RotStage, @mod((@enumToInt(new_piece.rot_stage) - 1), 4));
new_piece.rot_stage = @as(RotStage, @enumFromInt(@mod((@intFromEnum(new_piece.rot_stage) - 1), 4)));
// Rotate structure CCW
inline for (sequences) |seq| {
inline for (seq, 0..) |_, i| {
const refi = @mod((@intCast(i32, i) + 1), 4);
const refi = @mod((@as(i32, @intCast(i)) + 1), 4);
new_piece.structure[seq[i][0]][seq[i][1]] = self.structure[seq[refi][0]][seq[refi][1]];
}
}
@ -157,21 +156,21 @@ pub fn rotate(self: Self, dir: Rot) Self {
if (dir == Rot.right) {
// Cicle through rotation stage
new_piece.rot_stage = @intToEnum(RotStage, @mod((@enumToInt(new_piece.rot_stage) + 1), 4));
new_piece.rot_stage = @as(RotStage, @enumFromInt(@mod((@intFromEnum(new_piece.rot_stage) + 1), 4)));
// Rotate structure CW
inline for (sequences) |seq| {
inline for (seq, 0..) |_, i| {
const refi = @mod((@intCast(i32, i) - 1), 4);
const refi = @mod((@as(i32, @intCast(i)) - 1), 4);
new_piece.structure[seq[i][0]][seq[i][1]] = self.structure[seq[refi][0]][seq[refi][1]];
}
}
} else {
// Cicle through rotation stage
new_piece.rot_stage = @intToEnum(RotStage, @mod((@enumToInt(new_piece.rot_stage) - 1), 4));
new_piece.rot_stage = @as(RotStage, @enumFromInt(@mod((@intFromEnum(new_piece.rot_stage) - 1), 4)));
// Rotate structure CCW
inline for (sequences) |seq| {
inline for (seq, 0..) |_, i| {
const refi = @mod((@intCast(i32, i) + 1), 4);
const refi = @mod((@as(i32, @intCast(i)) + 1), 4);
new_piece.structure[seq[i][0]][seq[i][1]] = self.structure[seq[refi][0]][seq[refi][1]];
}
}

View File

@ -16,11 +16,11 @@ grid_pos_x: i32,
grid_pos_y: i32,
pub fn init(renderer: *Renderer) Self {
var wsize = renderer.getOutputSize();
//var wsize = renderer.getOutputSize();
const grid_cell_size = @divFloor(@min(wsize.width, wsize.height), 32);
const grid_pos_x = @divFloor(wsize.width, 2) - (grid_cell_size * @divFloor(Grid.ncolumns, 2));
const grid_pos_y = @divFloor(wsize.height, 2) - (grid_cell_size * @divFloor(Grid.nrows + Grid.buffer, 2));
const grid_cell_size = @divFloor(@min(640, 480), 32);
const grid_pos_x = @divFloor(640, 2) - (grid_cell_size * @divFloor(Grid.ncolumns, 2));
const grid_pos_y = @divFloor(480, 2) - (grid_cell_size * @divFloor(Grid.nrows + Grid.buffer, 2));
return Self{
.renderer = renderer,
.grid_pos_x = grid_pos_x,
@ -30,13 +30,15 @@ pub fn init(renderer: *Renderer) Self {
}
pub fn renderBag(self: *Self, game: Game) void {
const pos_x = self.grid_pos_x + ((Grid.ncolumns + 1) * self.grid_cell_size);
const pos_y = self.grid_pos_y + (Grid.buffer * self.grid_cell_size);
_ = self;
var r: u8 = 0;
var g: u8 = 0;
var b: u8 = 0;
var a: u8 = 255;
//const pos_x = self.grid_pos_x + ((Grid.ncolumns + 1) * self.grid_cell_size);
//const pos_y = self.grid_pos_y + (Grid.buffer * self.grid_cell_size);
// var r: u8 = 0;
// var g: u8 = 0;
// var b: u8 = 0;
// var a: u8 = 255;
for (game.bag.contents[0..5], 0..) |_, i| {
if (game.bag.contents[i]) |piece_type| {
@ -45,24 +47,24 @@ pub fn renderBag(self: *Self, game: Game) void {
for (piece.structure, 0..) |_, y| {
for (piece.structure[y], 0..) |_, x| {
if (piece.structure[y][x]) {
r = piece.color.r;
g = piece.color.g;
b = piece.color.b;
a = piece.color.a;
//r = piece.color.r;
//g = piece.color.g;
//b = piece.color.b;
//a = piece.color.a;
} else {
r = piece.color.r;
g = piece.color.g;
b = piece.color.b;
a = 50;
//r = piece.color.r;
//g = piece.color.g;
//b = piece.color.b;
//a = 50;
}
const new_x = pos_x + @intCast(i32, x) * self.grid_cell_size;
const new_y = pos_y + (@intCast(i32, y) + @intCast(i32, i * piece.structure.len)) * self.grid_cell_size;
//const new_x = pos_x + @as(i32, @intCast(x)) * self.grid_cell_size;
//const new_y = pos_y + (@as(i32, @intCast(y)) + @as(i32, @intCast(i * piece.structure.len))) * self.grid_cell_size;
self.renderer.setColor(r, g, b, a);
self.renderer.fillRectangle(new_x, new_y, self.grid_cell_size, self.grid_cell_size);
self.renderer.setColor(r -| 30, g -| 30, b -| 30, a);
self.renderer.drawRectangle(new_x, new_y, self.grid_cell_size, self.grid_cell_size);
//self.renderer.setColor(r, g, b, a);
//self.renderer.fillRectangle(new_x, new_y, self.grid_cell_size, self.grid_cell_size);
//self.renderer.setColor(r -| 30, g -| 30, b -| 30, a);
//self.renderer.drawRectangle(new_x, new_y, self.grid_cell_size, self.grid_cell_size);
}
}
}
@ -70,13 +72,15 @@ pub fn renderBag(self: *Self, game: Game) void {
}
pub fn renderHeld(self: *Self, game: Game) void {
const pos_x = self.grid_pos_x - (5 * self.grid_cell_size);
const pos_y = self.grid_pos_y + (Grid.buffer * self.grid_cell_size);
_ = self;
var r: u8 = 0;
var g: u8 = 0;
var b: u8 = 0;
var a: u8 = 255;
//const pos_x = self.grid_pos_x - (5 * self.grid_cell_size);
//const pos_y = self.grid_pos_y + (Grid.buffer * self.grid_cell_size);
// var r: u8 = 0;
// var g: u8 = 0;
// var b: u8 = 0;
// var a: u8 = 255;
if (game.held) |held_type| {
var held = Piece.init(held_type);
@ -84,24 +88,24 @@ pub fn renderHeld(self: *Self, game: Game) void {
for (held.structure, 0..) |_, y| {
for (held.structure[y], 0..) |_, x| {
if (held.structure[y][x]) {
r = held.color.r;
g = held.color.g;
b = held.color.b;
a = held.color.a;
//r = held.color.r;
//g = held.color.g;
//b = held.color.b;
//a = held.color.a;
} else {
r = held.color.r;
g = held.color.g;
b = held.color.b;
a = 50;
//r = held.color.r;
//g = held.color.g;
//b = held.color.b;
//a = 50;
}
const new_x = pos_x + @intCast(i32, x) * self.grid_cell_size;
const new_y = pos_y + @intCast(i32, y) * self.grid_cell_size;
//const new_x = pos_x + @as(i32, @intCast(x)) * self.grid_cell_size;
//const new_y = pos_y + @as(i32, @intCast(y)) * self.grid_cell_size;
self.renderer.setColor(r, g, b, a);
self.renderer.fillRectangle(new_x, new_y, self.grid_cell_size, self.grid_cell_size);
self.renderer.setColor(r -| 30, g -| 30, b -| 30, a);
self.renderer.drawRectangle(new_x, new_y, self.grid_cell_size, self.grid_cell_size);
// self.renderer.setColor(r, g, b, a);
//self.renderer.fillRectangle(new_x, new_y, self.grid_cell_size, self.grid_cell_size);
// self.renderer.setColor(r -| 30, g -| 30, b -| 30, a);
//self.renderer.drawRectangle(new_x, new_y, self.grid_cell_size, self.grid_cell_size);
}
}
}
@ -116,8 +120,10 @@ pub fn render(self: *Self, game: Game) void {
}
pub fn renderPiece(self: *Self, piece: Piece) void {
const pos_x = self.grid_pos_x;
const pos_y = self.grid_pos_y;
_ = self;
//const pos_x = self.grid_pos_x;
//const pos_y = self.grid_pos_y;
for (piece.structure, 0..) |_, y| {
for (piece.structure[y], 0..) |_, x| {
@ -126,42 +132,46 @@ pub fn renderPiece(self: *Self, piece: Piece) void {
continue;
}
var r = piece.color.r;
var g = piece.color.g;
var b = piece.color.b;
var a = piece.color.a;
//var r = piece.color.r;
//var g = piece.color.g;
//var b = piece.color.b;
//var a = piece.color.a;
const new_x = pos_x + (@intCast(i32, x) + piece.col) * self.grid_cell_size;
const new_y = pos_y + (@intCast(i32, y) + piece.row) * self.grid_cell_size;
//const new_x = pos_x + (@as(i32, @intCast(x)) + piece.col) * self.grid_cell_size;
//const new_y = pos_y + (@as(i32, @intCast(y)) + piece.row) * self.grid_cell_size;
self.renderer.setColor(r, g, b, a);
self.renderer.fillRectangle(new_x, new_y, self.grid_cell_size, self.grid_cell_size);
self.renderer.setColor(r -| 30, g -| 30, b -| 30, a);
self.renderer.drawRectangle(new_x, new_y, self.grid_cell_size, self.grid_cell_size);
//self.renderer.setColor(r, g, b, a);
//self.renderer.fillRectangle(new_x, new_y, self.grid_cell_size, self.grid_cell_size);
//self.renderer.setColor(r -| 30, g -| 30, b -| 30, a);
//self.renderer.drawRectangle(new_x, new_y, self.grid_cell_size, self.grid_cell_size);
}
}
}
pub fn renderGrid(self: *Self, grid: Grid) void {
const pos_x = self.grid_pos_x;
const pos_y = self.grid_pos_y;
const lg = color.light_grey;
_ = self;
//const pos_x = self.grid_pos_x;
//const pos_y = self.grid_pos_y;
//const lg = color.light_grey;
var visible = grid.cells[Grid.buffer..];
for (visible, 0..) |_, y| {
for (visible[y], 0..) |_, x| {
var r = visible[y][x].color.r;
var g = visible[y][x].color.g;
var b = visible[y][x].color.b;
var a = visible[y][x].color.a;
_ = x;
const new_x = pos_x + @intCast(i32, x) * self.grid_cell_size;
const new_y = pos_y + (@intCast(i32, y) + Grid.buffer) * self.grid_cell_size;
//var r = visible[y][x].color.r;
//var g = visible[y][x].color.g;
//var b = visible[y][x].color.b;
//var a = visible[y][x].color.a;
self.renderer.setColor(r, g, b, a);
self.renderer.fillRectangle(new_x, new_y, self.grid_cell_size, self.grid_cell_size);
self.renderer.setColor(lg.r, lg.g, lg.b, lg.a);
self.renderer.drawRectangle(new_x, new_y, self.grid_cell_size, self.grid_cell_size);
//const new_x = pos_x + @as(i32, @intCast(x)) * self.grid_cell_size;
//const new_y = pos_y + (@as(i32, @intCast(y)) + Grid.buffer) * self.grid_cell_size;
//self.renderer.setColor(r, g, b, a);
//self.renderer.fillRectangle(new_x, new_y, self.grid_cell_size, self.grid_cell_size);
//self.renderer.setColor(lg.r, lg.g, lg.b, lg.a);
//self.renderer.drawRectangle(new_x, new_y, self.grid_cell_size, self.grid_cell_size);
}
}
}

View File

@ -68,8 +68,8 @@ pub fn drop(grid: Grid, piece: Piece) Grid {
for (piece.structure, 0..) |_, y| {
for (piece.structure[y], 0..) |_, x| {
if (piece.structure[y][x]) {
new_grid.cells[@intCast(usize, piece.row + @intCast(i32, y))][@intCast(usize, piece.col + @intCast(i32, x))].free = false;
new_grid.cells[@intCast(usize, piece.row + @intCast(i32, y))][@intCast(usize, piece.col + @intCast(i32, x))].color = piece.color;
new_grid.cells[@as(usize, @intCast(piece.row + @as(i32, @intCast(y))))][@as(usize, @intCast(piece.col + @as(i32, @intCast(x))))].free = false;
//new_grid.cells[@as(usize, @intCast(piece.row + @as(i32, @intCast(y))))][@as(usize, @intCast(piece.col + @as(i32, @intCast(x))))].color = piece.color;
}
}
}
@ -86,11 +86,11 @@ fn checkCollision(grid: Grid, piece: Piece) bool {
for (piece.structure, 0..) |_, y| {
for (piece.structure[y], 0..) |_, x| {
if (piece.structure[y][x] and
((@intCast(i32, x) + piece.col > Grid.ncolumns - 1) or
(@intCast(i32, x) + piece.col < 0) or
(@intCast(i32, y) + piece.row > Grid.nrows - 1) or
(@intCast(i32, y) + piece.row < 0) or
(!grid.cells[@intCast(usize, piece.row + @intCast(i32, y))][@intCast(usize, piece.col + @intCast(i32, x))].free)))
((@as(i32, @intCast(x)) + piece.col > Grid.ncolumns - 1) or
(@as(i32, @intCast(x)) + piece.col < 0) or
(@as(i32, @intCast(y)) + piece.row > Grid.nrows - 1) or
(@as(i32, @intCast(y)) + piece.row < 0) or
(!grid.cells[@as(usize, @intCast(piece.row + @as(i32, @intCast(y))))][@as(usize, @intCast(piece.col + @as(i32, @intCast(x))))].free)))
{
return true;
}
@ -219,7 +219,7 @@ fn checkTTwist(grid: Grid, piece: Piece) bool {
var row = piece.row + rows[i];
var col = piece.col + cols[i];
if ((row > 0 and row < Grid.nrows and col > 0 and col < Grid.ncolumns) and
!grid.cells[@intCast(usize, row)][@intCast(usize, col)].free)
!grid.cells[@as(usize, @intCast(row))][@as(usize, @intCast(col))].free)
{
std.debug.print("Hit\n", .{});
diagonals += 1;

View File

@ -1,5 +1,5 @@
const std = @import("std");
const SDL = @import("sdl2");
//const SDL = @import("sdl2");
const range = @import("utils.zig").range;
const MenuSelection = @import("MainMenu/MenuSelection.zig");
@ -20,11 +20,11 @@ const ActionList = struct {
};
action_list: ActionList = .{
.right = Action.init(SDL.Scancode.right, actionTabRight), // Tab Right
.left = Action.init(SDL.Scancode.left, actionTabLeft), // Tab left
.down = Action.init(SDL.Scancode.down, actionSelDown), // Go down
.up = Action.init(SDL.Scancode.up, actionSelUp), // Go up
.select = Action.init(SDL.Scancode.@"return", actionSelect), // Select
.right = Action.init(0, actionTabRight), // Tab Right
.left = Action.init(0, actionTabLeft), // Tab left
.down = Action.init(0, actionSelDown), // Go down
.up = Action.init(0, actionSelUp), // Go up
.select = Action.init(0, actionSelect), // Select
},
tab_list: [3]MenuTab = .{
@ -65,14 +65,14 @@ pub fn getSel(self: Self, offset: i32) MenuSelection {
}
pub fn getSelIdx(self: Self, offset: i32) usize {
const len = @intCast(i32, self.getTab().contents.len);
const sel = @intCast(i32, self.getTab().sel);
const len = @as(i32, @intCast(self.getTab().contents.len));
const sel = @as(i32, @intCast(self.getTab().sel));
var ret: i32 = undefined;
if (offset < 0) {
ret = sel;
for (range(@intCast(usize, -offset))) |_| {
for (range(@as(usize, @intCast(-offset)))) |_| {
ret -= 1;
if (ret < 0) {
ret = len - 1;
@ -86,7 +86,7 @@ pub fn getSelIdx(self: Self, offset: i32) usize {
//std.debug.print("len {},offset {},ret {}, sel {}\n", .{ len, offset, ret, sel });
}
return @intCast(usize, ret);
return @as(usize, @intCast(ret));
}
pub fn getTab(self: Self) MenuTab {
@ -101,25 +101,25 @@ pub fn tick(self: *Self) State {
//const sel = self.getSel();
//const tab = self.getTab();
var key_state = SDL.getKeyboardState();
//var key_state = SDL.getKeyboardState();
const action_fields = std.meta.fields(ActionList);
inline for (action_fields) |field| {
const action = &@field(self.action_list, field.name);
if (key_state.isPressed(action.*.scancode) and !action.*.holding) {
action.*.holding = true;
action.*.activate = true;
}
if (!key_state.isPressed(action.*.scancode)) {
action.*.holding = false;
}
// const action_fields = std.meta.fields(ActionList);
// inline for (action_fields) |field| {
// const action = &@field(self.action_list, field.name);
// if (key_state.isPressed(action.*.scancode) and !action.*.holding) {
// action.*.holding = true;
// action.*.activate = true;
// }
// if (!key_state.isPressed(action.*.scancode)) {
// action.*.holding = false;
// }
// Action
if (action.*.activate) {
action.*.activate = false;
action.*.call(self);
}
}
// // Action
// if (action.*.activate) {
// action.*.activate = false;
// action.*.call(self);
// }
// }
//std.debug.print(
//\\Tab: {s}
//\\Selection: {s}

View File

@ -31,13 +31,16 @@ pub fn render(self: Self, main_menu: MainMenu) void {
main_menu.getNextTab(),
};
const wsize = self.renderer.getOutputSize();
const screen_width = @intCast(i32, wsize.width);
const screen_height = @intCast(i32, wsize.height);
// const wsize = self.renderer.getOutputSize();
// const screen_width = @as(i32, @intCast(wsize.width));
// const screen_height = @as(i32, @intCast(wsize.height));
const screen_width = 640;
const screen_height = 480;
for (tabs, 0..) |u_tab, u_tab_i| {
//const tab = @intCast(i32, u_tab);
const tab_i = @intCast(i32, u_tab_i);
const tab_i = @as(i32, @intCast(u_tab_i));
const curr_tab = main_menu.tab_list[u_tab];
// Auxiliary variables to claculate the center of the screen
@ -47,9 +50,9 @@ pub fn render(self: Self, main_menu: MainMenu) void {
// Current selection vertical offset
const sel_y_offset = y_spacing * 12;
// Number of items below selection
const n_sel_below = @intCast(usize, @divExact((screen_height - sel_y_offset), (height + y_spacing)));
const n_sel_below = @as(usize, @intCast(@divExact((screen_height - sel_y_offset), (height + y_spacing))));
// Number of items below selection
const n_sel_above = @intCast(usize, @divExact((sel_y_offset), (height + y_spacing)));
const n_sel_above = @as(usize, @intCast(@divExact((sel_y_offset), (height + y_spacing))));
// Move it from the left to the center
const centering = @divExact((screen_width - (total_width + total_spacing)), 2);
@ -64,65 +67,72 @@ pub fn render(self: Self, main_menu: MainMenu) void {
// Current selection
{
const y = @intCast(i32, sel_y_offset);
const y = @as(i32, @intCast(sel_y_offset));
// TODO: The shadow should be static, it is easier like this rn tho
if (tab_i == 1) {
// Shadow
self.renderer.setColor(0, 0, 0, 30);
self.renderer.fillRectangleEx(x + 10, y + 10, width, height, skew);
//self.renderer.setColor(0, 0, 0, 30);
//self.renderer.fillRectangleEx(x + 10, y + 10, width, height, skew);
}
self.renderMenu(x, y, curr_tab, curr_tab.sel, alpha, true);
}
for (range(n_sel_below), 0..) |_, i| {
const aux_sel: i32 = @intCast(i32, i + 1);
const aux_sel: i32 = @as(i32, @intCast(i + 1));
const curr_sel: usize = main_menu.getSelIdx(aux_sel);
const y = @intCast(i32, sel_y_offset + ((y_spacing + height) * (aux_sel)));
const y = @as(i32, @intCast(sel_y_offset + ((y_spacing + height) * (aux_sel))));
self.renderMenu(x - ((skew + 8) * aux_sel), y, curr_tab, curr_sel, alpha, false);
}
for (range(n_sel_above), 0..) |_, i| {
const aux_sel: i32 = -@intCast(i32, i + 1);
const aux_sel: i32 = -@as(i32, @intCast(i + 1));
const curr_sel: usize = main_menu.getSelIdx(aux_sel);
const y = @intCast(i32, sel_y_offset + ((y_spacing + height) * (aux_sel)));
const y = @as(i32, @intCast(sel_y_offset + ((y_spacing + height) * (aux_sel))));
self.renderMenu(x - ((skew + 8) * aux_sel), y, curr_tab, curr_sel, alpha, false);
}
// Tab header
self.renderer.setColor(curr_tab.color[0], curr_tab.color[1], curr_tab.color[2], alpha);
self.renderer.fillRectangleEx(x - 25, 10, width + 50, height + 50, skew);
//self.renderer.setColor(curr_tab.color[0], curr_tab.color[1], curr_tab.color[2], alpha);
//self.renderer.fillRectangleEx(x - 25, 10, width + 50, height + 50, skew);
}
// TODO: Set the Color depending on the Main Menu color
self.renderer.setColorF(0.91, 0.85, 0.65, 0.50);
self.renderer.fillRectangleEx(-150, 0, @divTrunc(wsize.width, 3), wsize.height, skew);
self.renderer.fillRectangleEx(@intCast(i32, screen_width) - 300, 0, @divTrunc(wsize.width, 3), wsize.height, skew);
//self.renderer.setColorF(0.91, 0.85, 0.65, 0.50);
//self.renderer.fillRectangleEx(-150, 0, @divTrunc(wsize.width, 3), wsize.height, skew);
//self.renderer.fillRectangleEx(@as(i32, @intCast(screen_width)) - 300, 0, @divTrunc(wsize.width, 3), wsize.height, skew);
}
fn renderMenu(self: Self, x: i32, y: i32, tab: MenuTab, sel: usize, a: u8, selected: bool) void {
_ = self;
_ = x;
_ = y;
_ = tab;
_ = sel;
_ = a;
// White background
self.renderer.setColor(255, 255, 255, a);
self.renderer.fillRectangleEx(x, y, width, height, skew);
//self.renderer.setColor(255, 255, 255, a);
//self.renderer.fillRectangleEx(x, y, width, height, skew);
//_ = sel;
if (selected) {
// Set color if selected
self.renderer.setColor(tab.color[0], tab.color[1], tab.color[2], a);
//self.renderer.setColor(tab.color[0], tab.color[1], tab.color[2], a);
} else {
// Set black color, not selected
self.renderer.setColor(0, 0, 0, a);
//self.renderer.setColor(0, 0, 0, a);
}
const margin = 20;
//const margin = 20;
//self.renderer.setColorF(1, 1, 1, 1);
var text = Renderer.Texture.fromText(tab.contents[sel].name, height - margin * 2);
self.renderer.renderTexture(text, x + margin, y + margin);
//var text = Renderer.Texture.fromText(tab.contents[sel].name, height - margin * 2);
//self.renderer.renderTexture(text, x + margin, y + margin);
//self.renderer.fillRectangleEx(x + margin, y + margin, width - margin * 2, height - margin * 2, skew);
self.renderer.fillRectangleEx(x + width - 6, y, 6, height, skew);
self.renderer.fillRectangleEx(x + width - 12, y, 3, height, skew);
//self.renderer.fillRectangleEx(x + width - 6, y, 6, height, skew);
//self.renderer.fillRectangleEx(x + width - 12, y, 3, height, skew);
}

View File

@ -1,14 +1,12 @@
const std = @import("std");
const sdl = @import("sdl2");
const zlm = @import("zlm");
const gl = @import("zgl");
const m = zlm.SpecializeOn(f32);
//const sdl = @import("sdl2");
//const zlm = @import("zlm");
//const gl = @import("zgl");
//const m = zlm.SpecializeOn(f32);
const Self = @This();
window: sdl.Window,
context: sdl.gl.Context,
buffer: gl.Buffer,
//window: sdl.Window,
color: [4]f32 = .{ 0, 0, 0, 0 },
// There's a vbo for each shader program
@ -16,271 +14,94 @@ vbo: [max_objects]f32 = .{0.0} ** max_objects,
vbo_index: usize = 0,
// The index of the program is the enum converted to int
textures: [max_objects]Texture = .{undefined} ** max_objects,
//textures: [max_objects]Texture = .{undefined} ** max_objects,
const max_objects: usize = 16384;
const quadSize: usize = 9 * 6;
fn glGetProcAddress(p: []const u8, proc: [:0]const u8) ?*const anyopaque {
_ = p;
return sdl.c.SDL_GL_GetProcAddress(@ptrCast([*c]const u8, proc));
}
pub fn init() !Self {
try sdl.init(.{ .video = true, .audio = true, .events = true });
try sdl.ttf.init();
try sdl.gl.setAttribute(.{ .context_major_version = 3 });
try sdl.gl.setAttribute(.{ .context_minor_version = 3 });
try sdl.gl.setAttribute(.{ .multisamplebuffers = true });
try sdl.gl.setAttribute(.{ .multisamplesamples = 4 });
const window = try sdl.createWindow(
"USG",
.{ .centered = {} },
.{ .centered = {} },
1280,
720,
.{ .context = .opengl, .vis = .shown },
);
const proc: []const u8 = undefined;
try gl.loadExtensions(proc, glGetProcAddress);
const ctx = try sdl.gl.createContext(window);
sdl.gl.setSwapInterval(.immediate) catch {
std.debug.print("WARNING: Unable to configure the swap interval.\n", .{});
var renderer = Self{
//.window = window,
};
// Activate blending and configure it
gl.enable(.blend);
gl.blendFunc(.src_alpha, .one_minus_src_alpha);
var buf = gl.Buffer.gen();
buf.bind(.array_buffer);
var renderer = Self{ .window = window, .context = ctx, .buffer = buf };
// Load the shader programs according to the names in the enum
_ = renderer.loadProgram("texture").use();
var vertex_array = gl.VertexArray.gen();
vertex_array.bind();
gl.vertexAttribPointer(0, 2, .float, false, @sizeOf(f32) * 9, @sizeOf(f32) * 0);
gl.enableVertexAttribArray(0);
gl.vertexAttribPointer(1, 4, .float, false, @sizeOf(f32) * 9, @sizeOf(f32) * 2);
gl.enableVertexAttribArray(1);
gl.vertexAttribPointer(2, 2, .float, false, @sizeOf(f32) * 9, @sizeOf(f32) * 6);
gl.enableVertexAttribArray(2);
gl.vertexAttribPointer(3, 1, .float, false, @sizeOf(f32) * 9, @sizeOf(f32) * 8);
gl.enableVertexAttribArray(3);
gl.clearColor(0.91, 0.85, 0.65, 1.00);
return renderer;
}
fn loadProgram(self: Self, comptime name: []const u8) gl.Program {
var program = gl.Program.create();
const vs = gl.Shader.create(.vertex);
defer vs.delete();
const fs = gl.Shader.create(.fragment);
defer fs.delete();
vs.source(1, &.{@embedFile("shaders/" ++ name ++ ".vert")});
fs.source(1, &.{@embedFile("shaders/" ++ name ++ ".frag")});
vs.compile();
fs.compile();
program.attach(vs);
defer program.detach(vs);
program.attach(fs);
defer program.detach(fs);
program.link();
// Get the matrix that converts coordinates to 1:1 on the screen from the OpenGL default
if (program.uniformLocation("mvp")) |mvpLocation| {
const wsize = self.window.getSize();
const xunit = @intToFloat(f32, wsize.width);
const yunit = @intToFloat(f32, wsize.height);
const ortho = m.Mat4.createOrthogonal(0.0, xunit, yunit, 0.0, 0.0, 100.0);
program.use();
gl.uniformMatrix4fv(mvpLocation, false, &.{ortho.fields});
}
return program;
}
pub fn render(self: *Self) void {
// TODO: Submit with SubData instead to not pass the whole buffer
self.buffer.data(f32, &self.vbo, .static_draw);
_ = self;
var i: usize = 0;
const amount = self.vbo_index / quadSize;
while (i < amount) : (i += 1) {
gl.bindTexture(self.textures[i].texture, .@"2d");
gl.drawArrays(.triangles, i * 6, 6);
}
self.vbo_index = 0;
//// TODO: Submit with SubData instead to not pass the whole buffer
//self.buffer.data(f32, &self.vbo, .static_draw);
// Clear the vbo, this really shouldn't be necessary as the index is set to zero,
// but otherwise it leads to bugs
self.vbo = .{0.0} ** max_objects;
//var i: usize = 0;
//const amount = self.vbo_index / quadSize;
//while (i < amount) : (i += 1) {
// gl.bindTexture(self.textures[i].texture, .@"2d");
// gl.drawArrays(.triangles, i * 6, 6);
//}
//self.vbo_index = 0;
sdl.gl.swapWindow(self.window);
gl.clear(.{ .color = true });
//// Clear the vbo, this really shouldn't be necessary as the index is set to zero,
//// but otherwise it leads to bugs
//self.vbo = .{0.0} ** max_objects;
//sdl.gl.swapWindow(self.window);
//gl.clear(.{ .color = true });
}
pub fn deinit(self: *Self) void {
gl.disableVertexAttribArray(0);
gl.disableVertexAttribArray(1);
gl.disableVertexAttribArray(2);
gl.disableVertexAttribArray(3);
sdl.quit();
sdl.ttf.quit();
self.window.destroy();
sdl.gl.deleteContext(self.context);
}
pub fn setColorF(self: *Self, r: f32, g: f32, b: f32, a: f32) void {
self.*.color = .{ r, g, b, a };
}
pub fn setColor(self: *Self, r: i32, g: i32, b: i32, a: i32) void {
self.*.color = .{
@intToFloat(f32, r) / 255.0,
@intToFloat(f32, g) / 255.0,
@intToFloat(f32, b) / 255.0,
@intToFloat(f32, a) / 255.0,
};
}
pub fn drawRectangle(self: *Self, x: i32, y: i32, w: i32, h: i32) void {
//const indices = [_]u8{ 0, 1, 1, 2, 2, 3, 3, 0 };
//self.renderRectangle(x, y, w, h, .lines, &indices);
_ = x;
_ = y;
_ = self;
_ = w;
_ = h;
}
pub fn fillRectangle(self: *Self, x: i32, y: i32, w: i32, h: i32) void {
self.fillRectangleEx(x, y, w, h, 0);
}
//pub const OutputSize = struct { width: c_int, height: c_int };
//pub fn getOutputSize(self: Self) OutputSize {
// var wsize = self.window.getSize();
// return OutputSize{
// .width = wsize.width,
// .height = wsize.height,
// };
//}
pub fn fillRectangleEx(self: *Self, x: i32, y: i32, w: i32, h: i32, skew_x: i32) void {
renderRectangle(self, x, y, w, h, skew_x, 0);
}
pub fn renderTexture(self: *Self, texture: Texture, x: i32, y: i32) void {
self.textures[self.vbo_index / quadSize] = texture;
renderRectangle(self, x, y, @intCast(i32, texture.width), @intCast(i32, texture.height), 0, 1);
}
fn renderRectangle(self: *Self, x: i32, y: i32, w: i32, h: i32, skew_x: i32, unit: f32) void {
var xf = @intToFloat(f32, x);
var yf = @intToFloat(f32, y);
var wf = @intToFloat(f32, w);
var hf = @intToFloat(f32, h);
const skew_x_offset = @intToFloat(f32, skew_x) * hf / 100;
const i = self.vbo_index;
const vertex_data = [_]f32{
xf + skew_x_offset, yf, // up-left
self.color[0], self.color[1],
self.color[2], self.color[3],
0, 0,
unit,
xf + wf + skew_x_offset, yf, // up-right
self.color[0], self.color[1],
self.color[2], self.color[3],
1, 0,
unit,
xf - skew_x_offset, yf + hf, // down-left
self.color[0], self.color[1],
self.color[2], self.color[3],
0, 1,
unit,
xf + wf - skew_x_offset, yf + hf, // down-right
self.color[0], self.color[1],
self.color[2], self.color[3],
1, 1,
unit,
xf + wf + skew_x_offset, yf, // up-right
self.color[0], self.color[1],
self.color[2], self.color[3],
1, 0,
unit,
xf - skew_x_offset, yf + hf, // down-left
self.color[0], self.color[1],
self.color[2], self.color[3],
0, 1,
unit,
};
std.mem.copy(f32, self.vbo[i..], &vertex_data);
self.vbo_index += vertex_data.len;
}
pub const OutputSize = struct { width: c_int, height: c_int };
pub fn getOutputSize(self: Self) OutputSize {
var wsize = self.window.getSize();
return OutputSize{
.width = wsize.width,
.height = wsize.height,
};
}
pub const Texture = struct {
texture: gl.Texture,
width: usize,
height: usize,
pub fn init(data: [*]const u8, width: usize, height: usize) Texture {
var tex = gl.genTexture();
//defer gl.Texture.delete(tex);
gl.bindTexture(tex, .@"2d");
gl.textureImage2D(.@"2d", 0, .rgba, width, height, .rgba, .unsigned_byte, data);
gl.texParameter(.@"2d", .wrap_s, .clamp_to_edge);
gl.texParameter(.@"2d", .wrap_r, .clamp_to_edge);
gl.texParameter(.@"2d", .min_filter, .linear);
gl.texParameter(.@"2d", .mag_filter, .linear);
return Texture{
.texture = tex,
.width = width,
.height = height,
};
}
pub fn fromText(text: [:0]const u8, size: c_int) Texture {
var font = sdl.ttf.openFont("res/fonts/MarginaliaRegular-8XlZ.ttf", size) catch unreachable;
defer font.close();
var surface = font.renderTextBlended(text, sdl.Color.white) catch unreachable;
defer surface.destroy();
const width = @intCast(usize, surface.ptr.w);
const height = @intCast(usize, surface.ptr.h);
var newsurf = sdl.c.SDL_ConvertSurfaceFormat(surface.ptr, @enumToInt(sdl.PixelFormatEnum.argb8888), 0) orelse unreachable;
const data = @ptrCast([*]const u8, newsurf.pixels);
return Texture.init(data, width, height);
}
pub fn deinit(self: *Texture) void {
gl.Texture.delete(self.texture);
}
};
//pub const Texture = struct {
// texture: gl.Texture,
// width: usize,
// height: usize,
//
// pub fn init(data: [*]const u8, width: usize, height: usize) Texture {
// var tex = gl.genTexture();
// //defer gl.Texture.delete(tex);
// gl.bindTexture(tex, .@"2d");
//
// gl.textureImage2D(.@"2d", 0, .rgba, width, height, .rgba, .unsigned_byte, data);
//
// gl.texParameter(.@"2d", .wrap_s, .clamp_to_edge);
// gl.texParameter(.@"2d", .wrap_r, .clamp_to_edge);
// gl.texParameter(.@"2d", .min_filter, .linear);
// gl.texParameter(.@"2d", .mag_filter, .linear);
//
// return Texture{
// .texture = tex,
// .width = width,
// .height = height,
// };
// }
//
// pub fn fromText(text: [:0]const u8, size: c_int) Texture {
// var font = sdl.ttf.openFont("res/fonts/MarginaliaRegular-8XlZ.ttf", size) catch unreachable;
// defer font.close();
//
// var surface = font.renderTextBlended(text, sdl.Color.white) catch unreachable;
// defer surface.destroy();
//
// const width = @intCast(usize, surface.ptr.w);
// const height = @intCast(usize, surface.ptr.h);
// var newsurf = sdl.c.SDL_ConvertSurfaceFormat(surface.ptr, @enumToInt(sdl.PixelFormatEnum.argb8888), 0) orelse unreachable;
// const data = @ptrCast([*]const u8, newsurf.pixels);
//
// return Texture.init(data, width, height);
// }
//
// pub fn deinit(self: *Texture) void {
// gl.Texture.delete(self.texture);
// }
//};

View File

@ -1,4 +1,4 @@
const SDL = @import("sdl2");
//const SDL = @import("sdl2");
const Self = @This();
@ -19,12 +19,12 @@ pub fn init(target: u64) Self {
pub fn start(self: *Self) void {
self.started = true;
self.progress = 0;
self.initial = SDL.getTicks64();
//self.initial = SDL.getTicks64();
}
pub fn finished(self: *Self) bool {
if (self.started) {
self.progress = SDL.getTicks64() - self.initial;
//self.progress = SDL.getTicks64() - self.initial;
if (self.progress >= self.target) {
return true;
} else return false;
@ -35,7 +35,7 @@ pub fn finished(self: *Self) bool {
pub fn reset(self: *Self) void {
self.progress = 0;
self.initial = SDL.getTicks64();
//self.initial = SDL.getTicks64();
}
pub fn stop(self: *Self) void {

View File

@ -1,5 +1,5 @@
const std = @import("std");
const SDL = @import("sdl2");
//const SDL = @import("sdl2");
const Renderer = @import("Renderer.zig");
const Game = @import("Game.zig");
@ -16,17 +16,19 @@ pub fn main() !void {
var current_state: State = main_menu.state;
try SDL.image.init(.{ .jpg = true });
//try SDL.image.init(.{ .jpg = true });
mainLoop: while (true) {
const start = SDL.getTicks64();
//mainLoop: while (true) {
while (true) {
//const start = SDL.getTicks64();
while (SDL.pollEvent()) |ev| {
switch (ev) {
.quit => break :mainLoop,
else => {},
}
}
// Manage window close request
//while (SDL.pollEvent()) |ev| {
// switch (ev) {
// .quit => break :mainLoop,
// else => {},
// }
//}
if (game.needs_reinit) {
game = Game.init(&renderer);
@ -43,11 +45,12 @@ pub fn main() !void {
renderer.render();
const delay = SDL.getTicks64() - start;
// Limit to 60 fps
//const delay = SDL.getTicks64() - start;
//std.debug.print("{} ms\n", .{delay});
if (delay < 17) {
SDL.delay(17 - @intCast(u32, delay));
}
//if (delay < 17) {
// SDL.delay(17 - @intCast(u32, delay));
//}
}
}