Оба объекта движутся, а не один в 2-й игре.

Я делаю игровую библиотеку java 2d, используя JSFML в качестве основы.

В последнее время обнаружил большую проблему. Все мои объекты в игре расширяют абстрактный класс GameObject, который содержит такие вещи, как положение, скорость, размер и имя объекта.

Все загруженные объекты хранятся в Game экземпляр класса, который обрабатывает игру.

Теперь проблема в том, что каждый раз, когда игрок движется, все вместе с ним движется.

Например, если я перемещаю игрока с помощью клавиш w, a, s, d, он перемещает не только игрока, но и пол.

Вот код с точки зрения пользователя:

      public static void main(String[] args) {
    GameSettings settings = new GameSettings("Testing window!", 800, 600);
    Game game = Game.Create(settings);

    GameObject floor = game.LoadObject(new Floor("Floor", new Vector2(400 - 500, 500), new Vector2(500, 16)));
    GameObject player = game.LoadObject(new Player("Player", new Vector2(400 - 16, 300 - 16), new Vector2(32, 32)));

    game.Start();
}

Вот классы игроков и этажей:

      public class Player extends GameObject {

    public float speed = 7.5f;

    public Player(String name, Vector2 position, Vector2 size) {
        super(name, position, size);
    }

    @Override
    public void Start() {
        this.canGoOutsideOfWindow = false;
        this.allowCollision = true;
        this.allowGravity = true;
    }

    @Override
    public void TickUpdate() {
        if (GameInput.IsKeyPressed(Keyboard.Key.D)) {
            this.velocity.x = speed;
        }
        if (GameInput.IsKeyPressed(Keyboard.Key.A)) {
            this.velocity.x = -speed;
        }
        if (GameInput.IsKeyPressed(Keyboard.Key.W)) {
            this.velocity.y = -speed;
        }
        if (GameInput.IsKeyPressed(Keyboard.Key.S)) {
            this.velocity.y = speed;
        }
    }
}
      public class Floor extends GameObject {
    public Floor(String name, Vector2 position, Vector2 size) {
        super(name, position, size);
    }

    @Override
    public void Start() {
        allowCollision = true;
        allowFriction = false;
        canGoOutsideOfWindow = false;
    }
}

