What's the proper way to destroy instance of Phaser.Game? - javascript

In the trivial case of creating and then destroying an instance of Phaser.Game there appears to be a memory leak. Below is a complete working example: click the button to create an instance, click again to destroy it. Repeatedly clicking the button causes memory usage to grow without bound. Is there something I'm missing about the phaser lifecycle that I should be doing instead?
I'm posting this as a code snippet rather than a jsfiddle because you need to look a a memory profiler or something like that to see the problem and so jsfiddle just complicates the matter.
<!doctype html>
<html>
<head>
<meta charset="UTF-8"/>
<title>test</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/phaser-ce/2.8.1/phaser.js">
</script>
</head>
<body>
<button id="button">Click</button>
<div id="canvas"></div>
<script>
window.onload = function() {
var d, n, game;
d = document.getElementById('button');
n = document.getElementById('canvas');
function preload() {
}
function create() {
}
function update() {
}
function handler() {
if(game) {
game.destroy();
game = null;
} else {
game = new Phaser.Game(800, 600, Phaser.AUTO, n, {
preload: preload,
create: create,
update: update
});
}
}
d.onclick = handler;
};
</script>
</body>
</html>

Answering (at least partially) my own question, the problem is in Phaser.CanvasPool. Whenever a new Phaser instance is created a new canvas is created and added to the pool. Destroying the instance dows not remove the canvas from the pool or mark it as available for re-use.
You can kinda-sorta hack this into working by doing something crude like setting Phaser.CanvasPool.pool = [] after calling game.destroy(), but that won't work if you have multiple phaser instances going.
If anyone knows what the correct workflow is supposed to be I'd love to know---Phaser.CanvasPool is one of phaser's points of contact with PIXI and all of those appear to be poorly documented.
EDIT: Found the source of the memory leak. It's Phaser.Utils.Debug.boot(), which adds a new canvas to the pool every time it's called, which by default is every time a phaser instance is created and booted.
The problem affects only WebGL-rendered canvases when enableDebug is enabled (which is the default).
For completeness, here's an edited version of the code above which disables debugging and therefore does not exhibit the memory leak:
<!doctype html>
<html>
<head>
<meta charset="UTF-8"/>
<title>test</title>
<script src="http://cdnjs.cloudflare.com/ajax/libs/phaser-ce/2.8.1/phaser.js"></script>
</head>
<body>
<button id="button">Click</button>
<div id="canvas"></div>
<script>
window.onload = function() {
var d, n, game;
d = document.getElementById('button');
n = document.getElementById('canvas');
function preload() {
}
function create() {
}
function update() {
}
function handler() {
if(game) {
game.destroy();
game = null;
} else {
game = new Phaser.Game({
width: 800,
height: 600,
renderer: Phaser.AUTO,
parent: n,
enableDebug: false,
state: {
preload: preload,
create: create,
update: update
},
});
}
}
d.onclick = handler;
};
</script>
</body>
</html>

Related

Phaser-3: Is there a way to move an image from one location to another while the program is running and so it is visible doing so?

i would like to create a battle system for an rpg game ,where an opening animation plays showing the battling characters move from the side of the screen to a location on the screen. Current code, assets and current running view provided below;
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>battle</title>
<script src="phaser.js"></script>
<style type="text/css">
body {
margin: 0;
}
</style>
</head>
<body>
<script type="text/javascript">
var config = {
type: Phaser.AUTO,
width: 1900,
height: 900,
physics: {
default: 'arcade',
arcade: {
gravity: { y: 0},
debug: false
}
},
scene: {
preload: preload,
create: create,
update: update,
}
};
var game = new Phaser.Game(config);
function preload(){
this.load.image("background","assets/battle background.png");
this.load.image("hydroBot","assets/water hydrant.png");
};
function create(){
const battle = this.add.image(0,0,"background").setOrigin(0,0);
const bot= this.add.image(1000,200,"hydroBot");
bot.setScale(5);
};
function update(){
};
</script>
</body>
water_hydrant/hydrobot
the battle background
the current view when running the code
much appreciated thanks :)
Yes, check for tween. You can move the image by using it.

song.play() returns "Uncaught TypeError: Cannot read property 'play' of undefined" for background music

I am trying to get background music playing behind my game using p5.js.
However, I have tried every variation I can possibly think of, trying new Audio, not having preLoad, etc. And whatever I do I still get the
Uncaught TypeError: Cannot read property 'play' of undefined" on my backgroundMusic.play();
I have tried to follow what the p5.js reference says to do.
let backgroundMusic;
function preLoad(){
backgroundMusic = loadSound("music.mp3");
}
function setup() {
createCanvas(600, 360);
backgroundMusic.play();
backgroundMusic.setVolume(10);
}
Here are few things i would like to add
You don't have to call the preload inside the setup, as mentioned in the above answer, because the setup is called by p5 after the preload, and if you will call the preload inside then p5 will again will call the setup and it will become a loop that will cause the stack to get overflow, you can read more about stack overflow here at this article
And here is what you should do to tackle this issue
Add p5 sound and p5 both because the loadSound is inside the p5 sound.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Play the music</title>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.1.9/p5.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.1.9/addons/p5.sound.min.js"></script>
<script>
let mySound;
function preload() {
mySound = loadSound("./yourfile.mp3");
// Todo : Add the path to your file above
}
function setup() {
let cnv = createCanvas(100, 100);
cnv.mousePressed(canvasPressed);
background(220);
text("tap here to play", 10, 20);
}
function canvasPressed() {
mySound.play();
}
</script>
</body>
</html>
Run the Above Code
you need to call preLoad() method inside the setup() to assign backGroundMusic.
let backgroundMusic;
function preLoad(){
backgroundMusic = loadSound("music.mp3");
}
function setup() {
createCanvas(600, 360);
preLoad(); //added
backgroundMusic.play();
backgroundMusic.setVolume(10);
}

