Adding features to our bouncing balls demo
先决条件: | 在尝试此评估之前,您应该已经完成了本单元中的所有文章。 |
---|---|
目的: | 测试JavaScript对象和面向对象结构的理解 |
初始点
要开始进行此评估,请制作本地副本 "external"> index-finished.html , ="external"> style.css 和 main-finished.js 从我们上一篇文章在您的本地计算机的新目录。
注意:或者,您也可以使用 JSBin 或 "https://thimble.mozilla.org/"class ="external-icon external"> Thimble 来做你的评估。 您可以将HTML,CSS和JavaScript粘贴到其中一个在线编辑器。 如果您使用的在线编辑器没有单独的JavaScript / CSS面板,请随意将它们放入HTML中的< script>
/ < style>
页。
工程概要
我们的弹性球演示是有趣的,但现在我们想通过添加一个用户控制的邪恶的圈子,它会吃球,如果它捕捉到一个更多的互动。 我们还想通过创建一个通用的 Shape()
对象来测试你的对象构建技能,我们的球和邪恶的圈子可以继承。 最后,我们要添加一个分数计数器来跟踪要捕获的球数。
下面的截图给出了一个完成的程序应该是什么样子的想法:
为了给您更多想法,请查看完成的示例 >(没有偷看源代码!)
步骤完成
以下部分描述了您需要做什么。
创建我们的新对象
首先,改变你现有的 Ball()
构造函数,使它成为一个 Shape()
构造函数和一个新的 Ball
- The
Shape()
constructor should define thex
,y
,velX
, andvelY
properties in the same way as theBall()
constructor did originally. - It should also define a new property called
exists
, which is used to track whether the balls exist in the program (have not been eaten by the evil circle). This should be a boolean, with an initial value oftrue
. - The
Ball()
constructor should inheritx
,y
,velX
,velY
, andexists
from theShape()
constructor. Remember that you'll need to define them as parameters as well as calling them. - It should also define a
color
and asize
property, which should both be initialized to the same random values as they were in the originalBall()
constructor. - Remember to set the
Ball()
constructor'sprototype
andconstructor
appropriately.
球 draw()
, update()
和碰撞检测()
方法定义应该能够保持完全一样, 。
在这一点上,尝试重新加载代码 - 它应该像以前一样工作,与我们重新设计的对象。
定义EvilCircle()
现在是时候遇到坏人 - EvilCircle()
! 我们的游戏只涉及一个邪恶的圈子,但我们仍然要使用继承自 Shape()
的构造函数来定义它,给你一些练习。 您可能想在以后添加另一个圈子,可以由另一个玩家控制,或有几个计算机控制的邪恶的圈子。 你可能不会用一个邪恶的圈子接管世界,但它会做这个评估。
EvilCircle()
构造函数应该从 Shape()中继承
代码>。 x
, y
它还应该定义自己的属性,如下所示:
-
color
—'white'
-
size
—10
-
velX
—20
-
velY
—20
同样,请记住在构造函数中将继承的属性定义为参数,并正确设置 prototype
和构造函数
属性。
定义EvilCircle()的方法
EvilCircle()
应该有四个方法,如下所述。
draw()
此方法与 Ball()
的 draw()
方法具有相同的目的:它在画布上绘制对象实例。 它将以非常类似的方式工作,因此您可以从复制 Ball.prototype.draw
定义开始。 然后,您应该进行以下更改:
- We want the evil circle to not be filled in, but rather just have an outer line (stroke). You can achieve this by updating
fillStyle
andfill()
tostrokeStyle
andstroke()
. - We also want to make the stroke a bit thicker, so you can see the evil circle a bit more easily. This can be achieved by setting a value for
lineWidth
somewhere after thebeginPath()
call (3 will do).
checkBounds()
这个方法将做与 Ball()
的 update()
函数的第一部分相同的事情 - 看看邪恶的圆圈是否会离开边缘 的屏幕,并停止这样做。 同样,你可以大多只是复制 Ball.prototype.update
的定义,但有一些修改你应该做:
- 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 updatevelX
/velY
; we want to instead change the value ofx
/y
so the evil circle is bounced back onto the screen slightly. Adding or subtracting (as appropriate) the evil circle'ssize
property would make sense.
setControls()
此方法将向 window
对象添加一个 onkeydown
事件侦听器,以便当按下某些键盘键时,我们可以移动邪恶的圆圈。 以下代码块应该放在方法定义中:
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; } }
因此,当按下某个键时,会查看事件对象的 keyCode 属性,以查看 按下该键。 如果它是由指定的键盘代表的四个之一,那么邪恶的圆圈将左/右/上/下移动。
- 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()
此方法将以非常类似于 Ball()
的 collisionDetect()
方法的方式运行,因此您可以使用该方法的副本作为此新方法的基础。 但有几个区别:
- 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?).
把邪恶的圆带进程序
现在我们已经定义了邪恶的圈子,我们需要让它出现在我们的场景中。 为此,您需要对 loop()
函数进行一些更改。
- 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()
, andcollisionDetect()
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()
, andcollisionDetect()
methods on every iteration of the loop.
实现分数计数器
要实施分数计数器,请按照以下步骤操作:
- In your HTML file, add a
<p>
element just below the<h1>
element containing the text "Ball count: ". - In your CSS file, add the following rule at the bottom:
p { position: absolute; margin: 0; top: 35px; right: 5px; color: #aaa; }
- In your JavaScript, make the following updates:
- Create a variable that stores a reference to the paragraph.
- Keep a count of the number of balls on screen in some way.
- Increment the count and display the updated number of balls each time a ball is added to the scene.
- Decrement the count and display the updated number of balls each time the evil circle eats a ball (causes it not to exist).
提示和提示
- This assessment is quite challenging. Take each step slowly and carefully.
- It might be an idea to keep a separate copy of the demo after you get each stage working, so you can refer back to it if you find yourself in trouble later on.
评定
如果您作为有组织课程的一部分参加此评估,您应该能够将您的工作交给您的老师/导师进行标记。 如果您是自学习的,那么您可以轻松地通过 dev-mdc 邮件列表,或者在 #mdn IRC频道中。 org / IRC"class ="external"> Mozilla IRC 。 尝试练习第一 - 没有什么可以通过作弊获得!