0451-Bomb-显示敌人和角色
环境
- Time 2024-03-16
- Zig 0.12.0-dev.3152+90c1a2c41
- WSL-Ubuntu 22.04.3 LTS
- raylib 5.0
前言
说明
参考资料:
- 《游戏开发:世嘉新人培训教材》
- 图片素材:https://www.ituring.com.cn/book/1742
目标
在上一节的基础上,显示出敌人和玩家控制的角色。
map.zig
在地图中新增了 roles 来保存玩家的角色和敌人。
const std = @import("std");
const engine = @import("engine.zig");
var tileMap: engine.TileMap = undefined;
pub fn init() void {
tileMap = engine.TileMap.init("map.png", 32);
}
pub fn deinit() void {
tileMap.deinit();
}
const StageConfig = struct {
enemy: usize,
brickRate: usize,
power: usize,
bomb: usize,
};
const stageConfig = [_]StageConfig{
.{ .enemy = 2, .brickRate = 90, .power = 4, .bomb = 6 },
.{ .enemy = 3, .brickRate = 80, .power = 1, .bomb = 0 },
.{ .enemy = 6, .brickRate = 30, .power = 0, .bomb = 1 },
};
// 定义地图的类型
pub const MapType = enum(u8) {
space = 9,
wall = 7,
brick = 8,
bomb = 2,
power = 3,
};
const MapTypeSet = std.enums.EnumSet(MapType);
const width = 19;
const height = 15;
var data: [width * height]MapTypeSet = undefined;
pub fn drawEnum(mapType: MapType, x: usize, y: usize) void {
tileMap.drawI(@intFromEnum(mapType), x, y);
}
const RoleType = enum(u8) { player1 = 1, player2 = 2, enemy = 6 };
const Role = struct {
x: usize,
y: usize,
type: RoleType = .enemy,
};
pub const WorldMap = struct {
width: usize = width,
height: usize = height,
data: []MapTypeSet,
roles: []Role,
pub fn init(_: usize) ?WorldMap {
const number = stageConfig[0].enemy + 1;
const roles = engine.allocator.alloc(Role, number) catch |e| {
std.log.info("create role error: {}", .{e});
return null;
};
roles[0] = .{ .x = 1, .y = 1, .type = .player1 };
const map = WorldMap{ .data = &data, .roles = roles };
map.generateMap(stageConfig[0]);
return map;
}
fn generateMap(self: WorldMap, config: StageConfig) void {
var bricks: [data.len]usize = undefined;
var brickNumber: usize = 0;
var floors: [data.len]usize = undefined;
var floorNumber: usize = 0;
for (0..self.height) |y| {
for (0..self.width) |x| {
self.data[x + y * width] = if (isFixWall(x, y))
MapTypeSet.initOne(.wall)
else if (isFixSpace(x, y))
MapTypeSet.initOne(.space)
else if (engine.random(100) < config.brickRate) label: {
bricks[brickNumber] = x << 16 | y;
brickNumber += 1;
break :label MapTypeSet.initOne(.brick);
} else label: {
floors[floorNumber] = x << 16 | y;
floorNumber += 1;
break :label MapTypeSet.initOne(.space);
};
}
}
generateItem(self, bricks[0..brickNumber], config);
generateRole(self, floors[0..floorNumber], config);
}
fn isFixWall(x: usize, y: usize) bool {
if (x == 0 or y == 0) return true;
if (x == width - 1 or y == height - 1) return true;
if (x % 2 == 0 and y % 2 == 0) return true;
return false;
}
fn isFixSpace(x: usize, y: usize) bool {
return y + x < 4;
}
fn generateItem(self: WorldMap, bricks: []usize, cfg: StageConfig) void {
for (0..cfg.bomb + cfg.power) |i| {
const swapped = engine.randomW(i, bricks.len);
const tmp = bricks[i];
bricks[i] = bricks[swapped];
bricks[swapped] = tmp;
const x = bricks[i] >> 16 & 0xFFFF;
const item: MapType = if (i < cfg.power) .power else .bomb;
self.data[x + (bricks[i] & 0xFFFF) * self.width].insert(item);
}
}
fn generateRole(self: WorldMap, floors: []usize, cfg: StageConfig) void {
for (0..cfg.enemy) |i| {
const swapped = engine.randomW(i, floors.len);
const tmp = floors[i];
floors[i] = floors[swapped];
floors[swapped] = tmp;
self.roles[1 + i] = .{
.x = floors[i] >> 16 & 0xFFFF,
.y = floors[i] & 0xFFFF,
};
}
}
pub fn draw(self: WorldMap) void {
for (0..self.height) |y| {
for (0..self.width) |x| {
const value = data[x + y * self.width];
if (value.contains(.wall)) drawEnum(.wall, x, y) //
else if (value.contains(.brick)) drawEnum(.brick, x, y) //
else {
drawEnum(.space, x, y);
if (value.contains(.power)) drawEnum(.power, x, y) //
else if (value.contains(.bomb)) drawEnum(.bomb, x, y);
}
}
}
for (self.roles) |value| {
tileMap.drawI(@intFromEnum(value.type), value.x, value.y);
}
}
pub fn size(self: WorldMap) usize {
return self.width * self.height;
}
pub fn deinit(self: WorldMap) void {
engine.allocator.free(self.roles);
}
};
效果

总结
显示敌人和角色。

浙公网安备 33010602011771号