Category: Games and simulations

Scrolling / Camera

The whole world drawing can be wrapped in a transform matrix to simulate a “camera” following certain coordinates

...
world.step();
  background(0);
 
  pushMatrix();
 
  //translate based on the protagonist position and offset to the center of the screen
  float tx = -protagonist.getX()*zoom+width/2;
  float ty = -protagonist.getY()*zoom+height/2;
 
  translate(tx, ty);
  scale(zoom);
 
  world.draw();
  popMatrix();
...

Full example:

 
import fisica.*;
 
FWorld world;
 
FCircle protagonist;
 
float SPEED = 100;
 
float zoom = 2; //200% bigger
 
//this is for the keyboard state detection - leave it here
boolean[] keys = new boolean[526];
 
 
void setup() {
  //sketch size
  size(800, 600);
 
  //initialize the library
  Fisica.init(this);
 
  //create a new Fisica world
  world = new FWorld();
 
  //for this example we are disabling the grab
  world.setGrabbable(false);
 
  //no gravity
  world.setGravity(0, 0);
 
  protagonist = new FCircle(20);
  protagonist.setNoStroke();
  protagonist.setPosition(width/2, height/2);
  protagonist.setDamping(10);
  world.add(protagonist);
 
  for (int i = 0; i< 10; i++)
  {
    FBox box = new FBox(20, 20);
    box.setPosition(random(width), random(height));
    world.add(box);
  }
}
 
 
void draw() {
  world.step();
  background(0);
 
  pushMatrix();
 
  //translate based on the protagonist position and offset to the center of the screen
  float tx = -protagonist.getX()*zoom+width/2;
  float ty = -protagonist.getY()*zoom+height/2;
 
  translate(tx, ty);
  scale(zoom);
 
  world.draw();
  popMatrix();
 
  //normal coordinates are restored for interface overlays etc
 
  if (keyIsDown(RIGHT)) {
    protagonist.adjustVelocity(SPEED, 0);
  }
 
  if (keyIsDown(LEFT)) {
    protagonist.adjustVelocity(-SPEED, 0);
  }
 
  if (keyIsDown(DOWN)) {
    protagonist.adjustVelocity(0, SPEED);
  }
 
  if (keyIsDown(UP)) {
    protagonist.adjustVelocity(0, -SPEED);
  }
}
 
//this function is called when a key is pressed
void keyPressed() {
 
  //update the state in the array
  keys[keyCode] = true;
}
 
//this function is called when a key is released
void keyReleased() {
  println("The key "+ key+ " just went up");
 
  //update the state in the array
  keys[keyCode] = false;
}
 
//This may be a little exotic, just leave it there
boolean keyIsDown(char c) { 
  String s = c + "";
  return keyIsDown(int(s.toUpperCase().charAt(0)));
}
boolean keyIsDown(String s) { 
  return keyIsDown(int(s.toUpperCase().charAt(0)));
}
boolean keyIsDown(int code) { 
  if (keys.length >= code) { 
    return keys[code];
  } 
  return false;
}

Joints and Motors

A joint establishes some kind of relation between two or more bodies. There are different kinds of joints:

Distance Joint

A spring or a rigid connector.

 
//joints
 
import fisica.*; 
 
FWorld world;
 
void setup() {
  //sketch size in pixels
  size(800, 600);
 
  //initialize the physics library
  Fisica.init(this);
 
  //create a new Fisica world
  world = new FWorld();
 
  //set the world's properties:
  world.setEdges();
  world.setGravity(0, 0);
 
 
  FBox b1 = new FBox(70, 20);
  b1.setPosition(100, 100);
  world.add(b1);
 
  FBox b2 = new FBox(20, 50);
  b2.setPosition(300, 100);
  world.add(b2);
 
  FDistanceJoint spring = new FDistanceJoint(b1, b2);
  world.add(spring);
 
  //you can change the spring position
  //spring.setAnchor1(30, 0);
  //spring.setAnchor2(0, 40);
 
  //and make it springy. It's rigid by default
  //spring.setFrequency(0.5);
  //spring.setDamping(0.1);
 
  //By default the balance between bodies is the distance between the bodies. 
  //But it can be arbitrary: 
  //spring.setLength(60);
 
 
  //it doesn't have to be visible
  //spring.setDrawable(false);
}
 
 
void draw() {
  //update the simulation
  world.step();
  background(255);
  //redraw the physics world
  world.draw();
}//end of draw loop

See the reference for the parent class FJoint for more methods
and FDistanceJoint for distance joint specific ones

Prismatic Joint

The prismatic joint is more commonly known as a slider joint. The two joined bodies have their rotation held fixed relative to each other, and they can only move along a specified axis.

 FBox b1 = new FBox(70, 20);
  b1.setPosition(400, 200);
  world.add(b1);
 
  FBox b2 = new FBox(20, 50);
  b2.setPosition(400, 300);
  world.add(b2);
 
  FPrismaticJoint rotor = new FPrismaticJoint(b1, b2);
  world.add(rotor);
 
  //a bit bizzarre now, let's reduce some degrees of freedom.
  //b1.setStatic(true);
  //b1.setGrabbable(false);
 
  //b1.setDrawable(false);
  //rotor.setDrawable(false);
 
  // Sets whether the bodies connected by the joint should collide with each other
  // method for all joints
  //rotor.setCollideConnected(false);

