-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathengine.js
executable file
·210 lines (190 loc) · 8.04 KB
/
engine.js
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
/* Engine.js
* This file provides the game loop functionality (update entities and render),
* draws the initial game board on the screen, and then calls the update and
* render methods on your player and enemy objects (defined in your app.js).
*
* A game engine works by drawing the entire game screen over and over, kind of
* like a flipbook you may have created as a kid. When your player moves across
* the screen, it may look like just that image/character is moving or being
* drawn but that is not the case. What's really happening is the entire "scene"
* is being drawn over and over, presenting the illusion of animation.
*
* This engine makes the canvas' context (ctx) object globally available to make
* writing app.js a little simpler to work with.
*/
var Engine = (function(global) {
/* Predefine the variables we'll be using within this scope,
* create the canvas element, grab the 2D context for that canvas
* set the canvas element's height/width and add it to the DOM.
*/
var doc = global.document,
win = global.window,
canvas = doc.createElement('canvas'),
ctx = canvas.getContext('2d'),
lastTime;
canvas.width = 505;
canvas.height = 606;
doc.body.appendChild(canvas);
/* This function serves as the kickoff point for the game loop itself
* and handles properly calling the update and render methods.
*/
function main() {
/* Get our time delta information which is required if your game
* requires smooth animation. Because everyone's computer processes
* instructions at different speeds we need a constant value that
* would be the same for everyone (regardless of how fast their
* computer is) - hurray time!
*/
var now = Date.now(),
dt = (now - lastTime) / 1000.0;
/* Call our update/render functions, pass along the time delta to
* our update function since it may be used for smooth animation.
*/
update(dt);
render();
/* Set our lastTime variable which is used to determine the time delta
* for the next time this function is called.
*/
lastTime = now;
/* Use the browser's requestAnimationFrame function to call this
* function again as soon as the browser is able to draw another frame.
*/
win.requestAnimationFrame(main);
}
/* This function does some initial setup that should only occur once,
* particularly setting the lastTime variable that is required for the
* game loop.
*/
function init() {
reset();
lastTime = Date.now();
main();
}
/* This function is called by main (our game loop) and itself calls all
* of the functions which may need to update entity's data. Based on how
* you implement your collision detection (when two entities occupy the
* same space, for instance when your character should die), you may find
* the need to add an additional function call here. For now, we've left
* it commented out - you may or may not want to implement this
* functionality this way (you could just implement collision detection
* on the entities themselves within your app.js file).
*/
function update(dt) {
updateEntities(dt);
checkCollisions();
checkGameWin();
}
function checkCollisions() {
console.log(`${player.x}, ${player.y}`)
for (const enemy of allEnemies) {
const xHitRadius = 80
const yHitRadius = 20
const x_range = [enemy.x-xHitRadius, enemy.x+xHitRadius]
const y_range = [enemy.y-yHitRadius, enemy.y+yHitRadius]
if (player.x >= x_range[0] && player.x <= x_range[1] && player.y >= y_range[0] && player.y <= y_range[1]) {
player.x = 200
player.y = 300
}
}
}
// Function checks if Player object has reached the water
function checkGameWin() {
if (player.y <= 0) {
console.log('You won!!!')
reset()
}
}
/* This is called by the update function and loops through all of the
* objects within your allEnemies array as defined in app.js and calls
* their update() methods. It will then call the update function for your
* player object. These update methods should focus purely on updating
* the data/properties related to the object. Do your drawing in your
* render methods.
*/
function updateEntities(dt) {
allEnemies.forEach(function(enemy) {
enemy.update(dt);
});
player.update();
}
/* This function initially draws the "game level", it will then call
* the renderEntities function. Remember, this function is called every
* game tick (or loop of the game engine) because that's how games work -
* they are flipbooks creating the illusion of animation but in reality
* they are just drawing the entire screen over and over.
*/
function render() {
/* This array holds the relative URL to the image used
* for that particular row of the game level.
*/
var rowImages = [
'images/water-block.png', // Top row is water
'images/stone-block.png', // Row 1 of 3 of stone
'images/stone-block.png', // Row 2 of 3 of stone
'images/stone-block.png', // Row 3 of 3 of stone
'images/grass-block.png', // Row 1 of 2 of grass
'images/grass-block.png' // Row 2 of 2 of grass
],
numRows = 6,
numCols = 5,
row, col;
// Before drawing, clear existing canvas
ctx.clearRect(0,0,canvas.width,canvas.height);
/* Loop through the number of rows and columns we've defined above
* and, using the rowImages array, draw the correct image for that
* portion of the "grid"
*/
for (row = 0; row < numRows; row++) {
for (col = 0; col < numCols; col++) {
/* The drawImage function of the canvas' context element
* requires 3 parameters: the image to draw, the x coordinate
* to start drawing and the y coordinate to start drawing.
* We're using our Resources helpers to refer to our images
* so that we get the benefits of caching these images, since
* we're using them over and over.
*/
ctx.drawImage(Resources.get(rowImages[row]), col * 101, row * 83);
}
}
renderEntities();
}
/* This function is called by the render function and is called on each game
* tick. Its purpose is to then call the render functions you have defined
* on your enemy and player entities within app.js
*/
function renderEntities() {
/* Loop through all of the objects within the allEnemies array and call
* the render function you have defined.
*/
allEnemies.forEach(function(enemy) {
enemy.render();
});
player.render();
}
/* This function does nothing but it could have been a good place to
* handle game reset states - maybe a new game menu or a game over screen
* those sorts of things. It's only called once by the init() method.
*/
function reset() {
player.x = 200
player.y = 300
}
/* Go ahead and load all of the images we know we're going to need to
* draw our game level. Then set init as the callback method, so that when
* all of these images are properly loaded our game will start.
*/
Resources.load([
'images/stone-block.png',
'images/water-block.png',
'images/grass-block.png',
'images/enemy-bug.png',
'images/char-boy.png',
'images/char-cat-girl.png'
]);
Resources.onReady(init);
/* Assign the canvas' context object to the global variable (the window
* object when run in a browser) so that developers can use it more easily
* from within their app.js files.
*/
global.ctx = ctx;
})(this);