Skip to content

lpagg/floppy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 

Repository files navigation

đź’ľ floppy đź’ľ

floppy is a micro game engine for beginners written in javascript.

  • it has basic primitives for drawing (rectangles, circles, lines, text)
  • it includes interaction (click, tap)
  • it includes sound (generated)
  • it comes with a (simple) web editor online and ...
  • ... with a tutorial to write your first game (simple, but complete)

Index

Tutorial

Commands

Editor

Thanks and Inspiration

Tutorial

In this tutorial we will create a squash like game.

Step 0

When opening the web editor default code include two functions (update and render) with empty body.

Code

function update() {

}
function render() {

}

What it is inside those functions it is executed continuosly (about 60 times each second). First the update function, then the render function.

Result

Step 1 - Coloring Background

In order to color the whole game window with a light blue, we add a Rect command to the render function.

Code

function update() {

}
function render() {
Rect(0,0,WIDTH,HEIGHT,"lightblue"); // NEW
}

WIDTH is a constant = 320 = the whole width of game window

HEIGHT is a constant = 480 = the whole height of game window

Result

Step 2 - Drawing Pad

To draw the pad, first we define four new variables (padX, padY, padW, padH) and then add a Rect command (using those variables).

Code

padX=100; // NEW
padY=430; // NEW 
padW=120; // NEW
padH=15; // NEW
function update() {

}
function render() {
Rect(0,0,WIDTH,HEIGHT,"lightblue");
Rect(padX,padY,padW,padH,"green"); // NEW
}

Result

Step 3 - Drawing Ball

To draw the ball, first we define its variables (ballX, ballY, ballR) and then add a Circle command (using those variables).

Code

padX=100;
padY=430;
padW=120;
padH=15;
ballX=160; // NEW
ballY=70; // NEW
ballR=16; // NEW
function update() {

}
function render() {
Rect(0,0,WIDTH,HEIGHT,"lightblue");
Rect(padX,padY,padW,padH,"green");
Circle(ballX,ballY,ballR,"red"); // NEW
}

Result

Step 4 - Moving Ball

To move the ball we update its position (ballX, ballY).

Three new variables are defined in order to manage the update (dirX, dirY, speed).

Code

padX=100;
padY=430;
padW=120;
padH=15;
ballX=160;
ballY=70;
ballR=16;
dirX=1; // NEW
dirY=1; // NEW
speed=2; // NEW
function update() {
ballX=ballX+dirX*speed; // NEW
ballY=ballY+dirY*speed; // NEW
}
function render() {
Rect(0,0,WIDTH,HEIGHT,"lightblue");
Rect(padX,padY,padW,padH,"green");
Circle(ballX,ballY,ballR,"red"); // NEW
}

Result

Step 5 - Bounching Right

When the ball reaches the right border of game window we set dirX to -1 in order to have the ball bounching.

Code

padX=100;
padY=430;
padW=120;
padH=15;
ballX=160;
ballY=70;
ballR=16;
dirX=1;
dirY=1;
speed=2;
function update() {
if (ballX + ballR > WIDTH) { // NEW
dirX=-1; // NEW
} // NEW 
ballX=ballX+dirX*speed;
ballY=ballY+dirY*speed;
}
function render() {
Rect(0,0,WIDTH,HEIGHT,"lightblue");
Rect(padX,padY,padW,padH,"green");
Circle(ballX,ballY,ballR,"red"); 
}

Step 6 - Bounching Left

When the ball reaches the left border of game window we set dirX to 1 in order to have the ball bounching.

Code

padX=100;
padY=430;
padW=120;
padH=15;
ballX=160;
ballY=70;
ballR=16;
dirX=1;
dirY=1;
speed=2;
function update() {
if (ballX + ballR > WIDTH) {
dirX=-1;
}
if  (ballX < ballR) {  // NEW
dirX=1;  // NEW 
}  // NEW
ballX=ballX+dirX*speed;
ballY=ballY+dirY*speed;
}
function render() {
Rect(0,0,WIDTH,HEIGHT,"lightblue");
Rect(padX,padY,padW,padH,"green");
Circle(ballX,ballY,ballR,"red"); 
}

Step 7 - Bounching Top

When the ball reaches the top border of game window we set dirY to 1 in order to have the ball bounching.

Code

padX=100;
padY=430;
padW=120;
padH=15;
ballX=160;
ballY=70;
ballR=16;
dirX=1;
dirY=1;
speed=2;
function update() {
if (ballX + ballR > WIDTH) {
dirX=-1;
}
if  (ballX < ballR) { 
dirX=1; 
}
if  (ballY < ballR) { // NEW
dirY=1; // NEW
} // NEW
ballX=ballX+dirX*speed;
ballY=ballY+dirY*speed;
}
function render() {
Rect(0,0,WIDTH,HEIGHT,"lightblue");
Rect(padX,padY,padW,padH,"green");
Circle(ballX,ballY,ballR,"red"); 
}

