Willkommen auf unserem Seminar-Blog

Immer auf dem aktuellen Stand bleiben

Dieser Seminar-Blog befindet sich noch im Aufbau und wird in den kommenden Tagen entsprechend verfeinert.

Member Login

Lost your password?

Registration is closed

Sorry, you are not allowed to register by yourself on this site!

You must either be invited by one of our team member or request an invitation by email at viad.info {at} zhdk {dot} ch.

01 Keyboard Hack

2. November 2011

Gruppenarbeit: Dominik Stucky, Diego Martinez In der erste Aufgabe haben wir eine (Mac-) Tastatur aufgeschraubt und den Controller ausgebaut. Auf dem Controller befinden sich zwei Blöcke mit Anschlüssen, welche wir mit einem Kabel jeweils verbunden haben. Mittels “Reverse Engineering” konnten wir so den verschiedenen Kombinationen Buchstaben zuordnen. Hat man ein paar Kombinationen gefunden, kann man an diese nun eigene Controller wie Taster anbauen. Idee Unsere Grundidee ist simpel – ein Spiel. Für dieses Spiel wird ein Ball und ein Pingpong-Schläger benutzt. Auf dem Schläger gibt es einen kleinen Kreis und einen Kreisring. Trifft man den Kreis mit dem Ball gewinnt man einen Punkt, trifft man jedoch den Kreisring wird ein Punkt abgezogen. Very Simple, but Fun! Problematiken Unser einziges Problem war, dass wir die beiden Aluminiumfelder nur durch ein Stück Papier getrennt hatten. Das Papier isolierte jedoch nicht gut genug. Die Lösung war auch simpel – Karton. Interaktionsstil Als Interaktionsstil haben wir uns für ein Ball entschieden. Welcher durch das Auftreffen auf ein Feld eine Aktion auslöst. Programmierung In Processing haben wir ein Interface programmiert, das als Feedbacksystem des Interface dient. Darauf werden die Treffer angezeigt, Fehler führen zu einem Abzug. Ziel des Spiels ist es die inneren Blöcke alle mit gültigen Hits auszufüllen. Links und rechts werden jeweils noch die gesamthaften Treffer und Fehler aufgelistet.

Innere Fläche löst einen Hit aus, die äussere einen Fehler

Treffer in die Mitte werden belohnt, Treffer am Rand haben einen Abzug zur Folge

Spiel erfolgreich beendet

Processing-Code
// AUFGABE 01: KEYBOARD HACK
// Embodied Interaction Design Basics
// Moritz Kemper, IAD Physical Computing Lab
// ZHdK, 30/10/2011

//**
//* PPGAME
//* Ping Pong Bat as Interface and Game Controller
//* Project by Dominik Stucky & Diego Martinez
//* ZHdK VIAD 2011
//*
//* INSTRUCTIONS
//* Key 'm' sets a hit
//* key 'n' removes a hit
//*

// libraries
import ddf.minim.*;
//import ddf.minim.analysis.*;
import fullscreen.*;

SoftFullScreen fs;
AudioPlayer song;
AudioPlayer ping;

int maxHits = 100;
int counterValid = 0;
int counterWrong = 0;
int counterMain = 0;
int hitsWidth = 36;

float numRows = 10; // number of rows
float numCols = 6; // number of columns
float marginSquare = 10;

float hitsYStart;
float hitsY;
float hitsXStart;
float hitsX;

float colsValidWrong = 12;
float hitsYwrongStart;
float hitsYwrong;
float hitsXwrongStart;
float hitsXwrong;
float hitsYvalidStart;
float hitsYvalid;
float hitsXvalidStart;
float hitsXvalid;

PImage b;
ArrayList animationHits = new ArrayList(); // sets of values for animation

void setup() // setup() routine
{
  size(1024, 600);
  background(255);
  smooth();
  frameRate(24);

  // Sound
  Minim minim = new Minim(this);
  song = minim.loadFile("mariosong.wav", 1024);
  song.loop();
  song.play();

  ping = minim.loadFile("wetbox_schritte_schuhe1.aiff", 1024);

  hitsXStart = (width-((hitsWidth+marginSquare)*numCols))/2 +marginSquare/2;
  hitsYStart = (height-((hitsWidth+marginSquare)*numRows))/2+marginSquare/2;
  hitsX = hitsXStart;
  hitsY = hitsYStart;

  hitsXwrongStart = marginSquare;
  hitsYwrongStart = hitsYStart;
  hitsXwrong = hitsXwrongStart;
  hitsYwrong = hitsYwrongStart;

  hitsXvalidStart = width - ((hitsWidth/2+marginSquare))*colsValidWrong;
  hitsYvalidStart = hitsYStart+marginSquare;
  hitsXvalid = hitsXvalidStart;
  hitsYvalid = hitsYvalidStart;

  b = loadImage("testblock.png");

  for(int nr=1; nr<=numRows; nr++) {
     for(int nc=1; nc<=numCols; nc++) {
        //* INI HITS *
        hitsX = hitsXStart+(hitsWidth+marginSquare)*(nc-1);
        hitsY = hitsYStart+(hitsWidth+marginSquare)*(nr-1);
        animationHits.add(new AnimHit(hitsX, hitsY, false));
     }
  }

  // fullscreen
  fs = new SoftFullScreen(this); // add (... ,1) to display on second display
  //fs.setShortcutsEnabled(true); // enable shortcut (cmd f)
  fs.enter();
}

