Wednesday, 9 March 2011

_13_Object

//Objects
//
//So far we have been using simple variables of
//either type 'int' or type 'boolean'.  These are
//called primative types because they are just raw
//data and can only store one value -- they don't
//have any other properties apart from the value
//you set them to.  Most of the time it is more useful
//to use more complex data types which have more than
//one value in them.
//
//For example, if you need to store today's date in your
//programme, you would probably make some int variables
//like this:
//
//  int day = 9;
//  int month = 3;
//  int year = 2011;
//
//This is fine if you are just handling one date but it
//gets really awkward if you need to store lots of dates,
//say for a calender programme.  Another problem is that
//the seperate variables aren't connected in any way even
//though they all belong to the same date.  A better way
//to store the numbers is to wrap them up into a new data
//type by writing a 'class':
//
//  class Date {
//    int day;
//    int month;
//    int year;
//  }
//
//When these three variable declarations are wrapped into
//a class they become a new 'complex' type.  Now we can
//make a variable which has 'Date' as its type:
//
//  Date myBirthday = new Date();
//
//The variable 'myBirthday' has three integers inside it
//with the names we gave them in the Date class.
//You can get at the individual variables like this:
//
//  myBirthday.day = 13;
//
//You write the name of the Date variable followed by a dot
//followed by the name of integer you want to access.
//Using classes is a lot neater than having lots of integer
//variables in your code.
//
//A class can have any kind of variable inside it that you
//want.

//Integer variables
int SCORE = 0;

//Constants
final int blockPoints = 10;

final int screenWidth = 480;
final int screenHeight = 800;

final int blocksPerRow = 10;
final int numRows = 4;
final int blockWidth = screenWidth / blocksPerRow;
final int blockHeight = 20;
final int firstRowYPos = 50;

//Boolean 'flags'
boolean gamePlaying = true;
boolean winner = false;


int [ ] [ ] theBlocks = new int[ numRows ] [ blocksPerRow ];


class Ball {
  final int Size = 10;
 
  int X = 240;
  int Y = 400;

  int Xspeed = 5;
  int Yspeed = -5;
}


class Bat {
  final int Size = 50;
  final int Height = 25;

  int X = 240;
  int Y = 700;
}


Ball ball = new Ball();
Bat bat = new Bat();

//===================================
void setup() {
  size( screenWidth, screenHeight );
  background( 0 );
  noCursor();
 
  setupBlockRows();
}

//
//The draw function is nice and simple
//====================================
void draw() {
  background( 0 );
 
  if( gamePlaying && !winner ) {
    drawScore();
    drawBlocks();
    moveTheBat();
    moveTheBall();
    winner = checkBlocksGone();
  }
  if( !gamePlaying ) {
    gameOver();
  }
  if( winner ) {
    gameWon();
  }
}

//This time the setupBlockRows() function
//uses 'nested' loops to count through each
//row, and then every column in that row.
//Traditionally, loop counters are often called
//'i', 'j' or 'k' especially when you have
//nested loops.
//==================================//
void setupBlockRows() {
//    |   ONE   |     TWO    | THREE |
  for( int i = 0; i < numRows;  i++  ) { 
                                              
    for( int j = 0; j < blocksPerRow; j++ ) { 
      theBlocks[ i ][ j ] = 1;                
    }                                         
  } 
}

//==================================//
void drawBlocks() {
  int rowPosition = firstRowYPos;
 
  fill( 200 );
 
  for( int i = 0; i < numRows; i++ ) {
    drawOneRow( rowPosition, theBlocks[ i ] ); // <- send just one row of the array
    rowPosition = rowPosition + blockHeight;
  }
}

//void drawOneRow( int, int[] )
//
//===================================//
void drawOneRow( int rowLevel, int[] someRow ) {
  int counter;
 
  for( counter = 0; counter < someRow.length; counter++ ) {
    if( someRow[counter] == 1 ) {
      rect( blockWidth * counter + 1, rowLevel + 1, blockWidth - 2, blockHeight - 2 );
    }
  }
}