Revolute joint

The revolute joint can be thought of as a hinge, a pin, or an axle. An anchor point is defined on each body, and the bodies will be moved so that these two points are always in the same place, and the relative rotation of the bodies is not restricted.

  FBox b1 = new FBox(70, 20);
  b1.setPosition(400, 200);
  world.add(b1);
 
  FBox b2 = new FBox(20, 50);
  b2.setPosition(width/2, height/2);
  world.add(b2);
 
  FRevoluteJoint axis = new FRevoluteJoint(b1, b2);
  world.add(axis);
 
  //the position of the anchor can be changed
  //axis.setAnchor(width/2, height/2);
 
  //a bit bizzarre now, let's reduce some degrees of freedom.
  //b1.setStatic(true);
  //b1.setGrabbable(false);
 
  //b1.setDrawable(false);
  //axis.setDrawable(false);
 
  // Sets whether the bodies connected by the joint should collide with each other
  // method for all joints
  axis.setCollideConnected(false);

MOtor

  //adding a motor
  axis.setEnableMotor(true);
  axis.setMotorSpeed(1000);
  axis.setMaxMotorTorque(100);

The humor and existential horror of physics games

QWOP

QWOP

Play Online
Also check Pole Riders (online & PS3)

Stair Dismount


One of the earliest ragdoll physics games. Original Mac version not online anymore

Flappy Bird

Not Tetris

NotTetris-Remake
Download PC/Mac

Also check:

“Pacman now moves absolutely realistically: Because physics”

Tug the Table

tug the table
Play online

Envirobear 2000: operation hybernation

envirobear
Download Mac/PC iPhone

Crayon Physics


Elegant walkthrough
Free demo paid full, all platforms

World of goo


Paid downloadable, all platforms

Incredipede


Paid downloadable, all platforms

Osmos


Paid download, all platforms

How do you do it?

How do you Do It
Play online

The Cat and the coup

cat-n-the-coup
Download PC/Mac

Ideas for games

I have to ideas for my games, both being these games on formalism. As of right now I would like to use the aesthetics of my “clock” piece and make it more interactive.

The first idea is an aesthetic game of tic-tac-toe in which the X’s are black and the O’s are white. The winner’s pieces then change from black or white to a black and white image of water. That being the reverse of the inverted picture of water in the background.

 

My other idea is a formal game that is more about constructing a geometric structure within the grid than actually winning a game. It is timed, so builders will have three minutes to construct something and then game over.

Here are some reference images:

Screen Shot 2014-10-14 at 9.21.39 PMother water

Animated Sprite and custom classes

Screen Shot 2014-10-23 at 9.14.56 AM
I’m not going into proper Object Oriented Programming but some of you may be interested in using or modifying a custom class I created that allows you to “attach” an animation to a fisica body (it’s still experimental):

The class is called Sprite is a custom class with an FBox (only a box for now) and an Animation (also a custom class). By custom I mean it’s not part of the Processing language or any library, it shows up as a tab in Processing and you need to have it in the same folder as the main sketch along with animation.
You declare a Sprite this way:

Sprite player;

Creating a sprite

This is how you create a new sprite. The needed parameters are: width, height, animation frames prefix, number of frames

  player = new Sprite(100, 100, "triangle_animated_", 9);

Assets: at this point Processing will try to load 9 images named “triangle_animated_0000.png” to “triangle_animated_0008.png” make sure you prepare the assets and name them properly.

Important:
– the numeration always has to start from 0000
– they must have have 4 digits in their number 0001 0002 etc
– they must be .png files so you can have transparency

Screen Shot 2014-10-23 at 9.21.34 AM

Proper game frameworks use spritesheets usually created with specialized applications or plugins. I’ll avoid them for now, I figure it’s easier to produce a series of images.

Using Sprites

The Sprite class extends FBox so it inherits all the properties and methods. You can still do things like:

player.setPosition(400, 500);
player.setName("player");
world.add(player);

Full example here: example13

Animation without fisica

You can use the Animation class independently from Sprite and Fisica and/or control it independently within the sprite (access it by yourSpriteName.animation).

Here’s an example

Game State: titles, restarting

Screen Shot 2014-10-23 at 8.47.26 AM
You typically don’t want your game to start immediately, you may want a title screen and various states before or after the proper game.

An easy way to implement these features is to use a string to keep track of the game state, e.g gameState:

String gameState = "intro";
 
...
 
