Java游戲服務(wù)器入門09 - 重新設(shè)計(jì)攻擊消息

之前為了測試重構(gòu)的代碼添加了攻擊消息,現(xiàn)在再來重新設(shè)計(jì)一下攻擊消息:UserAttkCmdHandler,使代碼簡潔一下,并且添加處理死亡消息,最后對(duì)攻擊消息的一個(gè)小BUG做調(diào)整:

1.對(duì)User進(jìn)行滿血調(diào)整

之前我們?cè)谔砑庸粝⒌臅r(shí)候,可以看到攻擊一下會(huì)扣除10滴血,但是并不清楚人物一共有多少血量,在這里做一個(gè)簡單的調(diào)整,把人物的滿血設(shè)置為100
在User類中添加當(dāng)前血量

package com.tk.tinygame.herostory.model;

public class User {

        /**
         * 用戶 Id
         */
        public int userId;

        /**
         * 影響形象
         */
        public String heroAvatar;

        /**
         * 當(dāng)前血量
         */
        public int currHp;

        /**
         * 移動(dòng)狀態(tài)
         */
        public final MoveState moveState = new MoveState();

}

在用戶入場時(shí)添加一個(gè)當(dāng)前血量為100

 User newUser = new User();
 newUser.userId = userId;
 newUser.heroAvatar = heroAvatar;
 //新添加,類中其他都不動(dòng)
 newUser.currHp = 100;
 UserManager.addUser(newUser);
2.修改用戶攻擊指令處理器:UserAttkCmdHandler

思路:獲取攻擊者/被攻擊者ID,當(dāng)攻擊時(shí),首先推送攻擊消息,再推送減血消息,如果被攻擊者死亡則推送死亡消息,直接上代碼,和之前差不多
注意:
1.減血的計(jì)算盡量在服務(wù)器端處理,如果在客戶端處理可能外掛的問題會(huì)比較嚴(yán)重
2.注意代碼

 if(null == targetUser){
            //如果沒打到人,也推送一下攻擊,這樣客戶端可以顯示攻擊動(dòng)作,否則沒有,影響體驗(yàn)
            broadcastAttrResult(attkUserId,-1);
            return;
        }

因?yàn)橹挥泄粽吆捅还粽呓聿庞袦p血邏輯,但是當(dāng)角色遠(yuǎn)距離點(diǎn)攻擊鍵時(shí),我們還是要廣播一個(gè)攻擊消息,否則其他客戶端都不會(huì)顯示角色的攻擊動(dòng)作,算是修復(fù)一個(gè)小BUG吧

package com.tk.tinygame.herostory.cmdhandler;

import com.tk.tinygame.herostory.Broadcaster;
import com.tk.tinygame.herostory.model.User;
import com.tk.tinygame.herostory.model.UserManager;
import com.tk.tinygame.herostory.msg.GameMsgProtocol;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.AttributeKey;

/**
 * 用戶攻擊指令處理器
 */

public class UserAttkCmdHandler implements ICmdHandler<GameMsgProtocol.UserAttkCmd>{
    @Override
    public void handle(ChannelHandlerContext ctx, GameMsgProtocol.UserAttkCmd cmd) {
        if (null == ctx ||
                null == cmd) {
            return;
        }

        // 獲取攻擊者 Id
        Integer attkUserId = (Integer) ctx.channel().attr(AttributeKey.valueOf("userId")).get();
        if (null == attkUserId) {
            return;
        }

        // 獲取被攻擊者 Id
        int targetUserId = cmd.getTargetUserId();
        User targetUser = UserManager.getByUserId(targetUserId);

        if(null == targetUser){
            //如果沒打到人,也推送一下攻擊,這樣客戶端可以顯示攻擊動(dòng)作,否則沒有,影響體驗(yàn)
            broadcastAttrResult(attkUserId,-1);
            return;
        }

        final int dmgPoint = 10;
        targetUser.currHp = targetUser.currHp - dmgPoint;

        //廣播攻擊結(jié)果
        broadcastAttrResult(attkUserId,targetUserId);
        //廣播減血結(jié)果
        broadcastSubtractHpResult(targetUserId,dmgPoint);

        if(targetUser.currHp <= 0){
            broadcastDieHpResult(targetUserId);
        }
    }

    /**
     * @param attkUserId
     * @param targetUserId
     * @deprecated 廣播攻擊結(jié)果
     */
    static private void broadcastAttrResult(int attkUserId,int targetUserId){
        if(attkUserId <= 0){
            return;
        }
        GameMsgProtocol.UserAttkResult.Builder resultBuilder = GameMsgProtocol.UserAttkResult.newBuilder();
        resultBuilder.setAttkUserId(attkUserId);
        resultBuilder.setTargetUserId(targetUserId);

        GameMsgProtocol.UserAttkResult newResult = resultBuilder.build();
        Broadcaster.broadcast(newResult);
    }

    /**
     * @param targetUserId
     * @param subtractHp
     * @deprecated 廣播減血結(jié)果
     */
    static private void broadcastSubtractHpResult(int targetUserId,int subtractHp){
        if(targetUserId <= 0 || subtractHp <= 0){
            return;
        }

        // 減血消息, 可以根據(jù)自己的喜好寫...
        // 例如加上裝備加成, 暴擊等等.
        // 這些都屬于游戲的業(yè)務(wù)邏輯了!
        GameMsgProtocol.UserSubtractHpResult.Builder resultBuilder2 = GameMsgProtocol.UserSubtractHpResult.newBuilder();
        resultBuilder2.setTargetUserId(targetUserId);
        //簡單的邏輯,打一下減10血
        resultBuilder2.setSubtractHp(subtractHp);

        GameMsgProtocol.UserSubtractHpResult newResult = resultBuilder2.build();
        Broadcaster.broadcast(newResult);
    }

    /**
     * @param targetUserId
     * @deprecated 廣播死亡結(jié)果
     */
    static private void broadcastDieHpResult(int targetUserId){
        if(targetUserId <= 0){
            return;
        }

        GameMsgProtocol.UserDieResult.Builder resultBuilder = GameMsgProtocol.UserDieResult.newBuilder();
        resultBuilder.setTargetUserId(targetUserId);

        GameMsgProtocol.UserDieResult newResult = resultBuilder.build();
        Broadcaster.broadcast(newResult);
    }
}
3.測試地址:注意是step020哦

測試地址:http://cdn0001.afrxvk.cn/hero_story/demo/step020/index.html?serverAddr=127.0.0.1:12345&userId=1,當(dāng)被攻擊者的血量到0時(shí),人物就被砍翻在地了= =,做出這個(gè)效果就對(duì)了。

效果圖

4.思考

大家可以思考一個(gè)問題,攻擊的效果似乎實(shí)現(xiàn)了,那么攻擊還有其他問題么?應(yīng)該如何解決呢,接下來的文章會(huì)有解釋和實(shí)現(xiàn)哈

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容