forked from ScruffyFurn/HTML5RPG2
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgame.js
More file actions
468 lines (385 loc) · 19.4 KB
/
Copy pathgame.js
File metadata and controls
468 lines (385 loc) · 19.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
/*
Copyright (c) 2014, Mickey "@ScruffyFurn" MacDonald,
Will "@WStieh" Stieh
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
//Initializes Enchant.js engine
enchant();
//This function is called when the window is loaded
//Think of it as your main function (Java, C++, C etc)
window.onload = function () {
/*************************************
Initialize base variables
**************************************/
var game = new Game(window.outerWidth, window.outerHeight);
//First we load up our settings for our sprite sheet
//Sprite sheets and sprites are two aspects of 2D game developement
//A sprite sheet is a file that stores the images we will need for our game
//Instead of having multiple separate image files for each frame of an objects animation, or state
//We stuff it into one image file, which is the sprite sheet, that we reference throughout the game
//Sprites are individual pieces of the sprite sheet
//If you look below, we set the width, height of the sprite sheet and then the width/height of our sprites
//Using that information we are able to locate a specific image
//Using our sprites.png image as an example
//This is what our sprites.png image represents in terms of a sprite sheet
//We know its size, and we know how large each sprite is so we can 'cut' it up into smaller pieces as seen below
//[0][1][2][3][4][5][7][8][9][10][11][12][13][14][15][16][17][18]
// ^
// |
// Player
//If you look at the file you will notice that our player is the 6th image but the 5th sprite (remember we count from 0)
//When the player is created we tell its sprite that its sprite offset is 5
//When we go to draw it enchantjs finds our sprite by looking at our sprite sheet and 'cutting' our sprite out
//It finds it via the sprite offset and simple math, which is the sprite offset x sprite width, which is 5 * 16 = 80
//Meaning that the players location is at x : 80 pixels
//Starting at that point, enchant will pull everything from 80 -> 96 (80+16) in x, and everything from 0 -> 16 in y (remember the origin is in the top left corner)
game.spriteSheetWidth = 304;//Width of the sprite sheet we will be using
game.spriteSheetHeight = 16;//Height of our sprite sheet
game.itemSpriteSheetWidth = 64;//The width of the sprite sheet for our items
game.preload(['sprites.png',
'items.png',
'titleScreen.png',
'deathScreen.png',
'hyperspaceadventure.mp3',
'ntd4.mp3']);//Preload the image and sound files that we will need so we have them when we need them
game.items = [{ price: 1000, description: "Hurter", id: 0, effect: function Effect(player) { console.log("You bought a hurter"); } },//An array of items for the player, with their descriptions, price and id for later lookup
{ price: 5000, description: "Drg. Paw", id: 1, effect: function Effect(player) { console.log("You bought claws"); } },
{ price: 5000, description: "Ice Magic", id: 2, effect: function Effect(player) { console.log("You bought ice magic"); } },
{ price: 60, description: "Chess Set", id: 3, effect: function Effect(player) { console.log("You bought a chess set"); } }]
game.fps = 15;//Setting our frames per second (fps) for the game, 15 frames is fine for a little game like this with simple 2 frame animations.
game.spriteWidth = 16;//Width of our sprites we will be pulling from our sprite sheet
game.spriteHeight = 16;//Height of our sprites we will be pulling from our sprite sheet
game.scale = 1.0;//How much everything in the game should be scaled, can be used to automatically scale everything up or down based on device, game mechanics etc
//Initialize the main variables we use, player, shop, battle, menu and the map
var localPlayer = new Player(game);//Our local player
var shop = new Shop(game);//An object that holds all of our shop logic, reference shop.js
var battle = new Battle(game, localPlayer);//An object that holds all of our combat logic, reference battle.js
var menu = new Menu(game);//An object that represents our title screen, reference menu.js
var map = new Map(game.spriteWidth, game.spriteHeight);//A map object that we use to display the background of the game world. Things the player won't react with, such as the ground
var foregroundMap = new Map(game.spriteWidth, game.spriteHeight);//A map object we use to represent the objects the player will interact with (enemies, trees, etc)
game.foregroundData = foregroundData;//We set the game's foregrounddata to the information stored in our map.js file, called foregroundData. This will populate the foreground map later
//Setup the stage here so we can reference it everywhere
var stage = new Group();
// Initialise the remote players array
var remotePlayers = [];
//**************************
//SOCKET EVENT HANDLERS
//These will be fleshed out more later, jump to our setSocket function to see how they are used
//**************************
// Socket connect to the server
// This function is called when our websocket successfully connects to the game server
//MULTIPLAYER COMMENT
//function onSocketConnected() {
// //Display socket connected message in console
// console.log("Connected to socket server");
// //Tell the server to create a new player
// game.socket.emit("new player",
// {
// x: localPlayer.getX(),
// y: localPlayer.getY()
// });
//};
// Socket disconnect from the server
// This function is called when our websocket disconnects from the game server
//MULTIPLAYER COMMENT
//function onSocketDisconnect() {
// console.log("Disconnected from socket server");
//};
// New Player
// This function is called when a new player is added to the game
//MULTIPLAYER COMMENT
//function onNewPlayer(data) {
// //Display new player message in console
// console.log("New player connected: " + data.id);
// /*Create a new player with placement information
// from the server. Then set the id of the new player
// and add it to the remote players array*/
// var newPlayer = new Player(game);
// newPlayer.id = data.id;
// //Initialize the new player
// newPlayer.setPlayer(false);
// //Set the x,y of the player
// newPlayer.setX(data.x);
// newPlayer.setY(data.y);
// //Add him to the stage and the remotePlayers array
// stage.addChild(newPlayer.object);
// remotePlayers.push(newPlayer);
//};
// Player moves
//This function is used to handle other player's movement
//MULTIPLAYER COMMENT
//function onMovePlayer(data) {
// //Select the player to move
// var movePlayer = playerById(data.id);
// //Display console message if the id is not in the array
// if (!movePlayer) {
// console.log("Player not found: " + data.id);
// return;
// };
// //We set the movePlayer's input
// //Remember, movePlayer is an object within the remotePlayer array
// //The input value that we are passing is a replacement for listening for key input
// movePlayer.setInput(data.input);
// //We then set the players x and y
// movePlayer.setX(data.x);
// movePlayer.setY(data.y);
//};
// Remove a Player
// Called after a disconnect, cleans up the screen so we don't continue to draw players that are no longer there
//MULTIPLAYER COMMENT
//function onRemovePlayer(data) {
// //Find the selected player to remove
// var removePlayer = playerById(data.id);
// //Display a console message if the id is not in array
// if (!removePlayer) {
// console.log("Player not found: " + data.id);
// return;
// };
// //Remove player from stage
// stage.removeChild(removePlayer.object);
// //Remove the selected player from the remote player array
// remotePlayers.splice(remotePlayers.indexOf(removePlayer), 1);
//};
//********************************************************************************
/**************************************************
** Player find helper function
**************************************************/
//MULTIPLAYER COMMENT
//function playerById(id) {
// var i;
// //Runs through the remote players array and returns the one with the id we passed in
// for (i = 0; i < remotePlayers.length; i++) {
// if (remotePlayers[i].id == id)
// return remotePlayers[i];
// };
// return false;
//};
//Loads the map objects
var setMaps = function () {
//First we tell the maps to use the sprites.png image when drawing
map.image = game.assets['sprites.png'];
//We load in the data from our map.js file
//The mapData is represented as a multi-dimensional array where its values are converted to a image on the spriteSheet (sprites.png)
map.loadData(mapData);
foregroundMap.image = game.assets['sprites.png'];
foregroundMap.loadData(game.foregroundData);
//As previously mentioned, the player only interacts with the foreground data
//Meaning we use it to get our collision information
//First we initialize it as an array
var collisionData = [];
for (var i = 0; i < game.foregroundData.length; i++) {
//For each row, we add another array
collisionData.push([]);
//Then we fill that row with the data within foreground data
for (var j = 0; j < game.foregroundData[0].length; j++) {
//Fun one line if statement
//If the current data modded by 13 is greater then 1 (not perfectly divisible by 13) then collision is 1 other wise its 0
var collision = game.foregroundData[i][j] % 13 > 1 ? 1 : 0;
collisionData[i][j] = collision;
}
}
map.collisionData = collisionData;
};
//Simple little helper function that is used to replace a specific type of npc with something else
game.popFromMap = function (type, replacement) {
for (var i = 0; i < game.foregroundData.length; i++) {
for (var j = 0; j < game.foregroundData[0].length; j++) {
if (game.foregroundData[i][j] == type)
game.foregroundData[i][j] = replacement;
}
}
setMaps();
}
//Pass in the row, column and the replacement
//We look into the foregrounddata and swap it out
game.replaceObjOnMap = function (row, col, replacement) {
if (row > game.foregroundData.length - 1 || col > game.foregroundData[0].length - 1)
return;
game.foregroundData[col][row] = replacement;
setMaps();
}
game.getRow = function (y) {
return Math.floor(y / game.spriteHeight);
}
game.getColumn = function (x) {
return Math.floor(x / game.spriteWidth);
}
//Function sets up the stage
var setStage = function () {
stage.addChild(map);//Add the map object to the stage
stage.addChild(localPlayer.object); //Adds the player object (which is a sprite, check out player.js) to the stage
//Next we add in the buttons for player input
game.buttonB = new enchant.ui.Button("B", "light");
game.buttonB.moveTo(180, 450);
//Now these we add to the games current scene, which is the scene that we are currently viewing
game.currentScene.addChild(game.buttonB);
game.buttonA = new enchant.ui.Button("A", "blue");
game.buttonA.moveTo(230, 410);
game.currentScene.addChild(game.buttonA);
//Set up input for the A button
game.buttonA.ontouchstart = function () {
//We get the direction the player is currently facing
var playerFacing = localPlayer.facing();
//If we are not facing an npc or other interactive object we just show the players stats
if (!playerFacing || !spriteRoles[playerFacing]) {
localPlayer.displayStatus();
//Now this code is specific, we know that '2' is the ID for the ratQuest giver
}else if(playerFacing == 2){
spriteRoles[playerFacing].action(game, new Quest(game, RatQuest, 2));
//Same idea as the ratQuest giver, this one is for the revenge quest
} else if (playerFacing == 18) {
spriteRoles[playerFacing].action(game, new Quest(game, RevengeQuest,18));
} else {
//Now if we are just facing a regular ol'npc that we call its action function
//Now the spriteRoles is an array we declare below that stores the identifier for each npc type, if you look it is the same size as our sprite sheet
//and each objects position matches its position on the sprite sheet
//Reference the npc.js
spriteRoles[playerFacing].action(game);
};
};
//Create the gamepad for the player's movement/options etc
game.pad = new enchant.ui.Pad();
game.pad.moveTo(0, 380);
game.currentScene.addChild(game.pad);
//Finally, we add the foreground map, players statuslabel (used to display messages) to the stage
//Then add the stage to the game's rootscene
stage.addChild(foregroundMap);
stage.addChild(localPlayer.object.statusLabel);
game.rootScene.addChild(stage);
};
//As explained above this is an array to identify different npc types
//Their position here is identical to their position in the sprite sheet
var spriteRoles = [, , ratQuestGiver, , cat, , , , , , , , , , , brawler,,,revengeQuestGiver]
//Focuses the game on the player, important for mobile devices where the screen is shrunk
game.focusViewport = function () {
var x = Math.min((game.width - 16) / 2 - localPlayer.getX(), 0);
var y = Math.min((game.height - 16) / 2 - localPlayer.getY(), 0);
//Set the games root scene's position
game.rootScene.x = x;
game.rootScene.y = y;
//Update the UI buttons based on that position
//We absolute the x and y values, then we set each button to that value + its offset
//To simplify things, our x and y values we just set are our new origin
x = Math.abs(x);
y = Math.abs(y);
game.pad.moveTo(x + 0 ,y + 380);
game.buttonA.moveTo(x + 230, y + 410);
game.buttonB.moveTo(x + 180, y + 450);
};
//Games OnLoad function
//When the game is loaded we first set the menu (because we see it first)
//Run its update to call the focusViewport code used above
game.onload = function () {
menu.setMenu();
game.rootScene.on('enterframe', function (e) {
game.focusViewport();
//Music update
if (game.backGroundMusic.currentTime >= game.backGroundMusic.duration)
game.backGroundMusic.play();
});
};
//Cry 'Havoc!', and let slip the dogs of war!
//This kick starts the engine and gets the game moving
game.start();
//Set up the game
//Basically it calls everyones initialization
game.setGame = function () {
//We initialize, or re-iniitalize everyone if we are doing a reset
localPlayer = new Player(game);
shop = new Shop(game);
battle = new Battle(game, localPlayer);
//Initialize, or re-init the socket
//MULTIPLAYER COMMENTgame.setSocket();
//After all that checking and declaring we finally initialize everyone by calling their set functions
setMaps();
//Note, the true variable passed in tells this player that he is our local player
localPlayer.setPlayer(true);
setStage();
shop.setShop();
battle.setBattle();
//Stop the title screen background music
game.titleBackgroundMusic.stop();
//Here we get our background music track and the begin playing it
game.backGroundMusic = game.assets['ntd4.mp3'];
game.backGroundMusic.play();
};
game.setSocket = function()
{
//MULTIPLAYER COMMENT
// Initialise the socket connection to the server
//var socket = io.connect('http://html5multiplayerbackupserver.azurewebsites.net:80');
//game.socket = socket;
////*****************************SOCKET EVENTS SETUP
//// Start listening for events
//// Socket events
//game.socket.on("connect", onSocketConnected);
//game.socket.on("disconnect", onSocketDisconnect);
//game.socket.on("new player", onNewPlayer);
//game.socket.on("move player", onMovePlayer);
//game.socket.on("remove player", onRemovePlayer);
//***********************************************
}
//Getters and Setters
game.getMap = function () {
return map;
};
game.getPlayer = function()
{
return localPlayer;
};
game.getShop = function()
{
return shop;
}
game.getBattle = function()
{
return battle;
}
game.showMenu = function (death) {
//Null stuff out, forces everyone to just be reinitialized when we call the setGame function
localPlayer = null;
shop = null;
battle = null;
game.socket = null;
socket = null;
//Make sure that the revenge quest is gone
game.popFromMap(18, 2);
//Stop our background music
game.backGroundMusic.stop();
//Here we get our title screens background music track and then begin playing it
game.titleBackgroundMusic = game.assets['hyperspaceadventure.mp3'];
game.titleBackgroundMusic.play();
//Tell the menu to show its menu screen, the death variable means whether its because the player died or not
//If so, we show a game over screen versus the menu screen
menu.showMenu(death);
};
game.getMenu = function () {
return menu;
};
//Our returns for our game object
return {
getPlayer : game.getPlayer,
getMap: game.getMap,
getShop: game.shop,
getBattle: game.getBattle,
popFromMap: game.popFromMap,
replaceObjOnMap: game.replaceObjOnMap,
getRow : game.getRow,
getColumn: game.getColumn,
setGame: game.setGame,
showMenu: game.showMenu,
getMenu: game.getMenu
};
};