void draw() {
 
 //is the state "intro"
  if(gameState == "intro")
  {
  //just draw the image and wait for input, see keyrelease function below
  image(title, 0, 0);
  }
  //update the simulation only if the state is "game"
  if(gameState == "game")
  {
  world.step();
 ...

Restart a game

There’s no straightforward way to reset a game to the initial state (variables, positions…) but there are some best practices I recommend:

1. In the setup function put all the operations that should be done only once forever: size, loading assets (loadImage, sounds, fonts). You can’t call this function again after the launch.

2. Create a game initialization function e.g. newGame() that contains all the operations setting up the game like creating a new Fisica world, creating the initial bodies, setting the score to 0 etc…

void newGame()
{
  score = 0;
  gameState = "game";
  //create a new Fisica world
  world = new FWorld();
...

3. Call the function when you reach a game over state (better if you wait for an input)

...in the draw function
if (gameState == "gameOver")
  {
    println("GAME OVER STATE");
    //press space to restart
    if (keyIsDown(' ')) {
    newGame();
    }
  }

Full example here: example11c – titles

Sounds effects with Minim

Recommended way to play a sound sample:
1) Import minim

import ddf.minim.*;

2) Initialize minim

minim = new Minim(this);

3) declare AudioPlayer object as global

AudioPlayer c2;

4) load an audio file in setup

c2 = minim.loadFile("c2.wav");

5) rewind and play the audioplayer

c2.rewind();
c2.play();
//or loop(n) for a loop
music.loop(3);

full example:

//sound with minim
 
//import minim, the sound library
import ddf.minim.*;
 
//Minim is the library it requires a main object
Minim minim;
 
//AudioPlayer is a object that contains your soundfile
AudioPlayer c2;
AudioPlayer e2;
AudioPlayer g1;
AudioPlayer music;
 
void setup() {
  //sketch size
  size(800, 600);
 
  //initialize the library 
  minim = new Minim(this);
 
  //load files
  c2 = minim.loadFile("c2.wav");
  e2 = minim.loadFile("e2.wav");
  g1 = minim.loadFile("g1.wav");
  music = minim.loadFile("percussion.mp3");
 
  //play the loop 3 times
  music.loop(3);
 
}
 
void draw() {
}
 
 
 
//this function is called when a key is pressed
void keyPressed() {
 
  if(key == 'a')
  {
    //rewind before playing
    g1.rewind();
    g1.play();
  }
 
  if(key == 's')
  {
    c2.rewind();
    c2.play();
  }
 
  if(key == 'd')
  {
    e2.rewind();
    e2.play();
  }
 
 
}
 
//it's good practice to close minim at the end
//stop is called when you shut down the program
void stop()
{
  minim.stop();
}

COLLISIONS AND SOUNDS

Here’s an example putting minima and fisica together.
example12b – sound and collisions

Snippets: random direction, screen wrap

Randomized speed:

  //randomize angle
  float angle = radians(random(360));
 
  //same speed
  float speed = 300;
 
  //break down the speed vector into x and y components
  float vX = speed * cos(angle);
  float vY = speed * sin(angle);
 
  //set the velocity
  circle.setVelocity(vX, vY);

Wrapping around the screen

//if the circle's x coordinate is < 0 teleport it to width keeping the same x
  if(circle.getX() < 0)
    circle.setPosition(width, circle.getY());
 
  if(circle.getX() > width)
    circle.setPosition(0, circle.getY());
 
  //similar and inverted for y coordinate
  if(circle.getY() < 0)
    circle.setPosition(circle.getX(), height);
 
  if(circle.getY() > height)
    circle.setPosition(circle.getX(), 0);

Full example here:

import fisica.*;
 
FWorld world;
 
FCircle circle;
 
void setup() {
  //sketch size
  size(800, 600);
 
  //initialize the library
  Fisica.init(this);
 
  //create a new Fisica world
  world = new FWorld();
 
  //for this example we are disabling the grab
  world.setGrabbable(false);
 
  //no gravity
  world.setGravity(0, 0);
 
  //create a circle
  circle = new FCircle(20);
  //appearance
  circle.setNoStroke();
  circle.setFill(255);
  //no inertia
  circle.setDamping(0);
  //make it lighter
  circle.setDensity(0.1);
  //make it bouncier
  circle.setRestitution(1);
  //no rotation
  circle.setRotatable(false);
  //set its position in the center of the sketch to the left
  circle.setPosition(400, 300);
  world.add(circle);
 
 
}
 
 
void draw() {
  world.step();
  background(0);
  world.draw(); 
 
  //if the circle's x coordinate is < 0 teleport it to width keeping the same x
  if(circle.getX() < 0)
    circle.setPosition(width, circle.getY());
 
  if(circle.getX() > width)
    circle.setPosition(0, circle.getY());
 
  //similar and inverted for y coordinate
  if(circle.getY() < 0)
    circle.setPosition(circle.getX(), height);
 
  if(circle.getY() > height)
    circle.setPosition(circle.getX(), 0);
 
}
 
void mousePressed()
{
 
 
  //randomize angle
  float angle = radians(random(360));
 
  //constant speed
  float speed = 300;
 
  //break down the speed vector into x and y components
  float vX = speed * cos(angle);
  float vY = speed * sin(angle);
 
  //set the velocity
  circle.setVelocity(vX, vY);
}