Вот класс игры:

      public class Game {

    // Instance variable for game class, because i don't want more instances of it, only one.
    private static Game i;

    // Variable to store game configuration
    private GameSettings settings;

    // Just some private variables, I don't know.
    private boolean started = false;
    private int framesPerSecond;
    private ArrayList<GameObject> objects = new ArrayList<GameObject>();

    // Constructor for creating game only private.
    private Game(GameSettings settings) {
        GameOutput.SendInfo("Creating game instance with settings " + settings + "...");

        this.settings = settings;

        GameOutput.SendInfo("Game instance created!");
    }

    // Beginning of string of methods after start.
    public void Start() {

        if (!started) {
            GameOutput.SendInfo("Starting the game...");

            for (GameObject o : objects)
                o.Start();

            GameOutput.SendInfo("Game started, and running...");
            InitWindow();
        } else {
            GameOutput.SendError("Your code is trying to start the game, but game is already started!");
        }
    }

    // Beginning of string of methods before stopping
    public void Stop() {
        if (GameWindow.Get().isOpen()) {
            GameOutput.SendInfo("Stopping game...");

            for (GameObject o : objects)
                o.Stop();

            GameWindow.Get().close();

            GameOutput.SendInfo("Game closed!");
            System.exit(69);
        } else {
            GameOutput.SendError("Your code is trying to stop the game, but game is already closed!");
        }
    }

    // Beginning of string of methods after frame update.
    private void FrameUpdate() {
        GameWindow w = GameWindow.Get();

        for (Event e : w.pollEvents()) {
            if (e.type == Event.Type.CLOSED) {
                Stop();
            }
        }
        CheckForInputs();

        for (GameObject o : objects)
            o.FrameUpdate();
    }

    // Just method for checking inputs every frame.
    private void CheckForInputs() {
        GameWindow w = GameWindow.Get();

        if (GameInput.IsKeyPressed(Keyboard.Key.ESCAPE))
            Stop();

        for (Event e : w.pollEvents()) {
            if (e.type == Event.Type.KEY_PRESSED) {
                for (GameObject o : objects)
                    o.KeyPressed(e.asKeyEvent());
            }
            if (e.type == Event.Type.KEY_RELEASED) {
                for (GameObject o : objects)
                    o.KeyReleased(e.asKeyEvent());
            }
        }
    }

    // Beginning of string of methods after frame render.
    private void FrameRender() {
        GameWindow w = GameWindow.Get();
        w.clear(new Color(30, 30, 30, 255));

        for (GameObject o : objects) {
            if (!o.canGoOutsideOfWindow)
                o.position = new Vector2(GameMath.Clamp(o.position.x, 0, GameWindow.Get().getSize().x - o.size.x), GameMath.Clamp(o.position.y, 0, GameWindow.Get().getSize().y - o.size.y));
            RectangleShape r = new RectangleShape();
            r.setSize(new Vector2f(o.size.x, o.size.y));
            r.setPosition(o.position.x, o.position.y);
            r.setFillColor(Color.WHITE);
            GameWindow.Get().draw(r);

            o.FrameRender();
        }

        w.display();
    }

    // Beginning of string of methods after tick update.
    private void TickUpdate() {
        for (GameObject o : objects) {
            Vector2 nextPosition = new Vector2(o.position.x + o.velocity.x, o.position.y + o.velocity.y);
            o.position = nextPosition;

            if (o.allowFriction) {
                if (o.velocity.x >= o.frictionAmount)
                    o.velocity.x -= o.frictionAmount;
                else if (o.velocity.x < o.frictionAmount && o.velocity.x > -o.frictionAmount)
                    o.velocity.x = 0;
                if (o.velocity.y >= o.frictionAmount)
                    o.velocity.y -= o.frictionAmount;
                else if (o.velocity.y < o.frictionAmount && o.velocity.y > -o.frictionAmount)
                    o.velocity.y = 0;

                if (o.velocity.x <= -o.frictionAmount)
                    o.velocity.x += o.frictionAmount;
                else if (o.velocity.x > o.frictionAmount && o.velocity.x < o.frictionAmount)
                    o.velocity.x = 0;
                if (o.velocity.y <= -o.frictionAmount)
                    o.velocity.y += o.frictionAmount;
                else if (o.velocity.y > o.frictionAmount && o.velocity.y < o.frictionAmount)
                    o.velocity.y = 0;
            }

            o.TickUpdate();
        }
    }

    // Starting the game window.
    private void InitWindow() {
        GameOutput.SendInfo("Initializing window...");

        GameWindow w = GameWindow.Create();
        w.create(new VideoMode(settings.windowWidth, settings.windowHeight), settings.windowTitle);
        GameOutput.SendInfo("Window initilized!");

        InitLoop();
    }

    // Starting game loop.
    private void InitLoop() {
        GameOutput.SendInfo("Initializing game loop...");

        long lastTime = System.nanoTime();
        double amountOfTicks = settings.ticksPerSecond;
        double ns = 1000000000 / amountOfTicks;
        double delta = 0;
        long timer = System.currentTimeMillis();
        int frames = 0;

        GameOutput.SendInfo("Game loop initialized!");

        while (GameWindow.Get().isOpen()) {
            long now = System.nanoTime();
            delta += (now - lastTime) / ns;
            lastTime = now;
            while (delta >= 1) {
                TickUpdate();
                delta--;
            }
            if (GameWindow.Get().isOpen()) {
                GameTime.deltaTime = (float) delta;
                FrameRender();
                FrameUpdate();
            }
            frames++;
            if (System.currentTimeMillis() - timer > 1000) {
                timer += 1000;
                framesPerSecond = frames;
                frames = 0;
            }
        }
            }

    // Only method for loading objects to game.
    public GameObject LoadObject(GameObject object) {
        GameOutput.SendInfo("Loading object " + object + " to the game...");

        objects.add(object);
        object.active = true;

        GameOutput.SendInfo("Loaded object " + object + " to the game!");
        return object;
    }

    // Only method for getting loaded object from game.
    public GameObject GetLoadedObject(String name) {
        GameObject result = null;

        for (GameObject o : objects)
            if (o.name.equalsIgnoreCase(name))
                result = o;

        return result;
    }

    // Public method for getting object list.
    public List<GameObject> GetLoadedObjects() {
        return objects;
    }

    // Only method for unloading objects to game.
    public void UnLoadObject(GameObject object) {
        GameOutput.SendInfo("UnLoading object " + object + " from the game...");

        objects.remove(object);
        object.active = false;

        GameOutput.SendInfo("UnLoaded object " + object + " from the game!");
    }

    // Publicly only method for creating instance if not created.
    public static Game Create(GameSettings settings) {
        if (i == null)
            i = new Game(settings);
        return i;
    }

    // Publicly only method for getting instance.
    public static Game Get() {
        return i;
    }
}

Весь код находится на GitHub, если вам нужна дополнительная информация: https://github.com/FilipeeX/GamerLibrary

Вот что я уже пробовал:

  • Я попытался проверить рендеринг фрагмента кода, но все в порядке.
  • Я также удалил половину библиотеки, чтобы максимально упростить работу, но даже если это просто, все должно работать нормально, но все равно ... ничего.

На этом я полностью застрял, я не знаю, что делать.

1 ответ

Решение

Когда вы создаете экземпляры GameObject, вы инициализируете все поля скорости статическим общедоступным полем Vector2.zero. Таким образом, каждый экземпляр GameObject будет иметь поле скорости, которое ссылается на один и тот же статический объект (например, Vector2.zero).

Таким образом, любое изменение скорости одного экземпляра одинаково повлияет на скорость каждого другого экземпляра GameObject.

Другие вопросы по тегам