当前位置: 首页 > news >正文

0451-Bomb-显示敌人和角色

环境

  • Time 2024-03-16
  • Zig 0.12.0-dev.3152+90c1a2c41
  • WSL-Ubuntu 22.04.3 LTS
  • raylib 5.0

前言

说明

参考资料:

  1. 《游戏开发:世嘉新人培训教材》
  2. 图片素材: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);}
};

效果

bomb

总结

显示敌人和角色。

附录

http://www.jsqmd.com/news/1403683/

相关文章:

  • STM32 USART 标准库完全指南——从串口发送到Printf重定向
  • Vue3 构建产物过大:先查副作用声明、导入方式和环境变量
  • AI模型自动化构建与部署实战:从MLOps原理到Oumi应用
  • Syncthing for Android 完整上手指南:三步实现不经过网盘的免费文件同步
  • 解决MSSTDFMT.DLL注册表缺失:从原理到实践的完整指南
  • Claude Code:轻量化代码协作工具的核心功能与实践
  • 玄琨GEO技术架构深度解析:从核心引擎到数据流闭环(产品技术篇) - 汇聚至此
  • Android 11 定制设置系统默认语言列表(en-US + zh-CN)与“添加语言“建议项
  • jqGrid经典用法全解析:从数据驱动到企业级表格实践
  • 2026年8月厦门外墙漏水维修防水公司推荐,高层高空渗水修缮避坑指南 - 聪居到家
  • 2026湛江泡沫混凝土楼顶保温电话施工队道路软基处理,泡沫轻质土改良松软土层?-萧昇建筑材料 - 行业甄选汇
  • AI+形式化验证实战:从Lean环境搭建到数学证明自动化
  • 基于DiFy、FastGPT和MaxKB构建企业级AI应用全栈方案
  • C++质数筛算法详解:从埃氏筛到欧拉筛的实战指南
  • 从CUDA Tile视角解析大模型算力核心:GEMM并行优化原理与实践
  • 移动硬盘格式选择指南:NTFS、exFAT、APFS、FAT32跨系统兼容性与数据安全实战
  • Arduino智慧交通沙盘:从零搭建物联网科创项目全攻略
  • 单仁牛商玄琨GEO:GEO生成式引擎优化的核心原理与技术架构解析(原理解析篇) - 汇聚至此
  • VSCode开发Java与SpringBoot:从环境配置到疑难排错实战指南
  • 2026年3款主流短视频总结软件测评3个核心维度帮你选对好用工具
  • 2026年新消息:伊春彩色鹅卵石规格深耕卵石业,老友常相伴-弘源达建材 - 行业甄选汇
  • DS4Android开源项目:安卓设备连接PS4手柄的原理、配置与实战指南
  • Windows 10管理员权限失效与用户名修改难题的深度解析与实战修复
  • 笔记本摄像头故障排查全攻略:从驱动修复到注册表清理
  • 优化.NET开发环境:迁移NuGet全局包文件夹释放C盘空间
  • Agent 故障复盘:按状态机还原工具调用链
  • 从零搭建现代化AI实验室:技术栈、工具链与RAG实战指南
  • 2026年新消息:衢州广场游乐车工厂实地展厅可看样,选款购机心里更敞亮-山东童星游乐设备厂 - 行业甄选汇
  • 安卓文件同步避坑实战:关于 Syncthing for Android,新手最想弄清的5个问题
  • Harness 架构智能体平台 Policy Engine 高风险操作安全控制方案