void draw() // Empty draw() to keep the programm running
{

  background(10);
  hitsXwrong = hitsXwrongStart;
  hitsYwrong = hitsYwrongStart;
  //* background squares *
  for(int vnr=1; vnr<=counterWrong; vnr++) {
         //* INI HITS *
          pushStyle();
             fill(102,0,0);
             noStroke();
             rect(hitsXwrong, hitsYwrong, hitsWidth/2, hitsWidth/2);
          popStyle();
        hitsXwrong+= (hitsWidth/2+marginSquare);
      if (vnr%colsValidWrong==0) {
            hitsXwrong = hitsXwrongStart;
            hitsYwrong+= (hitsWidth/2+marginSquare);
          }
   }

  pushMatrix();
  rotate(radians(180));
  translate(-1*width-hitsXvalidStart+marginSquare, -1*height-marginSquare);
  hitsXvalid = hitsXvalidStart;
  hitsYvalid = hitsYvalidStart;
  //* background squares *
  for(int vnr=1; vnr<=counterValid; vnr++) {
         //* INI HITS *
          pushStyle();
             fill(0,102,0);
             noStroke();
             rect(hitsXvalid, hitsYvalid, hitsWidth/2, hitsWidth/2);
          popStyle();
        hitsXvalid+= (hitsWidth/2+marginSquare);
      if (vnr%colsValidWrong==0) {
            hitsXvalid = hitsXvalidStart;
            hitsYvalid+= (hitsWidth/2+marginSquare);
          }
   }
  popMatrix();

  pushMatrix();
    rotate(radians(180));
    translate(-1*width, -1*height);

    //* background squares *
    for(int nr=1; nr<=numRows; nr++) {
       for(int nc=1; nc<=numCols; nc++) {
          //* INI HITS *
          hitsX = hitsXStart+(hitsWidth+marginSquare)*(nc-1);
          hitsY = hitsYStart+(hitsWidth+marginSquare)*(nr-1);
          pushStyle();
             fill(26,26,26);
             strokeWeight(1);
             stroke(51,51,51);
             rect(hitsX, hitsY, hitsWidth, hitsWidth);
          popStyle();
       }
    }

  //pushStyle();
    for(int i=0; i<counterWrong; i++) {
      image(b, (width-(width/4))+(hitsWidth/2)+i*25, 0);
    }
    fill(255,0,0);
    noStroke();
  popStyle();*/

    //* HIT CIRCLE *
    for(int i=0; i<animationHits.size(); i++)
    {
      AnimHit animHit = (AnimHit)animationHits.get(i);
      animHit.update();
    }
  popMatrix();

}

void keyPressed() // Do something if a key is pressed (I/O)
{
  switch(key) // Find out which key is pressed
  {
  case 'm':
    // VALID
    if (counterMain>=0 && counterMain<numCols*numRows) {
      counterValid++;
      // start animation
      AnimHit animHit = (AnimHit)animationHits.get(counterMain);
      animHit.valid=true;
      animHit.reset();
      counterMain++;
      //println(counterMain + " :: " + animationHits.size());
      //if(!ping.isPlaying()){
      //  ping.rewind();
      //  ping.play();
      //}
    }
    break;
  case 'n':
    // INVALID
    if (counterMain>0 && counterMain<=numCols*numRows) {
      counterWrong++;
      counterMain--;
      // reset animation (set valid false)
      AnimHit animHit = (AnimHit)animationHits.get(counterMain);
      animHit.valid=false;
      animHit.reset();
      //println(counterMain + " :: " + animationHits.size());
    }
    break;
  }
}

// NOT YET IN USE
void keyReleased() // Do something if a key is released (I/O)
{
  switch(key) // Find out which key is released
  {
  case 'a':
    // Do something if 'a' is released
    break;
  case 'b':
    // Do something if 'b' is released
    break;
  }
}

// * CLASS AnimHit
//* drawing and animation of hits

class AnimHit {

  float radiusV, radiusN, x, y;
  float strW;
  boolean valid;
  boolean highlighted;

  // constructor
  AnimHit (float extX, float extY, boolean extValid) {
    x = extX;
    y = extY;
    valid = extValid;
    reset();
  }

  // reset values
  void reset() {
    radiusV = 0;
    radiusN = 0;
    strW = 10;
    highlighted = false;
  }

  // update animation
  void update() {

    if (valid==true) {
      // draw rectangle
      pushStyle();
      noStroke();
      if (valid==true) {
        println(counterMain);
        fill(0,255,0);
        if (counterMain>=numCols*numRows) {
          if (highlighted==false) {
            fill(255,255,255);
            highlighted=true;
          } else {
            fill(0,255,0);
            highlighted=false;
          }
        }
      } else {
        //fill(255,0,0);
      }
      rect(x, y, hitsWidth, hitsWidth);
      popStyle();
    }

    // draw hit animation
      if (strW>0.1) {
        if (valid==true) {
          radiusV += 10;
          strW*= 0.85;
          pushStyle();
          noFill();
          stroke(0,255,0);
          strokeWeight(strW);
          ellipse(x+(hitsWidth/2),y+(hitsWidth/2),radiusV,radiusV);
          popStyle();
        } else {
          radiusN += 10;
          strW*= 0.85;
          pushStyle();
          noFill();
          stroke(204,0,0); strokeWeight(strW);
          ellipse(x+(hitsWidth/2),y+(hitsWidth/2),radiusN,radiusN);
          popStyle();
        }
      } else {
        strokeWeight(0);
      }
  }
}