Step 8 - Moving Pad

To move the pad, when TAPPED is true, we set the position of the pad taking the x position of our tapping (TAPX).

Code

padX=100;
padY=430;
padW=120;
padH=15;
ballX=160;
ballY=70;
ballR=16;
dirX=1;
dirY=1;
speed=2;
function update() {
if (ballX + ballR > WIDTH) {
dirX=-1;
}
if  (ballX < ballR) { 
dirX=1; 
}
if  (ballY < ballR) {
dirY=1;
}
if (TAPPED) { // NEW
padX=TAPX-padW/2; // NEW
} // NEW
ballX=ballX+dirX*speed;
ballY=ballY+dirY*speed;
}
function render() {
Rect(0,0,WIDTH,HEIGHT,"lightblue");
Rect(padX,padY,padW,padH,"green");
Circle(ballX,ballY,ballR,"red"); 
}

Result

Step 9 - Bounching Pad

When the ball reaches the pad we set dirY to -1 in order to have the ball bounching on the pad.

Code

padX=100;
padY=430;
padW=120;
padH=15;
ballX=160;
ballY=70;
ballR=16;
dirX=1;
dirY=1;
speed=2;
function update() {
if (ballX + ballR > WIDTH) {
dirX=-1;
}
if  (ballX < ballR) { 
dirX=1; 
}
if  (ballY < ballR) {
dirY=1;
}
if (TAPPED) {
padX=TAPX-padW/2;
}
if  ( (ballX >padX)  &&  (ballX <padX+padW)  &&  (ballY+ballR>padY)  )  { // NEW
dirY=-1; // NEW
} // NEW
ballX=ballX+dirX*speed;
ballY=ballY+dirY*speed;
}
function render() {
Rect(0,0,WIDTH,HEIGHT,"lightblue");
Rect(padX,padY,padW,padH,"green");
Circle(ballX,ballY,ballR,"red"); 
}

Step 10 - Restarting Ball

If the ball crosses the pad games is restarted from initial position.

Code

padX=100;
padY=430;
padW=120;
padH=15;
ballX=160;
ballY=70;
ballR=16;
dirX=1;
dirY=1;
speed=2;
function update() {
if (ballX + ballR > WIDTH) {
dirX=-1;
}
if  (ballX < ballR) { 
dirX=1; 
}
if  (ballY < ballR) {
dirY=1;
}
if (TAPPED) {
padX=TAPX-padW/2;
}
if  ( (ballX >padX)  &&  (ballX <padX+padW)  &&  (ballY+ballR>padY)  )  { 
dirY=-1; 
} 
if  ( ballY+ballR > padY+padH )   { // NEW
ballX=160; // NEW
ballY=70; // NEW
}
ballX=ballX+dirX*speed;
ballY=ballY+dirY*speed;
}
function render() {
Rect(0,0,WIDTH,HEIGHT,"lightblue");
Rect(padX,padY,padW,padH,"green");
Circle(ballX,ballY,ballR,"red"); 
}

Step 11 - Adding Score

In order to manage and show the score, we add a new variable (score) and we use the Text command in the render function.

Code

padX=100;
padY=430;
padW=120;
padH=15;
ballX=160;
ballY=70;
ballR=16;
dirX=1;
dirY=1;
speed=2;
score=0; // NEW
function update() {
if (ballX + ballR > WIDTH) {
dirX=-1;
}
if  (ballX < ballR) { 
dirX=1; 
}
if  (ballY < ballR) {
dirY=1;
}
if (TAPPED) {
padX=TAPX-padW/2;
}
if  ( (ballX >padX)  &&  (ballX <padX+padW)  &&  (ballY+ballR>padY)  )  { 
dirY=-1;
score=score+10; // NEW
} 
if  ( ballY+ballR > padY+padH )   { 
ballX=160; 
ballY=70; 
}
ballX=ballX+dirX*speed;
ballY=ballY+dirY*speed;
}
function render() {
Rect(0,0,WIDTH,HEIGHT,"lightblue");
Rect(padX,padY,padW,padH,"green");
Circle(ballX,ballY,ballR,"red");
Text(score,50,50,30,"green"); // NEW
}

Step 12 - Adding Lifes

To manage multiple lifes, we add a new variable (lifes). We set it initially to 3 and we subtract 1 every time we lose a ball.

Code

