mcpField
G
gamemaker-expert

gamemaker-expert

github.com/leihaht开发654 次安装52 周前更新
代码仓库

关于 gamemaker-expert

此技能为 GameMaker Studio 2 和 GML 项目提供开发指导,涵盖对象与资源创建、语言用法、架构和故障排查,适用于开发与维护 GameMaker 游戏的人员。

主要功能

  1. 01指导对象、事件和项目资源创建
  2. 02讲解 GML 语法与数据结构
  3. 03提供架构模式和常见问题参考
  4. 04涵盖内存管理与文件处理
  5. 05建议查阅官方手册

适用场景

  1. 01创建或修改 GameMaker 对象和脚本
  2. 02排查编译错误或运行时问题
  3. 03实现碰撞、绘制或网络功能
  4. 04优化项目结构与性能

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/leihaht/gamemaker-skills --skill gamemaker-expert

安装后在 Claude Code 中输入/gamemaker-expert确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
ADVANCED_TOPICS.md
ARCHITECTURE_PATTERNS.md
BUILT_IN_VARIABLES.md
COMMON_PITFALLS.md
GML_REFERENCE.md
MANAGER_CONSTRUCTOR_GUIDE.md
QUICK_REFERENCE.md

详细介绍

GameMaker 专家

概述

此技能为所有 GameMaker 项目提供全面的 GameMaker Studio 2 和 GML(GameMaker Language)专业知识。涵盖从创建基本对象到着色器编程、网络和平台专属开发等高级主题的所有内容。

适用场景:

  • 处理 .gml 文件(GML 脚本和事件)
  • 创建或修改 .yy 文件(对象定义、精灵定义等)
  • 编辑 .yyp 项目文件
  • 创建 GameMaker 对象、脚本或资产
  • 调试 GameMaker 编译错误或运行时问题
  • 实现 GameMaker 功能(绘图、碰撞、网络等)
  • 优化 GameMaker 性能
  • 任何 GameMaker Studio 2 开发任务

GameMaker 官方手册

主要参考资料:请始终查阅 GameMaker 官方手册,以获取全面且最新的文档: https://manual.gamemaker.io/monthly/en/

手册主要章节

适用场景:

  • 查询函数签名和参数
  • 了解特定平台的行为
  • 查看 IDE 版本的最新语法变更
  • 深入了解 GameMaker 功能
补充参考资料

高级架构指南:

适用场景:

  • 为游戏全局状态设计管理器构造函数
  • 避免与 GameMaker 内置变量冲突
  • 在 GML 中实现封装模式
  • 理解伪私有成员的 __ 前缀约定
  • 学习 GameMaker 环境中的 SOLID 原则
  • 查找有助于维护代码的架构模式

GameMaker 核心工作流

对象创建工作流(重要)

创建 GameMaker 对象需要完成全部四个步骤。缺少任何一步都会导致对象无法显示在 IDE 中或编译失败。

步骤 1:创建对象目录
objects/objYourObjectName/

命名约定:

  • 以 obj 前缀开头
  • 使用 PascalCase(例如,objPlayer、objEnemyMelee、objInventoryUI)
  • 使用能表明用途的描述性名称
步骤 2:创建事件文件

为对象需要的每个事件创建 .gml 文件:

常见事件:

事件文件事件类型使用时机
Create_0.gml创建事件初始化变量(务必包含)
Step_0.gml步骤事件每帧更新逻辑
Draw_0.gml绘制事件绘制游戏世界中的图形
Draw_64.gml绘制 GUI 事件绘制 UI 覆盖层
Destroy_0.gml销毁事件销毁时进行清理
Collision_objX.gml碰撞事件处理碰撞

事件命名规则:

  • 创建:Create_0.gml
  • 步骤:Step_0.gml
  • 绘制:Draw_0.gml
  • 绘制 GUI:Draw_64.gml(不是 Draw_GUI_0.gml!)
  • 碰撞:Collision_objTargetName.gml

Create_0.gml 示例:

/// objPlayer Create Event
// Initialize player variables

// Movement
move_speed = 4;
direction = 0;

// Stats
health = 100;
max_health = 100;

// State
is_moving = false;

show_debug_message("objPlayer created");
步骤 3:创建 .yy 文件(必需)

文件:objects/objYourObjectName/objYourObjectName.yy

模板:

