diff --git a/src/main/java/core/general/LayerManager.java b/src/main/java/core/general/LayerManager.java new file mode 100644 index 0000000..500f1d7 --- /dev/null +++ b/src/main/java/core/general/LayerManager.java @@ -0,0 +1,88 @@ +package core.general; + +import core.renderer.Drawable; + +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + +/** + * The {@code LayerManager} works with multiple render layers that contain the Renderers + */ +public class LayerManager { + + /** + * A {@code List} of the {@code Lists} which are the layers + */ + private final List> layers; + + /** + * The buffer of newly added Renderers + */ + private final List buffer = new ArrayList<>(); + + /** + * Create a new {@code LayerManager} + */ + public LayerManager() { + layers = new ArrayList<>(); + } + + /** + * Draw all {@code Renderers} + * @param g2d + */ + public void drawAll(Graphics2D g2d){ + layers.forEach(e -> e.forEach(f -> f.draw(g2d))); + } + + /** + * Add a new {@code Renderer} to the buffer + * @param d + */ + public void addToRendererBuffer(Drawable d){ + buffer.add(d); + } + + /** + * Add a new {@code Renderer} to the render layers. Should only be called between renderings. + * Creates new render layers if the requested layer doesn't exist + * @param d The Renderer + */ + private void addRenderer(Drawable d) { + + int layer = d.getLayer(); + + if (layer < 0) { + throw new IllegalArgumentException("Layer must be at least 0"); + } + + //layer exists check + int layerDif = layer - (layers.size() - 1); + if (layerDif > 0) { + for (int i = 0; i < layerDif; i++) { + layers.add(new ArrayList<>()); + } + } + + layers.get(layer).add(d); + } + + /** + * Remove a {@code Renderer} from the render layers. + *

If the object should only temporarily be invisible, change its {@code isVisible} field

+ * @param d The {@code Renderer} + * @return {@code true} if the element exists in its layer + */ + public boolean removeRenderer(Drawable d) { + return layers.get(d.getLayer()).remove(d); + } + + /** + * Flushes the buffer to the render layers + */ + public void flush(){ + buffer.forEach(this::addRenderer); + buffer.clear(); + } +} diff --git a/src/main/java/core/general/Main.java b/src/main/java/core/general/Main.java index 80ff629..bd09c21 100644 --- a/src/main/java/core/general/Main.java +++ b/src/main/java/core/general/Main.java @@ -25,7 +25,7 @@ class Main extends JFrame { private void initUI() { master = new Master(); - add(master); + add(master.getRenderEngine()); Init.init(); diff --git a/src/main/java/core/general/Master.java b/src/main/java/core/general/Master.java index 4467245..9d22ca6 100644 --- a/src/main/java/core/general/Master.java +++ b/src/main/java/core/general/Master.java @@ -5,7 +5,6 @@ import core.objects.core.CollGameObject; import core.physics.Collidable; import core.physics.Collision; import core.objects.base.DebugPos; -import core.physics.hitboxes.Hitbox; import core.objects.core.GameObject; import core.renderer.Drawable; import objects.Init; @@ -13,11 +12,12 @@ import objects.Init; import javax.swing.*; import java.awt.*; import java.util.ArrayList; +import java.util.List; /** * The main object that controls everything */ -public class Master extends JPanel { +public class Master { /** * The ratio of height to width. @@ -37,35 +37,29 @@ public class Master extends JPanel { /** * All GameObjects that exist */ - private final ArrayList objects; - - /** - * All GameObjects that can be drawn - * Has different render layers, 0 is on the bottom - */ - private final ArrayList> drawables; + private final List objects; /** * All physics objects that exist */ - private final ArrayList collidables; + private final List collidables; /** * Stores all GameObjects that were created during a frame */ - private final ArrayList objectBuffer; + private final List objectBuffer; /** * All physics objects that exist */ - private final ArrayList collidablesBuffer; - + private final List collidablesBuffer; /** - * The current width and height of the game area + * The {@code RenderEngine} that handles everything about rendering */ - private int w, h; + private final RenderEngine renderEngine = new RenderEngine(); + /** * Create a new master object @@ -77,41 +71,12 @@ public class Master extends JPanel { objectBuffer = new ArrayList<>(); collidables = new ArrayList<>(); collidablesBuffer = new ArrayList<>(); - drawables = new ArrayList<>(); - drawables.add(new ArrayList<>()); } public static Master getMaster() { return master; } - /** - * The mein drawing method, handles everything about drawing - * - * @param g - */ - @Deprecated - private void doDrawing(Graphics g) { - - if (getWidth() * 9 > getHeight() * 16) { - h = getHeight(); - w = h / 9 * 16; - } else { - w = getWidth(); - h = w / 16 * 9; - } - - Graphics2D g2d = (Graphics2D) g.create(); - - drawables.forEach(l -> l.forEach(o -> o.draw(g2d))); - } - - - @Override - public void paintComponent(Graphics g) { - super.paintComponent(g); - doDrawing(g); - } /** * Debug a position, creates a green dot at the position @@ -128,7 +93,7 @@ public class Master extends JPanel { * @param pos The position */ private void debugPosObj(Vector2D pos, long lifeTime) { - create(new DebugPos(pos, new Vector2D(2, 2), lifeTime), 3); + create(new DebugPos(pos, new Vector2D(2, 2), lifeTime)); } /** @@ -155,7 +120,8 @@ public class Master extends JPanel { objects.forEach(GameObject::startUpdate); long time2 = System.currentTimeMillis(); Input.frameReset(); - repaint(); + renderEngine.flush(); + renderEngine.repaint(); System.out.println("Frame took " + (System.currentTimeMillis() - time) + "ms, " + (time2 - time) + "ms for update, " + (System.currentTimeMillis() - time2) + "ms for draw"); } @@ -166,7 +132,7 @@ public class Master extends JPanel { */ public Point getMouseLocation() { Point p = MouseInfo.getPointerInfo().getLocation(); - SwingUtilities.convertPointFromScreen(p, this); + SwingUtilities.convertPointFromScreen(p, renderEngine); return p; } @@ -174,49 +140,25 @@ public class Master extends JPanel { /** * This method has to be called for every newly created GameObject * - * @param obj The new object + * @param obj The new object */ public T create(T obj) { - create(obj, obj.getLayer()); - return obj; - } - - /** - * This method has to be called for every newly created GameObject - * - * @param obj The new object - * @param renderLayer The render layer the object will be put on, 0 is below everything - */ - public void create(GameObject obj, int renderLayer) { objectBuffer.add(obj); if (obj instanceof CollGameObject) { collidablesBuffer.add((Collidable) obj); } - addDrawable(obj, renderLayer); + renderEngine.addRenderer(obj); + return obj; } /** * Add a new Drawable to the render list * * @param d The drawable - * @param layer The layer it should be put on (>=0) */ - public void addDrawable(Drawable d, int layer) { - - if (layer < 0) { - - throw new IllegalArgumentException("Layer must be at least 9"); - } - - //layer exists check - int layerDif = layer - (drawables.size() - 1); - if (layerDif > 0) { - for (int i = 0; i < layerDif; i++) { - drawables.add(new ArrayList<>()); - } - } - - drawables.get(layer).add(d); + @Deprecated + public void addDrawable(Drawable d) { + renderEngine.addRenderer(d); } @@ -251,25 +193,29 @@ public class Master extends JPanel { } public int getW() { - return w; + return renderEngine.getW(); } public int getH() { - return h; + return renderEngine.getH(); } public void destroy(GameObject gameObject) { objectBuffer.remove(gameObject); gameObject.getParent().removeChild(gameObject); - drawables.get(gameObject.getLayer()).remove(gameObject); + renderEngine.removeRenderer(gameObject); if (gameObject instanceof Collidable) { collidablesBuffer.remove(gameObject); if (Init.DEBUG_MODE) { - drawables.get(Hitbox.HITBOX_RENDER_LAYER).remove(((CollGameObject) gameObject).getHitbox()); + renderEngine.removeRenderer(((CollGameObject) gameObject).getHitbox()); } } } + + public RenderEngine getRenderEngine() { + return renderEngine; + } } \ No newline at end of file diff --git a/src/main/java/core/general/RenderEngine.java b/src/main/java/core/general/RenderEngine.java new file mode 100644 index 0000000..1bff344 --- /dev/null +++ b/src/main/java/core/general/RenderEngine.java @@ -0,0 +1,103 @@ +package core.general; + +import core.renderer.Drawable; + +import javax.swing.*; +import java.awt.*; + +/** + * The {@code RenderEngine} handles the rendering of all {@code Renderers} + * c

The {@code RenderEngine} extends JPanel and can be integrated into a JFrame. It gets the drawcall from resizing/moving the JPanel + * or from the {@code Master}

+ */ +public class RenderEngine extends JPanel { + + /** + * The current width and height of the game area + */ + private int w, h; + + /** + * The {@code LayerManager} for the render layers + */ + private final LayerManager layerManager; + + /** + * Construct a new {@code RenderEngine} + */ + public RenderEngine() { + layerManager = new LayerManager(); + } + + /** + * The mein drawing method, handles everything about drawing + * + * @param g The {@code Graphics} object + */ + private void doDrawing(Graphics g) { + + if (getWidth() * 9 > getHeight() * 16) { + h = getHeight(); + w = h / 9 * 16; + } else { + w = getWidth(); + h = w / 16 * 9; + } + + Graphics2D g2d = (Graphics2D) g.create(); + + layerManager.drawAll(g2d); + } + + + /** + * The paintComponent method is called from Swing. + * @param g + */ + @Override + public void paintComponent(Graphics g) { + super.paintComponent(g); + doDrawing(g); + } + + /** + * Add a {@code Renderer} to the scene. Gets added to the buffer + * @param d The {@code Renderer} + */ + public void addRenderer(Drawable d){ + layerManager.addToRendererBuffer(d); + } + + /** + * Remove a {@code Renderer} from the engine because it won't be needed anymore. + *

If the object should only temporarily be invisible, change its {@code isVisible} field

+ * @param d + * @return + */ + public boolean removeRenderer(Drawable d){ + return layerManager.removeRenderer(d); + } + + /** + * Get the true width of the current screen + * @return The width in Java2D coordinates + */ + public int getW() { + return w; + } + + /** + * Get the true height of the current screen + * @return The height in Java2D coordinates + */ + public int getH() { + return h; + } + + /** + * Flush the buffer + */ + public void flush() { + layerManager.flush(); + } +} diff --git a/src/main/java/core/physics/hitboxes/Hitbox.java b/src/main/java/core/physics/hitboxes/Hitbox.java index 4f8a1f4..284b7af 100644 --- a/src/main/java/core/physics/hitboxes/Hitbox.java +++ b/src/main/java/core/physics/hitboxes/Hitbox.java @@ -24,4 +24,9 @@ public abstract class Hitbox implements Drawable { public String toString() { return super.toString(); } + + @Override + public int getLayer() { + return HITBOX_RENDER_LAYER; + } } diff --git a/src/main/java/core/physics/hitboxes/RectHitBox.java b/src/main/java/core/physics/hitboxes/RectHitBox.java index dadfc8c..6edcb9d 100644 --- a/src/main/java/core/physics/hitboxes/RectHitBox.java +++ b/src/main/java/core/physics/hitboxes/RectHitBox.java @@ -34,7 +34,7 @@ public class RectHitBox extends Hitbox { this.y1 = Vector2D.add(x1, new Vector2D(0, size.y)); this.y2 = Vector2D.add(x1, new Vector2D(size.x, size.y)); if (Init.DEBUG_MODE) { - Master.getMaster().addDrawable(this, HITBOX_RENDER_LAYER); + //Master.getMaster().addDrawable(this); } } diff --git a/src/main/java/core/renderer/Drawable.java b/src/main/java/core/renderer/Drawable.java index 02c2900..6e75c68 100644 --- a/src/main/java/core/renderer/Drawable.java +++ b/src/main/java/core/renderer/Drawable.java @@ -17,4 +17,10 @@ public interface Drawable { * @param g2d The {@code Graphics2D} object given by the master */ void draw(Graphics2D g2d); + + /** + * Returns the layer of the Drawable + * @return The render layer + */ + int getLayer(); } diff --git a/src/main/java/core/renderer/RoundRectRenderer.java b/src/main/java/core/renderer/RoundRectRenderer.java index 18159cd..6188495 100644 --- a/src/main/java/core/renderer/RoundRectRenderer.java +++ b/src/main/java/core/renderer/RoundRectRenderer.java @@ -29,8 +29,6 @@ public class RoundRectRenderer extends Renderer { int xCenterAbs = (int) (abs.x + sizeAbs.x / 2); int yCenterAbs = (int) (abs.y + sizeAbs.y / 2); - master.debugPos(object.getCenterPosition(), 500); - g2d.setPaint(color); g2d.rotate(object.getRotation(), xCenterAbs, yCenterAbs); diff --git a/src/main/java/objects/ships/Turret.java b/src/main/java/objects/ships/Turret.java index 252804b..c2bd227 100644 --- a/src/main/java/objects/ships/Turret.java +++ b/src/main/java/objects/ships/Turret.java @@ -41,13 +41,10 @@ public class Turret extends GameObject { int xCenterAbs = (int) (abs.x + sizeAbs / 2); int yCenterAbs = (int) (abs.y + sizeAbs / 2); - Master.debugPos(getMapCoords(position), 1); - g2d.rotate(rotation, xCenterAbs, yCenterAbs); g2d.fillOval((int) abs.x, (int) abs.y, sizeAbs, sizeAbs); - Master.debugPos(abs, 1000); //BARRELS--------------------------------------- g2d.setStroke(new BasicStroke((int) Coordinates.getWorldCoordinates(new Vector2D(object.getSize().x / barrelAmount / BARREL_THICKNESS, 0)).x, BasicStroke.CAP_BUTT, @@ -98,13 +95,11 @@ public class Turret extends GameObject { lastShot = System.currentTimeMillis(); Vector2D shellVel = Vector2D.getUnitVector(rotation).negative().multiply(SHELL_SPEED); - //master.debugPos(centerMap); Vector2D pos = Vector2D.rotateAround( centerMap, spawnPosNR, rotation); - //master.debugPos(pos); master.create(new Shell(pos, new Vector2D(SHELL_SIZE, SHELL_SIZE), shellVel)); } }