从零开始手写mmo游戏从框架到爆炸(二十七)— 英雄属性展示及穿戴装备-1

导航:从零开始手写mmo游戏从框架到爆炸(零)------ 导航-CSDN博客

本章我们把命令行客户端与后台串起来,并完成穿戴装备的功能。

服务端改造

首先改造角色抽象类

增加穿戴的装备抽象(野怪也可以穿戴装备)

java 复制代码
public abstract class Character implements Attackable, Serializable {

    // 装备的装备
    private Equips equips;

    public Equips getEquips() {
        if(equips == null){
            equips = new Equips();
        }
        return equips;
    }

    public void setEquips(Equips equips) {
        this.equips = equips;
    }

穿戴装备的抽象

java 复制代码
@Data
public class Equips implements Serializable {

    public  String string ="\t\t\t\t\t\t\t\t\t";

    public  String tt ="\t\t";

    private List<Equipment> all;

    public Equips(){
        all = new ArrayList<>();
    }

    public Equips(String string, Equipment weapon, Equipment leftRing, Equipment rightRing, Equipment breastplate, Equipment shoes,
                  Equipment helmet, Equipment glove, Equipment necklace, Equipment legArmor, Equipment belt, Equipment barcer,
                  Equipment shoulder, Equipment shield) {
        all = new ArrayList<>();
        this.string = string;
        this.weapon = weapon;
        this.leftRing = leftRing;
        this.rightRing = rightRing;
        this.breastplate = breastplate;
        this.shoes = shoes;
        this.helmet = helmet;
        this.glove = glove;
        this.necklace = necklace;
        this.legArmor = legArmor;
        this.belt = belt;
        this.barcer = barcer;
        this.shoulder = shoulder;
        this.shield = shield;
        initAll();
    }

    private void initAll() {
        if(weapon != null){
            all.add(weapon);
        }
        if(leftRing != null){
            all.add(leftRing);
        }
        if(leftRing != null){
            all.add(leftRing);
        }
        if(breastplate != null)
            all.add(breastplate);
        if(shoes != null)
            all.add(shoes);
        if(helmet != null)
            all.add(helmet);
        if(glove != null)
            all.add(glove);

        if(necklace != null)
            all.add(necklace);
        if(legArmor != null)
            all.add(legArmor);

        if(belt != null)
            all.add(belt);
        if(barcer != null)
            all.add(barcer);

        if(shoulder != null)
            all.add(shoulder);
        if(shield != null)
            all.add(shield);
    }

    // 装备的武器
    private Equipment weapon;

    // 装备的戒指 左戒
    private Equipment leftRing;

    // 装备的戒指 右戒
    private Equipment rightRing;

    // 装备的护甲
    private Equipment breastplate;

    // 装备的鞋
    private Equipment shoes;

    // 装备的头盔
    private Equipment helmet;

    // 装备的手套
    private Equipment glove;

    // 装备的项链
    private Equipment necklace;

    // 装备的腿甲
    private Equipment legArmor;

    // 装备的腰带
    private Equipment belt;

    // 装备的护壁
    private Equipment barcer;

    // 装备的肩甲
    private Equipment shoulder;

    // 装备的盾牌
    private Equipment shield;

    public String prettyPrint() {
        return  string+"****装备信息**********************************************************\n"+
                tt + "武器:" + (getWeapon() == null ? "无" : getWeapon().toString()) +"\n"+
                tt + "盾牌:" + (getShield() == null ? "无" : getShield().toString()) +"\n"+
                tt + "胸甲:" + (getBreastplate() == null ? "无" : getBreastplate().toString()) +"\n"+
                tt + "头盔:" + (getHelmet() == null ? "无" : getHelmet().toString()) +"\n"+
                tt + "肩甲:" + (getShoulder() == null ? "无" : getShoulder().toString()) +"\n"+
                tt + "护壁:" + (getBarcer() == null ? "无" : getBarcer().toString()) +"\n"+
                tt + "手套:" + (getGlove() == null ? "无" : getGlove().toString()) +"\n"+
                tt + "腰带:" + (getBelt() == null ? "无" : getBelt().toString()) +"\n"+
                tt + "腿甲:" + (getLegArmor() == null ? "无" : getLegArmor().toString()) +"\n"+
                tt + "鞋子:" + (getShoes() == null ? "无" : getShoes().toString()) +"\n"+
                tt + "左戒:" + (getLeftRing() == null ? "无" : getLeftRing().toString()) +"\n"+
                tt + "右戒:" + (getRightRing() == null ? "无" : getRightRing().toString()) +"\n"+
                tt + "项链:" + (getNecklace() == null ? "无" : getNecklace().toString()) +"\n"+
                string+""+"************************************************************";
    }

