我如何添加一些多人游戏代码(对于java)来做一些简单的事情,例如更新客户端'位置

时间:2017-05-30 03:25:34

标签: java lwjgl multiplayer

如何在YouTube上使用ThinMatrix教程创建的多人游戏中添加一些代码?我一直在关注他的教程,当时我决定去......好吧......在切线上并开始在我的游戏中添加自己的东西。有人可以用一些代码来帮助我更新游戏中玩家实体的位置吗?我已经知道如何做(基本)网络。

谢谢!

编辑:从评论添加的代码

相机类:

package entities;

import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.util.vector.Vector3f;

public class Camera {

    private float distanceFromPlayer = 35;
    private float angleAroundPlayer = 0;

    private Vector3f position = new Vector3f(0, 0, 0);
    private float pitch = 20;
    private float yaw = 0;
    private float roll;

    private Player player;

    public Camera(Player player){
        this.player = player;
    }

    public void move(){
        calculateZoom();
        calculatePitch();
        calculateAngleAroundPlayer();
        float horizontalDistance = calculateHorizontalDistance();
        float verticalDistance = calculateVerticalDistance();
        calculateCameraPosition(horizontalDistance, verticalDistance);
        this.yaw = 180 - (player.getRotY() + angleAroundPlayer);
    }

    public Vector3f getPosition() {
        return position;
    }

    public float getPitch() {
        return pitch;
    }

    public float getYaw() {
        return yaw;
    }

    public float getRoll() {
        return roll;
    }

    private void calculateCameraPosition(float horizDistance, float verticDistance){
        float theta = player.getRotY() + angleAroundPlayer;
        float offsetX = (float) (horizDistance * Math.sin(Math.toRadians(theta)));
        float offsetZ = (float) (horizDistance * Math.cos(Math.toRadians(theta)));
        position.x = player.getPosition().x - offsetX;
        position.z = player.getPosition().z - offsetZ;
        position.y = player.getPosition().y + verticDistance + 4;
    }

    private float calculateHorizontalDistance(){
        return (float) (distanceFromPlayer * Math.cos(Math.toRadians(pitch+4)));
    }

    private float calculateVerticalDistance(){
        return (float) (distanceFromPlayer * Math.sin(Math.toRadians(pitch+4)));
    }

    private void calculateZoom(){
        float zoomLevel = Mouse.getDWheel() * 0.03f;
        distanceFromPlayer -= zoomLevel;
        if(distanceFromPlayer<5){
            distanceFromPlayer = 5;
        }
    }

    private void calculatePitch(){
        if(Mouse.isButtonDown(1)){
            float pitchChange = Mouse.getDY() * 0.2f;
            pitch -= pitchChange;
            if(pitch < 0){
                pitch = 0;
            }else if(pitch > 90){
                pitch = 90;
            }
        }
    }

    private void calculateAngleAroundPlayer(){
        if(Mouse.isButtonDown(0)){
            float angleChange = Mouse.getDX() * 0.3f;
            angleAroundPlayer -= angleChange;
        }
    }




}

玩家等级:

package entities;

import models.TexturedModel;

import org.lwjgl.input.Keyboard;
import org.lwjgl.util.vector.Vector3f;

import renderEngine.DisplayManager;
import terrains.Terrain;

public class Player extends Entity {

    private static final float RUN_SPEED = 40;
    private static final float TURN_SPEED = 160;
    private static final float GRAVITY = -50;
    private static final float JUMP_POWER = 18;

    private float currentSpeed = 0;
    private float currentTurnSpeed = 0;
    private float upwardsSpeed = 0;

    private boolean isInAir = false;

    public Player(TexturedModel model, Vector3f position, float rotX, float rotY, float rotZ,
            float scale) {
        super(model, position, rotX, rotY, rotZ, scale);
    }

    public void move(Terrain terrain) {
        checkInputs();
        super.increaseRotation(0, currentTurnSpeed * DisplayManager.getFrameTimeSeconds(), 0);
        float distance = currentSpeed * DisplayManager.getFrameTimeSeconds();
        float dx = (float) (distance * Math.sin(Math.toRadians(super.getRotY())));
        float dz = (float) (distance * Math.cos(Math.toRadians(super.getRotY())));
        super.increasePosition(dx, 0, dz);
        upwardsSpeed += GRAVITY * DisplayManager.getFrameTimeSeconds();
        super.increasePosition(0, upwardsSpeed * DisplayManager.getFrameTimeSeconds(), 0);
        float terrainHeight = terrain.getHeightOfTerrain(getPosition().x, getPosition().z);
        if (super.getPosition().y < terrainHeight) {
            upwardsSpeed = 0;
            isInAir = false;
            super.getPosition().y = terrainHeight;
        }
    }