padX=100;
padY=430;
padW=120;
padH=15;
ballX=160;
ballY=70;
ballR=16;
dirX=1;
dirY=1;
speed=2;
score=0; 
lifes=3; // NEW
function update() {
if (ballX + ballR > WIDTH) {
dirX=-1;
}
if  (ballX < ballR) { 
dirX=1; 
}
if  (ballY < ballR) {
dirY=1;
}
if (TAPPED) {
padX=TAPX-padW/2;
}
if  ( (ballX >padX)  &&  (ballX <padX+padW)  &&  (ballY+ballR>padY)  )  { 
dirY=-1;
score=score+10; 
} 
if  ( ballY+ballR > padY+padH )   { 
ballX=160; 
ballY=70;
lifes=lifes-1; // NEW
}
if (lifes==0)  { // NEW
speed=0; // NEW
} // NEW
ballX=ballX+dirX*speed;
ballY=ballY+dirY*speed;
}
function render() {
Rect(0,0,WIDTH,HEIGHT,"lightblue");
Rect(padX,padY,padW,padH,"green");
Circle(ballX,ballY,ballR,"red");
Text(score,50,50,30,"green");
Text(lifes,250,50,30,"red"); // NEW
}

Step 13 - Adding Challenge

To add a challenge in the game, we increase the ball speed by 0.2 at each bounch on the pad.

Code

padX=100;
padY=430;
padW=120;
padH=15;
ballX=160;
ballY=70;
ballR=16;
dirX=1;
dirY=1;
speed=2;
score=0; 
lifes=3; 
function update() {
if (ballX + ballR > WIDTH) {
dirX=-1;
}
if  (ballX < ballR) { 
dirX=1; 
}
if  (ballY < ballR) {
dirY=1;
}
if (TAPPED) {
padX=TAPX-padW/2;
}
if  ( (ballX >padX)  &&  (ballX <padX+padW)  &&  (ballY+ballR>padY)  )  { 
dirY=-1;
score=score+10;
speed=speed+0.2; // NEW
} 
if  ( ballY+ballR > padY+padH )   { 
ballX=160; 
ballY=70;
lifes=lifes-1; 
}
if (lifes==0)  { 
speed=0; 
} 
ballX=ballX+dirX*speed;
ballY=ballY+dirY*speed;
}
function render() {
Rect(0,0,WIDTH,HEIGHT,"lightblue");
Rect(padX,padY,padW,padH,"green");
Circle(ballX,ballY,ballR,"red");
Text(score,50,50,30,"green");
Text(lifes,250,50,30,"red"); 
}

Step 14 - Adding Sound

Last enrichment. We add a sound (generic) when bounching using the SoundEffect command.

Code

padX=100;
padY=430;
padW=120;
padH=15;
ballX=160;
ballY=70;
ballR=16;
dirX=1;
dirY=1;
speed=2;
score=0; 
lifes=3; 
function update() {
if (ballX + ballR > WIDTH) {
dirX=-1;
SoundEffect (); //
}
if  (ballX < ballR) { 
dirX=1;
SoundEffect (); //
}
if  (ballY < ballR) {
dirY=1;
SoundEffect (); //
}
if (TAPPED) {
padX=TAPX-padW/2;
}
if  ( (ballX >padX)  &&  (ballX <padX+padW)  &&  (ballY+ballR>padY)  )  { 
dirY=-1;
score=score+10;
speed=speed+0.2;
SoundEffect (); //
} 
if  ( ballY+ballR > padY+padH )   { 
ballX=160; 
ballY=70;
lifes=lifes-1; 
}
if (lifes==0)  { 
speed=0; 
} 
ballX=ballX+dirX*speed;
ballY=ballY+dirY*speed;
}
function render() {
Rect(0,0,WIDTH,HEIGHT,"lightblue");
Rect(padX,padY,padW,padH,"green");
Circle(ballX,ballY,ballR,"red");
Text(score,50,50,30,"green");
Text(lifes,250,50,30,"red"); 
}

Step 15 - Publishing Online

We can finally publish the game using HTML Pasta.

Here the game published online. Game.

Commands

Game Loop

function update() {};
function render() {};

Draw

Rect

Rect(x, y, w, h, "color");

Circle

Circle(x, y, r, "color");

Text

Text("text", x, y, size, "color");

Line

Line(x_init, y_init, x_end, y_end, width, "color");

Constants

WIDTH
HEIGHT

Interaction

TAPPED
TAPX
TAPY

Sound

SoundEffect(frequencyValue, attack, decay, type, volumeValue, panValue, wait, pitchBendAmount, reverse, randomValue, dissonance,  echo,    reverb, timeout);

more information @: https://github.com/kittykatattack/sound.js#generating-sound-effects-and-music

Utils

Random(min, max); // Random integer from min to max
PitchToFrequency(octave, semitone); // Frequency from octave (integer), semitone (integer)

Editor

web editor

with:

  • live preview
  • syntax warnings
  • saving game
  • exporting game
  • using offline

Thanks and Inspirations

For game engine: How To Design A Mobile Game With HTML5

For approach: pico-8

For sound: sound.js

About

a micro game engine for beginners

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published