1 Interaction, Avatars & Obstacles


Introduction and framework

The language p5: Link

The p5 Reference: Link

We use the online editor for convenience: Link

The collection of sketches for this course: Link

The Golden Age of Arcade Games


Pong, Atari (1972)


Breakout, Atari (1976) (Clone)


Donkey Kong, Nintendo (1981)


Asteroids, Atari (1979)


Space Invaders, Taito (1978)


Pac-Man, Namco (1980)


Pole Position, Namco (1982)


Tetris, Alexei Paschitnow (1984)


Mario Bros., Nintendo (1983)


Basic P5

Basic anatomy of a P5 sketch

  function setup(){
  
    }
    
    function draw(){
  
    }
    

Basic drawing functions

    function setup(){
        createCanvas(600, 400);
        background(255);
        fill(0);
      }
      
      function draw(){
          ellipse(300,200,10,10);
      }
      

Common Interfaces

Keyboard

The keyboard is often the favourite controller of first person game players. But we can use the classic "WASD" keyboard controls also to control a simple Pac Man:






      function setup(){
      }
      
      function draw(){
  
      }
  
      function keyPressed() {
        if (key == "a") {
          console.log("left");
        }
        if (key == "s") {
        console.log("right");
        }
      }
          

Mouse


      function setup() {
        createCanvas(600,400);
        background(255);
      }
      
      function draw() {
        ellipse(mouseX, mouseY, 10, 10);
      }
    

Assignment
In the original game hall version of Pong, two potentiometers were used to controll the "Avatars". Can you make a simple white bar on a black ground that is moved by the mouse like in Pong?

Game Pads

Driver to map buttons of the XBox controller in OSX

Coretet by Rob Hamilton at the IEM Graz

Game-Pads


        Code
      

More recent Interfaces

Gyroscope

Gyroscope

Eyetracking

External library for eyetracking:


Programming strategies we already used

Variables

A variable is an abstract container for a value that is used in the program flow. A variable is designated by a name. The value assigned to a variable can change during the program run.

A variable may only be declared once, but its value may change (e.g. radius = radius +6). Variable names must not be reserved expressions (null, true, false, etc..), or already used by processing (e.g. mouseX). It is highly recommended to assign variable names that say something about the use of the variable (radius, width, ...). Variables are only valid for a certain part of the program, depending on where they are declared. We declare our variables at the beginning of the program (before stetup()) and will come back to this later when we use variables that are not valid everywhere.

Besides the variables that we define in the code, Processing automatically provides us with some variables that contain information about our sketch:

width contains the width of the drawing window
height the height of the drawing window
frameCount the number of the current frame since program start
mouseX, mouseY the current mouse coordinates

Conditionals

Programs are usually not an exclusively linear sequence of instructions to the computer. Besides loops they contain branches, which are coupled to certain conditions: If a key is pressed... then the music starts. If the measured temperature of an Arduino sensor drops... then start PIN 3 If the number of created circles is over 500... then stop the generative graphics.

Instead of the german "wenn...dann" the English expression "if...then" is used. A query by if...then allows to create branches in the program and to execute or not execute certain parts of the code.


        if(condition){
          commands
          ...
        }else{
          commands
          ...
        }
  

Conditions can be combined by logical operators (see example-code above). The operators are as follows:
'&&' AND
'!' NOT
'||' OR

Assignment
Can you expand our little snake game in a way that the snake comes back on the opposite side of the screen when it leaves the screen?
You can use if…then to test for its coordinates and to reposition it.

Functions

We have already used some functions for our previous programs:

setup() - is executed once at the beginning of the program
draw() - is automatically executed by the Sketch as a loop
mousePressed() - executed once when the left mouse button is pressed
keyPressed()- is executed once when a key on the keyboard is pressed

Beside the functions, which are already available through processing, you can write your own functions to structure programs. Conveniently, we write a function for certain tasks that should be done in the code. This method is especially suitable for tasks that should be executed again and again. This makes the code clearer and you save the task of writing the same lines of code over and over again.


  function drawAvatar(x, y, direction) {
    fill(240, 240, 0);
    noStroke();
    if (openMouth == true){
      openAngle = 1;
    }else{
      openAngle = 0.1;
    }
    ellipse(x, y, diameter, diameter);
    fill(0);
    if (direction == "right") {
      arc(x, y, diameter + 1, diameter + 1, -openAngle, openAngle, PIE);
    } else if (direction == "left") {
      arc(x, y, diameter + 1, diameter + 1, -openAngle-PI, openAngle-PI, PIE);
    }else if (direction == "up") {
      arc(x, y, diameter + 1, diameter + 1, -openAngle-PI/2, openAngle-PI/2, PIE);
    }else if (direction == "down") {
      arc(x, y, diameter + 1, diameter + 1, -openAngle+PI/2, openAngle+PI/2, PIE);
    }
}
          

Avatars

In computing, an avatar (also known as a profile picture or userpic) is a graphical representation of a user or the user's character or persona. It may take either a two-dimensional form as an icon in Internet forums and other online communities or a three-dimensional form, as in games or virtual worlds.

In Pong we have seen the most basic version of an Avatar, when a simple rectangle represents the player on screen.

Loading Images

We´re using an image file to represent the player on screen.

 let img;
  
  function preload() {
    img = loadImage('spaceship.png');
  }
  
  function setup() {
    createCanvas(600, 400);
  }
  
  function draw() {
    background(0);
    image(img, mouseX, 300, 100,100);
  }
          
        

Note the preload() function! It is executed before the sketch starts and the whole programme waits until all files are loaded.



Assignment
Find your own Avatar online, upload it to your sketch and use it in your programme. Make shure it is a PNG so you can have tansparencies!

PAC MAN Google Doodle

Obstacles

Arrays

Arrays are chains of variables or fields in which several values can be stored. You can use them well as a replacement for several variables. They have a name and comprise several values each of which is accessed with a key.

More on Arrays: Link

One way to generate backgrounds for game levels is to divide the screen into squares. Then the squares are filled with different types of elements.

The data is best stored in an array.

  //Array to store the level map
  var levelMap = [
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  ]
  

The array data then can be read and used to generate a 2-dimensional matrix for the background.

  for(var x = 0; x < 15; x++){ 
      for(var y=0; y < 10; y++){ 
          var tst=levelMap[y*15+x]; 
          if (tst==1){
        rect(x*stepSize+(stepSize/2), y*stepSize+(stepSize/2), stepSize, stepSize); 
      } 
    } 
  }

for-loops

  for(var i = 0; i < 10; i++){ 
    // do something
  }

More about for-loops: Link



Now that we have our background, we want to check, if our avatar runs into the orange walls.

As we know the coordinates of the walls and our avatar in the matrix of the 2D game world, we can simply compare them. Therefore, we check the coordinates of the next step each time a key is pressed. If there is a wall coming up we don`t do the step. If there is space for us to move into, we do the step.

Here`s a function that checks for upcoming walls:

 function checkObstacle(dir, x, y) {
    obstacle = false;
    linearPos = y * 15 + x;
    if (dir == "left" && levelMap[linearPos - 1] == 1) {
      obstacle = true;
    }
    if (dir == "right" && levelMap[linearPos + 1] == 1) {
      obstacle = true;
    }
    if (dir == "up" && levelMap[linearPos - 15] == 1) {
      obstacle = true;
    }
    if (dir == "down" && levelMap[linearPos + 15] == 1) {
      obstacle = true;
    }
    return obstacle;
  }