游戏中大型自动比赛玩法设计

争霸赛赛程范例3月1日 0:00~3月3日 12:00 报名 40级以上手动报名3月3日 13:00 淘汰赛 “13:00取数据,提前1小时向玩家发送邮件提醒13:10开始出战报,每隔5分钟出1场战报天榜负5局进入地榜,地榜负5局则被淘汰”3月4日 14:00 16强赛(32进16) “每小时1局,每局取1次数据,5局3胜制天地榜同时进行比赛开始前1小时向玩家发送邮件提醒取数据制度”3月5日 14:00 16进83月6日 14:00 8进43月7日 14:00 半决赛3月8日 14:00 决赛3月8日 决赛全部结束 统一发放奖励

比赛的时间控制由单独时间进程来控制时间的推进,相当于php中的crontab,表结构上一个玩家比赛进程表player_race,一个各阶段玩家成员信息表player_race_member,后期系统匹配各阶段玩家匹配信息表player_race_opponent,一个各阶段玩家战报信息表player_race_report,一个各阶段玩家结果表player_race_result,玩家表可以分为 玩家比赛信息表 player_st_jjc_race 玩家匹配信息表 player_st_jjc_race_opponent 玩家日志表 player_st_jjc_race_score_log

第一步 报名很简单直接报名请求记录玩家数据就行,报名时间结束时触发事件对所有玩家进行匹配

case try_get_player_server_war(PlayerId) of

null ->

Tran = fun() ->

game_db:write(#player_server_war {

player_id = PlayerId,

apply_time = lib_misc:get_local_timestamp()

})

% mod_deploy:get(PlayerId, ?RACE_SERVER_WAR)

end,

game_db:do(Tran);

_ ->

exit(already_apply)

end.

% 本服报名结束手机玩家数据

apply_over() ->

List = get_all_player_server_war(),

Tran = fun() ->

lists:foreach(

fun(Rec) ->

game_db:write(Rec #player_server_war {

race_step = ?RS_TIAN_BANG_TAOTAI

})

end,

List

)

end,

game_db:do(Tran),

?INFO("apply_over",[]),

ZoneList = lists:foldl(

fun(PlayerServerWar, R) ->

[PlayerServerWar #player_server_war.player_id | R]

end,

[],

get_all_player_server_war()

),

mod_race:init_race_member(

?RACE_SERVER_WAR,

0,

?RS_TIAN_BANG_TAOTAI,

0,

ZoneList,

normal

).

注意的是用一个单独的进程来管理活动步骤开启结束!Er15646489002180

% 每一个活动开始所要做的处理

activity_start (ActivityId) ->

case mod_server:is_game_server() of

true ->

xdh_race_srv:activity_start(ActivityId);

false ->

case mod_server:is_cc_server() of

true ->

% cc_server_war_cron_srv:activity_start(Id);

noop;

false ->

noop

end

end.

% 每一个活动结束所要做的处理

activity_stop (ActivityId) ->

case mod_server:is_game_server() of

true ->

xdh_race_srv:activity_stop(ActivityId);

false ->

case mod_server:is_cc_server() of

true ->

% cc_server_war_cron_srv:activity_stop(Id);

noop;

false ->

noop

end

end.

在到点时间的相应上做特殊处理

第二步 开启淘汰赛淘汰赛的开启同样用时间进程来控制,到点后调用启动方法!Er15646493808263 (判断结束 、清上一轮数据)淘汰赛相当于一个递归的过程,全服玩家进行了一场比赛后记录玩家信息及淘汰结果直到淘汰赛结束的条件,同时需要一个全服步骤数据记录,然后循环比赛其中每一轮淘汰赛可分为 判断结束 、清上一轮数据 、不重复随机匹配 、 战斗及数据记录 、 循环!Er15647109579023 (不重复随机匹配 循环)

race_fight (RaceId, ZoneId, RaceStep, TeamIdA, TeamIdB) ->

#player_race {

race_times = RaceTimes

} = get_player_race(RaceId, ZoneId),

Tran = fun() ->

case race_call(RaceId, fight, [RaceStep, TeamIdA, TeamIdB]) of

[] ->

exit({invalid_fight, RaceId, TeamIdA, TeamIdB});

ReportList ->

{_, WinTeamId} = lists:foldr(

fun(Report, {NowIndex, NowWinTeamId}) ->

#war_result {

winner = {_, WinnerId},

army_result1 = #army_result {

army_key = {_, PlayerIdA}

},

army_result2 = #army_result {

army_key = {_, PlayerIdB}

}

} = Report,

NewWinTeamId = if

NowIndex =:= length(ReportList) ->

WinTeamId = if

WinnerId =:= PlayerIdA ->

TeamIdA;

true ->

TeamIdB

