PHP+Redis实现游戏体力值加减及自动恢复的操作

在开发小游戏项目时,有时需要服务端来操作用户的体力。如果使用数据库来保存略显冗余,性能也稍有不足,所有使用Redis的过期机制可以更好更快的快速实现需求。

示例中的Redis经过了多例的封装 参照 多例Redis类实现

<?php

namespace app\common;

use ryjoin\Redis;

/**
 * 体力计算
 * Class Live
 * @package app\common
 */
class Live
{
    /**
     * redis的key
     * @var string
     */
    protected $key;

    /**
     * 体力配置
     * @var array
     */
    protected $config = [
        'max' => 5, // 最大值
        'interval' => 60 // 体力恢复间隔(秒)
    ];

    /**
     * 设置用户
     * Energy constructor.
     * @param $user_id
     */
    public function __construct($user_id)
    {
        $this->key = "lives:$user_id";
    }

    /**
     * 获取体力
     * @return array
     */
    public function get()
    {
        $lives = $this->config['max']; // 体力
        $next_live_time= -1; // 恢复倒计时(秒)

        if (Redis::db()->exists($this->key)) {
            $ttl = (int)Redis::db()->ttl($this->key);
            $reduce = ceil($ttl / $this->config['interval']);
            $lives -= $reduce;
            $next_live_time = $ttl % $this->config['interval'];
            // 如果正好处于恢复时 否则会出现剩余0的情况
            if ($next_live_time == 0) {
                $next_live_time = $this->config['interval'] - 1;
            }
        }

        return [
            'lives' => (int)$lives, // 当前体力
            'next_live_time' => $next_live_time // 下一次恢复时间(秒)
        ];
    }

    /**
     * 扣除体力
     * @return bool
     */
    public function reduce()
    {
        $lives = $this->get();
        if ($lives['lives'] == 0) { // 没有体力
            return false;
        }

        if (Redis::db()->exists($this->key)) {
            $expired_ttl = (int)Redis::db()->ttl($this->key);
            Redis::db()->set($this->key, 1, $expired_ttl + $this->config['interval']);
        } else {
            Redis::db()->set($this->key, 1, $this->config['interval']);
        }

        return true;
    }

    /**
     * 增加体力
     * @return bool
     */
    public function increase()
    {
        $lives = $this->get();
        if ($lives['lives'] == $this->config['max']) { // 体力上限
            return true;
        }

        if (Redis::db()->exists($this->key)) {
            $expired_ttl = (int)Redis::db()->ttl($this->key);
            if ($expired_ttl <= $this->config['interval']) {
                Redis::db()->del($this->key);
            }

            Redis::db()->set($this->key, 1, $expired_ttl - $this->config['interval']);
        }

        return true;
    }
}

使用方式 (根据自身业务)

获取当前用户的体力

	/**
     * 获取用户体力
     * @param $user_id
     * @return array
     */
    public function getPlayer($user_id)
    {
        // 获取体力信息
        $live = new Live($user_id);
        $lives = $live->get();
        
        return [
            'currentLives' => $lives['lives'],
            'nextLiveTime' => $lives['next_live_time'],
            'watchAdCount' => $this->getWatchAdCount($user_id)
        ];
    }

观看激励视频后增加用户体力


	/**
     * 激励视频广告上限
     * @var int
     */
    protected $watchAdCount = 2;

    /**
     * 剩余广告次数
     * @param $user_id
     * @return int
     */
    protected function getWatchAdCount($user_id)
    {
        $todayWatchCount = (int)Redis::db()->get("game:watch:$user_id");
        return $this->watchAdCount - $todayWatchCount;
    }

	/**
     * 激励视
     * 频增加体力
     * @param $user_id
     * @return bool
     */
    public function watchAd($user_id)
    {
        $watchAdCount = $this->getWatchAdCount($user_id);
        if ($watchAdCount == 0) {
            $this->code = Code::FAILURE;
            $this->error = '次数不足';
            return false;
        }

        // 增加用户体力
        $live = new Live($user_id);
        $live->increase();
        Redis::db()->incrBy("game:watch:$user_id", 1);
        Redis::db()->expire("game:watch:$user_id", Tools::nowTillTomorrowZero());
        return true;
    }
    

扣除体力,当然扣除后是会自动恢复的

  // 扣除体力 每次-1 
  $live = new Live($GLOBALS['user_id']);
  $result = $live->reduce();
  

更多使用方式

如果有多个体力的场景,那么可以修改Live类中的key 这样就可以复用到多个体力场景

    /**
     * redis的key
     * @var string
     */
    protected $key;
    
	/**
     * 设置用户
     * Energy constructor.
     * @param $user_id
     */
    public function __construct($key, $user_id)
    {
        $this->key = "$key:$user_id";
    }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值