# 為彈跳彩球添增其他功能

## 須進行的步驟

### 建立新物件

1. `Shape()` 建構子對 `x``y``velX``velY` 屬性的定義方式，就如同 `Ball()` 建構子所用的方式。
2. 另須定義新的 `exists` 屬性，用以追蹤球體是否存在於程式之中 (也就是尚未遭邪惡圈所吃掉)。此屬性必為布林值 (Boolean)，初始值為 `true`
3. `Ball()` 建構子應從 `Shape()` 建構子繼承 `x``y``velX``velY``exists` 等屬性。另必須將這些屬性定義為參數以利呼叫之。
4. 必須定義 `color``size` 屬性各 1 組，且由於兩者均來自於原始的 `Ball()` 建構子之中，所以剛開始的隨機值亦須相同。
5. 記得應正確設定 `Ball()` 建構子的 `prototype``constructor`

### 定義 EvilCircle()

`EvilCircle()` 建構子應繼承 `Shape()``x``y``exists`

• `color``'white'`
• `size``10`
• `velX``20`
• `velY``20`

### 定義 EvilCircle() 的函式

`EvilCircle()` 應具備 4 個函式，如下：

#### `checkBounds()`

• Get rid of the last two lines — we don't want to automatically update the evil circle's position on every frame, because we will be moving it in some other way, as you'll see below.
• Inside the `if()` statements, if the tests return true we don't want to update `velX`/`velY`; we want to instead change the value of `x`/`y` so the evil circle is bounced back onto the screen slightly. Adding or subtracting (as appropriate) the evil circle's `size` property would make sense.

#### `setControls()`

This method will add an `onkeydown` event listener to the `window` object so that when certain keyboard keys are pressed, we can move the evil circle around. The following code block should be put inside the method definition:

js
``````var _this = this;
window.onkeydown = function (e) {
if (e.keyCode === 65) {
_this.x -= _this.velX;
} else if (e.keyCode === 68) {
_this.x += _this.velX;
} else if (e.keyCode === 87) {
_this.y -= _this.velY;
} else if (e.keyCode === 83) {
_this.y += _this.velY;
}
};
``````

So when a key is pressed, the event object's keyCode property is consulted to see which key is pressed. If it is one of the four represented by the specified keycodes, then the evil circle will move left/right/up/down.

• For a bonus point, let us know which keys the specified keycodes map to.
• For another bonus point, can you tell us why we've had to set `var _this = this;` in the position it is in? It is something to do with function scope.

#### `collisionDetect()`

This method will act in a very similar way to `Ball()`'s `collisionDetect()` method, so you can use a copy of that as the basis of this new method. But there are a couple of differences:

• In the outer `if` statement, you no longer need to check whether the current ball in the iteration is the same as the ball that is doing the checking — because it is not longer a ball, it is the evil circle! Instead, you need to do a test to see if the ball being checked exists (with which property could you do this with?). If it doesn't exist, it has already been eaten by the evil circle, so there is no need to check it again.
• In the inner `if` statement, you no longer want to make the objects change color when a collision is detected — instead, you want to set any balls that collide with the evil circle to not exist any more (again, how do you think you'd do that?).

### Bringing the evil circle into the program

Now we've defined the evil circle, we need to actually make it appear in our scene. To do this, you need to make some changes to the `loop()` function.

• First of all, create a new evil circle object instance, then call its `setControls()` method. You only need to do these two things once, not on every iteration of the loop.
• At the point where you loop through every ball and call the `draw()`, `update()`, and `collisionDetect()` functions for each one, make it so that these functions are only called if the current ball exists.
• Call the evil ball instance's `draw()`, `checkBounds()`, and `collisionDetect()` methods on every iteration of the loop.

### Implementing the score counter

To implement the score counter, follow the following steps:

1. In your HTML file, add a `<p>` element just below the `<h1>` element containing the text "Ball count: ".
2. In your CSS file, add the following rule at the bottom:
css
``````p {
position: absolute;
margin: 0;
top: 35px;
right: 5px;
color: #aaa;
}
``````