基本概念
成就:成就系统可以理解为对某个角色成长过程重大事件的记录;玩家通过查看成就跟踪角色涉及的重大事件。
问题分析
获得成就需要一定的条件,也就是,玩家需要完成某种指定的动作后,才可以获得需要的成就。下面我具体举一个成就的例子,说明成就系统的实现方式。
成就名: 勇者无畏
达成条件:战斗胜利次数到达10次
战斗奖励:增加玩家的声望值。
实现以上需求,需要注意的问题:
A 需要统计玩家战斗的次数
B 当成就达到的时候,不能重复达到
C 完成成就后,可以增加玩家的声望值
D 进行某种动作的时候,可能同时开启两个成就
业务逻辑
数据库设计
需要统计完成战斗次数的表:user_state
我的成就表: user_achievement
成就的配置表:
解决方案
JAVA
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zstu.metrocity.entity.Achievememt;
import org.apache.ibatis.annotations.*;
import java.util.List;
/**
* <p>
* Mapper 接口
* </p>
*
* @author ShenTuZhiGang
* @since 2020-04-09
*/
public interface AchievememtMapper extends BaseMapper<Achievememt> {
@Select("SELECT * FROM user_achievememt JOIN achievememt ON aid=achievememt.id WHERE uid=#{userId}")
@Results(value = {
@Result(property = "id",column = "aid")
})
List<Achievememt> getByUserId(Integer userId);
}
PHP
我的统计模型类:
记录需要统计的字段,如果字段发生改变,调用成就类里面的方法。
<?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);
}
}