You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
617 lines
19 KiB
617 lines
19 KiB
// lib/game-background.js
|
|
// Copyright (C) 2022 Rob Colbert @[email protected]
|
|
// License: Apache-2.0
|
|
|
|
'use strict';
|
|
|
|
import { NiceColor, NiceEasing, NiceSprite, NiceTween, NiceVector2d } from 'dtp-nice-game';
|
|
import GameButterfly from './game-buttterfly.js';
|
|
|
|
import GameObject from './game-object.js';
|
|
|
|
const SKY_HEIGHT = 200;
|
|
const WATER_HEIGHT = 150;
|
|
const WATER_END = SKY_HEIGHT + WATER_HEIGHT;
|
|
|
|
class OceanWave {
|
|
|
|
constructor (game) {
|
|
this.game = game;
|
|
|
|
function randomY ( ) {
|
|
return SKY_HEIGHT + (Math.random() * 20);
|
|
}
|
|
|
|
this.points = [ ];
|
|
this.startY = randomY();
|
|
|
|
const wavePointSpacing = game.playfield.width / 16;
|
|
for (let x = wavePointSpacing; x <= game.playfield.width; x += wavePointSpacing) {
|
|
this.points.push({
|
|
control: new NiceVector2d(x - (wavePointSpacing / 0.8), randomY()),
|
|
target: new NiceVector2d(x, randomY())
|
|
});
|
|
}
|
|
}
|
|
|
|
update (elapsed) {
|
|
const BASE_RATE = 10.0;
|
|
const VARIANCE = 2.0;
|
|
const timeScale = elapsed / 1000.0;
|
|
|
|
this.startY += (BASE_RATE + (VARIANCE * Math.random())) * timeScale;
|
|
|
|
let maxY = 0;
|
|
this.points.forEach((point) => {
|
|
point.control.y += (BASE_RATE + (VARIANCE * Math.random())) * timeScale;
|
|
point.target.y += (BASE_RATE + (VARIANCE * Math.random())) * timeScale;
|
|
if (point.target.y > maxY) {
|
|
maxY = point.target.y;
|
|
}
|
|
});
|
|
|
|
return maxY < WATER_END;
|
|
}
|
|
|
|
render (ctx) {
|
|
let maxY = 0;
|
|
let minY = this.game.playfield.height;
|
|
|
|
ctx.beginPath();
|
|
ctx.moveTo(0, this.startY);
|
|
if (this.startY > maxY) {
|
|
maxY = this.startY;
|
|
}
|
|
if (this.startY < minY) {
|
|
minY = this.startY;
|
|
}
|
|
|
|
this.points.forEach((point) => {
|
|
ctx.quadraticCurveTo(point.control.x, point.control.y, point.target.x, point.target.y);
|
|
if (point.target.y > maxY) {
|
|
maxY = point.target.y;
|
|
}
|
|
if (point.target.y < minY) {
|
|
minY = point.target.y;
|
|
}
|
|
});
|
|
|
|
const oldOpacity = ctx.globalAlpha;
|
|
|
|
ctx.globalAlpha = 1.0;
|
|
if (maxY > (WATER_END - 50)) {
|
|
let term = WATER_END - maxY;
|
|
if (term < 0) { term = 0; }
|
|
ctx.globalAlpha = term / 50.0;
|
|
}
|
|
|
|
let alpha = (maxY - SKY_HEIGHT) / WATER_HEIGHT;
|
|
|
|
const color = new NiceColor(255,255,255, alpha);
|
|
ctx.strokeStyle = color.toCssString();
|
|
ctx.lineWidth = 2.0;
|
|
ctx.stroke();
|
|
|
|
minY -= 80;
|
|
if (minY < SKY_HEIGHT) {
|
|
minY = SKY_HEIGHT;
|
|
}
|
|
ctx.lineTo(this.game.playfield.width, minY);
|
|
ctx.lineTo(0, minY);
|
|
ctx.closePath();
|
|
|
|
color.a /= 2.0;
|
|
if (color.a > 0.2) {
|
|
color.a = 0.4;
|
|
}
|
|
ctx.fillStyle = ctx.createLinearGradient(0, minY, 0, maxY);
|
|
ctx.fillStyle.addColorStop(0.0, '#ffffff00');
|
|
ctx.fillStyle.addColorStop(1.0, color.toCssString());
|
|
|
|
ctx.fill();
|
|
|
|
ctx.globalAlpha = oldOpacity;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* GameBackground is responsible for rendering the background/environment, and
|
|
* it uses a variety of techniques to do that. Gradients are used to render the
|
|
* sky, beach, and ocean. Images are used to render the trees, plants, and
|
|
* foreground base.
|
|
*
|
|
* GameBackground has modes, and can reconfigure itself and animate between
|
|
* them on command using reusable NiceTween instances. It currently supports
|
|
* GameBackground.MODE_STORY and GameBackground.MODE_PLAY.
|
|
*/
|
|
export default class GameBackground {
|
|
|
|
static get MODE_STORY ( ) { return 'story'; }
|
|
static get MODE_PLAY ( ) { return 'play'; }
|
|
|
|
constructor (game) {
|
|
this.game = game;
|
|
this.sprites = { };
|
|
this.tweens = { };
|
|
|
|
this.sun = {
|
|
position: new NiceVector2d(480, 140),
|
|
};
|
|
|
|
this.waves = [ ];
|
|
this.boats = [ ];
|
|
this.clouds = [ ];
|
|
}
|
|
|
|
async load ( ) {
|
|
await this.loadImages();
|
|
|
|
this.buildSprites();
|
|
this.buildTweens();
|
|
this.setEnvironmentMode('day');
|
|
}
|
|
|
|
async loadImages ( ) {
|
|
const jobs = [ ];
|
|
|
|
jobs.push(this.game.loadImage('bg:foreground-base', '/dist/assets/img/beach/foreground-base.png', 960, 114));
|
|
jobs.push(this.game.loadImage('bg:sailboat', '/dist/assets/img/beach/sailboat.png', 116, 120));
|
|
jobs.push(this.game.loadImage('bg:rocky-island', '/dist/assets/img/beach/rocky-island.png', 385, 80));
|
|
|
|
jobs.push(this.game.loadImage('bg:tree-left', '/dist/assets/img/beach/tree-left.png', 361, 540));
|
|
jobs.push(this.game.loadImage('bg:tree-right', '/dist/assets/img/beach/tree-right.png', 351, 540));
|
|
|
|
jobs.push(this.game.loadImage('bg:plant-left', '/dist/assets/img/beach/plant-left.png', 148, 303));
|
|
jobs.push(this.game.loadImage('bg:plant-right', '/dist/assets/img/beach/plant-right.png', 170, 211));
|
|
|
|
jobs.push(this.game.loadImage('bg:cloud-001', '/dist/assets/img/beach/cloud-001.png', 132, 40));
|
|
jobs.push(this.game.loadImage('bg:cloud-002', '/dist/assets/img/beach/cloud-002.png', 115, 40));
|
|
jobs.push(this.game.loadImage('bg:cloud-003', '/dist/assets/img/beach/cloud-003.png', 105, 60));
|
|
jobs.push(this.game.loadImage('bg:cloud-004', '/dist/assets/img/beach/cloud-004.png', 118, 32));
|
|
jobs.push(this.game.loadImage('bg:cloud-005', '/dist/assets/img/beach/cloud-005.png', 141, 50));
|
|
jobs.push(this.game.loadImage('bg:cloud-006', '/dist/assets/img/beach/cloud-006.png', 119, 50));
|
|
|
|
jobs.push(this.game.loadImage('bg:butterfly-001', '/dist/assets/img/beach/butterfly-001.png', 27, 24));
|
|
jobs.push(this.game.loadImage('bg:butterfly-002', '/dist/assets/img/beach/butterfly-002.png', 27, 24));
|
|
jobs.push(this.game.loadImage('bg:butterfly-003', '/dist/assets/img/beach/butterfly-003.png', 27, 24));
|
|
jobs.push(this.game.loadImage('bg:butterfly-004', '/dist/assets/img/beach/butterfly-004.png', 27, 24));
|
|
|
|
await Promise.all(jobs);
|
|
}
|
|
|
|
buildSprites ( ) {
|
|
this.sprites.foreground = new NiceSprite(this.game, new NiceVector2d(this.game.playfield.width / 2, this.game.playfield.height));
|
|
this.sprites.foreground.image = this.game.images['bg:foreground-base'];
|
|
this.sprites.foreground.registration = new NiceVector2d(480, this.sprites.foreground.image.height);
|
|
|
|
this.sprites.treeLeft = new NiceSprite(this.game, new NiceVector2d(0, this.game.playfield.height));
|
|
this.sprites.treeLeft.image = this.game.images['bg:tree-left'];
|
|
this.sprites.treeLeft.registration = new NiceVector2d(0, this.sprites.treeLeft.image.height);
|
|
|
|
this.sprites.treeRight = new NiceSprite(this.game, new NiceVector2d(this.game.playfield.width, 0));
|
|
this.sprites.treeRight.image = this.game.images['bg:tree-right'];
|
|
this.sprites.treeRight.registration = new NiceVector2d(this.sprites.treeRight.image.width, 0);
|
|
|
|
this.sprites.plantLeft = new NiceSprite(this.game, new NiceVector2d(0, this.game.playfield.height));
|
|
this.sprites.plantLeft.image = this.game.images['bg:plant-left'];
|
|
this.sprites.plantLeft.registration = new NiceVector2d(0, this.sprites.plantLeft.image.height);
|
|
|
|
this.sprites.plantRight = new NiceSprite(this.game, new NiceVector2d(this.game.playfield.width, this.game.playfield.height));
|
|
this.sprites.plantRight.image = this.game.images['bg:plant-right'];
|
|
this.sprites.plantRight.registration = new NiceVector2d(
|
|
this.sprites.plantRight.image.width,
|
|
this.sprites.plantRight.image.height,
|
|
);
|
|
}
|
|
|
|
buildTweens ( ) {
|
|
const FOREGROUND_DURATION = 1000;
|
|
const TREE_DURATION = 1250;
|
|
const PLANT_DURATION = 1500;
|
|
|
|
/*
|
|
* FOREGROUND BASE
|
|
*/
|
|
this.tweens.foregroundIn = new NiceTween(
|
|
this.game,
|
|
this.sprites.foreground.position,
|
|
{ y: this.game.playfield.height + this.sprites.foreground.image.height},
|
|
{ y: this.game.playfield.height },
|
|
NiceEasing.Quadratic.Out,
|
|
);
|
|
this.tweens.foregroundIn.duration(FOREGROUND_DURATION);
|
|
|
|
this.tweens.foregroundOut = new NiceTween(
|
|
this.game,
|
|
this.sprites.foreground.position,
|
|
{ y: this.game.playfield.height },
|
|
{ y: this.game.playfield.height + this.sprites.foreground.image.height},
|
|
NiceEasing.Quadratic.In,
|
|
);
|
|
this.tweens.foregroundOut.duration(FOREGROUND_DURATION);
|
|
|
|
/*
|
|
* TREE LEFT
|
|
*/
|
|
this.tweens.treeLeftIn = new NiceTween(
|
|
this.game,
|
|
this.sprites.treeLeft.position,
|
|
{ x: -this.sprites.treeLeft.image.width },
|
|
{ x: 0 },
|
|
NiceEasing.Elastic.Out,
|
|
);
|
|
this.tweens.treeLeftIn.duration(TREE_DURATION);
|
|
|
|
this.tweens.treeLeftOut = new NiceTween(
|
|
this.game,
|
|
this.sprites.treeLeft.position,
|
|
{ x: 0 },
|
|
{ x: -this.sprites.treeLeft.image.width },
|
|
NiceEasing.Elastic.In,
|
|
);
|
|
this.tweens.treeLeftOut.duration(TREE_DURATION);
|
|
|
|
/*
|
|
* TREE RIGHT
|
|
*/
|
|
this.tweens.treeRightIn = new NiceTween(
|
|
this.game,
|
|
this.sprites.treeRight.position,
|
|
{ x: this.game.playfield.width + this.sprites.treeRight.image.width },
|
|
{ x: this.game.playfield.width },
|
|
NiceEasing.Elastic.Out,
|
|
);
|
|
this.tweens.treeRightIn.duration(TREE_DURATION);
|
|
|
|
this.tweens.treeRightOut = new NiceTween(
|
|
this.game,
|
|
this.sprites.treeRight.position,
|
|
{ x: this.game.playfield.width },
|
|
{ x: this.game.playfield.width + this.sprites.treeRight.image.width },
|
|
NiceEasing.Elastic.In,
|
|
);
|
|
this.tweens.treeRightOut.duration(TREE_DURATION);
|
|
|
|
/*
|
|
* PLANT LEFT
|
|
*/
|
|
this.tweens.plantLeftIn = new NiceTween(
|
|
this.game,
|
|
this.sprites.plantLeft.position,
|
|
{ x: -this.sprites.plantLeft.image.width },
|
|
{ x: 0 },
|
|
NiceEasing.Elastic.Out,
|
|
);
|
|
this.tweens.plantLeftIn.duration(PLANT_DURATION);
|
|
|
|
this.tweens.plantLeftOut = new NiceTween(
|
|
this.game,
|
|
this.sprites.plantLeft.position,
|
|
{ x: 0 },
|
|
{ x: -this.sprites.plantLeft.image.width },
|
|
NiceEasing.Elastic.In,
|
|
);
|
|
this.tweens.plantLeftOut.duration(PLANT_DURATION);
|
|
|
|
/*
|
|
* PLANT RIGHT
|
|
*/
|
|
this.tweens.plantRightIn = new NiceTween(
|
|
this.game,
|
|
this.sprites.plantRight.position,
|
|
{ x: this.game.playfield.width + this.sprites.plantRight.width },
|
|
{ x: this.game.playfield.width },
|
|
NiceEasing.Elastic.Out,
|
|
);
|
|
this.tweens.plantRightIn.duration(PLANT_DURATION);
|
|
|
|
this.tweens.plantRightOut = new NiceTween(
|
|
this.game,
|
|
this.sprites.plantRight.position,
|
|
{ x: this.game.playfield.width },
|
|
{ x: this.game.playfield.width + this.sprites.plantRight.width },
|
|
NiceEasing.Elastic.In,
|
|
);
|
|
this.tweens.plantRightOut.duration(PLANT_DURATION);
|
|
|
|
/*
|
|
* Environment: Day To Night transition
|
|
*/
|
|
|
|
this.tweens.environmentDayToNight = new NiceTween(
|
|
this.game,
|
|
this.applyEnvironmentTween.bind(this),
|
|
{
|
|
sun_y: 20,
|
|
|
|
sky_r0: 189, sky_g0: 213, sky_b0: 179, sky_a0: 1.0,
|
|
sky_r1: 240, sky_g1: 242, sky_b1: 220, sky_a1: 1.0,
|
|
|
|
beach_r0: 224, beach_g0: 164, beach_b0: 127, beach_a0: 1.0,
|
|
beach_r1: 246, beach_g1: 234, beach_b1: 182, beach_a1: 1.0,
|
|
},
|
|
{
|
|
sun_y: 140,
|
|
|
|
sky_r0: 1, sky_g0: 13, sky_b0: 66, sky_a0: 1.0,
|
|
sky_r1: 49, sky_g1: 56, sky_b1: 122, sky_a1: 1.0,
|
|
|
|
beach_r0: 47, beach_g0: 81, beach_b0: 152, beach_a0: 1.0,
|
|
beach_r1: 36, beach_g1: 51, beach_b1: 92, beach_a1: 1.0,
|
|
},
|
|
NiceEasing.Circular.InOut,
|
|
);
|
|
|
|
/*
|
|
* Environment: Night To Day transition
|
|
*/
|
|
|
|
this.tweens.environmentNightToDay = new NiceTween(
|
|
this.game,
|
|
this.applyEnvironmentTween.bind(this),
|
|
{
|
|
sun_y: 140,
|
|
|
|
sky_r0: 1, sky_g0: 13, sky_b0: 66, sky_a0: 1.0,
|
|
sky_r1: 49, sky_g1: 56, sky_b1: 122, sky_a1: 1.0,
|
|
|
|
beach_r0: 47, beach_g0: 81, beach_b0: 152, beach_a0: 1.0,
|
|
beach_r1: 36, beach_g1: 51, beach_b1: 92, beach_a1: 1.0,
|
|
},
|
|
{
|
|
sun_y: 20,
|
|
|
|
sky_r0: 189, sky_g0: 213, sky_b0: 179, sky_a0: 1.0,
|
|
sky_r1: 240, sky_g1: 242, sky_b1: 220, sky_a1: 1.0,
|
|
|
|
beach_r0: 224, beach_g0: 164, beach_b0: 127, beach_a0: 1.0,
|
|
beach_r1: 246, beach_g1: 234, beach_b1: 182, beach_a1: 1.0,
|
|
},
|
|
NiceEasing.Cubic.InOut,
|
|
);
|
|
}
|
|
|
|
applyEnvironmentTween (current) {
|
|
this.sun.position.y = current.sun_y;
|
|
|
|
this.skyGradient = this.game.gameDisplayCtx.createLinearGradient(0, 0, 0, SKY_HEIGHT);
|
|
this.skyGradient.addColorStop(0.0, `rgba(${current.sky_r0},${current.sky_g0},${current.sky_b0}, ${current.sky_a0})`);
|
|
this.skyGradient.addColorStop(1.0, `rgba(${current.sky_r1},${current.sky_g1},${current.sky_b1}, ${current.sky_a1})`);
|
|
|
|
this.beachGradient = this.game.gameDisplayCtx.createLinearGradient(0, SKY_HEIGHT, 0, this.game.playfield.height);
|
|
this.beachGradient.addColorStop(0.0, `rgba(${current.beach_r0},${current.beach_g0},${current.beach_b0}, ${current.beach_a0})`);
|
|
this.beachGradient.addColorStop(1.0, `rgba(${current.beach_r1},${current.beach_g1},${current.beach_b1}, ${current.beach_a1})`);
|
|
}
|
|
|
|
setMode (mode) {
|
|
this.mode = mode;
|
|
|
|
delete this.butterfly;
|
|
|
|
this.tweens.foregroundIn.stop();
|
|
this.tweens.treeLeftIn.stop();
|
|
this.tweens.treeRightIn.stop();
|
|
this.tweens.plantLeftIn.stop();
|
|
this.tweens.plantRightIn.stop();
|
|
|
|
switch (this.mode) {
|
|
case 'story':
|
|
this.tweens.foregroundIn.delay(2000).run();
|
|
this.tweens.treeLeftIn.delay(2000).run();
|
|
this.tweens.treeRightIn.delay(2000).run();
|
|
this.tweens.plantLeftIn.delay(2000).run();
|
|
this.tweens.plantRightIn.delay(2000).run();
|
|
|
|
this.butterfly = new GameButterfly(
|
|
this.game,
|
|
this.game.images['bg:butterfly-002'],
|
|
new NiceVector2d(320, 280),
|
|
);
|
|
this.butterfly.navigator.setMoveSpeed(40.0);
|
|
this.butterfly.navigator.setTargetPosition(new NiceVector2d(503, 386));
|
|
break;
|
|
|
|
case 'play':
|
|
this.tweens.foregroundOut.run();
|
|
this.tweens.treeLeftOut.run();
|
|
this.tweens.treeRightOut.run();
|
|
this.tweens.plantLeftOut.run();
|
|
this.tweens.plantRightOut.run();
|
|
break;
|
|
}
|
|
}
|
|
|
|
update (elapsed, now) {
|
|
if ((!this.nextWaveSpawnTime) || (now >= this.nextWaveSpawnTime)) {
|
|
this.nextWaveSpawnTime = now + 12000;
|
|
this.waves.push(new OceanWave(this.game));
|
|
}
|
|
this.waves = this.waves.filter((wave) => wave.update(elapsed, now));
|
|
|
|
if ((!this.nextBoatSpawnTime) || (now >= this.nextBoatSpawnTime)) {
|
|
this.nextBoatSpawnTime = now + 20000 + (Math.random() * 10000);
|
|
this.spawnBoat();
|
|
}
|
|
if ((!this.nextCloudSpawnTime) || (now >= this.nextCloudSpawnTime)) {
|
|
this.nextCloudSpawnTime = now + 30000 + (Math.random() + 50000);
|
|
this.spawnCloud();
|
|
}
|
|
|
|
for (const tweenKey in this.tweens) {
|
|
const tween = this.tweens[tweenKey];
|
|
if (tween.state !== 'running') {
|
|
continue;
|
|
}
|
|
tween.update(elapsed, now);
|
|
}
|
|
|
|
if (this.butterfly) {
|
|
this.butterfly.update(elapsed, now);
|
|
}
|
|
}
|
|
|
|
spawnBoat ( ) {
|
|
function randomBoatY ( ) {
|
|
return SKY_HEIGHT + 20 + (Math.random() * 40);
|
|
}
|
|
|
|
const { playfield } = this.game;
|
|
if (Math.random() > 0.5) {
|
|
const boat = new NiceSprite(this.game, { x: 0, y: randomBoatY() });
|
|
boat.image = this.game.images['bg:sailboat'];
|
|
boat.registration = new NiceVector2d(boat.image.width / 2, boat.image.height - 10);
|
|
this.boats.push(boat);
|
|
this.game
|
|
.createTween(
|
|
boat.position,
|
|
{ x: -boat.image.width },
|
|
{ x: playfield.width + boat.image.width },
|
|
NiceEasing.Linear.None,
|
|
)
|
|
.duration(30000 + (Math.random() * 10000))
|
|
.run()
|
|
;
|
|
} else {
|
|
const boat = new NiceSprite(this.game, { x: playfield.width, y: randomBoatY() });
|
|
boat.image = this.game.images['bg:sailboat'];
|
|
boat.registration = new NiceVector2d(boat.image.width / 2, boat.image.height - 10);
|
|
boat.mirror = true;
|
|
this.boats.push(boat);
|
|
this.game
|
|
.createTween(
|
|
boat.position,
|
|
{ x: this.game.playfield.width + boat.image.width },
|
|
{ x: -boat.image.width },
|
|
NiceEasing.Linear.None,
|
|
)
|
|
.duration(30000 + (Math.random() * 10000))
|
|
.run()
|
|
;
|
|
}
|
|
|
|
this.boats = this.boats.sort((a, b) => a.position.y - b.position.y);
|
|
}
|
|
|
|
spawnCloud ( ) {
|
|
function randomCloudY ( ) {
|
|
return 20 + (Math.random() * (SKY_HEIGHT - 50));
|
|
}
|
|
|
|
const image = this.game.images['bg:cloud-001'];
|
|
if (Math.random() > 0.5) {
|
|
const cloud = new NiceSprite(this.game, new NiceVector2d(-image.width / 2, randomCloudY()));
|
|
this.clouds.push(cloud);
|
|
|
|
cloud.image = image;
|
|
cloud.registration = new NiceVector2d(image.width / 2, image.height / 2);
|
|
|
|
this.game
|
|
.createTween(
|
|
cloud.position,
|
|
{ x: -image.width / 2 },
|
|
{ x: this.game.playfield.width + image.width / 2 },
|
|
NiceEasing.Linear.None,
|
|
)
|
|
.duration(60000 + (Math.random() * 20000))
|
|
.run()
|
|
;
|
|
} else {
|
|
const cloud = new NiceSprite(this.game, new NiceVector2d(-image.width / 2, randomCloudY()));
|
|
this.clouds.push(cloud);
|
|
|
|
cloud.image = image;
|
|
cloud.registration = new NiceVector2d(image.width / 2, image.height / 2);
|
|
|
|
this.game
|
|
.createTween(
|
|
cloud.position,
|
|
{ x: this.game.playfield.width + image.width / 2 },
|
|
{ x: -image.width / 2 },
|
|
NiceEasing.Linear.None,
|
|
)
|
|
.duration(60000 + (Math.random() * 20000))
|
|
.run()
|
|
;
|
|
}
|
|
}
|
|
|
|
render (ctx) {
|
|
/*
|
|
* Gradient Fills
|
|
*/
|
|
ctx.fillStyle = this.skyGradient;
|
|
ctx.fillRect(0, 0, this.game.playfield.width, SKY_HEIGHT);
|
|
|
|
ctx.fillStyle = this.beachGradient;
|
|
ctx.fillRect(0, SKY_HEIGHT, this.game.playfield.width, this.game.playfield.height - SKY_HEIGHT);
|
|
|
|
this.drawSun(ctx);
|
|
|
|
this.waves.forEach((wave) => wave.render(ctx));
|
|
|
|
ctx.fillStyle = this.oceanGradient;
|
|
ctx.fillRect(0, SKY_HEIGHT, this.game.playfield.width, WATER_HEIGHT);
|
|
|
|
this.clouds.forEach((cloud) => cloud.render(ctx));
|
|
|
|
this.game.images['bg:rocky-island'].draw(ctx, 0, SKY_HEIGHT - 70);
|
|
this.boats.forEach((boat) => boat.render(ctx));
|
|
|
|
/*
|
|
* Image/sprite overlays
|
|
*/
|
|
for (const spriteKey in this.sprites) {
|
|
const sprite = this.sprites[spriteKey];
|
|
sprite.render(ctx);
|
|
}
|
|
|
|
if (this.butterfly) {
|
|
this.butterfly.render(ctx);
|
|
}
|
|
}
|
|
|
|
setEnvironmentMode (mode) {
|
|
const ctx = this.game.gameDisplayCtx;
|
|
switch (mode) {
|
|
case 'day':
|
|
this.tweens.environmentNightToDay.duration(2000).run();
|
|
|
|
this.oceanGradient = ctx.createLinearGradient(0, SKY_HEIGHT, 0, SKY_HEIGHT + WATER_HEIGHT);
|
|
this.oceanGradient.addColorStop(0.0, '#72b5aeff');
|
|
this.oceanGradient.addColorStop(0.75, '#72b5ae40');
|
|
this.oceanGradient.addColorStop(1.0, '#edeec800');
|
|
break;
|
|
}
|
|
}
|
|
|
|
drawSun (ctx) {
|
|
ctx.beginPath();
|
|
ctx.ellipse(
|
|
this.sun.position.x,
|
|
this.sun.position.y,
|
|
32,
|
|
32,
|
|
0,
|
|
0,
|
|
Math.PI * 2,
|
|
);
|
|
|
|
this.sun.gradient = ctx.createRadialGradient(
|
|
this.sun.position.x,
|
|
this.sun.position.y,
|
|
32,
|
|
this.sun.position.x + 16,
|
|
this.sun.position.y - 16,
|
|
4
|
|
);
|
|
this.sun.gradient.addColorStop(0.0, '#e0a579');
|
|
this.sun.gradient.addColorStop(1.0, '#eabf8a');
|
|
ctx.fillStyle = this.sun.gradient;
|
|
|
|
ctx.lineWidth = 3.0;
|
|
ctx.strokeStyle = '#593117';
|
|
|
|
ctx.fill();
|
|
ctx.stroke();
|
|
}
|
|
}
|