Added comments
This commit is contained in:
+67
-3
@@ -16,8 +16,11 @@ float cannonLength = 25; // How long the cannon on each tank extends
|
||||
float tank1CannonX1, tank1CannonX2, tank1CannonY1, tank1CannonY2;
|
||||
float tank2CannonX1, tank2CannonX2, tank2CannonY1, tank2CannonY2;
|
||||
float gravity = 0.05; // Strength of gravity
|
||||
float velocity;
|
||||
// Store velocity of projectile
|
||||
float velocity;
|
||||
// Store value for if projectile has collided with the ground or a tank
|
||||
boolean contactMade = false;
|
||||
// Store the diameter of the projectile
|
||||
int projectileSize = 8;
|
||||
|
||||
// Current state of the game
|
||||
@@ -29,26 +32,38 @@ float tank1CannonStrength = 3, tank2CannonStrength = 3; // Strength of intended
|
||||
|
||||
// Location of the projectile
|
||||
|
||||
// Store the state of the projectile
|
||||
boolean projectileInMotion = false;
|
||||
// Store projectile position and velocity values on screen
|
||||
float projectilePositionX, projectilePositionY;
|
||||
float projectileVelocityX, projectileVelocityY;
|
||||
|
||||
// Image object to encapsulate the background image
|
||||
PImage bg;
|
||||
|
||||
// Terrain generation function adapted from: http://www.redblobgames.com/articles/noise/introduction.html
|
||||
// Generate varying hills and valleys for terrain.
|
||||
void GenerateTerain() {
|
||||
// Store amplitudes (randomly generated within arbritrary limits) for each sine wave
|
||||
float amp[] = {random(1.5,2.5), random(0.8,1.4), random(0.1, 0.3), random(0.0001, 0.002), 0.01, 0.01};
|
||||
// Store frequencies (Hz) for each sine wave
|
||||
int frequency[] = {1, 2, 4, 8, 16, 32};
|
||||
// generate a random phase for sine waves
|
||||
float phase = random(0, 2*PI);
|
||||
|
||||
// Initialize all values of groundLevel to 0
|
||||
for(int i = 0; i < width; i++) {
|
||||
groundLevel[i] = 0;
|
||||
}
|
||||
// for every ground level array element
|
||||
for(int i = 0; i < width; i++) {
|
||||
// for all sine components to be accumulated
|
||||
for(int j = 0; j < frequency.length; j++) {
|
||||
// generate the current sample value for the current sine wave
|
||||
groundLevel[i] += (sin(2*PI * frequency[j]*i/width + phase)*amp[j])*30;
|
||||
}
|
||||
}
|
||||
// Apply an arbitrary offset to place terrain at appropriate level on screen
|
||||
for(int i = 0; i < width; i++) {
|
||||
groundLevel[i] += height - (height / 3.5);
|
||||
}
|
||||
@@ -57,11 +72,14 @@ void GenerateTerain() {
|
||||
void setup() {
|
||||
size(960, 480); // Set the screen size
|
||||
// Background image taken from https://www.behance.net/gallery/31516629/CARTOON-BACKGROUNDS
|
||||
// Load the background image into object
|
||||
bg = loadImage("background.png");
|
||||
|
||||
// Initialize the ground level
|
||||
groundLevel = new float[width];
|
||||
// Fill groundLevel array with values
|
||||
GenerateTerain();
|
||||
// set the height of the tanks relative to the generated ground level
|
||||
float player1Height = groundLevel[int(width*0.1)];
|
||||
float player2Height = groundLevel[int(width*0.9)];
|
||||
|
||||
@@ -76,13 +94,16 @@ void draw() {
|
||||
// Main draw loop. Farm out the individual tasks to other functions
|
||||
// for clarity (though it could be equivalently implemented entirely in this function.)
|
||||
|
||||
// Set the background to the picture provided
|
||||
background(bg);
|
||||
|
||||
// run draw functions for respecitive elements of the game
|
||||
drawTanks();
|
||||
drawGround();
|
||||
drawProjectile();
|
||||
drawStatus();
|
||||
|
||||
// draw projectiles at new positions and run collision detection for projectiles
|
||||
updateProjectilePositionAndCheckCollision();
|
||||
}
|
||||
|
||||
@@ -90,17 +111,26 @@ void draw() {
|
||||
void drawGround() {
|
||||
/* TO IMPLEMENT IN STEP 1 */
|
||||
strokeWeight(5);
|
||||
// Draw ground using a single custom shape using vertex functions
|
||||
beginShape();
|
||||
int idx;
|
||||
// for each groundLevel array element
|
||||
for(idx = 0; idx < groundLevel.length; idx++){
|
||||
// create a vertex point at the position on the screen determined by the array index position at the height of the element in the array
|
||||
vertex(idx, groundLevel[idx]);
|
||||
}
|
||||
// Apply two final vertices to fill space below generated vertices
|
||||
vertex(idx, height);
|
||||
vertex(0, height);
|
||||
|
||||
// Colour ground
|
||||
fill(250, 236, 157);
|
||||
endShape();
|
||||
|
||||
strokeWeight(0);
|
||||
// Set preceeding shapes to not have a border
|
||||
noStroke();
|
||||
// create layered ground with different colour and dimensions for aesthetic effect
|
||||
// Logic is essentially the same as above
|
||||
beginShape();
|
||||
for(idx = 0; idx < groundLevel.length; idx++){
|
||||
vertex(idx, (groundLevel[idx] * 0.85)+70);
|
||||
@@ -125,20 +155,32 @@ void drawTanks() {
|
||||
// Also be sure to draw the cannons, using the angles given at the top of the file
|
||||
|
||||
// Draw tank 1
|
||||
|
||||
// Set size of border to 10 pixels
|
||||
strokeWeight(10);
|
||||
|
||||
// set variable for placing tank 1 cannon at the center of the tank
|
||||
tank1CannonX1 = tank1X;
|
||||
// set variable for placing the tip of the cannon at the angle and length specified
|
||||
tank1CannonX2 = tank1X + (cannonLength * cos(tank1CannonAngle));
|
||||
// similar to above...
|
||||
tank1CannonY1 = tank1Y;
|
||||
tank1CannonY2 = tank1Y - (cannonLength * sin(tank1CannonAngle));
|
||||
|
||||
// draw tank cannon at position specified
|
||||
line(tank1CannonX1, tank1CannonY1, tank1CannonX2, tank1CannonY2);
|
||||
// Make cannon square
|
||||
strokeCap(SQUARE);
|
||||
|
||||
// Set global border size to 5 pixels
|
||||
strokeWeight(5);
|
||||
fill(255, 0, 0);
|
||||
// draw 1 tank body
|
||||
// arc was replaced with ellipse to account for more detailed varying ground level
|
||||
ellipse(tank1X, tank1Y, tankDiameter, tankDiameter);
|
||||
|
||||
// Draw tank 2
|
||||
// Exactly the same as tank 1
|
||||
strokeWeight(10);
|
||||
tank2CannonX1 = tank2X;
|
||||
tank2CannonX2 = tank2X + (cannonLength * cos(tank2CannonAngle));
|
||||
@@ -152,17 +194,23 @@ void drawTanks() {
|
||||
|
||||
// Draw the projectile, if one is currently in motion
|
||||
void drawProjectile() {
|
||||
if(!projectileInMotion && !contactMade) // Don't draw anything if there's no projectile in motion
|
||||
// Don't draw anything if there's no projectile in motion and the porjectile isn't exploding
|
||||
if(!projectileInMotion && !contactMade)
|
||||
return;
|
||||
// if projectile has exploded enough then stop
|
||||
else if(contactMade && projectileSize > 32) {
|
||||
// Set projectile state so that it no longer expands
|
||||
contactMade = false;
|
||||
// toggle to next player's turn
|
||||
nextPlayersTurn();
|
||||
}
|
||||
// Save the current global stroke colour
|
||||
// (Hacky workaround due to everything being in the global namespace)
|
||||
int strokeColourVar = g.strokeColor;
|
||||
noStroke();
|
||||
// Set projectile colour to yellow
|
||||
fill(255, 255, 0);
|
||||
// Set the position and size of projectile
|
||||
ellipse(projectilePositionX, projectilePositionY, projectileSize, projectileSize);
|
||||
// Recover previously set stroke colour
|
||||
stroke(strokeColourVar);
|
||||
@@ -170,19 +218,27 @@ void drawProjectile() {
|
||||
|
||||
// Draw the status text on the top of the screen
|
||||
void drawStatus() {
|
||||
// Temporarily save global variables locally
|
||||
float strokeWeightVar = g.strokeWeight;
|
||||
int strokeColourVar = g.strokeColor;
|
||||
// Set shape border size to 2 pixels
|
||||
strokeWeight(2);
|
||||
// Set stroke colour RGB
|
||||
stroke(230, 249, 211);
|
||||
// Set shape fill colour RGB
|
||||
fill(201, 246, 203);
|
||||
// Draw a background rectangular box to seperate information bar from background
|
||||
rect(0, 0, width, 45);
|
||||
// reset global values to their originals, avoiding unexpected behaviour in other functions
|
||||
strokeWeight(strokeWeightVar);
|
||||
stroke(strokeColourVar);
|
||||
|
||||
// Set text size and alignment parameters for info bar
|
||||
textSize(24);
|
||||
textAlign(LEFT);
|
||||
fill(0);
|
||||
|
||||
// Based on current state of game, display relevant information in information bar
|
||||
if(playerHasWon == 1)
|
||||
text("Player 1 Wins!", 10, 30);
|
||||
else if(playerHasWon == 2)
|
||||
@@ -201,13 +257,17 @@ void drawStatus() {
|
||||
|
||||
// Move the projectile and check for a collision
|
||||
void updateProjectilePositionAndCheckCollision() {
|
||||
// If projectile has finished all actions (moving and exploding)
|
||||
if(!projectileInMotion && !contactMade) {
|
||||
projectileSize = 8;
|
||||
return;
|
||||
}
|
||||
// Check for player's turn
|
||||
// This implementation could be vastly improved by creating a generic function that applies operations to either player 1 or 2 based on this boolean. An object oriented approach or a way of passing variables by refference to a generic function would achieve this.
|
||||
if(player1Turn) {
|
||||
/* TO IMPLEMENT IN STEP 3: UPDATE POSITION */
|
||||
|
||||
// If the projectile is in motion...
|
||||
if(!contactMade) {
|
||||
// Tasks: increment the position according to the velocity
|
||||
// For later: the velocity according to gravity (and optionally wind)
|
||||
@@ -215,6 +275,7 @@ void updateProjectilePositionAndCheckCollision() {
|
||||
projectilePositionY += (velocity * -sin(tank1CannonAngle));
|
||||
}
|
||||
else {
|
||||
// If the projectile has collided with an object, increment it's size
|
||||
projectileSize += 1;
|
||||
}
|
||||
|
||||
@@ -229,12 +290,15 @@ void updateProjectilePositionAndCheckCollision() {
|
||||
// When the projectile hits the ground, it's the next player's turn
|
||||
if(round(projectilePositionX) >= width || round(projectilePositionX) <= 0) {
|
||||
// When the projectile hits something, it stops moving (change projectileInMotion)
|
||||
// As projectile has finished moving and exploding, set all relevant booleans to false, ready for next player's turn
|
||||
projectileInMotion = false;
|
||||
contactMade = false;
|
||||
nextPlayersTurn();
|
||||
|
||||
}
|
||||
// If projectile has collided with an object but hasn't exploded...
|
||||
else if (projectilePositionY > groundLevel[round(projectilePositionX)]) {
|
||||
// Set boolean values accordingly
|
||||
projectileInMotion = false;
|
||||
contactMade = true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user