added y sorting for object layers

This commit is contained in:
Joe Weaver 2020-09-23 14:30:29 -04:00
parent 9cb4f55d9a
commit cf3c801bdb
8 changed files with 67 additions and 30 deletions

View File

@ -100,7 +100,7 @@ export default class MainScene extends Scene {
pauseButton.setText("Pause"); pauseButton.setText("Pause");
pauseButton.setPosition(700, 400); pauseButton.setPosition(700, 400);
pauseButton.onClick = () => { pauseButton.onClick = () => {
this.layers.forEach((layer: Layer) => layer.setPaused(true)); this.sceneGraph.getLayers().forEach((layer: Layer) => layer.setPaused(true));
pauseLayer.enable(); pauseLayer.enable();
} }
@ -114,7 +114,7 @@ export default class MainScene extends Scene {
resumeButton.setText("Resume"); resumeButton.setText("Resume");
resumeButton.setPosition(360, 150); resumeButton.setPosition(360, 150);
resumeButton.onClick = () => { resumeButton.onClick = () => {
this.layers.forEach((layer: Layer) => layer.setPaused(false)); this.sceneGraph.getLayers().forEach((layer: Layer) => layer.setPaused(false));
pauseLayer.disable(); pauseLayer.disable();
} }

View File

@ -172,8 +172,11 @@ export default class ResourceManager {
// Load everything in the queues. Tilemaps have to come before images because they will add new images to the queue // Load everything in the queues. Tilemaps have to come before images because they will add new images to the queue
this.loadTilemapsFromQueue(() => { this.loadTilemapsFromQueue(() => {
console.log("Loaded Tilemaps");
this.loadImagesFromQueue(() => { this.loadImagesFromQueue(() => {
console.log("Loaded Images");
this.loadAudioFromQueue(() => { this.loadAudioFromQueue(() => {
console.log("Loaded Audio");
// Done loading // Done loading
this.loading = false; this.loading = false;
this.justLoaded = true; this.justLoaded = true;

View File

@ -88,11 +88,13 @@ export default class TilemapFactory {
// Check if obj is collidable // Check if obj is collidable
let collidable = false; let collidable = false;
if(obj.properties){
for(let prop of obj.properties){ for(let prop of obj.properties){
if(prop.name === "Collidable"){ if(prop.name === "Collidable"){
collidable = prop.value; collidable = prop.value;
} }
} }
}
let sprite: Sprite; let sprite: Sprite;

View File

@ -13,6 +13,8 @@ export default class Layer {
protected hidden: boolean; protected hidden: boolean;
protected alpha: number; protected alpha: number;
protected items: Array<GameNode>; protected items: Array<GameNode>;
protected ySort: boolean;
protected depth: number;
constructor(scene: Scene){ constructor(scene: Scene){
this.scene = scene; this.scene = scene;
@ -21,6 +23,8 @@ export default class Layer {
this.hidden = false; this.hidden = false;
this.alpha = 1; this.alpha = 1;
this.items = new Array(); this.items = new Array();
this.ySort = false;
this.depth = 0;
} }
setPaused(pauseValue: boolean): void { setPaused(pauseValue: boolean): void {
@ -65,6 +69,22 @@ export default class Layer {
return this.parallax; return this.parallax;
} }
setYSort(ySort: boolean): void {
this.ySort = ySort;
}
getYSort(): boolean {
return this.ySort;
}
setDepth(depth: number): void {
this.depth = depth;
}
getDepth(): number {
return this.depth;
}
addNode(node: GameNode): void { addNode(node: GameNode): void {
this.items.push(node); this.items.push(node);
node.setLayer(this); node.setLayer(this);

View File

@ -14,7 +14,6 @@ import Receiver from "../Events/Receiver";
import Emitter from "../Events/Emitter"; import Emitter from "../Events/Emitter";
export default class Scene{ export default class Scene{
protected layers: Stack<Layer>;
protected worldSize: Vec2; protected worldSize: Vec2;
protected viewport: Viewport; protected viewport: Viewport;
protected running: boolean; protected running: boolean;
@ -42,7 +41,7 @@ export default class Scene{
public load: ResourceManager; public load: ResourceManager;
constructor(viewport: Viewport, sceneManager: SceneManager, game: GameLoop){ constructor(viewport: Viewport, sceneManager: SceneManager, game: GameLoop){
this.layers = new Stack(10);
this.worldSize = new Vec2(1600, 1000); this.worldSize = new Vec2(1600, 1000);
this.viewport = viewport; this.viewport = viewport;
this.viewport.setBounds(0, 0, 2560, 1280); this.viewport.setBounds(0, 0, 2560, 1280);
@ -138,9 +137,7 @@ export default class Scene{
* Adds a new layer to the scene and returns it * Adds a new layer to the scene and returns it
*/ */
addLayer(): Layer { addLayer(): Layer {
let layer = new Layer(this); return this.sceneGraph.addLayer();
this.layers.push(layer);
return layer;
} }
/** /**

View File

@ -3,6 +3,8 @@ import CanvasNode from "../Nodes/CanvasNode";
import Map from "../DataTypes/Map"; import Map from "../DataTypes/Map";
import Vec2 from "../DataTypes/Vec2"; import Vec2 from "../DataTypes/Vec2";
import Scene from "../Scene/Scene"; import Scene from "../Scene/Scene";
import Layer from "../Scene/Layer";
import Stack from "../DataTypes/Stack";
/** /**
* An abstract interface of a SceneGraph. Exposes methods for use by other code, but leaves the implementation up to the subclasses. * An abstract interface of a SceneGraph. Exposes methods for use by other code, but leaves the implementation up to the subclasses.
@ -12,12 +14,14 @@ export default abstract class SceneGraph {
protected nodeMap: Map<CanvasNode>; protected nodeMap: Map<CanvasNode>;
protected idCounter: number; protected idCounter: number;
protected scene: Scene; protected scene: Scene;
protected layers: Stack<Layer>;
constructor(viewport: Viewport, scene: Scene){ constructor(viewport: Viewport, scene: Scene){
this.viewport = viewport; this.viewport = viewport;
this.scene = scene; this.scene = scene;
this.nodeMap = new Map<CanvasNode>(); this.nodeMap = new Map<CanvasNode>();
this.idCounter = 0; this.idCounter = 0;
this.layers = new Stack(10);
} }
/** /**
@ -87,6 +91,18 @@ export default abstract class SceneGraph {
*/ */
protected abstract getNodeAtCoords(x: number, y: number): CanvasNode; protected abstract getNodeAtCoords(x: number, y: number): CanvasNode;
addLayer(): Layer {
let layer = new Layer(this.scene);
let depth = this.layers.size();
layer.setDepth(depth);
this.layers.push(layer);
return layer;
}
getLayers(): Stack<Layer> {
return this.layers;
}
abstract update(deltaT: number): void; abstract update(deltaT: number): void;
/** /**

View File

@ -2,6 +2,8 @@ import SceneGraph from "./SceneGraph";
import CanvasNode from "../Nodes/CanvasNode"; import CanvasNode from "../Nodes/CanvasNode";
import Viewport from "./Viewport"; import Viewport from "./Viewport";
import Scene from "../Scene/Scene"; import Scene from "../Scene/Scene";
import Stack from "../DataTypes/Stack";
import Layer from "../Scene/Layer"
export default class SceneGraphArray extends SceneGraph{ export default class SceneGraphArray extends SceneGraph{
private nodeList: Array<CanvasNode>; private nodeList: Array<CanvasNode>;
@ -65,6 +67,16 @@ export default class SceneGraphArray extends SceneGraph{
} }
} }
// Sort by depth, then by visible set by y-value
visibleSet.sort((a, b) => {
if(a.getLayer().getDepth() === b.getLayer().getDepth()){
return (a.getPosition().y + a.getSize().y*a.getScale().y)
- (b.getPosition().y + b.getSize().y*b.getScale().y);
} else {
return a.getLayer().getDepth() - b.getLayer().getDepth();
}
});
return visibleSet; return visibleSet;
} }
} }

View File

@ -12,11 +12,9 @@ import { GameEventType } from "./Events/GameEventType";
export default class SecondScene extends Scene { export default class SecondScene extends Scene {
loadScene(){ loadScene(){
this.load.tilemap("level2", "assets/tilemaps/OtherMap.json"); this.load.tilemap("level2", "assets/tilemaps/TopDown2.json");
this.load.tilemap("background2", "assets/tilemaps/OtherBackground.json");
this.load.image("player", "assets/sprites/player.png"); this.load.image("player", "assets/sprites/player.png");
this.load.audio("player_jump", "assets/sounds/jump-3.wav"); this.load.audio("music", "assets/sounds/level.wav")
this.load.audio("level_music", "assets/sounds/level.wav");
let loadingScreen = this.addLayer(); let loadingScreen = this.addLayer();
let box = this.add.graphic(Rect, loadingScreen, new Vec2(200, 300), new Vec2(400, 60)); let box = this.add.graphic(Rect, loadingScreen, new Vec2(200, 300), new Vec2(400, 60));
@ -34,23 +32,12 @@ export default class SecondScene extends Scene {
} }
startScene(){ startScene(){
// Add the background tilemap
let backgroundTilemapLayer = this.add.tilemap("background2")[0];
// ...and make it have parallax
backgroundTilemapLayer.setParallax(1, 1);
backgroundTilemapLayer.setAlpha(0.2);
// Add the music and start playing it on a loop
this.emitter.fireEvent(GameEventType.PLAY_SOUND, {key: "level_music", loop: true, holdReference: true});
// Add the tilemap // Add the tilemap
this.add.tilemap("level2"); let mainLayer = this.add.tilemap("level2")[1];
mainLayer.setYSort(true);
// Create the main game layer
let mainLayer = this.addLayer();
// Add a player // Add a player
let player = this.add.physics(Player, mainLayer, "platformer"); let player = this.add.physics(Player, mainLayer, "topdown");
let playerSprite = this.add.sprite("player", mainLayer); let playerSprite = this.add.sprite("player", mainLayer);
player.setSprite(playerSprite); player.setSprite(playerSprite);
@ -99,7 +86,7 @@ export default class SecondScene extends Scene {
pauseButton.setText("Pause"); pauseButton.setText("Pause");
pauseButton.setPosition(700, 400); pauseButton.setPosition(700, 400);
pauseButton.onClick = () => { pauseButton.onClick = () => {
this.layers.forEach((layer: Layer) => layer.setPaused(true)); this.sceneGraph.getLayers().forEach((layer: Layer) => layer.setPaused(true));
pauseLayer.enable(); pauseLayer.enable();
} }
@ -113,7 +100,7 @@ export default class SecondScene extends Scene {
resumeButton.setText("Resume"); resumeButton.setText("Resume");
resumeButton.setPosition(400, 200); resumeButton.setPosition(400, 200);
resumeButton.onClick = () => { resumeButton.onClick = () => {
this.layers.forEach((layer: Layer) => layer.setPaused(false)); this.sceneGraph.getLayers().forEach((layer: Layer) => layer.setPaused(false));
pauseLayer.disable(); pauseLayer.disable();
} }
} }