foxroxracer Posted June 26, 2017 Share Posted June 26, 2017 Hello everybody! I'm having issues destroying a Phaser game with the game.destroy method. When destroying the game, somehow it wants to keep running the update loop, which gives null reference errors. Error in console: phaser.js:36338 Uncaught TypeError: Cannot read property 'update' of null at Phaser.Game.updateLogic (phaser.js:36338) at Phaser.Game.update (phaser.js:36280) at Phaser.RequestAnimationFrame.updateRAF (phaser.js:61979) at _onLoop (phaser.js:61962) If I go that line in the code it fails on this.stage.update(); I think it fails because game.destroy() already has set the stage to null, but why would it still update then? Version of Phaser: v2.6.2 I need to have phaser quit this way, without refreshing the browser, because it is part of an angularJS application. Code: var collectGameVariables = { dataFromZip: null, game: null, player: null, enemies: [], collectables: [], background1: null, background2: null, scoreText: null, score: 0, spriteScale: 0.2 * (window.devicePixelRatio / 3), playerSpriteScale: 0.4 * (window.devicePixelRatio / 3), backgroundScrollSpeed: 3, objectFallSpeed: 10, enemySpawnInterval: 500, collectableSpawnInterval: 1000, fallspeedReferenceResolution: 1000, enemySpawnTimer: null, collectiblesSpawnTimer: null, enemySpawnLoop: null, collectiblesSpawnLoop: null, objectsScaleMultiplier: 0.4, playerScaleMultiplier: 1.2, newScaleRatio: null, max_canvas_height: 1080, max_canvas_width: 1920, UI_elements_group: null, background_elements_group: null, SFX_hitEnemy: null, SFX_pickupCollectible: null, soundtrack: null, ArrowKeySensivity: 20, cursors: null, enableDesktopControls: false, isGameEnded: false, }; function startCollectGame(width, height, data) { console.log('Starting collect game'); collectGameVariables.game = new Phaser.Game(width, height, Phaser.CANVAS, 'container', { init: collect_init, preload: collect_preload, create: collect_create, update: collect_update }); collectGameVariables.dataFromZip = data; } function collect_init() { collect_setupScalingRatio(); collect_resetScore(); //collect_setupSFX(); if (collectGameVariables.game.device.desktop) { collectGameVariables.cursors = collectGameVariables.game.input.keyboard.createCursorKeys(); collectGameVariables.enableDesktopControls = true; } } function collect_preload() { collect_loadContentFromDataURIs(); } function collect_create() { collectGameVariables.game.physics.startSystem(Phaser.Physics.ARCADE); collectGameVariables.background_elements_group = collectGameVariables.game.add.group(); collectGameVariables.UI_elements_group = collectGameVariables.game.add.group(); collect_setupScoreText(); collect_setupBackground(); collect_setupPlayer(); //Spawn the enemies & collectibles collectGameVariables.enemySpawnTimer = collectGameVariables.game.time.events; collectGameVariables.collectiblesSpawnTimer = collectGameVariables.game.time.events; collectGameVariables.enemySpawnLoop = collectGameVariables.game.time.events.loop(collectGameVariables.enemySpawnInterval * (collectGameVariables.game.world.height / collectGameVariables.fallspeedReferenceResolution), function () { collect_spawnObject('enemy', collectGameVariables.enemies); }, this); collectGameVariables.collectiblesSpawnLoop = collectGameVariables.game.time.events.loop(collectGameVariables.collectableSpawnInterval * (collectGameVariables.game.world.height / collectGameVariables.fallspeedReferenceResolution), function () { collect_spawnObject('collectable', collectGameVariables.collectables); }, this); } function collect_update() { if (!collectGameVariables.isGameEnded) { if (collectGameVariables.enableDesktopControls) { collect_movePlayerAccordingToArrowKeys(); } else { collect_movePlayerAccordingToMouse(); } collect_updateEnemies(); collect_updateCollectible(); collect_scrollBackground(); if (collectGameVariables.game.physics) { collectGameVariables.game.physics.arcade.collide(collectGameVariables.player, collectGameVariables.enemies, collect_enemyCollidedWithPlayer); } if (collectGameVariables.game.physics) { collectGameVariables.game.physics.arcade.collide(collectGameVariables.player, collectGameVariables.collectables, collect_collectibleCollidedWithPlayer); } if (collectGameVariables.game.physics) { collectGameVariables.game.physics.arcade.collide(collectGameVariables.enemies, collectGameVariables.collectables, collect_enemyCollidedWithCollectible); } } else { console.log('game ended'); } } function collect_quit() { collectGameVariables.game.paused = true; collectGameVariables.isGameEnded = true; //Disable spawning sprites collectGameVariables.enemySpawnTimer.stop(true); collectGameVariables.collectiblesSpawnTimer.stop(true); collectGameVariables.game.physics.destroy(); collectGameVariables.game.world.removeAll(); console.log('Destroying game'); collectGameVariables.game.destroy(); EndGame(); } function collect_collectibleCollidedWithPlayer(player, collectible) { //SFX_pickupCollectible.play(); collectible.destroy(); collectGameVariables.score++; collectGameVariables.scoreText.setText(collectGameVariables.score); } function collect_enemyCollidedWithCollectible(enemy, collectible) { collectible.destroy(); } function collect_enemyCollidedWithPlayer(player, enemy) { //SFX_hitEnemy.play(); player.destroy(); collect_quit(); } function collect_movePlayerAccordingToArrowKeys() { var x_pos_input = collectGameVariables.player.position.x; var minBounds = collectGameVariables.player.width; var maxBounds = collectGameVariables.game.width - collectGameVariables.player.width; if (collectGameVariables.cursors.left.isDown) { x_pos_input -= collectGameVariables.ArrowKeySensivity; } if (collectGameVariables.cursors.right.isDown) { x_pos_input += collectGameVariables.ArrowKeySensivity; } if (x_pos_input < minBounds) { x_pos_input = minBounds; } if (x_pos_input > maxBounds) { x_pos_input = maxBounds; } collectGameVariables.player.x = x_pos_input; } function collect_movePlayerAccordingToMouse() { var x_pos_input = collectGameVariables.game.input.x; //Cap the position for the bounds var minBounds = collectGameVariables.player.width; var maxBounds = collectGameVariables.game.width - collectGameVariables.player.width; if (x_pos_input < minBounds) { x_pos_input = minBounds; } if (x_pos_input > maxBounds) { x_pos_input = maxBounds; } collectGameVariables.player.x = x_pos_input; } function collect_scrollBackground() { collectGameVariables.background1.position.y += collectGameVariables.backgroundScrollSpeed; collectGameVariables.background2.position.y += collectGameVariables.backgroundScrollSpeed; if (collectGameVariables.background1.position.y >= collectGameVariables.game.world.height) { //Move it to the top collectGameVariables.background1.position.y = collectGameVariables.background2.position.y - collectGameVariables.game.world.height; } if (collectGameVariables.background2.position.y >= collectGameVariables.game.world.height) { //Move it to the top collectGameVariables.background2.position.y = collectGameVariables.background1.position.y - collectGameVariables.game.world.height; } } function collect_loadContentFromDataURIs() { //Loading images collect_loadImage('player', collectGameVariables.dataFromZip[4]); collect_loadImage('enemy', collectGameVariables.dataFromZip[2]); collect_loadImage('background', collectGameVariables.dataFromZip[1]); collect_loadImage('collectable', collectGameVariables.dataFromZip[3]); //Loading audio //loadAudio('backgroundmusic', dataFromZip[5]); //loadAudio('pickupCollectible', dataFromZip[6]); //loadAudio('hitEnemy', dataFromZip[7]); collectGameVariables.game.load.start(); } function collect_loadImage(spriteKey, dataUri) { if (!collectGameVariables.game.cache.checkImageKey(spriteKey)) { collectGameVariables.game.load.image(spriteKey, dataUri); } } function collect_loadAudio(audioKey, dataUri) { if (!collectGameVariables.game.cache.checkSoundKey(audioKey)) { collectGameVariables.game.load.audio(audioKey, dataUri); } } function collect_setupScalingRatio() { var containerWidth = document.getElementById('container').offsetWidth; var containerHeight = document.getElementById('container').offsetHeight; var aspect_ratio = containerWidth / containerHeight; if (aspect_ratio > 1) { collectGameVariables.newScaleRatio = containerHeight / collectGameVariables.max_canvas_height; } else { collectGameVariables.newScaleRatio = containerWidth / collectGameVariables.max_canvas_width; } } function collect_resetScore() { collectGameVariables.score = 0; } function collect_setupSFX() { collectGameVariables.soundtrack = collectGameVariables.game.add.audio('backgroundmusic'); collectGameVariables.SFX_hitEnemy = collectGameVariables.game.add.audio('hitEnemy'); collectGameVariables.SFX_pickupCollectible = collectGameVariables.game.add.audio('pickupCollectible'); collectGameVariables.game.sound.setDecodedCallback([collectGameVariables.soundtrack, collectGameVariables.SFX_hitEnemy, collectGameVariables.SFX_pickupCollectible], collect_playSoundtrack, this); } function collect_playSoundtrack() { collectGameVariables.soundtrack.loopFull(1.0); } function collect_setupScoreText() { collectGameVariables.scoreText = collectGameVariables.game.add.text(collectGameVariables.game.world.centerX, collectGameVariables.game.world.top + 20, "0", { font: "65px Arial", fill: "#FFFFFF", align: "center" }); collectGameVariables.scoreText.anchor.setTo(0.5, 0); collectGameVariables.UI_elements_group.add(collectGameVariables.scoreText); } function collect_setupPlayer() { collectGameVariables.player = collectGameVariables.game.add.sprite(0, 0, 'player'); collectGameVariables.player.anchor.setTo(0.5); collectGameVariables.player.scale.setTo(collectGameVariables.newScaleRatio * collectGameVariables.playerScaleMultiplier); collectGameVariables.player.position.setTo(collectGameVariables.game.world.centerX, collectGameVariables.game.world.height - collectGameVariables.player.height); collectGameVariables.game.physics.enable(collectGameVariables.player, Phaser.Physics.ARCADE); } function collect_setupBackground() { collectGameVariables.background1 = collectGameVariables.game.add.sprite(0, 0, 'background'); collectGameVariables.background1.width = collectGameVariables.game.world.width; collectGameVariables.background1.height = collectGameVariables.game.world.height; collectGameVariables.background2 = collectGameVariables.game.add.sprite(0, 0 - collectGameVariables.game.world.height, 'background'); collectGameVariables.background2.width = collectGameVariables.game.world.width; collectGameVariables.background2.height = collectGameVariables.game.world.height; collectGameVariables.background_elements_group.add(collectGameVariables.background1); collectGameVariables.background_elements_group.add(collectGameVariables.background2); } function collect_spawnObject(objectSpriteName, objectCollection) { var object = collectGameVariables.game.add.sprite(Math.random() * collectGameVariables.game.width, -50, objectSpriteName); object.scale.set(collectGameVariables.newScaleRatio * collectGameVariables.objectsScaleMultiplier); var spawnPosition = object.width + (Math.random() * (collectGameVariables.game.width - (object.width * 2))); object.x = spawnPosition; object.anchor.setTo(0.5, 0.5); objectCollection.push(object); collectGameVariables.game.physics.enable(object, Phaser.Physics.ARCADE); } function collect_updateEnemies() { collectGameVariables.enemies.forEach(function (enemy) { enemy.position.y += (collectGameVariables.game.world.height / collectGameVariables.fallspeedReferenceResolution) * collectGameVariables.objectFallSpeed; if (enemy.position.y >= collectGameVariables.game.height) { enemy.destroy(); } }); } function collect_updateCollectible() { collectGameVariables.collectables.forEach(function (collectable) { collectable.position.y += (collectGameVariables.game.world.height / collectGameVariables.fallspeedReferenceResolution) * collectGameVariables.objectFallSpeed; if (collectable.position.y >= collectGameVariables.game.height) { collectable.destroy(); } }); } Thanks! Link to comment Share on other sites More sharing options...
samme Posted June 28, 2017 Share Posted June 28, 2017 You can't destroy a game from within the update loop itself. Try it via an event handler or setTimeout instead. Link to comment Share on other sites More sharing options...
ForgeableSum Posted July 1, 2017 Share Posted July 1, 2017 I wouldn't recommend using game.destroy in any circumstance. If you want to stop the game from running, shutdown the state with state.shutdown(). Link to comment Share on other sites More sharing options...
foxroxracer Posted July 3, 2017 Author Share Posted July 3, 2017 Thanks for the replies! I combined your answers and when the game needed to destroy itself, I first cleared the current state (with clearCurrentState()). And I destroyed the game in a setTimeout function. This method gave me no errors on quit anymore. collectGameVariables.game.state.clearCurrentState(); setTimeout( function () { collectGameVariables.game.destroy(); }, 5); Thanks for the help!! Link to comment Share on other sites More sharing options...
Recommended Posts