game.state is undefined in Phaser 3 (TypeError)

I began coding a game in phaser and while getting the game states ready. It popped up a 'game.state is undefined' type error in the console. Not sure what to do as I've tried whatever I can to try to fix this problem. The code is given below.
The index.html file:
<!DOCTYPE html>
<html>
<head>
<title>Phaser Game</title>
<meta charset="utf-8">
<script src="phaser.min.js"></script>
<script src="state1.js"></script>
</head>
<body>
<script src="main.js"></script>
</body>
</html>
The Main.js file:
const game = new Phaser.Game(600, 400, Phaser.AUTO);
game.State.add('state1', demo.state1);
game.State.start('state1');
The state1.js file:
var demo = {};
demo.state1 = function(){};
demo.state1.prototype = {
preload: function(){},
create: function(){},
update: function(){}
};
There isn't state in game object. you should replace it with scene.
It's also better to use the standard way to create game object.
var config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 600,
height: 400,
scene: {
preload: function(){},
create: function(){},
update: function(){}
}
};
var game = new Phaser.Game(config);
More details can be found on the phaser docs
You can Find many useful examples here

JavaScript Phaser game doesn't load?

I'm normally a python guy, and although JavaScript isn't completely new to me, the Phaser game library is. I'm trying to make an archery game with Phaser, and although my game file isn't complete, to my knowledge this file should at least load a background image. Could someone help me figure out why it isn't loading anything? I'm using VSCode's live server extension to load it, if that helps.
Index HTML File
<!DOCTYPE html>
<html>
<head>
<meta charset = "UTF-8">
<title>Game</Title>
<script type = "text/javascript" src = "phaser.min.js"></script>
</head>
<body><script type="text/javascript" src="archery_game.js"></script></body>
</html>
Game file
const game = new Phaser.game(800, 600, Phaser.AUTO, '', {
preload: preload,
create: create,
update: update })
//Variables
let score = 0
let scoreText
let arrows
let player
function preload() {
//Load and define our images
game.load.image('archer', 'archer.png')
game.load.image('sky', 'sky.png')
game.load.image('ground', 'platform.png')
game.load.image('target', 'archery_target.png')
}
function create() {
//Implement physics
game.physics.startSystem(Phaser.physics.ARCADE)
//Add the sky sprite
game.add.sprite(0, 0, 'sky')
//Create the ground
platforms = game.add.group()
platforms.enableBody = true
let ground = platforms.create(0, game.world.height - 64, 'ground')
ground.scale.setTo(2, 2)
}
function update() {
//Update physics
}
You need to capitalize the Game constructor:
const game = new Phaser.game(800, 600...
should be
const game = new Phaser.Game(800, 600...
See
https://phaser.io/docs/2.6.2/Phaser.Game.html

Defining Position in Phaser

I'm making a very basic game in Javascript using the Phaser Directory. I have made games with Phaser many times before but this time I have come across an issue that is new to me and I've never had before. I've looked it up online and no one seems to have had this problem. In phaser it is telling me my "x" is not defined when I refer to x as a position. How would I go about defining x as a position or what error am I facing? I and currently using VS Code on mac with a Chrome browser and newest version of Phaser.
Thanks for the Help,
Murdoc
var game = new Phaser.Game(640, 360, Phaser.Auto);
var car1;
var GameState = {
preload: function(){
game.load.image("thecar1", "../assets/car_1.png");
//game.load.image("thecar2", "../assets/car_2.png");
//game.load.image("backgroundImg", "../assets/thebackground.png");
},
create: function(){
var car1 = game.add.sprite(200, 270, "thecar1");
//var car2 = game.add.sprite(200, 270, "thecar2");
/*game.input.keyboard.addKey(Phaser.Keyboard.W)
.onDown.add(car1Up);*/
game.input.keyboard.addKey(Phaser.Keyboard.A)
.onDown.add(car1Left);
/*game.input.keyboard.addKey(Phaser.Keyboard.S)
.onDown.add(car1Down);
game.input.keyboard.addKey(Phaser.Keyboard.D)
.onDown.add(car1Right);*/
},
update: function(){
}
};
function car1Left() {
car1.x = car1.x + 10;
}
game.state.add('GameState', GameState);
game.state.start('GameState');
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Pixel Soccer</title>
<script src="phaser.js"></script>
<script src="main.js"></script>
<style>
body {
background: white;
margin: 0;
padding: 0;
}
body canvas {
margin-left: auto;
margin-right: auto;
}
</style>
</head>
<body>
</body>
</html>
You're declaring the same variable twice. You're dealing with what's called "variable shadowing". When you do var car1 = game.add.sprite(200, 270, "thecar1"); in the create() function, the scope changes to function-only and the variable with the sprite you assign to it is only available in the scope of that function. The error basically comes to tell you that var car1 that you declared outside of the function scope is undefined (which it is). Try doing just car1 = game.add.sprite(200, 270, "thecar1"); inside create() and it should be fine.

Categories

Resources