Оба объекта движутся, а не один в 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.