From 67bcba2c5fbce840f02ad6bae13ac1c196252d7c Mon Sep 17 00:00:00 2001 From: Joe Weaver Date: Mon, 10 Aug 2020 13:19:59 -0400 Subject: [PATCH] restructured game nodes and created canvas node subclass --- src/Nodes/CanvasNode.ts | 24 +++++++++++++++ src/Nodes/ColoredCircle.ts | 6 ++-- src/Nodes/GameNode.ts | 22 +++++++------- src/Nodes/Player.ts | 4 +-- src/Nodes/UIElement.ts | 49 ++++++++++++++++--------------- src/SceneGraph/SceneGraphArray.ts | 18 ++++++------ src/SceneGraph/Viewport.ts | 3 +- src/main.ts | 12 ++++---- 8 files changed, 82 insertions(+), 56 deletions(-) create mode 100644 src/Nodes/CanvasNode.ts diff --git a/src/Nodes/CanvasNode.ts b/src/Nodes/CanvasNode.ts new file mode 100644 index 0000000..b89dfc2 --- /dev/null +++ b/src/Nodes/CanvasNode.ts @@ -0,0 +1,24 @@ +import GameNode from "./GameNode"; +import Vec2 from "../DataTypes/Vec2"; + +export default abstract class CanvasNode extends GameNode{ + protected size: Vec2; + + constructor(){ + super(); + this.size = new Vec2(0, 0); + } + + getSize(): Vec2 { + return this.size; + } + + contains(x: number, y: number): boolean { + if(this.position.x < x && this.position.x + this.size.x > x){ + if(this.position.y < y && this.position.y + this.size.y > y){ + return true; + } + } + return false; + } +} \ No newline at end of file diff --git a/src/Nodes/ColoredCircle.ts b/src/Nodes/ColoredCircle.ts index 9561424..d7fe117 100644 --- a/src/Nodes/ColoredCircle.ts +++ b/src/Nodes/ColoredCircle.ts @@ -1,10 +1,10 @@ -import GameNode from "./GameNode"; +import CanvasNode from "./CanvasNode"; import Color from "../Utils/Color"; import Vec2 from "../DataTypes/Vec2"; import RandUtils from "../Utils/RandUtils"; -export default class ColoredCircle extends GameNode{ - private color: Color; +export default class ColoredCircle extends CanvasNode{ + private color: Color; constructor(){ super(); diff --git a/src/Nodes/GameNode.ts b/src/Nodes/GameNode.ts index f20856d..2d03f83 100644 --- a/src/Nodes/GameNode.ts +++ b/src/Nodes/GameNode.ts @@ -1,35 +1,33 @@ import EventQueue from "../Events/EventQueue"; import InputReceiver from "../Input/InputReceiver"; import Vec2 from "../DataTypes/Vec2"; +import Map from "../DataTypes/Map"; +import Receiver from "../Events/Receiver"; +import GameEvent from "../Events/GameEvent"; export default abstract class GameNode{ - protected eventQueue: EventQueue; + private eventQueue: EventQueue; protected input: InputReceiver; protected position: Vec2; - protected size: Vec2; + private receiver: Receiver; constructor(){ this.eventQueue = EventQueue.getInstance(); this.input = InputReceiver.getInstance(); this.position = new Vec2(0, 0); - this.size = new Vec2(0, 0); } getPosition(): Vec2 { return this.position; } - getSize(): Vec2 { - return this.size; + subscribe(eventType: string){ + this.eventQueue.subscribe(this.receiver, eventType); } - contains(x: number, y: number): boolean { - if(x > this.position.x && x < this.position.x + this.size.x){ - if(y > this.position.y && y < this.position.y + this.size.y){ - return true; - } - } - return false; + emit(eventType: string, data: Map | Record = null){ + let event = new GameEvent(eventType, data); + this.eventQueue.addEvent(event); } abstract update(deltaT: number): void; diff --git a/src/Nodes/Player.ts b/src/Nodes/Player.ts index 7c114ff..32d7c47 100644 --- a/src/Nodes/Player.ts +++ b/src/Nodes/Player.ts @@ -1,7 +1,7 @@ -import GameNode from "./GameNode"; +import CanvasNode from "./CanvasNode"; import Vec2 from "../DataTypes/Vec2"; -export default class Player extends GameNode{ +export default class Player extends CanvasNode{ velocity: Vec2; speed: number; diff --git a/src/Nodes/UIElement.ts b/src/Nodes/UIElement.ts index 2d75669..3246823 100644 --- a/src/Nodes/UIElement.ts +++ b/src/Nodes/UIElement.ts @@ -1,31 +1,34 @@ -import GameNode from "./GameNode"; +import CanvasNode from "./CanvasNode"; import Color from "../Utils/Color"; import Vec2 from "../DataTypes/Vec2"; -import GameEvent from "../Events/GameEvent"; -export default class UIElement extends GameNode{ - parent: GameNode; - children: Array; - text: string; - backgroundColor: Color; +export default class UIElement extends CanvasNode{ + // Style attributes textColor: Color; - onPress: Function; - onPressSignal: string; + backgroundColor: Color; + borderColor: Color; + text: string; + font: string; + + // EventAttributes + onClick: Function; + onClickEventId: string; onHover: Function; + onHoverEventId: string; constructor(){ super(); - - this.parent = null; - this.children = []; - this.text = ""; - this.backgroundColor = new Color(0, 0, 0, 0); this.textColor = new Color(0, 0, 0, 1); + this.backgroundColor = new Color(0, 0, 0, 0); + this.borderColor = new Color(0, 0, 0, 0); + this.text = ""; + this.font = "30px Arial"; - this.onPress = null; - this.onPressSignal = null; + this.onClick = null; + this.onClickEventId = null; this.onHover = null; + this.onHoverEventId = null; } setPosition(vecOrX: Vec2 | number, y: number = null): void { @@ -58,7 +61,7 @@ export default class UIElement extends GameNode{ update(deltaT: number): void { if(this.input.isMouseJustPressed()){ - let mousePos = this.input.getMousePressPosition(); + let mousePos = this.input.getMousePressPosition(); if(mousePos.x >= this.position.x && mousePos.x <= this.position.x + this.size.x){ // Inside x bounds if(mousePos.y >= this.position.y && mousePos.y <= this.position.y + this.size.y){ @@ -67,12 +70,12 @@ export default class UIElement extends GameNode{ this.onHover(); } - if(this.onPress !== null){ - this.onPress(); + if(this.onClick !== null){ + this.onClick(); } - if(this.onPressSignal !== null){ - let event = new GameEvent(this.onPressSignal, {}); - this.eventQueue.addEvent(event); + if(this.onClickEventId !== null){ + let data = {}; + this.emit(this.onClickEventId, data); } } } @@ -83,7 +86,7 @@ export default class UIElement extends GameNode{ ctx.fillStyle = this.backgroundColor.toStringRGBA(); ctx.fillRect(this.position.x - viewportOrigin.x, this.position.y - viewportOrigin.y, this.size.x, this.size.y); ctx.fillStyle = this.textColor.toStringRGBA(); - ctx.font = "30px Arial" + ctx.font = this.font; ctx.fillText(this.text, this.position.x - viewportOrigin.x, this.position.y - viewportOrigin.y + 30); } } \ No newline at end of file diff --git a/src/SceneGraph/SceneGraphArray.ts b/src/SceneGraph/SceneGraphArray.ts index 04772e0..7d70705 100644 --- a/src/SceneGraph/SceneGraphArray.ts +++ b/src/SceneGraph/SceneGraphArray.ts @@ -1,15 +1,15 @@ import SceneGraph from "./SceneGraph"; -import GameNode from "../Nodes/GameNode"; +import CanvasNode from "../Nodes/CanvasNode"; import Viewport from "./Viewport"; export default class SceneGraphArray extends SceneGraph{ - private nodeList: Array; + private nodeList: Array; private turnOffViewportCulling_demoTool: boolean; constructor(viewport: Viewport){ super(viewport); - this.nodeList = new Array(); + this.nodeList = new Array(); this.turnOffViewportCulling_demoTool = false; } @@ -17,18 +17,18 @@ export default class SceneGraphArray extends SceneGraph{ this.turnOffViewportCulling_demoTool = bool; } - addNodeSpecific(node: GameNode, id: string): void { + addNodeSpecific(node: CanvasNode, id: string): void { this.nodeList.push(node); } - removeNodeSpecific(node: GameNode, id: string): void { + removeNodeSpecific(node: CanvasNode, id: string): void { let index = this.nodeList.indexOf(node); if(index > -1){ this.nodeList.splice(index, 1); } } - getNodeAtCoords(x: number, y: number): GameNode { + getNodeAtCoords(x: number, y: number): CanvasNode { // TODO: This only returns the first node found. There is no notion of z coordinates for(let node of this.nodeList){ if(node.contains(x, y)){ @@ -44,17 +44,17 @@ export default class SceneGraphArray extends SceneGraph{ } } - getVisibleSet(): Array { + getVisibleSet(): Array { // If viewport culling is turned off for demonstration if(this.turnOffViewportCulling_demoTool){ - let visibleSet = new Array(); + let visibleSet = new Array(); for(let node of this.nodeList){ visibleSet.push(node); } return visibleSet; } - let visibleSet = new Array(); + let visibleSet = new Array(); for(let node of this.nodeList){ if(this.viewport.includes(node)){ diff --git a/src/SceneGraph/Viewport.ts b/src/SceneGraph/Viewport.ts index 9b54a48..95bd5c0 100644 --- a/src/SceneGraph/Viewport.ts +++ b/src/SceneGraph/Viewport.ts @@ -1,6 +1,7 @@ import Vec2 from "../DataTypes/Vec2"; import Vec4 from "../DataTypes/Vec4"; import GameNode from "../Nodes/GameNode"; +import CanvasNode from "../Nodes/CanvasNode"; import MathUtils from "../Utils/MathUtils"; export default class Viewport{ @@ -39,7 +40,7 @@ export default class Viewport{ } } - includes(node: GameNode): boolean { + includes(node: CanvasNode): boolean { let nodePos = node.getPosition(); let nodeSize = node.getSize(); if(nodePos.x + nodeSize.x > this.position.x && nodePos.x < this.position.x + this.size.x){ diff --git a/src/main.ts b/src/main.ts index cb1e0dd..32d1345 100644 --- a/src/main.ts +++ b/src/main.ts @@ -20,21 +20,21 @@ function main(){ recordButton.setText("Record"); recordButton.setBackgroundColor(new Color(200, 100, 0, 0.3)); recordButton.setPosition(400, 30); - recordButton.onPressSignal = "record_button_press"; + recordButton.onClickEventId = "record_button_press"; let stopButton = new UIElement(); stopButton.setSize(100, 50); stopButton.setText("Stop"); stopButton.setBackgroundColor(new Color(200, 0, 0, 0.3)); stopButton.setPosition(550, 30); - stopButton.onPressSignal = "stop_button_press"; + stopButton.onClickEventId = "stop_button_press"; let playButton = new UIElement(); playButton.setSize(100, 50); playButton.setText("Play"); playButton.setBackgroundColor(new Color(0, 200, 0, 0.3)); playButton.setPosition(700, 30); - playButton.onPressSignal = "play_button_press"; + playButton.onClickEventId = "play_button_press"; let cycleFramerateButton = new UIElement(); cycleFramerateButton.setSize(150, 50); @@ -43,7 +43,7 @@ function main(){ cycleFramerateButton.setPosition(5, 400); let i = 0; let fps = [15, 30, 60]; - cycleFramerateButton.onPress = () => { + cycleFramerateButton.onClick = () => { game.setMaxFPS(fps[i]); i = (i + 1) % 3; } @@ -53,7 +53,7 @@ function main(){ pauseButton.setText("Pause"); pauseButton.setBackgroundColor(new Color(200, 0, 200, 1)); pauseButton.setPosition(700, 400); - pauseButton.onPress = () => { + pauseButton.onClick = () => { game.getGameState().addScene(pauseMenu); } @@ -67,7 +67,7 @@ function main(){ resumeButton.setText("Resume"); resumeButton.setBackgroundColor(new Color(200, 0, 200, 1)); resumeButton.setPosition(400, 200); - resumeButton.onPress = () => { + resumeButton.onClick = () => { game.getGameState().removeScene(); }