Your browser does not support the canvas tag.

previous        Show / Hide Source        Download        next
//global variables

//positioning and movement-based variables for players and ball
float redPosX, redPosY, goalsRed, redVelX, redVelY;
float bluePosX, bluePosY, goalsBlue, blueVelX, blueVelY;
float ballPosX, ballPosY, ballVelX, ballVelY;

//variables holding goal positions
int redGoalX1=20;
int redGoalX2=30;
int redGoalY1=120;
int redGoalY2=280;
int blueGoalX1=370;
int blueGoalX2=380;
int blueGoalY1=120;
int blueGoalY2=280;

//score-keeping variables
int redScore=0;
int blueScore=0;

//variables used for fine-tuning key game elements
int playerWidth=25;
int ballWidth=15;
int playerAccel=1;
float kickStrength=1.2;
float fric=0.2;

void setup()
{
  size(400, 400);
  frameRate(60);
  //the game should be reset when the program starts
  resetGame();
}

void draw()
{
  //check if the ball hit a goal
  checkGoals();

  //if a key is being pressed, check further to see what action needs to be done in response
  if (keyPressed)
    movePlayers();

  //check if players have collided
  checkPlayerCollision();

  //creates drag on players so they slide to a stop
  friction();

  //after movement calculations are done, check if out of bounds before updating entity positions
  updateEntities();

  background(0, 100, 50);

  //draw the players for this frame
  drawEntities();

  //draw scoreboards
  drawScoreboards();
}

//resets the field conditions and places the ball at a random Y-coordinate in the centre of the field
void resetGame()
{
  //move red back to starting pos
  redPosX=60;
  redPosY=200;

  //move blue back to starting pos
  bluePosX=340;
  bluePosY=200;

  //move ball back to starting pos
  ballPosX=200;
  ballPosY=random(1, 400);

  //reset velocities
  redVelX=0;
  redVelY=0;
  blueVelX=0;
  blueVelY=0;
  ballVelX=0;
  ballVelY=0;
}

//applies drag on the players and ball
void friction()
{
  //if objects have velocity, slow them down, but not past 0 velocity
  //red friction
  if (redVelX!=0)
  {
    if (redVelX<0)
      redVelX+=fric;
    else if (redVelX>0)
      redVelX-=fric;
  }
  if (redVelY!=0)
  {
    if (redVelY<0)
      redVelY+=fric;
    else if (redVelY>0)
      redVelY-=fric;
  }

  //blue friction
  if (blueVelX!=0)
  {
    if (blueVelX<0)
      blueVelX+=fric;
    else if (blueVelX>0)
      blueVelX-=fric;
  }
  if (blueVelY!=0)
  {
    if (blueVelY<0)
      blueVelY+=fric;
    else if (blueVelY>0)
      blueVelY-=fric;
  }

  //ball friction
  if (ballVelX!=0)
  {
    if (ballVelX<0)
      ballVelX+=fric;
    else if (ballVelX>0)
      ballVelX-=fric;
  }
  if (ballVelY!=0)
  {
    if (ballVelY<0)
      ballVelY+=fric;
    else if (ballVelY>0)
      ballVelY-=fric;
  }
}

//checks whether or not the ball has hit a goal
void checkGoals()
{
  //check red goal
  if (ballPosX>redGoalX1&&ballPosX<redGoalX2&&ballPosY>redGoalY1&&ballPosY<redGoalY2)
  {
    blueScore++;
    println("Blue scores!"+redScore+"-"+blueScore);
    resetGame();
  }
  //check blue goal
  else if (ballPosX>blueGoalX1&&ballPosX<blueGoalX2&&ballPosY>blueGoalY1&&ballPosY<blueGoalY2)
  {
    redScore++;
    println("Red scores!"+redScore+"-"+blueScore);
    resetGame();
  }
}

//draws squares on the screen to show each player's current score
void drawScoreboards()
{
  rectMode(CENTER);

  for (int tally=1; tally<=blueScore; tally++)
  {
    fill(0, 0, 255);
    rect(10, 10*tally, 5, 5);
  }
  for (int tally=1; tally<=redScore; tally++)
  {
    fill(255, 0, 0);
    rect(390, 10*tally, 5, 5);
  }
}

//handles player controls and movement
void movePlayers()
{
  /*
  HANDLE RED MOVEMENT
   */
  if (keyCode==UP)
  {
    redVelY-=playerAccel;
  } else if (keyCode==DOWN)
  {
    redVelY+=playerAccel;
  } else if (keyCode==LEFT)
  {
    redVelX-=playerAccel;
  } else if (keyCode==RIGHT)
  {
    redVelX+=playerAccel;
  }

  //caps the player's maximum speed
  if (redVelX>6)
    redVelX=6;
  else if (redVelX<-6)
    redVelX=-6;

  if (redVelY>6)
    redVelY=6;
  else if (redVelY<-6)
    redVelY=-6;


  /*
  HANDLE BLUE MOVEMENT
   */
  if (key=='w')
  {
    blueVelY-=playerAccel;
  } else if (key=='s')
  {
    blueVelY+=playerAccel;
  } else if (key=='a')
  {
    blueVelX-=playerAccel;
  } else if (key=='d')
  {
    blueVelX+=playerAccel;
  }

  //caps the player's maximum speed
  if (blueVelX>6)
    blueVelX=6;
  else if (blueVelX<-6)
    blueVelX=-6;

  if (blueVelY>6)
    blueVelY=6;
  else if (blueVelY<-6)
    blueVelY=-6;
}

