Experiment
Day 1: Review + intro to JS
Activity 1: Review HTML + CSS (15 mins)
Edit the HTML files below to do two things:
- Make it look better with different fonts, colors (especially the
background-color
and the linkcolor
), along with any other CSS you like. - Replace the joke with your own! Feel free to add in images or other HTML elements if you’d like.
Activity 2: Hello World with JS (5 mins)
console.log('Hello World')
Activity 3: Introduce JS + JS Canvas (40 mins)
Start by drawing one rectangle to the js canvas. It can be a square, like the one shown below, or it can be a rectangle of your choosing. You can change the background color and the rectangle number to whatever you’d like.
Then draw 10 rectangles onto the canvas using a for
loop:
for (let i = 0; i < 10; i++) {
// draw one rectangle here!
}
If you’re feeling inspired, play around and see what you can make!
Show Example
Day 2: P5.js animations
Activity 1: P5.js drawing (15 mins)
Here’s a duplicate of the first square we drew, this time using the P5.js library.
Note the script import on line 10 with src="../../p5.js"
inside of the rect.html
on line 10. This imports the p5.js library.
What are libraries?
A library in programming is a collection of `code` such as `functions` and `classes` which are designed to make other programmers' jobs easier (we'll cover classes tomorrow). You don't have to read all of the code inside of `p5.js` to use the library, you can simply call the functions laid out in the [p5.js documentation](https://p5js.org/reference/) and trust that the library will take care of the rest.
Be a little rebelious! Make the square a rectangle! I won’t try to stop ya ;)
Activity 2: P5.js animating (15 mins)
Here’s a fancy animation! Ooooohhhh aaaaaaaa
See if you can make a better animation! Remember to use replit’s p5.js template!
Activity 3: P5.js interactivity (30 mins)
Now we get to the real fun part! Interactivity!
In level 1 you might have been frustrated that we couldn’t interact with the fancy CSS animations. Kind of boring, I know. Well worry no longer! In JavaScript we can listen to keyboard and mouse events and react to them! Basically the computer knows when you clack on keys or move the mouse and do cool stuff when you do!
This is the start to building a fully interactive UI, like the one you’re using to read and code on!
Keyboard Input
Try using WASD to make sooo many copies of our good frind, the square.
Mouse Input
Try moving around the mouse! Fancy, I know!
Day 3: Vectors and Objects!
Today we get to learn about what makes every video game possible: vectors and objects.
Lesson 1: Vectors (45 mins)
Why Learn Vectors?
Vectors are used constantly in video games and other art to define motion for characters including rotation, position, and change in motion over time, raytracing to simulate realistic lighting, particle simulations, fancy graphics, anything involving graphics, and more!
Additional (longer) Resources!
A deeper dive into vectors specifically applied to video game design!
Vectors & Dot Product • Math for Game Devs [Part 1]
Also A deeper dive into raytracing specifically for real time rendering meaning all the calculations must happen every 16-4 milliseconds (that’s 1/1000 of a second!). I strongly recommend watching the first video before watching the second video on ray tracing.
Here’s an example which shows how to represent motion using vectors:
Playing around with the demo above should give you an intuitive feel for vectors.
The dot’s position (represented with the black line), velocity (represented with the red line), and acceleration (represented with the blue line), are controlled with the WASD keys depending on which mode is active. You can switch modes with the spacebar.
A few things to try:
- Try setting the velocity to a low value by tapping the ‘w’ key while on ‘velocity’
mode and then “fight” the velocity with your position by holding the “s” key while
on the ‘position’ mode.
- Similarly try setting the acceleration to a low value and then “fight” the acceleration with your velocity.
- Try to define position, velocity, and acceleration.
- Think about how the relationship between position and velocity is similar to the relationship between velocity and acceleration.
- Think of game ideas you could make using position, velocity, and acceleration as player-controlled values.
Lesson 2: Classes (15 mins)
Classes are like a blueprint for making objects. Objects are just fancy clusters of the same old variables you’re used to. Once we have the blueprint for one dot we can make 2, or 3, or 100, or 1000 or however many we want.
That way we can make millions of dots! Muhahahaha!
We’ll start with two though.
In this case, we’re clustering together
our position
, velocity
, acceleration
, and mode
variables into one class
which includes the functions we made that use those four variables like draw
and updateMotion
along with the helper functions that help us draw a dot and
update a dot’s motion.
We’ll also cluster controls into a class so that we can have one user use
WASD and Q to control their dot while the other user uses IJKL and O to control
theirs. That class is a little easier to write because all we need to know is
which keys we’d like to associate with up
, down
, left
, and right
along
with a way to check if they’re pressed:
class Controls {
constructor(up, left, down, right, toggle) {
this.up = up
this.left = left
this.down = down
this.right = right
this.toggle = toggle
}
isUp() {
return keyIsDown(this.up)
}
isLeft() {
return keyIsDown(this.left)
}
isDown() {
return keyIsDown(this.down)
}
isRight() {
return keyIsDown(this.right)
}
}
Then to create a control scheme it’s just one function call with the fancy new
keyword next to it because we’re creating some new
controls.
const W = 87
const A = 65
const S = 83
const D = 68
const Q = 81
const WASDQ = {
up: W,
left: A,
down: S,
right: D,
toggle: Q
}
new Controls(
WASDQ.up,
WASDQ.left,
WASDQ.down,
WASDQ.right,
WASDQ.toggle
)
Now onto the Dot
class:
class Dot {
position
velocity
acceleration
motion
constructor(controls) {
// we initiate our variables like when we had one dot
// so that the dot starts still in the top left corner
this.position = createVector(0, 0)
this.velocity = createVector(0, 0)
this.acceleration = createVector(0, 0)
this.motion = 0
// we assume controls is a Controls object created by doing
// new Controls(...)
this.controls = controls
}
// helper function for updateMotion()
getVectorBeingChanged() {
switch (this.motion) {
case 0:
return this.position
case 1:
return this.velocity
case 2:
return this.acceleration
}
}
// updates motion
// relies on the Controls class methods like isLeft, isRight, etc.
// Also does vector math to figure out the updated position, velocity, and
// acceleration for the dot.
updateMotion() {
const vector = this.getVectorBeingChanged()
const deltaVector = createVector(0, 0)
const amount = 0.1 ** (1 * this.motion)
if (this.controls.isLeft()) {
deltaVector.x -= amount
}
if (this.controls.isRight()) {
deltaVector.x += amount
}
if (this.controls.isUp()) {
deltaVector.y -= amount
}
if (this.controls.isDown()) {
deltaVector.y += amount
}
vector.add(deltaVector)
this.velocity.add(this.acceleration)
this.position.add(this.velocity)
this.keepInBounds()
}
// Maybe toggle motion checks whether the toggle key is the one that was
// most recently pressed. If so, it calls toggleMotion to change the motion
// vector that gets changed.
maybeToggleMotion() {
if (this.controls.toggle === keyCode) {
this.toggleMotion()
}
}
// helper for maybeToggleMotion
toggleMotion() {
this.motion = (this.motion + 1) % 3
}
// helper for updateMotion: keeps the dot on the screen.
// Resets velocity and acceleration along with position to
// prevent weird glitchy behavior where you get trapped against a wall.
keepInBounds() {
if (this.position.x < 0) {
this.position.x = 0
this.velocity.x = 0
this.acceleration.x = 0
}
if (this.position.x > width) {
this.position.x = width
this.velocity.x = 0
this.acceleration.x = 0
}
if (this.position.y < 0) {
this.position.y = 0
this.velocity.y = 0
this.acceleration.y = 0
}
if (this.position.y > height) {
this.position.y = height
this.velocity.y = 0
this.acceleration.y = 0
}
}
// helper for draw()
getMotionAsText() {
switch (this.motion) {
case 0:
return 'position'
case 1:
return 'velocity' // first derivative - a preview of college math
case 2:
return 'acceleration' // second derivative
}
}
// uses the variables in the class to draw out the dot along with the various
// vector variables inside the class and the current motion mode.
draw() {
fill(0)
ellipse(this.position.x, this.position.y, 10, 10)
// draw lines to show the vectors
drawVector(createVector(0, 0), this.position, 'black', 0)
drawVector(this.position, this.velocity, 'red', 1)
drawVector(this.position, this.acceleration, 'blue', 2)
stroke(0)
text(this.getMotionAsText(), this.position.x, this.position.y)
}
}
Try
Try changing the default position of the dots so that they start somewhere other than the top left! For an extra challenge, see if you can get them to start in the center of the screen.
Try adding another mode or two to the dots! Maybe make an AI mode which chases the other dot around or a gravity mode which sets acceleration to always be negative and then lets you try to “fight” against the gravity by changing the acceleration with WASD.
Day 4: Move!
Activity 1: Dinosaur Game Clone (60 mins)
This activity is challenging! I want you to try each class on your own for 5 minutes. I’ll start doing a code along in 5 minutes. If you feel confident feel free to ignore the code along and just get to coding yourself!
Player Class
Make a player controller for a P5.js rectangle with a player class that lets the player jump. Also have a drawn function like we learned yesterday. The player should only move up and down, not left and right.
A jump can be performed by setting velocity to be a high value while having acceleration be negative. Then when you hit the bottom of the screen set both velocity and acceleration to 0.
Cactus/Spike class
Make a cactus class that draws a cactus and moves to the left. Have 2-3 cacti that move at different speeds.
You can reuse cacti by teleporting cacti which they reach the far left of the screen back to the far right of the screen.
Game Loop
Points
When a cactus gets to the other side of the screen the player should get a point for successfully dodging the cactus. For an extra challenge, make the player get the point as soon as the cactus passes the player.
You can use a
this
variable like we did for the 1 dot example from yesterday.
Collision Detection/Game Over
Make a collision detection function that checks if the player is touching the cactus. If the player is touching the cactus, the game should end.
How can you tell when two rectangles intersect? Try drawing this out on paper first!
Try
Try making an end screen rather than just making the game stop running, complete with showing your total score and maybe even your high score!
Day 5: Your Turn!
Draft experiment (5 mins)
Here’s some ideas of projects you could make!
- A drawing app! Track the mouse using
mouseX and
mouseY and only draw the background
inside of the setup function. That way you can draw a circle wherever the
mouse is on each draw frame.
- Additional challenges:
- Only draw circles when mouseIsPressed
- Let the user select different colors by typing keys on the keyboard.
- Additional challenges:
- Another game! Maybe a jetpack game where you collect coins (yellow colored circles)? Maybe something else?
- Click the button challenge! Teleport a button around the screen and see how
many clicks someone can make in 3600 draw calls. After 3600 draw calls, show
the user an end screen! (3600 draw calls is around 60 seconds).
- It shouldn’t be too hard to figure out when a point will be inside of a rectangle after doing the harder version of figuring out when two rectangles are intersecting from yesterday.
- Anything else you can think of!
- I’ll try to help everyone get progress on their projects as much as I can!
- Remember! The P5.js docs are your friend!
Warning
Make sure to limit the scope of the project! You’ll only have 40 minutes to make the project, so be sure to get the basic functionality down before focusing on the smaller less important details.
Make project (40 mins)
Code up the project!
Ask for help when you get stuck! We are here to help!
Share/present projects (15 mins)
Share what you’ve made!