在游戏系统中,我们需要给玩家设计出一个成就系统,满足玩家的荣誉感, 同时给玩家设定目标,除了荣誉感,达成某种成就,往往也会给玩家带来某种好处,例如声望值的提高。
获得成就需要一定的条件,也就是,玩家需要完成某种指定的动作后,才可以获得需要的成就。下面我具体举一个成就的例子,说明成就系统的实现方式。
成就名: 勇者无畏
达成条件:战斗胜利次数到达10次
战斗奖励:增加玩家的声望值。
实现以上需求,需要注意的问题:
A 需要统计玩家战斗的次数
B 当成就达到的时候,不能重复达到
C 完成成就后,可以增加玩家的声望值
D 进行某种动作的时候,可能同时开启两个成就
成就的完成流程:
数据库设计:
需要统计完成战斗次数的表:user_state
我的成就表: user_achievement
成就的配置表:
* related_step_field: 如果字段可以对应到user_stats 这样就可以不要记录成就的完成度 当获取进度的时候 $this->_user['stats][related_step_field]
类设计
我的统计模型类:
职能:记录需要统计的字段,如果字段发生改变,调用成就类里面的方法。
<?php
/**
* 我的统计 模型
*
* @author zhangkai
* $Id: Stats.php 4374 2013-07-30 07:26:26Z sunli $
*/
class Model_User_Stats extends Model_User_Trait
{
/**
* 子类构函
*
* @return void
*/
protected function _initTrait()
{
$this->_prop = $this->DaoDs('UserStats')->get($this->_uid);
}
/**
* 指定字段自增
*
* @return bool
*/
public function increment($field, $offset = 1)
{
// 注意这里 需要给这个属性加成,否则,就算数据库里面的字段已经更新,还是不能获取到最新信息
$this->_prop[$field] += $offset;
return $this->DaoDs('UserStats')
->where(array('uid' => $this->_uid))
->increment($field, $offset);
}
// 增加主动胜利场数
public function addTotalWinTimes($num = 1)
{
$this->increment('total_win_times', $num);
$this->_user->achievement->checkBattleWinAchieve();
}
}
我的成就类:
职能:
检测成就是否达成
改变我的成就的进度
成就达成后,给予相应的奖励
/**
* 我的成就
*
*/
class Model_User_Achievement extends Model_User_Trait
{
// 内部方法,用于判断是否达成了某种类型的成就
private function _checkAchieve($field, $attrs)
{
$times = $this->_user['stats'][$field];
$result = array();
foreach ($attrs as $data) {
if ($times >= $data['line']) {
$result[$data['achieve_id']] = $this->achieve($data['achieve_id']);
}
}
return $result;
}
// 检测是否达成了战斗胜利的相关成就
public function checkBattleWinAchieve()
{
$data = array();
// 同时开启两个成就 line:表示成就需要的总进度
$data[] = array('line' => 100, 'achieve_id' => 721003);
$data[] = array('line' => 10, 'achieve_id' => 721001);
return $this->_checkAchieve('total_win_times', $data);
}
// 达成成就(不可重复达成)
public function achieve($achieveId)
{
// 已达成过直接退出 如果是第一次开启成就,则插入此成就
if ($this->DaoDs('UserAchievement')->isCreated($this->_uid, $achieveId)) {
return false;
}
// 成就详细
$achieveInfo = Dao('Static_Achievement')->get($achieveId);
// 实时弹出框
$this->_user->tips->setTips('showGainAchievementTip', $achieveInfo);
// 达成成就后 奖励声望
$this->_user->base->addReputation($achieveInfo['reputation_award']);
// 设置成就已经完成
return $this->DaoDs('UserAchievement')->createAchieve($this->_uid, $achieveId);
}
}