    private void jump() {
        if (!isInAir) {
            this.upwardsSpeed = JUMP_POWER;
            isInAir = true;
        }
    }

    private void checkInputs() {
        if (Keyboard.isKeyDown(Keyboard.KEY_W)) {
            this.currentSpeed = RUN_SPEED;
        } else if (Keyboard.isKeyDown(Keyboard.KEY_S)) {
            this.currentSpeed = -RUN_SPEED;
        } else {
            this.currentSpeed = 0;
        }

        if (Keyboard.isKeyDown(Keyboard.KEY_D)) {
            this.currentTurnSpeed = -TURN_SPEED;
        } else if (Keyboard.isKeyDown(Keyboard.KEY_A)) {
            this.currentTurnSpeed = TURN_SPEED;
        } else {
            this.currentTurnSpeed = 0;
        }

        if (Keyboard.isKeyDown(Keyboard.KEY_SPACE)) {
            jump();
        }
    }

}

2 个答案:

答案 0 :(得分:0)

您想要实现的任务很简单,但由于您的代码编写方式,它已成为一项不必要的艰巨任务。如果不了解有关面向对象的代码和高效网络的更多信息,修复代码并不是您准备好的。

所以在这一点上我不会尝试修复你的代码,但我会建议一种方法让它有点工作,并且要知道如果你继续这个项目你将会遇到很多问题。

首先,我们需要一种简单的方法来处理更新Player实体的位置。我们可以通过向您的Player类添加一个方法来实现这一点:

public void moveByFloatInput(fload newX, float newY, float newY) {
    //Here you need to get the current terrain object for this player entity
    Terrain currentTerrain = getTerrain();
    //Now update the terrain object with your new x,y,z points (not sure what methods Terrain contains, you may need to make changes or expose more variables)
    currentTerrain.setNewPosition(newX, newY, newZ);
    //Now call the normal move method using the updated terrain with a new position
    move(updatedTerrainObject);
}

注意:可能有更好的方法可以做到这一点,但我不知道如何构造terrain类,以及可以调用哪些方法。另请注意,您需要传递玩家正在查看的方向,但为了保持此示例简单,我没有包含任何内容。

现在,当我们从客户端/服务器收到xy和z信息时,我们可以更新播放器实体,例如,如果您使用的是InputStreamReader(不是最好的主意,但它会帮助您入门):

float x;
float y;
float z;
while ((message = myBufferedReaderInputFromSocket.readLine()) != null) {
    if (message != null) {
        //check if X
        if (message.startsWith("moveX"))
            //save new X so we can update a player entity
            x = Float.parseFloat(message.substring(5));
        //check if Y
        if (message.startsWith("moveY"))
            //save new Y so we can update a player entity
            y = Float.parseFloat(message.substring(5));
        //check if Z
        if (message.startsWith("moveZ"))
            //save new Z so we can update a player entity
            z = Float.parseFloat(message.substring(5));
    }
    //when x, y and y all have a new position we can update a player entity
    if(x != null && y != null && z != null)
    {
        //call our new player move method and change that player entities position
        playerEntityForThisSocket.moveByFloatInput(x, y, z);
        //reset x,y,z to null so that the server can receive the next movement
        x = null;
        y = null;
        z = null;
    }
}

然后通过套接字发送你可以这样做:

//you could create a Print writer for your socket:
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
//then simply send a players new position info
//inculde the "moveX" keyword before the Float x,y,z so that the server/client at the other end knows how to process the info:
out.println(moveX + newXposition);
out.println(moveY + newYposition);
out.println(moveZ + newZposition);

如果这没有意义,那么我建议你在继续编码之前完成基本的Java教程,因为教程包含了使用Java编写的基本构建块,并且有了这些知识,你可以在项目,但没有这些知识,你注定永远不会结束问题: http://docs.oracle.com/javase/tutorial/index.html

答案 1 :(得分:0)

你需要做到这一点,这样你的玩家类可以返回当前的位置,这样做可以让事情变得简单,因为您需要做的就是用新包创建另一个游戏实例并运行它但是在服务器端你需要发送玩家当前位置并使此更新一致,因为这将使用坐标系,但这是非常基本的,所以你已经需要游戏中的实体,如游戏服务器端的玩家实体,这样做你需要这个实体更新它的位置,这样你就可以做类似于player.getPosition()的事情,然后是serverSideModel = player.getPosition(),因为它会将两个模型设置为相同的位置,如果这样做的话