restructured game nodes and created canvas node subclass

This commit is contained in:
Joe Weaver 2020-08-10 13:19:59 -04:00
parent 40a05fdbdb
commit 67bcba2c5f
8 changed files with 82 additions and 56 deletions

24
src/Nodes/CanvasNode.ts Normal file
View File

@ -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;
}
}

View File

@ -1,10 +1,10 @@
import GameNode from "./GameNode"; import CanvasNode from "./CanvasNode";
import Color from "../Utils/Color"; import Color from "../Utils/Color";
import Vec2 from "../DataTypes/Vec2"; import Vec2 from "../DataTypes/Vec2";
import RandUtils from "../Utils/RandUtils"; import RandUtils from "../Utils/RandUtils";
export default class ColoredCircle extends GameNode{ export default class ColoredCircle extends CanvasNode{
private color: Color; private color: Color;
constructor(){ constructor(){
super(); super();

View File

@ -1,35 +1,33 @@
import EventQueue from "../Events/EventQueue"; import EventQueue from "../Events/EventQueue";
import InputReceiver from "../Input/InputReceiver"; import InputReceiver from "../Input/InputReceiver";
import Vec2 from "../DataTypes/Vec2"; 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{ export default abstract class GameNode{
protected eventQueue: EventQueue; private eventQueue: EventQueue;
protected input: InputReceiver; protected input: InputReceiver;
protected position: Vec2; protected position: Vec2;
protected size: Vec2; private receiver: Receiver;
constructor(){ constructor(){
this.eventQueue = EventQueue.getInstance(); this.eventQueue = EventQueue.getInstance();
this.input = InputReceiver.getInstance(); this.input = InputReceiver.getInstance();
this.position = new Vec2(0, 0); this.position = new Vec2(0, 0);
this.size = new Vec2(0, 0);
} }
getPosition(): Vec2 { getPosition(): Vec2 {
return this.position; return this.position;
} }
getSize(): Vec2 { subscribe(eventType: string){
return this.size; this.eventQueue.subscribe(this.receiver, eventType);
} }
contains(x: number, y: number): boolean { emit(eventType: string, data: Map<any> | Record<string, any> = null){
if(x > this.position.x && x < this.position.x + this.size.x){ let event = new GameEvent(eventType, data);
if(y > this.position.y && y < this.position.y + this.size.y){ this.eventQueue.addEvent(event);
return true;
}
}
return false;
} }
abstract update(deltaT: number): void; abstract update(deltaT: number): void;

View File

@ -1,7 +1,7 @@
import GameNode from "./GameNode"; import CanvasNode from "./CanvasNode";
import Vec2 from "../DataTypes/Vec2"; import Vec2 from "../DataTypes/Vec2";
export default class Player extends GameNode{ export default class Player extends CanvasNode{
velocity: Vec2; velocity: Vec2;
speed: number; speed: number;

View File

@ -1,31 +1,34 @@
import GameNode from "./GameNode"; import CanvasNode from "./CanvasNode";
import Color from "../Utils/Color"; import Color from "../Utils/Color";
import Vec2 from "../DataTypes/Vec2"; import Vec2 from "../DataTypes/Vec2";
import GameEvent from "../Events/GameEvent";
export default class UIElement extends GameNode{ export default class UIElement extends CanvasNode{
parent: GameNode; // Style attributes
children: Array<GameNode>;
text: string;
backgroundColor: Color;
textColor: Color; textColor: Color;
onPress: Function; backgroundColor: Color;
onPressSignal: string; borderColor: Color;
text: string;
font: string;
// EventAttributes
onClick: Function;
onClickEventId: string;
onHover: Function; onHover: Function;
onHoverEventId: string;
constructor(){ constructor(){
super(); 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.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.onClick = null;
this.onPressSignal = null; this.onClickEventId = null;
this.onHover = null; this.onHover = null;
this.onHoverEventId = null;
} }
setPosition(vecOrX: Vec2 | number, y: number = null): void { setPosition(vecOrX: Vec2 | number, y: number = null): void {
@ -58,7 +61,7 @@ export default class UIElement extends GameNode{
update(deltaT: number): void { update(deltaT: number): void {
if(this.input.isMouseJustPressed()){ 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){ if(mousePos.x >= this.position.x && mousePos.x <= this.position.x + this.size.x){
// Inside x bounds // Inside x bounds
if(mousePos.y >= this.position.y && mousePos.y <= this.position.y + this.size.y){ 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(); this.onHover();
} }
if(this.onPress !== null){ if(this.onClick !== null){
this.onPress(); this.onClick();
} }
if(this.onPressSignal !== null){ if(this.onClickEventId !== null){
let event = new GameEvent(this.onPressSignal, {}); let data = {};
this.eventQueue.addEvent(event); this.emit(this.onClickEventId, data);
} }
} }
} }
@ -83,7 +86,7 @@ export default class UIElement extends GameNode{
ctx.fillStyle = this.backgroundColor.toStringRGBA(); ctx.fillStyle = this.backgroundColor.toStringRGBA();
ctx.fillRect(this.position.x - viewportOrigin.x, this.position.y - viewportOrigin.y, this.size.x, this.size.y); ctx.fillRect(this.position.x - viewportOrigin.x, this.position.y - viewportOrigin.y, this.size.x, this.size.y);
ctx.fillStyle = this.textColor.toStringRGBA(); 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); ctx.fillText(this.text, this.position.x - viewportOrigin.x, this.position.y - viewportOrigin.y + 30);
} }
} }

View File

@ -1,15 +1,15 @@
import SceneGraph from "./SceneGraph"; import SceneGraph from "./SceneGraph";
import GameNode from "../Nodes/GameNode"; import CanvasNode from "../Nodes/CanvasNode";
import Viewport from "./Viewport"; import Viewport from "./Viewport";
export default class SceneGraphArray extends SceneGraph{ export default class SceneGraphArray extends SceneGraph{
private nodeList: Array<GameNode>; private nodeList: Array<CanvasNode>;
private turnOffViewportCulling_demoTool: boolean; private turnOffViewportCulling_demoTool: boolean;
constructor(viewport: Viewport){ constructor(viewport: Viewport){
super(viewport); super(viewport);
this.nodeList = new Array<GameNode>(); this.nodeList = new Array<CanvasNode>();
this.turnOffViewportCulling_demoTool = false; this.turnOffViewportCulling_demoTool = false;
} }
@ -17,18 +17,18 @@ export default class SceneGraphArray extends SceneGraph{
this.turnOffViewportCulling_demoTool = bool; this.turnOffViewportCulling_demoTool = bool;
} }
addNodeSpecific(node: GameNode, id: string): void { addNodeSpecific(node: CanvasNode, id: string): void {
this.nodeList.push(node); this.nodeList.push(node);
} }
removeNodeSpecific(node: GameNode, id: string): void { removeNodeSpecific(node: CanvasNode, id: string): void {
let index = this.nodeList.indexOf(node); let index = this.nodeList.indexOf(node);
if(index > -1){ if(index > -1){
this.nodeList.splice(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 // TODO: This only returns the first node found. There is no notion of z coordinates
for(let node of this.nodeList){ for(let node of this.nodeList){
if(node.contains(x, y)){ if(node.contains(x, y)){
@ -44,17 +44,17 @@ export default class SceneGraphArray extends SceneGraph{
} }
} }
getVisibleSet(): Array<GameNode> { getVisibleSet(): Array<CanvasNode> {
// If viewport culling is turned off for demonstration // If viewport culling is turned off for demonstration
if(this.turnOffViewportCulling_demoTool){ if(this.turnOffViewportCulling_demoTool){
let visibleSet = new Array<GameNode>(); let visibleSet = new Array<CanvasNode>();
for(let node of this.nodeList){ for(let node of this.nodeList){
visibleSet.push(node); visibleSet.push(node);
} }
return visibleSet; return visibleSet;
} }
let visibleSet = new Array<GameNode>(); let visibleSet = new Array<CanvasNode>();
for(let node of this.nodeList){ for(let node of this.nodeList){
if(this.viewport.includes(node)){ if(this.viewport.includes(node)){

View File

@ -1,6 +1,7 @@
import Vec2 from "../DataTypes/Vec2"; import Vec2 from "../DataTypes/Vec2";
import Vec4 from "../DataTypes/Vec4"; import Vec4 from "../DataTypes/Vec4";
import GameNode from "../Nodes/GameNode"; import GameNode from "../Nodes/GameNode";
import CanvasNode from "../Nodes/CanvasNode";
import MathUtils from "../Utils/MathUtils"; import MathUtils from "../Utils/MathUtils";
export default class Viewport{ 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 nodePos = node.getPosition();
let nodeSize = node.getSize(); let nodeSize = node.getSize();
if(nodePos.x + nodeSize.x > this.position.x && nodePos.x < this.position.x + this.size.x){ if(nodePos.x + nodeSize.x > this.position.x && nodePos.x < this.position.x + this.size.x){

View File

@ -20,21 +20,21 @@ function main(){
recordButton.setText("Record"); recordButton.setText("Record");
recordButton.setBackgroundColor(new Color(200, 100, 0, 0.3)); recordButton.setBackgroundColor(new Color(200, 100, 0, 0.3));
recordButton.setPosition(400, 30); recordButton.setPosition(400, 30);
recordButton.onPressSignal = "record_button_press"; recordButton.onClickEventId = "record_button_press";
let stopButton = new UIElement(); let stopButton = new UIElement();
stopButton.setSize(100, 50); stopButton.setSize(100, 50);
stopButton.setText("Stop"); stopButton.setText("Stop");
stopButton.setBackgroundColor(new Color(200, 0, 0, 0.3)); stopButton.setBackgroundColor(new Color(200, 0, 0, 0.3));
stopButton.setPosition(550, 30); stopButton.setPosition(550, 30);
stopButton.onPressSignal = "stop_button_press"; stopButton.onClickEventId = "stop_button_press";
let playButton = new UIElement(); let playButton = new UIElement();
playButton.setSize(100, 50); playButton.setSize(100, 50);
playButton.setText("Play"); playButton.setText("Play");
playButton.setBackgroundColor(new Color(0, 200, 0, 0.3)); playButton.setBackgroundColor(new Color(0, 200, 0, 0.3));
playButton.setPosition(700, 30); playButton.setPosition(700, 30);
playButton.onPressSignal = "play_button_press"; playButton.onClickEventId = "play_button_press";
let cycleFramerateButton = new UIElement(); let cycleFramerateButton = new UIElement();
cycleFramerateButton.setSize(150, 50); cycleFramerateButton.setSize(150, 50);
@ -43,7 +43,7 @@ function main(){
cycleFramerateButton.setPosition(5, 400); cycleFramerateButton.setPosition(5, 400);
let i = 0; let i = 0;
let fps = [15, 30, 60]; let fps = [15, 30, 60];
cycleFramerateButton.onPress = () => { cycleFramerateButton.onClick = () => {
game.setMaxFPS(fps[i]); game.setMaxFPS(fps[i]);
i = (i + 1) % 3; i = (i + 1) % 3;
} }
@ -53,7 +53,7 @@ function main(){
pauseButton.setText("Pause"); pauseButton.setText("Pause");
pauseButton.setBackgroundColor(new Color(200, 0, 200, 1)); pauseButton.setBackgroundColor(new Color(200, 0, 200, 1));
pauseButton.setPosition(700, 400); pauseButton.setPosition(700, 400);
pauseButton.onPress = () => { pauseButton.onClick = () => {
game.getGameState().addScene(pauseMenu); game.getGameState().addScene(pauseMenu);
} }
@ -67,7 +67,7 @@ function main(){
resumeButton.setText("Resume"); resumeButton.setText("Resume");
resumeButton.setBackgroundColor(new Color(200, 0, 200, 1)); resumeButton.setBackgroundColor(new Color(200, 0, 200, 1));
resumeButton.setPosition(400, 200); resumeButton.setPosition(400, 200);
resumeButton.onPress = () => { resumeButton.onClick = () => {
game.getGameState().removeScene(); game.getGameState().removeScene();
} }