导航:从零开始手写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上点个星星,谢谢!