Bouncing Box, but you control the box, and it doesn't bounce!
Table of Contents
- Overview
- Lesson Steps
- TODO 1: Understand the Template and Change the Box
- TODO 2: Register Keyboard Inputs
- TODO 3: React to Specific Keycodes
- TODO 4: Declare
walker
Variable - TODO 5: Declare Some Helper Functions
- TODO 6: Update
speedX
andspeedY
with the Keyboard - TODO 7: Reset
speedX
andspeedY
on"keyup"
- TODO 8: Implement Borders`
- Challenge Ideas
- Submit Your Work
In this project we will be building a simple program that allows us to control the movement of a box with the arrow keys. As a challenge, try limiting the movement of the "walker" to the boundaries of the board. Then, add a second "walker" and turn the program into a game of tag!
- Become familiar with the template repository
- Apply lesson on detecting keyboard inputs
- Make connections to the Bouncing Box program and recognize patterns
- Continue to practice using jQuery
To push to GitHub, enter the following commands in bash:
git add -A
git commit -m "saving walker"
git push
- All code in proper sections (setup, core, helpers, etc.) - 5 points
- Use comments to describe setup and functions - 10 points
- Use helper functions to separate concerns - 10 points
NOTE: Incomplete programs will receive partial credit based on the number of TODOs completed with the above best practices in place.
- TODO 1 - 5 points
- TODO 2 - 10 points
- TODO 3 - 10 points
- TODO 4 - 10 points
- TODO 5 - 10 points
- TODO 6 - 10 points
- TODO 7 - 10 points
- TODO 8 - 10 points
- Challenge 1 - 5 points (bonus)
- Challenge 2 - 5 points (bonus)
- Challenge 3 - 10 points (bonus) NOTE: the bonus will not give you a score of over 100 should you earn that many points, but these challenges will help you out much later if you can do them.
Let's begin by going through the existing code of the template and making a few minor changes
The body only has 2 elements: the #board
and a single #gameItem
. It should look like this:
<body>
<div id='board'>
<div id='gameItem'></div>
</div>
</body>
This produces a basic game board with a single game item on the board. If you need/want to add more, then you will need to place them on the board.
All elements will have unique id
attributes, which means that you can select them using the appropriate CSS selectors whenever using jQuery or CSS.
- 1a) Change the
id
of'gameItem'
to be'walker'
NOTE: When you do this, the box will no longer display. This will be remedied in the next step.
The games we will build this semester will all use 2D graphics since we are limiting ourselves to HTML and CSS. Most of the shapes can be easily drawn as rectangles using the width
and height
properties.
Notice the values for the
position
properties set for the#board
and the#gameItem
. The parent element (#board
) has theposition: relative
property while the child element (#gameItem
) has theposition: absolute
property. This combo means that the child element can be placed anywhere inside the parent element by manipulating theleft
andtop
properties.
left
is the x-coordinate, or distance from the lefttop
is the y-coordinate, or distance from the top
Finally: Be aware that rectangles can be made into circles by adding a border-radius
property.
-
1b) Change the id selector
#gameItem
to#walker
so that it matches the HTML -
1c) Add a
border-radius
property to the#walker
. To make it a perfect circle, set theborder-radius
to the same value as thewidth
andheight
. You do not need to make it a perfect circle, but you do need at least a small bit of curvature.
Look at the code written under each header. Remember:
- Setup: variable declarations, any one-off statements needed to start the program
- Core Logic: The main logic driving the program. Should delegate work to helper functions.
- Helper Functions: functions that help implement the core logic.
FIND:
Open the index.js
file.
Our first task is to make our game register "keydown"
events and respond to them. We'll keep the response simple for now until we know that our code is working.
In the SETUP section, find where the event handler's are registered ($(document).on('eventType', handleEvent)
.
CODE:
- 2a) Modify the code such that, instead of calling
handleEvent
, it calls a different function:handleKeyDown
. - 2b) Make sure that it is called in response to
"keydown"
events. - 2c) Find the event handler function
handleEvent
and change its name tohandleKeyDown
. Inside, add aconsole.log()
statement to its{code block}
that prints the keycode of the key pressed:
Together, these components will look like this:
// SETUP...
$(document).on('keydown', handleKeyDown);
// CORE LOGIC...
function handleKeyDown(event) {
console.log(???);
}
HINT: How do you know which key was pressed from the given
event
object? Check out keycode.info for help!
TESTING: Save your code and refresh your game. Open the running application in a new window (see below)
Open the console, then press keys to make sure that the events are properly being registered.
Now that we know our "keydown"
events are being handled, let's figure out exactly which keys are being pressed.
-
3a) Declare a new constant variable
KEY
in the SETUP section and assign an Object to it. The object should map the following keys:"LEFT"
,"UP"
,"RIGHT"
,"DOWN"
, to their respective keycodes. For example, the keycode for the Enter key is13
:Example:
var KEY = { ENTER: 13, };
-
3b) Now, modify your
handleKeyDown
function such that it can react differently to our target keys. For example, if I wanted to print out"enter pressed"
when the Enter key is pressed, I could write:function handleKeyDown(event) { if (event.which === KEY.ENTER) { console.log("enter pressed"); } }
Modify this function such that it can print out
"left pressed"
when the left arrow is pressed. Do the same for the other three arrow keys.
TESTING: Save your code and refresh your application in the other window. Test it to make sure that the right messages are being printed to the console.
Now that we can determine which keys are being pressed, we can move on to the problem of moving the walker
game item.
This is actually a problem we've already solved in Bouncing Box. To move the box, we needed the following data:
var positionX = 0; // the x-coordinate location for the box
var speedX = 0; // the speed for the box along the x-axis
NOTE: The above code was for Bouncing Box, not for Walker, but the idea is similar.
For this project, we want to be able to move along the x-axis AND the y-axis.
FIND: Because this involves variable declarations global to the project, it should go up in the SETUP section.
CODE:
-
4a) Declare a variable for the
walker
game item (feel free to name the variablewalker
as well). This variable will need to store an object such that we can monitor and control the following information:- the x-coordinate location
- the y-coordinate location
- the speed along the x-axis
- the speed along the y-axis
-
4b) Initialize each of the four properties of this object to hold the value
0
READ:
Now that we have our data tracking in place, we need to use that data to actually move the walker
game item on each update
. This is a problem solved in Bouncing Box.
REMINDER: The below code snippets are taken directly from Bouncing Box and are not the exact code that you should use here. They are merely examples of how to solve a similar but simpler problem.
To reposition the box in Bouncing Box we wrote:
positionX += speedX; // update the position of the box along the x-axisAnd to redraw the box in the new x-location we wrote:
$("#box").css("left", positionX); // draw the box in the new location, positionX pixels away from the "left"
CODE:
- 5a) In the HELPER FUNCTIONS section, declare two new functions called
repositionGameItem()
andredrawGameItem()
. - 5b) Reference the code above to complete these two functions such that they can reposition and redraw the GameItem to move along the x-axis AND the y-axis.
- 5c) Call each function on each
newFrame
.
HINT 1: Use the "top"
CSS property to draw the box y
pixels from the "top"
HINT 2: Check what the id of the GameItem is for your jQuery statements.
HINT 3: Keep in mind that you have an object storing your data this time. There are no "positionX", "speedX", ect. variables, so you will need to use the properties of your object.
Save your code and refresh the game. If you try pressing keys you'll notice that the box isn't moving.
READ:
The box isn't moving yet because we initialized the speedX
and speedY
properties to 0
. As long as speedX
is 0
, the walker
game item will not move along the x-axis. The same goes for speedY
and the y-axis.
When we press a key, we want the walker
game item to move in that direction which we can accomplish by, for example, setting the speedX
propery to some positive number when the right arrow is pressed and setting to a negative value when the left arrow is pressed. Then, on the following newFrame
, the position of the walker
game item will be recalculated based on the the code we wrote in TODO 4.
CODE:
- 6a) Modify your
handleKeyDown
function such that when theKEY.LEFT
key is pressed, thespeedX
property is set to-5
:
if (event.which === KEY.LEFT) {
walker.speedX = -5;
}
- 6b) Do the same for the other 3 arrow keys.
Question: Why does the box only move diagonally after your press the keys?
READ:
We now have motion! However, the walker
game item doesn't stop moving once we set it off. We need some way to stop it from moving.
Ideally, the walker
game item would stop moving once we release the arrow key. This "keyup"
event can be listened for in the same way that the "keydown"
event can be listened for.
CODE:
- 7a) Similar to the code that you've already written in TODO 5, set up your program to listen for
"keyup"
events and set thespeedX
andspeedY
properties to0
whenever the arrow keys are released. This will involve both creating thehandleKeyUp
event handler function and registering it.
Your final task is to make sure that the walker object does not leave the board area.
CODE:
- 8a) Make a helper function called
wallCollision()
. In this function, use conditionals to prevent the walker object from leaving the board. You may use$("#board").width()
and$("#board").height()
to get the x coordinate of the right wall and the y coordinate of the bottom wall, respctively. You may hardcode the coordinates of the left and top walls as0
.
HINT: Do not reverse the speed if there is a collision, as this will make your object bounce. Instead, simply subtract the speed from its current position.
- 8b) Call your
wallCollision()
function from yournewFrame()
function. You will want to call it afterrepositionGameItem()
but beforeredrawGameItem()
.
What will you need to add to the setup area? What will you need to add to the core logic? What new helper functions will you need?
If you want the colors to be random, you can produce a random color with the following code:
var randomColor = "#000000".replace(/0/g, function () {
return (~~(Math.random() * 16)).toString(16);
});
There are other, less cryptic ways to produce random numbers, and you should definitely try and figure them out on your own, but if you just want a random color, this will work.
After the two players collide, make the player who is "it" turn red and move each player to the opposite corners of the screen. Try making the "it" player have a slightly slower speed so that the other player can escape more easily (and maybe make the board bigger).
Submit your work regularly. Because these files are already being tracked by your GitHub repo, you can skip the "git add" step. Instead, enter the following commands:
git commit -a -m "saving walker"
git push
Congratulations on completing Walker!