CyberLord09 / AnvayDNHSCompSci

Apache License 2.0
0 stars 0 forks source link

Lava and Flying Platform (with flag) + Player HP bar (Anvay + Yash) #6

Open CyberLord09 opened 2 months ago

CyberLord09 commented 2 months ago

Pre-eruption Actions

Before the lava erupts, there are a couple of things that the game uses to inform the player that lava is rising. The first is a large warning symbol.

this.warningSymbol = document.createElement('img');
this.warningSymbol.src = "/platformer3x/images/platformer/sprites/alert.gif";
this.warningSymbol.style.position = 'absolute';
this.warningSymbol.style.top = '35%';
this.warningSymbol.style.left = '50%';
this.warningSymbol.style.transform = 'translate(-50%, -50%)';
this.warningSymbol.style.display = 'none'; // Initially hidden
document.body.appendChild(this.warningSymbol);

By creating a warning symbol element, which plays a gif, it is clear to the player that something is happening. To ensure that the players knows what the warning symbol is actually for, we have created text under the symbol that the player can see.

Player interaction with lava

In order for the player to interact with the lava, we added a case in playerGreece.js for lava collisions.

We also wanted to add a twist, that the player doesn't just die the first time he hits the lava. For this reason, we created an HP bar, and also caused the player to jump on a collision with lava.

The HP bar is drawn in the drawHPbox function, and the parameters are placed in the constructor. For the sake of brevity, that code will not be shown here, but can be accessed in playerGreece.js

As for the collisions, if the player collides with the lava, there are two things that can happen. Note that the player has 3 health ticks before it dies. On the first and second tick (each doing 33 damage out of 99 total) the player is sent up in the air as a jump, and also loses 33 HP. On the third tick, the player loses all HP (clearing the HP bar), and then dies like normal.