Selective collisions – shooting

Screen Shot 2014-10-21 at 1.05.53 PM
Let’s examine a series of common problems occurring when an object spawns another, e.g. shooting.

Download the example: example11b – bullets

If you don’t want certain objects to collide with some other objects give them the same groupIndex:

triangle.setGroupIndex(-1);
...
newBullet.setGroupIndex(-1);

The isBullet property makes for more precise collisions with fast moving objects

newBullet.setBullet(true);

To shoot at an angle we use the trigonometry we’ve seen before:

float bulletVX = bulletSpeed * cos(angle);
float bulletVY = bulletSpeed * sin(angle);

Collisions in Fisica

pong

Most video games are about objects bumping into each other. Fisica automatically resolves the reactions (bouncing) when two FBody collide but it’s crucial to detect when that happens in order to give the player some meaningful feedback.

These functions can be added to any fisica world to detect collisions:

//the functions contactStarted contactEnded
//are executed at the beginning and end of a contact
//that ALWAYS involves two bodies
void contactStarted(FContact c) {
 
  //c is the event object containing the information about the collision
  //for example the two bodies that can be retrieved using:
  //c.getBody1();
  //c.getBody2();
 
  //if the contact involves the triangle
  if (c.contains(triangle) )
  {
    //this condition checks if the collision happened with a
    //static body (in this case the margins)
    //I have to check both bodies
    //if (c.getBody1().isStatic()== false && c.getBody2().isStatic()==false)
 
    //remove the triangle
    world.remove(triangle);
  }
  //the triangle disappears upon contact
}
 
//similar event
void contactEnded(FContact c) {
 
  //the circle shrinks
  //if the contact involves the circle and the box
  //alternate use of c.contains
  if(c.contains(circle, box) )
  {
    //read the current size
    //note: get size only works for FCircle types of bodies
    float currentSize = circle.getSize();
    //set the size as current - 4 pixels
    float newSize = currentSize-4;
 
    //negative size may throw an error so I check it first
    if (newSize > 0)
      circle.setSize(newSize);
  }
}

This function provides an object type FContact which contains information about the collision between two, and only two, bodies, in particular the references of the bodies. This is how you get them:

FBody body1 = c.getBody1();
FBody body2 = c.getBody2();

Now I can manipulate body1 and body2 in the same way I manipulate all the FBody, changing parameters, destroying them etc.

Note: a body involved in a collision can arbitrarily be the first or the second. So you may need to do two checks.

The FContact method .contains can also be useful to verify certain conditions.

Is one of the bodies triangle which I declared as global using

FPoly triangle;
...
if (c.contains(triangle) )

Is this a contact that involves a body named “hero” and a “star”? See naming below.

if(c.contains("hero", "star"))

Full example here

Names and collisions

Often you need to discriminate collision between certain groups of bodies (e.g. bullets vs enemies) of which you don’t have direct references (i.e. they are not declared as named object globally like “FCircle circle;”).
Names come in very handy for this purpose. Also check accessing dynamically created bodies.

You can set a name at any point using setName, usually when you create and object:

newStar.setName("star");

And then check that name when the collision is detected:

if(body1.getName() == "star")

Full example here in which I want the stars but not the walls to disappear upon contact with the avatar.

You are now ready to create your first video game!
Start with Pong or Breakout.

Accessing dynamically created bodies

This example cycles through all bodied, get a reference of each and deletes them but it can be used to operate on existing bodies in general.

//import the physics library
import fisica.*;
 
//declare a global variable: our newtonian world
FWorld world;
 
void setup() {
  //sketch size
  size(800, 600);
 
  //initialize the library
  Fisica.init(this);
 
  //create a new Fisica world
  world = new FWorld();
 
  //creates the edges: 4 static bodies at the edge of the sketch
  world.setEdges();
}
 
 
void draw() {
 
   background(255);
 
   if(frameCount%10 == 0)
    {
    //create new circle 30 pix diameter
    FCircle c = new FCircle(30);
 
    //set its center position
    c.setPosition(random(50, width-50), 100);
 
    c.setFill(133, 203, 72);
    c.setNoStroke();
 
    world.add(c);
    }
 
 
  //update the simulation
  world.step();
 
  //display the results
  world.draw();
}
 
void mousePressed()
{
    //get an ArrayList with all the bodies
   //http://www.processing.org/reference/ArrayList.html
   ArrayList< FBody > bodies = world.getBodies();
 
   //cycle thrugh all bodies with a for loop
   for (int i = 0; i < bodies.size(); i++) 
   {
   //get each body and store it in a temporary variable
   FBody myBody = bodies.get(i);
 
   //do anything you would normally do with it
   //http://www.ricardmarxer.com/fisica/reference/fisica/FBody.html
 
   //don't remove certain bodies
   if(myBody != world.left && myBody != world.right && myBody != world.top && myBody != world.bottom)
     world.remove(myBody); 
 
   //*don't use body.removeFromWorld()
 
   }
 
 
}

Naming Objects

