← 返回信息流
AI 资讯Hacker News·19 小时前

C64 Basic地牢探险游戏教程:哥布林攻击(第8部分)

原标题:C64 Basic Dungeon Crawler: Goblin Attack (C64 Basic Part 8)

速览

这是C64 Basic编程系列教程的第8部分,专注于开发一个地牢探险游戏(Dungeon Crawler)。本教程详细讲解了如何实现哥布林攻击(Goblin Attack)功能,包括敌人移动与碰撞检测。该系列面向复古编程爱好者,展示在8位计算机上使用Basic语言构建游戏的技术。

AI 深度解读

背景

这是《C64 Basic Dungeon Crawler》系列教程的第八部分,前作(第七部分)中,程序员构建了一个充满哥布林的地牢,但这些哥布林像花园小矮人一样毫无威胁——它们只会站在原地,玩家可以走过去戳一下,掉5点血然后走开,过一会儿回来它们还在原地。本部分的核心目标是让哥布林学会追逐玩家,并且引入真正的战斗系统、自定义按键,以及修复一个诡异的字符集内存损坏 bug。作者强调,这个 bug 的排查过程是整个教程中最有价值的教训。

核心内容

本部分实现的四个改变

  1. 自定义按键:玩家不再只能使用默认的 QAOP(向上/左/下/右 + 空格键),而是可以自由映射任何按键。
  2. 哥布林拥有位置、生命值和“大脑”:每个哥布林现在有独立的坐标、血量(默认10点),并具备简单的追逐逻辑(虽然很小)。
  3. 战斗系统:攻击使用真实的 d20 骰子(20面骰)加上力量修正值来计算伤害。
  4. 修复内存 bug:游戏不再“自食其肉”——作者在开发过程中遇到了一个字符集被损坏的奇怪 bug,本部分给出了解决方案。

自定义按键的实现细节

为了不让特定操作习惯的玩家不满(QAOP 是老派标准,WASD 是另一派的偏好),作者决定让玩家自己映射按键。关键在于:游戏代码不能再用硬编码的字母(如 Q),而必须比较当前存储的按键变量。

变量名的陷阱(Commodore BASIC 特有)

  • 两字母限制:Commodore BASIC 的变量名只存储前两个字符。例如 PLAYERHEALTHPLAYERX 实际上是同一个变量 PL,导致游戏行为诡异且难以调试。因此,作者特意让五个按键变量名在前两个字母上唯一:QKEY$QK)、AKEY$AK)、OKEY$OK)、PKEY$PK)、FKEY$FK)。
  • BASIC 关键字冲突:变量名中不能包含 BASIC 关键字,因为 tokenizer 会从左到右识别关键字并替换成 token。例如 GOLD 中的 GO 会被识别为 GO TO 的关键字,导致语法错误。常见的陷阱包括 TOIFONORAND 等,所以 SCORE(含 OR)、COUNT(含 ON)、TOTAL(含 TO)都是危险变量名。

按键读取的实现

  • 使用 GET 而非 INPUTINPUT 会等待用户输入并回车,且对逗号等字符敏感,不适合即时按键映射。GET 从键盘缓冲区读取一个字符后立即返回,如果缓冲区为空则返回空字符串。
  • 为了让游戏等待按键,需要循环检测直到 GET 返回非空字符串:
CHANGETHISKEY:
GET K$: IF K$="" THEN GOTO CHANGETHISKEY
RETURN
  • 映射流程:先显示当前默认键(QAOP 和空格),然后依次提示用户按下“上”、“下”、“左”、“右”、“发射”键,将结果存入对应变量。最后要求确认(Y/N),如果按 N 则跳回重新开始映射,避免误操作。

哥布林对象化:从像素到游戏对象

之前,哥布林仅仅是屏幕上的像素图案(屏幕代码 38),程序无法跟踪它们。现在需要为每个哥布林分配位置、血量,并能够移动和判断存亡。作者使用并行数组(parallel arrays)来模拟记录/结构体:

REM DECLARE ENEMY VARIABLES
GC=0: REM 哥布林计数器
DIM GH(10) : REM 哥布林血量数组
FOR GC=1 TO 10: GH(GC)=10: NEXT GC
GC=0
DIM GX(10) : DIM GY(10) : REM 哥布林坐标列表
  • GXGY 分别存储每个哥布林的列和行,GH 存储血量,GC 是实际放置的哥布林数量。
  • 循环中复用 GC 作为计数器来初始化血量,之后再重置为 0。这种并行数组方式在 8 位机器上比替代方案(如字符串或复杂数据结构)更高效。

战斗系统

战斗使用真实的 d20 骰子(20面骰)加上力量修正值。原文未给出完整战斗代码,但明确提到“Combat happens with a real d20 roll and a strength modifier”。

内存 bug 的教训

作者在开发过程中遇到了一个字符集被损坏的 bug,表现为字符集在游戏运行时被覆盖。该 bug 的排查过程被作者认为是本部分最有价值的教训。原文未详细展示 bug 的代码,但提醒读者不要跳过“内存部分”(memory section),并指出“the game stops eating itself”是一个比听起来更长的故事。

关键要点

  • 按键自定义的核心是抽象:游戏代码不再比较硬编码的字母,而是比较变量,从而支持动态映射。这是从“写死”到“可配置”的关键一步。
  • Commodore BASIC 变量名陷阱:只取前两个字符,且不能包含 BASIC 关键字。这是现代开发者容易忽视的坑,会导致难以调试的 bug。
  • GET vs INPUT:在即时按键映射场景下,GET 更合适,但需要循环等待直到缓冲区有数据。INPUT 会引入回车和特殊字符问题。
  • 并行数组模拟对象:在无结构体的语言中,用三个数组(坐标X、Y、血量)和计数器来表示多个哥布林,是高效且经典的做法。
  • 内存 bug 的教训:字符集损坏往往源于内存覆盖,例如变量数组越界或不当的 POKE 操作。排查需要逐行检查内存地址和变量分配。
  • 验证机制的重要性:按键映射后要求确认(Y/N),避免误操作后无法恢复,提供了简单的“撤销”路径。

意义与影响

本部分将一个静态的装饰性游戏(地牢生成后只有固定哥布林)升级为具有基本 AI 和战斗系统的可玩原型。按键自定义功能显著提升了用户体验,反映了在资源受限的 8 位平台上设计交互细节的思考——从“我替用户选”到“让用户自己选”。对 Commodore BASIC 变量名陷阱的深入剖析,不仅帮助了该系列读者,也为所有学习 6502 平台 BASIC 编程的人提供了宝贵的避坑指南。内存

查看原文 →retrogamecoders.com