I'm making java 2d game library, using JSFML as base.
Lately I found a big problem.
All of my objects in game, are extending abstract class GameObject
, that contains stuff like position, velocity, size and name of object.
All loaded objects are stored in Game
class instance, that handlers the game.
Now the problem is: Every time player moves, everything with it moves too.
For example, if I move player with w, a, s, d keys, it won't move only player, but the floor moves too.
Here's code from user's perspective:
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();
}
Here are player and floor 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;
}
}
Here's the game 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;
}
}
Entire code is on GitHub if you need more information: https://github.com/FilipeeX/GamerLibrary
Here's what I already tried:
- I tried checking rendering piece of code, but there's nothing wrong.
- I also removed half a library just to simplify things as much as possible, but even if it's simple, everything should be working normally, still.. nothing.
At this point, I'm completely stuck I don't know what to do.