I can “tag” certain types of objects to access them selectively late.

In this example I’m naming all the boxes “box” when I create them:

b.setName("box");

…so I can find tell them apart later and change their fill at the mouse click:

if(myBody.getName() == "box")

The rest is almost the same as the examples above:

//import the physics library
import fisica.*;
 
//declare a global variable: our newtonian world
FWorld world;
 
void setup() {
  //sketch size
  size(800, 600);
 
  //initialize the library
  Fisica.init(this);
 
  //create a new Fisica world
  world = new FWorld();
 
  //creates the edges: 4 static bodies at the edge of the sketch
  world.setEdges();
}
 
 
void draw() {
 
   background(255);
 
   if(frameCount%10 == 0)
    {
    //create new circle 30 pix diameter
    FCircle c = new FCircle(30);
 
    //set its center position
    c.setPosition(random(50, width-50), 100);
 
    c.setFill(133, 203, 72);
    c.setNoStroke();
 
    world.add(c);
    }
 
   if(frameCount%10 == 5)
    {
    //create new circle 30 pix diameter
    FBox b = new FBox(30, 30);
 
    //set its center position
    b.setPosition(random(50, width-50), 100);
 
    b.setFill(133, 203, 72);
    b.setNoStroke();
 
    //tagging all the boxes with a name
    b.setName("box");
 
    world.add(b);
    }
 
 
  //update the simulation
  world.step();
 
  //display the results
  world.draw();
}
 
void mousePressed()
{
   //get an ArrayList with all the bodies
   //http://www.processing.org/reference/ArrayList.html
   ArrayList < FBody > bodies = world.getBodies();
 
   //cycle thrugh all bodies with a for loop
   for (int i = 0; i < bodies.size(); i++) 
   {
   //get each body and store it in a temporary variable
   FBody myBody = bodies.get(i);
 
   //do anything you would normally do with it
   //http://www.ricardmarxer.com/fisica/reference/fisica/FBody.html
 
   //perform an action only on bodies with a certain name
   if(myBody.getName() == "box")
     {
      myBody.setFill(random(255), random(255), random(255));
     }
 
   }
}

Game controls: input and forces

Affecting bodies dynamically
Create a fisica world and combine them with the standard Processing functions mousePressed and keyPressed:

void mousePressed()
{
//do something
}
 
//this function is called when a key is pressed
void keyPressed() {
//now you have to check which key was pressed
 
//for letters, symbols and numbers you can use the special variable 'key'
  if (key == 'a') {
    println("a pressed");
  }
 
  if (key == ' ') {
    println("space pressed");
  }
 
  //for special keys you can use keyCode and these processing constants:
  //UP, DOWN, LEFT, RIGHT, ALT, CONTROL, SHIFT, BACKSPACE, TAB, ENTER, RETURN, ESC, DELETE
  if (keyCode == SHIFT) {
    println("SHIFT Pressed");
  }
}

Find a way to:
.create a new body
.setting the position of an existing body to the mouse coordinate
.setting the rotation, the width and height of a body
.toggle the body as “static”
.remove a body
.attach and detach an image to the body

How to detect if a key is down

Processing doesn’t have a function to detect if a particular key is currently pressed. You have to use state variables or arrays in combination with keyPressed and keyReleased.
This is a very important feature in games so we’ll use a couple of custom functions from now on (this is not a fisica specific example).

//I use an array to store the state of all keys in a boolean array down true, up false
//an array is like a table or a container of variables of the same kind
boolean[] keys = new boolean[526];
 
void setup() {
  //sketch size
  size(800, 600);
}
 
 
void draw() {
 
  /*
  this is the function you can use to check if a key is currently down
  it can be used in a few ways: 
  if(keyIsDown('a'))
  if(keyIsDown("a"))
  if(keyIsDown(UP)) UP is the constant for the arrow key
  others are UP, DOWN, LEFT, RIGHT arrow keys and ALT, CONTROL, SHIFT...
  */
 
  if(keyIsDown('a'))
    println("The key A is DOWN");
 
  //you can also check if it's up
  //if(keyIsDown('a') == false)
    //println("The key A is UP");
 
}
 
//this function is called when a key is pressed
void keyPressed() {
println("The key "+ key+ " just went down");
 
//update the state in the array
keys[keyCode] = true;
}
 
//this function is called when a key is released
void keyReleased() {
println("The key "+ key+ " just went up");
 
//update the state in the array
keys[keyCode] = false; 
}
 
//This may be a little exotic, just leave it there
boolean keyIsDown(char c) { String s = c + "";
return keyIsDown(int(s.toUpperCase().charAt(0))); }
boolean keyIsDown(String s) { return keyIsDown(int(s.toUpperCase().charAt(0))); }
boolean keyIsDown(int code) { if (keys.length >= code) { return keys[code]; } return false; }

Moving things: Force, Impulse, Momentum

Screen Shot 2014-10-14 at 11.10.24 AM

Download the example

Different ways to move objects:

circle.addForce(2000, 0);
 
triangle.addTorque(100);
 
