要实现一个双人战斗的匹配类,需要设计匹配队列、玩家状态管理、匹配逻辑和回调机制。以下是一个基于热血江湖游戏框架的匹配类实现示例,主要参考了服务端接口和客户端交互模式:
```lua
-- 双人战斗匹配类
local DoubleBattleMatch = class("DoubleBattleMatch")
function DoubleBattleMatch:ctor()
self._matchQueue = {} -- 匹配队列
self._matchedPairs = {} -- 已匹配成功的对局
self._playerStates = {} -- 玩家状态:1=空闲 2=匹配中 3=战斗中
self._matchTimeout = 30 -- 匹配超时时间(秒)
self._matchTimer = nil -- 匹配定时器
end
-- 玩家加入匹配队列
function DoubleBattleMatch:JoinMatch(actor)
local userId = userid(actor)
if not userId then return false end
-- 检查玩家状态
if self._playerStates[userId] == 3 then
sendmsg(actor, 6, "您正在战斗中,无法加入匹配")
return false
end
-- 设置玩家状态为匹配中
self._playerStates[userId] = 2
-- 加入匹配队列
table.insert(self._matchQueue, {
actor = actor,
userId = userId,
joinTime = os.time(),
level = currabil(actor, 0), -- 获取玩家等级
power = getfightpower(actor) -- 获取战斗力
})
sendmsg(actor, 6, "已加入匹配队列,等待对手...")
-- 启动匹配检查
self:StartMatchCheck()
return true
end
-- 玩家取消匹配
function DoubleBattleMatch:CancelMatch(actor)
local userId = userid(actor)
if not userId then return false end
-- 从队列中移除
for i, player in ipairs(self._matchQueue) do
if player.userId == userId then
table.remove(self._matchQueue, i)
self._playerStates[userId] = 1
sendmsg(actor, 6, "已取消匹配")
return true
end
end
return false
end
-- 开始匹配检查
function DoubleBattleMatch:StartMatchCheck()
if self._matchTimer then return end
self._matchTimer = SL:Schedule(function()
self:CheckMatch()
end, 1) -- 每秒检查一次匹配
end
-- 匹配逻辑
function DoubleBattleMatch:CheckMatch()
local currentTime = os.time()
-- 清理超时玩家
for i = #self._matchQueue, 1, -1 do
local player = self._matchQueue[i]
if currentTime - player.joinTime > self._matchTimeout then
sendmsg(player.actor, 6, "匹配超时,已退出队列")
self._playerStates[player.userId] = 1
table.remove(self._matchQueue, i)
end
end
-- 匹配玩家(至少需要2人)
if #self._matchQueue >= 2 then
-- 按等级和战斗力进行匹配(简单实现:按加入顺序)
for i = 1, #self._matchQueue - 1 do
for j = i + 1, #self._matchQueue do
local player1 = self._matchQueue[i]
local player2 = self._matchQueue[j]
-- 检查等级差(例如不超过5级)
local levelDiff = math.abs(player1.level - player2.level)
if levelDiff <= 5 then
-- 匹配成功
self:CreateBattle(player1, player2)
-- 从队列移除
table.remove(self._matchQueue, j)
table.remove(self._matchQueue, i)
return
end
end
end
end
end
-- 创建战斗
function DoubleBattleMatch:CreateBattle(player1, player2)
-- 设置玩家状态为战斗中
self._playerStates[player1.userId] = 3
self._playerStates[player2.userId] = 3
-- 生成战斗ID
local battleId = os.time() .. "_" .. math.random(1000, 9999)
-- 保存匹配对局
self._matchedPairs[battleId] = {
player1 = player1,
player2 = player2,
startTime = os.time(),
mapId = 1001, -- 战斗地图ID
pos1 = {x = 100, y = 50, z = 100}, -- 玩家1出生点
pos2 = {x = 200, y = 50, z = 200} -- 玩家2出生点
}
-- 通知玩家匹配成功
sendmsg(player1.actor, 6, string.format("匹配成功!对手:%s", targetinfo(player2.actor, "NAME")))
sendmsg(player2.actor, 6, string.format("匹配成功!对手:%s", targetinfo(player1.actor, "NAME")))
-- 准备传送(延迟3秒)
SL:Schedule(function()
self:TeleportToArena(battleId)
end, 3)
end
-- 传送到竞技场
function DoubleBattleMatch:TeleportToArena(battleId)
local battle = self._matchedPairs[battleId]
if not battle then return end
-- 传送玩家到战斗地图
map(battle.player1.actor, battle.mapId, battle.pos1.x, battle.pos1.y, battle.pos1.z)
map(battle.player2.actor, battle.mapId, battle.pos2.x, battle.pos2.y, battle.pos2.z)
-- 设置敌对关系
setrelation(battle.player1.actor, battle.player2.actor, 1) -- 1=敌人
setrelation(battle.player2.actor, battle.player1.actor, 1)
-- 开始战斗倒计时
self:StartBattleCountdown(battleId)
end
-- 开始战斗倒计时
function DoubleBattleMatch:StartBattleCountdown(battleId)
local battle = self._matchedPairs[battleId]
if not battle then return end
local countdown = 5
local timer = SL:Schedule(function()
if countdown > 0 then
sendmsg(battle.player1.actor, 6, string.format("战斗将在 %d 秒后开始", countdown))
sendmsg(battle.player2.actor, 6, string.format("战斗将在 %d 秒后开始", countdown))
countdown = countdown - 1
else
-- 开始战斗
sendmsg(battle.player1.actor, 6, "战斗开始!")
sendmsg(battle.player2.actor, 6, "战斗开始!")
-- 停止定时器
if timer then
SL:Unschedule(timer)
end
-- 设置战斗状态
self:SetBattleState(battleId, true)
end
end, 1)
end
-- 设置战斗状态
function DoubleBattleMatch:SetBattleState(battleId, isFighting)
local battle = self._matchedPairs[battleId]
if not battle then return end
-- 设置玩家战斗状态
SL:SetValue("BATTLE_IS_FIGHT_STATE", isFighting, battle.player1.actor)
SL:SetValue("BATTLE_IS_FIGHT_STATE", isFighting, battle.player2.actor)
end
-- 战斗结束处理
function DoubleBattleMatch:EndBattle(battleId, winnerUserId)
local battle = self._matchedPairs[battleId]
if not battle then return end
-- 重置玩家状态
self._playerStates[battle.player1.userId] = 1
self._playerStates[battle.player2.userId] = 1
-- 重置战斗状态
self:SetBattleState(battleId, false)
-- 重置关系
setrelation(battle.player1.actor, battle.player2.actor, 3) -- 3=无关系
setrelation(battle.player2.actor, battle.player1.actor, 3)
-- 发送结果
if winnerUserId then
local winner = (winnerUserId == battle.player1.userId) and battle.player1.actor or battle.player2.actor
local loser = (winnerUserId == battle.player1.userId) and battle.player2.actor or battle.player1.actor
sendmsg(winner, 6, "恭喜你获得胜利!")
sendmsg(loser, 6, "很遗憾,你输了")
-- 发放奖励(示例)
giveitem(winner, 1001, 1) -- 胜利奖励
giveitem(loser, 1002, 1) -- 参与奖励
end
-- 清理数据
self._matchedPairs[battleId] = nil
-- 传送回主城(示例)
SL:Schedule(function()
map(battle.player1.actor, 1000, 100, 50, 100)
map(battle.player2.actor, 1000, 100, 50, 100)
end, 5)
end
-- 检查玩家是否在战斗中
function DoubleBattleMatch:IsPlayerInBattle(userId)
return self._playerStates[userId] == 3
end
-- 获取匹配队列人数
function DoubleBattleMatch:GetQueueCount()
return #self._matchQueue
end
-- 清理所有匹配
function DoubleBattleMatch:CleanAll()
self._matchQueue = {}
self._matchedPairs = {}
self._playerStates = {}
if self._matchTimer then
SL:Unschedule(self._matchTimer)
self._matchTimer = nil
end
end
return DoubleBattleMatch
```
**使用示例:**
```lua
-- 初始化匹配系统
local matchSystem = DoubleBattleMatch.new()
-- 玩家加入匹配
function OnJoinDoubleBattle(actor)
local result = matchSystem:JoinMatch(actor)
if result then
-- 可以在这里更新UI显示匹配状态
SL:SetValue("BATTLE_IS_SEARCH_STATE", true, actor)
end
end
-- 玩家取消匹配
function OnCancelDoubleBattle(actor)
local result = matchSystem:CancelMatch(actor)
if result then
SL:SetValue("BATTLE_IS_SEARCH_STATE", false, actor)
end
end
-- 检查战斗结果(可以在玩家死亡时调用)
function OnPlayerDie(actor, killer)
local userId = userid(actor)
-- 查找对应的战斗
for battleId, battle in pairs(matchSystem._matchedPairs) do
if battle.player1.userId == userId or battle.player2.userId == userId then
local winnerUserId = (killer and userid(killer)) or
(battle.player1.userId == userId and battle.player2.userId or battle.player1.userId)
matchSystem:EndBattle(battleId, winnerUserId)
break
end
end
end
```
**主要功能说明:**
1. **匹配队列管理**:玩家加入/取消匹配队列
2. **智能匹配**:基于等级差进行匹配(可扩展为战斗力匹配)
3. **状态管理**:跟踪玩家状态(空闲/匹配中/战斗中)
4. **战斗管理**:创建战斗、传送玩家、设置敌对关系
5. **结果处理**:战斗结束后的奖励发放和状态重置
6. **超时处理**:匹配超时自动清理
**扩展建议:**
- 可添加匹配条件配置(如等级范围、战斗力范围)
- 可添加匹配优先级(等待时间越长匹配范围越宽)
- 可添加观战功能
- 可添加战绩记录和排行榜
这个实现参考了热血江湖的SL系统、消息发送、地图传送、关系设置等核心机制,可以直接集成到现有游戏系统中。