2. 触发条件设计:布尔条件、阈值条件、时间条件、组合条件(AND/OR/NOT)
触发条件,说白了就是事件轮换的「开关」。你设计得再好的事件链,如果触发条件写死了,玩家体验就会很僵硬。我在项目里见过太多「条件写得太死,玩家死活触发不了」的惨案。
这一章我们就把四种基础条件拆开揉碎,再讲怎么把它们组合起来。嗯,先看一张总览图,心里有个谱。
2.1 布尔条件:最简单的开关
布尔条件就是 true 或 false。游戏里最常见的就是「某个标志位是否被设置」。比如玩家是否接取了任务、某个门是否已经打开、Boss 是否已经被击败。
我个人习惯把布尔条件叫做「旗帜检查」。你想想看,一个变量要么是 1,要么是 0,没有中间态。写起来也最简单:
// 伪代码示例:检查任务是否完成
if (quest_completed == true) {
trigger_event("打开隐藏通道");
}
我在项目中遇到过一个问题:多个系统同时读写同一个布尔变量,导致条件判断出现竞态。后来我强制要求所有布尔条件变量只能由单一系统写入,其他系统只读。这个习惯一直保留到现在。
2.2 阈值条件:数值的比较游戏
阈值条件比布尔条件灵活得多。它不是简单的 true/false,而是比较一个数值是否达到某个界限。比如玩家血量低于 30% 时触发低血量警告,或者金币数量超过 1000 时解锁 VIP 商店。
说白了,阈值条件就是「大于、小于、等于、区间判断」。写代码时要注意边界值处理:
// 伪代码示例:血量阈值触发
if (player.hp <= player.max_hp * 0.3) {
trigger_event("low_hp_warning");
}
// 金币阈值触发
if (player.gold >= 1000) {
unlock_feature("vip_shop");
}
我曾经踩过一个坑:阈值条件用了 > 而不是 >=,结果玩家刚好达到 1000 金币时死活触发不了 VIP 商店。测试组报 bug 报了一整天。从那以后我写阈值条件都会在注释里标清楚「含不含边界」。
| 比较类型 | 运算符 | 示例 | 说明 |
|---|---|---|---|
| 大于 | > | score > 100 | 不包含 100 |
| 大于等于 | >= | score >= 100 | 包含 100 |
| 小于 | < | hp < 30 | 不包含 30 |
| 小于等于 | <= | hp <= 30 | 包含 30 |
| 区间 | && | level >= 5 && level <= 10 | 5 到 10 级之间 |
2.3 时间条件:让事件「等一等」
时间条件是最容易被新手忽略的。你想想看,玩家刚进游戏就弹出一个活动公告,是不是很烦?但如果等 3 秒再弹,体验就好很多。这就是时间条件的价值。
时间条件通常分三种:
- 延迟触发:条件满足后等一段时间再触发事件
- 间隔触发:每隔一段时间重复触发事件
- 时间窗口:只在某个时间段内允许触发(比如晚上 8 点到 10 点的限时活动)
// 伪代码示例:延迟触发
if (condition_met == true) {
start_timer(3.0); // 等待 3 秒
// 3 秒后自动触发
trigger_event("show_announcement");
}
// 间隔触发
start_interval_timer(60.0); // 每 60 秒触发一次
trigger_event("auto_save");
// 时间窗口判断
if (current_hour >= 20 && current_hour < 22) {
trigger_event("limited_time_activity");
}
2.4 组合条件:AND / OR / NOT
单个条件太单薄了。实际项目中,一个事件往往需要多个条件同时满足,或者满足其中之一。这时候就需要组合条件。
组合条件就三个逻辑运算符:
- AND(与):所有条件都为 true 才触发
- OR(或):任意一个条件为 true 就触发
- NOT(非):条件为 false 时才触发
我建议你记住一个原则:AND 收紧条件,OR 放宽条件,NOT 反转条件。看个例子:
// AND 组合:玩家等级 >= 10 并且 拥有钥匙
if (player.level >= 10 && player.has_key == true) {
trigger_event("open_secret_room");
}
// OR 组合:玩家是 VIP 或者 充值超过 100 元
if (player.is_vip == true || player.total_recharge > 100) {
trigger_event("unlock_premium_shop");
}
// NOT 组合:玩家不在战斗状态
if (!player.in_combat) {
trigger_event("show_rest_menu");
}
// 更复杂的嵌套组合
if ((player.level >= 5 && player.has_quest == true) || player.is_gm == true) {
trigger_event("debug_teleport");
}
我曾经在项目里见过一个「万恶的条件表达式」:
if (a || b && c || !d && e) {
// 这行代码没人能看懂
}
嗯,这种写法我强烈建议你避免。组合条件超过 3 个,一定要加括号明确优先级。或者干脆拆成多个 if 判断,可读性比「一行炫技」重要得多。
2.5 实战:设计一个「限时副本」的触发条件
光说不练假把式。我们拿一个真实需求来练手:
需求:设计一个限时副本的触发条件。玩家必须满足以下所有条件才能进入:
- 等级 ≥ 30 级
- 拥有「副本钥匙」道具
- 当前时间在晚上 19:00 ~ 22:00 之间
- 今天还没有进入过该副本
你看,这就是一个典型的组合条件。我们来写一下:
// 限时副本触发条件
bool can_enter_dungeon() {
// 条件1:等级阈值
bool level_ok = (player.level >= 30);
// 条件2:布尔条件 - 拥有钥匙
bool has_key = player.has_item("dungeon_key");
// 条件3:时间窗口
bool time_ok = (current_hour >= 19 && current_hour < 22);
// 条件4:布尔条件 - 今日未进入
bool not_entered_today = (player.daily_dungeon_count == 0);
// 组合:四个条件全部满足
return level_ok && has_key && time_ok && not_entered_today;
}
// 调用
if (can_enter_dungeon()) {
trigger_event("enter_limited_dungeon");
} else {
show_message("条件不满足,无法进入");
}
这个例子把布尔条件、阈值条件、时间条件、组合条件全用上了。你想想看,如果不用组合条件,你得写多少个 if 嵌套?