I'm working on a game for Windows 8 in HTML5 and JavaScript. I have a working version of the game that stores "roach" objects in an array. I am trying to put the game code i have into a sample from Microsoft (linked here). In this example they decalere a set of object literals for the game state that are saved and used in various classes:
internal: {
gamePaused: false,
gamePhase: "ready",
speed: 5,
score: 0,
}
In there I would like to put the array for my roach objects. I thought I could do:
roaches: [],
but when I call:
this.state.roaches.push(new Roach());
this.state.roaches.length;
I get a:
JavaScript runtime error: Unable to get property 'length' of undefined or null reference
What am I doing wrong and how can I fix it?
Nat
additional info:
alright so here is my roach class:
var Roach = WinJS.Class.define( function () {
this.position.x = Math.random() * gameCanvas.width + 1;
this.position.y = Math.random() * gameCanvas.height + 1;
this.squished = false;
this.image = GameManager.assetManager.assets.roachImage;
},
{
move: function (speed) {
// changes position
},
squish: function() {
}
});
this is in a file called game.js which contains another class:
var Game = WinJS.Class.define(
null,
{
// other functions
// Called when the game is being prepared to start
ready: function () {
// TODO: Replace with your own new game initialization logic
if (this.isSnapped()) {
this.state.gamePaused = true;
} else {
this.state.gamePaused = false;
}
this.state.gamePhase = "ready";
switch (this.settings.skillLevel) {
case 0:
this.state.speed = 3;
break;
case 1:
this.state.speed = 5;
break;
case 2:
this.state.speed = 10;
break;
}
this.state.roaches.push(new Roach());
this.state.score = 0;
},
// Main game render loop
draw: function () {
this.gameContext.clearRect(0, 0, gameCanvas.width, gameCanvas.height);
// TODO: Sample game rendering to be replaced
// Draw the current score
this.gameContext.fillStyle = "#FFFF99";
this.gameContext.font = "bold 48px Segoe UI";
this.gameContext.textBaseline = "middle";
this.gameContext.textAlign = "right";
this.gameContext.fillText(this.state.score, gameCanvas.width - 5, 20);
// update image positions
// THROWS ERROR HERE
for (var i = 0; i < this.state.roaches.length; i++) {
if (!this.state.roaches[i].squished) {
}
}
// Draw a ready or game over or paused indicator
if (this.state.gamePhase === "ready") {
this.gameContext.textAlign = "center";
this.gameContext.fillText("READY", gameCanvas.width / 2, gameCanvas.height / 2);
} else if (this.state.gamePhase === "ended") {
this.gameContext.textAlign = "center";
this.gameContext.fillText("GAME OVER", gameCanvas.width / 2, gameCanvas.height / 2);
} else if (this.state.gamePaused) {
this.gameContext.textAlign = "center";
this.gameContext.fillText("PAUSED", gameCanvas.width / 2, gameCanvas.height / 2);
}
}
Now in a file called gameState.js a gameState class is defined that holds the variables that I referenced earlier.
var GameState = WinJS.Class.define(
null,
{
config: {
// TODO: Adjust these values to configure the template itself
frameRate: 20, // Set to 0 to have no update loop at all
minSquished: 20,
currentPage: "/html/homePage.html",
gameName: "SDK Game Sample", // Used by share contract on scores page
},
// TODO: Replace these public settings exposed on the settings panel
external: {
playerName: "Player",
soundVolume: 100,
skillLevel: 0,
},
// TODO: Replace these values with state variables relevant for your game
internal: {
gamePaused: false,
gamePhase: "ready",
roaches: [],
speed: 5,
score: 0,
},
These files are assembled under the GameManager namespace which calls each class from the files and creates them under that namespace. So when the user starts the game the ready function is called by the GameManager and then the draw function is called to update the screen. Hopefully this helps clarify.
the namespace is defined here:
var game = new Game();
var touchPanel = new TouchPanel();
var state = new GameState();
state.load();
WinJS.Namespace.define("GameManager", {
navigateHome: navigateHome,
navigateGame: navigateGame,
navigateRules: navigateRules,
navigateScores: navigateScores,
navigateCredits: navigateCredits,
showPreferences: showPreferences,
onBeforeShow: onBeforeShow,
onAfterHide: onAfterHide,
game: game,
state: state,
assetManager: assetManager,
scoreHelper: scoreHelper,
gameId: gameId,
touchPanel: touchPanel
});