重新启动状态后的空引用
Null Reference after restarting a State
我用 Phaser 创建了一个小游戏用于演示目的。在你赢了或输了之后,你可以重新开始游戏。这是通过状态完成的。当我在游戏重新启动后尝试发射子弹时,出现空引用错误并且游戏冻结。出现空引用似乎是因为this.game
属性在状态重启后类没有正确设置
var PhaserGame = function () {
this.background = null;
this.stars = null;
this.player = null;
this.enemies = null;
this.cursors = null;
this.speed = 300;
this.weapons = [];
this.currentWeapon = 0;
this.weaponName = null;
this.score = 0;
};
PhaserGame.prototype = {
init: function () {
this.game.renderer.renderSession.roundPixels = true;
this.physics.startSystem(Phaser.Physics.ARCADE);
},
preload: function () {
this.game.time.advancedTiming = true;
},
create: function () {
this.background = this.add.tileSprite(0, 0, this.game.width, this.game.height, 'background');
this.background.autoScroll(-40, 0);
this.stars = this.add.tileSprite(0, 0, this.game.width, this.game.height, 'stars');
this.stars.autoScroll(-60, 0);
this.weapons.push(new Weapon.SingleBullet(this.game));
//this.weapons.push(new Weapon.FrontAndBack(this.game));
this.weapons.push(new Weapon.ThreeWay(this.game));
//this.weapons.push(new Weapon.EightWay(this.game));
this.weapons.push(new Weapon.ScatterShot(this.game));
this.weapons.push(new Weapon.Beam(this.game));
this.weapons.push(new Weapon.SplitShot(this.game));
//this.weapons.push(new Weapon.Pattern(this.game));
this.weapons.push(new Weapon.Rockets(this.game));
this.weapons.push(new Weapon.ScaleBullet(this.game));
//this.weapons.push(new Weapon.Combo1(this.game));
//this.weapons.push(new Weapon.Combo2(this.game));
this.currentWeapon = 0;
for (var i = 1; i < this.weapons.length; i++)
{
this.weapons[i].visible = false;
}
this.player = this.add.existing(new Spaceship(this.game, 100, 200, 'player'));
this.player.events.onKilled.add(this.toGameOver, this);
this.physics.arcade.enable(this.player);
this.player.body.collideWorldBounds = true;
this.player.animations.add('flame', [0, 1, 2, 3], 10, true);
this.player.animations.play('flame');
//Enemies
this.enemies = this.add.group();
//Enable Physics for Enemies
//this.physics.arcade.enable(this.enemies);
this.enemies.enableBody = true;
for (var i = 0; i < 24; i++) {
//create a star inside the group
var enemy = this.enemies.add(new Enemy(this.game, 1000 + (i * 50), 10 + Math.random() * 300, 'enemy'));
enemy.events.onKilled.add(this.raiseCounter, this);
}
//this.weaponName = this.add.bitmapText(8, 364, 'shmupfont', "ENTER = Next Weapon", 24);
// Cursor keys to fly + space to fire
this.cursors = this.input.keyboard.createCursorKeys();
this.input.keyboard.addKeyCapture([ Phaser.Keyboard.SPACEBAR ]);
var changeKey = this.input.keyboard.addKey(Phaser.Keyboard.ENTER);
changeKey.onDown.add(this.nextWeapon, this);
},
nextWeapon: function () {
// Tidy-up the current weapon
this.weapons[this.currentWeapon].visible = false;
this.weapons[this.currentWeapon].callAll('reset', null, 0, 0);
this.weapons[this.currentWeapon].setAll('exists', false);
// Activate the new one
this.currentWeapon++;
if (this.currentWeapon === this.weapons.length)
{
this.currentWeapon = 0;
}
this.weapons[this.currentWeapon].visible = true;
//this.weaponName.text = this.weapons[this.currentWeapon].name;
},
enemyHit: function (bullet, enemy) {
bullet.kill();
enemy.dealDamage(2);
},
playerHit: function (player, enemy) {
player.dealDamage(10);
enemy.dealDamage(1);
},
raiseCounter: function () {
this.score++;
},
toGameOver: function () {
this.game.state.start('GameOver', true, false, this.score);
},
update: function () {
//Framerate
this.game.debug.text(this.time.fps || '--', 2, 14, "#00ff00");
this.game.debug.text('Health: ' + this.player.health || 'Health: ---', 2, 30, "#00ff00");
this.game.debug.text('Counter: ' + this.score || 'Counter: ---', 2, 44, "#00ff00");
this.game.physics.arcade.overlap(this.weapons[this.currentWeapon], this.enemies, this.enemyHit, null, this);
this.game.physics.arcade.overlap(this.player, this.enemies, this.playerHit, null, this);
this.player.body.velocity.set(0);
this.enemies.setAll('body.velocity.x', -50);
if (this.cursors.left.isDown)
{
this.player.body.velocity.x = -this.speed;
}
else if (this.cursors.right.isDown)
{
this.player.body.velocity.x = this.speed;
}
if (this.cursors.up.isDown)
{
this.player.body.velocity.y = -this.speed;
}
else if (this.cursors.down.isDown)
{
this.player.body.velocity.y = this.speed;
}
if (this.input.keyboard.isDown(Phaser.Keyboard.SPACEBAR))
{
this.weapons[this.currentWeapon].fire(this.player);
}
}
};
武器-类取自Phaser-Coding-Tips 7:
Weapon.SingleBullet = function (game) {
console.log(game);
Phaser.Group.call(this, game, game.world, 'Single Bullet', false, true, Phaser.Physics.ARCADE);
this.nextFire = 0;
this.bulletSpeed = 600;
this.fireRate = 200;
for (var i = 0; i < 64; i++)
{
this.add(new Bullet(game, 'bullet5'), true);
}
return this;
};
Weapon.SingleBullet.prototype = Object.create(Phaser.Group.prototype);
Weapon.SingleBullet.prototype.constructor = Weapon.SingleBullet;
Weapon.SingleBullet.prototype.fire = function (source) {
//Here occurs the problem, because this.game is null after restarting the state
if (this.game.time.time < this.nextFire) { return; }
var x = source.x + 50;
var y = source.y + 15;
this.getFirstExists(false).fire(x, y, 0, this.bulletSpeed, 0, 0);
this.nextFire = this.game.time.time + this.fireRate;
};
问题出现在所有武器 类 重启状态后一致
在create
方法的开头,在weapons
被填充之前,我忘了清空数组。有趣的是:我之前尝试过清空数组,但没有用。当我记录 weapons
的长度时,它突然开始按预期工作。可能是 javascript 引擎做了一个奇怪的优化。
我用 Phaser 创建了一个小游戏用于演示目的。在你赢了或输了之后,你可以重新开始游戏。这是通过状态完成的。当我在游戏重新启动后尝试发射子弹时,出现空引用错误并且游戏冻结。出现空引用似乎是因为this.game
属性在状态重启后类没有正确设置
var PhaserGame = function () {
this.background = null;
this.stars = null;
this.player = null;
this.enemies = null;
this.cursors = null;
this.speed = 300;
this.weapons = [];
this.currentWeapon = 0;
this.weaponName = null;
this.score = 0;
};
PhaserGame.prototype = {
init: function () {
this.game.renderer.renderSession.roundPixels = true;
this.physics.startSystem(Phaser.Physics.ARCADE);
},
preload: function () {
this.game.time.advancedTiming = true;
},
create: function () {
this.background = this.add.tileSprite(0, 0, this.game.width, this.game.height, 'background');
this.background.autoScroll(-40, 0);
this.stars = this.add.tileSprite(0, 0, this.game.width, this.game.height, 'stars');
this.stars.autoScroll(-60, 0);
this.weapons.push(new Weapon.SingleBullet(this.game));
//this.weapons.push(new Weapon.FrontAndBack(this.game));
this.weapons.push(new Weapon.ThreeWay(this.game));
//this.weapons.push(new Weapon.EightWay(this.game));
this.weapons.push(new Weapon.ScatterShot(this.game));
this.weapons.push(new Weapon.Beam(this.game));
this.weapons.push(new Weapon.SplitShot(this.game));
//this.weapons.push(new Weapon.Pattern(this.game));
this.weapons.push(new Weapon.Rockets(this.game));
this.weapons.push(new Weapon.ScaleBullet(this.game));
//this.weapons.push(new Weapon.Combo1(this.game));
//this.weapons.push(new Weapon.Combo2(this.game));
this.currentWeapon = 0;
for (var i = 1; i < this.weapons.length; i++)
{
this.weapons[i].visible = false;
}
this.player = this.add.existing(new Spaceship(this.game, 100, 200, 'player'));
this.player.events.onKilled.add(this.toGameOver, this);
this.physics.arcade.enable(this.player);
this.player.body.collideWorldBounds = true;
this.player.animations.add('flame', [0, 1, 2, 3], 10, true);
this.player.animations.play('flame');
//Enemies
this.enemies = this.add.group();
//Enable Physics for Enemies
//this.physics.arcade.enable(this.enemies);
this.enemies.enableBody = true;
for (var i = 0; i < 24; i++) {
//create a star inside the group
var enemy = this.enemies.add(new Enemy(this.game, 1000 + (i * 50), 10 + Math.random() * 300, 'enemy'));
enemy.events.onKilled.add(this.raiseCounter, this);
}
//this.weaponName = this.add.bitmapText(8, 364, 'shmupfont', "ENTER = Next Weapon", 24);
// Cursor keys to fly + space to fire
this.cursors = this.input.keyboard.createCursorKeys();
this.input.keyboard.addKeyCapture([ Phaser.Keyboard.SPACEBAR ]);
var changeKey = this.input.keyboard.addKey(Phaser.Keyboard.ENTER);
changeKey.onDown.add(this.nextWeapon, this);
},
nextWeapon: function () {
// Tidy-up the current weapon
this.weapons[this.currentWeapon].visible = false;
this.weapons[this.currentWeapon].callAll('reset', null, 0, 0);
this.weapons[this.currentWeapon].setAll('exists', false);
// Activate the new one
this.currentWeapon++;
if (this.currentWeapon === this.weapons.length)
{
this.currentWeapon = 0;
}
this.weapons[this.currentWeapon].visible = true;
//this.weaponName.text = this.weapons[this.currentWeapon].name;
},
enemyHit: function (bullet, enemy) {
bullet.kill();
enemy.dealDamage(2);
},
playerHit: function (player, enemy) {
player.dealDamage(10);
enemy.dealDamage(1);
},
raiseCounter: function () {
this.score++;
},
toGameOver: function () {
this.game.state.start('GameOver', true, false, this.score);
},
update: function () {
//Framerate
this.game.debug.text(this.time.fps || '--', 2, 14, "#00ff00");
this.game.debug.text('Health: ' + this.player.health || 'Health: ---', 2, 30, "#00ff00");
this.game.debug.text('Counter: ' + this.score || 'Counter: ---', 2, 44, "#00ff00");
this.game.physics.arcade.overlap(this.weapons[this.currentWeapon], this.enemies, this.enemyHit, null, this);
this.game.physics.arcade.overlap(this.player, this.enemies, this.playerHit, null, this);
this.player.body.velocity.set(0);
this.enemies.setAll('body.velocity.x', -50);
if (this.cursors.left.isDown)
{
this.player.body.velocity.x = -this.speed;
}
else if (this.cursors.right.isDown)
{
this.player.body.velocity.x = this.speed;
}
if (this.cursors.up.isDown)
{
this.player.body.velocity.y = -this.speed;
}
else if (this.cursors.down.isDown)
{
this.player.body.velocity.y = this.speed;
}
if (this.input.keyboard.isDown(Phaser.Keyboard.SPACEBAR))
{
this.weapons[this.currentWeapon].fire(this.player);
}
}
};
武器-类取自Phaser-Coding-Tips 7:
Weapon.SingleBullet = function (game) {
console.log(game);
Phaser.Group.call(this, game, game.world, 'Single Bullet', false, true, Phaser.Physics.ARCADE);
this.nextFire = 0;
this.bulletSpeed = 600;
this.fireRate = 200;
for (var i = 0; i < 64; i++)
{
this.add(new Bullet(game, 'bullet5'), true);
}
return this;
};
Weapon.SingleBullet.prototype = Object.create(Phaser.Group.prototype);
Weapon.SingleBullet.prototype.constructor = Weapon.SingleBullet;
Weapon.SingleBullet.prototype.fire = function (source) {
//Here occurs the problem, because this.game is null after restarting the state
if (this.game.time.time < this.nextFire) { return; }
var x = source.x + 50;
var y = source.y + 15;
this.getFirstExists(false).fire(x, y, 0, this.bulletSpeed, 0, 0);
this.nextFire = this.game.time.time + this.fireRate;
};
问题出现在所有武器 类 重启状态后一致
在create
方法的开头,在weapons
被填充之前,我忘了清空数组。有趣的是:我之前尝试过清空数组,但没有用。当我记录 weapons
的长度时,它突然开始按预期工作。可能是 javascript 引擎做了一个奇怪的优化。