xxxxxxxxxx
705
let bg,
cityBg,
ocean,
mangoImg,
chilliImg,
greyCar,
mice,
birds,
coinImg,
boat,
seagull,
anchor,
landscape,
cityTitle,
oceanTitle,
landing,
endScreen,
goats,
sheep,
bull;
let collectSound, losePointSound, bgMusic, villageMusic, cityMusic, oceanMusic;
var x1 = 0;
let scrollSpeed = 2;
let x;
let y;
let groundY = 280;
let walkSpeed = 8;
let g = 1;
let game;
let gameState = 0;
let showScore = false;
let storyFont;
class Game {
constructor() {
this.score = 0;
this.player = new Player(spritesheet, 4, 4, 0, groundY, 8);
this.playerBoat = new Boat(spritesheet, 4, 4, 0, 280, 8);
this.levelOneObstacleTypes = [goats, bull];
this.levelOneObstacles = [];
this.obstacleSpacing = 200;
for (let i = 0; i < 45; i++) {
let obstacle = random(this.levelOneObstacleTypes);
let randomOffset = random(0, 250);
x = (i + 1) * this.obstacleSpacing + randomOffset;
this.levelOneObstacles.push(
new Obstacle(obstacle, 3, 4, width + x, groundY + 15, 4, -10)
);
}
this.levelOneCollectables = [];
for (let i = 0; i < 55; i++) {
x = random(0, 20 * width);
y = random(groundY + 10, 100);
this.levelOneCollectables.push(
new Collectable(mangoImg, 15, width + x, y)
);
}
this.levelTwoObstacles = [];
let lastCarLoc = 0;
for (let i = 0; i < 55; i++) {
if (i % 5 == 0) {
let minDistance = 200; // Minimum distance between cars
let randomOffset = random(minDistance, 9 * width);
let x = lastCarLoc + minDistance + randomOffset;
lastCarLoc = x; // Update the last car location
this.levelTwoObstacles.push(
new Obstacle(greyCar, 1, 2, width + x, groundY + 40, 7, -10, 0)
);
} else {
let randomOffset = random(30, 250);
let y = random(50, groundY);
x = (i + 1) * this.obstacleSpacing + randomOffset;
this.levelTwoObstacles.push(
new Obstacle(birds, 3, 4, width + x, y, 5, -10)
);
if (i % 4 == 0) {
x = (i + 1) * this.obstacleSpacing + randomOffset;
this.levelTwoObstacles.push(
new Obstacle(mice, 3, 4, width + x, groundY + 50, 5, -10)
);
}
}
}
this.levelTwoCollectables = [];
for (let i = 0; i < 55; i++) {
x = random(0, 20 * width);
y = random(150, groundY + 40);
this.levelTwoCollectables.push(
new Collectable(coinImg, 15, width + x, y, 40, 40)
);
}
this.levelThreeObstacles = [];
for (let i = 0; i < 25; i++) {
let y = random(50, groundY);
let randomOffset = random(0, 12 * width);
x = (i + 1) * this.obstacleSpacing + randomOffset;
this.levelThreeObstacles.push(
new Obstacle(birds, 3, 4, width + x, y, 6, -10)
);
y = random(50, groundY);
randomOffset = random(0, 8 * width);
x = (i + 1) * this.obstacleSpacing + randomOffset;
this.levelThreeObstacles.push(
new Obstacle(seagull, 3, 4, width + x, y, 4, -10)
);
}
this.levelThreeCollectables = [];
for (let i = 0; i < 70; i++) {
x = random(0, 16 * width);
y = random(50, groundY);
this.levelThreeCollectables.push(
new Collectable(anchor, 15, width + x, y, 35, 35)
);
}
}
landingScreen() {
rectMode(CORNER);
// Set tint for the background image to make it semi-transparent
tint(255, 180);
image(landing, 0, 0, width, height);
noTint(); // Reset tint
fill("#012d38");
textAlign(LEFT, TOP);
textFont(gameFont);
textSize(36);
rectMode(CORNER);
text("A Life Odyssey", 15, height / 2 - 50);
textAlign(LEFT, TOP);
rectMode(CORNER);
textFont(storyFont);
textSize(20);
text(
`A story in parts. Navigate our character through different stages in his life.
Press spacebar to jump (and you can double jump!). You gain points for getting collectables, and lose points when you hit obstacles.
Click anywhere to start.`,
15,
height / 2,
500
);
}
finalScreen() {
// Set tint for the background image to make it semi-transparent
tint(255, 180);
image(endScreen, 0, 0, width, height);
noTint(); // Reset tint
fill("white");
textAlign(LEFT);
textFont(gameFont);
textSize(28);
text(`Final Score: ${this.score}`, 15, 150);
textFont(storyFont);
textSize(36);
text("You made it!", 15, 210);
textFont(storyFont);
textSize(25);
textAlign(LEFT);
text(
`Who knows where we will go next.
Click anywhere to start again.`,
15,
height / 2 + 80
);
}
levelOneTitleScreen() {
let textContent = `Chapter 1: THE SIMPLE LIFE
You're in the village! Gather ripe mangoes while avoiding the village cattle and herd.
Click anywhere to continue.`;
image(landscape, 0, 0, width, height);
tint(255, 127);
noStroke();
fill("#97bfb5");
rectMode(CENTER);
rect(width / 2, height / 2, 480, 230);
fill("#eeedda");
rect(width / 2, height / 2, 450, 200);
fill("#145926");
textAlign(CENTER, CENTER);
textFont(storyFont);
textSize(28);
text(textContent, width / 2, height / 2, 400, 200);
}
levelTwoTitleScreen() {
let textContent = `Chapter 2: THE CONCRETE JUNGLE
You've decided to move to the city. Collect coins and avoid getting into mishaps on the street!
Click anywhere to continue.`;
image(cityTitle, 0, 0, width, height);
tint(255, 127);
noStroke();
fill("#47346a");
rectMode(CENTER);
rect(width / 2, height / 2, 480, 230);
fill("#e6cdbe");
rect(width / 2, height / 2, 450, 200);
fill("#47346a");
textAlign(CENTER, CENTER);
textFont(storyFont);
textSize(28);
text(textContent, width / 2, height / 2, 400, 200);
}
levelThreeTitleScreen() {
let textContent = `Chapter 3: SETTING SAIL
You're headed off to sea, and embracing the sailor's life. Collect anchors and try to stay afloat!
Click anywhere to continue.`;
image(oceanTitle, 0, 0, width, height);
tint(255, 127);
noStroke();
fill("#667b9d");
rectMode(CENTER);
rect(width / 2, height / 2, 480, 230);
fill("#deebff");
rect(width / 2, height / 2, 450, 200);
fill("#30306b");
textAlign(CENTER, CENTER);
textFont(storyFont);
textSize(28);
text(textContent, width / 2, height / 2, 400, 200);
}
levelOne() {
tint(255);
image(bg, x1, 0, width, height);
image(bg, x2, 0, width, height);
let last = this.levelOneObstacles.length - 1;
x1 -= scrollSpeed;
x2 -= scrollSpeed;
if (x1 < -width) {
x1 = x2 + width;
}
if (x2 < -width) {
x2 = x1 + width;
}
this.player.updatePosition();
for (let i = 0; i < this.levelOneObstacles.length; i++) {
this.levelOneObstacles[i].updatePosition();
if (
this.player.collision(this.levelOneObstacles[i]) &&
this.levelOneObstacles[i].hit == false
) {
// print("u lose");
losePointSound.play();
this.score += this.levelOneObstacles[i].points;
this.levelOneObstacles[i].hit = true;
}
}
for (let i = 0; i < this.levelOneCollectables.length; i++) {
if (!this.levelOneCollectables[i].collected) {
this.levelOneCollectables[i].drawSelf();
}
if (
this.player.collision(this.levelOneCollectables[i]) &&
this.levelOneCollectables[i].collected == false
) {
collectSound.play();
this.score += this.levelOneCollectables[i].points;
this.levelOneCollectables[i].collected = true;
}
}
if (this.levelOneObstacles[last].x + this.levelOneObstacles[last].w < 0) {
gameState += 1;
showScore = false;
updateMusic(gameState);
}
}
levelTwo() {
tint(255);
let last = this.levelTwoObstacles.length - 1;
this.player.setGround(groundY + 30);
image(cityBg, x1, 0, width, height);
image(cityBg, x2, 0, width, height);
x1 -= scrollSpeed;
x2 -= scrollSpeed;
if (x1 < -width) {
x1 = x2 + width;
}
if (x2 < -width) {
x2 = x1 + width;
}
this.player.updatePosition();
for (let i = 0; i < this.levelTwoObstacles.length; i++) {
this.levelTwoObstacles[i].updatePosition();
if (
this.player.collision(this.levelTwoObstacles[i]) &&
this.levelTwoObstacles[i].hit == false
) {
losePointSound.play();
this.score += this.levelTwoObstacles[i].points;
this.levelTwoObstacles[i].hit = true;
}
}
for (let i = 0; i < this.levelTwoCollectables.length; i++) {
if (!this.levelTwoCollectables[i].collected) {
this.levelTwoCollectables[i].drawSelf();
}
if (
this.player.collision(this.levelTwoCollectables[i]) &&
this.levelTwoCollectables[i].collected == false
) {
// ("u lose");
collectSound.play();
this.score += this.levelTwoCollectables[i].points;
this.levelTwoCollectables[i].collected = true;
}
}
if (this.levelTwoObstacles[last].x + this.levelTwoObstacles[last].w < 0) {
gameState += 1;
showScore = false;
updateMusic(gameState);
}
}
levelThree() {
tint(255);
let last = this.levelThreeObstacles.length - 1;
image(ocean, x1, 0, width, height);
image(ocean, x2, 0, width, height);
x1 -= scrollSpeed;
x2 -= scrollSpeed;
if (x1 < -width) {
x1 = x2 + width;
}
if (x2 < -width) {
x2 = x1 + width;
}
this.playerBoat.updatePosition();
for (let i = 0; i < this.levelThreeObstacles.length; i++) {
this.levelThreeObstacles[i].updatePosition();
if (
this.playerBoat.collision(this.levelThreeObstacles[i]) &&
this.levelThreeObstacles[i].hit == false
) {
losePointSound.play();
this.score += this.levelThreeObstacles[i].points;
this.levelThreeObstacles[i].hit = true;
}
}
for (let i = 0; i < this.levelThreeCollectables.length; i++) {
if (!this.levelThreeCollectables[i].collected) {
this.levelThreeCollectables[i].drawSelf();
}
if (
this.playerBoat.collision(this.levelThreeCollectables[i]) &&
this.levelThreeCollectables[i].collected == false
) {
collectSound.play();
this.score += this.levelThreeCollectables[i].points;
this.levelThreeCollectables[i].collected = true;
}
}
if (
this.levelThreeObstacles[last].x + this.levelThreeObstacles[last].w <
0
) {
gameState += 1;
showScore = false;
updateMusic(gameState);
}
}
}
class Player {
constructor(spritesheet, spritesAcross, spritesDown, x, y, speed) {
this.w = int(spritesheet.width / spritesAcross);
this.h = int(spritesheet.height / spritesDown);
this.across = spritesAcross;
this.down = spritesDown;
this.direction = 2;
this.sprites = [];
for (let y = 0; y < spritesDown; y++) {
this.sprites[y] = [];
for (let x = 0; x < spritesAcross; x++) {
this.sprites[y][x] = spritesheet.get(
x * this.w,
y * this.h,
this.w,
this.h
);
}
}
this.x = this.w + 15;
this.y = y;
this.ground = y;
this.speed = speed;
this.step = 0;
this.jump = 15;
this.vy = 0;
this.canDoubleJump = true;
this.g = 1;
this.isMoving = true;
// this.score = 0;
}
setGround(newY) {
this.ground = newY;
}
updatePosition() {
this.y += this.vy;
// gx -= obstacleSpeed;
if (this.y < this.ground) {
this.vy += g;
} else {
this.vy = 0;
this.y = this.ground;
this.canDoubleJump = true;
}
if (this.isMoving) {
if (frameCount % this.speed == 0) {
this.step = (this.step + 1) % this.across;
}
}
image(this.sprites[this.direction][this.step], this.x, this.y);
}
doAJump() {
if (this.y >= this.ground) {
this.vy = -this.jump;
this.canDoubleJump = true;
} else if (this.canDoubleJump) {
this.vy = -this.jump;
this.canDoubleJump = false; // Consume double jump
}
}
/*
collision(obj) {
let playerLeft = this.x;
let playerRight = this.x + this.w;
let playerTop = this.y;
let playerBottom = this.y + this.h;
let objectLeft = obj.x;
let objectRight = obj.x + obj.w;
let objectTop = obj.y;
let objectBottom = obj.y + obj.h;
if (
playerLeft < objectRight &&
playerRight > objectLeft &&
playerTop < objectBottom &&
playerBottom > objectTop
) {
// Collided
return true;
} else {
// Not collided
return false;
}
}*/
collision(obj) {
// Calculate the center of the character
let playerCenterX = this.x + this.w / 2;
let playerCenterY = this.y + this.h / 2;
// Calculate the center of the collision object
let objectCenterX = obj.x + obj.w / 2;
let objectCenterY = obj.y + obj.h / 2;
// Define the collision radius (e.g., 5 pixels)
let collisionRadius = 10;
// Calculate the distance between the two centers
let distance = Math.sqrt(
(playerCenterX - objectCenterX) ** 2 +
(playerCenterY - objectCenterY) ** 2
);
if (distance < collisionRadius + obj.w / 2) {
// Collided
return true;
} else {
// Not collided
return false;
}
}
}
class Boat extends Player {
constructor(spritesheet, spritesAcross, spritesDown, x, y, speed) {
super(spritesheet, spritesAcross, spritesDown, x, y, speed);
}
updatePosition() {
this.y += this.vy;
if (this.y < this.ground) {
this.vy += g;
} else {
this.vy = 0;
this.y = this.ground;
this.canDoubleJump = true;
}
image(this.sprites[2][0], 80, this.y);
image(boat, 0, 170, 260, 200);
}
}
class Obstacle {
constructor(
spritesheet,
spritesAcross,
spritesDown,
startX,
startY,
speed,
points,
direction = 1
) {
this.w = int(spritesheet.width / spritesAcross);
this.h = int(spritesheet.height / spritesDown);
this.across = spritesAcross;
this.down = spritesDown;
this.direction = direction;
this.sprites = [];
for (let y = 0; y < spritesDown; y++) {
this.sprites[y] = [];
for (let x = 0; x < spritesAcross; x++) {
this.sprites[y][x] = spritesheet.get(
x * this.w,
y * this.h,
this.w,
this.h
);
}
}
this.x = startX;
this.y = startY;
this.speed = speed;
this.step = 0;
this.points = points;
this.hit = false;
}
updatePosition() {
this.x -= this.speed;
if (frameCount % this.speed == 0) {
this.step = (this.step + 1) % this.across;
}
image(this.sprites[this.direction][this.step], this.x, this.y);
}
}
class Collectable {
constructor(img, points, x, y, w = 26, h = 26) {
this.img = img;
this.points = points;
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.collected = false;
}
drawSelf() {
this.x -= 5;
image(this.img, this.x, this.y, this.w, this.h);
}
}
function preload() {
gameFont = loadFont("fonts/joystix-monospace.otf");
storyFont = loadFont("fonts/dpcomic.ttf");
spritesheet = loadImage("images/character.png");
bg = loadImage("images/village-bg.jpg");
goats = loadImage("images/goat.png");
mangoImg = loadImage("images/mango.png");
// chilliImg = loadImage("images/chilli.png");
// sheep = loadImage("images/sheep.png");
bull = loadImage("images/bull.png");
cityBg = loadImage("images/city.jpg");
greyCar = loadImage("images/grey-car.png");
mice = loadImage("images/mice2.png");
birds = loadImage("images/birds.png");
coinImg = loadImage("images/coin.png");
ocean = loadImage("images/ocean.png");
boat = loadImage("images/boat2.png");
seagull = loadImage("images/seagull_3.png");
anchor = loadImage("images/anchor.png");
landscape = loadImage("images/landscape.jpeg");
cityTitle = loadImage("images/cityTitle.png");
oceanTitle = loadImage("images/oceanTitle.jpeg");
landing = loadImage("images/landing2.jpeg");
endScreen = loadImage("images/end2.jpeg");
collectSound = loadSound("sounds/collect.mp3");
losePointSound = loadSound("sounds/hitSound.wav");
bgMusic = loadSound("sounds/bg.mp3");
cityMusic = loadSound("sounds/cityMusic.mp3");
oceanMusic = loadSound("sounds/atSeashort.mp3");
villageMusic = loadSound("sounds/village.mp3");
}
function updateMusic(state) {
if (state == 1) {
bgMusic.stop();
villageMusic.loop();
} else if (state == 3) {
console.log("here");
villageMusic.stop();
cityMusic.loop();
} else if (state == 5) {
cityMusic.stop();
oceanMusic.loop();
} else if (state == 7) {
oceanMusic.stop();
bgMusic.loop();
}
}
function setup() {
createCanvas(600, 400);
x2 = width;
bgMusic.loop();
// player = new Player(spritesheet, 4, 4, 0, groundY, 8);
// goat = new Obstacle(goatSpriteSheet, 3, 4, width + 10, groundY + 15, 4);
// mango = new Collectable(mangoImg, 10, width / 2, groundY + 15);
game = new Game();
}
function draw() {
clear();
background(255);
if (gameState == 1) {
game.levelOneTitleScreen();
} else if (gameState == 2) {
game.levelOne();
} else if (gameState == 3) {
game.levelTwoTitleScreen();
} else if (gameState == 4) {
game.levelTwo();
} else if (gameState == 5) {
game.levelThreeTitleScreen();
} else if (gameState == 6) {
game.levelThree();
} else if (gameState == 0) {
game.landingScreen();
} else if (gameState == 7) {
game.finalScreen();
}
if (showScore) {
fill("black");
textFont(gameFont);
textAlign(LEFT);
textSize(28);
text(`Score: ${game.score}`, 15, 50);
}
}
function keyPressed() {
if (keyCode == 32) {
if (gameState == 6) {
game.playerBoat.doAJump();
} else {
game.player.doAJump();
}
}
}
function mouseClicked() {
if (gameState == 0) {
gameState += 1;
updateMusic(gameState);
} else if (gameState == 7) {
delete game;
game = new Game();
gameState = 0;
} else if (gameState % 2 != 0) {
gameState += 1;
showScore = true;
updateMusic(gameState);
}
}