moved rendering from the Master to the RenderEngine

This commit is contained in:
nora 2020-12-31 17:03:28 +01:00
parent 7e90017e8f
commit 39558c94c7
9 changed files with 231 additions and 90 deletions

View file

@ -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<List<Drawable>> layers;
/**
* The buffer of newly added Renderers
*/
private final List<Drawable> 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.
* <p>If the object should only temporarily be invisible, change its {@code isVisible} field</p>
* @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();
}
}

View file

@ -25,7 +25,7 @@ class Main extends JFrame {
private void initUI() { private void initUI() {
master = new Master(); master = new Master();
add(master); add(master.getRenderEngine());
Init.init(); Init.init();

View file

@ -5,7 +5,6 @@ import core.objects.core.CollGameObject;
import core.physics.Collidable; import core.physics.Collidable;
import core.physics.Collision; import core.physics.Collision;
import core.objects.base.DebugPos; import core.objects.base.DebugPos;
import core.physics.hitboxes.Hitbox;
import core.objects.core.GameObject; import core.objects.core.GameObject;
import core.renderer.Drawable; import core.renderer.Drawable;
import objects.Init; import objects.Init;
@ -13,11 +12,12 @@ import objects.Init;
import javax.swing.*; import javax.swing.*;
import java.awt.*; import java.awt.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
/** /**
* The main object that controls everything * The main object that controls everything
*/ */
public class Master extends JPanel { public class Master {
/** /**
* The ratio of height to width. * The ratio of height to width.
@ -37,35 +37,29 @@ public class Master extends JPanel {
/** /**
* All GameObjects that exist * All GameObjects that exist
*/ */
private final ArrayList<GameObject> objects; private final List<GameObject> objects;
/**
* All GameObjects that can be drawn
* Has different render layers, 0 is on the bottom
*/
private final ArrayList<ArrayList<Drawable>> drawables;
/** /**
* All physics objects that exist * All physics objects that exist
*/ */
private final ArrayList<Collidable> collidables; private final List<Collidable> collidables;
/** /**
* Stores all GameObjects that were created during a frame * Stores all GameObjects that were created during a frame
*/ */
private final ArrayList<GameObject> objectBuffer; private final List<GameObject> objectBuffer;
/** /**
* All physics objects that exist * All physics objects that exist
*/ */
private final ArrayList<Collidable> collidablesBuffer; private final List<Collidable> 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 * Create a new master object
@ -77,41 +71,12 @@ public class Master extends JPanel {
objectBuffer = new ArrayList<>(); objectBuffer = new ArrayList<>();
collidables = new ArrayList<>(); collidables = new ArrayList<>();
collidablesBuffer = new ArrayList<>(); collidablesBuffer = new ArrayList<>();
drawables = new ArrayList<>();
drawables.add(new ArrayList<>());
} }
public static Master getMaster() { public static Master getMaster() {
return master; 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 * Debug a position, creates a green dot at the position
@ -128,7 +93,7 @@ public class Master extends JPanel {
* @param pos The position * @param pos The position
*/ */
private void debugPosObj(Vector2D pos, long lifeTime) { 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); objects.forEach(GameObject::startUpdate);
long time2 = System.currentTimeMillis(); long time2 = System.currentTimeMillis();
Input.frameReset(); 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"); 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() { public Point getMouseLocation() {
Point p = MouseInfo.getPointerInfo().getLocation(); Point p = MouseInfo.getPointerInfo().getLocation();
SwingUtilities.convertPointFromScreen(p, this); SwingUtilities.convertPointFromScreen(p, renderEngine);
return p; return p;
} }
@ -174,49 +140,25 @@ public class Master extends JPanel {
/** /**
* This method has to be called for every newly created GameObject * This method has to be called for every newly created GameObject
* *
* @param obj The new object * @param obj The new object
*/ */
public <T extends GameObject> T create(T obj) { public <T extends GameObject> 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); objectBuffer.add(obj);
if (obj instanceof CollGameObject) { if (obj instanceof CollGameObject) {
collidablesBuffer.add((Collidable) obj); collidablesBuffer.add((Collidable) obj);
} }
addDrawable(obj, renderLayer); renderEngine.addRenderer(obj);
return obj;
} }
/** /**
* Add a new Drawable to the render list * Add a new Drawable to the render list
* *
* @param d The drawable * @param d The drawable
* @param layer The layer it should be put on (>=0)
*/ */
public void addDrawable(Drawable d, int layer) { @Deprecated
public void addDrawable(Drawable d) {
if (layer < 0) { renderEngine.addRenderer(d);
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);
} }
@ -251,25 +193,29 @@ public class Master extends JPanel {
} }
public int getW() { public int getW() {
return w; return renderEngine.getW();
} }
public int getH() { public int getH() {
return h; return renderEngine.getH();
} }
public void destroy(GameObject gameObject) { public void destroy(GameObject gameObject) {
objectBuffer.remove(gameObject); objectBuffer.remove(gameObject);
gameObject.getParent().removeChild(gameObject); gameObject.getParent().removeChild(gameObject);
drawables.get(gameObject.getLayer()).remove(gameObject); renderEngine.removeRenderer(gameObject);
if (gameObject instanceof Collidable) { if (gameObject instanceof Collidable) {
collidablesBuffer.remove(gameObject); collidablesBuffer.remove(gameObject);
if (Init.DEBUG_MODE) { if (Init.DEBUG_MODE) {
drawables.get(Hitbox.HITBOX_RENDER_LAYER).remove(((CollGameObject) gameObject).getHitbox()); renderEngine.removeRenderer(((CollGameObject) gameObject).getHitbox());
} }
} }
} }
public RenderEngine getRenderEngine() {
return renderEngine;
}
} }

View file

@ -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<p>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}</p>
*/
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.
* <p>If the object should only temporarily be invisible, change its {@code isVisible} field</p>
* @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();
}
}

