-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
273 lines (248 loc) · 7.94 KB
/
index.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
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
const canvas = document.querySelector('canvas');
const c = canvas.getContext('2d');
canvas.width = 1024;
canvas.height = 576;
c.fillRect(0, 0, canvas.width, canvas.height); // create new rectangle đại diện cho nhân vật
const gravity = 0.6
const background = new Sprite({ // sprite để render bg
position: { x: 0, y: 0 },
imageSrc: './BG/background.png'
})
const shop = new Sprite({ // sprite để render shop animation
position: { x: 600, y: 128 },
imageSrc: './BG/shop.png',
scale: 2.75, // phóng to shop image lên 1.5 px
frameMax: 6
})
const player = new Fighter({
position: { x: 54, y: 0 },
velocity: { x: 0, y: 0 },
offset: { x: 0, y: 0 },
imageSrc: './P1/Idle.png',
frameMax: 8,
scale: 2.5,
offset: { x: 215, y: 157 },
sprites: { // chứa các sprite movement của 1 char
idle: {
imageSrc: './P1/Idle.png',
frameMax: 8,
},
run: {
imageSrc: './P1/Run.png',
frameMax: 8,
},
jump: {
imageSrc: './P1/Jump.png',
frameMax: 2,
},
fall: {
imageSrc: './P1/Fall.png',
frameMax: 2,
},
attack1: {
imageSrc: './P1/Attack1.png',
frameMax: 6,
}
},
attackBox: {
offset: {
x: 140, y: 50
},
width: 140,
height: 50
}
})
const enemy = new Fighter({
position: { x: 900, y: 100 },
velocity: { x: 0, y: 0 },
color: 'blue',
offset: { x: -50, y: 0 },
imageSrc: './P2/Idle.png',
frameMax: 4,
scale: 2.5,
offset: { x: 215, y: 167 },
sprites: { // chứa các sprite movement của 1 char
idle: {
imageSrc: './P2/Idle.png',
frameMax: 4,
},
run: {
imageSrc: './P2/Run.png',
frameMax: 8,
},
jump: {
imageSrc: './P2/Jump.png',
frameMax: 2,
},
fall: {
imageSrc: './P2/Fall.png',
frameMax: 2,
},
attack1: {
imageSrc: './P2/Attack1.png',
frameMax: 4,
}
},
attackBox: {
offset: {
x: -185, y: 50
},
width: 185,
height: 50
}
})
enemy.draw();
const keys = { // để khắc phục việc buôn 1 phím nhưng dừng movement
a: {
pressed: false
},
d: {
pressed: false
},
ArrowRight: {
pressed: false
},
ArrowLeft: {
pressed: false
}
}
decreaseTimer()
function animate(){
window.requestAnimationFrame(animate) // loop funct animate lại nhiều lần
// để có thể animate object frame by frame
c.fillStyle = 'black' // cho nền đen
c.fillRect(0, 0, canvas.width, canvas.height) // fill full size canvas màu đen mỗi frame để tạo hiệu ứng rơi thật hơn - không bị chảy dài xuống như sơn
background.update() // gọi bg trc để k bị đè lên model character
shop.update()
player.update()
enemy.update()
player.velocity.x = 0 // dừng model player character khi bỏ tay ra
enemy.velocity.x = 0 // dừng model enemy character khi bỏ tay ra
// player movement
if(keys.a.pressed && player.lastKey === 'a'){ // nếu pressed = true
player.velocity.x = -5
player.switchSprite('run') // chuyển qua run sprites khi press A
}
else if (keys.d.pressed && player.lastKey === 'd'){
player.velocity.x = 5
player.switchSprite('run') // chuyển qua run sprites khi press D
} else {
player.switchSprite('idle') // sẽ là idle khi không press A hoặc D
}
// player jump
if (player.velocity.y < 0) { // đang nhảy
player.switchSprite('jump')
} else if (player.velocity.y > 0) { // đang rơi
player.switchSprite('fall')
}
// enemy movement
if(keys.ArrowLeft.pressed && enemy.lastKey === 'ArrowLeft'){ // nếu pressed = true
enemy.velocity.x = -5
enemy.switchSprite('run')
}
else if (keys.ArrowRight.pressed && enemy.lastKey === 'ArrowRight'){
enemy.velocity.x = 5
enemy.switchSprite('run')
} else {
enemy.switchSprite('idle')
}
// enemy jump
if (enemy.velocity.y < 0) { // đang nhảy
enemy.switchSprite('jump')
} else if (enemy.velocity.y > 0) { // đang rơi
enemy.switchSprite('fall')
}
// Nhận diện va chạm giữa model cho player
if( rectangularCollision({
attackRect: player,
getHitRect: enemy
}) && player.isAttacking && player.frameCurrent === 4 ) // chỉ trừ máu khi tới frame 4
{
player.isAttacking = false; // dòng này chỉ cho phép get hit 1 lần
console.log("player attack!");
enemy.health = enemy.health - 15
document.querySelector('#enemyHealth').style.width = enemy.health + '%'// giảm máu enemy khi nhận sát thương
}
// if player miss hit
if (player.isAttacking && player.frameCurrent === 4){
player.isAttacking = false;
}
// Nhận diện va chạm giữa model cho enemy
if( rectangularCollision({
attackRect: enemy,
getHitRect: player
}) && enemy.isAttacking && enemy.frameCurrent === 2 )
{
enemy.isAttacking = false; // dòng này chỉ cho phép get hit 1 lần
console.log("enemy attack!");
player.health = player.health - 10
document.querySelector('#playerHealth').style.width = player.health + '%'// giảm máu player khi nhận sát thương
}
// if enemy miss hit
if (enemy.isAttacking && enemy.frameCurrent === 2){
enemy.isAttacking = false;
}
// end game by out of health
if(enemy.health <= 0 || player.health <= 0){
determineWinner({player, enemy, timerId})
}
}
animate()
window.addEventListener( 'keydown', (event) => {
switch ( event.key){
// movement player
case 'd':
keys.d.pressed = true; // di chuyển 1 px mỗi khi ấn d
player.lastKey = 'd'
break
case 'a':
keys.a.pressed = true;
// di chuyển 1 px mỗi khi ấn a
player.lastKey = 'a'
break
case 'w':
// bay lên - hạ xuống được nhờ có gravity, vì gravity luôn kéo model xuống nếu như lơ lững (k gần edge rìa)
player.velocity.y = -10 // thêm 20px vào trục y để nhảy
break
case 'j': // ấn space
player.attack()
break
// movement enemy
case 'ArrowRight':
keys.ArrowRight.pressed = true; // di chuyển 1 px mỗi khi ấn mũi tên phải
enemy.lastKey = 'ArrowRight'
break
case 'ArrowLeft':
keys.ArrowLeft.pressed = true;
// di chuyển 1 px mỗi khi ấn mũi tên trái
enemy.lastKey = 'ArrowLeft'
break
case 'ArrowUp':
// bay lên - hạ xuống được nhờ có gravity, vì gravity luôn kéo model xuống nếu như lơ lững (k gần edge rìa)
enemy.velocity.y = -10 // thêm 20px vào trục y để nhảy
break
case '0': // ấn 0
enemy.attack()
break
}
})
window.addEventListener( 'keyup', (event) => {
// player
switch ( event.key){
case 'd':
keys.d.pressed = false; // di chuyển 1 px mỗi khi ấn d
break
case 'a':
keys.a.pressed = false; // di chuyển 1 px mỗi khi ấn a
break
}
// enemy
switch ( event.key){
case 'ArrowRight':
keys.ArrowRight.pressed = false; // di chuyển 1 px mỗi khi ấn d
break
case 'ArrowLeft':
keys.ArrowLeft.pressed = false; // di chuyển 1 px mỗi khi ấn a
break
}
})