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.

Lektion 9 // Breakout Adaption // Erneute Verwirrung

5. Oktober 2012

Wir bekamen als Grundlage den rudimentären Code des Klassiker Breakout. Die Aufgabe bestand darin, eine eigene Gestaltung und ein neues Spielkonzept auf dem bestehenden Code zu auf zu bauen. Meine Idee basiert auf einer sehr simplen Geschichte. Ein Mann bekommt nach langjährigem Studium sein Diplom und geht anschliessend so richtig festen. Der Schläger der den Ball zurückgibt ist in diesem Fall sein „Abschluss Hut“. Mit jedem Brick den er getroffen/jedem Shot den er getrunken hat, wird er ein wenig mehr betrunken und fängt immer mehr an zu schwanken. So wird es mit der Zeit immer schwieriger, denn Ball aufzufangen. Lange musste ich mit random und noise herumspielen bis Max mich auf die Sinusfunktion aufmerksam machte. Für meinen Verwendungszweck perfekt. Mit jedem getroffenen Brick erhöt sich die Amplitude und der Student kann irgendwann kaum noch gerade laufen. Bricks/Shots generieren sich immer neu, so hört das Saufgelage erst auf, nachdem man aufgrund zu heftigen Schwankens den Ball nicht mehr trifft. Die Highscore entspricht den getrunkenen Shots. Einzelne Bricks fallen herunter, wenn man sie trifft. Fängt man sie auf wird man um die Hälfte weniger betrunken. Mein Fehler während der Arbeit an diesem Projekt bestand darin, das ich sehr lange Zeit an Einzelheiten herumexperimentiert habe anstatt mich dem Gesamtkonzept zu widmen. Ich fühlte mich ausserdem zuerst völlig erschlagen  von dem vielen Code. Die Aufteilung in einzelne Klassen mag zwar praktisch sein, nahm mir aber die Übersicht über den sonst schon verwirrenden Code. Nach dem Abschluss des Programmiermoduls nahm ich mir dann nochmals die Zeit mein Spiel so gut als möglich fertig zu stellen. Die Grafische Umsetzung ist nun mehr bezogen auf das Spielkonzept. Ausserdem ist es durch die sich immer wieder generierenden Bricks, ein einziges Level, welches man jedoch unendlich lang spielen könnte.

/* --------------------------------------------------------------------------
 * BreakOut
 * --------------------------------------------------------------------------
 * prog:  Max Rheiner
 * date:  26/09/2012 (m/d/y)
 * ----------------------------------------------------------------------------
 */

import ddf.minim.*;

Minim minim;
AudioSample ballHitSnd;
AudioSample ballHitSchlaegerSnd;

BouncingBall ball;
Racket       schlaeger = null;
Brick[]      brickList = null;
dropDown[]   dropDownList = null;

PImage muenze;
PImage imageStart;
PImage headbehind;

int score=0;

float dru = 0;

final static int GAME_MODE_MENU      = 0;
final static int GAME_MODE_PLAY      = 1;
final static int GAME_MODE_GAMEOVER  = 2;

int          gameMode = GAME_MODE_MENU;

float alp=0;

void setup()
{
  size(displayWidth, displayHeight);

  ball = new BouncingBall(width/2, height/2, 7);

  schlaeger = new Racket(0, height - 170, 100, 15);

  muenze = loadImage("fuenf.png");
  imageStart = loadImage("abschluss.jpeg");
  headbehind=loadImage("headbehind.jpeg");
  // sound init
  minim = new Minim(this);
  ballHitSnd = minim.loadSample("hit.mp3");
  ballHitSchlaegerSnd = minim.loadSample("hitSchlaeger.mp3");

  smooth();
  noCursor();
}

void initGameScene()
{
  dru = alp = 0;
  // setzte die start posititon des balles
  ball.set(new PVector(width/2, height/2), new PVector(random(-7, 7), -7), 1);
 score=0;
  // erzeuge die ziegel

   int randomCount = (int)random(3, 12);
   brickList = new Brick[randomCount];
   dropDownList = new dropDown[randomCount];
   for (int i=0;i < brickList.length;i++)
   {
    brickList[i] = new Brick(200 + i * 55, 200, 50, 20);
    dropDownList[i] = new dropDown(200 + i * 55, 200, 50, 20);
   }
int Zeile=13;
int Spalte=24;

  brickList = new Brick[Zeile*Spalte];
  dropDownList = new dropDown[Zeile*Spalte];

  int xZ = 75;
  int yZ = 200;

  for (int a=0;a < Zeile; a++)
  {

   for (int i=0;i < brickList.length/Zeile;i++)
    {
      if(random(1)<0.2){
        brickList[i+(brickList.length/Zeile*a)] = new Brick(xZ , yZ, 53, 20);

        dropDownList[i+(brickList.length/Zeile*a)] = new dropDown(xZ , yZ, 53, 20);
      }
        xZ += 55;

    }

    xZ = 75;
    yZ += 25;

  }

}

