JT tutorials
Here's an index of all available tutorials (more to come!):
Start up
Here are some simple steps to get started
- Download the JT library here.
- Create a new folder and put the jt_lib javascript file and the index HTML file inside of it.
- Open the index.html file in your favorite text editor (I personally use Visual Studio Code dark theme)
- Open the index.html file in your browser, if you see a small canvas centered with gray background, congratulations, you're all set up!
- From here, simply choose a tutorial above and get creating!
Pong
Make you sure you're ready to start
Draw the bars
Create two bars objects before the app object with x, y, width, height and a color variables like so:
//Create both bars var bar1={ x:0, y:0, w:20, h:60, c:"green" } var bar2={ x:0, y:0, w:20, h:60, c:"red" }
Then inside the app.setup function, change their initial values so they both appear at the side of the screen like so:
//Initialize position of the bars bar1.x=10; bar1.y=jt.h()/2; bar2.x=jt.w()-bar2.w-10; bar2.y=jt.h()/2;
Finally draw them both by adding this at the end of the app.update function:
jt.rect(bar1); jt.rect(bar2);
Open the interactive editor to see if you got it right:
Control the bars
Add up and down movement to the bars at the start of the app.update function:
//Moving the bars var speed=4; if(jt.keyCheck("w")){ bar1.y-=speed; } if(jt.keyCheck("s")){ bar1.y+=speed; } if(jt.keyCheck("up")){ bar2.y-=speed; } if(jt.keyCheck("down")){ bar2.y+=speed; }
Don't allow the bars to go offscreen just after the previous code like so:
//Bars stay onscreen bar1.y=jt.stay(bar1.y,0,jt.h()-bar1.h); bar2.y=jt.stay(bar2.y,0,jt.h()-bar2.h);
Open the interactive editor to see if you got it right:
Create the ball
Create a ball object with x, y, width, height, velocities and color variables and add it right after the bars like so:
var ball={ x:0, y:0, w:10, h:10, vX:0, vY:0, c:"blue" }
Initialize the position of the ball in the middle and the velocities with either -1 or 1 with a respawn function, so we can use it later, put the function after the code above:
function respawn(){ ball.x=jt.w()/2; ball.y=jt.h()/2; ball.vX=jt.choose([-1,1]); ball.vY=jt.choose([-1,1]); }
Call the respawn function after initializing the bars in the app.setup function:
respawn();
Draw the ball right drawing the bars like so:
jt.rect(ball);
Open the interactive editor to see if you got it right:
Move the ball
Move the ball in the app.update function after the bars control:
//Move the ball ball.x+=ball.vX; ball.y+=ball.vY;
Make the ball bounce and respawn right after:
//Make the ball bounce if(!jt.between(ball.x,0,jt.w())){ ball.vX=ball.vX*-1; respawn(); } if(!jt.between(ball.y,0,jt.h())){ ball.vY=ball.vY*-1; ball.y=jt.stay(ball.y,0,jt.h()) }
Let's make the ball faster by adding 2 new variables in the ball object right before the color:
speed:2, initial:2, increment:0.25,
Then multiply the velocities by that speed, when the lines where we move the ball in the app.update function:
//Move the ball ball.x+=ball.vX*ball.speed; ball.y+=ball.vY*ball.speed;
Open the interactive editor to see if you got it right:
Collisions
Let's finally make the game playable by adding collisions between the bars and the ball. Since the bars and the ball are already an object with an x, a y, a width and a height, it'll be easier, so put the code right after all the movement in the app.update function:
//Collisions if(jt.cRect(bar1,ball)){ ball.vX=1; } if(jt.cRect(bar2,ball)){ ball.vX=-1; }
Let's make it more fun by making the ball go faster each time it's hit by a bar, in the same code, simply increment the speed by the increment:
//Collisions if(jt.cRect(bar1,ball)){ ball.vX=1; ball.speed+=ball.increment; } if(jt.cRect(bar2,ball)){ ball.vX=-1; ball.speed+=ball.increment; }
Let's also make the ball reset it's own speed when it respawns, so in the respawn function, simply put the ball's speed equal to it's initial speed:
ball.speed=ball.initial;
Open the interactive editor to see if you got it right:
Minor fixes
When something is drawn in the canvas, it is always drawn from the top left corner, so everything is a bit off-center, let's fix the ball's respawn function so it spawns in the middle:
ball.x=jt.w()/2-ball.w/2; ball.y=jt.h()/2-ball.h/2;
Let's also fix the ball's collision so it never goes even a big offstage on the vertical, but always go a bit offstage before scoring on the horizontal, when we make the ball bounce, change these lines:
//Make the ball bounce if(!jt.between(ball.x,-ball.w,jt.w())){ ball.vX=ball.vX*-1; respawn(); } if(!jt.between(ball.y,0,jt.h()-ball.h)){ ball.vY=ball.vY*-1; ball.y=jt.stay(ball.y,0,jt.h()-ball.h) }
Then, let's make it so that when the ball hits a bar, the ball will get teleported in the front of the bar, so it doesn't hit multiple collisions when hit from behind and gain lots of speed, add these lines in the collisions inside the app.update function:
//Collisions if(jt.cRect(bar1,ball)){ ball.vX=1; ball.x=bar1.x+bar1.w; ball.speed+=ball.increment; } if(jt.cRect(bar2,ball)){ ball.vX=-1; ball.x=bar2.x-ball.w; ball.speed+=ball.increment; }
Open the interactive editor to see if you got it right:
If you compare with the previous editor, it might not change like a lot, but it makes the game feel nicer
Score
Let's a 2 variables to keep track of the score between players, add this before creating the bars:
//Create score var score1=0; var score2=0;
Then before the ball respawns, check if it's to the left or to the right and add 1 to the correct score, add this code just before the ball respawns in the app.update function:
//Make the ball bounce if(!jt.between(ball.x,-ball.w,jt.w())){ if(ball.vX<0){ score2++; }else if(ball.vX>0){ score1++; } ball.vX=ball.vX*-1; respawn(); }
Set the text setting at the start of the app.setup function so we don't set these every frame:
//Set the text settings jt.font("Consolas"); jt.fontSize(24); jt.align("center");
Finally draw the score after drawing everything else at the end of the app.update function:
//draw the score jt.text(score1+" | "+score2,jt.w()/2,10,"black");
Open the interactive editor to see if you got it right:
Congratulations, you finished the tutorial! There is an additionnal section if you want to make the game a lot of more polished.
(Optional) Sounds
We can make the game a lot nicer with some easy to add effects, let's start with sounds, first of all we need to load a mp3 file, on this site it is already loading but in your folder you need to put a mp3 file, then link it right at the end of your index.html like this:
jt=new JT("can",app.w,app.h,60,'setup','update','app',false); jt.loadSound("assets/change.mp3","hitBar"); jt.loadSound("assets/walk.mp3","hitWall"); jt.loadSound("assets/hurt.mp3","goal");
The first parameter is the path of the file and the second is the name we're gonna use in the JT library, so change the path to your file and the names for "hit" and "goal", then play "hit" when the ball collides with a bar:
//Collisions if(jt.cRect(bar1,ball)){ ball.vX=1; ball.x=bar1.x+bar1.w; ball.speed+=ball.increment; jt.stopPlay("hitBar"); } if(jt.cRect(bar2,ball)){ ball.vX=-1; ball.x=bar2.x-ball.w; ball.speed+=ball.increment; jt.stopPlay("hitBar"); }
Then let's play another sound when the ball hits the screen border:
if(!jt.between(ball.y,0,jt.h()-ball.h)){ ball.vY=ball.vY*-1; ball.y=jt.stay(ball.y,0,jt.h()-ball.h) jt.stopPlay("hitWall"); }
Now let's play the last sound when someones score a point:
//Make the ball bounce if(!jt.between(ball.x,-ball.w,jt.w())){ if(ball.vX<0){ score2++; }else if(ball.vX>0){ score1++; } ball.vX=ball.vX*-1; respawn(); jt.stopPlay("goal"); }
Open the interactive editor to see if you got it right:
(Optional) Ploish
We can make the game a lot nicer with some easy to add effects, let's initialize the camera to add some screen shake, at the end of the app.setup function add this:
//Activate the camera jt.camActive(true);
We can make the game a lot nicer with some easy to add effects, let's add some screen shake when someone scores a goal, so right when the ball scores, add this:
//Make the ball bounce if(!jt.between(ball.x,-ball.w,jt.w())){ if(ball.vX<0){ score2++; }else if(ball.vX>0){ score1++; } ball.vX=ball.vX*-1; jt.shake(20); respawn(); jt.stopPlay("goal"); };
Let's also make it so that when the ball hits a bar, depending on where it hits the bar it will go in that direction, so let's add some code to the bar collision in the app.update function. It will calculate the angle from both object's middle and then transform that into a value between -1 and 1:
//Collisions if(jt.cRect(bar1,ball)){ ball.vX=1; var barMiddle={x:bar1.x+bar1.w/2,y:bar1.y+bar1.h/2}; var ballMiddle={x:ball.x+ball.w/2,y:ball.y+ball.h/2}; var angle=jt.angle(barMiddle,ballMiddle); ball.vY=jt.ratioY(angle); ball.x=bar1.x+bar1.w; ball.speed+=ball.increment; jt.stopPlay("hitBar"); } if(jt.cRect(bar2,ball)){ ball.vX=-1; var barMiddle={x:bar2.x+bar2.w/2,y:bar2.y+bar2.h/2}; var ballMiddle={x:ball.x+ball.w/2,y:ball.y+ball.h/2}; var angle=jt.angle(barMiddle,ballMiddle); ball.vY=jt.ratioY(angle); ball.x=bar2.x-ball.w; ball.speed+=ball.increment; jt.stopPlay("hitBar"); }
Open the interactive editor to see if you got it right:
Hope you enjoyed this additionnal polish tutorial! I basically kept adding polish to a basic pong game to make my game "Xtreme Pong", you can play it here.