Ryan Ryan - 5 months ago 9
Java Question

What's an efficient way to store enemies, positions, and what's on screen

I'm making a game, where you dodge different enemies. Right now, I do have a way to create enemies, but it obviously isn't done right and isn't efficient. Any recommendations? Maybe a separate class? I want to make it so whenever I render, enemies move just a tad, but in my current case they're not stored so obviously they blink. Thank you!

package local.ryan.bufferstrategy;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferStrategy;
import java.util.Random;

public class Game implements Runnable, KeyListener{

static Frame frame;
static Game game;
public boolean running = false;
Thread graphicsThread;
BufferStrategy bs;
Rectangle enemy;
Random r;


private int charX = 20, charY = 70;

public static void main(String[] args) {

frame = new Frame();
game = new Game();

}

public Game() {

frame.addKeyListener(this);
frame.setFocusable(true);

// establish buffer-strategy out of 'running' loop, to prevent flickering.
// doesnt have to grab graphics constantly.
frame.createBufferStrategy(2);
bs = frame.getBufferStrategy();

// main methods
graphicsThread = new Thread(this);
graphicsThread.start();

}

public void run() {

start();

while(running) {

long lastLoopTime = System.currentTimeMillis();

try {
// prevents faster machines from speeding up
// 1000 (mili-seconds to a second) / 25 frames per second = delay. Will be reduced since rendering methods.
Thread.sleep(1000 / 25);
} catch (InterruptedException e) {
e.printStackTrace();
}

long delta = System.currentTimeMillis() - lastLoopTime;
lastLoopTime = System.currentTimeMillis();

// System.out.println("FPS: " + delta + ".");
render(bs.getDrawGraphics(), (int) delta);

}

}

public void render(Graphics g, int FPS) {

// remember do things in order, for things to show. :)

g.clearRect(0, 0, frame.WIDTH * frame.SCALE, frame.HEIGHT * frame.SCALE);

// print background
g.setColor(Color.black);
g.fillRect(0, 0, frame.WIDTH * frame.SCALE, frame.HEIGHT * frame.SCALE);

// print character
g.setColor(Color.cyan.brighter());
g.fillOval(charX, charY, 20, 20);

// print fps
g.setColor(Color.white);

Font font = g.getFont().deriveFont( 15.0f );
g.setFont(font);
g.drawString("FPS: " + FPS + ".", 20, 50);

g.fillRect(createEnemy().x, createEnemy().y, createEnemy().width, createEnemy().height);

g.dispose();
frame.getBufferStrategy().show();

}

public synchronized void start() {

if(running)
return;

running = true;
}

public synchronized void stop() {

if(!running)
return;

running = false;

}

public Rectangle createEnemy() {

enemy = new Rectangle();
enemy.height = 30;
enemy.width = 30;
enemy.x = frame.WIDTH * frame.SCALE - 200;
r = new Random();
int starty = r.nextInt(frame.HEIGHT * frame.SCALE) + 1;
enemy.y = starty;

return enemy;

}

public void keyPressed(KeyEvent e) {

if(e.getKeyCode() == e.VK_A) {

charX -= 5;

}

if(e.getKeyCode() == e.VK_D) {

charX += 5;

}

if(e.getKeyCode() == e.VK_W) {

charY -= 5;

}

if(e.getKeyCode() == e.VK_S) {

charY += 5;

}

}


public void keyReleased(KeyEvent arg0) {


}


public void keyTyped(KeyEvent arg0) {


}


}

Answer

I would definitely be making a GameObject class that would be the base of your player and enemies.

For a simple game you can just make instances of your enemies and push them into a List<GameObject> or, better yet, create a Drawable interface which implements a draw(Graphics g) method. That way you can have a structure of all the drawables and when you render the screen you simply iterate the list and call drawable.draw(g); on each. That method would draw the rectangle or whatever shape is representing the game object.

As far as tracking a location, you can make your own Location class with an x and y value or opt for a Java implementation such as Point2D.Double. You'd then have an instance of the point in your game object class.