end,

game_db:write(#player_race_result {

race_id = RaceId,

zone_id = ZoneId,

race_step = RaceStep,

player_id = TeamIdA,

player_id1 = TeamIdB,

race_times = RaceTimes,

version = ?GET_ENV(vsn, ""),

report_time = lib_misc:get_local_timestamp(),

winner_id = WinTeamId

}),

WinTeamId;

true ->

NowWinTeamId

end,

game_db:write(#player_race_report {

race_id = RaceId,

zone_id = ZoneId,

race_step = RaceStep,

player_id = TeamIdA,

race_times = RaceTimes,

index = NowIndex,

attacker_id = PlayerIdA,

defender_id = PlayerIdB,

winner_id = WinnerId,

report_id = war_report_srv:record_war_report(Report, 30 * 86400)

}),

{

NowIndex - 1,

NewWinTeamId

}

end,

{length(ReportList), 0},

ReportList

),

WinTeamId

end

end,

{atomic, TeamId} = game_db:do(Tran),

TeamId.

在淘汰赛结束后,将剩余晋级玩家进入晋级赛步骤,同时初始化随机匹配!Er15647120482687一下两种匹配方式

init_race_member(RaceId, ZoneId, RaceStep, Group, TeamIdList, normal) ->

Tran = fun() ->

lists:foldl(

fun(TeamId, NowIndex) ->

game_db:write(#player_race_member {

race_id = RaceId,

race_step = RaceStep,

zone_id = ZoneId,

group = Group,

index = NowIndex,

player_id = TeamId

}),

NowIndex + 1

end,

1,

TeamIdList

)

end,

game_db:do(Tran);

init_race_member(RaceId, ZoneId, RaceStep, Group, TeamIdList, random) ->

#race_step {

match_num = MatchNum

} = get_race_step(RaceStep),

Step = get_index_step(length(TeamIdList), MatchNum),

Tran = fun() ->

lists:foldl(

fun(TeamId, NowIndex) ->

game_db:write(#player_race_member {

race_id = RaceId,

race_step = RaceStep,

zone_id = ZoneId,

group = Group,

index = NowIndex,

player_id = TeamId

}),

if

NowIndex + Step > MatchNum * 2 ->

1 + Step div 2;

true ->

NowIndex + Step

end

end,

1,

lib_misc:shuffle(TeamIdList)

)

end,

game_db:do(Tran);

第三步 战报战报开启也是进程时间来控制!Er15647145661718

第四步 开启晋级赛同样是进程计时器开启,比赛流程除了一局定输赢以外和淘汰赛基本一致,比赛也是一次性打完,战报根据时间慢慢的播放

% 开启杯赛

timer_start_race() ->

case mod_server:is_cc_server() of

true ->

% cc_server_war_cron_srv:start_race(0);

noop;

false ->

Times = mod_server:get_player_server_int_data(?SDT_SERVER_WAR_RACE_TIMES),

xdh_race_srv:try_apply(mod_server,set_player_server_int_data,[?SDT_SERVER_WAR_RACE_TIMES,Times + 1]),

start_race(),

mod_timer:reset(1, ?TIMER_XIAN_DAO_HUI_BEI_SAI)

end.

start_race() ->

RaceStep = get_server_war_race_step(),

PlayerRace = mod_race:get_player_race(?RACE_SERVER_WAR,0),

IsOver = case mod_race:start_race(?RACE_SERVER_WAR, 0, RaceStep, 3) of

true ->

true;

_ ->

mod_timer:reset(0, ?TIMER_XIAN_DAO_HUI_BEI_SAI, 3420),

false

end,

RaceTimes = if

RaceStep =/= PlayerRace #player_race.race_step ->

1;

true ->

PlayerRace #player_race.race_times + 1

end,

xdh_race_srv:try_apply(mod_server,set_player_server_int_data,[?SDT_SERVER_WAR_RACE_TIMES,RaceTimes]),

deal_receive_beisai_data(RaceStep,IsOver).

战斗部分基本一致多一个匹配结果记录表

start_race(RaceId, ZoneId, RaceStep, WinTimes) ->

#race_step {

match_num = MatchNum,

next_race = NextRace,

next_step = NextStep

} = get_race_step(RaceStep),

Tran = fun() ->

PlayerRace = get_player_race(RaceId, ZoneId),

if

PlayerRace #player_race.race_step =:= RaceStep,

PlayerRace #player_race.race_times =/= 0 ->

case check_race_over(RaceId, ZoneId, RaceStep) of

true ->

exit(race_over);

_ ->

noop

end,

game_db:write(PlayerRace #player_race {

race_times = PlayerRace #player_race.race_times + 1,

last_time = lib_misc:get_local_timestamp()

});

true ->

