
Trong phần này ta sẽ thêm khả năng bắn đạn của tower cũng như HP của các enemy. Như thường lệ tôi sẽ cố gắng viết các comment trong code để người đọc có thể hiểu ngay. Phần bài viết này chỉ có nhiệm vụ dẫn dắt bạn vào những phần chính.
Nếu đây là phần đầu tiên bạn đọc, bạn có thể quay lại đọc các phần 1, 2.
Nếu đây là phần đầu tiên bạn đọc, bạn có thể quay lại đọc các phần 1, 2.
Xem Demo.

HP của Enemy
Ta sẽ vẽ một thanh màu đỏ phía trên mỗi enemy để người chơi ước lượng được % lượng HP còn lại của chúng. Khi khởi tạo Enemy, ta thêm thuộc tính mới cho lớp này:
1
2
3
4
5
| function Enemy(roadX,roadY){ var maxhp = 1000; this .hp = maxhp; // ...c } |
Vẽ thanh HP:
1
2
3
4
5
| this .draw = function (context){ // ... context.fillStyle = "red" ; context.fillRect( this .left, this .top - 5, UNIT_SIZE * this .hp / maxhp, 3); }; |
Và bổ sung phương thức để kiểm tra xem enemy có dính đạn hay không (mỗi viên đạn được coi là một điểm):
1
2
3
4
| this .contain = function (x, y){ return this .left <= x && this .top <= y && this .right >= x && this .bottom >=y; }; |
Bullet – Đạn
Trong lớp này, ta sẽ xác định hướng di chuyển của mỗi viên đạn từ góc xoay của tower tạo ra nó. Trong đó, ta cũng cần một phương thức để kiểm tra va chạm của đạn với enemy. Khi va chạm xảy ra, ta sẽ trừ HP của enemy dựa vào chỉ số damage của tower:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| this .collide = function (damage, enemies){ for ( var i = 0; i < enemies.length; i++) { var e = enemies[i]; if (!e.isDisposed && e.contain( this .cx, this .cy)) { e.hp -= damage; if (e.hp <= 0) { e.hp = 0; e.isDisposed = true ; } this .isDisposed = true ; return ; } } }; |
Ngoài ra cần đảm bảo rằng tầm bay của đạn không vượt quá phạm vi bắn của tower. Vì vậy trong phương thức update(), ta sẽ lưu lại khoảng cách mà đã bay. Và khi đã vượt qua giới hạn, ta cần hủy nó:
1
2
3
4
5
6
7
| this .update = function (){ this .cx += speedX; this .cy += speedY; distance += speed; if (distance >= range) this .isDisposed = true ; }; |
Tower
Đây là lớp thay đổi nhiều nhất vì phải thêm các thuộc tính, biến mới:
this.damage = 100;
var bullets = [];
var lastFired = 0;
var fireDelay = 400; // fire rate
var target;
var bullets = [];
var lastFired = 0;
var fireDelay = 400; // fire rate
var target;
Trong đó, biến target giúp lưu trữ đối tượng enemy mà tower đang nhắm vào. Như vậy ta không cần lặp qua để tìm enemy gần nhất mỗi lần update. Chỉ cần kiểm tra khoảng cách giữa tower vừa target, nếu nó nằm ngoài tầm bắn thì ta mới tìm kiếm một enemy khác:
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
| this .update = function (enemies){ var targetAngle; if (target) { if (target.isDisposed) target = null ; else { // check if the target is within the shooting range var dx = target.cx - this .cx; var dy = target.cy - this .cy; var distance = Math.sqrt(dx * dx + dy * dy); if (distance <= this .shootingRange) { targetAngle = Math.atan2(dy, dx); if (Math.abs( this .angle - targetAngle) < ANGLE_EPSILON) { // fire the enemy var newtick = ( new Date()).getTime(); if (newtick - lastFired >= fireDelay) { this .fire(); lastFired = newtick; } } } else // the target is out of shooting range, // we need to find a new target target = null ; } } if (!target){ // find the nearest enemy within range for ( var x in enemies) { var e = enemies[x]; var dx = e.cx - this .cx; var dy = e.cy - this .cy; var distance = Math.sqrt(dx * dx + dy * dy); if (distance <= this .shootingRange) { targetAngle = Math.atan2(dy, dx); target = e; break ; } } } // ... }; |
Comments[ 0 ]
Đăng nhận xét