case "lava": // Note: Goomba.js and Player.js could be refactored

                if (this.collisionData.touchPoints.other.id === "lava") {
                    if (GameEnv.difficulty === "normal" || GameEnv.difficulty === "hard") {
                        if (this.state.isDying == false) {
                            if(this.currentHp == 33){
                                this.currentHp -= 33;
                                this.drawHpBox();
                                this.state.isDying = true;
                                this.canvas.style.transition = "transform 0.5s";
                                this.canvas.style.transform = "rotate(-90deg) translate(-26px, 0%)";
                                GameEnv.playSound("PlayerDeath");
                                setTimeout(async() => {
                                    await GameControl.transitionToLevel(GameEnv.levels[GameEnv.levels.indexOf(GameEnv.currentLevel)]);
                                }, 900); 
                            } else{
                                this.setY(this.y - (this.bottom * 0.6));
                                this.currentHp -= 33;
                            }
                        }
CyberLord09 commented 2 months ago

Timer and Lava Rising

Timer Element

  1. Creation and Styling: The timerElement is an HTML <div> element created in the constructor of the Lava class:
    this.timerElement = document.createElement('div');
    this.timerElement.style.position = 'absolute';
    this.timerElement.style.fontFamily = 'Stencil Std, fantasy';
    this.timerElement.style.fontSize = '24px';
    this.timerElement.style.color = 'white';
    this.timerElement.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';
    this.timerElement.style.padding = '10px 20px';
    this.timerElement.style.borderRadius = '10px';
    this.timerElement.style.boxShadow = '0 0 10px rgba(0, 0, 0, 0.5)';
    this.timerElement.style.top = '70%';
    this.timerElement.style.left = '50%';
    this.timerElement.style.transform = 'translate(-50%, -50%)';
    this.timerElement.style.display = 'none'; // Initially hidden
    document.body.appendChild(this.timerElement);
    • Position and Font: The timer is positioned in the center of the screen using top and left properties and transform: translate(-50%, -50%) to center it.
    • Initially, the timerElement is hidden (display: none). It is then shown when the level is loaded.

Timer Functionality

  1. Start Timer: The startTimer method is responsible for counting down and updating the timerElement every second:
    startTimer() {
       setInterval(() => {
           this.timeUntilRise -= 1000; // Decrease the time remaining by 1 second
           if (this.timeUntilRise <= 0) {
               this.timeUntilRise = 0;
               this.initialDelayElapsed = true; // Mark the initial delay as elapsed
               this.timerElement.style.display = 'none'; // Hide the timer
           } else if (this.timeUntilRise <= this.initialDelay) {
               this.timerElement.style.display = 'block'; // Show the timer
           }
           this.timerElement.innerText = `TIME UNTIL LAVA RISES: ${this.timeUntilRise / 1000}s`;
       }, 1000); // Execute this block every second (1000 milliseconds)
    }
    • Countdown: The timeUntilRise increments by 1000 milliseconds (1 second) each time the function runs.
    • Initial Delay: When timeUntilRise reaches 0, it sets initialDelayElapsed to true, indicating that the initial delay is over, and hides the timerElement.
    • Displaying the Element: If timeUntilRise is less than or equal to the initialDelay but greater than 0, the timerElement is displayed, showing the countdown.

Raising the Lava

  1. Update Method: The update method is called to raise the lava once the initial delay has elapsed:

    update() {
       if (this.initialDelayElapsed) {
           // Calculate time passed since the last update
           const currentTime = Date.now();
           const deltaTime = currentTime - this.lastUpdateTime;
    
           // Update the lava's position based on rising speed and delta time
           this.islandY -= (this.risingSpeed * deltaTime) / 1000;
    
           // Update last update time
           this.lastUpdateTime = currentTime;
    
           // Call collision checks
           this.collisionChecks();
           this.size();
       }
    }
    • Checking Initial Delay: The lava will only start rising if initialDelayElapsed is true.
    • Time Calculation: It calculates the time elapsed (deltaTime) since the last update by comparing the current time (currentTime) with the last recorded update time (this.lastUpdateTime).
    • Rising Logic: The lava's islandY position is decreased based on the risingSpeed and deltaTime. This basically moves the lava upwards at a rate defined by the risingSpeed property.
    • Update Time: The lastUpdateTime is updated to the current time for the next cycle.

Flying Platform With the EndObject

As when the lava rises, if the EndGameObject is on the floor, it wouldn't be reachable. For this, we created a flying platform that has the Flag from our level.

The code is as follows:

import  GameObject  from  './GameObject.js';
import  GameEnv  from  './GameEnv.js';
import  GameControl  from  './GameControl.js';
import  BlockPlatform  from  './BlockPlatform.js';

export  class  FlyingIsland  extends  BlockPlatform {
constructor(canvas,  image,  data,  xPercentage,  yPercentage) {
super(canvas,  image,  data,  xPercentage,  yPercentage);
}

update() {
super.update();
}

draw() {
super.draw();
}

size() {
// Formula for Height should be on constant ratio, using a proportion of 832
const  scaledWidth  =  this.canvas.width*0.75;
const  scaledHeight  =  this.canvas.height*0.75;
const  platformX  =  this.platformX;
const  platformY  =  (GameEnv.bottom  -  scaledHeight)  *  this.platformY;
// set variables used in Display and Collision algorithms
this.bottom  =  platformY;
this.collisionHeight  =  scaledHeight;
this.collisionWidth  =  scaledWidth;
//this.canvas.width = this.width;
//this.canvas.height = this.height;
this.canvas.style.width  =  `${scaledWidth}px`;
this.canvas.style.height  =  `${scaledHeight}px`;
this.canvas.style.position  =  'absolute';
this.canvas.style.left  =  `${platformX}px`;
this.canvas.style.top  =  `${platformY}px`;
    }
}

export  default  FlyingIsland;

To break it down:

  1. FlyingIsland extends BlockPlatform in which all of the properities of a block platform are inherited into the FlyingIsland
  2. The constructor does not need any new code so the super is just called. a. This same applies with the update and draw functions.
  3. The size function just has a bunch of different properties that also apply to block platform (not much different here).

In GameSetup.js:

  1. Island is added as a png image island: { src: "/images/platformer/platforms/island.png" },
  2. Y percentage is raised to make the island floating xPercentage: 0.82, yPercentage: 0.55

With this, complications arised with the collisions between the player and the flag as the flag was raised above the ground. This meant that the previous conditions for collisions (player hits top and falls lower) did not work anymore. Due to this issue, we had to change the collision code to support collision at any place on the flag.