View file

@ -24,4 +24,9 @@ public abstract class Hitbox implements Drawable {
public String toString() { public String toString() {
return super.toString(); return super.toString();
} }
@Override
public int getLayer() {
return HITBOX_RENDER_LAYER;
}
} }

View file

@ -34,7 +34,7 @@ public class RectHitBox extends Hitbox {
this.y1 = Vector2D.add(x1, new Vector2D(0, size.y)); this.y1 = Vector2D.add(x1, new Vector2D(0, size.y));
this.y2 = Vector2D.add(x1, new Vector2D(size.x, size.y)); this.y2 = Vector2D.add(x1, new Vector2D(size.x, size.y));
if (Init.DEBUG_MODE) { if (Init.DEBUG_MODE) {
Master.getMaster().addDrawable(this, HITBOX_RENDER_LAYER); //Master.getMaster().addDrawable(this);
} }
} }

View file

@ -17,4 +17,10 @@ public interface Drawable {
* @param g2d The {@code Graphics2D} object given by the master * @param g2d The {@code Graphics2D} object given by the master
*/ */
void draw(Graphics2D g2d); void draw(Graphics2D g2d);
/**
* Returns the layer of the Drawable
* @return The render layer
*/
int getLayer();
} }

View file

@ -29,8 +29,6 @@ public class RoundRectRenderer extends Renderer {
int xCenterAbs = (int) (abs.x + sizeAbs.x / 2); int xCenterAbs = (int) (abs.x + sizeAbs.x / 2);
int yCenterAbs = (int) (abs.y + sizeAbs.y / 2); int yCenterAbs = (int) (abs.y + sizeAbs.y / 2);
master.debugPos(object.getCenterPosition(), 500);
g2d.setPaint(color); g2d.setPaint(color);
g2d.rotate(object.getRotation(), xCenterAbs, yCenterAbs); g2d.rotate(object.getRotation(), xCenterAbs, yCenterAbs);

View file

@ -41,13 +41,10 @@ public class Turret extends GameObject {
int xCenterAbs = (int) (abs.x + sizeAbs / 2); int xCenterAbs = (int) (abs.x + sizeAbs / 2);
int yCenterAbs = (int) (abs.y + sizeAbs / 2); int yCenterAbs = (int) (abs.y + sizeAbs / 2);
Master.debugPos(getMapCoords(position), 1);
g2d.rotate(rotation, xCenterAbs, yCenterAbs); g2d.rotate(rotation, xCenterAbs, yCenterAbs);
g2d.fillOval((int) abs.x, (int) abs.y, sizeAbs, sizeAbs); g2d.fillOval((int) abs.x, (int) abs.y, sizeAbs, sizeAbs);
Master.debugPos(abs, 1000);
//BARRELS--------------------------------------- //BARRELS---------------------------------------
g2d.setStroke(new BasicStroke((int) Coordinates.getWorldCoordinates(new Vector2D(object.getSize().x / barrelAmount / BARREL_THICKNESS, 0)).x, BasicStroke.CAP_BUTT, 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(); lastShot = System.currentTimeMillis();
Vector2D shellVel = Vector2D.getUnitVector(rotation).negative().multiply(SHELL_SPEED); Vector2D shellVel = Vector2D.getUnitVector(rotation).negative().multiply(SHELL_SPEED);
//master.debugPos(centerMap);
Vector2D pos = Vector2D.rotateAround( Vector2D pos = Vector2D.rotateAround(
centerMap, centerMap,
spawnPosNR, spawnPosNR,
rotation); rotation);
//master.debugPos(pos);
master.create(new Shell(pos, new Vector2D(SHELL_SIZE, SHELL_SIZE), shellVel)); master.create(new Shell(pos, new Vector2D(SHELL_SIZE, SHELL_SIZE), shellVel));
} }
} }