{
  "$GMObject":"",
  "%Name":"objYourObjectName",
  "eventList":[
    {"$GMEvent":"v1","%Name":"","collisionObjectId":null,"eventNum":0,"eventType":0,"isDnD":false,"name":"","resourceType":"GMEvent","resourceVersion":"2.0",},
    {"$GMEvent":"v1","%Name":"","collisionObjectId":null,"eventNum":64,"eventType":8,"isDnD":false,"name":"","resourceType":"GMEvent","resourceVersion":"2.0",},
    {"$GMEvent":"v1","%Name":"","collisionObjectId":null,"eventNum":0,"eventType":3,"isDnD":false,"name":"","resourceType":"GMEvent","resourceVersion":"2.0",},
  ],
  "managed":true,
  "name":"objYourObjectName",
  "overriddenProperties":[],
  "parent":{
    "name":"Objects",
    "path":"folders/Objects.yy",
  },
  "parentObjectId":null,
  "persistent":false,
  "physicsAngularDamping":0.1,
  "physicsDensity":0.5,
  "physicsFriction":0.2,
  "physicsGroup":1,
  "physicsKinematic":false,
  "physicsLinearDamping":0.1,
  "physicsObject":false,
  "physicsRestitution":0.1,
  "physicsSensor":false,
  "physicsShape":1,
  "physicsShapePoints":[],
  "physicsStartAwake":true,
  "properties":[],
  "resourceType":"GMObject",
  "resourceVersion":"2.0",
  "solid":false,
  "spriteId":null,
  "spriteMaskId":null,
  "visible":true,
}

事件类型编号:

事件eventTypeeventNum
创建00
步骤30
绘制80
绘制 GUI864
销毁10

重要字段:

  • %Name 和 name:必须与对象名称完全一致
  • eventList:为创建的每个 .gml 文件添加条目
  • parentObjectId:使用继承时,设置为父对象的资源路径(例如,{"name":"objCreature","path":"objects/objCreature/objCreature.yy"})
  • persistent:对象应跨房间持续存在时设为 true
  • visible:没有精灵的控制器对象设为 false
步骤 4:在项目文件中注册(必需)

文件:YourProject.yyp