box.addImpulse(2000, 0);
 
circle.setVelocity(100, 0);
 
triangle.setAngularVelocity(radians(180));

Example: 4-way movement

Defender (1981)
Defender (1981)

When games moved from the paddle (knob to play pong) to the joystick, 4 or 8 way controls became popular and established genres and conventions like shoot ’em up, top-down (e.g. Zelda), or side scrolling brawler (e.g. Double Dragon).
Download Example

Example: move toward a point
maniac-mansion-day-of-the-tentacle_13
Point an click movements (usually in combination with path-finding algorithms to avoid obstacles) are the basis of several genres like the graphic adventure (Maniac Mansion) or the Real Time Strategy or RTS (e.g. Starcraft).
DownloadDownload Example

Example: directional movement

Asteroids (1979)
Asteroids (1979)

The 360 degree relative movement was the among the very first type of control employed in games (i.e. SpaceWar!) and it’s the basis of top down racing games. It breaks the controls into rotation and thrust, a simple interface paddle/knob + button can command very complex manoeuvres.
example08d

Assignment

Implement a control system for a body that “feels good” and responsive.

Assignment: Clock

Screen Shot 2014-10-06 at 5.47.49 PM

Using Fisica, create a 2D physics world that visualizes the passing of time
*It doesn’t necessarily have to be readable as a clock
*It can integrate standard processing elements we saw before
*Keep it abstract, don’t import images
*look up the fisica reference and use at least 2 methods I haven’t covered in class

Some inspirations here, here, and here

Timed Events (system clock, millis, frameCount)

The first assignment using Fisica will be a clock/time visualization app.

This is how to use time functions (you also have day(), month(), year()).

int s = second();  // Values from 0 - 59
int m = minute();  // Values from 0 - 59
int h = hour();    // Values from 0 - 23

They simply read your operating system’s clock.

This sketch prints 3 bars proportional to seconds minutes and hours.

int s;
int m;
int h;
 
void setup()
{
  size(250, 250);
}
 
//this function is called 60 times per second
void draw()
{
  background(0);
 
  //update variables with time and date
  s = second();
  m = minute();
  h = hour();
 
  //change fill
  fill(255, 0, 0);
  //map the lenght of my bar according to my seconds
  float sWidth = map(s, 0, 60, 0, 200);
  //draw a rectangle
  rect(0, 0, sWidth, 50);
 
  //do the same for minutes and hours
  fill(0, 255, 0);
  float mWidth = map(m, 0, 60, 0, 200);
  rect(0,100, mWidth, 50);
 
  fill(0, 0, 255);
  float hWidth = map(h, 0, 23, 0, 200);
  rect(0,200, hWidth, 50);
 
}

How to make something happen every second

int s;
int lastSecond;
 
void setup()
{
  size(200, 200);
}
 
//this function is called 60 times per second
void draw()
{
  s = second();
 
  //if the second was updated then do something once
  if (s != lastSecond)
  {
    println("A second elapsed");
    //update the last second
    lastSecond = s;
    //this variables will be the same until
    //the next second change in the clock
  }
}

Timing events using frame count
frameCount is a processing variable keeping track of the number of seconds since the launch of the program.

The Modulo operator % calculates the remainder of a division so it can be used to repeat event every -multiples of x-

void setup()
{
size(300, 300);
frameRate(60);
}
 
void draw()
{
if(frameCount%60 == 0)
  {
  background(random(255), 255, 255);
  }
 
println(frameRate);
}

millis: how to make something happen between seconds

Common problem: second() is related to the system clock but millis() count starts as you run the applet. Sometimes you need them to be in sync, for example if you want an analog clock with a second arm moving smoothly:

//the function millis() returns the time elapsed since
//the launch of the sketch in milliseconds
 
//millisRolloverTime is the time elapsed since
//the last time a second changed in milliseconds
int millisRolloverTime;
int prevSec;
 
void setup()
{
  size(100, 100);
  millisRolloverTime = 0;
}
 
void draw()
{
  background(0);
 
  if (prevSec != second () ) {
    millisRolloverTime = millis();
  }
 
  prevSec = second();
 
  int milliseconds = millis() - millisRolloverTime;
  text(second() + " " + milliseconds, 10, 20);
 
}

Putting all together in Fisica

Screen Shot 2014-10-06 at 5.00.32 PM

A couple of applications here:

import fisica.*;
 
FWorld world;
 
//declare box as global because I want to be able to access it
FBox b;
 
//same here
FPoly p;
 
//millisRolloverTime is the time elapsed since
//the last time a second changed in milliseconds
int millisRolloverTime;
int lastSecond;
 