    public Equipment findByPosition(EquipmentEnum equipmentEnum){
        if(equipmentEnum.equals(EquipmentEnum.WEAPON))
            return this.getWeapon();
        if(equipmentEnum.equals(EquipmentEnum.BARCER))
            return this.getBarcer();
        if(equipmentEnum.equals(EquipmentEnum.BELT))
            return this.getBelt();
        if(equipmentEnum.equals(EquipmentEnum.BREASTPLATE))
            return this.getBreastplate();
        if(equipmentEnum.equals(EquipmentEnum.GLOVES))
            return this.getGlove();
        if(equipmentEnum.equals(EquipmentEnum.HELMET))
            return this.getHelmet();
        if(equipmentEnum.equals(EquipmentEnum.LEFTRING))
            return this.getLeftRing();
        if(equipmentEnum.equals(EquipmentEnum.LEGARMOR))
            return this.getLegArmor();
        if(equipmentEnum.equals(EquipmentEnum.NECKLACE))
            return this.getNecklace();
        if(equipmentEnum.equals(EquipmentEnum.RIGHTRING))
            return this.getRightRing();
        if(equipmentEnum.equals(EquipmentEnum.SHIELD))
            return this.getShield();
        if(equipmentEnum.equals(EquipmentEnum.SHOES))
            return this.getShoes();
        if(equipmentEnum.equals(EquipmentEnum.SHOULDER))
            return this.getShoulder();
        return null;
    }


    public List<Equipment> getAll() {
        return all;
    }
}

穿脱装备的功能开发

新增一个接口 WearEquipment

java 复制代码
public interface WearEquipment {

    String wear(Equipment equipment, int weaponType);

    String takeOff(Equipment equipment);
}

在角色抽象类Character 中来实现:

java 复制代码
 @Override
    public Tuple<String, List<String>> wear(Equipment equipment, int weaponType) {
        Tuple<String, List<String>> result = new Tuple<>();
        result.setValue(new ArrayList<>());

        String takeOffEquipmentId = null;
        // 装备级别要小于等于英雄的等级
        if(equipment.getLevel() > 1 && equipment.getLevel() > getLevel()){
            result.getValue().add("对不起,装备等级高于英雄,无法穿戴");
            result.setKey(null);
            return result;
        }
        // 先看同类的是否存在,如果存在,先脱再穿
        EquipmentEnum equipmentPosition = equipment.getEquipmentPosition();
        switch (equipmentPosition.getCode().toLowerCase()) {
            case "weapon":
                if(weaponType != equipment.getWeaponTypeEnum().getCode()){
                    result.getValue().add("对不起,该武器不适合英雄,无法穿戴");
                    result.setKey(null);
                    return result;
                }
                if (equips.getWeapon() != null) {
                    takeOffEquipmentId = takeOff(equips.getWeapon());
                }
                equips.setWeapon(equipment);
                break;
            case "breastplate":
                if (equips.getBreastplate() != null) {
                    takeOffEquipmentId = takeOff(equips.getBreastplate());
                }
                equips.setBreastplate(equipment);
                break;
            case "shield":
                if (equips.getShield() != null) {
                    takeOffEquipmentId = takeOff(equips.getShield());
                }
                equips.setShield(equipment);
                break;
            case "shoes":
                if (equips.getShoes() != null) {
                    takeOffEquipmentId = takeOff(equips.getShoes());
                }
                equips.setShoes(equipment);
                break;
            case "helmet":
                if (equips.getHelmet() != null) {
                    takeOffEquipmentId = takeOff(equips.getHelmet());
                }
                equips.setHelmet(equipment);
                break;
            case "gloves":
                if (equips.getGlove() != null) {
                    takeOffEquipmentId = takeOff(equips.getGlove());
                }
                equips.setGlove(equipment);
                break;
            case "necklace":
                if (equips.getNecklace() != null) {
                    takeOffEquipmentId = takeOff(equips.getNecklace());
                }
                equips.setNecklace(equipment);
                break;
            case "leftring":
                if (equips.getLeftRing() != null) {
                    takeOffEquipmentId = takeOff(equips.getLeftRing());
                }
                equips.setLeftRing(equipment);
                break;
            case "rightring":
                if (equips.getRightRing() != null) {
                    takeOffEquipmentId = takeOff(equips.getRightRing());
                }
                equips.setRightRing(equipment);
                break;
            case "legarmor":
                if (equips.getLegArmor() != null) {
                    takeOffEquipmentId = takeOff(equips.getLegArmor());
                }
                equips.setLegArmor(equipment);
                break;
            case "belt":
                if (equips.getBelt() != null) {
                    takeOffEquipmentId =  takeOff(equips.getBelt());
                }
                equips.setBelt(equipment);
                break;
            case "barcer":
                if (equips.getBarcer() != null) {
                    takeOffEquipmentId = takeOff(equips.getBarcer());
                }
                equips.setBarcer(equipment);
                break;
            case "shoulder":
                if (equips.getShoulder() != null) {
                    takeOffEquipmentId = takeOff(equips.getShoulder());
                }
                equips.setShoulder(equipment);
                break;
            default:
                result.getValue().add("穿戴装备失败" + equipment.getName());
                result.setKey(null);
                return result;
        }
        List<String> lines = wearEquipment(equipment);
        result.getValue().addAll(lines);
        result.setKey(takeOffEquipmentId);
        return result;
    }