位置:找到 "resources":[ 数组

添加条目(按字母顺序排序):

{"id":{"name":"objYourObjectName","path":"objects/objYourObjectName/objYourObjectName.yy",},},

示例:

"resources":[
  {"id":{"name":"objInventoryUI","path":"objects/objInventoryUI/objInventoryUI.yy",},},
  {"id":{"name":"objPlayer","path":"objects/objPlayer/objPlayer.yy",},},
  {"id":{"name":"objYourObjectName","path":"objects/objYourObjectName/objYourObjectName.yy",},},
]

重要:缺少此步骤会导致“object not found”等编译错误。

GML 语言基础
变量作用域
// Local variable (function/script scope only)
var _local_var = 100;

// Instance variable (attached to object instance)
instance_var = 50;

// Global variable (accessible everywhere)
global.game_state = "playing";

最佳实践:为清晰起见,局部变量名以下划线 _ 开头。

数据类型
  • 实数:数字 var _x = 100; var _pi = 3.14159;
  • 字符串:文本 var _name = "Player";
  • 布尔值:真/假 var _is_alive = true;
  • 数组:var _items = [1, 2, 3]; var _nested = [[1,2], [3,4]];
  • 结构体:var _player = { x: 0, y: 0, health: 100 };
  • 未定义:undefined(使用 is_undefined() 检查)
  • 指针/ID:对实例、数据结构和资源的引用
运算符

算术:+ - * / div mod 比较:== != > < >= <= 逻辑:&& || ! ^^ (and, or, not, xor) 位运算:& | ^ << >> ~ 三元运算符:condition ? true_value : false_value

重要 — 三元运算符链式调用:

链式三元运算符必须使用双括号括起嵌套条件:

// ✅ CORRECT
var _result = condition_a ? "foo" : ((condition_b ? "bar" : "baz"));

// ❌ WRONG (will cause compile error in some versions)
var _result = condition_a ? "foo" : condition_b ? "bar" : "baz";

参考:https://manual.gamemaker.io/beta/en/GameMaker_Language/GML_Overview/Expressions_And_Operators.htm

控制流
// If statement
if (condition) {
    // code
} else if (other_condition) {
    // code
} else {
    // code
}

// Switch statement
switch (value) {
    case 1:
        // code
        break;
    case 2:
    case 3:
        // code for 2 or 3
        break;
    default:
        // code
        break;
}

// For loop
for (var _i = 0; _i < 10; _i++) {
    show_debug_message(_i);
}

// While loop
while (condition) {
    // code
}

// Repeat loop
repeat (10) {
    // code
}

// With loop (iterate instances)
with (objEnemy) {
    health -= 10;
}
数据结构与内存管理
Struct(轻量级 — 推荐)
// Create struct (no manual cleanup needed!)
var _player = {
    name: "Hero",
    health: 100,
    max_health: 100,
    level: 1
};

// Access properties
show_debug_message(_player.name); // "Hero"
_player.health -= 10;

// Check if property exists
if (variable_struct_exists(_player, "mana")) {
    // property exists
}

// Dynamic property access
var _prop_name = "health";
var _value = _player[$ _prop_name]; // Same as _player.health

适用场景:轻量级数据容器、配置数据、简单的键值对。 优点:无需手动清理,由垃圾回收自动处理。

ds_list(动态数组)
// Create
var _list = ds_list_create();

// Add items
ds_list_add(_list, "apple", "banana", "cherry");
ds_list_insert(_list, 1, "orange"); // Insert at index

// Access
var _item = _list[| 0]; // "apple"
var _size = ds_list_size(_list);

// Iterate
for (var _i = 0; _i < ds_list_size(_list); _i++) {
    show_debug_message(_list[| _i]);
}

// CRITICAL: Always destroy when done!
ds_list_destroy(_list);

适用场景:大型集合、需要特定列表操作、性能关键型代码。 重要:必须使用 ds_list_destroy() 手动销毁,否则会发生内存泄漏!

ds_map(键值对)
// Create
var _map = ds_map_create();

// Add items
_map[? "name"] = "Player";
_map[? "health"] = 100;

// Access
var _hp = _map[? "health"]; // 100

// Check if key exists
if (ds_map_exists(_map, "mana")) {
    // key exists
}

// Iterate
var _key = ds_map_find_first(_map);
while (!is_undefined(_key)) {
    show_debug_message(_key + ": " + string(_map[? _key]));
    _key = ds_map_find_next(_map, _key);
}

// CRITICAL: Always destroy when done!
ds_map_destroy(_map);

适用场景:旧版代码、需要特定映射操作、与现有 ds_map 代码集成。 重要:必须手动调用 ds_map_destroy() 销毁,否则会发生内存泄漏!

建议:尽可能使用结构体代替 ds_map——结构体更简单,无需手动清理。

防止内存泄漏

必须销毁的数据结构:

  • ds_list_destroy(_list)
  • ds_map_destroy(_map)
  • ds_grid_destroy(_grid)
  • ds_priority_destroy(_priority)
  • ds_queue_destroy(_queue)
  • ds_stack_destroy(_stack)
  • surface_free(_surface)
  • buffer_delete(_buffer)

在 Destroy 事件中进行清理的模式:

/// objPlayer Destroy Event
// Clean up data structures

if (ds_exists(inventory_list, ds_type_list)) {
    ds_list_destroy(inventory_list);
}

if (surface_exists(shadow_surface)) {
    surface_free(shadow_surface);
}
文件系统与持久化
datafiles/ 文件夹(包含的文件)

重要限制:某些 GameMaker 版本仅支持 datafiles/ 中的根目录文件——不支持子目录!

✅ CORRECT:
datafiles/config.json
datafiles/items.json
datafiles/level_data.json

❌ WRONG (may not work in all versions):
datafiles/configs/game_config.json
datafiles/data/items/weapons.json

必须注册:datafiles/ 中的每个文件都必须在 .yyp 项目文件中注册:

{"$GMIncludedFile":"","%Name":"config.json","CopyToMask":-1,"filePath":"datafiles","name":"config.json","resourceType":"GMIncludedFile","resourceVersion":"2.0",},
JSON 文件
// Load JSON from datafiles/
function load_json_file(_filename) {
    if (!file_exists(_filename)) {
        show_debug_message("ERROR: File not found: " + _filename);
        return noone;
    }

    var _file = file_text_open_read(_filename);
    var _json_string = "";
    while (!file_text_eof(_file)) {
        _json_string += file_text_read_string(_file);
        file_text_readln(_file);
    }
    file_text_close(_file);

    return json_parse(_json_string);
}

// Save JSON to working directory
function save_json_file(_filename, _data) {
    var _json_string = json_stringify(_data);
    var _file = file_text_open_write(_filename);
    file_text_write_string(_file, _json_string);
    file_text_close(_file);
}
存档文件位置
// Working directory (platform-dependent save location)
var _save_path = working_directory + "savegame.json";

// Game save ID (unique folder for your game)
// On Windows: %LOCALAPPDATA%/[game_save_id]/
var _save_id = game_save_id;
事件系统与执行顺序
事件执行顺序(每帧)
  1. Begin Step - 主逻辑执行前
  2. Alarm Events - 倒计时计时器
  3. Keyboard/Mouse Events - 输入检测
  4. Step - 主要更新逻辑
  5. Collision Events - 移动后
  6. End Step - 所有逻辑执行后
  7. Draw - 渲染游戏世界中的图形
  8. Draw GUI - 渲染 UI 覆盖层
  9. Draw End - 后期处理
持久对象

在 .yy 文件中设置 persistent: true,使对象在房间切换后继续存在。

重要:对持久对象使用事件处理程序时,重新进入房间时要清除处理程序,以避免重复注册!

// rmGameplay Room Creation Code
// Clear handlers to prevent duplicates
global.input_controller.clear_all_handlers();

// Register handlers fresh
global.input_controller.register_handler("ACTION", function(_cmd) {
    // handle action
});
绘图与图形
基本绘图
// Draw sprite
draw_sprite(spr_player, image_index, x, y);
draw_sprite_ext(spr_player, image_index, x, y, scale_x, scale_y, rotation, color, alpha);

// Draw text
draw_text(x, y, "Hello World");
draw_set_font(fnt_arial);
draw_set_color(c_white);
draw_set_halign(fa_center);
draw_set_valign(fa_middle);

// Draw shapes
draw_rectangle(x1, y1, x2, y2, outline);
draw_circle(x, y, radius, outline);
draw_line(x1, y1, x2, y2);
Surface(渲染目标)
// Create surface
if (!surface_exists(shadow_surface)) {
    shadow_surface = surface_create(room_width, room_height);
}

// Draw to surface
surface_set_target(shadow_surface);
draw_clear_alpha(c_black, 0);
// ... draw operations ...
surface_reset_target();

// Draw surface to screen
draw_surface(shadow_surface, 0, 0);

// CRITICAL: Free surface when done
if (surface_exists(shadow_surface)) {
    surface_free(shadow_surface);
}
性能优化
绘制调用优化
  • 将精灵批量放入纹理页,以尽量减少绘制调用
  • 对静态内容(背景、图块)使用图层
  • 缓存开销较大的计算(不要在 Draw 事件中重复计算)
  • 避免在 Draw 事件中创建或销毁实例
碰撞优化
  • 精确碰撞检测前,先进行宽阶段距离检查
  • 设置适当的碰撞遮罩(精确或边界框)
  • 使用碰撞图层和组
  • 需要获取实例时,可考虑使用 instance_position() 代替 place_meeting()
内存管理
  • 使用完毕后始终销毁数据结构
  • 不再需要时释放 Surface
  • 使用后删除缓冲区
  • 在 Destroy 事件中进行清理

常见问题与解决方案

请参阅 COMMON_PITFALLS.md 获取全面的故障排查指南。

快速参考

对象创建问题:

  • 缺少 .yy 文件 → 对象不会出现在 IDE 中 → 使用上面的模板创建 .yy 文件
  • 缺少 .yyp 注册 → 编译错误“object not found” → 将条目添加到 .yyp 资源数组中
  • 事件名称错误 → 事件不会触发 → 使用准确名称(Draw_64.gml,而不是 Draw_GUI_0.gml)

内存问题:

  • 数据结构泄漏 → 内存使用量不断增长 → 始终调用 ds_destroy 函数
  • Surface 泄漏 → 内存使用量不断增长 → 始终调用 surface_free()
  • 忘记添加 Destroy 事件 → 资源未清理 → 添加包含清理代码的 Destroy 事件

文件系统问题:

  • datafiles/ 子目录 → 文件未找到错误 → 将文件移到 datafiles/ 根目录
  • 缺少 .yyp 注册 → 找不到包含的文件 → 在 .yyp 中注册文件

GML 语法问题:

  • 三元运算符链式嵌套 → 编译错误 → 使用双括号包裹嵌套条件
  • 变量作用域 → 未定义变量 → 检查局部、实例和全局作用域
  • 数组边界 → 索引超出范围 → 访问前检查数组大小

高级主题

如需深入了解高级功能,请参阅:

着色器编程(GLSL ES)

何时使用着色器:

  • 高级视觉效果(光照、模糊、描边、色彩分级)
  • 逐像素操作(自定义渲染效果)
  • 性能优化(基于 GPU 的计算)

基本着色器工作流:

  1. 在 IDE 中创建着色器资源
  2. 编写顶点着色器(.vsh)和片段着色器(.fsh)
  3. 设置着色器:shader_set(shd_outline);
  4. 传递 uniforms:shader_set_uniform_f(u_time, current_time);
  5. 绘制精灵/表面
  6. 重置着色器:shader_reset();

GLSL ES 语法、示例和常见着色器模式请参阅 ADVANCED_TOPICS.md。

网络与多人游戏

何时使用网络功能:

  • 多人游戏(客户端-服务端、点对点)
  • 在线排行榜
  • HTTP API 集成
  • 云存档系统

异步 HTTP 示例:

// Send GET request
var _request_id = http_get("https://api.example.com/data");

// In Async HTTP event
var _id = async_load[? "id"];
if (_id == _request_id) {
    var _status = async_load[? "status"];
    if (_status == 0) {
        var _result = async_load[? "result"];
        var _data = json_parse(_result);
        // Process data
    }
}

网络套接字、缓冲区、多人游戏架构和同步模式请参阅 ADVANCED_TOPICS.md。

平台专属开发

移动端(iOS/Android):

  • 触摸输入:device_mouse_x_to_gui()、device_mouse_y_to_gui()
  • 虚拟按键:virtual_key_add()
  • 传感器:device_get_tilt_x()、device_get_tilt_y()

主机(PlayStation、Xbox、Nintendo Switch):

  • 手柄支持:gamepad_button_check()、gamepad_axis_value()
  • 平台检测:os_type、os_get_config()

HTML5:

  • 浏览器集成:clickable_add()、clickable_set_style()
  • JavaScript 执行:js_runner_eval()

桌面端(Windows、macOS、Linux):

  • 文件对话框:get_open_filename()、get_save_filename()
  • 窗口控制:window_set_fullscreen()、window_set_size()

平台专属开发指南请参阅 ADVANCED_TOPICS.md。

资源

此技能包含全面的参考文档:

references/

GML_REFERENCE.md(约 1500 行)

  • 按类别整理的完整 GML 函数参考
  • 绘图、数学、字符串、实例、房间、数据结构、文件、网络、着色器、表面、粒子、音频
  • 常见任务的代码模式(库存、状态机、对话、保存/加载、摄像机系统)
  • Struct 与 Object 的选择指南
  • 构造函数模式和方法变量

ARCHITECTURE_PATTERNS.md(约 500 行)

  • GameMaker 专属架构模式(服务定位器、命令模式、事件驱动流程、过程式逻辑、数据驱动设计)
  • 为什么游戏引擎不适合 MVC/MVP(事件驱动架构与请求/响应架构)
  • GML 场景下的 SOLID 原则(SRP、OCP、LSP、ISP、DIP,附代码示例)
  • 设计原则(DRY、KISS、YAGNI)
  • 性能模式(热路径优化、struct 与 ds_map、查找映射)
  • 应避免的反模式(滥用全局变量、深层继承、函数重定义)

COMMON_PITFALLS.md(约 800 行)

  • 对象创建问题(缺少 .yy、未在 .yyp 中注册、事件名称错误)
  • 文件系统问题(datafiles/ 子目录、.yyp 注册、路径)
  • GML 语法陷阱(三元运算符、变量作用域、数组边界、访问未定义内容)
  • 内存管理(ds_* 泄漏、表面泄漏、缓冲区泄漏、清理模式)
  • 性能问题(绘制优化、碰撞优化、实例管理)
  • 网络问题(异步事件、缓冲区类型、超时、平台差异)
  • 着色器问题(GLSL ES 兼容性、uniform 命名、纹理采样)

QUICK_REFERENCE.md(约 600 行)

  • 事件类型/编号完整表及执行顺序
  • 键盘常量(vk_* 常量、ord() 用法、按键按下与按键检测)
  • 鼠标常量(mb_* 常量、鼠标事件类型、device_mouse_* 函数)
  • 常见 GML 模式(距离检测、方向计算、碰撞检测、随机范围)
  • 颜色函数(常量、make_color_、color_get_、merge_color)
  • IDE 版本参考(常见版本、功能、兼容性说明)

ADVANCED_TOPICS.md(约 1000 行)

  • 着色器编程(GLSL ES 语法、顶点/片段着色器示例、uniform、多通道技术、调试)
  • 网络模式(客户端-服务端架构、大厅系统、数据包结构、延迟补偿、缓冲区)
  • 平台专属开发(移动端触摸/传感器、主机游戏手柄/成就、HTML5 浏览器 API、桌面操作系统交互)
  • 高级图形(表面、光照系统、法线贴图、粒子、图块地图、摄像机)
  • 性能分析(调试覆盖层、瓶颈定位、内存分析、减少绘制调用、代码分析)

请记住:此技能提供指导和参考。请始终查阅官方 GameMaker 手册,以获取最新、最全面的文档!

评论

支持 Markdown