//====================================
void moveTheBat() {
  fill( 255 );
 
  bat.X = mouseX;
 
  //if the bat 'hits' the left edge move it back
  if( bat.X < bat.Size ) {
    bat.X = bat.Size;
  }
 
  //if the bat 'hits' the right edge move it
  if( bat.X > screenWidth - bat.Size ) {
    bat.X = screenWidth - bat.Size;
  }
 
  rect( bat.X - bat.Size, bat.Y, bat.Size * 2, bat.Height );
}


//=======================================
void moveTheBall() {
  ball.X = ball.X + ball.Xspeed;
  ball.Y = ball.Y + ball.Yspeed;
 
  if( ball.X < ball.Size ) {
    ball.X = ball.Size;
    ball.Xspeed = ball.Xspeed * -1;
  }
 
  if( ball.X > screenWidth - ball.Size ) {
    ball.X = screenWidth - ball.Size;
    ball.Xspeed = ball.Xspeed * -1;
  }
 
  if( ball.Y < ball.Size ) {
    ball.Y = ball.Size;
    ball.Yspeed = ball.Yspeed * -1;
  }
 
  if( ballHitBat() ) {
    ball.Yspeed = ball.Yspeed * -1;
  }
 
  if( ball.Y > screenHeight ) {
    gamePlaying = false;
  }
 
  for( int i = 0; i < numRows; i++ ) {
    checkBallHitRow( theBlocks[ i ], i );
  }
 
  rect( ball.X - ball.Size, ball.Y - ball.Size, ball.Size * 2, ball.Size * 2 );
}



//=================================//
boolean checkBallHitRow( int[] someRow, int rownumber ) {
  int blockLeft;
  int blockRight;
  int blockTop;
  int blockBottom;
  boolean hit = false;
 
  for( int whichblock = 0; whichblock < 10; whichblock++ ) {
    blockLeft   =          0 + blockWidth * whichblock;
    blockRight  = blockWidth + blockWidth * whichblock;
   
    blockTop    =  firstRowYPos                + blockHeight * rownumber;
    blockBottom = (firstRowYPos + blockHeight) + blockHeight * rownumber;
   
    if( ball.X > blockLeft && ball.X < blockRight ) {
      if( ball.Y > blockTop && ball.Y < blockBottom ) {
        if( someRow[whichblock] == 1 ) {
          someRow[whichblock] = 0;
          SCORE += blockPoints;
          hit = true;
        }
      }
    }
  }
 
  return hit;
}
//=======================================//
boolean checkBlocksGone() {
  int totalblocks = 0;
 
  for( int i = 0; i < numRows; i++ ) {
    for( int j = 0; j < blocksPerRow; j++ ) {
      totalblocks += theBlocks[ i ][ j ];
    }
  }
 
  return (totalblocks == 0);
}

//=====================================//
void drawScore() {
  fill( 255 );
  text( "Score: " + SCORE, 10, 10 );
}

//======================================//
void gameOver() {
  fill( 255 );
  text("Game Over", 200, 400);
}

//======================================//
void gameWon() {
  fill( 255 );
  text("WINNER!", 200, 400);
}
 
//======================================//
boolean ballHitBat() {
  if( ball.Y + ball.Size >= bat.Y ) {
    if( ball.Y + ball.Size <= bat.Y + ball.Size * 2 ) {
      if( ball.X > bat.X - bat.Size ) {
        if( ball.X < bat.X + bat.Size ) {
          //the ball has hit the bat so return the answer is 'true'
          return true;
        }
      }
    }
  }
  //if we get this far then the ball hasn't hit, return the answer 'false'
  return false;
}

//mousePressed()
//
//This is another one of Processing's built in functions
//When the mouse button is pressed, Processing automatically
//calls this function so your program can react.
void mousePressed() {
  if( !gamePlaying || winner ) {
    SCORE = 0;
    gamePlaying = true;
    winner = false;
    setupBlockRows();
   
    ball.X = 240;
    ball.Y = 400;
  }
}


No comments:

Post a Comment

Note: only a member of this blog may post a comment.