    @Override
    public String takeOff(Equipment equipment) {
        // 脱装备就是整体属性下降
        this.setStrength(this.strength - equipment.getStrength());
        this.setArmature(this.armature - equipment.getArmature());
        this.setConstitution(this.constitution - equipment.getConstitution());
        this.hp.addAndGet(-equipment.getHp());
        this.setMagic(this.magic - equipment.getMagic());
        this.setTechnique(this.technique - equipment.getTechnique());
        this.setSpeed(this.speed - equipment.getSpeed());
        this.setPoisonResistance(this.poisonResistance - equipment.getPoisonResistance());
        this.setFlameResistance(this.flameResistance - equipment.getFlameResistance());
        this.setThunderResistance(this.thunderResistance - equipment.getThunderResistance());
        this.setIceResistance(this.iceResistance - equipment.getIceResistance());
        equipment.setUsed(false);
        return equipment.getId();
    }

    private List<String> wearEquipment(Equipment equipment) {
        List<String> result = new ArrayList<>();
        result.add("穿戴装备" + equipment.getName() + " 成功");
        // 穿装备就是整体属性提升
        this.setStrength(this.strength + equipment.getStrength());
        this.setArmature(this.armature + equipment.getArmature());
        this.setConstitution(this.constitution + equipment.getConstitution());
        this.hp.addAndGet(equipment.getConstitution() * 10 + equipment.getHp());
        this.hpMax = this.hp.get();
        this.setMagic(this.magic + equipment.getMagic());
        this.setTechnique(this.technique + equipment.getTechnique());
        this.setSpeed(this.speed + equipment.getSpeed());
        // 装备提升的抗性
        this.setThunderResistance(this.thunderResistance + equipment.getThunderResistance());
        this.setFlameResistance(this.flameResistance + equipment.getFlameResistance());
        this.setPoisonResistance(this.poisonResistance + equipment.getPoisonResistance());
        this.setIceResistance(this.iceResistance + equipment.getIceResistance());
        equipment.setUsed(true);
        return result;
    }

新增接口

新增装备列表和穿戴装备接口,以及获得个人属性接口- ServerHeroTag

java 复制代码
package com.loveprogrammer.command.server;

public interface ServerHeroTag {


    /***
     * 创建英雄
     */
    int TAG_HERO_CREATE = 1;


    /***
     * 英雄的详情
     */
    int TAG_HERO_INFO = 2;

    /***
     * 英雄装备列表
     */
    int TAG_HERO_EQUIP_LIST = 3;

    /***
     * 英雄穿戴装备
     */
    int TAG_HERO_EQUIP_WEAR = 4;
}

英雄详情查询

英雄查询返回体:

HeroInfo

java 复制代码
@Data
public class HeroInfo extends RequestBase {

    public HeroInfo() {
    }

    public String string = "\t\t\t\t\t\t\t\t\t";

    private int id;                         // 角色id
    private String name;                   // 角色信息模板
    private int strength;                  // 力量 影响物理输出 物理技能输出
    private int armature;                 // 护甲值 影响物理防御和法术防御
    private int constitution;               // 体质 影响生命值 一点体质增加10点生命值
    private int magic;                       // 魔力 影响法术输出 法术技能输出
    private int technique;                   // 技巧 影响闪避率、暴击率
    private int speed;                         // 攻击速度
    private int hpMax;                        // 最大生命值

    private int level;                           // 级别
    private Integer currentExp;

    /**
     * 下一级所需经验值
     **/
    private Integer nextLevelNeedExp;

    // 毒抗
    private int poisonResistance;

    // 火抗
    private int flameResistance;

    // 电抗
    private int thunderResistance;

    // 冰抗
    private int iceResistance;

