diff --git a/src/DataTypes/Map.ts b/src/DataTypes/Map.ts index e3cd876..29c11f1 100644 --- a/src/DataTypes/Map.ts +++ b/src/DataTypes/Map.ts @@ -1,6 +1,6 @@ import Collection from "./Collection"; -export default class Map implements Collection{ +export default class Map implements Collection { private map: Record; constructor(){ @@ -30,4 +30,8 @@ export default class Map implements Collection{ forEach(func: Function): void { Object.keys(this.map).forEach(key => func(key)); } + + clear(): void { + this.forEach((key: string) => delete this.map[key]); + } } \ No newline at end of file diff --git a/src/MainScene.ts b/src/MainScene.ts index 0373fed..f1b2cfe 100644 --- a/src/MainScene.ts +++ b/src/MainScene.ts @@ -7,6 +7,7 @@ import Vec2 from "./DataTypes/Vec2"; import UIElement from "./Nodes/UIElement"; import Button from "./Nodes/UIElements/Button"; import Layer from "./Scene/Layer"; +import SecondScene from "./SecondScene"; export default class MainScene extends Scene { @@ -40,7 +41,8 @@ export default class MainScene extends Scene { backgroundTilemap.getLayer().setAlpha(0.5); // Add the music and start playing it on a loop - this.add.audio("level_music").play(true); + let music = this.add.audio("level_music"); + music.play(true); // Add the tilemap this.add.tilemap("platformer", OrthogonalTilemap); @@ -114,10 +116,19 @@ export default class MainScene extends Scene { let resumeButton = this.add.uiElement(Button, pauseLayer); resumeButton.setSize(100, 50); resumeButton.setText("Resume"); - resumeButton.setPosition(400, 200); + resumeButton.setPosition(360, 150); resumeButton.onClick = () => { this.layers.forEach((layer: Layer) => layer.setPaused(false)); pauseLayer.disable(); } + + let switchButton = this.add.uiElement(Button, pauseLayer); + switchButton.setSize(140, 50); + switchButton.setText("Change Scene"); + switchButton.setPosition(340, 190); + switchButton.onClick = () => { + music.stop(); + this.sceneManager.changeScene(SecondScene); + } } } \ No newline at end of file diff --git a/src/Nodes/Graphics/Rect.ts b/src/Nodes/Graphics/Rect.ts index f488962..b1534a4 100644 --- a/src/Nodes/Graphics/Rect.ts +++ b/src/Nodes/Graphics/Rect.ts @@ -14,6 +14,8 @@ export default class Rect extends Graphic { render(ctx: CanvasRenderingContext2D): void { let origin = this.getViewportOriginWithParallax(); + console.log(origin.toFixed()); + ctx.fillStyle = this.color.toStringRGBA(); ctx.fillRect(this.position.x - origin.x, this.position.y - origin.y, this.size.x, this.size.y); } diff --git a/src/ResourceManager/ResourceManager.ts b/src/ResourceManager/ResourceManager.ts index 58336cd..52668e4 100644 --- a/src/ResourceManager/ResourceManager.ts +++ b/src/ResourceManager/ResourceManager.ts @@ -108,6 +108,23 @@ export default class ResourceManager { } + unloadAllResources(): void { + this.loading = false; + this.justLoaded = false; + + this.imagesLoaded = 0; + this.imagesToLoad = 0; + this.images.clear(); + + this.tilemapsLoaded = 0; + this.tilemapsToLoad = 0; + this.tilemaps.clear(); + + this.audioLoaded = 0; + this.audioToLoad = 0; + this.audioBuffers.clear(); + } + private loadTilemapsFromQueue(onFinishLoading: Function){ this.tilemapsToLoad = this.tilemapLoadingQueue.getSize(); this.tilemapsLoaded = 0; diff --git a/src/Scene/Scene.ts b/src/Scene/Scene.ts index ce68630..e3737f4 100644 --- a/src/Scene/Scene.ts +++ b/src/Scene/Scene.ts @@ -9,6 +9,7 @@ import FactoryManager from "./Factories/FactoryManager"; import Tilemap from "../Nodes/Tilemap"; import ResourceManager from "../ResourceManager/ResourceManager"; import GameLoop from "../Loop/GameLoop"; +import SceneManager from "./SceneManager"; export default class Scene{ protected layers: Stack; @@ -16,6 +17,7 @@ export default class Scene{ protected viewport: Viewport; protected running: boolean; protected game: GameLoop; + protected sceneManager: SceneManager; protected tilemaps: Array; protected sceneGraph: SceneGraph; @@ -24,13 +26,14 @@ export default class Scene{ public add: FactoryManager; public load: ResourceManager; - constructor(viewport: Viewport, game: GameLoop){ + constructor(viewport: Viewport, sceneManager: SceneManager, game: GameLoop){ this.layers = new Stack(10); this.worldSize = new Vec2(1600, 1000); this.viewport = viewport; this.viewport.setBounds(0, 0, 2560, 1280); this.running = false; this.game = game; + this.sceneManager = sceneManager; this.tilemaps = new Array(); this.sceneGraph = new SceneGraphArray(this.viewport, this); diff --git a/src/Scene/SceneManager.ts b/src/Scene/SceneManager.ts index ba2327f..556f6c2 100644 --- a/src/Scene/SceneManager.ts +++ b/src/Scene/SceneManager.ts @@ -16,8 +16,8 @@ export default class SceneManager{ this.game = game; } - public addScene(constr: new (...args: any) => T){ - let scene = new constr(this.viewport, this.game); + public addScene(constr: new (...args: any) => T): void { + let scene = new constr(this.viewport, this, this.game); this.currentScene = scene; // Enqueue all scene asset loads @@ -27,7 +27,18 @@ export default class SceneManager{ this.resourceManager.loadResourcesFromQueue(() => { scene.startScene(); scene.setRunning(true); - }) + }); + } + + public changeScene(constr: new (...args: any) => T): void { + // unload current scene + this.currentScene.unloadScene(); + + this.resourceManager.unloadAllResources(); + + this.viewport.setPosition(0, 0); + + this.addScene(constr); } public render(ctx: CanvasRenderingContext2D){ diff --git a/src/SceneGraph/Viewport.ts b/src/SceneGraph/Viewport.ts index e048d1b..e404a09 100644 --- a/src/SceneGraph/Viewport.ts +++ b/src/SceneGraph/Viewport.ts @@ -25,7 +25,7 @@ export default class Viewport{ this.position.set(vecOrX.x, vecOrX.y); } else { this.position.set(vecOrX, y); - } + } } getSize(): Vec2{ diff --git a/src/SecondScene.ts b/src/SecondScene.ts new file mode 100644 index 0000000..79e47b1 --- /dev/null +++ b/src/SecondScene.ts @@ -0,0 +1,123 @@ +import Scene from "./Scene/Scene"; +import OrthogonalTilemap from "./Nodes/Tilemaps/OrthogonalTilemap"; +import Player from "./Player"; +import Rect from "./Nodes/Graphics/Rect"; +import Color from "./Utils/Color"; +import Vec2 from "./DataTypes/Vec2"; +import UIElement from "./Nodes/UIElement"; +import Button from "./Nodes/UIElements/Button"; +import Layer from "./Scene/Layer"; + +export default class SecondScene extends Scene { + + loadScene(){ + this.load.tilemap("level2", "assets/tilemaps/OtherMap.json"); + this.load.tilemap("background2", "assets/tilemaps/OtherBackground.json"); + this.load.image("player", "assets/sprites/player.png"); + this.load.audio("player_jump", "assets/sounds/jump-3.wav"); + this.load.audio("level_music", "assets/sounds/level.wav"); + + let loadingScreen = this.addLayer(); + let box = this.add.graphic(Rect, loadingScreen, new Vec2(200, 300), new Vec2(400, 60)); + box.setColor(new Color(0, 0, 0)); + let bar = this.add.graphic(Rect, loadingScreen, new Vec2(205, 305), new Vec2(0, 50)); + bar.setColor(new Color(255, 100, 0)); + + this.load.onLoadProgress = (percentProgress: number) => { + bar.setSize(295 * percentProgress, bar.getSize().y); + } + + this.load.onLoadComplete = () => { + loadingScreen.disable(); + } + } + + startScene(){ + // Add the background tilemap + let backgroundTilemap = this.add.tilemap("background2", OrthogonalTilemap)[0]; + // ...and make it have parallax + backgroundTilemap.getLayer().setParallax(1, 1); + backgroundTilemap.getLayer().setAlpha(0.2); + + // Add the music and start playing it on a loop + this.add.audio("level_music").play(true); + + // Add the tilemap + this.add.tilemap("level2", OrthogonalTilemap); + + // Create the main game layer + let mainLayer = this.addLayer(); + + // Add a player + let player = this.add.physics(Player, mainLayer, "platformer"); + let playerSprite = this.add.sprite("player", mainLayer); + player.setSprite(playerSprite); + + // TODO - Should sound playing be handled with events? + let playerJumpSound = this.add.audio("player_jump"); + player.jumpSound = playerJumpSound; + + this.viewport.follow(player); + + // Initialize UI + let uiLayer = this.addLayer(); + uiLayer.setParallax(0, 0); + + let recordButton = this.add.uiElement(Button, uiLayer); + recordButton.setSize(100, 50); + recordButton.setText("Record"); + recordButton.setPosition(400, 30); + recordButton.onClickEventId = "record_button_press"; + + let stopButton = this.add.uiElement(Button, uiLayer); + stopButton.setSize(100, 50); + stopButton.setText("Stop"); + stopButton.setPosition(550, 30); + stopButton.onClickEventId = "stop_button_press"; + + let playButton = this.add.uiElement(Button, uiLayer); + playButton.setSize(100, 50); + playButton.setText("Play"); + playButton.setPosition(700, 30); + playButton.onClickEventId = "play_button_press"; + + let cycleFramerateButton = this.add.uiElement(Button, uiLayer); + cycleFramerateButton.setSize(150, 50); + cycleFramerateButton.setText("Cycle FPS"); + cycleFramerateButton.setPosition(5, 400); + let i = 0; + let fps = [15, 30, 60]; + cycleFramerateButton.onClick = () => { + this.game.setMaxFPS(fps[i]); + i = (i + 1) % 3; + } + + // Pause Menu + let pauseLayer = this.addLayer(); + pauseLayer.setParallax(0, 0); + pauseLayer.disable(); + + let pauseButton = this.add.uiElement(Button, uiLayer); + pauseButton.setSize(100, 50); + pauseButton.setText("Pause"); + pauseButton.setPosition(700, 400); + pauseButton.onClick = () => { + this.layers.forEach((layer: Layer) => layer.setPaused(true)); + pauseLayer.enable(); + } + + let modalBackground = this.add.uiElement(UIElement, pauseLayer); + modalBackground.setSize(400, 200); + modalBackground.setBackgroundColor(new Color(0, 0, 0, 0.4)); + modalBackground.setPosition(200, 100); + + let resumeButton = this.add.uiElement(Button, pauseLayer); + resumeButton.setSize(100, 50); + resumeButton.setText("Resume"); + resumeButton.setPosition(400, 200); + resumeButton.onClick = () => { + this.layers.forEach((layer: Layer) => layer.setPaused(false)); + pauseLayer.disable(); + } + } +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index bcc77d0..dcc62a5 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,7 +2,6 @@ "files": [ "src/main.ts", "src/Player.ts", - "src/PlayerSprite.ts", "src/DataTypes/Tilesets/TiledData.ts", "src/DataTypes/Tilesets/Tileset.ts",