EDIT - I just read the OP again to make sure I was not posting useless shite and I noticed this:
If you are learning, the last thing you want to do is get caught up in “good practices”, there are things you should be doing but when they start to prevent you from coding you need to reconsider your approach. You should worry less about OOP structure/design and just code, OOP design is not something you really learn by specifically practising it hours on end, it comes from experience and time.
My OOP is still a bit rubbish and I have trouble coming up with a decent structure, but it is 10x better than what it was a year ago. Code, code, code and code some more, look back at it in a few month time and you will see that somehow, by complete magic that your code structure and organization has dramatically improved :p. Looking online at code snippets helps speed this process up.
I might be reading into this wrong but I think you might be over-thinking things.
Bare in mind positioning and moving is all just numbers, all you have to do is change the numbers in order to simulate movement. So all you have to do is move things over-time in a stable loop, you can read more about loops HERE.
So if you have the X and Y coordinates in a variable you can easily change these values, such as:
x += speed * 1f/60f
What this basically does it take the X value, add speed onto it and multiply it by a fixed time step (0.0166ms). In LibGDX the loop is locked to 60 updates per second (60FPS) so this number is roughly right, when you make your own game loop or use LibGDX you can use a “delta” value. Delta is the time that has passed since the last frame. I merely put the fixed 0.0166ms value just for explanation purposes.
Space invaders is a good example for basic movement code, as there are 2 ways of doing it. The invaders jump spot to spot and your laser base/laser/enemy laser all move smoothly.
Here is my invader move code:
/** Move the invader left by 1 unit */
public void moveLeft() {
bounds.x -= speed;
}
/** Move the invader right by 1 unit */
public void moveRight() {
bounds.x += speed;
}
Since here we do not want to move the aliens smoothly, we simply just add the speed onto the current X value which causes them to jump to the next spot on my virtual little grid.
For the laser base we are doing the following:
if (Gdx.input.isKeyPressed(Keys.A) || Gdx.input.isKeyPressed(Keys.LEFT)) {
velocity.set(-speed, 0);
} else if (Gdx.input.isKeyPressed(Keys.D)
|| Gdx.input.isKeyPressed(Keys.RIGHT)) {
velocity.set(speed, 0);
} else {
velocity.set(0, 0);
}
Velocity is a Vector2, as you are familar with. We basically set the velocity of the target to the max speed instantly and then later in the loop we add these values onto the current X and Y coordinate of the laser base, which is also a Vector2. Then multiply by delta to get smooth movement.
/* Apply a velocity to our entity */
bounds.x += velocity.x * delta;
bounds.y += velocity.y * delta;
The same principle can be used for Animation. An animation is basically a collection of still images that are played in sequence using some sort of timing mechanism in order to change the frame appropriately. This can be applied to any code, all of the code I have posted thus far is generic, as long as you have some sort of game loop.
The simplest way to do animation is to store each frame in an array and shift through it has time passes. Like so (I wrote this specially for you <3:
public class AnimatorExample {
// All the textures we want to use, depending on what library you use this
// will be different, e.g BufferedImage
Texture[] keyFrames;
// The actual frame we are on
Texture currentFrame;
// The current frame number we are on
int currentFrameNumber;
// This is the total time the animation has been in the current frame
float stateTime;
// The total time in milliseconds each frame lasts for, you can use seconds, nanoseconds or whatever but delta time usually
// usually works in milliseconds
float frameDuration;
// The total duration of the entire animation, this can be used to check if
// the animation is finished
float animDuration;
/**
* We basically state the animation duration and pass in an array of frames,
* from this data we can setup the rest of the class
*
* @param frameDuration
* @param frames
*/
public AnimatorExample(float frameDuration, Texture... frames) {
frames = new Texture[frames.length];
for (int i = 0; i < frames.length; i++) {
keyFrames[i] = frames[i];
}
currentFrameNumber = 0;
currentFrame = keyFrames[currentFrameNumber];
this.frameDuration = frameDuration;
animDuration = frameDuration * keyFrames.length;
}
/**
* This method is a little specific to LibGDX but you might know what a
* sprite batch is anyway. In Java2D this would be Graphics2D I think, the
* delta time is just the time since the last frame.
* <p>
*
* Usually you want to separate the updating from the drawing code but I put
* it in one place for convenience.
* <p>
* Now all you have to do is call this is a loop (which you have to anyway
* to get it to draw) and pass in the delta time, you can just pass 1f/60f
* if you don't have a loop that calculates delta
*
* @param batch
* @param delta
*/
public void draw(SpriteBatch batch, float delta) {
// Here we increase the state time so we can decide when to switch frame
stateTime += delta;
// Check if the state time is more than the frame duration
if (stateTime > frameDuration) {
// Make sure we stay within the bounds of the array, ideally we use
// a
// method for this but whatever
if (currentFrameNumber != keyFrames.length) {
// Increase the current frame number and set the current frame
// to the correct one
currentFrameNumber++;
currentFrame = keyFrames[currentFrameNumber];
} else {
// The animation is finished, reset it. We can do something
// different here if you want, like stop it, repeat etc. For now
// I just repeat
currentFrameNumber = 0;
currentFrame = keyFrames[currentFrameNumber];
}
stateTime = 0;
}
// Just draw the current frame, same goes for Java2D like graphics.paint(currentFrame), I am rusty with Java2D so
//forgive me :p
batch.draw(currentFrame, 50, 50);
}
}
I hope this has helped clear things up a little, you might just be having trouble realising that all these things are numbers that you change using other numbers
Nothing fancy going on here, even when you simulate real physics and/or use fancy mathematics, the code remains simple but the logic becomes complicate. If that makes sense.
You can see all my Space Invaders code here, take it with a grain of salt though as this project was rushed in a week to gain entry to a Games Development course at college. The code is not bad and it has some good examples but hell, it probably has more bad ones than anything. It got to the point I literally chucked OOP design out the window and started coupling code horribly all over the place.
Source
Official Thread