clear_race_data(RaceId, ZoneId, RaceStep),

init_race_opponent(RaceId, ZoneId, RaceStep),

game_db:write(PlayerRace #player_race {

race_step = RaceStep,

race_times = 1,

last_time = lib_misc:get_local_timestamp(),

win_times = WinTimes

})

end,

lists:foreach(

fun(Group) ->

lists:foreach(

fun(Index) ->

RaceMemberA = try_get_player_race_member(RaceId, ZoneId, RaceStep, Group, Index * 2 - 1),

RaceMemberB = try_get_player_race_member(RaceId, ZoneId, RaceStep, Group, Index * 2),

if

RaceMemberA =:= null, RaceMemberB =:= null ->

noop;

%%轮空为全空或者B为空

% RaceMemberA =:= null ->

% game_db:write(#player_race_member {

% race_id = RaceId,

% race_step = NextRace,

% group = Group,

% index = Index,

% player_id = RaceMemberB #player_race_member.player_id

% });

RaceMemberB =:= null ->

TeamIdA = RaceMemberA #player_race_member.player_id,

case check_opponent_over(RaceId, ZoneId, RaceStep, TeamIdA) of

true ->

noop;

_ ->

Opponent = try_get_player_race_opponent(RaceId, ZoneId, RaceStep, TeamIdA),

game_db:write(Opponent #player_race_opponent {

winner_id = TeamIdA

}),

game_db:write(#player_race_member {

race_id = RaceId,

zone_id = ZoneId,

race_step = NextRace,

group = Group,

index = Index,

player_id = TeamIdA

}),

race_call(RaceId, race_win, [TeamIdA, Group, RaceStep, NextRace])

end;

true ->

TeamIdA = RaceMemberA #player_race_member.player_id,

TeamIdB = RaceMemberB #player_race_member.player_id,

case check_opponent_over(RaceId, ZoneId, RaceStep, TeamIdA) of

true ->

noop;

_ ->

case race_fight(RaceId, ZoneId, RaceStep, TeamIdA, TeamIdB) of

0 ->

noop;

WinnerId ->

case check_opponent_over(RaceId, ZoneId, RaceStep, TeamIdA, TeamIdB) of

true ->

Opponent = try_get_player_race_opponent(RaceId, ZoneId, RaceStep, TeamIdA),

game_db:write(Opponent #player_race_opponent {

winner_id = WinnerId

}),

game_db:write(#player_race_member {

race_id = RaceId,

zone_id = ZoneId,

race_step = NextRace,

group = Group,

index = Index,

player_id = WinnerId

}),

race_call(RaceId, race_win, [WinnerId, Group, RaceStep, NextRace]);

_ ->

noop

end

end

end

end

end,

lists:seq(1, MatchNum)

)

end,

get_all_race_group()

),

IsOver = check_race_over(RaceId, ZoneId, RaceStep),

if

IsOver =:= true ->

NowPlayerRace = get_player_race(RaceId, ZoneId),

game_db:write(NowPlayerRace #player_race {

race_step = NextStep,

race_times = 0,

last_time = lib_misc:get_local_timestamp()

});

true ->

noop

end,

IsOver

end,

{atomic, Result} = game_db:do(Tran),

Result.

第五步 出晋级赛战报

% 播报战报及通知

deal_receive_beisai_data(RaceStep,IsOver) ->

Tran = fun() ->

% write_race_data(RaceReportList,RaceResultList,MemberList,OpponentList, WorldWarList),

if

IsOver =:= true ->

#race_step {

next_step = NextStep

} = mod_race:get_race_step(RaceStep),

% return_bet(RaceStep),

if

RaceStep =:= ?RS_RACE_1 ->

% give_award(),给予奖励

ZoneId = 0,

case mod_race:try_get_player_race_member(?RACE_SERVER_WAR, ZoneId, ?RS_RACE_1_OVER, ?RG_TIAN_BANG, 1) of

null ->

noop;

Member ->

ServerId = mod_player:get_player_data(Member #player_race_member.player_id,server_id),

ServerName = mod_server:get_server_name(ServerId),

NickName = mod_player:get_player_data(Member #player_race_member.player_id,nickname),

api_chat:centre_screen_message_notify(

?MEST_XIAN_DAO_HUI_GUAN_JUN,

[{ServerName},{NickName}]

)

end;

true ->

noop

end,

mod_server:set_player_server_int_data(?SDT_SERVER_WAR_RACE_STEP, NextStep),

mod_server:set_player_server_int_data(?SDT_SERVER_WAR_RACE_TIMES, 0),

mod_timer:close(1,?TIMER_XIAN_DAO_HUI_BEI_SAI);

true ->

noop

end

end,

game_db:do(Tran).

% api_server_war:notify_new_report().