From 661fc6d2753b498467fc00ba7f8e21ab3f583338 Mon Sep 17 00:00:00 2001 From: DaniTheSkunk Date: Tue, 11 Oct 2022 02:15:14 +0000 Subject: [PATCH] started writing node system --- com/danitheskunk/skunkworks/BaseGame.java | 11 +++- com/danitheskunk/skunkworks/TestNode.java | 19 ++++++ com/danitheskunk/skunkworks/Vec2f.java | 1 + com/danitheskunk/skunkworks/nodes/Node.java | 59 ++++++++++++++++++ .../skunkworks/nodes/NodeSprite.java | 27 ++++++++ demoassets/test.png | Bin 0 -> 17977 bytes 6 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 com/danitheskunk/skunkworks/TestNode.java create mode 100644 com/danitheskunk/skunkworks/nodes/Node.java create mode 100644 com/danitheskunk/skunkworks/nodes/NodeSprite.java create mode 100644 demoassets/test.png diff --git a/com/danitheskunk/skunkworks/BaseGame.java b/com/danitheskunk/skunkworks/BaseGame.java index c9555a1..f710d8f 100644 --- a/com/danitheskunk/skunkworks/BaseGame.java +++ b/com/danitheskunk/skunkworks/BaseGame.java @@ -3,17 +3,20 @@ package com.danitheskunk.skunkworks; import com.danitheskunk.skunkworks.gfx.Color; import com.danitheskunk.skunkworks.gfx.IRenderContext; import com.danitheskunk.skunkworks.gfx.font.IFont; +import com.danitheskunk.skunkworks.nodes.Node; public abstract class BaseGame { protected Engine engine; protected IWindow window; protected IFont debugFont; + protected Node rootNode; public BaseGame(Vec2i windowSize, String windowTitle) { this.engine = new Engine(); this.window = engine.openWindow(windowSize, windowTitle); //todo: load from .jar this.debugFont = window.loadFontTileset("fonts/ega-8x14.png"); + this.rootNode = new Node(); init(); } @@ -23,6 +26,8 @@ public abstract class BaseGame { //todo: frame rate control update(1000.0 / 60.0); var rc = window.renderStart(); + renderPre(rc); + rootNode.render(rc); render(rc); window.renderFinish(rc); } @@ -32,8 +37,12 @@ public abstract class BaseGame { } + protected void renderPre(IRenderContext rc) { + + } + protected void render(IRenderContext rc) { - rc.drawString(new Vec2i(8, 8), "Welcome to Skunkworks, please overide the render method to get started", debugFont, Color.LIGHT_GRAY); + //rc.drawString(new Vec2i(8, 8), "Welcome to Skunkworks, please overide the render method to get started", debugFont, Color.LIGHT_GRAY); } protected void update(double delta) { diff --git a/com/danitheskunk/skunkworks/TestNode.java b/com/danitheskunk/skunkworks/TestNode.java new file mode 100644 index 0000000..2c23087 --- /dev/null +++ b/com/danitheskunk/skunkworks/TestNode.java @@ -0,0 +1,19 @@ +package com.danitheskunk.skunkworks; + +import com.danitheskunk.skunkworks.nodes.NodeSprite; + +public class TestNode extends BaseGame { + NodeSprite sprite; + + public TestNode() { + super(new Vec2i(1280, 720), "Skunkworks"); + sprite = new NodeSprite(); + sprite.setTexture(window.loadTexture("demoassets/test.png")); + sprite.setPos(new Vec2f(100, 100)); + rootNode.add(sprite); + } + + public static void main(String[] args) { + new TestNode().run(); + } +} diff --git a/com/danitheskunk/skunkworks/Vec2f.java b/com/danitheskunk/skunkworks/Vec2f.java index 8a4e7c1..5d8b99c 100644 --- a/com/danitheskunk/skunkworks/Vec2f.java +++ b/com/danitheskunk/skunkworks/Vec2f.java @@ -1,6 +1,7 @@ package com.danitheskunk.skunkworks; public final class Vec2f { + public final static Vec2f ZERO = new Vec2f(0, 0); private final double x, y; //constructors diff --git a/com/danitheskunk/skunkworks/nodes/Node.java b/com/danitheskunk/skunkworks/nodes/Node.java new file mode 100644 index 0000000..0e15209 --- /dev/null +++ b/com/danitheskunk/skunkworks/nodes/Node.java @@ -0,0 +1,59 @@ +package com.danitheskunk.skunkworks.nodes; + +import com.danitheskunk.skunkworks.Vec2f; +import com.danitheskunk.skunkworks.gfx.IRenderContext; + +import java.sql.Array; +import java.util.*; + +//todo: figure out the whole translation position thingie + +public class Node implements Iterable { + protected List children; + protected Node parent; + protected Vec2f pos; + + public Node() { + children = new ArrayList<>(); + parent = null; + pos = Vec2f.ZERO; + } + + public Vec2f getPos() { + return pos; + } + + public void setPos(Vec2f pos) { + this.pos = pos; + } + + public void add(Node node) { + if(node.parent != null) { + throw new RuntimeException("Can't add node to two nodes"); + } + node.parent = this; + children.add(node); + } + + public void remove(Node node) { + node.parent = null; + children.remove(node); + } + + public void render(IRenderContext rc) { + for(var child : this) { + child.render(rc); + } + } + + public Vec2f getAbsolutePos() { + if(parent == null) + return pos; + return Vec2f.add(parent.getAbsolutePos(), pos); + } + + @Override + public Iterator iterator() { + return children.iterator(); + } +} diff --git a/com/danitheskunk/skunkworks/nodes/NodeSprite.java b/com/danitheskunk/skunkworks/nodes/NodeSprite.java new file mode 100644 index 0000000..5d8acce --- /dev/null +++ b/com/danitheskunk/skunkworks/nodes/NodeSprite.java @@ -0,0 +1,27 @@ +package com.danitheskunk.skunkworks.nodes; + +import com.danitheskunk.skunkworks.Vec2f; +import com.danitheskunk.skunkworks.gfx.IRenderContext; +import com.danitheskunk.skunkworks.gfx.ITexture; + +public class NodeSprite extends Node { + //todo: support animations + private ITexture texture; + + public NodeSprite() { + texture = null; + } + + public ITexture getTexture() { + return texture; + } + + public void setTexture(ITexture texture) { + this.texture = texture; + } + + @Override + public void render(IRenderContext rc) { + rc.drawTexture(getAbsolutePos().toVec2i(), texture); + } +} diff --git a/demoassets/test.png b/demoassets/test.png new file mode 100644 index 0000000000000000000000000000000000000000..f00f1a37b887191fa40c22f7726baee10994a007 GIT binary patch literal 17977 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 A+yDRo literal 0 HcmV?d00001