Platforms correct visualization; opt-in shadow etc

This commit is contained in:
Mottributo 2023-03-26 16:58:15 +03:00
parent aa0943467f
commit 11d12e3d65

272
sketch.js
View File

@ -6,6 +6,7 @@ var fps_recent_values = [];
var death_timer;
var showDebugData = false;
var debug_charTrace = [];
var shadows_enabled = false;
var gameChar;
@ -26,17 +27,35 @@ function Platform(curGroundIndex, x, width, y) {
this.curGroundIndex = curGroundIndex;
this.x = x;
this.width = width;
this.y = y || Math.pow(gameChar.baseJumpingStrength, 2) / 2 - 2 * gameChar.baseJumpingStrength;
// To make platforms jumpable to each other, define a max vertical difference
// thru an arithmetic progression dependent on the game character's jumping strength and gravity.
this.max_y_deviation =
(gameChar.baseJumpingStrength/gravity)*(gameChar.baseJumpingStrength)/2;
this.y = y || groundPositions[curGroundIndex] - this.max_y_deviation;
this.draw = function () {
push();
stroke(0);
strokeWeight(2);
fill(palette.ground_color0);
fill(palette.ground_colors[curGroundIndex]);
rect(
this.x - this.width,
floorPos_y - this.y,
width*2, height/100,
this.y + height / 100,
width * 2,
height / 100
);
pop();
};
this.drawShadow = function () {
push();
// drawing shadow on the ground
noStroke();
fill("rgba(0,0,0, 0.15)");
rect(
this.x - this.width,
groundPositions[curGroundIndex],
width * 2,
height / 100
);
pop();
@ -71,9 +90,11 @@ function setup() {
body_color: color("white"),
head_color: color("darkgreen"),
sky_color: color("#8E9887"),
ground_color0: color("#684622"),
ground_color1: color("#734E26"),
ground_color2: color("#7F562A"),
ground_colors: [
color("#874321"),
color("#636721"),
color("#634345")
],
river_river_color: color("#56C525"),
river_river_wave_color: color("#4BAD21"),
river_color: color("#7B672A"),
@ -128,7 +149,7 @@ function startGame(level_start) {
speed: 5,
baseLives: 3,
curLives: 3,
baseJumpingStrength: 15,
baseJumpingStrength: 16,
curJumpingStrength: 0,
isRight: false,
isLeft: false,
@ -137,17 +158,18 @@ function startGame(level_start) {
isPlummeting: false,
curGroundIndex: 0,
_updateSprite: function()
{
_updateSprite: function () {
if (gameChar.isPlummeting) {
gameChar.sprite = 2;
} else if (gameChar.isFalling) {
gameChar.sprite = 2;
if (gameChar.isLeft && !gameChar.isRight) gameChar.sprite = 5;
if (gameChar.isLeft && !gameChar.isRight)
gameChar.sprite = 5;
else if (gameChar.isRight && !gameChar.isLeft)
gameChar.sprite = 6;
} else {
if (gameChar.isLeft && !gameChar.isRight) gameChar.sprite = 4;
if (gameChar.isLeft && !gameChar.isRight)
gameChar.sprite = 4;
else if (gameChar.isRight && !gameChar.isLeft)
gameChar.sprite = 3;
else gameChar.sprite = 1;
@ -325,6 +347,69 @@ function startGame(level_start) {
this.y_step /= this.scale;
pop();
},
drawShadow: function () {
push();
noStroke();
this.x_step *= this.scale;
this.y_step *= this.scale;
fill('rgba(0,0,0,0.2)');
if (!gameChar.isPlumetting) shadow_y = groundPositions[gameChar.curGroundIndex];
else shadow_y = NaN;
ellipse(gameChar.x,
shadow_y,
gameChar.x_step*5,
gameChar.y_step*1.5);
this.x_step /= this.scale;
this.y_step /= this.scale;
pop();
},
_checkPlayerDie: function () {
if (frameCount - death_timer > 60) {
if (gameChar.curLives > 1) {
gameChar.curLives--;
death_timer = undefined;
startGame();
} else if (gameChar.curLives == 1) {
gameChar.curLives--;
} else {
gameChar.curLives = 0;
}
}
},
act: function () {
if (!gameChar.isPlummeting) {
if (gameChar.isLeft && !gameChar.isRight) {
gameChar.x -= gameChar.speed;
} else if (gameChar.isRight && !gameChar.isLeft) {
gameChar.x += gameChar.speed;
}
if (gameChar.isJumping) {
gameChar.y -= gameChar.curJumpingStrength;
gameChar.curJumpingStrength -= gravity;
if (gameChar.curJumpingStrength <= 0) {
gameChar.isFalling = true;
gameChar.isJumping = false;
}
} else if (gameChar.isFalling) {
gameChar.y -= gameChar.curJumpingStrength;
gameChar.curJumpingStrength -= gravity;
if (gameChar.y >= gameChar.getCurGroundY()) {
gameChar.y = gameChar.getCurGroundY();
gameChar.isFalling = false;
}
} else {
}
}
this._checkPlayerDie();
// Doing plummeting
if (gameChar.isPlummeting) {
// using OR operator to set to frameCount in case death_timer is undefined,
// but not updating the death_timer again in case it is not undefined.
death_timer = death_timer || frameCount;
gameChar.y += 3;
}
},
getCurGroundY: function () {
return groundPositions[this.curGroundIndex];
},
@ -446,8 +531,49 @@ function startGame(level_start) {
}
for (i = 0; i < 100; i++) {
if (i == 0) {
platforms[0][0] = new Platform(0, 700, 50,
pow(gameChar.baseJumpingStrength, 2) / 2 - 2*gameChar.baseJumpingStrength);
platforms[0][0] = new Platform(
0,
700,
50,
groundPositions[0] - Platform.max_y_deviation
);
platforms[1][0] = new Platform(
1,
800,
50,
groundPositions[1] - Platform.max_y_deviation
);
platforms[2][0] = new Platform(
2,
900,
50,
groundPositions[2] - Platform.max_y_deviation
);
} else {
let groundPosIndex = floor(
random(0, groundPositions.length)
);
// array.slice(-1)[0] gets the last element of an array without removing it,
// contrary to array.pop().
prev = platforms[groundPosIndex].slice(-1)[0];
// stopping generation after the flagpole
if (prev.x + prev.width + 155 > finish_position_x) break;
platforms[groundPosIndex].push(
new Platform(
groundPosIndex,
prev.x +
random(
prev.width + 70,
prev.width + 155
),
random(15, 60),
max(
random(prev.y -
prev.max_y_deviation,
floorPos_y - prev.max_y_deviation),
height / 8)
)
);
}
}
}
@ -478,7 +604,11 @@ function draw() {
if (gameChar.x < finish_position_x)
cameraPosX = lerp(gameChar.x - width / 2, cameraPosX, camera_speed);
else
cameraPosX = lerp(finish_position_x - width/2, cameraPosX, camera_speed);
cameraPosX = lerp(
finish_position_x - width / 2,
cameraPosX,
camera_speed
);
// -------- CLOUDS --------------
drawClouds();
@ -492,6 +622,11 @@ function draw() {
}
// -------- TREES ---------------
drawTrees();
// -------- PLATFORMS SHADOWS ---
if (shadows_enabled)
for (i=0; i<groundPositions.length; i++) {
drawPlatformsShadows(i);
}
// -------- COLLECTABLES --------
for (i = 0; i < collectables.length; i++) {
collectable = collectables[i];
@ -501,49 +636,30 @@ function draw() {
// -------- FLAGPOLE ------------
renderFlagpole();
if (!flagpole.isReached) checkFlagpole();
// -------- PLATFORMS
drawPlatforms();
// -------- GAME CHARACTER ------
{
// Behavior
if (!gameChar.isPlummeting) {
if (gameChar.isLeft && !gameChar.isRight) {
gameChar.x -= gameChar.speed;
} else if (gameChar.isRight && !gameChar.isLeft) {
gameChar.x += gameChar.speed;
}
if (gameChar.isJumping) {
gameChar.y -= gameChar.curJumpingStrength;
gameChar.curJumpingStrength -= gravity;
if (gameChar.curJumpingStrength <= 0) {
gameChar.isFalling = true;
gameChar.isJumping = false;
}
} else if (gameChar.isFalling) {
gameChar.y -= gameChar.curJumpingStrength;
gameChar.curJumpingStrength -= gravity;
if (gameChar.y >= gameChar.getCurGroundY()) {
gameChar.y = gameChar.getCurGroundY();
gameChar.isFalling = false;
}
} else {
}
}
checkPlayerDie();
// Doing plummeting
if (gameChar.isPlummeting) {
if (death_timer == undefined) death_timer = frameCount;
gameChar.y += 3;
}
// Drawing a sprite
gameChar.draw();
}
pop(); // Scrolling
// GAMECHAR, PLATFORMS & ENEMIES RENDER
complexDraw();
// - ------ GAME CHARACTER ------
gameChar.act();
pop(); // Scrolling end
// -------- INTERFACE -----------
drawInterface();
}
function complexDraw() {
// Since platforms require being drawn in three different ordrs relative to enemies and the game character,
// a function is made to handle this and to decrease clutter.
for (i=0; i<=gameChar.curGroundIndex; i++) {
drawPlatforms(i);
}
if (shadows_enabled) gameChar.drawShadow();
gameChar.draw();
for (i=gameChar.curGroundIndex+1; i<groundPositions.length; i++) {
drawPlatforms(i);
}
}
function drawInterface() {
push();
fill(0);
stroke(0);
text("Score: " + game_score, 12, text_size);
drawLives();
if (gameChar.curLives < 1)
@ -564,7 +680,7 @@ function draw() {
function drawCharTrace() {
debug_charTrace.push([gameChar.x, gameChar.y]);
if (debug_charTrace.length > 100) debug_charTrace.shift();
push()
push();
stroke(255, 0, 0);
strokeWeight(3);
translate(-cameraPosX, 0);
@ -601,16 +717,16 @@ function checkCollectable(t_collectable) {
function drawGround() {
push();
noStroke();
fill(palette.ground_color0);
fill(palette.ground_colors[0]);
rect(0, floorPos_y, width, height - floorPos_y);
fill(palette.ground_color1);
fill(palette.ground_colors[1]);
rect(
0,
floorPos_y + (2 * (height - floorPos_y)) / 6,
width,
floorPos_y + (2 * (height - floorPos_y)) / 6
);
fill(palette.ground_color2);
fill(palette.ground_colors[2]);
rect(
0,
floorPos_y + (4 * (height - floorPos_y)) / 6,
@ -843,12 +959,19 @@ function drawTrees() {
}
}
function drawPlatforms() {
for (i=0; i<groundPositions.length; i++) {
for (k=0; k<platforms[i].length;k++) {
platforms[i][k].draw();
function drawPlatforms(rowIndex) {
push();
for (k = 0; k < platforms[rowIndex].length; k++) {
platforms[rowIndex][k].draw();
}
pop();
}
function drawPlatformsShadows(rowIndex) {
push();
for (k = 0; k < platforms[rowIndex].length; k++) {
platforms[rowIndex][k].drawShadow();
}
pop();
}
function renderFlagpole() {
@ -889,19 +1012,7 @@ function checkFlagpole() {
flagpole.isReached = true;
}
}
function checkPlayerDie() {
if (frameCount - death_timer > 60) {
if (gameChar.curLives > 1) {
gameChar.curLives--;
death_timer = undefined;
startGame();
} else if (gameChar.curLives == 1) {
gameChar.curLives--;
} else {
gameChar.curLives = 0;
}
}
}
function drawFps() {
push();
fps = Math.round(frameRate() * 10) / 10;
@ -926,14 +1037,15 @@ function keyPressed() {
startGame((level_start = true));
}
} else if (!gameChar.isPlummeting) {
if (keyCode == 65 /*A*/ || keyCode == LEFT_ARROW) gameChar.isLeft = true;
if (keyCode == 68 /*D*/ || keyCode == RIGHT_ARROW) gameChar.isRight = true;
if (keyCode == 65 /*A*/ || keyCode == LEFT_ARROW)
gameChar.isLeft = true;
if (keyCode == 68 /*D*/ || keyCode == RIGHT_ARROW)
gameChar.isRight = true;
if (keyCode == 83 /*S*/ || keyCode == DOWN_ARROW) gameChar.goDown();
if (keyCode == 87 /*W*/ || keyCode == UP_ARROW) gameChar.goUp();
// Rewrote jumping routine to make it more natural and be able to support platforms and different player dimensions
if (
(keyCode == 32 /*Space*/ ||
keyCode == 88 /*X*/) &&
(keyCode == 32 /*Space*/ || keyCode == 88) /*X*/ &&
!gameChar.isFalling &&
!gameChar.isJumping
) {