//calculates the position of the red player, blue player, and ball in the next frame
void updateEntities()
{
  /*
  UPDATE RED PLAYER POSITIONS
   */
  if (redPosX+redVelX>width)
    redVelX=0;
  if (redPosX+redVelX<0)
    redVelX=0;
  if (redPosY+redVelY>height)
    redVelY=0;
  if (redPosY+redVelY<0)
    redVelY=0;

  redPosX=redPosX+redVelX;
  redPosY=redPosY+redVelY;


  /*
  UPDATE BLUE PLAYER POSITIONS
   */
  if (bluePosX+blueVelX>width)
    blueVelX=0;
  if (bluePosX+blueVelX<0)
    blueVelX=0;
  if (bluePosY+blueVelY>height)
    blueVelY=0;
  if (bluePosY+blueVelY<0)
    blueVelY=0;

  bluePosX=bluePosX+blueVelX;
  bluePosY=bluePosY+blueVelY;


  /*
  UPDATE BALL POSITION
   */
  //check if the ball has been kicked
  checkBallCollision();

  //ball will reverse its velocity values when hitting the edge of the screen, causing it to "bounce"
  if (ballPosX+ballVelX>width)
    ballVelX=-ballVelX;
  if (ballPosX+ballVelX<0)
    ballVelX=-ballVelX;
  if (ballPosY+ballVelY>height)
    ballVelY=-ballVelY;
  if (ballPosY+ballVelY<0)
    ballVelY=-ballVelY;

  ballPosX=ballPosX+ballVelX;
  ballPosY=ballPosY+ballVelY;
}

//makes sure players do not simply pass through eachother without event
void checkPlayerCollision()
{
  //if the players collide, they get thrown away from eachother
  if (redPosX+redVelX<=bluePosX+blueVelX+playerWidth&&redPosX+redVelX>=bluePosX+blueVelX-playerWidth&&redPosY+redVelY<=bluePosY+blueVelY+playerWidth&&redPosY+redVelY>=bluePosY+blueVelY-playerWidth)
  {
    //temporary variable needed for swapping player velocities
    float temp;

    //swap velocities
    temp=redVelX;
    redVelX=blueVelX;
    blueVelX=temp;

    temp=redVelY;
    redVelY=blueVelY;
    blueVelY=temp;
  }
}

//produces a "kick" of the ball if a player is nearby
void checkBallCollision()
{
  //if player hitboxes collide with the ball, it inherits their velocity

  //if both players kick the ball, then the ball stops completely (protects against rushing through the opponent)
  if (redPosX<=ballPosX+playerWidth-ballWidth&&redPosX>=ballPosX-playerWidth+ballWidth&&redPosY<=ballPosY+playerWidth-ballWidth&&redPosY>=ballPosY-playerWidth+ballWidth&&bluePosX<=ballPosX+playerWidth-ballWidth&&bluePosX>=ballPosX-playerWidth+ballWidth&&bluePosY<=ballPosY+playerWidth-ballWidth&&bluePosY>=ballPosY-playerWidth+ballWidth)
  {
    ballVelX=0;
    ballVelY=0;
  }
  //red kick check
  else if (redPosX<=ballPosX+playerWidth&&redPosX>=ballPosX-playerWidth&&redPosY<=ballPosY+playerWidth&&redPosY>=ballPosY-playerWidth)
  {
    ballVelX=redVelX*kickStrength;
    ballVelY=redVelY*kickStrength;
  }

  //blue kick check
  else if (bluePosX<=ballPosX+playerWidth&&bluePosX>=ballPosX-playerWidth&&bluePosY<=ballPosY+playerWidth&&bluePosY>=ballPosY-playerWidth)
  {
    ballVelX=blueVelX*kickStrength;
    ballVelY=blueVelY*kickStrength;
  }
}

//draw the next frame
void drawEntities()
{
  rectMode(CENTER);

  //draw the red player
  fill(255, 0, 0);
  rect(redPosX, redPosY, playerWidth, playerWidth);

  //draw the blue player
  fill(0, 0, 255);
  rect(bluePosX, bluePosY, playerWidth, playerWidth);

  //draw ball
  fill(255, 255, 200);
  rect(ballPosX, ballPosY, ballWidth, ballWidth);

  //draw goals
  fill(200, 255, 30);
  rectMode(CORNERS);
  rect(redGoalX1, redGoalY1, redGoalX2, redGoalY2);
  rect(blueGoalX1, blueGoalY1, blueGoalX2, blueGoalY2);
}