C++20游戏循环移动逻辑实现咨询:如何避免代码冗余
C++20 游戏移动逻辑的几种实现方案
结合你使用C++20和GCC 11.1.0的环境,针对移动逻辑需求,下面提供几种可行的实现方案:
方案一:使用std::optional(类型安全,推荐)
利用C17引入、C20完善的std::optional标记速度值是否存在,既保证类型安全,又能清晰区分"无值"与"有值"状态,可读性和维护性都不错。
#include <optional> // 游戏循环内的代码 std::optional<int> xVel, yVel; if (direction == LEFT /* && 其他条件 */) { xVel = /* left_calculation */; } else if (direction == RIGHT /* && 其他条件 */) { xVel = /* right_calculation */; } else if (direction == UP /* && 其他条件 */) { yVel = /* up_calculation */; } else if (direction == DOWN /* && 其他条件 */) { yVel = /* down_calculation */; } // 统一处理逻辑 if (xVel.has_value() || yVel.has_value()) { // 使用*xVel、*yVel访问实际值 if (xVel) player.pos.x += *xVel; if (yVel) player.pos.y += *yVel; // 其他庞大的处理逻辑... }
优点:类型安全,无未初始化变量风险;逻辑清晰,分支职责明确;符合现代C++风格。
缺点:需引入<optional>头文件,新手需理解基础用法。
方案二:使用goto跳转(简洁直接)
若追求代码紧凑,且处理逻辑庞大不想重复编写,可通过goto直接跳转到统一处理块。注意提前声明变量,避免跳过初始化导致未定义行为。
// 游戏循环内的代码 int xVel = 0, yVel = 0; bool hasX = false, hasY = false; if (direction == LEFT /* && 其他条件 */) { xVel = /* left_calculation */; hasX = true; goto handle_movement; } else if (direction == RIGHT /* && 其他条件 */) { xVel = /* right_calculation */; hasX = true; goto handle_movement; } else if (direction == UP /* && 其他条件 */) { yVel = /* up_calculation */; hasY = true; goto handle_movement; } else if (direction == DOWN /* && 其他条件 */) { yVel = /* down_calculation */; hasY = true; goto handle_movement; } // 无有效方向时跳过处理 goto end_movement; handle_movement: // 统一处理逻辑 if (hasX || hasY) { if (hasX) player.pos.x += xVel; if (hasY) player.pos.y += yVel; // 其他庞大的处理逻辑... } end_movement: // 后续代码
优点:避免重复编写处理逻辑,代码紧凑;适合简单场景快速实现。
缺点:滥用goto会降低代码可读性,增加维护难度;需额外布尔标记判断值有效性。
方案三:重构为独立函数(解耦逻辑,适合复杂场景)
若底部处理逻辑非常庞大,将计算与处理拆分到独立函数,能让主逻辑更简洁,也方便单独测试处理逻辑。
#include <optional> #include <utility> // 计算速度的函数 std::pair<std::optional<int>, std::optional<int>> calculateMovement(Direction direction /*, 其他参数 */) { std::optional<int> xVel, yVel; if (direction == LEFT /* && 其他条件 */) { xVel = /* left_calculation */; } else if (direction == RIGHT /* && 其他条件 */) { xVel = /* right_calculation */; } else if (direction == UP /* && 其他条件 */) { yVel = /* up_calculation */; } else if (direction == DOWN /* && 其他条件 */) { yVel = /* down_calculation */; } return {xVel, yVel}; } // 处理移动的函数 void handleMovement(std::optional<int> xVel, std::optional<int> yVel) { if (xVel.has_value() || yVel.has_value()) { if (xVel) player.pos.x += *xVel; if (yVel) player.pos.y += *yVel; // 其他庞大的处理逻辑... } } // 游戏循环内的代码 auto [xVel, yVel] = calculateMovement(currentDirection /*, 其他参数 */); handleMovement(xVel, yVel);
优点:逻辑解耦,主循环代码简洁;处理逻辑可单独维护测试;符合模块化编程思想。
缺点:需额外定义函数,简单场景略显繁琐;若需访问全局游戏状态(如player),需合理设计参数或类结构。
内容的提问来源于stack exchange,提问作者spaL
相关产品推荐
相关产品推荐

