123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- const $ = (s) => document.querySelector(s);
-
- const ROOT = $('#root');
- const LIVES_LABEL = $('#lives');
- const SOUND_BUTTON = $('#sound');
- const CANVAS = $('#canvas');
- const CTX = CANVAS.getContext('2d');
-
-
- const X_BOUND = 0.05;
- const GAME_OVER_BOUND = 0.9;
- const MAX_RAINDROPS = 100;
-
- const clouds = new Set();
- const bullets = new Set();
- const raindrops = new Set();
- let shootingPad = new ShootingPad();
- let running = false;
- let direction = 1;
- let soundEnabled = localStorage.soundEnabled !== 'false';
-
- const initCloudField = () => {
- for (let y = 0; y < 6; y++) {
- for (let x = 0; x < 11; x++) {
- const cloud = new Cloud(X_BOUND + 0.06 * x, 0.04 + 0.06 * y, 0.03, 0.02);
- clouds.add(cloud);
- }
- }
- }
-
- const initRainEffect = () => {
- noise.seed(Math.random());
- for (let i = 0; i < MAX_RAINDROPS; i++) {
- const raindrop = new BackgroundRaindrop(
- randRange(-0.5, 1.5),
- randRange(-1, -0.1),
- randRange(0.01, 0.03),
- );
-
- raindrops.add(raindrop);
- }
- }
-
- const updateSoundButton = () => {
- SOUND_BUTTON.textContent = soundEnabled ? '🔊' : '🔈';
- SOUND_BUTTON.title = `Sound ${soundEnabled ? 'enabled' : 'disabled'}`;
- }
-
- const start = () => {
- $('.result')?.remove();
-
- shootingPad?.destroy();
- shootingPad = new ShootingPad();
-
- bullets.forEach(c => c.destroy());
- bullets.clear();
-
- clouds.forEach(c => c.destroy());
- clouds.clear();
- Cloud.reset();
- initCloudField();
-
- running = true;
- }
-
- const gameOver = (result) => {
- const resultLabel = document.createElement('div');
- resultLabel.className = 'result';
- resultLabel.textContent = result;
- ROOT.appendChild(resultLabel);
- running = false;
- }
-
- const loop = () => {
- document.title = `${fps()} FPS | CloudInvaders | OLC Codejam 2022`;
- CTX.clearRect(0, 0, CANVAS.width, CANVAS.height);
-
- raindrops.forEach(d => {
- d.update();
- d.draw();
- });
- if (running) {
- let directionUpdated = false;
- let isOver = false;
- Array.from(clouds).forEach(c => {
- c.update(direction);
- c.draw();
- if (c.x < X_BOUND || c.x > 1 - X_BOUND) {
- directionUpdated = true;
- }
- if (c.y >= GAME_OVER_BOUND) {
- isOver = true;
- }
- if (!c.alive) {
- clouds.delete(c);
- }
- });
-
- if (directionUpdated) {
- direction = -direction;
- }
-
- if (isOver) {
- gameOver('Game over');
- }
-
- Array.from(bullets).forEach(b => {
- b.update();
- b.draw();
-
- if (!b.alive) {
- bullets.delete(b);
- }
- });
-
- shootingPad.update();
- shootingPad.draw();
-
- if (clouds.size === 0) {
- gameOver('WIN');
- }
- }
- requestAnimationFrame(loop);
- };
-
- SOUND_BUTTON.addEventListener('click', () => {
- soundEnabled = !soundEnabled;
- localStorage.soundEnabled = soundEnabled;
- updateSoundButton();
- });
-
- document.addEventListener('keypress', () => {
- if (!running) {
- start();
- }
- });
-
- initRainEffect();
- updateSoundButton();
- loop();
- gameOver('🌩 Cloud Invaders 🌩');
|