void setup() {
  size(800, 600);
 
  Fisica.init(this);
  world = new FWorld();
 
  //creates the edges: 4 static bodies at the edge of the sketch
  world.setEdges();
 
  //their names are world.left, world.right, world.bottom, world.top 
  //set borders invisible (but still active)
  world.top.setDrawable(false);
  world.right.setDrawable(false);
  world.bottom.setDrawable(false);
  world.left.setDrawable(false);
 
  //gravity
  world.setGravity(0, 200);
 
  //create an FBox: a body 30pixels W X 50 pixels H
  b = new FBox(150, 80);
 
  //set its position in the center of the sketch to the left
  b.setPosition(width/2-100, height/2);
 
  //i don't want it to be affected by other bodies
  b.setStatic(true);
 
  //fill
  b.setFill(252, 138, 199);
  //no stroke
  b.setNoStroke();
 
  //add it to the world
  world.add(b);
 
  //create the polygon
  p = new FPoly();
  p.setNoStroke();
 
  //draw like a processing vertex point by point
  p.vertex(0, -50);
  p.vertex(14, -20);
  p.vertex(47, -15);
  p.vertex(23, 7);
  p.vertex(29, 40);
  p.vertex(0, 25);
  p.vertex(-29, 40);
  p.vertex(-23, 7);
  p.vertex(-47, -15);
  p.vertex(-14, -20);
 
  p.setFill(252, 138, 199);
 
  //the center is the position 0, 0
  p.setPosition(200, height-100);
 
  world.add(p);
}
 
 
void draw() {
 
  //change bg according to seconds using HSB mode
  colorMode(HSB, 100); //values from 0 to 99
 
  float bgHue = map(second(), 0, 59, 0, 99);
  color bgColor = color( bgHue, 20, 100);
 
  background(bgColor);
 
  //restore default RGB mode
  colorMode(RGB, 255);
 
  //calculate the current milliseconds
  if (lastSecond != second () ) {
    millisRolloverTime = millis();
  }
 
  int milliseconds = millis() - millisRolloverTime;
 
  //the box moves according to the milliseconds
  float boxRotation = map(milliseconds, 0, 999, -30, 30);
  b.setRotation(radians(boxRotation));
  //note how the rotation doesn't actually push the circles
 
  float boxPosition = map(second(), 0, 59, 200, 600);
  b.setPosition(boxPosition, 400);
 
 
  //every second I create a circle
  if (second() != lastSecond)
  {
  //create new circle 30 pix diameter
  FCircle c = new FCircle(10);
 
  //set its center position
  c.setPosition(width/2, 100);
 
  c.setFill(133, 203, 72);
  c.setNoStroke();
 
  world.add(c);
  }
 
  //every second I also apply a force and a torque to the star
  if (second() != lastSecond)
  {
   p.addImpulse(0, -1000); 
   p.addTorque(1000); 
  }
 
  //obviously update this at the end
  lastSecond = second();
 
  //simulating and drawing are separate steps
  //update the simulation
  world.step();
 
  //draw the physics world
  world.draw();
}

Hello Fisica (OOP)

Screen Shot 2014-10-06 at 3.18.01 PM
Processing is not exactly appropriate for game development for a variety of reasons but we can use it to prototype game ideas if we extend it with libraries.

Fisica is a wrapper for the most popular 2D physics engine Box2D.

This is the reference
This is a human readable tutorial

The main physics simulation takes place in an FWorld object.
But wait, what are Objects?

We can use Object Oriented Programming (OOP) without knowing how to write classes for now. Here are some general principles:

An object is a computational model of something (e.g. cat).

An object has properties that define its features and its state (the cat is Siamese, sitting on the couch, hungry…).
A properties is a variables contained within an object.

An object has behaviors described by methods (the cat is meowing, eating, dying).
A method is a function contained within an object.

An object is an instance of a class (the idea of cat is the class, my cat Felix is the instance). Think of a class as a blueprint for creating a kind of object.

Some classes can extend other classes (e.g. the class Cat extends the class Animal)

In some cases, like in fisica, objects can contain other objects (e.g. the object Room contains two Cats, each Cat has 4 Leg object).

In Processing objects are used this way (note the example shows an imaginary object Cat which is not part of Processing, this is not functional code):

 
//Declare an object
Cat felix;
 
void setup()  {    
  //Initialize an object
  felix = new Cat();
  //set a property, in this case a string
  felix.breed = "siamese";
  //set another property, in this case a integer
  felix.speed = 0;
}    
 
void draw()  {    
  background(255);  
  //Call methods on the object 
  felix.move();   
  felix.display();   
}
 
void keyPressed() {
if (keyCode == RIGHT) {
   felix.speed = 10;
}
if (keyCode == LEFT) {
   felix.speed = -10;
}
}

Now we don’t really need to know how the “move” or “display” methods are implemented in order to “use” a cat. Objects can be black boxes that take certain inputs and return certain outputs.

Fisica

This is how we set up a world in Fisica.

//Basic setup
 
//import the physics library
import fisica.*;
 
//declare a global variable: our newtonian world
FWorld world;
 
void setup() {
  //sketch size
  size(800, 600);
 
  //initialize the library
  Fisica.init(this);
 
  //create a new Fisica world
  world = new FWorld();
}
 
 
void draw() {
  //simulating and drawing are separate steps
 
  //update the simulation
  world.step();
 
  //display the results
  world.draw();
}

