Reputation: 13
I'm kinda new to coding and I started building a Website with HTML & CSS and came pretty quickly up with the idea to create a game on my page. Because I'm still new to any programming language and only have some starter knowledge I worked a lot with ChatGPT and an example of phaser to edit the code and learn more JavaScript/phaser basics. Currently I'm trying to implement a whole new function instead of just editing code of the example. This function is supposed to give me a restart/respawn button, but I ran into the same issue with every solution I found.
https://html-test.jonaschmidt56.repl.co/gamepage.html
If you want to see the Game itself at its current stage.
This is my current code (all of it), last change I made was putting the restartGame function in the create function, before it was a lone function between update and hitBomb function.
The console always gives me the same error in the player = this.physics.add.sprite(100, 450, 'dude');
line of the restartGame function:
[Error] TypeError: undefined is not an object (evaluating 'this.physics.add')
restartGame (script2.js:165)
(anonymous function) (script2.js:147)
emit (phaser.js:201)
processDownEvents (phaser.js:103739)
update (phaser.js:103443)
updateInputPlugins (phaser.js:102156)
onMouseDown (phaser.js:102357)
(anonymous function) (phaser.js:115867)
var config = {
type: Phaser.AUTO,
width: 1280,
height: 720,
parent: 'game-container',
physics: {
default: 'arcade',
arcade: {
gravity: {
y: 300
},
debug: false
}
},
scene: {
preload: preload,
create: create,
update: update
}
};
var player;
var coins;
var bombs;
var platforms;
var cursors;
var score = 0;
var gameOver = false;
var scoreText;
var keyW;
var keyA;
var keyS;
var keyD;
var restartButton;
var game = new Phaser.Game(config);
function preload() {
this.load.image('background', 'assets/background.png');
this.load.image('ground', 'assets/platform.png');
this.load.spritesheet('coin', 'assets/coin.png', {
frameWidth: 20,
frameHeight: 24
});
this.load.image('bomb', 'assets/bomb.png');
this.load.spritesheet('dude', 'assets/dude.png', {
frameWidth: 32,
frameHeight: 48
});
}
function create() {
// cursor keys für WASD
cursors = this.input.keyboard.createCursorKeys();
keyW = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.W);
keyA = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.A);
keyS = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.S);
keyD = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.D);
// A simple background for our game
const background = this.add.tileSprite(0, 0, 1280, 720, 'background');
background.tileScaleX = 1;
background.tileScaleY = 1;
background.setOrigin(0, 0);
// The platforms group contains the ground and the 2 ledges we can jump on
platforms = this.physics.add.staticGroup();
// Here we create the ground.
// Scale it to fit the width of the game (the original sprite is 400x32 in size)
platforms.create(400, 700, 'ground').setScale(2).refreshBody();
platforms.create(900, 700, 'ground').setScale(2).refreshBody();
// Now let's create some ledges
platforms.create(600, 600, 'ground');
platforms.create(600, 300, 'ground');
platforms.create(50, 250, 'ground');
platforms.create(900, 420, 'ground');
platforms.create(1100, 420, 'ground');
// The player and its settings
player = this.physics.add.sprite(100, 450, 'dude');
// Player physics properties. Give the little guy a slight bounce.
player.setBounce(0.1);
player.setCollideWorldBounds(true);
// Our player animations, turning, walking left and walking right.
this.anims.create({
key: 'left',
frames: this.anims.generateFrameNumbers('dude', {
start: 0,
end: 3
}),
frameRate: 10,
repeat: -1
});
this.anims.create({
key: 'turn',
frames: [{
key: 'dude',
frame: 4
}],
frameRate: 20
});
this.anims.create({
key: 'right',
frames: this.anims.generateFrameNumbers('dude', {
start: 5,
end: 8
}),
frameRate: 10,
repeat: -1
});
// Input Events
cursors = this.input.keyboard.createCursorKeys();
// Some coins to collect, 12 in total, evenly spaced 70 pixels apart along the x axis
coins = this.physics.add.group({
key: 'coin',
repeat: 11,
setXY: {
x: 0,
y: 0,
stepX: 70
}
});
this.anims.create({
key: 'spin',
frames: this.anims.generateFrameNumbers('coin', {
start: 0,
end: 3
}),
frameRate: 10,
repeat: -1,
});
coins.children.iterate(function(child) {
child.play('spin');
child.setBounceY(Phaser.Math.FloatBetween(0.1, 0.3));
child.x += Phaser.Math.Between(0, 400);
child.y += Phaser.Math.Between(0, 200);
});
bombs = this.physics.add.group();
// The score
scoreText = this.add.text(32, 16, 'Score: 0', {
fontSize: '32px',
fill: '#fff',
fontFamily: 'Oswald, sans-serif'
});
// Collide the player and the coins with the platforms
this.physics.add.collider(player, platforms);
this.physics.add.collider(coins, platforms);
this.physics.add.collider(bombs, platforms);
this.physics.resume();
restartButton = this.add.text(600, 350, 'Respawn', {
fontSize: '32px',
fill: '#fff',
fontFamily: 'Oswald, sans-serif'
});
restartButton.setInteractive();
restartButton.on('pointerdown', function() {
restartGame.call(this); // Call restartGame with the correct context
});
function restartGame() {
score = 0;
gameOver = false;
coins.clear(true, true);
bombs.clear(true, true);
player.setX(100);
player.setY(450);
player.clearTint();
//player = this.physics.add.sprite(100, 450, 'dude');
//player.setBounce(0.1);
//player.setCollideWorldBounds(true);
player = this.physics.add.sprite(100, 450, 'dude');
player.setBounce(0.1);
player.setCollideWorldBounds(true);
coins.children.iterate(function(child) {
child.enableBody(true, Phaser.Math.Between(0, 400), Phaser.Math.Between(0, 200), true, true);
child.play('spin');
child.setBounceY(Phaser.Math.FloatBetween(0.1, 0.3));
});
restartButton.setVisible(false);
this.physics.add.collider(player, platforms);
this.physics.add.collider(coins, platforms);
this.physics.add.collider(bombs, platforms);
console.log(restartGame);
}
}
function update() {
if (gameOver) {
return;
}
if ((cursors.left.isDown || keyA.isDown) && !(cursors.right.isDown || keyD.isDown)) {
player.setVelocityX(-160);
player.anims.play('left', true);
} else if ((cursors.right.isDown || keyD.isDown) && !(cursors.left.isDown || keyA.isDown)) {
player.setVelocityX(160);
player.anims.play('right', true);
} else {
player.setVelocityX(0);
player.anims.play('turn');
}
if ((cursors.up.isDown || keyW.isDown) && player.body.touching.down) {
player.setVelocityY(-330);
}
if (cursors.down.isDown || keyS.isDown) {
player.setVelocityY(330);
}
// Checks to see if the player overlaps with any of the coins, if he does call the collectCoin functionm
this.physics.add.overlap(player, coins, collectCoin, null, this);
this.physics.add.collider(player, bombs, hitBomb, null, this);
}
function collectCoin(player, coin) {
coin.disableBody(true, true);
// Add and update the score
score += 1;
scoreText.setText('Score: ' + score);
if (coins.countActive(true) === 0) {
// A new batch of coins to collect
coins.children.iterate(function(child) {
child.enableBody(true, child.x, 0, true, true);
});
var x = (player.x < 400) ? Phaser.Math.Between(400, 800) : Phaser.Math.Between(0, 400);
var bomb = bombs.create(x, 16, 'bomb');
bomb.setBounce(1);
bomb.setCollideWorldBounds(true);
bomb.setVelocity(Phaser.Math.Between(-200, 200), 20);
bomb.allowGravity = false;
}
}
function restartGame(scene, physics) {
score = 0;
gameOver = false;
coins.clear(true, true);
bombs.clear(true, true);
player.setX(100);
player.setY(450);
player.clearTint();
//player = this.physics.add.sprite(100, 450, 'dude');
//player.setBounce(0.1);
//player.setCollideWorldBounds(true);
player = physics.add.sprite(100, 450, 'dude'); // Use 'scene' to access physics
player.setBounce(0.1);
player.setCollideWorldBounds(true);
coins.children.iterate(function(child) {
child.enableBody(true, Phaser.Math.Between(0, 400), Phaser.Math.Between(0, 200), true, true);
child.play('spin');
child.setBounceY(Phaser.Math.FloatBetween(0.1, 0.3));
});
restartButton.setVisible(false);
this.physics.add.collider(player, platforms);
this.physics.add.collider(coins, platforms);
this.physics.add.collider(bombs, platforms);
console.log(restartGame);
}
function hitBomb(player, bomb) {
this.physics.pause();
player.setTint(0xff0000);
player.anims.play('turn');
player.anims.stop();
gameOver = true;
restartButton.setVisible(true);
}
Upvotes: 1
Views: 157
Reputation: 14720
The solution is to pass the scene / this
to the eventlistener (link to the documentation), and pass the function as a function like seens in the example:
restartButton.on('pointerdown', restartGame, this);
If you want don't want to pass the callback function
directly, as seen, you could do this.
restartButton.on('pointerdown', function() {
restartGame.call(this); // Call restartGame with the correct context
}, this); // <-- still passing `this` as the context
Or you could use an arrow function, since the arrow function, doesn't have its own this
context ():
restartButton.on('pointerdown', () => {
restartGame.call(this);
}); // <-- no need for `this`
Info: This article / documentation explains the javascript nuances, of the last two code snipplets. Basically: "...In arrow functions,
this
retains the value of the enclosing lexical context'sthis
...."
P.s.: For future reference I would suggest reading this StackoverFlow howto, on how to improve code examples for questions on Stackoverflow. Apart from helping us answer them faster, it can help you, while debugging, to find the problem/issue.
Update:
Well the issue is, that on hit (in the function hitBomb
), you are setting many things, and some of them you are not setting back on restart:
So in the function restartGame
, there are somethings to do:
player.clearTint();
this.physics.resume();
.this
on the eventlistener restartButton.on('pointerdown', restartGame, this);
in the create
functioncoins.clear(true, true);
from the restartGame
function, since you still need them.Upvotes: 0