void draw()
{
  // ghosting
  fill(255, 100);
  rect(0, 0, width, height);

  drawScene();
}

void drawScene()
{
  switch(gameMode)
  {
  case GAME_MODE_MENU:
    drawMenu();
    break;
  case GAME_MODE_PLAY:
    drawGame();
    break;
  case GAME_MODE_GAMEOVER:
    drawGameOver();
    break;
  }
}

void drawMenu()
{
  pushStyle();

  fill(0);
//  text("Ready To Get Drunk?", 350, 200);
  image(imageStart,230,-200);
//  text("\'p\' : start game", 350, 230);
//  text("Space : stop game", 350, 250);
  popStyle();
}

void drawGameOver()
{
  pushStyle();
  fill(0);
  text("Overdose, Next Time You'll Stomache More. Shots You Drank: "+score, 350, 200);

  popStyle();
}

void drawGame()
{
  // update die daten, berechne kollisionen
  updateScene();

  // zeichne ziegel
  for (int i=0;i < brickList.length;i++)
  {
    if (brickList[i] != null)
      brickList[i].draw();
  }
   for (int i=0;i < dropDownList.length;i++)
  {
    if (dropDownList[i] != null)
      dropDownList[i].draw();
  }
  pushStyle();
  fill(0);
  text(score, 30, 30);
  popStyle();
  // zeichne den ball
  ball.draw();

  // zeichne schlaeger
  schlaeger.draw();
}

void keyPressed()
{
  switch(key)
  {
  case 'p':
    // start game
    gameMode = GAME_MODE_PLAY;
    initGameScene();
    break;
  case ' ':
    // end
    gameMode = GAME_MODE_MENU;
    break;
  }
}

void  updateScene()
{
  // test ob ball aus dem spielfeld ist
  if (ball._pos.y > height- ball._r)
  {
    gameMode = GAME_MODE_GAMEOVER;
    return;
  }

  // update schlaeger pos
 // schlaeger.move(schlaeger._pos.x+(mouseX-schlaeger._pos.x)*dru, mouseY);
   alp+=0.1;
  schlaeger.move(mouseX+sin(alp)*dru, mouseY);
  PVector hitPos = new PVector();

  // teste ob ball den schlaeger trifft
  int retVal = schlaeger.checkCollision(ball._pos.x, ball._pos.y, ball._r, ball._dir,hitPos);
  switch(retVal)
  {
  case Brick.HIT_LEFT:
  case Brick.HIT_RIGTH:
    // aendere flugrichtung ball
    ball._dir.x *= -1;

    // spiele sound
    ballHitSchlaegerSnd.trigger();
    break;
  case Brick.HIT_TOP:
  case Brick.HIT_BOTTOM:
    // aendere flugrichtung ball

    // anschnitt berechnen
    float hitV = hitPos.x - (schlaeger._pos.x - schlaeger._w/2);
    hitV = 1.0 / schlaeger._w * hitV - 0.5;

    ball._dir.x += hitV * 8;
    ball._dir.y *= -1;

    // ball soll die gleiche geschwindigkeit haben wie am anfang
    float speed = ball._dir.mag();
    ball._dir.normalize();
    ball._dir.mult(speed);

    // setzte ball buendig auf den schlaeger(das er nicht im schlaeger ist)
    ball._pos.y = schlaeger._pos.y - schlaeger._h/2 -1 ;

    // spiele sound
    ballHitSchlaegerSnd.trigger();
    break;
  }

  // test ob ball einen ziegel trifft
  for (int i=0;i < brickList.length;i++)
  {
    if (brickList[i] != null)
    {
      retVal = brickList[i].checkCollision(ball._pos.x, ball._pos.y, ball._r, ball._dir,hitPos);
      switch(retVal)
      {
      case Brick.HIT_LEFT:
      case Brick.HIT_RIGTH:
        // aendere flugrichtung ball
        ball._dir.x *= -1;

        // entferne ziegel aus liste
        //brickList[i] = null;
        brickList[i] = new Brick(int(random(25))*55+75 , int(random(13))*25+300, 53, 20);
        // spiele sound
        score++;
        ballHitSnd.trigger();
        break;
      case Brick.HIT_TOP:
      case Brick.HIT_BOTTOM:
        // aendere flugrichtung ball
        ball._dir.y *= -1;

        // entferne ziegel aus liste
         brickList[i] = new Brick(int(random(25))*55+75 , int(random(13))*25+300, 53, 20);
        score++;
        // spiele sound
        ballHitSnd.trigger();

        dru = dru + 0.5;

        break;
      }
       if (retVal != Brick.HIT_NO) {
       if(i<dropDownList.length)
        dropDownList[i].startFall();

  }

    }
  }
}