javascript - Libgdx socket.io 敌人移动只出现在第一个连接的客户端
问题描述
我正在使用socket.io(使用node.js)在Libgdx中构建一个mmorpg。我正在尝试创建敌人(怪物,骷髅等)。我创建了一个怪物类,它适用于单人游戏,但我正在尝试在每个在线玩家上正确移动这些敌人。当我运行此代码时,它会在所有客户端上创建敌人,但是当敌人移动时,客户端上不会出现任何动作。所以我需要将每个怪物的位置发送到服务器并在每个客户端获取这些位置客户,但我不知道该怎么做。
我的游戏画面代码:
public class GameScreen implements Screen {
private final float UPDATE_TIME = 1/60f;
float timer;
private Socket socket;
String id;
Player player;
Texture playerTex;
Texture friendlyPlayerTex;
Texture monsterTex;
HashMap<String, FriendlyPlayer> friendlyPlayers;
HashMap<String, MPMonster> monsters;
private Multiplayer game;
TiledMap tiledMap;
OrthographicCamera camera;
private Viewport gamePort;
TiledMapRenderer tiledMapRenderer;
private Hud hud;
private World world;
private Box2DDebugRenderer box2DDebugRenderer;
private BitmapFont usernameFont;
private Monster monster;
public GameScreen(Multiplayer game) {
this.game = game;
Gdx.input.setInputProcessor(null);
playerTex = new Texture("player.png");
friendlyPlayerTex = new Texture("player.png");
monsterTex = new Texture("agent.png");
friendlyPlayers = new HashMap<String, FriendlyPlayer>();
monsters = new HashMap<String, MPMonster>();
float w = Gdx.graphics.getWidth() / Multiplayer.PPM;
float h = Gdx.graphics.getHeight() / Multiplayer.PPM;
camera = new OrthographicCamera();
camera.setToOrtho(false,w,h);
camera.update();
tiledMap = new TmxMapLoader().load("maps/newmap.tmx");
tiledMapRenderer = new OrthogonalTiledMapRenderer(tiledMap, 1 / Multiplayer.PPM);
world = new World(new Vector2(0, 0), true);
box2DDebugRenderer = new Box2DDebugRenderer();
new B2DWorldCreator(world, tiledMap);
gamePort = new FitViewport(Multiplayer.V_WIDTH / Multiplayer.PPM, Multiplayer.V_HEIGHT / Multiplayer.PPM, camera);
hud = new Hud(game.batch);
usernameFont = new BitmapFont(Gdx.files.internal("pixthulhu/raw/font-export.fnt"));
usernameFont.setUseIntegerPositions(false);
usernameFont.getData().setScale(1 / 140f);
usernameFont.setColor(Color.WHITE);
//monster = new Monster(700, 800, 28, 32, monsterTex, world);
connectSocket();
configSocketEvents();
}
public void updateServer(float dt) {
timer += dt;
if(timer >= UPDATE_TIME && player != null && player.hasMoved()) {
JSONObject data = new JSONObject();
try {
data.put("x", player.getX());
data.put("y", player.getY());
data.put("vx", player.body.getLinearVelocity().x);
data.put("vy", player.body.getLinearVelocity().y);
data.put("bx", player.body.getPosition().x);
data.put("by", player.body.getPosition().y);
data.put("username", player.username);
socket.emit("playerMoved", data);
} catch (JSONException e) {
Gdx.app.log("SOCKET.IO", "Error sending update data!");
}
}
if(timer >= UPDATE_TIME && monster != null && monster.hasMoved()) {
JSONObject data = new JSONObject();
try {
data.put("x", monster.getX());
data.put("y", monster.getY());
data.put("vx", monster.body.getLinearVelocity().x);
data.put("vy", monster.body.getLinearVelocity().y);
data.put("bx", monster.body.getPosition().x);
data.put("by", monster.body.getPosition().y);
socket.emit("monsterMoved", data);
} catch (JSONException e) {
Gdx.app.log("SOCKET.IO", "Error sending update data!");
}
}
}
public void handleInput(){
if(Gdx.input.isKeyPressed(Input.Keys.Y)) {
camera.zoom += 0.1f;
} else if(Gdx.input.isKeyPressed(Input.Keys.H)) {
camera.zoom -= 0.1f;
}
}
@Override
public void render (float delta) {
handleInput();
updateServer(Gdx.graphics.getDeltaTime());
world.step(1/60f, 6, 2);
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
tiledMapRenderer.setView(camera);
tiledMapRenderer.render();
box2DDebugRenderer.render(world, camera.combined);
game.batch.setProjectionMatrix(camera.combined);
game.batch.begin();
if(player != null){
player.update(delta);
player.draw(game.batch);
player.handleInput();
}
if(monster != null) {
monster.update(delta);
monster.draw(game.batch);
monster.chase(player);
}
camera.update();
for(HashMap.Entry<String, FriendlyPlayer> entry : friendlyPlayers.entrySet()){
//entry.getValue().update(delta);/////////////!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
entry.getValue().draw(game.batch);
entry.getValue().setPosition();
usernameFont.draw(game.batch, entry.getValue().username, entry.getValue().bx - 15 / Multiplayer.PPM, entry.getValue().by + 38 / Multiplayer.PPM);
}
for(HashMap.Entry<String, MPMonster> entry : monsters.entrySet()){
entry.getValue().draw(game.batch);
//entry.getValue().update(delta);
}
game.batch.end();
game.batch.setProjectionMatrix(hud.stage.getCamera().combined);
hud.stage.draw();
}
public void connectSocket(){
try {
socket = IO.socket("http://localhost:8080");
socket.connect();
} catch(Exception e){
System.out.println(e);
}
}
public void configSocketEvents(){
socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
@Override
public void call(Object... args) {
Gdx.app.log("SocketIO", "Connected");
player = new Player(playerTex, world, camera);
monster = new Monster(700, 800, 28, 32, monsterTex, world);
}
}).on("socketID", new Emitter.Listener() {
@Override
public void call(Object... args) {
JSONObject data = (JSONObject) args[0];
try {
id = data.getString("id");
Gdx.app.log("SocketIO", "My ID: " + id);
} catch (JSONException e) {
Gdx.app.log("SocketIO", "Error getting ID");
}
}
}).on("newPlayer", new Emitter.Listener() {
@Override
public void call(Object... args) {
JSONObject data = (JSONObject) args[0];
try {
String playerId = data.getString("id");
Gdx.app.log("SocketIO", "New Player Connect: " + id);
friendlyPlayers.put(playerId, new FriendlyPlayer(friendlyPlayerTex, world, game));
}catch(JSONException e){
Gdx.app.log("SocketIO", "Error getting New PlayerID");
}
}
}).on("playerDisconnected", new Emitter.Listener() {
@Override
public void call(Object... args) {
JSONObject data = (JSONObject) args[0];
try {
id = data.getString("id");
friendlyPlayers.remove(id);
}catch(JSONException e){
Gdx.app.log("SocketIO", "Error getting disconnected PlayerID");
}
}
}).on("playerMoved", new Emitter.Listener() {
@Override
public void call(Object... args) {
JSONObject data = (JSONObject) args[0];
try {
//SEND STATE AND BOX2D
String playerId = data.getString("id");
Double x = data.getDouble("x");
Double y = data.getDouble("y");
Double vx = data.getDouble("vx");
Double vy = data.getDouble("vy");
Double bx = data.getDouble("bx");
Double by = data.getDouble("by");
String username = data.getString("username");
if(friendlyPlayers.get(playerId) != null) {
friendlyPlayers.get(playerId).setPosition(x.floatValue(), y.floatValue());
friendlyPlayers.get(playerId).vx = vx.floatValue();
friendlyPlayers.get(playerId).vy = vy.floatValue();
friendlyPlayers.get(playerId).bx = bx.floatValue();
friendlyPlayers.get(playerId).by = by.floatValue();
friendlyPlayers.get(playerId).username = username;
friendlyPlayers.get(playerId).update(Gdx.graphics.getDeltaTime());
}
}catch(JSONException e){
}
}
}).on("getPlayers", new Emitter.Listener() {
@Override
public void call(Object... args) {
JSONArray objects = (JSONArray) args[0];
try {
for(int i = 0; i < objects.length(); i++){
/////GET STATE AND SET TO COOP PLAYER
FriendlyPlayer coopPlayer = new FriendlyPlayer(friendlyPlayerTex, world, game);
Vector2 position = new Vector2();
Float vx, vy;
Float bx, by;
String username;
position.x = ((Double) objects.getJSONObject(i).getDouble("x")).floatValue();
position.y = ((Double) objects.getJSONObject(i).getDouble("y")).floatValue();
vx = ((Double) objects.getJSONObject(i).getDouble("vx")).floatValue();
vy = ((Double) objects.getJSONObject(i).getDouble("vy")).floatValue();
bx = ((Double) objects.getJSONObject(i).getDouble("bx")).floatValue();
by = ((Double) objects.getJSONObject(i).getDouble("by")).floatValue();
username = objects.getJSONObject(i).getString("username");
coopPlayer.setPosition(position.x, position.y);
coopPlayer.vx = vx;
coopPlayer.vy = vy;
coopPlayer.bx = bx;
coopPlayer.by = by;
coopPlayer.username = username;
friendlyPlayers.put(objects.getJSONObject(i).getString("id"), coopPlayer);
coopPlayer.update(Gdx.graphics.getDeltaTime());
}
} catch(JSONException e){
}
}
}).on("newMonster", new Emitter.Listener() {
@Override
public void call(Object... args) {
JSONObject data = (JSONObject) args[0];
try {
String monsterId = data.getString("id");
monsters.put(monsterId, new MPMonster(700, 800, 28, 32, monsterTex, world));
}catch(JSONException e){
Gdx.app.log("SocketIO", "Error creating new monster");
}
}
}).on("monsterMoved", new Emitter.Listener() {
@Override
public void call(Object... args) {
JSONObject data = (JSONObject) args[0];
try {
String playerId = data.getString("pid");
String monsterId = data.getString("id");
Double x = data.getDouble("x");
Double y = data.getDouble("y");
Double vx = data.getDouble("vx");
Double vy = data.getDouble("vy");
Double bx = data.getDouble("bx");
Double by = data.getDouble("by");
if(monsters.get(monsterId) != null) {
monsters.get(monsterId).setPosition(x.floatValue(), y.floatValue());
monsters.get(monsterId).vx = vx.floatValue();
monsters.get(monsterId).vy = vy.floatValue();
monsters.get(monsterId).bx = bx.floatValue();
monsters.get(monsterId).by = by.floatValue();
monsters.get(monsterId).update(Gdx.graphics.getDeltaTime());
}
} catch (JSONException e) {
}
}
}).on("getMonsters", new Emitter.Listener() {
@Override
public void call(Object... args) {
JSONArray objects = (JSONArray) args[0];
try {
for(int i = 0; i < objects.length(); i++){
/////GET STATE AND SET TO COOP PLAYER
MPMonster monster = new MPMonster(700, 800, 28, 32, monsterTex, world);
Vector2 position = new Vector2();
Float vx, vy;
Float bx, by;
position.x = ((Double) objects.getJSONObject(i).getDouble("x")).floatValue();
position.y = ((Double) objects.getJSONObject(i).getDouble("y")).floatValue();
vx = ((Double) objects.getJSONObject(i).getDouble("vx")).floatValue();
vy = ((Double) objects.getJSONObject(i).getDouble("vy")).floatValue();
bx = ((Double) objects.getJSONObject(i).getDouble("bx")).floatValue();
by = ((Double) objects.getJSONObject(i).getDouble("by")).floatValue();
monster.setPosition(position.x, position.y);
monster.vx = vx;
monster.vy = vy;
monster.bx = bx;
monster.by = by;
monsters.put(objects.getJSONObject(i).getString("id"), monster);
//monsters.get(objects.getJSONObject(i).getString("id")).chase(player);
monsters.get(objects.getJSONObject(i).getString("id")).update(Gdx.graphics.getDeltaTime());
//monster.update(Gdx.graphics.getDeltaTime());
}
} catch(JSONException e){
}
}
});
}
@Override
public void show() {
}
@Override
public void resize(int width, int height) {
gamePort.update(width, height);
}
@Override
public void pause() {
}
@Override
public void resume() {
}
@Override
public void hide() {
}
@Override
public void dispose() {
playerTex.dispose();
friendlyPlayerTex.dispose();
}
}
我的怪物代码:
public class Monster extends Sprite {
private float x;
private float y;
private World world;
private Vector2 previousPosition;
public Body body;
private TextureRegion monsterStand;
public Monster(float x, float y, int w, int h, Texture texture, World world) {
super(texture);
this.x = x;
this.y = y;
this.world = world;
monsterStand = new TextureRegion(texture, 0, 0, w, h);
setBounds(700 / Multiplayer.PPM, 800 / Multiplayer.PPM, 28 / Multiplayer.PPM, 32 / Multiplayer.PPM);
monsterPhysics();
setRegion(monsterStand);
previousPosition = new Vector2(getX(), getY());
}
public void update(float dt) {
setPosition(body.getPosition().x - getWidth() / 2, body.getPosition().y - getHeight() / 2);
body.applyLinearImpulse(
(0 - body.getLinearVelocity().x) * body.getMass(),
(0 - body.getLinearVelocity().y) * body.getMass(),
body.getWorldCenter().x, body.getWorldCenter().y, true
);
}
public void chase(Player player) {
float speedX = 0;
float speedY = 0;
if(Funcs.distance(body.getPosition(), player.body.getPosition()) <= 1.3f) {
if(player.body.getPosition().x > body.getPosition().x) {
speedX = 0.5f;
} else if(player.body.getPosition().x < body.getPosition().x) {
speedX = -0.5f;
} else {
speedX = 0f;
}
if(player.body.getPosition().y > body.getPosition().y) {
speedY = 0.5f;
} else if(player.body.getPosition().y < body.getPosition().y) {
speedY = -0.5f;
} else {
speedY = 0f;
}
body.applyLinearImpulse(
(speedX - body.getLinearVelocity().x) * body.getMass(),
(speedY - body.getLinearVelocity().y) * body.getMass(),
body.getWorldCenter().x, body.getWorldCenter().y, true
);
}
}
private void monsterPhysics() {
BodyDef bdef = new BodyDef();
PolygonShape shape = new PolygonShape();
FixtureDef fdef = new FixtureDef();
Rectangle rect = getBoundingRectangle();
bdef.type = BodyDef.BodyType.DynamicBody;
bdef.position.set(700 / Multiplayer.PPM, 800 / Multiplayer.PPM);
body = world.createBody(bdef);
shape.setAsBox(rect.getWidth() / 2, rect.getHeight() / 2);
fdef.shape = shape;
body.createFixture(fdef);
}
public boolean hasMoved(){
if(previousPosition.x != getX() || previousPosition.y != getY()){
previousPosition.x = getX();
previousPosition.y = getY();
return true;
}
return false;
}
}
我也有 MPMonster 类:
public class MPMonster extends Sprite {
private float x;
private float y;
public float vx;
public float vy;
public float bx;
public float by;
private World world;
private Vector2 previousPosition;
public Body body;
private TextureRegion monsterStand;
public MPMonster(float x, float y, int w, int h, Texture texture, World world) {
super(texture);
this.x = x;
this.y = y;
this.world = world;
monsterStand = new TextureRegion(texture, 0, 0, w, h);
setBounds(x / Multiplayer.PPM, y / Multiplayer.PPM, w / Multiplayer.PPM, h / Multiplayer.PPM);
monsterPhysics();
setRegion(monsterStand);
previousPosition = new Vector2(getX(), getY());
}
public void update(float dt) {
//setRegion(getFrame(dt));
setPosition(body.getPosition().x - getWidth() / 2, body.getPosition().y - getHeight() / 2);
body.setTransform(bx, by, 0);
}
public void chase(Player player) {
float speedX = 0;
float speedY = 0;
if(Funcs.distance(body.getPosition(), player.body.getPosition()) <= 1.3f) {
if(player.body.getPosition().x > body.getPosition().x) {
speedX = 0.5f;
} else if(player.body.getPosition().x < body.getPosition().x) {
speedX = -0.5f;
} else {
speedX = 0f;
}
if(player.body.getPosition().y > body.getPosition().y) {
speedY = 0.5f;
} else if(player.body.getPosition().y < body.getPosition().y) {
speedY = -0.5f;
} else {
speedY = 0f;
}
body.applyLinearImpulse(
(speedX - body.getLinearVelocity().x) * body.getMass(),
(speedY - body.getLinearVelocity().y) * body.getMass(),
body.getWorldCenter().x, body.getWorldCenter().y, true
);
}
}
private void monsterPhysics() {
BodyDef bdef = new BodyDef();
PolygonShape shape = new PolygonShape();
FixtureDef fdef = new FixtureDef();
Rectangle rect = getBoundingRectangle();
bdef.type = BodyDef.BodyType.DynamicBody;
bdef.position.set(x / Multiplayer.PPM, y / Multiplayer.PPM);
body = world.createBody(bdef);
shape.setAsBox(rect.getWidth() / 2, rect.getHeight() / 2);
fdef.shape = shape;
body.createFixture(fdef);
}
public boolean hasMoved(){
if(previousPosition.x != getX() || previousPosition.y != getY()){
previousPosition.x = getX();
previousPosition.y = getY();
return true;
}
return false;
}
}
我的服务器代码:
var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var players = [];
var monsters = [];
server.listen(8080, function(){
console.log("Server is now running...");
});
io.on('connection', function(socket){
console.log("Player Connected!");
monsterID = ID();
socket.emit('socketID', { id: socket.id });
socket.emit('getPlayers', players);
socket.emit('getMonsters', monsters);
socket.broadcast.emit('newPlayer', { id: socket.id });
socket.broadcast.emit('newMonster', { id: monsterID });
socket.on('playerMoved', function(data) {
data.id = socket.id;
socket.broadcast.emit('playerMoved', data);
for(var i = 0; i < players.length; i++) {
if(players[i].id == data.id) {
players[i].username = data.username;
players[i].x = data.x;
players[i].y = data.y;
players[i].vx = data.vx;
players[i].vy = data.vy;
players[i].bx = data.bx;
players[i].by = data.by;
}
}
});
socket.on('monsterMoved', function(data) {
data.id = monsterID;
data.pid = socket.id;
socket.broadcast.emit('monsterMoved', data);
for(var i = 0; i < monsters.length; i++) {
if(monsters[i].id == data.id) {
monsters[i].x = data.x;
monsters[i].y = data.y;
monsters[i].vx = data.vx;
monsters[i].vy = data.vy;
monsters[i].bx = data.bx;
monsters[i].by = data.by;
}
}
});
socket.on('disconnect', function(){
console.log("Player Disconnected");
socket.broadcast.emit('playerDisconnected', { id: socket.id });
for(var i = 0; i < players.length; i++){
if(players[i].id == socket.id){
players.splice(i, 1);
}
}
});
players.push(new player(socket.id, "", 900 / 100, 600 / 100, 0, 0, 0, 0));
monsters.push(new monster(monsterID, 700 / 100, 800 / 100, 0, 0, 700 / 100, 800 / 100));
});
function player(id, username, x, y, vx, vy, bx, by){
this.id = id;
this.username = username;
this.x = x;
this.y = y;
this.vx = vx;
this.vy = vy;
this.bx = bx;
this.by = by;
}
function monster(id, x, y, vx, vy, bx, by) {
this.id = id;
this.x = x;
this.y = y;
this.vx = vx;
this.vy = vy;
this.bx = bx;
this.by = by;
}
var ID = function () {
return Math.random().toString().substr(2, 9);
};
解决方案
推荐阅读
- java - Maven 项目编译错误:找不到符号(即 java.lang.String)
- spatial - 如何在 Grakn 中定义多边形?
- javascript - 左右未选中的单选按钮的总和值
- python - 如何使用appium删除带有空格的文件?
- python-3.x - how to install sub modules of keras and tensorflow?
- python - 坚持这个高中编码活动
- css - CSS斜边边框角
- node.js - 将数据从一台设备传输到另一台设备而不将其存储在 nodejs 服务器中
- angular - RxJS 倒数计时器未达到零
- php - 来自 GET 请求的格式错误的 JSON