两个物体都在移动,而不是 2d 游戏中的一个
Both objects are moving instead of just one in 2d game
我正在制作 java 二维游戏库,使用 JSFML 作为基础。
最近发现一个大问题。
我在游戏中的所有对象都在扩展抽象 class GameObject
,其中包含对象的位置、速度、大小和名称等内容。
所有加载的对象都存储在 Game
class 实例中,该实例处理游戏。
现在的问题是:每当玩家移动时,它所带的所有东西也会移动。
例如,如果我用 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();
}
这是球员和地板 classes:
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;
}
}
这是游戏 class:
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
这是我已经尝试过的方法:
- 我尝试检查渲染代码段,但没有任何问题。
- 我也删除了半个库只是为了尽可能地简化事情,但即使它很简单,一切都应该正常工作,仍然..没有。
至此,我完全陷入了困境,我不知道该怎么办。
当您构造 GameObject 实例时,您会将所有速度场初始化为静态 public 场,Vector2.zero。因此,GameObject 的每个实例都将有一个引用相同静态对象的速度场(即 Vector2.zero)。
因此,对一个实例速度的任何更改都会以相同的方式影响所有其他 GameObject 实例的速度。
我正在制作 java 二维游戏库,使用 JSFML 作为基础。
最近发现一个大问题。
我在游戏中的所有对象都在扩展抽象 class GameObject
,其中包含对象的位置、速度、大小和名称等内容。
所有加载的对象都存储在 Game
class 实例中,该实例处理游戏。
现在的问题是:每当玩家移动时,它所带的所有东西也会移动。
例如,如果我用 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();
}
这是球员和地板 classes:
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;
}
}
这是游戏 class:
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
这是我已经尝试过的方法:
- 我尝试检查渲染代码段,但没有任何问题。
- 我也删除了半个库只是为了尽可能地简化事情,但即使它很简单,一切都应该正常工作,仍然..没有。
至此,我完全陷入了困境,我不知道该怎么办。
当您构造 GameObject 实例时,您会将所有速度场初始化为静态 public 场,Vector2.zero。因此,GameObject 的每个实例都将有一个引用相同静态对象的速度场(即 Vector2.zero)。
因此,对一个实例速度的任何更改都会以相同的方式影响所有其他 GameObject 实例的速度。