    //角色打印信息的重写
    public String prettyPrint() {
        return string + "*****信息****\n" +
                string + "姓名:" + this.name + "\n" +
                string + "级别" + this.level + "\n" +
                string + "血量:" + this.hpMax + "\n" +
                string + "力量:" + this.strength + "\n" +
                string + "法力:" + this.magic + "\n" +
                string + "技巧:" + this.technique + "\n" +
                string + "护甲值" + this.armature + "\n" +
                string + "速度" + this.speed + "\n" +
                string + "毒抗" + this.poisonResistance + "\n" +
                string + "火抗" + this.flameResistance + "\n" +
                string + "雷抗" + this.thunderResistance + "\n" +
                string + "冰抗" + this.iceResistance + "\n" +
                string + "当前经验" + this.currentExp + "\n" +
                string + "下一级经验" + this.nextLevelNeedExp + "\n" +
                string + "" + "*************";
    }


    //角色打印信息的重写
    public String toString() {
        return "**** 名称:" + this.name + " " +
                "级" + this.level + " " +
                "血:" + this.hpMax + " " +
                "甲: " + this.armature + " " +
                "力:" + this.strength + " " +
                "法:" + this.magic + " " +
                "技:" + this.technique + " " +
                "速:" + this.speed + " " +
                "抗性[毒:" + this.poisonResistance + " " +
                "火:" + this.flameResistance + " " +
                "雷:" + this.thunderResistance + " " +
                "冰:" + this.iceResistance + "] " +
                "经验(" + this.currentExp + "/" + this.nextLevelNeedExp + ") ****";
    }
}

HeroHandler

java 复制代码
@TagListener(tag = ServerHeroTag.TAG_HERO_INFO,messageClass = StringRequest.class)
    public StringMessage getHeroInfo(ChannelHandlerContext ctx, StringRequest data) throws Exception {
        int sessionId = getSessionId(ctx.channel());
        UserGameWrapper gameWrapper = SessionGameContext.USER_GAME_MAP.get(sessionId);
        HeroWrapper currentHero = gameWrapper.getCurrentHero();

        // 转成英雄详情
        HeroInfo heroInfo = HeroConvert.INSTANCE.toHeroInfo(currentHero.getHero());
        StringMessage message = StringMessage.create(data.getSuccessCallbackTopic(), data.getSuccessCallbackTag());
        message.setStatusCode(CommonValue.MSG_STATUS_CODE_SUCCESS);
        message.setBody(JSON.toJSONString(heroInfo));
        return message;
    }

客户端改造

补充展示命令 ClientSceneTag

java 复制代码
public interface ClientSceneTag {

    /***
     * 战斗场景
     */
    int TAG_SCENE_BATTLE = 1;

