egret+java小游戏服务端02创建基础pojo类和构建游戏逻辑


一、创建基础pojo类

1.Instruct指令类

public class Instruct{
	private String order;//指令类型
    private long time;//指令的发送时间戳
    private Object obj;//指令包含的内容
    private int roomId;//指令
    private int uid;//userId
   }

基础逻辑是前端发送固定指令类型的Json对象,服务端解析后根据order的不同来调用不同的函数

这显然对后期的维护和扩展有些阻碍,后续会重构这个类

2.Player玩家类

public class Player {

    private double x;//x坐标
    private double y;//y坐标
    private int uid;
    private int token;
    private boolean move = false;
    private double angle;//玩家角度
    private float speed = 30;//玩家速度
    public PlayerMoving playerMoving;//聚合的移动玩家类(继承Player类)
}

这里不得不提到PlayerMoving类
由于指令为move时玩家为移动状态,服务端需要新建一个线程不断的更新玩家的坐标数据,于是新建PlayerMoving extends Player类用于这个线程

public class PlayerMoving extends Player implements Runnable {

    private long time;

    public PlayerMoving(double x, double y, int uid, int token, boolean move, double angle, float speed) {
        super(x, y, uid, token, move, angle, speed);
    }

    public long getTime() {
        return time;
    }

    public PlayerMoving setTime(long time) {
        this.time = time;
        return this;
    }

    @Override
    public void run() {
        //System.out.println("跑动线程启动了,当前move情况" + this.getMove() + "超类情况" + super.getMove());
        long timeDiffer = 0;
        while(this.getMove()){
            try {
                Thread.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized ((Long)time) {
                timeDiffer = System.currentTimeMillis() - time;
                time = System.currentTimeMillis();
                this.setX(this.getX() + (timeDiffer * this.getSpeed() * 0.1F * Math.sin(Math.PI / 180 * this.getAngle())));
                //System.out.println("角度=" + this.getAngle() + "X=" + timeDiffer + "*" + this.getSpeed() + "* 0.1 *" + Math.sin(Math.PI / 180 * this.getAngle()));
                this.setY(this.getY() - (timeDiffer * this.getSpeed() * 0.1F * Math.cos(Math.PI / 180 * this.getAngle())));
                //System.out.println("Y=" + timeDiffer + "*" + this.getSpeed() + "* 0.1 *" + Math.cos(Math.PI / 180 * this.getAngle()));
                //System.out.println("修改后 x:" + this.getX() + "y:" + this.getY());
                Player player = Room.players.get(this.getUid() + "");
                //System.out.println(Room.users.toString());
                //System.out.println(user);
                player.setX(this.getX());
                player.setY(this.getY());
                //System.out.println("跑动线程..." + user.toString());
            }
        }
    }

}

其中跑动函数用玩家的角度和速度,通过简单的三角函数不断计算一定时间内玩家xy值的变化量后更新。

3.Room类

public class Room {
    public static ConcurrentHashMap<String,Player> players = new ConcurrentHashMap<>();
}

Room为一个游戏房间,里面包含所有玩家

示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。

二、游戏逻辑

1.前端发送的指令处理

在channelHandler中,对接收消息进行以下处理

@Override
	protected void channelRead0(ChannelHandlerContext ctx,
								TextWebSocketFrame msg) throws Exception { // (1)
		//System.out.println("接收到text消息..." + msg.text());
		//先对比uid是否正确
		//将消息转为Instruct指令形式,然后交付给manage处理
		Channel incoming = ctx.channel();
		JSONObject jsonObject = JSONObject.fromObject(msg.text());
		Instruct instruct = new Instruct(jsonObject.get("order")+"",jsonObject.getLong("time"),jsonObject.get("obj"),jsonObject.getInt("roomId"),Integer.parseInt(jsonObject.get("uid").toString()));
		if (instruct.getOrder().equals("JOIN")){
			if (!channelMap.containsKey(incoming.id()+"")){
				System.out.println("指令异常返回");
				return;
			}
			System.out.println("map更新" + channelMap.toString());
			channelMap.put(instruct.getUid() + "",channelMap.remove(incoming.id()+""));
			System.out.println("map更新完毕" + channelMap.toString());
		}
		if (!channelMap.containsKey(instruct.getUid() + "")){
			System.out.println("不存在该UID...");
			return;
		}
		//System.out.println("指令存入队列中...");
		MsgManage.addInstruct(instruct);
	}

2.MsgManage接收到指令后进行处理

public class MsgManage implements Runnable{

    private static Queue<Instruct> instructs = new MyLinkedList();
    public static Instruct instruct;
    private boolean manageRun = true;
    public static void addInstruct(Instruct instruct){
        instructs.offer(instruct);
    }

这里包含一个MyLinkedList对offer方法进行了重写,实现了一个简单的代理监听器

public class MyLinkedList extends LinkedList<Instruct> {

    @Override
    public boolean offer(Instruct instruct) {
        super.offer(instruct);
        MsgManage.instruct = this.poll();//返回后删除
        switch (instruct.getOrder()) {
            case "MOVE":
                MsgManage.move();
                break;
            case "JOIN":
                MsgManage.join();
                break;
            case "MOVEOUT":
                MsgManage.moveOut();
                break;
        }
        return true;
    }
}

这里只是使用了最简单的switch进行指令识别,对后续扩展有很大阻碍,后面会对这里进行重构。

3.MsgManage的指令处理

public static void moveOut(){
        Player player = Room.players.get(instruct.getUid()+"");
        if (player == null)
            return;
        player.playerMoving.setMove(false);
        player.setMove(false);
    }
    public static void move(){
        Player player = Room.players.get(instruct.getUid()+"");
        if (player==null)
            return;
        if (player.playerMoving == null){
            player.instanceMoving(instruct.getTime());
        }else{
            player.playerMoving.setTime(System.currentTimeMillis());
        }
        if (instruct.getObj().getClass().equals(Integer.class)){
            player.playerMoving.setAngle(Double.valueOf(instruct.getObj() + ""));
        }else {
            player.playerMoving.setAngle((Double) instruct.getObj());
        }
        if (player.playerMoving.getMove() == true){

        }else {
            player.playerMoving.setMove(true);
            player.setMove(true);
            new Thread(player.playerMoving).start();
        }
    }
    public static void join(){
        //在Room里面加入...
        System.out.println(instruct.toString());
        if (instruct.getUid() == 9){
            Room.players.put(instruct.getUid()+"",new Player(0,0,instruct.getUid(),123,false,0,20));
        }else {
            System.out.println("当前Room" + Room.players.toString());
            System.out.println("Room添加数据");
            Room.players.put(instruct.getUid() + "", new Player(0, 0, instruct.getUid(), 123, false, 0, 1));
            System.out.println("Room添加完毕" +Room.players.toString());
        }
    }

三、游戏房间广播逻辑

//每个房间独有的一个线程,存放在线程池中
public class MsgLogic implements Runnable{

    Room room = new Room();

    @Override
    public void run() {
        while(true) {
            //广播房间信息...
            try {
                Thread.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (Room.players == null || Room.players.isEmpty()) {
                continue;
            }
            for (Map.Entry<String, IPlayer> entry : Room.players.entrySet()) {
                JSONObject jsonObject = JSONObject.fromObject(Room.players);
                //System.out.println("uid" + entry.getKey() + "广播内容" + jsonObject.toString());
                TextWebSocketFrameHandler.channelMap.get(entry.getKey() + "").writeAndFlush(new TextWebSocketFrame(jsonObject.toString()));
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值