环境
- Time 2023-08-22
- Zig 0.11.0
- WSL-Ubuntu 22.04.3 LTS
前言
说明
参考资料:
- https://www.youtube.com/watch?v=nF_crEtmpBo
- https://github.com/howprice/sdl2-tetris
目标
将方块的七种类型表示出来,定义四个方向,方块可以变形。
表示方式为一个二维数组,一维来表示方向,另一维来表示方块所占的方格。
一个方块包含四个小方格,一个方格需要横纵坐标,所以使用长度为 8 的数组来表示。
七种方格的定义
const std = @import("std");
const display = @import("display.zig");const tetriminoes: [7]Tetrimino = label: {var arr: [7]Tetrimino = undefined;// Iarr[0] = .{ .y = -1, .value = .{.{ 0, 1, 1, 1, 2, 1, 3, 1 },.{ 2, 0, 2, 1, 2, 2, 2, 3 },.{ 0, 2, 1, 2, 2, 2, 3, 2 },.{ 1, 0, 1, 1, 1, 2, 1, 3 },}, .color = 0x00ffffff };// Jarr[1] = .{ .value = .{.{ 0, 0, 0, 1, 1, 1, 2, 1 },.{ 1, 0, 2, 0, 1, 1, 1, 2 },.{ 0, 1, 1, 1, 2, 1, 2, 2 },.{ 1, 0, 1, 1, 0, 2, 1, 2 },}, .color = 0x0000ffff };// Larr[2] = .{ .value = .{.{ 2, 0, 0, 1, 1, 1, 2, 1 },.{ 1, 0, 1, 1, 1, 2, 2, 2 },.{ 0, 1, 1, 1, 2, 1, 0, 2 },.{ 0, 0, 1, 0, 1, 1, 1, 2 },}, .color = 0xffaa00ff };// Oarr[3] = .{ .value = .{.{ 1, 0, 2, 0, 1, 1, 2, 1 },.{ 1, 0, 2, 0, 1, 1, 2, 1 },.{ 1, 0, 2, 0, 1, 1, 2, 1 },.{ 1, 0, 2, 0, 1, 1, 2, 1 },}, .color = 0xffff00ff };// Sarr[4] = .{ .value = .{.{ 1, 0, 2, 0, 0, 1, 1, 1 },.{ 1, 0, 1, 1, 2, 1, 2, 2 },.{ 1, 1, 2, 1, 0, 2, 1, 2 },.{ 0, 0, 0, 1, 1, 1, 1, 2 },}, .color = 0x00ff00ff };// Tarr[5] = .{ .value = .{.{ 1, 0, 0, 1, 1, 1, 2, 1 },.{ 1, 0, 1, 1, 2, 1, 1, 2 },.{ 0, 1, 1, 1, 2, 1, 1, 2 },.{ 1, 0, 0, 1, 1, 1, 1, 2 },}, .color = 0x9900ffff };// Zarr[6] = .{ .value = .{.{ 0, 0, 1, 0, 1, 1, 2, 1 },.{ 2, 0, 1, 1, 2, 1, 1, 2 },.{ 0, 1, 1, 1, 1, 2, 2, 2 },.{ 1, 0, 0, 1, 1, 1, 0, 2 },}, .color = 0xff0000ff };break :label arr;
};
结构
pub const Facing = enum { North, East, South, West };
pub const Tetrimino = struct {x: i32 = 3,y: i32 = 0,facing: Facing = .North,value: [4][8]u8 = undefined,color: u32,solid: bool = false,pub fn position(self: *const Tetrimino) [8]u8 {return self.value[@intFromEnum(self.facing)];}pub fn random(rand: *std.rand.DefaultPrng) Tetrimino {const len = tetriminoes.len;return tetriminoes[rand.random().uintLessThan(usize, len)];}pub fn rotate(self: *Tetrimino) void {const int: u8 = @intFromEnum(self.facing);const len = std.enums.values(Facing).len;self.facing = @enumFromInt(int + 1 % len);}pub fn locateIn(self: *Tetrimino) void {const pos = self.position();const minx = @min(@min(@min(pos[0], pos[2]), pos[4]), pos[6]);if (self.x + minx < 0) self.x -= self.x + minx;const maxx = @max(@max(@max(pos[0], pos[2]), pos[4]), pos[6]);const x = self.x + maxx - display.WIDTH;if (x >= 0) self.x -= x + 1;}
};
- position 方法会根据当前方向,计算出方块的像素点。
- rotate 会调整方块的朝向。
- random 可以随机生成七种方块中的一种。
- locateIn 保证方块不超出屏幕的两边。
总结
定义了全部方块的类型和结构,定义了其中的一些方法。方块模块 block.zig 就这些代码,后续不再修改和列出。
附录
block.zig
const std = @import("std");
const display = @import("display.zig");pub const tetriminoes: [7]Tetrimino = label: {var arr: [7]Tetrimino = undefined;// Iarr[0] = .{ .y = -1, .value = .{.{ 0, 1, 1, 1, 2, 1, 3, 1 },.{ 2, 0, 2, 1, 2, 2, 2, 3 },.{ 0, 2, 1, 2, 2, 2, 3, 2 },.{ 1, 0, 1, 1, 1, 2, 1, 3 },}, .color = 0x00ffffff };// Jarr[1] = .{ .value = .{.{ 0, 0, 0, 1, 1, 1, 2, 1 },.{ 1, 0, 2, 0, 1, 1, 1, 2 },.{ 0, 1, 1, 1, 2, 1, 2, 2 },.{ 1, 0, 1, 1, 0, 2, 1, 2 },}, .color = 0x0000ffff };// Larr[2] = .{ .value = .{.{ 2, 0, 0, 1, 1, 1, 2, 1 },.{ 1, 0, 1, 1, 1, 2, 2, 2 },.{ 0, 1, 1, 1, 2, 1, 0, 2 },.{ 0, 0, 1, 0, 1, 1, 1, 2 },}, .color = 0xffaa00ff };// Oarr[3] = .{ .value = .{.{ 1, 0, 2, 0, 1, 1, 2, 1 },.{ 1, 0, 2, 0, 1, 1, 2, 1 },.{ 1, 0, 2, 0, 1, 1, 2, 1 },.{ 1, 0, 2, 0, 1, 1, 2, 1 },}, .color = 0xffff00ff };// Sarr[4] = .{ .value = .{.{ 1, 0, 2, 0, 0, 1, 1, 1 },.{ 1, 0, 1, 1, 2, 1, 2, 2 },.{ 1, 1, 2, 1, 0, 2, 1, 2 },.{ 0, 0, 0, 1, 1, 1, 1, 2 },}, .color = 0x00ff00ff };// Tarr[5] = .{ .value = .{.{ 1, 0, 0, 1, 1, 1, 2, 1 },.{ 1, 0, 1, 1, 2, 1, 1, 2 },.{ 0, 1, 1, 1, 2, 1, 1, 2 },.{ 1, 0, 0, 1, 1, 1, 1, 2 },}, .color = 0x9900ffff };// Zarr[6] = .{ .value = .{.{ 0, 0, 1, 0, 1, 1, 2, 1 },.{ 2, 0, 1, 1, 2, 1, 1, 2 },.{ 0, 1, 1, 1, 1, 2, 2, 2 },.{ 1, 0, 0, 1, 1, 1, 0, 2 },}, .color = 0xff0000ff };break :label arr;
};pub const Facing = enum { North, East, South, West };
pub const Tetrimino = struct {x: i32 = 3,y: i32 = 0,facing: Facing = .North,value: [4][8]u8 = undefined,color: u32,solid: bool = false,pub fn position(self: *const Tetrimino) [8]u8 {return self.value[@intFromEnum(self.facing)];}pub fn random(rand: *std.rand.DefaultPrng) Tetrimino {const len = tetriminoes.len;return tetriminoes[rand.random().uintLessThan(usize, len)];}pub fn rotate(self: *Tetrimino) void {const int: u8 = @intFromEnum(self.facing);const len = std.enums.values(Facing).len;self.facing = @enumFromInt(int + 1 % len);}pub fn locateIn(self: *Tetrimino) void {const pos = self.position();const minx = @min(@min(@min(pos[0], pos[2]), pos[4]), pos[6]);if (self.x + minx < 0) self.x -= self.x + minx;const maxx = @max(@max(@max(pos[0], pos[2]), pos[4]), pos[6]);const x = self.x + maxx - display.WIDTH;if (x >= 0) self.x -= x + 1;}
};