Let’s add a body (FBox) to the world. Add this in the setup function:

  //declare a variable FBox: a body 30pixels W X 50 pixels H
  FBox b = new FBox(30, 50);
 
  //set its position in the center of the sketch
  b.setPosition(width/2, height/2);
 
  //add it to the world
  world.add(b);

This is not just an animation, there’s a lot going on behind the scene. Try to grab the box!

World properties
Here are some properties of an FWorld we can set (also in the setup):

 
  //creates the edges: 4 static bodies at the edge of the sketch
  world.setEdges();
 
  //their names are world.left, world.right, world.bottom, world.top 
  //so you can remove them
  world.remove(world.top);
 
  //gravity
  world.setGravity(0, 100);
 
  //are objects grabbable?
  //world.setGrabbable(false);
 
  //friction and restitution (loss of velocity at collision)
  world.setEdgesFriction(0);
  world.setEdgesRestitution(1);

Bodies properties
Here are a few useful ones:

//Bodies' properties
 
//import the physics library
import fisica.*;
 
//declare a global variable: our newtonian world
FWorld world;
 
void setup() {
  //sketch size
  size(800, 600);
 
  //initialize the library
  Fisica.init(this);
 
  //create a new Fisica world
  world = new FWorld();
 
  //creates the edges: 4 static bodies at the edge of the sketch
  world.setEdges();
 
  //their names are world.left, world.right, world.bottom, world.top 
  //so you can remove them
  world.remove(world.top);
 
  //gravity
  world.setGravity(0, 100);
 
  //declare a variable FBox: a body 30pixels W X 50 pixels H
  FBox b = new FBox(30, 50);
 
  //set its position in the center of the sketch to the left
  b.setPosition(width/2 - 100, height/2);
 
  //add it to the world
  world.add(b);
 
  //Second Box
 
  //declare a variable FBox for comparison: a body 30pixels W X 50 pixels H
  FBox b2 = new FBox(30, 50);
 
  //set its position in the center of the sketch to the left
  b2.setPosition(width/2 + 100, height/2);
 
  //Setting body properties common for all types of bodies
 
  //density: grams per pixel
  b2.setDensity(3000);
  //it will fall at the same speed but it will be heavier
 
  //restitution: loss of velocity at collision (bounciness)
 //b2.setRestitution(2);
 
  //friction: loss of velocity at friction (when the body rubs against other b)
  //b2.setFriction(30);
 
  //damping: loss of velocity at movement (think of air friction)
  //try to set gravity to 0
  //b2.setDamping(10);
 
  //loss of velocity at rotation
  //b2.setAngularDamping(10);
 
  //toggle static/dynamic
  //b2.setStatic(true);
 
  //toggle roteable
  //b2.setRotatable(false);
 
  //toggle grabbing
  //b2.setGrabbable(false);
 
  //make it invisible
  //b2.setDrawable(false);
 
  //add it to the world
  world.add(b2);
 
}
 
void draw() {
 
  //simulating and drawing are separate steps
 
  //update the simulation
  world.step();
 
  background(0);
 
  //display the results
  world.draw();
}

Let’s play around with them.

Other bodies

  //declare a variable FBox: a body 30pixels W X 50 pixels H
  FBox b = new FBox(30, 50);
 
  //set its position in the center of the sketch to the left
  b.setPosition(100, height/2);
 
  //add it to the world
  world.add(b);
 
  //Circle
 
  //create new circle 30 pix diameter
  FCircle c = new FCircle(30);
 
  //set its center position
  c.setPosition(200, height/2);
 
  world.add(c);
 
  //polygon
 
  //create the variable
  FPoly p = new FPoly();
 
  //draw like a processing vertex point by point
  p.vertex(-30, -20);
  p.vertex( 30, -20);
  p.vertex( 30, 0);
  p.vertex( 10, 0);
  p.vertex( 10, 40);
  p.vertex(-10, 40);
  p.vertex(-10, 0);
  p.vertex(-30, 0);
 
  //the center is the position 0, 0
  p.setPosition(300, height/2);
 
  world.add(p);
 
 
  //lines are always static and black by default 
  //you can't grab them
  //since they have no thickness fast bodies might go through them aka "tunnelling"
 
  //point Ax, Ay, Bx, Bx 
  FLine l = new FLine(0, 0, 200, 200);
 
  //position is at 0, 0  
  l.setPosition(500, height/2);
 
  world.add(l);
 
 
  //compound body: a combination of other bodies glued together
 
  //create the pieces separately
  FBox m1 = new FBox(6, 60);
  FCircle m2 = new FCircle(20);
 
  //position them properly
  m2.setPosition(0, -30);
 
  //create a compount (like a group)
  FCompound m = new FCompound();
 
  //add the bodies to the compound with addBody
  m.addBody(m1);
  m.addBody(m2);
 
  //now the compound behaves like a single entity
  m.setPosition(400, height/2);
 
  //don't forget to add it
  world.add(m);

Changing the appearances
Screen Shot 2014-10-06 at 3.58.52 PM

You can download the example with images here