    /***
     * 英雄属性查看
     */
    int TAG_SCENE_HERO = 2;
}

展示功能- 改造portalMenu

java 复制代码
@TagListener(tag = ClientMenuTag.TAG_MENU_PORTAL,messageClass = StringRequest.class)
    public void portalMenu(ChannelHandlerContext ctx, StringRequest msg){
        ConsolePrint.publishMessage(msg.getContent());
        // 展示首页数据
        ConsolePrint.publishMessage("请选择您要进行的操作");
        ConsolePrint.publishMessage("【1.打怪】  【2.属性及装备】  【3.战兽】");
        ConsolePrint.publishMessage("【4.冒险者工会】   【5.副本】  【6.工会】 ");
        ConsolePrint.publishMessage("【8.配置】  【9.退出】");
        ConsolePrint.publishMessage("请选择:");

        int choose = ScannerInput.inputInt(1, 9, 9);

        if (choose != 9) {
            switch (choose) {
                case 1:
                    // 请求地图列表,同时跳转到地图菜单
                    StringMessage message = StringMessage.create(ServerTopic.TOPIC_BATTLE, ServerBattleTag.TAG_BATTLE_MAPS);
                    message.setStatusCode(CommonValue.MSG_STATUS_CODE_SUCCESS);
                    StringRequest request = new StringRequest(ClientTopic.TOPIC_MENU,ClientMenuTag.TAG_MENU_MAP_CHOOSE, ClientTopic.TOPIC_MENU,ClientMenuTag.TAG_MENU_PORTAL);
                    message.setBody(JSON.toJSONString(request));
                    ChannelUtils.pushToServer(ctx.channel(), message);
                    break;
                case 2:
                    // 请求英雄数据
                    message = StringMessage.create(ServerTopic.TOPIC_HERO, ServerHeroTag.TAG_HERO_INFO);
                    message.setStatusCode(CommonValue.MSG_STATUS_CODE_SUCCESS);
                    request = new StringRequest(ClientTopic.TOPIC_SCENE,ClientSceneTag.TAG_SCENE_HERO, ClientTopic.TOPIC_MENU,ClientMenuTag.TAG_MENU_PORTAL);
                    message.setBody(JSON.toJSONString(request));
                    ChannelUtils.pushToServer(ctx.channel(), message);

       ...

增加新的handler方法

java 复制代码
@TagListener(tag = ClientSceneTag.TAG_SCENE_HERO, messageClass = HeroInfo.class)
    public void heroInfo(ChannelHandlerContext ctx, HeroInfo data) {
        ConsolePrint.publishMessage("英雄属性如下");
        ConsolePrint.publishMessage(data.prettyPrint());


        ConsolePrint.publishMessage("英雄装备如下");


        ConsolePrint.publishMessage("请选择操作");
        ConsolePrint.publishMessage("【1.根据系统推荐更换装备】  【2.查看已有装备,自选装备更换】 【3.卖掉装备】", 1);
        ConsolePrint.publishMessage("【4.合成装备】   【5.查看共享装备】  【6.返回】", 1);
        ConsolePrint.publishMessage("请选择:");
        int choose = ScannerInput.inputInt(1, 6, 6);
        if (choose != 6) {
            switch (choose) {
                case 1:
                    ConsolePrint.publishMessage("暂未开放");
                    break;
                case 2:
                    ConsolePrint.publishMessage("暂未开放");
                    break;
                case 3:
                    ConsolePrint.publishMessage("暂未开放");
                    break;
                case 4:
                    ConsolePrint.publishMessage("暂未开放");
                    break;
                case 5:
                    ConsolePrint.publishMessage("暂未开放");
                    break;
                default:
                    ConsolePrint.publishMessage("暂未开放");
                    break;
            }
        }

        // 返回上一级菜单 主菜单
        StringRequest msg = new StringRequest();
        NetworkClientListener.getInstance().forward(ctx,ClientTopic.TOPIC_MENU, ClientMenuTag.TAG_MENU_PORTAL, JSON.toJSONString(msg));
    }

效果

java 复制代码
【1.登录已有账户】  【2.注册新账户】  【3.退出】
请选择:
1
请输入账户名:
eric
请输入密码:
111111
234:234
请选择要创建的职业
1:JobChoose.JobItem(id=1, name=战士, desc=剑类武器, strength=60, armature=5, constitution=80, magic=0, technique=15, speed=130)
1
选择的职业为战士
请输入角色的名称:
haha
124:124
英雄创建成功
请选择您要进行的操作
【1.打怪】  【2.属性及装备】  【3.战兽】
【4.冒险者工会】   【5.副本】  【6.工会】 
【8.配置】  【9.退出】
请选择:
2
暂未开放,敬请期待
367:367
英雄属性如下
									*****信息****
									姓名:haha
									级别0
									血量:800
									力量:60
									法力:0
									技巧:15
									护甲值5
									速度130
									毒抗0
									火抗0
									雷抗0
									冰抗0
									当前经验0
									下一级经验100
									*************
英雄装备如下
请选择操作
【1.根据系统推荐更换装备】  【2.查看已有装备,自选装备更换】 【3.卖掉装备】
【4.合成装备】   【5.查看共享装备】  【6.返回】
请选择:

全部源码详见:

gitee : eternity-online: 多人在线mmo游戏 - Gitee.com

分支:step-14

请各位帅哥靓女帮忙去gitee上点个星星,谢谢!

相关推荐
职略2 小时前
负载均衡类型和算法解析
java·运维·分布式·算法·负载均衡
区块链蓝海2 小时前
Ignis 应用: 社交 + 游戏 + 工业4.0,Ignis 构建Web3生态圈
游戏·web3
A22742 小时前
LeetCode 196, 73, 105
java·算法·leetcode
容若只如初见3 小时前
项目实战--Spring Boot + Minio文件切片上传下载
java·spring boot·后端
阿里巴巴P8资深技术专家3 小时前
Java常用算法&集合扩容机制分析
java·数据结构·算法
weixin_440401693 小时前
分布式锁——基于Redis分布式锁
java·数据库·spring boot·redis·分布式
码农爱java3 小时前
Spring Boot 中的监视器是什么?有什么作用?
java·spring boot·后端·面试·monitor·监视器
zengson_g3 小时前
当需要对大量数据进行排序操作时,怎样优化内存使用和性能?
java·数据库·算法·排序算法
血战灬狂龙4 小时前
pom.xml文件加载后没有变成maven图标
xml·java·maven
Apifox.4 小时前
什么是 HTTP POST 请求?初学者指南与示范
后端·http·学习方法·web