diff --git a/README.md b/README.md index c0ea0bbc..cd5300c8 100644 --- a/README.md +++ b/README.md @@ -236,34 +236,36 @@ ________________________________________________________________________________ | 178 | [Platform Game Engine](./SinglePlayer%20-%20Games/Platform_Game_Engine) | | 179 | [Castle Escape Game](.SinglePlayer%20-%20Games/Castle_Escape_Game) | | 180 | [Shadow Poke Guessing Game](.SinglePlayer%20-%20Games/Shadow_Poke_Guessing_Game) | -| 181 | [Marvel Role Playing Game](.SinglePlayer%20-%20Games/Marvel_Role_Playing_Game) | +| 181 | [Marvel Role Playing Game](.SinglePlayer%20-%20Games/Marvel_Role_Playing_Game) | | 182 | [Animal Name Guessing Game](.SinglePlayer%20-%20Games/Animal_Name_Guessing_Game) | | 183 | [Basketball Game](.SinglePlayer%20-%20Games/Basketball_Game) | | 184 | [Ball Jumper Game](.SinglePlayer%20-%20Games/Ball_Jumper_Game) | | 185 | [Math Sprint Game](.SinglePlayer%20-%20Games/Math_Sprint_Game) | + main +| 186 | [Quick Type](.SinglePlayer%20-%20Games/QuickType) | +| 187 | [SIMON_GAME](.SinglePlayer%20-%20Games/SIMON_GAME) | + | 186 | [Quick Type](.SinglePlayer%20-%20Games/QuickType) | | 187 | [SIMON_GAME](.SinglePlayer%20-%20Games/SIMON_GAME) | + main | 188 | [Cubula_Game](.SinglePlayer%20-%20Games/Cubula_Game) | | 189 | [Ball_Shooting_Game](.SinglePlayer%20-%20Games/Ball_Shooting_Game) | | 190 | [Baseball_Game](.SinglePlayer%20-%20Games/Baseball_Game) | | 189 | [Hand_Cricket_Champ](./SinglePlayer%20-%20Games/Hand_Cricket_Champ) | | 190 | [Pop My Balloon]() | + main +| 191 | [Doraemon Run](.SinglePlayer%20-%20Games/DoraemonRun) | +| 192 | [Earth_Guardian](./SinglePlayer%20-%20Games/Earth_Guardian) | | 191 | [Doraemon Run](.SinglePlayer%20-%20Games/DoraemonRun) | | 192 | [Hand_Cricket_Champ](./SinglePlayer%20-%20Games/Hand_Cricket_Champ) | | 193 | [SnakeBites Game](./SinglePlayer%20-%20Games/SnakeBites) | - | 194 | [Ball_Shooting_Game](.SinglePlayer%20-%20Games/Ball_Shooting_Game) | | 195 | [Baseball_Game](.SinglePlayer%20-%20Games/Baseball_Game) | | 196 | [Flames_Game](../MultiPlayer%20-%20Games/Flames_Game) | - - - - - ________________________________________________________________________________________________________________________________________________________________ # How to make a PR in a Project đŸŸĸ diff --git a/SinglePlayer - Games/Earth_Guardian/README.md b/SinglePlayer - Games/Earth_Guardian/README.md new file mode 100644 index 00000000..f75ad531 --- /dev/null +++ b/SinglePlayer - Games/Earth_Guardian/README.md @@ -0,0 +1,44 @@ +# Earth Guardian + +# [Game Interface] + + +------------------- + +
+ +## **Description 📃** +-Earth Guardian is a remake of the classic Space shooter type of games, with 8-bit (pixel art) assets. This project used free assets (music and graphics) provided by [Jonathan So](https://jonathan-so.itch.io/),[KennyNL](https://kenney.nl/) and other sources, like Google images and [OpenGameArt](https://opengameart.org). This was a learning project. There will be some updates in the near future. Hope you like it, have fun! + + +## **functionalities 🎮** +1. This a classic space shooter game . +2. It has a timer going on , before the timer end you have to kill more more alien ships , it will be your final score +3. You can store your timer and health by collecting the time and health. + +
+ +## **How to play? 🕹ī¸** + +- Use arrow keys to move the ship ! +- Press spacebar to shoot ! +- Hold shift key to use booster! + +
+ +###### Bugs: +* Minor bug with multiple keys pressed movement (LEFT UP AND SHOOT); + +
+ +## **Screenshots 📸** + +
+ # [Game image] + + +
+ +---------- +#### Releases: +##### v1.0.0 - May 14 2024 diff --git a/SinglePlayer - Games/Earth_Guardian/assets/audio/Crimson Drive.mp3 b/SinglePlayer - Games/Earth_Guardian/assets/audio/Crimson Drive.mp3 new file mode 100644 index 00000000..144e9f5e Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/assets/audio/Crimson Drive.mp3 differ diff --git a/SinglePlayer - Games/Earth_Guardian/assets/audio/Fallen in Battle.mp3 b/SinglePlayer - Games/Earth_Guardian/assets/audio/Fallen in Battle.mp3 new file mode 100644 index 00000000..ea58e892 Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/assets/audio/Fallen in Battle.mp3 differ diff --git a/SinglePlayer - Games/Earth_Guardian/assets/audio/Mecha Collection.mp3 b/SinglePlayer - Games/Earth_Guardian/assets/audio/Mecha Collection.mp3 new file mode 100644 index 00000000..6287f2f4 Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/assets/audio/Mecha Collection.mp3 differ diff --git a/SinglePlayer - Games/Earth_Guardian/assets/audio/alarm.wav b/SinglePlayer - Games/Earth_Guardian/assets/audio/alarm.wav new file mode 100644 index 00000000..5aa34218 Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/assets/audio/alarm.wav differ diff --git a/SinglePlayer - Games/Earth_Guardian/assets/audio/explosion_enemy.wav b/SinglePlayer - Games/Earth_Guardian/assets/audio/explosion_enemy.wav new file mode 100644 index 00000000..6a8c9464 Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/assets/audio/explosion_enemy.wav differ diff --git a/SinglePlayer - Games/Earth_Guardian/assets/audio/explosion_enemy.wav.meta b/SinglePlayer - Games/Earth_Guardian/assets/audio/explosion_enemy.wav.meta new file mode 100644 index 00000000..dacd3ce9 --- /dev/null +++ b/SinglePlayer - Games/Earth_Guardian/assets/audio/explosion_enemy.wav.meta @@ -0,0 +1,20 @@ +fileFormatVersion: 2 +guid: 72e76810224064300b7d32e8322a5d12 +AudioImporter: + serializedVersion: 6 + defaultSettings: + loadType: 1 + sampleRateSetting: 0 + sampleRateOverride: 0 + compressionFormat: 0 + quality: .5 + conversionMode: 0 + platformSettingOverrides: {} + forceToMono: 0 + normalize: 1 + preloadAudioData: 1 + loadInBackground: 0 + 3D: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/SinglePlayer - Games/Earth_Guardian/assets/audio/explosion_player.wav b/SinglePlayer - Games/Earth_Guardian/assets/audio/explosion_player.wav new file mode 100644 index 00000000..16ac3611 Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/assets/audio/explosion_player.wav differ diff --git a/SinglePlayer - Games/Earth_Guardian/assets/audio/explosion_player.wav.meta b/SinglePlayer - Games/Earth_Guardian/assets/audio/explosion_player.wav.meta new file mode 100644 index 00000000..1f2d8c56 --- /dev/null +++ b/SinglePlayer - Games/Earth_Guardian/assets/audio/explosion_player.wav.meta @@ -0,0 +1,20 @@ +fileFormatVersion: 2 +guid: a019ae3af8e864616b85773c509f5285 +AudioImporter: + serializedVersion: 6 + defaultSettings: + loadType: 1 + sampleRateSetting: 0 + sampleRateOverride: 0 + compressionFormat: 0 + quality: .5 + conversionMode: 0 + platformSettingOverrides: {} + forceToMono: 0 + normalize: 1 + preloadAudioData: 1 + loadInBackground: 0 + 3D: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/SinglePlayer - Games/Earth_Guardian/assets/audio/go.ogg b/SinglePlayer - Games/Earth_Guardian/assets/audio/go.ogg new file mode 100644 index 00000000..89683948 Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/assets/audio/go.ogg differ diff --git a/SinglePlayer - Games/Earth_Guardian/assets/audio/laser1.ogg b/SinglePlayer - Games/Earth_Guardian/assets/audio/laser1.ogg new file mode 100644 index 00000000..56ad23de Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/assets/audio/laser1.ogg differ diff --git a/SinglePlayer - Games/Earth_Guardian/assets/audio/loading.wav b/SinglePlayer - Games/Earth_Guardian/assets/audio/loading.wav new file mode 100644 index 00000000..2387724f Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/assets/audio/loading.wav differ diff --git a/SinglePlayer - Games/Earth_Guardian/assets/audio/menu hover.wav b/SinglePlayer - Games/Earth_Guardian/assets/audio/menu hover.wav new file mode 100644 index 00000000..9485c5bf Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/assets/audio/menu hover.wav differ diff --git a/SinglePlayer - Games/Earth_Guardian/assets/audio/menu select.wav b/SinglePlayer - Games/Earth_Guardian/assets/audio/menu select.wav new file mode 100644 index 00000000..e1e74ec4 Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/assets/audio/menu select.wav differ diff --git a/SinglePlayer - Games/Earth_Guardian/assets/audio/music_background.wav b/SinglePlayer - Games/Earth_Guardian/assets/audio/music_background.wav new file mode 100644 index 00000000..0f66dd53 Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/assets/audio/music_background.wav differ diff --git a/SinglePlayer - Games/Earth_Guardian/assets/audio/music_background.wav.meta b/SinglePlayer - Games/Earth_Guardian/assets/audio/music_background.wav.meta new file mode 100644 index 00000000..55ab787d --- /dev/null +++ b/SinglePlayer - Games/Earth_Guardian/assets/audio/music_background.wav.meta @@ -0,0 +1,20 @@ +fileFormatVersion: 2 +guid: 7b04c59dd84f14039b601e1abbe7b884 +AudioImporter: + serializedVersion: 6 + defaultSettings: + loadType: 1 + sampleRateSetting: 0 + sampleRateOverride: 0 + compressionFormat: 1 + quality: .5 + conversionMode: 0 + platformSettingOverrides: {} + forceToMono: 0 + normalize: 1 + preloadAudioData: 1 + loadInBackground: 0 + 3D: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/SinglePlayer - Games/Earth_Guardian/assets/audio/powerUp11.ogg b/SinglePlayer - Games/Earth_Guardian/assets/audio/powerUp11.ogg new file mode 100644 index 00000000..88f53216 Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/assets/audio/powerUp11.ogg differ diff --git a/SinglePlayer - Games/Earth_Guardian/assets/audio/weapon_player.wav b/SinglePlayer - Games/Earth_Guardian/assets/audio/weapon_player.wav new file mode 100644 index 00000000..3e214c36 Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/assets/audio/weapon_player.wav differ diff --git a/SinglePlayer - Games/Earth_Guardian/assets/audio/weapon_player.wav.meta b/SinglePlayer - Games/Earth_Guardian/assets/audio/weapon_player.wav.meta new file mode 100644 index 00000000..67c887a3 --- /dev/null +++ b/SinglePlayer - Games/Earth_Guardian/assets/audio/weapon_player.wav.meta @@ -0,0 +1,20 @@ +fileFormatVersion: 2 +guid: bf75b984df8a84987bcf3a8bf6e2862d +AudioImporter: + serializedVersion: 6 + defaultSettings: + loadType: 1 + sampleRateSetting: 0 + sampleRateOverride: 0 + compressionFormat: 0 + quality: .5 + conversionMode: 0 + platformSettingOverrides: {} + forceToMono: 0 + normalize: 1 + preloadAudioData: 1 + loadInBackground: 0 + 3D: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/SinglePlayer - Games/Earth_Guardian/assets/images/3.png b/SinglePlayer - Games/Earth_Guardian/assets/images/3.png new file mode 100644 index 00000000..e233256a Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/assets/images/3.png differ diff --git a/SinglePlayer - Games/Earth_Guardian/assets/images/Earth Guardian.png b/SinglePlayer - Games/Earth_Guardian/assets/images/Earth Guardian.png new file mode 100644 index 00000000..4be2ecf7 Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/assets/images/Earth Guardian.png differ diff --git a/SinglePlayer - Games/Earth_Guardian/assets/images/Earth_Guardian.png b/SinglePlayer - Games/Earth_Guardian/assets/images/Earth_Guardian.png new file mode 100644 index 00000000..10ee7ec1 Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/assets/images/Earth_Guardian.png differ diff --git a/SinglePlayer - Games/Earth_Guardian/assets/images/background.png b/SinglePlayer - Games/Earth_Guardian/assets/images/background.png new file mode 100644 index 00000000..25712abf Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/assets/images/background.png differ diff --git a/SinglePlayer - Games/Earth_Guardian/assets/images/enemy.png b/SinglePlayer - Games/Earth_Guardian/assets/images/enemy.png new file mode 100644 index 00000000..02d4c0e7 Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/assets/images/enemy.png differ diff --git a/SinglePlayer - Games/Earth_Guardian/assets/images/enemyRocket.png b/SinglePlayer - Games/Earth_Guardian/assets/images/enemyRocket.png new file mode 100644 index 00000000..ccd932e5 Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/assets/images/enemyRocket.png differ diff --git a/SinglePlayer - Games/Earth_Guardian/assets/images/engineFire.jpg b/SinglePlayer - Games/Earth_Guardian/assets/images/engineFire.jpg new file mode 100644 index 00000000..b45a4f6d Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/assets/images/engineFire.jpg differ diff --git a/SinglePlayer - Games/Earth_Guardian/assets/images/engineFlameBooster.png b/SinglePlayer - Games/Earth_Guardian/assets/images/engineFlameBooster.png new file mode 100644 index 00000000..9beecf8f Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/assets/images/engineFlameBooster.png differ diff --git a/SinglePlayer - Games/Earth_Guardian/assets/images/engineFlameNormal.png b/SinglePlayer - Games/Earth_Guardian/assets/images/engineFlameNormal.png new file mode 100644 index 00000000..8137a8b3 Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/assets/images/engineFlameNormal.png differ diff --git a/SinglePlayer - Games/Earth_Guardian/assets/images/firstAid.png b/SinglePlayer - Games/Earth_Guardian/assets/images/firstAid.png new file mode 100644 index 00000000..0b484e94 Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/assets/images/firstAid.png differ diff --git a/SinglePlayer - Games/Earth_Guardian/assets/images/github.png b/SinglePlayer - Games/Earth_Guardian/assets/images/github.png new file mode 100644 index 00000000..9e50ad1e Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/assets/images/github.png differ diff --git a/SinglePlayer - Games/Earth_Guardian/assets/images/meteorFlyby.png b/SinglePlayer - Games/Earth_Guardian/assets/images/meteorFlyby.png new file mode 100644 index 00000000..6611a868 Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/assets/images/meteorFlyby.png differ diff --git a/SinglePlayer - Games/Earth_Guardian/assets/images/player.png b/SinglePlayer - Games/Earth_Guardian/assets/images/player.png new file mode 100644 index 00000000..62ab271b Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/assets/images/player.png differ diff --git a/SinglePlayer - Games/Earth_Guardian/assets/images/playerDown.png b/SinglePlayer - Games/Earth_Guardian/assets/images/playerDown.png new file mode 100644 index 00000000..0cd0320d Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/assets/images/playerDown.png differ diff --git a/SinglePlayer - Games/Earth_Guardian/assets/images/playerRocket.png b/SinglePlayer - Games/Earth_Guardian/assets/images/playerRocket.png new file mode 100644 index 00000000..3f75474e Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/assets/images/playerRocket.png differ diff --git a/SinglePlayer - Games/Earth_Guardian/assets/images/playerUp.png b/SinglePlayer - Games/Earth_Guardian/assets/images/playerUp.png new file mode 100644 index 00000000..4daaccf2 Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/assets/images/playerUp.png differ diff --git a/SinglePlayer - Games/Earth_Guardian/assets/images/screenshot.png b/SinglePlayer - Games/Earth_Guardian/assets/images/screenshot.png new file mode 100644 index 00000000..b6ba52eb Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/assets/images/screenshot.png differ diff --git a/SinglePlayer - Games/Earth_Guardian/assets/images/shieldImage.png b/SinglePlayer - Games/Earth_Guardian/assets/images/shieldImage.png new file mode 100644 index 00000000..f5c6ce60 Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/assets/images/shieldImage.png differ diff --git a/SinglePlayer - Games/Earth_Guardian/assets/images/soundOff.png b/SinglePlayer - Games/Earth_Guardian/assets/images/soundOff.png new file mode 100644 index 00000000..8bc2da16 Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/assets/images/soundOff.png differ diff --git a/SinglePlayer - Games/Earth_Guardian/assets/images/soundOn.png b/SinglePlayer - Games/Earth_Guardian/assets/images/soundOn.png new file mode 100644 index 00000000..d76a45f2 Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/assets/images/soundOn.png differ diff --git a/SinglePlayer - Games/Earth_Guardian/assets/images/timer.png b/SinglePlayer - Games/Earth_Guardian/assets/images/timer.png new file mode 100644 index 00000000..abf7a310 Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/assets/images/timer.png differ diff --git a/SinglePlayer - Games/Earth_Guardian/assets/images/tombstone.png b/SinglePlayer - Games/Earth_Guardian/assets/images/tombstone.png new file mode 100644 index 00000000..4f4dc3e2 Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/assets/images/tombstone.png differ diff --git a/SinglePlayer - Games/Earth_Guardian/index.html b/SinglePlayer - Games/Earth_Guardian/index.html new file mode 100644 index 00000000..74a2af91 --- /dev/null +++ b/SinglePlayer - Games/Earth_Guardian/index.html @@ -0,0 +1,222 @@ + + + + + + + + Earth Guardian + + + + + + + + + +
+

0%

+
+
+
+ +
+

COMMANDS:

+

Use arrow keys to move the ship !

+

Press spacebar to shoot !

+

Hold shift key to use booster!

+
+
+ + +
+ + + + +
+ +
+

100%

+
+
+ + +
+ +
+

100%

+
+
+ + +
+ + +
+ + +
+

OVERHEAT:

+
+
+
+
+
+
+
+
+
+
+
+
+ + + + +
+ Tombstone +

Thank you for your service.

+ + +
+

+ + +
+ + +
+

Total kills:

+

Time played multiplier:

+

Final score:

+

Current Highscore:

+
+ + +
+ + +
+

GAME PAUSED

+ + + +
+ + +
+

SETTINGS

+
+

VOLUME CONTROLS:

+ +
+ + +
+ +
+ + +
+
+ +
+

SHIP COMMANDS:

+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ MUTE: + +
+ + + + + +
+
+
+
+ + + + + diff --git a/SinglePlayer - Games/Earth_Guardian/package.json b/SinglePlayer - Games/Earth_Guardian/package.json new file mode 100644 index 00000000..100e136a --- /dev/null +++ b/SinglePlayer - Games/Earth_Guardian/package.json @@ -0,0 +1,25 @@ +{ + "name": "earth-guardian", + "version": "1.2.0", + "description": "Remake of old popular space-shooter type of games.", + "main": "mainGlavno.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [ + "remake", + "game", + "vanilla", + "js", + "space", + "shooter", + "8bit", + "classic" + ], + "author": "Pujan-sarkar", + "license": "ISC", + "bugs": { + "url": "https://github.com/Pujan-sarkar" + } + +} diff --git a/SinglePlayer - Games/Earth_Guardian/static/fonts/MaterialIcons-Regular.eot b/SinglePlayer - Games/Earth_Guardian/static/fonts/MaterialIcons-Regular.eot new file mode 100644 index 00000000..70508eba Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/static/fonts/MaterialIcons-Regular.eot differ diff --git a/SinglePlayer - Games/Earth_Guardian/static/fonts/MaterialIcons-Regular.ttf b/SinglePlayer - Games/Earth_Guardian/static/fonts/MaterialIcons-Regular.ttf new file mode 100644 index 00000000..7015564a Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/static/fonts/MaterialIcons-Regular.ttf differ diff --git a/SinglePlayer - Games/Earth_Guardian/static/fonts/MaterialIcons-Regular.woff b/SinglePlayer - Games/Earth_Guardian/static/fonts/MaterialIcons-Regular.woff new file mode 100644 index 00000000..b648a3ee Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/static/fonts/MaterialIcons-Regular.woff differ diff --git a/SinglePlayer - Games/Earth_Guardian/static/fonts/MaterialIcons-Regular.woff2 b/SinglePlayer - Games/Earth_Guardian/static/fonts/MaterialIcons-Regular.woff2 new file mode 100644 index 00000000..9fa21125 Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/static/fonts/MaterialIcons-Regular.woff2 differ diff --git a/SinglePlayer - Games/Earth_Guardian/static/fonts/PressStart2P.ttf b/SinglePlayer - Games/Earth_Guardian/static/fonts/PressStart2P.ttf new file mode 100644 index 00000000..98044e93 Binary files /dev/null and b/SinglePlayer - Games/Earth_Guardian/static/fonts/PressStart2P.ttf differ diff --git a/SinglePlayer - Games/Earth_Guardian/static/js/lib/assets.js b/SinglePlayer - Games/Earth_Guardian/static/js/lib/assets.js new file mode 100644 index 00000000..d22f8efc --- /dev/null +++ b/SinglePlayer - Games/Earth_Guardian/static/js/lib/assets.js @@ -0,0 +1,99 @@ +// Import modules +import {sfx} from "../main.js"; +import {endPath} from "./path.js"; + +// Graphical assets +export class Graphics{ + constructor() { + this.bg = new Image(); + this.ship = new Image(); + this.enemy = new Image(); + this.missile = new Image(); + this.explosion = new Image(); + this.timerImage = new Image(); + this.healthImage = new Image(); + this.shieldImage = new Image(); + this.enemyMissile = new Image(); + this.engineFlames = new Image(); + + this.bg.src = `${endPath}/assets/images/background.png`; + this.ship.src = `${endPath}/assets/images/player.png`; + this.enemy.src = `${endPath}/assets/images/enemy.png`; + this.missile.src = `${endPath}/assets/images/playerRocket.png`; + this.explosion.src = `${endPath}/assets/images/3.png`; + this.healthImage.src = `${endPath}/assets/images/firstAid.png`; + this.enemyMissile.src = `${endPath}/assets/images/enemyRocket.png`; + this.timerImage.src = `${endPath}/assets/images/timer.png`; + this.shieldImage.src = `${endPath}/assets/images/shieldImage.png`; + this.engineFlames.src = `${endPath}/assets/images/engineFlameNormal.png`; + } +} + +// Sound assets +export class Sfx { + constructor() { + this.music = new Audio(); + this.goVoice = new Audio(); + this.alarmSound = new Audio(); + this.enemyShooting = new Audio(); + this.playerShooting = new Audio(); + this.explosionSound = new Audio(); + this.restorationSound = new Audio(); + + this.playerShooting.src = `${endPath}/assets/audio/weapon_player.wav`; + this.explosionSound.src = `${endPath}/assets/audio/explosion_enemy.wav`; + this.enemyShooting.src = `${endPath}/assets/audio/laser1.ogg`; + this.music.src = `${endPath}/assets/audio/music_background.wav`; + this.restorationSound.src = `${endPath}/assets/audio/powerUp11.ogg`; + this.alarmSound.src = `${endPath}/assets/audio/alarm.wav`; + this.goVoice.src =`${endPath}/assets/audio/go.ogg`; + + this.sfxVolume = 0.3; + this.musicVolume = 0.4; + this.music.loop = true; + this.soundOff = false; + this.controllingVolume = false; + + this.playerShooting.volume = this.sfxVolume; + this.explosionSound.volume = this.sfxVolume; + this.enemyShooting.volume = this.sfxVolume; + this.music.volume = this.musicVolume; + this.restorationSound.volume = this.sfxVolume; + this.alarmSound.volume = this.sfxVolume; + this.goVoice.volume = 0.1; + + // Menu sounds + this.menuMove = new Audio(); + this.menuSelected = new Audio(); + this.menuMove.src = `${endPath}/assets/audio/menu hover.wav` + this.menuSelected.src = `${endPath}/assets/audio/menu select.wav`; + } + + // Toggle all music / sound on and off + toggleMusic() { + this.soundOff = !this.soundOff; + if(this.soundOff) { + this.sfxVolume = 0; + this.musicVolume = 0; + this.menuSelected.volume = 0; + this.menuMove.volume = 0; + } else { + this.playerShooting.volume = this.sfxVolume; + this.explosionSound.volume = this.sfxVolume; + this.enemyShooting.volume = this.sfxVolume; + this.music.volume = this.musicVolume; + this.restorationSound.volume = this.sfxVolume; + this.volume = this.sfxVolume; + this.menuSelected.volume = 1; + this.menuMove.volume = 1; + } + } + + // Play restoration sound effect when player picks up health, shield or timer. + restorationEffect() { + this.restorationSound.currentTime = 0; + this.restorationSound.play(); + } +} + +export const graphics = new Graphics(); diff --git a/SinglePlayer - Games/Earth_Guardian/static/js/lib/enemies.js b/SinglePlayer - Games/Earth_Guardian/static/js/lib/enemies.js new file mode 100644 index 00000000..3cf6d408 --- /dev/null +++ b/SinglePlayer - Games/Earth_Guardian/static/js/lib/enemies.js @@ -0,0 +1,41 @@ +// Import modules +import {game} from "./game.js"; +import {graphics, sfx} from "../main.js"; + +export class Enemies { + constructor() { + this.speed = 1; + this.spawnDistance = 1200; + this.enemiesArray = []; + this.ammo = []; + this.spawned = false; + this.shootingSpeed = 700; + this.enemiesShootingInterval; + } + + spawnEnemies() { + this.enemiesArray.push({ + x: game.cWidth, + y: Math.floor(Math.random() * ( (game.maxHeight - graphics.enemyShip.height) - game.minHeight) + game.minHeight) + }) + } + + shoot() { + if(this.spawned) { + let minShip = 0; + let maxShip = this.enemiesArray.length - 1; + let randomShip = Math.floor(Math.random() * (maxShip - minShip + 1)) + minShip; + + // Randomize + this.ammo.push({ + x: this.enemiesArray[randomShip].x - graphics.enemy.width, + y: this.enemiesArray[randomShip].y + (graphics.enemy.height / 2) + }) + + sfx.enemyShooting.currentTime = 0; + sfx.enemyShooting.play(); + } + } +} +export const enemies = new Enemies(); +enemies.enemiesShootingInterval = setInterval(enemies.shoot.bind(enemies), enemies.shootingSpeed); \ No newline at end of file diff --git a/SinglePlayer - Games/Earth_Guardian/static/js/lib/game.js b/SinglePlayer - Games/Earth_Guardian/static/js/lib/game.js new file mode 100644 index 00000000..34d95cfd --- /dev/null +++ b/SinglePlayer - Games/Earth_Guardian/static/js/lib/game.js @@ -0,0 +1,416 @@ +// Import modules +import {player} from "./player.js"; +import {enemies} from "./enemies.js"; +import {sfx, powerups, startGame} from "../main.js"; +import {endPath} from "./path.js"; + + +export class Game { + constructor() { + // Game elements + this.canvas = document.querySelector("#canvas"); + this.displayKills = document.querySelector("#killCount"); + this.currentExp = document.querySelector("#currentExp"); + this.requiredExpText = document.querySelector("#requiredExp"); + this.levelBar = document.querySelector(".level-bar_fill"); + this.notificationText = document.querySelector(".notification"); + this.timerDisplay = document.querySelector("#timerDisplay"); + this.gameOver = document.querySelector(".game--over"); + this.ctx = this.canvas.getContext("2d"); + this.cWidth = this.canvas.width; + this.cHeight = this.canvas.height; + this.minHeight = 0; + this.maxHeight = 500; + + // On start values + this.requiredExp = 80; + this.score = 0; + this.startingTime; + this.endTime; + this.pausedTime; + this.timePassed; + this.init; + this.preGame; + this.isStarted = false; + + // Time + this.time = 30; + this.secondsLeft; + this.countdown; + this.currentTime; // Used for pausing / continuing game + + // Scores + this.highscore; + }; + + // Update kills and increase experience when player kills an enemy + updateKillcount() { + player.killCount++; + this.displayKills.textContent = player.killCount; + + player.exp += 20; + this.currentExp.textContent = player.exp; + + // When required exp is met, level up + if(player.exp === this.requiredExp) { + player.exp = 0; + this.requiredExp = this.requiredExp * 2; + this.currentExp.textContent = player.exp; + this.requiredExpText.textContent = this.requiredExp + " XP"; + player.levelUp(); + } + let levelExp = (player.exp / this.requiredExp) * 100; + this.levelBar.style.width = `${levelExp}%`; + }; + + // Increase game's difficulty as time goes by + increaseDifficulty() { + // Get how much time has passed since the game has started + this.endTime = new Date(); + this.timePassed = Math.floor((this.endTime - this.startingTime) / 1000); + + if(this.timePassed === 30) { + // Clear the interval for enemies shooting + clearInterval(enemies.enemiesShootingInterval); + + // Increase enemies shooting speed + enemies.speed = 2; + enemies.shootingSpeed = 600; + + // After speed update, enable interval again + enemies.enemiesShootingInterval = setInterval(enemies.shoot.bind(enemies), enemies.shootingSpeed); + + this.displayNotification("They are speeding up!"); + } else if (this.timePassed === 60) { + // Clear the interval for enemies shooting + clearInterval(enemies.enemiesShootingInterval); + + // Increase enemies shooting speed + enemies.speed = 4; + enemies.shootingSpeed = 400; + + // After speed update, enable interval again + enemies.enemiesShootingInterval = setInterval(enemies.shoot.bind(enemies), enemies.shootingSpeed); + + this.displayNotification("They are speeding up again!!"); + } else if (this.timePassed === 90) { + // Clear the interval for enemies shooting + clearInterval(enemies.enemiesShootingInterval); + + // Increase enemies shooting speed + enemies.speed = 8; + enemies.shootingSpeed = 300; + + // After speed update, enable interval again + enemies.enemiesShootingInterval = setInterval(enemies.shoot.bind(enemies), enemies.shootingSpeed); + this.displayNotification("Oh my god, will we make it?!"); + } else if (this.timePassed === 120) { + // Clear the interval for enemies shooting + clearInterval(enemies.enemiesShootingInterval); + + // Increase enemies shooting speed + enemies.speed = 10; + enemies.shootingSpeed = 200; + + // After speed update, enable interval again + enemies.enemiesShootingInterval = setInterval(enemies.shoot.bind(enemies), enemies.shootingSpeed); + + this.displayNotification("They are way too fast!!!"); + } + }; + + // Display notifications + displayNotification(message) { + this.notificationText.classList.add("activeNotification"); + + this.notificationText.innerHTML = `warning

${message}

`; + + // Remove the notification active class after 4 seconds + setTimeout(() => { + this.notificationText.classList.remove("activeNotification"); + }, 3000); + } + + // Game's timer + timer(secondsLeft){ + clearInterval(this.countdown); + + const now = Date.now(); + const then = now + this.time * 1000; + this.displayTimeLeft(this.time); + + this.countdown = setInterval(() =>{ + this.secondsLeft = Math.round((then - Date.now()) / 1000); + + // Show a warning for few seconds left + if(this.secondsLeft === 10) { + this.timerDisplay.classList.add("timeLow"); + this.displayNotification("You don't have much time left!"); + } else if (this.secondsLeft < 0) { + // If the timer ran out, end the game + clearInterval(this.countdown); + clearInterval(game); + this.endgame(this.secondsLeft); + return; + } + this.currentTime = this.secondsLeft; + this.time = this.currentTime; + + this.displayTimeLeft(this.secondsLeft); + }, 1000) + }; + + // Display time left + displayTimeLeft(seconds) { + const minutes = Math.floor(seconds / 60); + const remainder = seconds % 60; + this.timerDisplay.textContent = `${minutes}:${remainder < 10 ? 0 : ""}${remainder}`; + }; + + // Add playtime when user picks up timer + addPlaytime() { + // First remove the class before re-adding it + document.querySelector(".time").classList.remove("timeShake"); + + // Random time awarded for picking up the time renewal + let minTime = 8; + let maxTime = 12; + minTime = Math.ceil(minTime); + maxTime = Math.floor(maxTime); + let spawnTime = Math.floor(Math.random() * (maxTime - minTime + 1)) + minTime; + + this.time = this.secondsLeft + spawnTime; + this.timer(this.time); + + // Display message and add shaking to the time + document.querySelector(".time").classList.add("timeShake"); + this.timerDisplay.classList.remove("timeLow"); + this.displayNotification("Added play time!"); + }; + + // New score + newScore(finalScore) { + const inputMenu = document.querySelector(".newHighscore-input"); + const scoreText = document.querySelector("#scoreText"); + const inputField = document.querySelector("#playerName-input"); + const saveBtn = document.querySelector("#savePlayer"); + inputMenu.style.display = "flex"; + + // Display different message according to the score + if(finalScore > this.highscore) { + scoreText.innerHTML = `

NEW HIGHSCORE !!!

`; + } else { + scoreText.innerHTML = `

NOT BAD

`; + } + + // Save player's name and score to local storage + saveBtn.addEventListener("click", () => { + const value = inputField.value; + const results = { + name: value, + score: finalScore + } + let highscoresArray = JSON.parse(localStorage.getItem("highscoresList")) || []; + highscoresArray.push(results); + localStorage.setItem("highscoresList", JSON.stringify(highscoresArray)); + + // Hide the menu + inputMenu.style.display = "none"; + }) + }; + + // Get saved highscore in local storage + savedHighscore() { + this.highscore = localStorage.getItem("highscore"); + }; + + // New Highscore + newHighscore() { + const emptyWarningText = document.querySelector(".emptyWarning-text"); + + // Display notification that a new highscore was set! + emptyWarningText.textContent = "NEW HIGHSCORE !!!"; + emptyWarningText.classList.add("emptyWarning-Highscore"); + + // Remove the notification + setTimeout(() => { + emptyWarningText.classList.remove("emptyWarning-Highscore"); + }, 2000); + }; + + // Clear intervals + clearGameIntervals () { + clearInterval(enemies.enemiesShootingInterval); // Enemies module + clearInterval(player.graduallyRestoreInterval); // Player module + clearInterval(this.countdown); + clearInterval(powerups.timerInterval); + clearInterval(powerups.healthInterval); + clearInterval(powerups.shieldInterval); + + clearInterval(this.countdown); + clearInterval(player.graduallyRestoreInterval); // Player module + clearInterval(enemies.enemiesShootingInterval); // Enemies module + clearInterval(powerups.timerInterval); + clearInterval(powerups.healthInterval); + clearInterval(powerups.shieldInterval); + + } + + // End the game + endgame(secondsLeft){ + // Disable the intervals + this.clearGameIntervals(); + + // End measuring time + this.endTime = new Date(); + + // Divide the difference to get the starting time + let timeDifference = (this.endTime - this.startingTime) / 1000; + let timePlayed = Math.floor(timeDifference); + + // Multiplie the ending score by the time played divided by 100, which will result in a multiplier in the form of, for example x0.5 - x3, based on time played + let multiplier = timePlayed / 100; + this.score = player.killCount * 100; + let finalScore = this.score + (this.score * multiplier); + + // Stop movements + this.isStarted = false; + + // Disable enemies + enemies.spawned = false; + + // Destroy all powerups + powerups.healthRenew.length = 0; + powerups.shieldRenew.length = 0; + powerups.timeRenew.length = 0; + + // Game Over / Game finished menu + this.gameOver.style.display = "block"; + + // If player was killed. + if(player.hp === 0){ + displayImage.src = `${endPath}/assets/images/tombstone.png`; + message.textContent = "At least you tried..."; + } + + // If the time is up + if(secondsLeft <= 0) { + message.textContent = "Time's up !"; + } + + // Play game-ending music (currently plays ontop of the game music ?_?) + sfx.music.src = `${endPath}/assets/audio/Fallen in Battle.mp3`; + sfx.music.volume = 0.2; + sfx.music.play(); + sfx.music.loop = false; + + // Score and Highscore + document.querySelector("#totalKills").textContent = player.killCount; + document.querySelector("#multiplier").textContent = "x" + multiplier; + document.querySelector("#finalScore").textContent = finalScore; + document.querySelector("#highscore").textContent = this.highscore; + + // Display the menu with an input to enter player's name + this.newScore(finalScore); + + // If the new final score is bigger than the current highscore, save it and display notification + if(finalScore > this.highscore) { + localStorage.setItem("highscore", finalScore); + document.querySelector("#highscore").textContent = localStorage.getItem("highscore"); + this.newHighscore(); + } + }; + + // Restart game + restartGame() { + // Clear the intervals + this.clearGameIntervals(); + clearInterval(this.init); + + // Reset game parameters + this.isStarted = false; + + // Reset timer + this.timerDisplay.classList.remove("timeLow"); // In case user died while time was low. + this.timerDisplay.textContent = "0:30"; + + // Reset the colored blocks + player.blocks.forEach(block => { + block.classList.remove("greenPhase") + block.classList.remove("yellowPhase") + block.classList.remove("redPhase") + }); + + // Destroy all enemies, healths, timers, shields and reset them to 0. + enemies.enemiesArray.splice(0, enemies.enemiesArray.length); + enemies.ammo.splice(0, enemies.ammo.length); + + // Delete all existing items in the arrays + powerups.healthRenew.length = 0; + powerups.shieldRenew.length = 0; + powerups.timeRenew.length = 0; + + player.ammo.splice(0, player.ammo.length); + player.map = {}; + + // Reset the kill count text. + player.killCount = 0; + this.displayKills.textContent = player.killCount; + + // Reset pregame countdown and hide game over menu + this.preGame = 3; + this.gameOver.style.display = "none"; + this.time = 30; + + // Reset player's (ship's) parameters + player.d = ""; + player.hp = 100; + player.shield = 100; + player.overheat = 0; + player.boost = 100 + player.x = 50; + player.y = 250; + player.speed = 5; + player.increasedSpeed = 5; + player.heat = -1; + player.dynamicRestoration = 400; + player.shieldDestroyed = false; + player.exp = 0; + player.level = 1; + player.currentLevel.textContent = player.level; + + // Reset level and experience + this.requiredExp = 80; + this.requiredExpText.textContent = this.requiredExp + " XP"; + this.currentExp.textContent = player.exp; + + let levelExp = (player.exp / this.requiredExp) * 100; + this.levelBar.style.width = `${levelExp}%`; + + // Restart current time which affets difficulty + this.startingTime = new Date(); + this.increaseDifficulty(); + + // Reset enemies data + enemies.spawned = false; + enemies.speed = 1; + enemies.shootingSpeed = 700; + + // Reset health and shield text display + player.healthText.textContent = player.hp + "%"; + player.shieldText.textContent = player.shield + "%"; + + // Clear input field at game over menu + const inputField = document.querySelector("#playerName-input"); + inputField.value = ""; + + // Set restoration and enemy shooting intervals again. + player.graduallyRestoreInterval = setInterval(player.graduallyRestore.bind(player), player.dynamicRestoration); + enemies.enemiesShootingInterval = setInterval(enemies.shoot.bind(enemies), enemies.shootingSpeed); + + // Run the game again + startGame(); + } +} +export const game = new Game(); +game.savedHighscore(); diff --git a/SinglePlayer - Games/Earth_Guardian/static/js/lib/menus.js b/SinglePlayer - Games/Earth_Guardian/static/js/lib/menus.js new file mode 100644 index 00000000..426562b4 --- /dev/null +++ b/SinglePlayer - Games/Earth_Guardian/static/js/lib/menus.js @@ -0,0 +1,193 @@ +// Import Modules +import {player} from "./player.js"; +import {game} from "./game.js"; +import {sfx} from "../main.js"; + +const menu = document.querySelector(".menu"); +const pauseMenu = document.querySelector(".pause--menu"); +const gameOver = document.querySelector(".game--over"); +const exitGameBtn = document.querySelectorAll(".exitGame"); +const highscoresListMenu = document.querySelector(".highscoresList-menu"); +const highscoreList = document.querySelector("#highscoreList"); +const orderedList = document.querySelector("#theList"); +const clearListBtn = document.querySelector("#clearList"); +const closeHighscores = document.querySelector("#closeHighscores") +const shipControls = document.querySelectorAll(`.settings-menu input[type="text"]`); +const displayCommand = document.querySelectorAll(".displayCommand"); +const mainMenuButtons = document.querySelectorAll(".main-menu_buttons"); +const soundControl = document.querySelectorAll(".soundControl"); + +// About menu +const aboutMenu = document.querySelector(".aboutMenu"); +let aboutShowed = false; +function displayAbout() { + if(!aboutShowed) { + aboutMenu.style.display = "block"; + aboutShowed = !aboutShowed; + } else { + aboutMenu.style.display = "none"; + aboutShowed = !aboutShowed; + } +} + +// Highscores menu +function displayHighscores() { + highscoresListMenu.style.display = "block"; + const getHighscores = JSON.parse(localStorage.getItem("highscoresList")); + const noHighscoresNote = document.querySelector("#noHighscores"); + + if(getHighscores.length === 0) { + noHighscoresNote.style.display = "block"; + } else { + noHighscoresNote.style.display = "none"; + } + + // Sort the highscores from top to bottom + getHighscores.sort((a,b) => (a.score > b.score) ? -1 : 1); + + // Create a new list element for each highscore. + getHighscores.forEach(highscore => { + const li = document.createElement("li"); + li.classList.add("highscoreList-items"); + li.innerHTML = `${highscore.name}${highscore.score}`; + orderedList.appendChild(li); + + if(orderedList.childNodes.length > 0) { + clearListBtn.style.display = "inline-block"; + } + }) +} + +// Clear highscores list +function clearHighscores() { + localStorage.removeItem("highscoresList"); + localStorage.removeItem("highscore"); + + // While there is a first child in the ordered list, remove the first child. + while(orderedList.firstChild) { + orderedList.removeChild(orderedList.firstChild); + } +} + +// Close the highscores menu +function closeHighscoresMenu() { + highscoresListMenu.style.display = "none"; + + // While there is a first child in the ordered list, remove the first child. + while(orderedList.firstChild) { + orderedList.removeChild(orderedList.firstChild); + } +} + +// Settings menu (in-game) +const volumeControls = document.querySelectorAll(`.settings-menu input[type="range"]`); +const displayChange = document.querySelectorAll(".displayChange"); + +function controlVolume() { + if(sfx.controllingVolume) { + displayChange.forEach(change => { + if(this.name === change.id) { + change.textContent = this.value + "%"; + } + + // If input name is SFX, edit sfx, otherwise edit music's volume. + if(this.name === "sfx") { + sfx.sfxVolume = this.value / 100; + sfx.playerShooting.volume = sfx.sfxVolume; + sfx.explosionSound.volume = sfx.sfxVolume; + sfx.enemyShooting.volume = sfx.sfxVolume; + sfx.restorationSound.volume = sfx.sfxVolume; + sfx.alarmSound.volume = sfx.sfxVolume;; + } else if(this.name === "bgMusic") { + sfx.musicVolume = this.value / 100; + sfx.music.volume = sfx.musicVolume; + } + }) + } +} + +// Change ship's controls +function changeControls(e) { + e = e || event; + const key = e.key; + const code = e.code; + + if(code === "Space") { + this.value = code; + } else if (code !== key) { + this.value = key; + } + + displayCommand.forEach(command => { + // Display the command text + if(this.name === command.id) { + command.textContent = this.value || key; + } + + // Change the player's commands + if(this.name === "left") { + player.left = e.keyCode; + } else if(this.name === "up") { + player.up = e.keyCode; + } else if(this.name === "right") { + player.right = e.keyCode; + } else if(this.name === "down") { + player.down = e.keyCode; + } else if(this.name === "shooting") { + player.shooting = e.keyCode; + } else if(this.name === "useBooster") { + player.useBooster = e.keyCode; + } + }) +} + +// Hover on menues +mainMenuButtons.forEach(button => button.addEventListener("mouseover", ()=>{ + sfx.menuMove.currentTime = 0; + sfx.menuMove.play(); +})) + +// Select menues +mainMenuButtons.forEach(button => button.addEventListener("click", ()=>{ + sfx.menuSelected.currentTime = 0; + sfx.menuSelected.play(); +})) + +// Toggle sfx / music on and off. +soundControl.forEach(control => control.addEventListener("click", ()=>{ + sfx.toggleMusic(); + if(sfx.soundOff) { + control.src = `../assets/images/soundOff.png`; + } else { + control.src = `../assets/images/soundOn.png`; + } +})); + +// Volume control event listeners +volumeControls.forEach(control => control.addEventListener("mousedown",() => { + sfx.controllingVolume = true +})); +volumeControls.forEach(control => control.addEventListener("mouseup",() => { + sfx.controllingVolume = false +})); +volumeControls.forEach(control => control.addEventListener("change", controlVolume)); +volumeControls.forEach(control => control.addEventListener("mousemove", controlVolume)); + +// Menus event listeners +clearListBtn.addEventListener("click", clearHighscores); +closeHighscores.addEventListener("click", closeHighscoresMenu); +highscoreList.addEventListener("click", displayHighscores); +document.getElementById("about").addEventListener("click", displayAbout); +document.getElementById("closeAbout").addEventListener("click", displayAbout); +document.querySelector("#settings").addEventListener("click", ()=>{ + document.querySelector(".settings-menu").style.display = "flex"; +}) +document.querySelector("#goBack").addEventListener("click", ()=>{ + document.querySelector(".settings-menu").style.display = "none"; +}) + +// Ship controls event listeners +shipControls.forEach(control => control.addEventListener("keyup", changeControls)); +shipControls.forEach(control => control.addEventListener("click", function(){ + this.value = "" +})); diff --git a/SinglePlayer - Games/Earth_Guardian/static/js/lib/path.js b/SinglePlayer - Games/Earth_Guardian/static/js/lib/path.js new file mode 100644 index 00000000..086eb147 --- /dev/null +++ b/SinglePlayer - Games/Earth_Guardian/static/js/lib/path.js @@ -0,0 +1,7 @@ +// Export path to files (to solve issues with GitHub pages hosting that occur sometimes) +const fullPath = window.location.pathname; +const splitPath = fullPath.split('/'); +if (splitPath[splitPath.length - 1] == 'index.html') { + splitPath.pop(); +} +export const endPath = splitPath.length > 2 ? splitPath.join('/') : ''; \ No newline at end of file diff --git a/SinglePlayer - Games/Earth_Guardian/static/js/lib/player.js b/SinglePlayer - Games/Earth_Guardian/static/js/lib/player.js new file mode 100644 index 00000000..1f01a1ff --- /dev/null +++ b/SinglePlayer - Games/Earth_Guardian/static/js/lib/player.js @@ -0,0 +1,371 @@ +import {game} from "./game.js"; +import {enemies} from "./enemies.js"; +import {graphics, sfx} from "../main.js"; + +const emptyWarningText = document.querySelector(".emptyWarning-text"); + +export class Player { + constructor() { + this.d = null; // Direction + this.x = 50; + this.y = 250; + this.speed = 5; + this.hp = 100; + this.shield = 100; + this.overheat = 0; + this.booster = 100; + this.missileSpeed = 15; + this.increasedSpeed = 5; // Speed increased by level up + this.heat = -1; + + this.ammo = []; + + this.speedBooster = false; + this.isOverheated = false; + this.isSpaceDown = false; + this.shieldDestroyed = false; + + + // Player related elements + this.blocks = document.querySelectorAll(".overheat-bar_block"); + this.currentLevel = document.querySelector("#currentLevel"); + this.shieldText = document.querySelector("#shieldText"); + this.healthText = document.querySelector("#healthText"); + + // Player ship interval + this.graduallyRestoreInterval; + this.dynamicRestoration = 400; + + // Player's level + this.level = 1; + this.exp = 0; + this.killCount = 0; + + // Ship's default commands + this.left = 37; + this.right = 39; + this.up = 38; + this.down = 40; + this.shooting = 32; + this.useBooster = 16; + this.map = {}; + }; + + // Level up + levelUp() { + this.level++; + this.currentLevel.textContent = this.level; + this.shieldDestroyed = false; + + // Increase the movement and missile speed on level up + this.increasedSpeed++; + this.speed = this.increasedSpeed; + this.missileSpeed += 1; + + // Dynamic restoration (cooling) of weapons + if(this.dynamicRestoration >= 150) { + // First clear the current interval for player restoration + clearInterval(player.graduallyRestoreInterval); + + // Change the interval's speed + this.dynamicRestoration -= 50; + + // After that re-add the interval with the new updated speed now + player.graduallyRestoreInterval = setInterval(player.graduallyRestore.bind(player), player.dynamicRestoration); + } + + // Restore health and shield to the ship + if(this.hp <= 60) { + this.hp += 40; + } + + if(this.shield <= 80) { + this.shield += 20; + } + this.healthText.textContent = this.hp + "%"; + this.shieldText.textContent = this.shield + "%"; + + // Small animation to notify the player he's leveled up + document.querySelector("#levelText").classList.add("levelTextActive"); + + setTimeout(() => { + document.querySelector("#levelText").classList.remove("levelTextActive"); + }, 1500); + }; + + // Player movement + playerMovement (e) { + e = e || event; + if(game.isStarted) { + this.map[e.keyCode] = e.type === "keydown"; + if(this.map[this.left] && this.map[this.up] || this.map[this.left] && this.map[this.up] && this.map[this.shooting]) { + this.d = "UP_LEFT"; + } else if (this.map[this.left] && this.map[this.down] || this.map[this.left] && this.map[this.down] && this.map[this.shooting]) { + this.d = "DOWN_LEFT"; + } else if (this.map[this.left] || this.map[this.left] && this.map[this.shooting]) { + this.d = "LEFT"; + } else if(this.map[this.right] && this.map[this.up] || this.map[this.right] && this.map[this.up] && this.map[this.shooting]) { + this.d = "UP_RIGHT"; + } else if(this.map[this.right] && this.map[this.down] || this.map[this.right] && this.map[this.down] && this.map[this.shooting]) { + this.d = "DOWN_RIGHT"; + } else if(this.map[this.right] || this.map[this.right] && this.map[this.shooting]) { + this.d = "RIGHT"; + } else if(this.map[this.down] || this.map[this.down] && this.map[this.shooting]) { + this.d = "DOWN"; + } else if(this.map[this.up] || this.map[this.up] && this.map[this.shooting]) { + this.d = "UP"; + } + + // Player uses speed booster + if(this.map[this.useBooster] && this.d === "LEFT" + || this.map[this.useBooster] && this.d === "RIGHT"){ + if(this.booster > 0 && this.booster <= 100) { + this.speedBooster = true; + this.speed += 10; + + // Empty the booster + this.booster -= 2; + } + + // Disable the booster if it reaches 0 + if(this.booster <= 0) { + this.speedBooster = false; + this.speed = this.speed; + emptyWarningText.textContent = "BOOSTER EMPTY !"; + emptyWarningText.classList.add("emptyWarning-textActive"); + + // Play alarm sound + sfx.alarmSound.currentTime = 0; + sfx.alarmSound.play(); + + // Restore the booster to max + this.restoreBooster(); + } + } + } + }; + + // Clear the ship commands when player doesn't holds a key down + clearShipCommands() { + this.speed = this.increasedSpeed; + this.isSpaceDown = false; + this.speedBooster = false; + this.d = ""; + } + + // Shoot + shoot(e) { + e = e || event; + if(game.isStarted && !this.isOverheated) { + if(this.isSpaceDown) return; // End the function if user is already holding space + + if(e.keyCode === this.shooting) { + this.isSpaceDown = true; + if(this.level < 3) { + new Ammo(0, 0); + } else if (this.level >= 3 && this.level <= 5) { + new Ammo(0, 0) + new Ammo(0, 20); + } else if (this.level >= 5 && this.level <= 7) { + new Ammo(0, 0); + new Ammo(0, 20); + new Ammo(0, -20); + } else if(this.level >= 8) { + new Ammo(0, 0); + new Ammo(0, 40); + new Ammo(0, -40); + new Ammo(15, 60); + new Ammo(15, -60); + new Ammo(30, 80); + new Ammo(30, -80); + } + sfx.playerShooting.currentTime = 0; + sfx.playerShooting.play(); + this.overheating(); + + // Prevent default action if user sets shooting to be on alt, ctrl etc. + e.preventDefault(); + } + } + }; + + // Overheating + overheating() { + this.overheat = this.overheat + 10; + + // If player.overheat meter reaches max(100), stop the ship from shooting, when it starts cooling off enable shooting. + if(this.overheat === 100) { + this.isOverheated = true; + emptyWarningText.textContent = "OVERHEATED !"; + emptyWarningText.classList.add("emptyWarning-textActive"); + + // Play alarm sound + sfx.alarmSound.currentTime = 0; + sfx.alarmSound.play(); + this.coolOut(); + } else if (this.overheat > 0 && this.overheat < 100) { + this.isOverheated = false; + this.displayOverheating(); + } + }; + + // Display overheating by painting the blocks + displayOverheating() { + if(this.heat >= -1 && this.heat <= 10) { + this.heat++; + } + + // Cycle trough the blocks and add according classes. + if(this.heat >= 0 && this.heat <= 3) { + this.blocks[this.heat].classList.add("greenPhase"); + } else if(this.heat >= 4 && this.heat <= 6) { + this.blocks[this.heat].classList.add("yellowPhase"); + } else if(this.heat >= 7 && this.heat <= 10) { + this.blocks[this.heat].classList.add("redPhase"); + } + }; + + // Gradually restore guns heat and booster + graduallyRestore() { + if(this.overheat >= 10 && this.overheat <= 90) { + this.overheat = this.overheat - 10; + + // Re-color the blocks (remove classes) + if(this.heat >= 0 && this.heat <= 3) { + this.blocks[this.heat].classList.remove("greenPhase"); + this.heat--; + } else if (this.heat >= 4 && this.heat <= 6) { + this.blocks[this.heat].classList.remove("yellowPhase"); + this.heat--; + } else if(this.heat >= 7 && this.heat <= 10) { + this.blocks[this.heat].classList.remove("redPhase"); + this.heat--; + } + } + + // Restore ship's booster + if(this.booster >= 0 && this.booster <= 98) { + this.booster = this.booster + 2; + } + }; + + // When guns overheat (reach 100), wait 2 seconds and restore to 0. + coolOut() { + setTimeout(() => { + this.overheat = 0; + this.isOverheated = false; + emptyWarningText.classList.remove("emptyWarning-textActive"); + this.blocks.forEach(block => { + block.classList.remove("greenPhase") + block.classList.remove("yellowPhase") + block.classList.remove("redPhase") + }); + this.heat = -1; + }, 2000); + }; + + // Restore the booster to max (100) after 5 seconds after it is emptied. + restoreBooster() { + setTimeout(() => { + this.booster = 100; + this.speedBooster = true; + emptyWarningText.classList.remove("emptyWarning-textActive"); + }, 5000); + }; + + // If the player is hit by the enemies + playerHit() { + // Play explosion sound + sfx.explosionSound.currentTime = 0; + sfx.explosionSound.play(); + + // Destroy the alien ammo upon hit + for(let i = 0; i < enemies.ammo.length; i++) { + let enemyRockets = enemies.ammo[i]; + let enemyRocketsIndex = enemies.ammo.indexOf(enemyRockets); + if(enemyRocketsIndex > -1) { + enemies.ammo.splice(enemyRocketsIndex, 1); + } + } + + // Decrease shield + this.decreaseShield(); + + // Decrease ship HP + this.decreaseShipHP(); + + if(this.hp === 0) { + game.endgame(); + } + }; + + // Restore the ship's HP + restoreShipHP() { + // If ship's already on max health dont do anything + if(this.hp === 100) { + this.hp = this.hp; + } else{ + // Restore ships HP and display a notification. + this.hp = this.hp + 20; + this.healthText.textContent = this.hp+"%"; + game.displayNotification("Restored health!"); + } + }; + + // Decrease the ship's HP on hit + decreaseShipHP() { + if(this.hp >= 20 && this.hp <= 100 && this.shieldDestroyed){ + this.hp = this.hp - 20; + this.healthText.textContent = this.hp+"%"; + } else if(this.hp === 0) { + game.endgame(); + } + }; + + // Restoring the ship's shield + restoreShield() { + if(this.shield === 100) { + this.shieldDestroyed = false; + this.shield = this.shield; + } else if(this.shield <= 80){ + // Enable shield on player's ship + this.shieldDestroyed = false; + + // Restore shield points and display a notification + this.shield = this.shield + 20; + this.shieldText.textContent = this.shield+"%"; + game.displayNotification("Restored shield!"); + } + }; + + // Decrease the ship's shield on hit + decreaseShield() { + // Decrease shield + if(this.shield >= 20 && this.shield <= 100) { + this.shield = this.shield - 20; + this.shieldText.textContent = this.shield+"%"; + } else if(this.shield < 20) { + // If shield is at 0 (at 20% shield gets deducted 20, so it goes straight to 0), mark it as destroyed + this.shieldDestroyed = true; + } + } +}; + +class Ammo { + constructor(ammoX, ammoY) { + player.ammo.push({ + x: player.x + graphics.ship.width + ammoX, + y: player.y + (graphics.ship.height / 2 ) + ammoY + }) + } +}; + +export const player = new Player(); + +// Set the restoration interval on load +player.graduallyRestoreInterval = setInterval(player.graduallyRestore.bind(player), player.dynamicRestoration); + +// Bind event listeners +onkeydown = onkeyup = player.playerMovement.bind(player); +document.addEventListener("keydown", player.shoot.bind(player)); +document.addEventListener("keyup", player.clearShipCommands.bind(player)); \ No newline at end of file diff --git a/SinglePlayer - Games/Earth_Guardian/static/js/lib/powerups.js b/SinglePlayer - Games/Earth_Guardian/static/js/lib/powerups.js new file mode 100644 index 00000000..df2abd32 --- /dev/null +++ b/SinglePlayer - Games/Earth_Guardian/static/js/lib/powerups.js @@ -0,0 +1,61 @@ +// Import modules +import {game} from "./game.js"; +import {graphics} from "./assets.js"; + +export class Powerups{ + constructor() { + this.healthRenew = []; + this.healthRenew[0] = { + x: game.cWidth, + y: Math.floor(Math.random() * ( (game.maxHeight - graphics.healthImage) - game.minHeight) + game.minHeight) + } + this.shieldRenew = []; + this.shieldRenew[0] = { + x: game.cWidth, + y: Math.floor(Math.random() * ( (game.maxHeight - graphics.shieldImage) - game.minHeight) + game.minHeight) + } + this.timeRenew = []; + this.timeRenew[0] = { + x: game.cWidth, + y: Math.floor(Math.random() * ( (game.maxHeight - graphics.timerImage) - game.minHeight) + game.minHeight) + } + + // Intervals + this.healthInterval = null; + this.shieldInterval = null; + this.timerInterval = null; + } + + // Spawn health restoration every 20 seconds + healthRenewFunction() { + this.healthInterval = setInterval(() => { + this.healthRenew.push({ + x: game.cWidth, + y: Math.floor(Math.random() * (game.maxHeight - graphics.healthImage.height) - game.minHeight) + game.minHeight + }) + console.log("Pushed health") + }, 20 * 1000); + } + + // Spawn shield restoration every 60 seconds + shieldRenewFunction() { + this.shieldInterval = setInterval(() => { + this.shieldRenew.push({ + x: game.cWidth, + y: Math.floor(Math.random() * (game.maxHeight - graphics.shieldImage.height) - game.minHeight) + game.minHeight + }) + console.log("Pushed shield") + }, 30 * 1000); + } + + // Spawn a timer to add more playing time every 10 to 15 seconds + timeRenewFunction() { + this.timerInterval = setInterval(() => { + this.timeRenew.push({ + x: game.cWidth, + y: Math.floor(Math.random() * (game.maxHeight - graphics.timerImage.height) - game.minHeight) + game.minHeight + }); + console.log("Pushed time") + }, 10 * 1000); + } +} \ No newline at end of file diff --git a/SinglePlayer - Games/Earth_Guardian/static/js/main.js b/SinglePlayer - Games/Earth_Guardian/static/js/main.js new file mode 100644 index 00000000..7518e52d --- /dev/null +++ b/SinglePlayer - Games/Earth_Guardian/static/js/main.js @@ -0,0 +1,470 @@ +// Import modules +import * as menus from "./lib/menus.js"; +import {enemies} from "./lib/enemies.js"; +import {player} from "./lib/player.js"; +import {game} from "./lib/game.js"; +import {Graphics, Sfx} from "./lib/assets.js"; +import {Powerups} from "./lib/powerups.js"; +import {endPath} from "./lib/path.js"; + +// Export single instances +export const graphics = new Graphics(); +export const powerups = new Powerups(); +export const sfx = new Sfx(); + + +// Elements +const menu = document.querySelector(".menu"); +const pauseMenu = document.querySelector(".pause--menu"); +const shieldContainer = document.querySelector(".shield-container"); +const healthContainer = document.querySelector(".health-container"); +const overheatContainer = document.querySelector(".overheat-container"); + +// Load game +function loadGame() { + // Play loading music + sfx.music.src = `${endPath}/assets/audio/loading.wav`; + sfx.music.play(); + + // Hide the main menu + const mainMenu = document.querySelector(".main-menu"); + mainMenu.style.display = "none"; + + // Display loading container + const loadingContainer = document.querySelector(".loading"); + loadingContainer.style.display = "flex"; + + // Loading bar + let loadingBarPercent = 0; + const loadingBar = document.querySelector(".loading-bar_fill"); + const loadingBarText = document.querySelector(".loading-text"); + + let load = setInterval(()=>{ + if(loadingBarPercent < 100) { + loadingBarPercent++; + } + loadingBarText.textContent = loadingBarPercent+"%"; + loadingBar.style.width = `${loadingBarPercent}%`; + + if(loadingBarPercent === 100) { + setTimeout(()=> loadingContainer.style.display = "none", 500); + startGame(); + clearInterval(load); + } + }, 50) +} + +// Start the game +export function startGame() { + setTimeout(() => { + // Display the MENU/SCORE panel + menu.style.display = "flex"; + + // Pre-game countdown + const preGameCountdown = document.querySelector(".countdown"); + game.preGame = 3; + preGameCountdown.textContent = "3"; + + // Display elements + setTimeout(() => { + menu.classList.add("menuActive"); + healthContainer.style.display = "block"; + shieldContainer.style.display = "block"; + overheatContainer.style.display = "flex"; + preGameCountdown.style.display = "block"; + }, 500); + + // Pre-game countdown - 3 seconds then GO ! + const preGameCountdownInterval = setInterval(()=>{ + game.preGame--; + preGameCountdown.textContent = game.preGame; + if(game.preGame === 0) { + // Clear any existing items in the health, shield, time renew arrays + powerups.healthRenew.length = 0; + powerups.shieldRenew.length = 0; + powerups.timeRenew.length = 0; + + // Initiate functions for health, shield and time renew as the game starts + powerups.healthRenewFunction(); + powerups.shieldRenewFunction(); + powerups.timeRenewFunction(); + console.log("Pushed items") + + sfx.goVoice.play(); + preGameCountdown.textContent = "GO !"; + setTimeout(()=> preGameCountdown.style.display = "none", 250) + + // Activate enemies and ship movement. + game.isStarted = true; + + // Enemies shoot every 2 seconds + enemies.spawned = true; + + // Start the timer countdown untill boss spawns + game.timer(game.time); + + // Start measuring played time + game.startingTime = new Date(); + + clearInterval(preGameCountdownInterval); + } + }, 1000) + + // Play background music + sfx.music.src = `${endPath}/assets/audio/Mecha Collection.mp3`; + sfx.music.volume = 0.2; + sfx.music.play(); + + // Run the game + game.init = setInterval(draw, 1000 / 60); + }, 500); +} + +// Game +function draw() { + // Display the canvas and paint the background + game.canvas.style.display = "block"; + game.ctx.drawImage(graphics.bg, 0,0); + + // Check if the game started + if(game.isStarted) { + for(let i = 0; i < enemies.enemiesArray.length; i++){ + // Draw a enemy + game.ctx.drawImage(graphics.enemy, enemies.enemiesArray[i].x, enemies.enemiesArray[i].y); + + enemies.enemiesArray[i].x -= enemies.speed; + + if(enemies.enemiesArray[i].x === enemies.spawnDistance) { + enemies.enemiesArray.push({ + x: game.cWidth, + y: Math.floor(Math.random() * ( (game.maxHeight-graphics.enemy.height) - game.minHeight) + game.minHeight) + }) + } + + // If spaceship and enemy colide + if(player.x + graphics.ship.width >= enemies.enemiesArray[i].x + && player.x <= enemies.enemiesArray[i].x + graphics.enemy.width + && player.y + graphics.ship.height >= enemies.enemiesArray[i].y + && player.y <= enemies.enemiesArray[i].y + graphics.enemy.height) { + // Draw explosion at those coords. + game.ctx.drawImage(graphics.explosion, enemies.enemiesArray[i].x - graphics.enemy.width, enemies.enemiesArray[i].y - graphics.enemy.height); + + // Delete the enemy from screen. + enemies.enemiesArray.splice(i, 1); + + // Deduct shield on hit + player.decreaseShield(); + + // Deduct HP on hit. + player.decreaseShipHP(); + + // Update the kill count, thus upating the score + game.updateKillcount(); + + sfx.explosionSound.currentTime = 0; + sfx.explosionSound.play(); + + // If spaceship HP reaches 0, end game. + if(player.hp === 0) { + clearInterval(game.init); + game.endgame(); + } + } else if(enemies.enemiesArray[i].x + graphics.enemy.width < 0) { + // Remove the alien space ship from the enemies array. + enemies.enemiesArray.splice(i, 1); + } + } + + // Create a new enemy if all enemies on screen are destroyed. + if(enemies.enemiesArray.length === 0) { + enemies.enemiesArray.push({ + x: game.cWidth, + y: Math.floor(Math.random() * ( (game.maxHeight-graphics.enemy.height) - game.minHeight) + game.minHeight) + }) + } + } + + /* ============================================================================= */ + + // PLAYER ROCKETS + if(game.isStarted){ + for(let j = 0; j < player.ammo.length; j++) { + // game.ctx.drawImage(graphics.missile, player.ammo[j].x, player.ammo[j].y); + + game.ctx.fillRect(player.ammo[j].x, player.ammo[j].y, 10, 10) + game.ctx.fillStyle = "#FFD600"; + + player.ammo[j].x += player.missileSpeed; + + const hitEnemy = enemies.enemiesArray.find(e => { + return player.ammo[j].x >= e.x + && player.ammo[j].x <= e.x + graphics.enemy.width + && player.ammo[j].y >= e.y + && player.ammo[j].y <= e.y + graphics.enemy.height + }) + + // Ammo colides enemy + if (hitEnemy) { + game.ctx.drawImage(graphics.explosion, hitEnemy.x - graphics.enemy.width, hitEnemy.y - graphics.enemy.height); + + // Remove the missiles + player.ammo.splice(j, 1); + + // Remove the enemy from screen + let enemiesArrayIndex = enemies.enemiesArray.indexOf(hitEnemy); + if(enemiesArrayIndex > -1) { + enemies.enemiesArray.splice(enemiesArrayIndex, 1) + } + sfx.explosionSound.play(); + sfx.explosionSound.currentTime = 0; + + // Update the kill count, thus updating the score + game.updateKillcount(); + } else if (player.ammo[j].x > game.cWidth) { // If player's ammo goes past canvas width + player.ammo.splice(j, 1); + } + } + } + + /* ============================================================================= */ + + // HEALTH RESTORATION + for(let i = 0; i < powerups.healthRenew.length; i++) { + powerups.healthRenew[i].x -= 2; + + if(powerups.healthRenew[i].x <= 0 - graphics.healthImage.width) { + powerups.healthRenew.splice(0, 1); + } + } + + for(let i = 0; i < powerups.healthRenew.length; i++){ + game.ctx.drawImage(graphics.healthImage, powerups.healthRenew[i].x, powerups.healthRenew[i].y); + + const pickedUpHealthRenew = player.x + graphics.ship.width >= powerups.healthRenew[i].x + && player.x <= powerups.healthRenew[i].x + graphics.healthImage.width + && player.y + graphics.ship.height >= powerups.healthRenew[i].y + && player.y <= powerups.healthRenew[i].y + graphics.healthImage.height; + + // If the ship touches the health, restore the ship's HP. + if(pickedUpHealthRenew) { + // Remove the HP restore. + powerups.healthRenew.splice(i, 1) + + // Restore ship's HP. + player.restoreShipHP(); + + // Play Sound effect + sfx.restorationEffect(); + } else if(powerups.healthRenew[i].x + graphics.healthImage.width < 0 ) { + // If HP restore goes past the canvas width, remove it. + powerups.healthRenew.splice(i, 1); + } + } + + /* ============================================================================= */ + + // SHIELD RESTORATION + for(let i = 0; i < powerups.shieldRenew.length; i++) { + powerups.shieldRenew[i].x -= 2; + + if(powerups.shieldRenew[i].x <= 0 - graphics.shieldImage.width) { + powerups.shieldRenew.splice(0, 1); + } + } + + for(let i = 0; i < powerups.shieldRenew.length; i++) { + game.ctx.drawImage(graphics.shieldImage, powerups.shieldRenew[i].x, powerups.shieldRenew[i].y); + + const pickedUpShieldRenew = player.x + graphics.ship.width >= powerups.shieldRenew[i].x + && player.x <= powerups.shieldRenew[i].x + graphics.shieldImage.width + && player.y + graphics.ship.height >= powerups.shieldRenew[i].y + && player.y <= powerups.shieldRenew[i].y + graphics.shieldImage.height + + // If the ship touches the shield, renew its shield. + if(pickedUpShieldRenew) { + // Remove the shield from screen + powerups.shieldRenew.splice(i, 1); + + // Restore 50 points to the player ship shield + player.restoreShield(); + + // Play Sound effect + sfx.restorationEffect(); + } else if(powerups.shieldRenew[i].x + graphics.shieldImage.width < 0) { + // If the shield item goes off canvas, remove it + powerups.shieldRenew.splice(i, 1); + } + } + + /* ============================================================================= */ + + // ADD PLAY TIME + for(let i = 0; i < powerups.timeRenew.length; i++){ + game.ctx.drawImage(graphics.timerImage, powerups.timeRenew[i].x, powerups.timeRenew[i].y) + // If the ship touches the sand timer, add more time + + const pickedUpTimeRenew = player.x + graphics.ship.width >= powerups.timeRenew[i].x + && player.x <= powerups.timeRenew[i].x + graphics.timerImage.width + && player.y + graphics.ship.height >= powerups.timeRenew[i].y + && player.y <= powerups.timeRenew[i].y + graphics.timerImage.height + + if(pickedUpTimeRenew) { + // Remove the timer from the array + powerups.timeRenew.splice(i, 1); + + // Add time + game.addPlaytime(); + + // Play Sound effect + sfx.restorationEffect(); + } else if(powerups.timeRenew[i].x < 0) { + // If clock goes past canvas + powerups.timeRenew.splice(i, 1); + } + } + + // Start moving the timer image when theres is one + for(let i = 0; i < powerups.timeRenew.length; i++) { + powerups.timeRenew[i].x -= 2; + + // If the timer goes behind canvas screen, remove it from the array + if(powerups.timeRenew[i].x <= 0 - graphics.timerImage.width) { + powerups.timeRenew.splice(0, 1); + } + } + /* ============================================================================= */ + + // Move the ship + if(player.d === "LEFT") { + player.x -= player.speed; + } + if(player.d === "RIGHT"){ + player.x += player.speed; + } + if(player.d === "UP") { + player.y -= player.speed; + } + if(player.d === "DOWN") { + player.y += player.speed; + } + + // DIAGONAL MOVEMENT + if(player.d === "UP_LEFT") { + player.x -= player.speed; + player.y -= player.speed; + } + if(player.d === "DOWN_LEFT") { + player.x -= player.speed; + player.y += player.speed; + } + if(player.d === "UP_RIGHT") { + player.x += player.speed; + player.y -= player.speed; + } + if(player.d === "DOWN_RIGHT") { + player.x += player.speed; + player.y += player.speed; + } + + // ALIEN (ENEMY) ROCKETS + if(game.isStarted && enemies.spawned){ + for(let i = 0; i < enemies.ammo.length;i++) { + game.ctx.drawImage(graphics.enemyMissile, enemies.ammo[i].x, enemies.ammo[i].y); + enemies.ammo[i].x -= 15; + + const hitEnemyAmmo = enemies.ammo[i].x >= player.x + && enemies.ammo[i].x <= player.x + graphics.ship.width + && enemies.ammo[i].y >= player.y + && enemies.ammo[i].y <= player.y + graphics.ship.height + && enemies.spawned; + + if(hitEnemyAmmo) { + // Draw explosion at the spot + game.ctx.drawImage(graphics.explosion, player.x, player.y); + + // Run function when player's ship is hit. + player.playerHit(); + } else if(enemies.ammo[i].x < 0) { // If the alien rocket goes behind player's ship + enemies.ammo.splice(i, 1); + } + } + } + + // If spaceship hits the boundry, remove the direction or teleport him top-bottom / bottom-top + if(player.x <= 0) { + player.x += player.speed; + } else if (player.x >= 1300 - graphics.ship.width) { + player.x -= player.speed; + } else if (player.y <= -40) { + player.y = 520 - player.speed; + } else if (player.y >= 520) { + player.y = -30 + player.speed; + } + + // Draw the ship + game.ctx.drawImage(graphics.ship, player.x, player.y); + + // Check how much time has passed and increase difficulty accordingly. + game.increaseDifficulty(); +} + +// Pause game +function pauseGame(){ + // Display the menu + pauseMenu.style.display = "flex"; + + // Clear the intervals + clearInterval(game.init); + clearInterval(enemies.enemiesShootingInterval); + clearInterval(player.graduallyRestoreInterval); + clearInterval(game.countdown); + + // Stop enemies and ship from moving + game.isStarted = false; + + // Enemies shoot every 2 seconds + enemies.spawned = false; + + // Divide the difference to get milliseconds. + game.pausedTime = (new Date() - game.startingTime) / 1000; + Math.floor(game.pausedTime); +} + +// Continue game +function continueGame(){ + // Hide the menu + pauseMenu.style.display = "none"; + + // Run the interval + game.init = setInterval(draw, 1000 / 60); + enemies.enemiesShootingInterval = setInterval(enemies.shoot.bind(enemies), enemies.shootingSpeed); + player.graduallyRestoreInterval = setInterval(player.graduallyRestore.bind(player), player.dynamicRestoration); + game.timer(game.currentTime); + + // Enable enemies and ship movement + game.isStarted = true; + + // Enemies shoot every 2 seconds + enemies.spawned = true; + + // Continue measuring time after game was paused + game.pausedTime *= 1000; +} + +// Exit game +const exitGame = document.querySelectorAll(".exitGame"); +exitGame.forEach(exit => exit.addEventListener("click", ()=> location.reload())); + +// Event listeners +document.querySelector("#startGame").addEventListener("click", loadGame); +document.querySelector("#pauseGame").addEventListener("click", pauseGame); +document.querySelector("#continueGame").addEventListener("click", continueGame); +document.querySelector("#restartGame").addEventListener("click", game.restartGame.bind(game)); + +// Pause game on ESCAPE and if clicked outside of canvas +window.addEventListener("keydown", e => { + if(e.keyCode === 27 && game.isStarted) pauseGame(); +}) +window.addEventListener("click", e => { + if(e.target.id !== "canvas" && e.target.id !== "continueGame" && game.isStarted) pauseGame(); +}) \ No newline at end of file diff --git a/SinglePlayer - Games/Earth_Guardian/static/styles/animations.css b/SinglePlayer - Games/Earth_Guardian/static/styles/animations.css new file mode 100644 index 00000000..923428c1 --- /dev/null +++ b/SinglePlayer - Games/Earth_Guardian/static/styles/animations.css @@ -0,0 +1,105 @@ +@keyframes buttonsAnimation{ + 0% { transform: translateY(0); } + 100% { transform: translateY(-5px); } +} +@keyframes overheatAnimation{ + 0%{ + color: #f5f5f5; + text-shadow: 4px 4px #860905; + transform: translate(-50%, -50%) scale(1); + } + 50%{ + color: #b30d07; + text-shadow: 4px 4px #f5f5f5; + transform: translate(-50%, -50%) scale(1.1); + } + 100%{ + color: #f5f5f5; + text-shadow: 4px 4px #860905; + transform: translate(-50%, -50%) scale(1); + } +} + +@keyframes highscoreAnimation{ + 0%{ + transform: scale(1); + } + 20%{ + transform: scale(1.1); + } + 40%{ + transform: scale(1); + } + 60%{ + transform: scale(1.1); + } + 80%{ + transform: scale(1); + } + 100%{ + transform: scale(1); + } +} + +@keyframes pauseTitle{ + 0%{ + color: #f5f5f5; + } + 50%{ + color: #b30d07; + } + 100%{ + color: #f5f5f5; + } +} +@keyframes shake{ + 10%, 90% { + transform: translate3d(-1px, 0, 0); + } + + 20%, 80% { + transform: translate3d(2px, 0, 0); + } + + 30%, 50%, 70% { + transform: translate3d(-4px, 0, 0); + } + + 40%, 60% { + transform: translate3d(4px, 0, 0); + } +} +@keyframes notification{ + 0%{ + transform: translateY(100px) + } + 50%{ + transform: translateY(30px) + } + 100%{ + transform: translateY(100px); + } +} + +@keyframes notifyLevelUp{ + 0%{ + color: #f5f5f5; + transform: scale(1) + } + 25%{ + color: #FFD600; + transform: scale(1.05) + } + 50%{ + color: #f5f5f5; + transform: scale(0.95); + } + 75%{ + color: #FFD600; + transform: scale(1.05); + } + 100%{ + color: #f5f5f5; + transform: scale(1); + } +} \ No newline at end of file diff --git a/SinglePlayer - Games/Earth_Guardian/static/styles/fonts.css b/SinglePlayer - Games/Earth_Guardian/static/styles/fonts.css new file mode 100644 index 00000000..39228d7d --- /dev/null +++ b/SinglePlayer - Games/Earth_Guardian/static/styles/fonts.css @@ -0,0 +1,42 @@ +@font-face { + font-family: 'Material Icons'; + font-style: normal; + font-weight: 400; + src: url("../fonts/MaterialIcons-Regular.eot"); /* For IE6-8 */ + src: local('Material Icons'), + local('MaterialIcons-Regular'), + url("../fonts/MaterialIcons-Regular.woff2") format('woff2'), + url("../fonts/MaterialIcons-Regular.woff") format('woff'), + url("../fonts/MaterialIcons-Regular.ttf") format('truetype'); +} +@font-face { + font-family: "Press Start 2P"; + src: url("../fonts/PressStart2P.ttf"); +} + + +/* MATERIAL DESIGN ICONS CSS */ +.material-icons { + font-family: 'Material Icons'; + font-weight: normal; + font-style: normal; + font-size: 24px; /* Preferred icon size */ + display: inline-block; + line-height: 1; + text-transform: none; + letter-spacing: normal; + word-wrap: normal; + white-space: nowrap; + direction: ltr; + + /* Support for all WebKit browsers. */ + -webkit-font-smoothing: antialiased; + /* Support for Safari and Chrome. */ + text-rendering: optimizeLegibility; + + /* Support for Firefox. */ + -moz-osx-font-smoothing: grayscale; + + /* Support for IE. */ + font-feature-settings: 'liga'; +} \ No newline at end of file diff --git a/SinglePlayer - Games/Earth_Guardian/static/styles/main.css b/SinglePlayer - Games/Earth_Guardian/static/styles/main.css new file mode 100644 index 00000000..f645bf97 --- /dev/null +++ b/SinglePlayer - Games/Earth_Guardian/static/styles/main.css @@ -0,0 +1,990 @@ +body { + background-color: #000; + overflow: hidden; + color: #f5f5f5; +} + +body .mainMenu-fade { + opacity: 0; +} + +body .main-menu_buttons:hover { + -webkit-animation: buttonsAnimation 0.5s ease forwards infinite; + animation: buttonsAnimation 0.5s ease forwards infinite; +} + +body button { + outline: none; +} + +.main-menu { + width: 100%; + height: 100vh; + position: relative; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-transition: 2.5s ease; + transition: 2.5s ease; + z-index: 3; + opacity: 1; + overflow: hidden; +} + +.main-menu .title { + text-align: center; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} + +.main-menu .title * { + margin: 15px 0; +} + +.main-menu .title h1 { + text-align: center; + font-family: "Press Start 2P"; + font-size: 50px; + color: #f5f5f5; + letter-spacing: 1px; + margin: 0 auto; + margin-bottom: 40px; +} + +@media (min-width: 1920px) { + .main-menu .title h1 { + font-size: 70px; + } +} + +.main-menu .title .mainButtons { + font-size: 14px; + font-family: "Press Start 2P"; + border: none; + background: none; + color: #f5f5f5; + letter-spacing: 1px; + cursor: pointer; + z-index: 3; + outline: none; + -webkit-transition: 0.3s ease; + transition: 0.3s ease; +} + +@media (min-width: 1920px) { + .main-menu .title .mainButtons { + font-size: 18px; + } +} + +.main-menu .title .mainButtons:hover { + color: gold; +} + +.main-menu .title #copyright { + margin-top: 80px; + font-family: "Press Start 2P"; + font-size: 8px; + color: #f5f5f5; + justify-self: flex-end; +} + +@media (min-width: 1920px) { + .main-menu .title #copyright { + font-size: 14px; + } +} + +.main-menu .title .soundControl { + cursor: pointer; +} + +.aboutMenu { + display: none; + padding: 15px; + width: 450px; + height: auto; + position: absolute; + top: 50%; + left: 50%; + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); + color: #f5f5f5; + background-color: #000016; + z-index: 3; + border: 1px solid #dddddd30; + text-align: center; + font-family: "Press Start 2P"; + font-size: 12px; + letter-spacing: 2px; + line-height: 15px; +} + +@media (min-width: 1920px) { + .aboutMenu { + width: 600px; + line-height: 20px; + } +} + +.aboutMenu h3 { + color: gold; + font-size: 20px; +} + +.aboutMenu p { + padding: 25px; +} + +@media (min-width: 1920px) { + .aboutMenu p { + font-size: 18px; + } +} + +.aboutMenu a { + color: gold; + text-decoration: none; +} + +.highscoresList-menu { + display: none; + width: 400px; + height: auto; + padding: 20px; + border: 1px solid #f5f5f535; + font-family: "Press Start 2P"; + color: #f5f5f5; + background-color: #000016; + position: absolute; + top: 50%; + left: 50%; + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); + z-index: 3; +} + +.highscoresList-menu h3 { + font-size: 20px; + letter-spacing: 2px; + color: gold; + margin-bottom: 20px; +} + +.highscoresList-menu #theName { + color: gold; +} + +.highscoresList-menu p { + font-size: 12px; + margin: 10px 0; +} + +.highscoresList-menu .highscoreList-items { + width: 100%; + padding: 0 5px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + font-size: 12px; + list-style-type: none; +} + +.highscoresList-menu .highscoreList-items * { + margin: 3px 0; +} + +.highscoresList-menu #clearList { + display: none; +} + +.highscoresList-menu #clearList:hover { + color: #bd0e08; +} + +.loading { + position: absolute; + top: 50%; + left: 50%; + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); + display: none; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + z-index: 3; + font-family: "Press Start 2P"; +} + +.loading .loading-text { + font-size: 12px; + color: #f5f5f5; + margin-bottom: 10px; +} + +@media (min-width: 1920px) { + .loading .loading-text { + font-size: 18px; + } +} + +.loading .loading-bar { + width: 200px; + height: 20px; + border: 1px solid grey; +} + +.loading .loading-bar .loading-bar_fill { + width: 0%; + height: 100%; + background-color: #f5f5f5; +} + +.loading .info { + margin: 30px 0px; +} + +.loading .info h2 { + margin: 10px 0; + font-size: 16px; + text-align: center; + color: gold; + letter-spacing: 2px; +} + +@media (min-width: 1920px) { + .loading .info h2 { + font-size: 22px; + letter-spacing: 3px; + } +} + +.loading .info p { + color: #f5f5f5; + font-size: 10px; + margin: 5px 0; +} + +@media (min-width: 1920px) { + .loading .info p { + font-size: 18px; + } +} + +.container { + width: 1280px; + height: 500px; + position: relative; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: end; + -ms-flex-pack: end; + justify-content: flex-end; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + position: absolute; + top: 50%; + left: 50%; + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); + overflow: hidden; +} + +.container canvas { + display: none; + border: 2px solid #dddddd10; + position: absolute; + left: 50%; + top: 50%; + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); +} + +.container .containerText { + width: 60px; + height: 12px; + padding: 5px; + border: 2px solid #860905; + border-radius: 25px; + background-color: PeachPuff; + color: #111; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: end; + -ms-flex-pack: end; + justify-content: flex-end; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + position: absolute; + bottom: 7px; + left: 15px; + z-index: -1; + font-size: 12px; + font-family: "Press Start 2P"; +} + +.container .health-container { + display: none; + position: absolute; + bottom: 5px; + left: 5px; + z-index: 3; +} + +.container .health-container img { + z-index: 2; +} + +.container .shield-container { + display: none; + position: absolute; + bottom: 5px; + left: 90px; + z-index: 3; +} + +.container .shield-container img { + z-index: 2; +} + +.container .countdown { + display: none; + font-family: "Press Start 2P"; + font-size: 30px; + color: #f5f5f5; + text-shadow: 3px 3px #a82121; + z-index: 3; + position: absolute; + top: 50%; + left: 50%; + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); +} + +.container .emptyWarning-text { + display: none; + font-family: "Press Start 2P"; + font-size: 22px; + letter-spacing: 3px; + color: #f5f5f5; + text-shadow: 4px 4px #860905; + position: absolute; + top: 50%; + left: 50%; + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); + z-index: 3; +} + +.container .emptyWarning-textActive { + display: block; + -webkit-animation: overheatAnimation 0.6s ease forwards infinite; + animation: overheatAnimation 0.6s ease forwards infinite; +} + +.container .emptyWarning-highscore { + display: block; + -webkit-animation: highscoreAnimation 1.25s ease forwards infinite; + animation: highscoreAnimation 1.25s ease forwards infinite; +} + +.container .notificationsContainer { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + position: absolute; + left: 50%; + bottom: 5px; + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); +} + +.container .notificationsContainer .notification { + padding: 5px; + width: 300px; + height: 40px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-transform: translateY(100px); + transform: translateY(100px); + font-size: 12px; + font-family: "Press Start 2P"; +} + +.container .notificationsContainer .notification i { + color: #e1302a; +} + +.container .notificationsContainer .notification p { + margin-left: 5px; + color: #f5f5f5; +} + +.container .notificationsContainer .notification .health { + color: #f5f5f5; +} + +.container .notificationsContainer .notification .shield { + color: #1aeb71; +} + +.container .notificationsContainer .notification .timer { + color: gold; +} + +.container .notificationsContainer .activeNotification { + -webkit-animation: notification 3s ease forwards; + animation: notification 3s ease forwards; +} + +.menu { + display: none; + width: 1250px; + opacity: 0; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + position: absolute; + top: 20px; + left: 50%; + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); + z-index: 3; + -webkit-transition: 0.75s ease; + transition: 0.75s ease; + color: #f5f5f5; + font-family: "Press Start 2P"; +} + +.menu #pauseGame { + cursor: pointer; +} + +.menu .time { + width: 150px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} + +.menu .time * { + margin: 0 3px; +} + +.menu .time i { + font-size: 30px; +} + +.menu .time #timerDisplay { + font-size: 17px; + letter-spacing: 2px; + color: gold; + font-family: "Press Start 2P"; +} + +.menu .time #timerDisplay.timeLow { + color: #b30d07; + font-size: 22px; +} + +.menu .timeShake { + -webkit-animation: shake 0.82s cubic-bezier(0.36, 0.07, 0.19, 0.97) both; + animation: shake 0.82s cubic-bezier(0.36, 0.07, 0.19, 0.97) both; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-perspective: 1000px; + perspective: 1000px; +} + +.menu .level-container { + width: 350px; + padding: 3px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + font-size: 14px; +} + +.menu .level-container .levelTextActive { + -webkit-animation: notifyLevelUp 0.5s ease forwards infinite; + animation: notifyLevelUp 0.5s ease forwards infinite; +} + +.menu .level-container .level-bar { + width: 200px; + height: 25px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + border: 2px solid #f5f5f520; + border-radius: 3px; + position: relative; + overflow: hidden; +} + +.menu .level-container .level-bar p { + color: #f5f5f5; + z-index: 9999; +} + +.menu .level-container .level-bar .level-bar_fill { + position: absolute; + top: 0; + left: 0; + width: 0%; + height: 100%; + -webkit-transition: 0.3s ease; + transition: 0.3s ease; + border-top-left-radius: 3px; + border-bottom-left-radius: 3px; + background-color: #b30d07; +} + +.menuActive { + opacity: 1; +} + +.overheat-container { + display: none; + padding: 5px; + position: absolute; + left: 16%; + bottom: 3px; + -webkit-transform: translate(-16%); + transform: translate(-16%); + background-color: rgba(0, 0, 0, 0.95); + z-index: 3; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-transition: 0.5s ease; + transition: 0.5s ease; +} + +.overheat-container p { + text-align: center; + font-family: "Press Start 2P"; + font-size: 12px; + letter-spacing: 2px; + color: goldenrod; +} + +.overheat-container .overheat-bar { + width: 140px; + height: 25px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} + +.overheat-container .overheat-bar * { + margin: 0px 2px; +} + +.overheat-container .overheat-bar .overheat-bar_block:nth-child(1) { + margin-left: -5px; +} + +.overheat-container .overheat-bar .overheat-bar_block { + width: 10px; + height: 20px; + background-color: #fff; +} + +.overheat-container .overheat-bar .greenPhase { + width: 10px; + height: 20px; + background-color: #2ECC40; +} + +.overheat-container .overheat-bar .yellowPhase { + width: 10px; + height: 20px; + background-color: #FFDC00; +} + +.overheat-container .overheat-bar .redPhase { + width: 10px; + height: 20px; + background-color: #b30d07; +} + +.game--over { + display: none; + width: 420px; + height: auto; + padding: 20px; + background-color: #000016; + text-align: center; + color: #f5f5f5; + font-family: "Press Start 2P"; + font-size: 12px; + border: 1px solid #f5f5f535; + position: absolute; + top: 50%; + left: 50%; + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); + z-index: 3; +} + +.game--over #message { + margin: 10px 0; + font-family: "Press Start 2P"; + font-size: 12px; +} + +.game--over .newHighscore-input { + width: 340px; + height: auto; + padding: 15px; + margin: 0 auto; + display: none; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + z-index: 3; +} + +.game--over .newHighscore-input * { + margin: 5px 0; +} + +.game--over .newHighscore-input input { + background-color: #010120; + border: 1px solid #f5f5f535; + padding: 5px; + color: #f5f5f5; + font-family: "Press Start 2P"; + font-size: 10px; + outline: none; +} + +.game--over .newHighscore-input #scoreText { + font-size: 12px; +} + +.game--over .newHighscore-notification { + color: #f5f5f5; + text-shadow: 4px 4px #860905; + -webkit-animation: highscoreAnimation 1.25s ease forwards infinite; + animation: highscoreAnimation 1.25s ease forwards infinite; +} + +.game--over .scores { + margin-top: 5px; + text-align: left; +} + +.game--over .scores span { + color: gold; + font-size: 15px; +} + +.game--over .scores * { + margin: 10px 0; +} + +.game--over .scores #finalScore, .game--over .scores #highscore { + color: gold; +} + +.game--over .gameOverBtn { + display: inline-block; + margin-top: 10px; + padding: 5px 10px; + background: none; + border: none; + color: #f5f5f5; + font-family: "Press Start 2P"; + font-size: 18px; + cursor: pointer; + border-radius: 1px; +} + +.game--over .gameOverBtn:hover { + text-shadow: 3px 3px #a10909; +} + +.pause--menu { + display: none; + width: 250px; + height: 180px; + padding: 10px; + background-color: #000016; + color: #f5f5f5; + text-align: center; + font-family: "Press Start 2P"; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + border: 2px solid #dddddd30; + position: absolute; + top: 50%; + left: 50%; + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); + z-index: 9; +} + +.pause--menu h3 { + font-size: 19px; + margin: 20px 0; + -webkit-animation: pauseTitle 0.8s ease infinite forwards; + animation: pauseTitle 0.8s ease infinite forwards; +} + +.pause--menu p { + margin: 10px 0; + cursor: pointer; +} + +.pause--menu p:hover { + color: gold; + text-shadow: 2px 2px #a10909; +} + +.settings-menu { + display: none; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + width: 350px; + height: 400px; + background-color: #000016; + border: 1px solid #f5f5f535; + padding: 15px; + z-index: 10; + font-family: "Press Start 2P"; + font-size: 12px; + position: absolute; + left: 50%; + top: 50%; + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); +} + +.settings-menu h2 { + font-size: 22px; + margin-bottom: 10px; + color: gold; + letter-spacing: 3px; + -webkit-animation: settingsText 1s ease forwards infinite; + animation: settingsText 1s ease forwards infinite; +} + +.settings-menu h3 { + color: #f5f5f5; +} + +.settings-menu button { + background: none; + border: none; + font-size: 14px; + font-family: "Press Start 2P"; + color: #f5f5f5; + cursor: pointer; + margin-top: 10px; + -webkit-transition: 0.35s ease; + transition: 0.35s ease; +} + +.settings-menu button:hover { + color: gold; + text-shadow: 2px 2px #860905; +} + +.settings-menu .settings-music, .settings-menu .settings-sfx { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + width: 320px; +} + +.settings-menu * { + margin: 5px 0; +} + +.settings-menu .directionControl { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + width: 320px; +} + +.settings-menu .directionControl * { + margin: 5px 0; +} + +.settings-menu input { + width: 100px; + cursor: pointer; + margin: 2px 0; +} + +.settings-menu input[type="text"] { + width: 100px; + cursor: text; + background: none; + border: none; + border-bottom: 1px solid #f5f5f5; + font-family: "Press Start 2P"; + color: #f5f5f5; + text-align: right; + font-size: 10px; + outline: none; + -webkit-transition: 0.3s ease; + transition: 0.3s ease; + opacity: 0.2; +} + +.settings-menu input[type="text"]:focus { + opacity: 1; + border-bottom: 2px solid gold; + padding: 5px; +} + +.settings-menu .muteContainer { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: start; + -ms-flex-pack: start; + justify-content: flex-start; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + width: 100%; + height: 20px; + margin-left: 5px; + font-size: 14px; + color: gold; +} + +.settings-menu .muteContainer img { + cursor: pointer; +} +/*# sourceMappingURL=main.css.map */ \ No newline at end of file diff --git a/SinglePlayer - Games/Earth_Guardian/static/styles/main.css.map b/SinglePlayer - Games/Earth_Guardian/static/styles/main.css.map new file mode 100644 index 00000000..14ae75ee --- /dev/null +++ b/SinglePlayer - Games/Earth_Guardian/static/styles/main.css.map @@ -0,0 +1,9 @@ +{ + "version": 3, + "mappings": "AA0BA,AAAA,IAAI,CAAA;EACA,gBAAgB,EA1BP,IAAI;EA2Bb,QAAQ,EAAE,MAAM;EAChB,KAAK,EA1BO,OAAO;CAuCtB;;AAhBD,AAKI,IALA,CAKA,cAAc,CAAA;EACV,OAAO,EAAE,CAAC;CACb;;AAPL,AASI,IATA,CASA,kBAAkB,AAAA,MAAM,CAAA;EACpB,SAAS,EAAE,4CAA4C;CAC1D;;AAXL,AAaI,IAbA,CAaA,MAAM,CAAC;EACH,OAAO,EAAE,IAAI;CAChB;;AAIL,AAAA,UAAU,CAAA;EACN,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,KAAK;EACb,QAAQ,EAAE,QAAQ;EAClB,OAAO,EAAE,IAAI;EACb,eAAe,EAAE,MAAM;EACvB,WAAW,EAAE,MAAM;EACnB,UAAU,EAAE,SAAS;EACrB,OAAO,EAAE,CAAC;EACV,OAAO,EAAE,CAAC;EACV,QAAQ,EAAE,MAAM;CA2DnB;;AArED,AAYI,UAZM,CAYN,MAAM,CAAA;EACF,UAAU,EAAE,MAAM;EAClB,OAAO,EAAE,IAAI;EACb,cAAc,EAAE,MAAM;EACtB,eAAe,EAAE,MAAM;EACvB,WAAW,EAAE,MAAM;CAmDtB;;AApEL,AAmBQ,UAnBE,CAYN,MAAM,CAOF,CAAC,CAAA;EACG,MAAM,EAAE,MAAM;CACjB;;AArBT,AAsBQ,UAtBE,CAYN,MAAM,CAUF,EAAE,CAAA;EACE,UAAU,EAAE,MAAM;EAClB,WAAW,EA3DZ,gBAAgB;EA4Df,SAAS,EAAE,IAAI;EACf,KAAK,EApED,OAAO;EAqEX,cAAc,EAhEhB,GAAG;EAiED,MAAM,EAAE,MAAM;EACd,aAAa,EAAE,IAAI;CAKtB;;AA1DL,MAAM,EAAE,SAAS,EAAE,MAAM;EAwB7B,AAsBQ,UAtBE,CAYN,MAAM,CAUF,EAAE,CAAA;IAUM,SAAS,EAAE,IAAI;GAEtB;;;AAlCT,AAmCQ,UAnCE,CAYN,MAAM,CAuBF,YAAY,CAAA;EACR,SAAS,EAAE,IAAI;EACf,WAAW,EAxEZ,gBAAgB;EAyEf,MAAM,EAAE,IAAI;EACZ,UAAU,EAAE,IAAI;EAChB,KAAK,EAAE,OAAO;EACd,cAAc,EA9EhB,GAAG;EA+ED,MAAM,EAAE,OAAO;EACf,OAAO,EAAE,CAAC;EACV,OAAO,EAAE,IAAI;EACb,UAAU,EAAE,SAAS;CAKxB;;AA1EL,MAAM,EAAE,SAAS,EAAE,MAAM;EAwB7B,AAmCQ,UAnCE,CAYN,MAAM,CAuBF,YAAY,CAAA;IAaJ,SAAS,EAAE,IAAI;GAEtB;;;AAlDT,AAmDQ,UAnDE,CAYN,MAAM,CAuCF,YAAY,AAAA,MAAM,CAAA;EACd,KAAK,EA7FA,IAAI;CA8FZ;;AArDT,AAsDQ,UAtDE,CAYN,MAAM,CA0CF,UAAU,CAAA;EACN,UAAU,EAAE,IAAI;EAChB,WAAW,EA3FZ,gBAAgB;EA4Ff,SAAS,EAAE,GAAG;EACd,KAAK,EApGD,OAAO;EAqGX,YAAY,EAAE,QAAQ;CAKzB;;AAxFL,MAAM,EAAE,SAAS,EAAE,MAAM;EAwB7B,AAsDQ,UAtDE,CAYN,MAAM,CA0CF,UAAU,CAAA;IAQF,SAAS,EAAE,IAAI;GAEtB;;;AAhET,AAiEQ,UAjEE,CAYN,MAAM,CAqDF,aAAa,CAAA;EACT,MAAM,EAAE,OAAO;CAClB;;AAIT,AAAA,UAAU,CAAA;EACN,OAAO,EAAE,IAAI;EACb,OAAO,EAAE,IAAI;EACb,KAAK,EAAE,KAAK;EACZ,MAAM,EAAE,IAAI;EAEZ,QAAQ,EAAE,QAAQ;EAClB,GAAG,EAAE,GAAG;EACR,IAAI,EAAE,GAAG;EACT,SAAS,EApHJ,qBAAqB;EAsH1B,KAAK,EA5HO,OAAO;EA6HnB,gBAAgB,EA9HR,OAAO;EA+Hf,OAAO,EAAE,CAAC;EACV,MAAM,EAAE,mBAAmB;EAE3B,UAAU,EAAE,MAAM;EAClB,WAAW,EA3HJ,gBAAgB;EA4HvB,SAAS,EAAE,IAAI;EACf,cAAc,EAAE,GAAG;EACnB,WAAW,EAAE,IAAI;CAwBpB;;AA3IG,MAAM,EAAE,SAAS,EAAE,MAAM;EA+F7B,AAAA,UAAU,CAAA;IAuBF,KAAK,EAAE,KAAK;IACZ,WAAW,EAAE,IAAI;GAoBxB;;;AA5CD,AA2BI,UA3BM,CA2BN,EAAE,CAAA;EACE,KAAK,EA5II,IAAI;EA6Ib,SAAS,EAAE,IAAI;CAClB;;AA9BL,AAgCI,UAhCM,CAgCN,CAAC,CAAA;EACG,OAAO,EAAE,IAAI;CAKhB;;AArID,MAAM,EAAE,SAAS,EAAE,MAAM;EA+F7B,AAgCI,UAhCM,CAgCN,CAAC,CAAA;IAIO,SAAS,EAAE,IAAI;GAEtB;;;AAtCL,AAwCI,UAxCM,CAwCN,CAAC,CAAA;EACG,KAAK,EAzJI,IAAI;EA0Jb,eAAe,EAAE,IAAI;CACxB;;AAGL,AAAA,oBAAoB,CAAA;EAChB,OAAO,EAAE,IAAI;EACb,KAAK,EAAE,KAAK;EACZ,MAAM,EAAE,IAAI;EACZ,OAAO,EAAE,IAAI;EACb,MAAM,EAAE,mBAAmB;EAE3B,WAAW,EA/JJ,gBAAgB;EAgKvB,KAAK,EAvKO,OAAO;EAwKnB,gBAAgB,EAzKR,OAAO;EA2Kf,QAAQ,EAAE,QAAQ;EAClB,GAAG,EAAE,GAAG;EACR,IAAI,EAAE,GAAG;EACT,SAAS,EAvKJ,qBAAqB;EAyK1B,OAAO,EAAE,CAAC;CAyCb;;AAzDD,AAkBI,oBAlBgB,CAkBhB,EAAE,CAAA;EACE,SAAS,EAAE,IAAI;EACf,cAAc,EAAE,GAAG;EACnB,KAAK,EAnLI,IAAI;EAoLb,aAAa,EAAE,IAAI;CACtB;;AAvBL,AAyBI,oBAzBgB,CAyBhB,QAAQ,CAAA;EACJ,KAAK,EAxLI,IAAI;CAyLhB;;AA3BL,AA6BI,oBA7BgB,CA6BhB,CAAC,CAAA;EACG,SAAS,EAAE,IAAI;EACf,MAAM,EAAE,MAAM;CACjB;;AAhCL,AAkCI,oBAlCgB,CAkChB,oBAAoB,CAAA;EAChB,KAAK,EAAE,IAAI;EACX,OAAO,EAAE,KAAK;EAEd,OAAO,EAAE,IAAI;EACb,eAAe,EAAE,aAAa;EAC9B,WAAW,EAAE,MAAM;EAEnB,SAAS,EAAE,IAAI;EACf,eAAe,EAAE,IAAI;CAKxB;;AAhDL,AA6CQ,oBA7CY,CAkChB,oBAAoB,CAWhB,CAAC,CAAC;EACE,MAAM,EAAE,KAAK;CAChB;;AA/CT,AAkDI,oBAlDgB,CAkDhB,UAAU,CAAC;EACP,OAAO,EAAE,IAAI;CAChB;;AApDL,AAsDI,oBAtDgB,CAsDhB,UAAU,AAAA,MAAM,CAAA;EACZ,KAAK,EAAE,OAAO;CACjB;;AAIL,AAAA,QAAQ,CAAC;EACL,QAAQ,EAAE,QAAQ;EAClB,GAAG,EAAE,GAAG;EACR,IAAI,EAAE,GAAG;EACT,SAAS,EAzNJ,qBAAqB;EA2N1B,OAAO,EAAE,IAAI;EACb,cAAc,EAAE,MAAM;EACtB,eAAe,EAAE,MAAM;EACvB,WAAW,EAAE,MAAM;EACnB,OAAO,EAAE,CAAC;EAEV,WAAW,EAhOJ,gBAAgB;CAoR1B;;AAhED,AAcI,QAdI,CAcJ,aAAa,CAAA;EACT,SAAS,EAAE,IAAI;EACf,KAAK,EA3OG,OAAO;EA4Of,aAAa,EAAE,IAAI;CAKtB;;AA/ND,MAAM,EAAE,SAAS,EAAE,MAAM;EAyM7B,AAcI,QAdI,CAcJ,aAAa,CAAA;IAML,SAAS,EAAE,IAAI;GAEtB;;;AAtBL,AAwBI,QAxBI,CAwBJ,YAAY,CAAA;EACR,KAAK,EAAE,KAAK;EACZ,MAAM,EAAE,IAAI;EACZ,MAAM,EAAE,cAAc;CAOzB;;AAlCL,AA6BQ,QA7BA,CAwBJ,YAAY,CAKR,iBAAiB,CAAC;EACd,KAAK,EAAE,EAAE;EACT,MAAM,EAAE,IAAI;EACZ,gBAAgB,EAAE,OAAO;CAC5B;;AAjCT,AAoCI,QApCI,CAoCJ,KAAK,CAAA;EACD,MAAM,EAAE,QAAQ;CA0BnB;;AA/DL,AAuCQ,QAvCA,CAoCJ,KAAK,CAGD,EAAE,CAAC;EACC,MAAM,EAAE,MAAM;EAEd,SAAS,EAAE,IAAI;EACf,UAAU,EAAE,MAAM;EAElB,KAAK,EAvQA,IAAI;EAwQT,cAAc,EAAE,GAAG;CAMtB;;AA7PL,MAAM,EAAE,SAAS,EAAE,MAAM;EAyM7B,AAuCQ,QAvCA,CAoCJ,KAAK,CAGD,EAAE,CAAC;IAUK,SAAS,EAAE,IAAI;IACf,cAAc,EAAE,GAAG;GAE1B;;;AApDT,AAsDQ,QAtDA,CAoCJ,KAAK,CAkBD,CAAC,CAAC;EACE,KAAK,EAlRD,OAAO;EAmRX,SAAS,EAAE,IAAI;EACf,MAAM,EAAE,KAAK;CAKhB;;AAvQL,MAAM,EAAE,SAAS,EAAE,MAAM;EAyM7B,AAsDQ,QAtDA,CAoCJ,KAAK,CAkBD,CAAC,CAAC;IAMM,SAAS,EAAE,IAAI;GAEtB;;;AAKT,AAAA,UAAU,CAAC;EACP,KAAK,EAAE,MAAM;EACb,MAAM,EAAE,KAAK;EACb,QAAQ,EAAE,QAAQ;EAElB,OAAO,EAAE,IAAI;EACb,cAAc,EAAE,MAAM;EACtB,eAAe,EAAE,QAAQ;EACzB,WAAW,EAAE,MAAM;EAEnB,QAAQ,EAAE,QAAQ;EAClB,GAAG,EAAE,GAAG;EACR,IAAI,EAAE,GAAG;EACT,SAAS,EArSJ,qBAAqB;EAsS1B,QAAQ,EAAE,MAAM;CAoJnB;;AAlKD,AAgBI,UAhBM,CAgBN,MAAM,CAAC;EACH,OAAO,EAAE,IAAI;EACb,MAAM,EAAE,mBAAmB;EAE3B,QAAQ,EAAE,QAAQ;EAClB,IAAI,EAAE,GAAG;EACT,GAAG,EAAE,GAAG;EACR,SAAS,EA/SR,qBAAqB;CAgTzB;;AAxBL,AA2BI,UA3BM,CA2BN,cAAc,CAAA;EACV,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,IAAI;EACZ,OAAO,EAAE,GAAG;EAEZ,MAAM,EAAE,iBAAiB;EACzB,aAAa,EAAE,IAAI;EAEnB,gBAAgB,EAAE,SAAS;EAC3B,KAAK,EAAE,IAAI;EAEX,OAAO,EAAE,IAAI;EACb,eAAe,EAAE,QAAQ;EACzB,WAAW,EAAE,MAAM;EACnB,QAAQ,EAAE,QAAQ;EAClB,MAAM,EAAE,GAAG;EACX,IAAI,EAAE,IAAI;EACV,OAAO,EAAE,EAAE;EAEX,SAAS,EAAE,IAAI;EACf,WAAW,EAtUR,gBAAgB;CAuUtB;;AAhDL,AAkDI,UAlDM,CAkDN,iBAAiB,CAAC;EACd,OAAO,EAAE,IAAI;EACb,QAAQ,EAAE,QAAQ;EAClB,MAAM,EAAE,GAAG;EACX,IAAI,EAAE,GAAG;EACT,OAAO,EAAE,CAAC;CAKb;;AA5DL,AAyDQ,UAzDE,CAkDN,iBAAiB,CAOb,GAAG,CAAA;EACC,OAAO,EAAE,CAAC;CACb;;AA3DT,AA8DI,UA9DM,CA8DN,iBAAiB,CAAA;EACb,OAAO,EAAE,IAAI;EACb,QAAQ,EAAE,QAAQ;EAClB,MAAM,EAAE,GAAG;EACX,IAAI,EAAE,IAAI;EACV,OAAO,EAAE,CAAC;CAKb;;AAxEL,AAqEQ,UArEE,CA8DN,iBAAiB,CAOb,GAAG,CAAC;EACA,OAAO,EAAE,CAAC;CACb;;AAvET,AA0EI,UA1EM,CA0EN,UAAU,CAAC;EACP,OAAO,EAAE,IAAI;EACb,WAAW,EAnWR,gBAAgB;EAoWnB,SAAS,EAAE,IAAI;EACf,KAAK,EA5WG,OAAO;EA6Wf,WAAW,EAAE,GAAG,CAAC,GAAG,CAAC,OAAgB;EACrC,OAAO,EAAE,CAAC;EACV,QAAQ,EAAE,QAAQ;EAClB,GAAG,EAAE,GAAG;EACR,IAAI,EAAE,GAAG;EACT,SAAS,EA5WR,qBAAqB;CA6WzB;;AArFL,AAuFI,UAvFM,CAuFN,kBAAkB,CAAA;EACd,OAAO,EAAE,IAAI;EAEb,WAAW,EAjXR,gBAAgB;EAkXnB,SAAS,EAAE,IAAI;EACf,cAAc,EAAE,GAAG;EAEnB,KAAK,EA5XG,OAAO;EA6Xf,WAAW,EAAE,eAAe;EAC5B,QAAQ,EAAE,QAAQ;EAClB,GAAG,EAAE,GAAG;EACR,IAAI,EAAE,GAAG;EACT,SAAS,EA3XR,qBAAqB;EA4XtB,OAAO,EAAE,CAAC;CACb;;AArGL,AAuGI,UAvGM,CAuGN,wBAAwB,CAAA;EACpB,OAAO,EAAE,KAAK;EACd,SAAS,EAAE,6CAA6C;CAC3D;;AA1GL,AA4GI,UA5GM,CA4GN,uBAAuB,CAAA;EACnB,OAAO,EAAE,KAAK;EACd,SAAS,EAAE,+CAA+C;CAC7D;;AA/GL,AAiHI,UAjHM,CAiHN,uBAAuB,CAAA;EACnB,OAAO,EAAE,IAAI;EACb,eAAe,EAAE,MAAM;EACvB,WAAW,EAAE,MAAM;EAEnB,QAAQ,EAAE,QAAQ;EAClB,IAAI,EAAE,GAAG;EACT,MAAM,EAAE,GAAG;EACX,SAAS,EAjZR,qBAAqB;CAybzB;;AAjKL,AA2HQ,UA3HE,CAiHN,uBAAuB,CAUnB,aAAa,CAAC;EACV,OAAO,EAAE,GAAG;EACZ,KAAK,EAAE,KAAK;EACZ,MAAM,EAAE,IAAI;EAEZ,OAAO,EAAE,IAAI;EACb,eAAe,EAAE,MAAM;EACvB,WAAW,EAAE,MAAM;EAEnB,SAAS,EAAE,iBAAiB;EAE5B,SAAS,EAAE,IAAI;EACf,WAAW,EA9ZZ,gBAAgB;CAoblB;;AA7JT,AAyIY,UAzIF,CAiHN,uBAAuB,CAUnB,aAAa,CAcT,CAAC,CAAC;EACE,KAAK,EAAE,OAAO;CACjB;;AA3Ib,AA6IY,UA7IF,CAiHN,uBAAuB,CAUnB,aAAa,CAkBT,CAAC,CAAC;EACE,WAAW,EAAE,GAAG;EAChB,KAAK,EA7aL,OAAO;CA8aV;;AAhJb,AAkJY,UAlJF,CAiHN,uBAAuB,CAUnB,aAAa,CAuBT,OAAO,CAAC;EACJ,KAAK,EAjbL,OAAO;CAkbV;;AApJb,AAsJY,UAtJF,CAiHN,uBAAuB,CAUnB,aAAa,CA2BT,OAAO,CAAC;EACJ,KAAK,EAAE,OAAO;CACjB;;AAxJb,AA0JY,UA1JF,CAiHN,uBAAuB,CAUnB,aAAa,CA+BT,MAAM,CAAC;EACH,KAAK,EAAE,IAAI;CACd;;AA5Jb,AA8JQ,UA9JE,CAiHN,uBAAuB,CA6CnB,mBAAmB,CAAC;EAChB,SAAS,EAAE,6BAA6B;CAC3C;;AAKT,AAAA,KAAK,CAAC;EACF,OAAO,EAAE,IAAI;EACb,KAAK,EAAE,MAAM;EACb,OAAO,EAAE,CAAC;EAEV,OAAO,EAAE,IAAI;EACb,eAAe,EAAE,aAAa;EAC9B,WAAW,EAAE,MAAM;EACnB,QAAQ,EAAE,QAAQ;EAClB,GAAG,EAAC,IAAI;EACR,IAAI,EAAE,GAAG;EACT,SAAS,EAxcJ,qBAAqB;EA0c1B,OAAO,EAAE,CAAC;EACV,UAAU,EAAE,UAAU;EAEtB,KAAK,EAndO,OAAO;EAodnB,WAAW,EA7cJ,gBAAgB;CAqiB1B;;AAzGD,AAmBI,KAnBC,CAmBD,UAAU,CAAC;EACP,MAAM,EAAE,OAAO;CAClB;;AArBL,AAuBI,KAvBC,CAuBD,KAAK,CAAC;EACF,KAAK,EAAE,KAAK;EACZ,OAAO,EAAE,IAAI;EACb,eAAe,EAAE,MAAM;EACvB,WAAW,EAAE,MAAM;CAoBtB;;AA/CL,AA4BQ,KA5BH,CAuBD,KAAK,CAKD,CAAC,CAAC;EACE,MAAM,EAAE,KAAK;CAChB;;AA9BT,AAgCQ,KAhCH,CAuBD,KAAK,CASD,CAAC,CAAC;EACE,SAAS,EAAE,IAAI;CAClB;;AAlCT,AAoCQ,KApCH,CAuBD,KAAK,CAaD,aAAa,CAAC;EACV,SAAS,EAAE,IAAI;EACf,cAAc,EAAE,GAAG;EACnB,KAAK,EAzeA,IAAI;EA0eT,WAAW,EApeZ,gBAAgB;CAqelB;;AAzCT,AA2CQ,KA3CH,CAuBD,KAAK,CAoBD,aAAa,AAAA,QAAQ,CAAA;EACjB,KAAK,EAAE,OAAO;EACd,SAAS,EAAE,IAAI;CAClB;;AA9CT,AAiDI,KAjDC,CAiDD,UAAU,CAAA;EACN,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,oCAA6B,CAAC,IAAI;EACzD,SAAS,EAAE,oBAAoB;EAC/B,mBAAmB,EAAE,MAAM;EAC3B,WAAW,EAAE,MAAM;CACtB;;AAtDL,AAwDI,KAxDC,CAwDD,gBAAgB,CAAA;EACZ,KAAK,EAAE,KAAK;EACZ,OAAO,EAAE,GAAG;EAEZ,OAAO,EAAE,IAAI;EACb,eAAe,EAAE,aAAa;EAC9B,WAAW,EAAE,MAAM;EAEnB,SAAS,EAAE,IAAI;CAwClB;;AAxGL,AAkEQ,KAlEH,CAwDD,gBAAgB,CAUZ,gBAAgB,CAAC;EACb,SAAS,EAAE,yCAAyC;CACvD;;AApET,AAqEQ,KArEH,CAwDD,gBAAgB,CAaZ,UAAU,CAAC;EACP,KAAK,EAAE,KAAK;EACZ,MAAM,EAAE,IAAI;EAEZ,OAAO,EAAE,IAAI;EACb,eAAe,EAAE,MAAM;EACvB,WAAW,EAAE,MAAM;EAEnB,MAAM,EAAE,mBAAmB;EAC3B,aAAa,EAAE,GAAG;EAElB,QAAQ,EAAE,QAAQ;EAClB,QAAQ,EAAE,MAAM;CAsBnB;;AAvGT,AAmFY,KAnFP,CAwDD,gBAAgB,CAaZ,UAAU,CAcN,CAAC,CAAC;EACE,KAAK,EAAE,OAAO;EACd,OAAO,EAAE,IAAI;CAChB;;AAtFb,AAwFY,KAxFP,CAwDD,gBAAgB,CAaZ,UAAU,CAmBN,eAAe,CAAA;EACX,QAAQ,EAAE,QAAQ;EAClB,GAAG,EAAE,CAAC;EACN,IAAI,EAAE,CAAC;EAEP,KAAK,EAAE,EAAE;EACT,MAAM,EAAE,IAAI;EAEZ,UAAU,EAAE,SAAS;EAErB,sBAAsB,EAAE,GAAG;EAC3B,yBAAyB,EAAE,GAAG;EAE9B,gBAAgB,EAAE,OAAO;CAC5B;;AAKb,AAAA,WAAW,CAAA;EACP,OAAO,EAAE,CAAC;CACb;;AAGD,AAAA,mBAAmB,CAAA;EACf,OAAO,EAAE,IAAI;EACb,OAAO,EAAE,GAAG;EAEZ,QAAQ,EAAE,QAAQ;EAClB,IAAI,EAAE,GAAG;EACT,MAAM,EAAE,GAAG;EACX,SAAS,EAAE,eAAe;EAE1B,gBAAgB,EAAE,mBAAgB;EAClC,OAAO,EAAE,CAAC;EAEV,cAAc,EAAE,MAAM;EACtB,eAAe,EAAE,MAAM;EACvB,WAAW,EAAE,MAAM;EAEnB,UAAU,EAAE,SAAS;CAiDxB;;AAjED,AAkBI,mBAlBe,CAkBf,CAAC,CAAC;EACE,UAAU,EAAE,MAAM;EAClB,WAAW,EAhkBR,gBAAgB;EAikBnB,SAAS,EAAE,IAAI;EACf,cAAc,EAAE,GAAG;EACnB,KAAK,EAAE,SAAS;CACnB;;AAxBL,AA0BI,mBA1Be,CA0Bf,aAAa,CAAA;EACT,KAAK,EAAE,KAAK;EACZ,MAAM,EAAE,IAAI;EAEZ,OAAO,EAAE,IAAI;EACb,eAAe,EAAE,MAAM;EACvB,WAAW,EAAE,MAAM;CAgCtB;;AAhEL,AAkCQ,mBAlCW,CA0Bf,aAAa,CAQT,CAAC,CAAC;EACE,MAAM,EAAE,OAAO;CAClB;;AApCT,AAsCQ,mBAtCW,CA0Bf,aAAa,CAYT,mBAAmB,AAAA,UAAW,CAAA,CAAC,EAAE;EAC7B,WAAW,EAAE,IAAI;CACpB;;AAxCT,AA0CQ,mBA1CW,CA0Bf,aAAa,CAgBT,mBAAmB,CAAA;EACf,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,IAAI;EACZ,gBAAgB,EAAE,IAAI;CACzB;;AA9CT,AAiDQ,mBAjDW,CA0Bf,aAAa,CAuBT,WAAW,CAAA;EACP,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,IAAI;EACZ,gBAAgB,EAAE,OAAO;CAC5B;;AArDT,AAsDQ,mBAtDW,CA0Bf,aAAa,CA4BT,YAAY,CAAA;EACR,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,IAAI;EACZ,gBAAgB,EAAE,OAAO;CAC5B;;AA1DT,AA2DQ,mBA3DW,CA0Bf,aAAa,CAiCT,SAAS,CAAA;EACL,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,IAAI;EACZ,gBAAgB,EAAE,OAAO;CAC5B;;AAKT,AAAA,WAAW,CAAA;EACP,OAAO,EAAE,IAAI;EACb,KAAK,EAAE,KAAK;EACZ,MAAM,EAAE,IAAI;EACZ,OAAO,EAAE,IAAI;EACb,gBAAgB,EAAE,OAAO;EAEzB,UAAU,EAAE,MAAM;EAClB,KAAK,EA/nBO,OAAO;EAgoBnB,WAAW,EAznBJ,gBAAgB;EA0nBvB,SAAS,EAAE,IAAI;EAEf,MAAM,EAAE,mBAAmB;EAC3B,QAAQ,EAAE,QAAQ;EAClB,GAAG,EAAE,GAAG;EACR,IAAI,EAAE,GAAG;EACT,SAAS,EAjoBJ,qBAAqB;EAmoB1B,OAAO,EAAE,CAAC;CAsFb;;AAxGD,AAoBI,WApBO,CAoBP,QAAQ,CAAA;EACJ,MAAM,EAAE,MAAM;EACd,WAAW,EAtoBR,gBAAgB;EAuoBnB,SAAS,EAAE,IAAI;CAClB;;AAxBL,AA0BI,WA1BO,CA0BP,mBAAmB,CAAA;EACf,KAAK,EAAE,KAAK;EACZ,MAAM,EAAE,IAAI;EACZ,OAAO,EAAE,IAAI;EACb,MAAM,EAAE,MAAM;EAEd,OAAO,EAAE,IAAI;EACb,eAAe,EAAE,MAAM;EACvB,WAAW,EAAE,MAAM;EACnB,cAAc,EAAE,MAAM;EAEtB,OAAO,EAAE,CAAC;CAqBb;;AA1DL,AAuCQ,WAvCG,CA0BP,mBAAmB,CAaf,CAAC,CAAC;EACE,MAAM,EAAE,KAAK;CAChB;;AAzCT,AA2CQ,WA3CG,CA0BP,mBAAmB,CAiBf,KAAK,CAAC;EACF,gBAAgB,EAAE,OAAO;EACzB,MAAM,EAAE,mBAAmB;EAC3B,OAAO,EAAE,GAAG;EAEZ,KAAK,EAvqBD,OAAO;EAwqBX,WAAW,EAjqBZ,gBAAgB;EAkqBf,SAAS,EAAE,IAAI;EAEf,OAAO,EAAE,IAAI;CAChB;;AArDT,AAuDQ,WAvDG,CA0BP,mBAAmB,CA6Bf,UAAU,CAAA;EACN,SAAS,EAAE,IAAI;CAClB;;AAzDT,AA4DI,WA5DO,CA4DP,0BAA0B,CAAA;EACtB,KAAK,EAAE,OAAO;EACd,WAAW,EAAE,eAAe;EAC5B,SAAS,EAAE,+CAA+C;CAC7D;;AAhEL,AAkEI,WAlEO,CAkEP,OAAO,CAAA;EACH,UAAU,EAAE,GAAG;EACf,UAAU,EAAE,IAAI;CAcnB;;AAlFL,AAsEQ,WAtEG,CAkEP,OAAO,CAIH,IAAI,CAAC;EACD,KAAK,EA7rBA,IAAI;EA8rBT,SAAS,EAAE,IAAI;CAClB;;AAzET,AA2EQ,WA3EG,CAkEP,OAAO,CASH,CAAC,CAAC;EACE,MAAM,EAAE,MAAM;CACjB;;AA7ET,AA+EQ,WA/EG,CAkEP,OAAO,CAaH,WAAW,EA/EnB,WAAW,CAkEP,OAAO,CAaU,UAAU,CAAA;EACnB,KAAK,EAtsBA,IAAI;CAusBZ;;AAjFT,AAoFI,WApFO,CAoFP,YAAY,CAAA;EACR,OAAO,EAAE,YAAY;EACrB,UAAU,EAAE,IAAI;EAChB,OAAO,EAAE,QAAQ;EAEjB,UAAU,EAAE,IAAI;EAChB,MAAM,EAAE,IAAI;EAEZ,KAAK,EAntBG,OAAO;EAotBf,WAAW,EA7sBR,gBAAgB;EA8sBnB,SAAS,EAAE,IAAI;EAGf,MAAM,EAAE,OAAO;EACf,aAAa,EAAE,GAAG;CACrB;;AAnGL,AAqGI,WArGO,CAqGP,YAAY,AAAA,MAAM,CAAA;EACd,WAAW,EAAE,GAAG,CAAC,GAAG,CAAC,OAAc;CACtC;;AAIL,AAAA,YAAY,CAAA;EACR,OAAO,EAAE,IAAI;EACb,KAAK,EAAE,KAAK;EACZ,MAAM,EAAE,KAAK;EACb,OAAO,EAAE,IAAI;EACb,gBAAgB,EAxuBR,OAAO;EA0uBf,KAAK,EAzuBO,OAAO;EA0uBnB,UAAU,EAAE,MAAM;EAClB,WAAW,EApuBJ,gBAAgB;EAsuBvB,cAAc,EAAE,MAAM;EACtB,eAAe,EAAE,MAAM;EACvB,WAAW,EAAE,MAAM;EAEnB,MAAM,EAAE,mBAAmB;EAE3B,QAAQ,EAAE,QAAQ;EAClB,GAAG,EAAE,GAAG;EACR,IAAI,EAAE,GAAG;EACT,SAAS,EAhvBJ,qBAAqB;EAivB1B,OAAO,EAAE,CAAC;CAgBb;;AArCD,AAuBI,YAvBQ,CAuBR,EAAE,CAAA;EACE,SAAS,EAAE,IAAI;EACf,MAAM,EAAE,MAAM;EACd,SAAS,EAAE,sCAAsC;CACpD;;AA3BL,AA6BI,YA7BQ,CA6BR,CAAC,CAAC;EACE,MAAM,EAAE,MAAM;EACd,MAAM,EAAE,OAAO;CAClB;;AAhCL,AAiCI,YAjCQ,CAiCR,CAAC,AAAA,MAAM,CAAC;EACJ,KAAK,EAnwBI,IAAI;EAowBb,WAAW,EAAE,GAAG,CAAC,GAAG,CAAC,OAAc;CACtC;;AAIL,AAAA,cAAc,CAAA;EACV,OAAO,EAAE,IAAI;EACb,cAAc,EAAE,MAAM;EACtB,eAAe,EAAE,MAAM;EACvB,WAAW,EAAE,MAAM;EAEnB,KAAK,EAAE,KAAK;EACZ,MAAM,EAAE,KAAK;EACb,gBAAgB,EAnxBR,OAAO;EAoxBf,MAAM,EAAE,mBAAmB;EAC3B,OAAO,EAAE,IAAI;EAEb,OAAO,EAAE,EAAE;EAGX,WAAW,EAlxBJ,gBAAgB;EAmxBvB,SAAS,EAAE,IAAI;EAEf,QAAQ,EAAE,QAAQ;EAClB,IAAI,EAAE,GAAG;EACT,GAAG,EAAE,GAAG;EACR,SAAS,EAzxBJ,qBAAqB;CA23B7B;;AAvHD,AAuBI,cAvBU,CAuBV,EAAE,CAAC;EACC,SAAS,EAAE,IAAI;EACf,aAAa,EAAE,IAAI;EACnB,KAAK,EAnyBI,IAAI;EAoyBb,cAAc,EAAE,GAAG;EACnB,SAAS,EAAE,sCAAsC;CACpD;;AA7BL,AA+BI,cA/BU,CA+BV,EAAE,CAAC;EACC,KAAK,EA1yBG,OAAO;CA2yBlB;;AAjCL,AAmCI,cAnCU,CAmCV,MAAM,CAAC;EACH,UAAU,EAAE,IAAI;EAChB,MAAM,EAAE,IAAI;EAEZ,SAAS,EAAE,IAAI;EACf,WAAW,EA3yBR,gBAAgB;EA4yBnB,KAAK,EAnzBG,OAAO;EAqzBf,MAAM,EAAE,OAAO;EACf,UAAU,EAAE,IAAI;EAChB,UAAU,EAAE,UAAU;CACzB;;AA9CL,AAgDI,cAhDU,CAgDV,MAAM,AAAA,MAAM,CAAA;EACR,KAAK,EA1zBI,IAAI;EA2zBb,WAAW,EAAE,eACjB;CAAC;;AAnDL,AAqDI,cArDU,CAqDV,eAAe,EArDnB,cAAc,CAqDO,aAAa,CAAA;EAC1B,OAAO,EAAE,IAAI;EACb,eAAe,EAAE,aAAa;EAC9B,WAAW,EAAE,MAAM;EACnB,KAAK,EAAE,KAAK;CACf;;AA1DL,AA4DI,cA5DU,CA4DV,CAAC,CAAC;EACE,MAAM,EAAE,KAAK;CAChB;;AA9DL,AAgEI,cAhEU,CAgEV,iBAAiB,CAAC;EACd,OAAO,EAAE,IAAI;EACb,eAAe,EAAE,aAAa;EAC9B,WAAW,EAAE,MAAM;EACnB,KAAK,EAAE,KAAK;CAKf;;AAzEL,AAsEQ,cAtEM,CAgEV,iBAAiB,CAMb,CAAC,CAAC;EACE,MAAM,EAAE,KAAK;CAChB;;AAxET,AA2EI,cA3EU,CA2EV,KAAK,CAAA;EACD,KAAK,EAAE,KAAK;EACZ,MAAM,EAAE,OAAO;EACf,MAAM,EAAE,KAAK;CAChB;;AA/EL,AAiFI,cAjFU,CAiFV,KAAK,CAAA,AAAA,IAAC,CAAK,MAAM,AAAX,EAAa;EACf,KAAK,EAAE,KAAK;EACZ,MAAM,EAAE,IAAI;EACZ,UAAU,EAAE,IAAI;EAChB,MAAM,EAAE,IAAI;EACZ,aAAa,EAAE,iBAAiB;EAEhC,WAAW,EA31BR,gBAAgB;EA41BnB,KAAK,EAn2BG,OAAO;EAo2Bf,UAAU,EAAE,KAAK;EACjB,SAAS,EAAE,IAAI;EAEf,OAAO,EAAE,IAAI;EAEb,UAAU,EAAE,SAAS;EACrB,OAAO,EAAE,GAAG;CACf;;AAjGL,AAmGI,cAnGU,CAmGV,KAAK,CAAA,AAAA,IAAC,CAAK,MAAM,AAAX,CAAY,MAAM,CAAC;EACrB,OAAO,EAAE,CAAC;EACV,aAAa,EAAE,GAAG,CAAC,KAAK,CA92Bf,IAAI;EA+2Bb,OAAO,EAAE,GAAG;CACf;;AAvGL,AAyGI,cAzGU,CAyGV,cAAc,CAAC;EACX,OAAO,EAAE,IAAI;EACb,eAAe,EAAE,UAAU;EAC3B,WAAW,EAAE,MAAM;EACnB,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,IAAI;EACZ,WAAW,EAAE,GAAG;EAChB,SAAS,EAAE,IAAI;EACf,KAAK,EA13BI,IAAI;CA+3BhB;;AAtHL,AAmHQ,cAnHM,CAyGV,cAAc,CAUV,GAAG,CAAC;EACA,MAAM,EAAE,OAAO;CAClB", + "sources": [ + "main.scss" + ], + "names": [], + "file": "main.css" +} \ No newline at end of file diff --git a/SinglePlayer - Games/Earth_Guardian/static/styles/main.scss b/SinglePlayer - Games/Earth_Guardian/static/styles/main.scss new file mode 100644 index 00000000..3031bc29 --- /dev/null +++ b/SinglePlayer - Games/Earth_Guardian/static/styles/main.scss @@ -0,0 +1,901 @@ +$colors: ( + primary: #000, + menues: #000016, + textColors: #f5f5f5, + highlighted: gold, +); + +// Variables +$spacing: 1px; // Letter spacing +$center: translate(-50%, -50%); +$mainFont: "Press Start 2P"; + +// Function +@function color($colorName) { + @return map-get($colors, $colorName); +} + +// Mixin - used for media queries +$desktopBigger: 1920px; + +@mixin desktopBigger { + @media (min-width: #{$desktopBigger}) { + @content; + }; +} + +body{ + background-color: color(primary); + overflow: hidden; + color: color(textColors); + + .mainMenu-fade{ + opacity: 0; + } + + .main-menu_buttons:hover{ + animation: buttonsAnimation 0.5s ease forwards infinite; + } + + button { + outline: none; + } +} + +// Main menu +.main-menu{ + width: 100%; + height: 100vh; + position: relative; + display: flex; + justify-content: center; + align-items: center; + transition: 2.5s ease; + z-index: 3; + opacity: 1; + overflow: hidden; + + .title{ + text-align: center; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + + *{ // All items + margin: 15px 0; + } + h1{ + text-align: center; + font-family: $mainFont; + font-size: 50px; + color: color(textColors); + letter-spacing: $spacing; + margin: 0 auto; + margin-bottom: 40px; + + @include desktopBigger { + font-size: 70px; + } + } + .mainButtons{ + font-size: 14px; + font-family: $mainFont; + border: none; + background: none; + color: #f5f5f5; + letter-spacing: $spacing; + cursor: pointer; + z-index: 3; + outline: none; + transition: 0.3s ease; + + @include desktopBigger { + font-size: 18px; + } + } + .mainButtons:hover{ + color: color(highlighted); + } + #copyright{ + margin-top: 80px; + font-family: $mainFont; + font-size: 8px; + color: color(textColors); + justify-self: flex-end; + + @include desktopBigger { + font-size: 14px; + } + } + .soundControl{ + cursor: pointer; + } + } +} + +.aboutMenu{ + display: none; + padding: 15px; + width: 450px; + height: auto; + + position: absolute; + top: 50%; + left: 50%; + transform: $center; + + color: color(textColors); + background-color: color(menues); + z-index: 3; + border: 1px solid #dddddd30; + + text-align: center; + font-family: $mainFont; + font-size: 12px; + letter-spacing: 2px; + line-height: 15px; + + @include desktopBigger { + width: 600px; + line-height: 20px; + } + + h3{ + color: color(highlighted); + font-size: 20px; + } + + p{ + padding: 25px; + + @include desktopBigger { + font-size: 18px; + } + } + + a{ + color: color(highlighted); + text-decoration: none; + } +} + +.highscoresList-menu{ + display: none; + width: 400px; + height: auto; + padding: 20px; + border: 1px solid #f5f5f535; + + font-family: $mainFont; + color: color(textColors); + background-color: color(menues); + + position: absolute; + top: 50%; + left: 50%; + transform: $center; + + z-index: 3; + + h3{ + font-size: 20px; + letter-spacing: 2px; + color: color(highlighted); + margin-bottom: 20px; + } + + #theName{ + color: color(highlighted); + } + + p{ + font-size: 12px; + margin: 10px 0; + } + + .highscoreList-items{ + width: 100%; + padding: 0 5px; + + display: flex; + justify-content: space-between; + align-items: center; + + font-size: 12px; + list-style-type: none; + + * { + margin: 3px 0; + } + } + + #clearList { + display: none; + } + + #clearList:hover{ + color: #bd0e08; + } +} + +// LOADING MENU +.loading { + position: absolute; + top: 50%; + left: 50%; + transform: $center; + + display: none; + flex-direction: column; + justify-content: center; + align-items: center; + z-index: 3; + + font-family: $mainFont; + + .loading-text{ + font-size: 12px; + color: color(textColors); + margin-bottom: 10px; + + @include desktopBigger { + font-size: 18px; + } + } + + .loading-bar{ + width: 200px; + height: 20px; + border: 1px solid grey; + + .loading-bar_fill { + width: 0%; + height: 100%; + background-color: #f5f5f5; + } + } + + .info{ + margin: 30px 0px; + + h2 { + margin: 10px 0; + + font-size: 16px; + text-align: center; + + color: color(highlighted); + letter-spacing: 2px; + + @include desktopBigger { + font-size: 22px; + letter-spacing: 3px; + } + } + + p { + color: color(textColors); + font-size: 10px; + margin: 5px 0; + + @include desktopBigger { + font-size: 18px; + } + } + } +} + +// CONTAINER +.container { + width: 1280px; + height: 500px; + position: relative; + + display: flex; + flex-direction: column; + justify-content: flex-end; + align-items: center; + + position: absolute; + top: 50%; + left: 50%; + transform: $center; + overflow: hidden; + + canvas { + display: none; + border: 2px solid #dddddd10; + + position: absolute; + left: 50%; + top: 50%; + transform: $center; + } + + // Health / shield status + .containerText{ + width: 60px; + height: 12px; + padding: 5px; + + border: 2px solid #860905; + border-radius: 25px; + + background-color: PeachPuff; + color: #111; + + display: flex; + justify-content: flex-end; + align-items: center; + position: absolute; + bottom: 7px; + left: 15px; + z-index: -1; + + font-size: 12px; + font-family: $mainFont; + } + + .health-container { + display: none; + position: absolute; + bottom: 5px; + left: 5px; + z-index: 3; + + img{ + z-index: 2; + } + } + + .shield-container{ + display: none; + position: absolute; + bottom: 5px; + left: 90px; + z-index: 3; + + img { + z-index: 2; + } + } + + .countdown { + display: none; + font-family: $mainFont; + font-size: 30px; + color: color(textColors); + text-shadow: 3px 3px rgb(168, 33, 33); + z-index: 3; + position: absolute; + top: 50%; + left: 50%; + transform: $center; + } + + .emptyWarning-text{ + display: none; + + font-family: $mainFont; + font-size: 22px; + letter-spacing: 3px; + + color: color(textColors); + text-shadow: 4px 4px #860905; + position: absolute; + top: 50%; + left: 50%; + transform: $center; + z-index: 3; + } + + .emptyWarning-textActive{ + display: block; + animation: overheatAnimation 0.6s ease forwards infinite; + } + + .emptyWarning-highscore{ + display: block; + animation: highscoreAnimation 1.25s ease forwards infinite; + } + + .notificationsContainer{ + display: flex; + justify-content: center; + align-items: center; + + position: absolute; + left: 50%; + bottom: 5px; + transform: $center; + + .notification { + padding: 5px; + width: 300px; + height: 40px; + + display: flex; + justify-content: center; + align-items: center; + + transform: translateY(100px); + + font-size: 12px; + font-family: $mainFont; + + i { + color: #e1302a; + } + + p { + margin-left: 5px; + color: color(textColors); + } + + .health { + color: color(textColors); + } + + .shield { + color: #1aeb71; + } + + .timer { + color: gold; + } + } + .activeNotification { + animation: notification 3s ease forwards; + } + } +} + +// GAME MENU (MENU, KILLS, TIMER, LEVEL) +.menu { + display: none; + width: 1250px; + opacity: 0; + + display: flex; + justify-content: space-between; + align-items: center; + position: absolute; + top:20px; + left: 50%; + transform: $center; + + z-index: 3; + transition: 0.75s ease; + + color: color(textColors); + font-family: $mainFont; + + #pauseGame { + cursor: pointer; + } + + .time { + width: 150px; + display: flex; + justify-content: center; + align-items: center; + * { + margin: 0 3px; + } + + i { + font-size: 30px; + } + + #timerDisplay { + font-size: 17px; + letter-spacing: 2px; + color: color(highlighted); + font-family: $mainFont; + } + + #timerDisplay.timeLow{ + color: #b30d07; + font-size: 22px; + } + } + + .timeShake{ + animation: shake 0.82s cubic-bezier(.36,.07,.19,.97) both; + transform: translate3d(0, 0, 0); + backface-visibility: hidden; + perspective: 1000px; + } + + .level-container{ + width: 350px; + padding: 3px; + + display: flex; + justify-content: space-between; + align-items: center; + + font-size: 14px; + + .levelTextActive { + animation: notifyLevelUp 0.5s ease forwards infinite; + } + .level-bar { + width: 200px; + height: 25px; + + display: flex; + justify-content: center; + align-items: center; + + border: 2px solid #f5f5f520; + border-radius: 3px; + + position: relative; + overflow: hidden; + + p { + color: #f5f5f5; + z-index: 9999; + } + + .level-bar_fill{ + position: absolute; + top: 0; + left: 0; + + width: 0%; + height: 100%; + + transition: 0.3s ease; + + border-top-left-radius: 3px; + border-bottom-left-radius: 3px; + + background-color: #b30d07; + } + } + } +} + +.menuActive{ + opacity: 1; +} + +// OVERHEAT BAR +.overheat-container{ + display: none; + padding: 5px; + + position: absolute; + left: 16%; + bottom: 3px; + transform: translate(-16%); + + background-color: rgba(0,0,0,0.95); + z-index: 3; + + flex-direction: column; + justify-content: center; + align-items: center; + + transition: 0.5s ease; + + p { + text-align: center; + font-family: $mainFont; + font-size: 12px; + letter-spacing: 2px; + color: goldenrod; + } + + .overheat-bar{ + width: 140px; + height: 25px; + + display: flex; + justify-content: center; + align-items: center; + + * { + margin: 0px 2px; + } + + .overheat-bar_block:nth-child(1) { + margin-left: -5px; + } + + .overheat-bar_block{ + width: 10px; + height: 20px; + background-color: #fff; + } + + // BLOCKS PHASES + .greenPhase{ + width: 10px; + height: 20px; + background-color: #2ECC40; + } + .yellowPhase{ + width: 10px; + height: 20px; + background-color: #FFDC00; + } + .redPhase{ + width: 10px; + height: 20px; + background-color: #b30d07; + } + } +} + +// GAME OVER MENU +.game--over{ + display: none; + width: 420px; + height: auto; + padding: 20px; + background-color: #000016; + + text-align: center; + color: color(textColors); + font-family: $mainFont; + font-size: 12px; + + border: 1px solid #f5f5f535; + position: absolute; + top: 50%; + left: 50%; + transform: $center; + + z-index: 3; + + #message{ + margin: 10px 0; + font-family: $mainFont; + font-size: 12px; + } + + .newHighscore-input{ + width: 340px; + height: auto; + padding: 15px; + margin: 0 auto; + + display: none; + justify-content: center; + align-items: center; + flex-direction: column; + + z-index: 3; + + * { + margin: 5px 0; + } + + input { + background-color: #010120; + border: 1px solid #f5f5f535; + padding: 5px; + + color: color(textColors); + font-family: $mainFont; + font-size: 10px; + + outline: none; + } + + #scoreText{ + font-size: 12px; + } + } + + .newHighscore-notification{ + color: #f5f5f5; + text-shadow: 4px 4px #860905; + animation: highscoreAnimation 1.25s ease forwards infinite; + } + + .scores{ + margin-top: 5px; + text-align: left; + + span { + color: color(highlighted); + font-size: 15px; + } + + * { + margin: 10px 0; + } + + #finalScore, #highscore{ + color: color(highlighted); + } + } + + .gameOverBtn{ + display: inline-block; + margin-top: 10px; + padding: 5px 10px; + + background: none; + border: none; + + color: color(textColors); + font-family: $mainFont; + font-size: 18px; + + + cursor: pointer; + border-radius: 1px; + } + + .gameOverBtn:hover{ + text-shadow: 3px 3px rgb(161, 9, 9); + } +} + +// PAUSE MENU +.pause--menu{ + display: none; + width: 250px; + height: 180px; + padding: 10px; + background-color: color(menues); + + color: color(textColors); + text-align: center; + font-family: $mainFont; + + flex-direction: column; + justify-content: center; + align-items: center; + + border: 2px solid #dddddd30; + + position: absolute; + top: 50%; + left: 50%; + transform: $center; + z-index: 9; + + h3{ + font-size: 19px; + margin: 20px 0; + animation: pauseTitle 0.8s ease infinite forwards; + } + + p { + margin: 10px 0; + cursor: pointer; + } + p:hover { + color: color(highlighted); + text-shadow: 2px 2px rgb(161, 9, 9); + } +} + +// SETTINGS MENU +.settings-menu{ + display: none; + flex-direction: column; + justify-content: center; + align-items: center; + + width: 350px; + height: 400px; + background-color: color(menues); + border: 1px solid #f5f5f535; + padding: 15px; + + z-index: 10; + + color: color(highligh); + font-family: $mainFont; + font-size: 12px; + + position: absolute; + left: 50%; + top: 50%; + transform: $center; + + h2 { + font-size: 22px; + margin-bottom: 10px; + color: color(highlighted); + letter-spacing: 3px; + animation: settingsText 1s ease forwards infinite; + } + + h3 { + color: color(textColors); + } + + button { + background: none; + border: none; + + font-size: 14px; + font-family: $mainFont; + color: color(textColors); + + cursor: pointer; + margin-top: 10px; + transition: 0.35s ease; + } + + button:hover{ + color: color(highlighted); + text-shadow: 2px 2px #860905 + } + + .settings-music, .settings-sfx{ + display: flex; + justify-content: space-between; + align-items: center; + width: 320px; + } + + * { + margin: 5px 0; + } + + .directionControl { + display: flex; + justify-content: space-between; + align-items: center; + width: 320px; + + * { + margin: 5px 0; + } + } + + input{ + width: 100px; + cursor: pointer; + margin: 2px 0; + } + + input[type="text"] { + width: 100px; + cursor: text; + background: none; + border: none; + border-bottom: 1px solid #f5f5f5; + + font-family: $mainFont; + color: color(textColors); + text-align: right; + font-size: 10px; + + outline: none; + + transition: 0.3s ease; + opacity: 0.2; + } + + input[type="text"]:focus { + opacity: 1; + border-bottom: 2px solid color(highlighted); + padding: 5px; + } + + .muteContainer { + display: flex; + justify-content: flex-start; + align-items: center; + width: 100%; + height: 20px; + margin-left: 5px; + font-size: 14px; + color: color(highlighted); + + img { + cursor: pointer; + } + } +} \ No newline at end of file diff --git a/SinglePlayer - Games/Earth_Guardian/static/styles/style.css b/SinglePlayer - Games/Earth_Guardian/static/styles/style.css new file mode 100644 index 00000000..f9de58a0 --- /dev/null +++ b/SinglePlayer - Games/Earth_Guardian/static/styles/style.css @@ -0,0 +1,795 @@ +*{ + margin: 0; + padding: 0; + box-sizing: border-box; +} +body{ + background-color: #000; + overflow: hidden; +} +button{ + outline: none; +} +/* MAIN MENU */ +.main-menu{ + width: 100%; + height: 100vh; + position: relative; + overflow: hidden; + opacity: 1; + transition: 2.5s ease; + z-index: 9; + display: flex; + justify-content: center; + align-items: center; +} +.mainMenuFade{ + opacity: 0; +} +.main-menu_buttons:hover{ + animation: buttonsAnimation 0.3s ease forwards infinite alternate; +} + +.title { + text-align: center; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} +.title > *{ + margin: 15px 0; +} +.title h1{ + text-align: center; + font-family: "Press Start 2P"; + font-size: 50px; + color: #f5f5f5; + letter-spacing: 1px; + margin: 0 auto; + margin-bottom: 40px; +} +.mainButtons{ + border: none; + background: none; + font-size: 14px; + font-family: "Press Start 2P"; + color: #f5f5f5; + letter-spacing: 1px; + cursor: pointer; + transition: 0.3s ease; + z-index: 9; + outline: none; +} +.mainButtons:hover{ + color: gold; +} +#copyright{ + font-family: "Press Start 2P"; + font-size: 8px; + color: #f5f5f5; + justify-self: flex-end; + margin-top: 80px; +} +.soundControl{ + cursor: pointer; +} + + + +.loading{ + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + display: none; + flex-direction: column; + justify-content: center; + align-items: center; + z-index: 999; +} + +.loading-text{ + font-family: "Press Start 2P"; + font-size: 12px; + color: #f5f5f5; + margin-bottom: 10px; +} +.loading-bar{ + width: 200px; + height: 20px; + border: 1px solid grey; +} +.loading-bar_fill{ + width: 5%; + height: 100%; + background-color: #f5f5f5; +} +.loading .info{ + margin: 30px 0; +} +.loading .info h2{ + color: #f5f5f5; + font-family: "Press Start 2P"; + font-size: 16px; + margin: 10px 0; + text-align: center; + color: gold; + letter-spacing: 2px; +} +.loading .info p{ + color: #f5f5f5; + font-family: "Press Start 2P"; + font-size: 10px; + margin: 5px 0; +} +.aboutMenu{ + display: none; + padding: 15px; + width: 450px; + height: auto; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + background-color: #000; + z-index: 999; + border: 1px solid #dddddd30; + color: #f5f5f5; + font-family: "Press Start 2P"; + font-size: 12px; + letter-spacing: 2px; + text-align: center; + line-height: 15px; +} +.aboutMenu h3{ + color: gold; + font-size: 20px; +} +.aboutMenu p { + padding: 25px; +} +.aboutMenu a { + color: gold; + text-decoration: none; +} +.highscoresList-menu { + display: none; + color: #f5f5f5; + width: 400px; + height: auto; + padding: 20px; + border: 1px solid #f5f5f535; + background-color: #000016; + z-index: 9; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + font-family: "Press Start 2P"; +} +.highscoresList-menu h3{ + font-size: 20px; + letter-spacing: 2px; + color: gold; + margin-bottom: 20px; +} +.highscoresList-menu #theName{ + color: gold; +} +.highscoresList-menu p { + font-size: 12px; + margin: 10px 0; +} +.highscoreList-items { + width: 100%; + display: flex; + justify-content: space-between; + align-items: center; + padding: 0 5px; + list-style-type: none; + font-size: 12px; + +} +.highscoreList-items > * { + margin: 3px 0; +} + +.closeMenu{ + background: none; + border: none; + color: #f5f5f5; + font-family: "Press Start 2P"; + cursor: pointer; +} +.closeMenu:hover{ + color: gold; +} +#clearList{ + display: none; +} +#clearList:hover{ + color: #bd0e08; +} + +/*////////////////////////////////////////////*/ + +/* GAME MENU */ +.menu{ + display: none; + opacity: 0; + width: 1250px; + color: #f5f5f5; + display: flex; + justify-content: space-between; + align-items: center; + position: absolute; + top:10px; + left: 50%; + transform: translate(-50%); + z-index: 99; + transition: 0.75s ease; + font-family: "Press Start 2P"; +} +#openMenu{ + cursor: pointer; +} +.menuActive{ + opacity: 1; +} +.menu .level-container{ + display: flex; + justify-content: space-between; + align-items: center; + font-size: 14px; + padding: 3px; + width: 350px; +} +.level-bar{ + width: 200px; + height: 25px; + display: flex; + justify-content: center; + align-items: center; + border: 2px solid #f5f5f520; + border-radius: 20px; + position: relative; + overflow: hidden; +} +.level-bar p{ + color: #f5f5f5; + z-index: 9999; +} +.level-bar_fill{ + position: absolute; + top: 0; + left: 0; + width: 0%; + height: 100%; + transition: 0.3s ease; + border-top-left-radius: 20px; + border-bottom-left-radius: 20px; + background-color: #b30d07; +} +.container .health-container{ + display: none; + position: absolute; + bottom: 5px; + left: 5px; + z-index: 999; +} +.container .health-container img{ + z-index: 2; +} +.containerText{ + width: 70px; + height: 23px; + border: 2px solid #860905; + border-radius: 25px; + background-color: PeachPuff ; + color: #111; + padding: 5px; + display: flex; + justify-content: flex-end; + align-items: center; + position: absolute; + bottom: 7px; + left: 15px; + z-index: -1; + font-size: 12px; + font-family: "Press Start 2P"; +} +.container .shield-container{ + display: none; + position: absolute; + bottom: 5px; + left: 90px; + z-index: 999; +} +.shield-decreased { + color: #860905; +} +.score{ + text-align: center; +} +.emptyWarning-text{ + display: none; + font-family: "Press Start 2P"; + font-size: 22px; + letter-spacing: 3px; + color: #f5f5f5; + text-shadow: 4px 4px #860905; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + z-index: 999; +} +.emptyWarning-textActive{ + display: block; + animation: overheatAnimation 0.6s ease forwards infinite; +} + + +.countdown { + display: none; + font-family: "Press Start 2P"; + font-size: 30px; + color: #f5f5f5; + text-shadow: 3px 3px rgba(168, 33, 33); + z-index: 999; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} +canvas{ + display: none; + border: 2px solid #dddddd10; + position: absolute; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); +} +.overheat-container{ + display: none; + position: absolute; + left: 16%; + bottom: 3px; + transform: translate(-16%); + background-color: rgba(0,0,0,0.95); + padding: 5px; + z-index: 999; + transition: 0.5s ease; + flex-direction: column; + justify-content: center; + align-items: center; +} +.overheat-container p { + text-transform: uppercase; + text-align: center; + font-family: "Press Start 2P"; + font-size: 12px; + letter-spacing: 2px; + color: goldenrod; +} +.overheat-bar{ + width: 140px; + height: 25px; + display: flex; + justify-content: center; + align-items: center; +} +.overheat-bar > * { + margin: 0px 2px; +} +.overheat-bar_block:nth-child(1) { + margin-left: -5px; +} +.overheat-bar_block{ + width: 10px; + height: 20px; + background-color: #fff; +} +.greenPhase{ + width: 10px; + height: 20px; + background-color: #2ECC40; +} +.yellowPhase{ + width: 10px; + height: 20px; + background-color: #FFDC00; +} +.redPhase{ + width: 10px; + height: 20px; + background-color: #b30d07; +} + +/* GAME OVER MENU */ +.game--over{ + display: none; + text-align: center; + background-color: #000016; + color: #f5f5f5; + font-family: "Press Start 2P"; + font-size: 12px; + width: 420px; + height: auto; + padding: 20px; + border: 1px solid #f5f5f535; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + z-index: 999; +} +.game--over .newHighscore-input{ + width: 340px; + height: auto; + padding: 15px; + margin: 0 auto; + display: none; + justify-content: center; + align-items: center; + flex-direction: column; + z-index: 9999; +} +.game--over .newHighscore-input > * { + margin: 5px 0; +} +.game--over .newHighscore-input input{ + background-color: #010120; + border: 1px solid #f5f5f535; + padding: 5px; + color: #f5f5f5; + outline: none; + + font-family: "Press Start 2P"; + font-size: 10px; +} +.game--over .newHighscore-input .newHighscore-notification{ + color: #f5f5f5; + text-shadow: 4px 4px #860905; + animation: highscoreAnimation 1.25s ease forwards infinite; +} +.game--over .newHighscore-input #scoreText{ + font-size: 12px; +} +.game--over .scores{ + margin-top: 5px; + text-align: left; +} +.game--over .scores span { + color: gold; + font-size: 15px; +} +.scores > * { + margin: 10px 0; +} +.gameOverBtn{ + display: inline-block; + margin-top: 10px; + background: none; + border: none; + color: #f5f5f5; + font-family: "Press Start 2P"; + font-size: 18px; + padding: 5px 10px; + cursor: pointer; + border-radius: 1px; +} +.gameOverBtn:hover{ + text-shadow: 3px 3px rgb(161, 9, 9); +} + +#message{ + margin: 10px 0; + font-family: "Press Start 2P"; + font-size: 12px; +} +#finalScore, #highscore{ + color: gold; +} + +.bars{ + display: flex; + align-items: center; +} +.hp-bars{ + width: 100px; + height: 20px; + border: 1px solid #dddddd30; + border-radius: 5px; +} +.shipShield{ + width: 100px; + height: 20px; + border: 1px solid #dddddd30; + border-radius: 5px;; +} + +.gunOverheat{ + width: 100px; + height: 20px; + border: 1px solid #dddddd30; + border-radius: 5px; +} +.speedBooster{ + width: 100px; + height: 20px; + border: 1px solid #dddddd30; + border-radius: 5px; +} +.speedBooster-fill{ + width: 100%; + height: 100%; + background-color: gold; + transition: 0.5s ease; + border-radius: 5px; +} +.ship-hpFill{ + width: 100%; + height: 100%; + background-color: #e1302a; + transition: 0.5s ease; + border-radius: 5px; +} +.shipShield-fill{ + width: 100%; + height: 100%; + background-color: #1aeb71; + transition: 0.5s ease; + border-radius: 5px; +} +.gunOverheat-fill{ + width: 0%; + height: 100%; + border-radius: 5px; + background-color: rgb(168, 33, 33); + transition: 0.5s ease; +} +/* PAUSE MENU */ +.pause--menu{ + display: none; + width: 250px; + height: 180px; + padding: 10px; + background-color: #000016; + color: #f5f5f5; + text-align: center; + flex-direction: column; + justify-content: center; + align-items: center; + border: 2px solid #dddddd30; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + z-index: 9; +} +.pause--menu h3{ + font-family: "Press Start 2P"; + font-size: 19px; + margin: 20px 0; + animation: pauseTitle 0.8s ease infinite forwards; +} + +.pause--menu p{ + margin: 10px 0; + cursor: pointer; + font-family: "Press Start 2P"; +} +.pause--menu p:hover{ + color: gold; + text-shadow: 2px 2px rgb(161, 9, 9); +} + +/* SETTINGS MENU */ +.settings-menu{ + display: none; + flex-direction: column; + justify-content: center; + align-items: center; + width: 350px; + height: 370px; + background-color: #000016; + border: 1px solid #f5f5f535; + padding: 15px; + z-index: 9999999; + color: gold; + font-family: "Press Start 2P"; + font-size: 12px; + + position: absolute; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); +} +.settings-menu h2{ + font-size: 22px; + margin-bottom: 10px; + color: gold; + letter-spacing: 3px; + animation: settingsText 1s ease forwards infinite; +} +.settings-menu h3{ + color: #f5f5f5; +} +.settings-menu button{ + background: none; + border: none; + font-size: 14px; + font-family: "Press Start 2P"; + color: #f5f5f5; + cursor: pointer; + margin-top: 10px; + transition: 0.35s ease; +} +.settings-menu button:hover{ + color: gold; + text-shadow: 2px 2px #860905 +} +.settings-menu .settings-music, .settings-menu .settings-sfx{ + display: flex; + justify-content: space-between; + align-items: center; + width: 320px; +} +.settings-menu > * { + margin: 10px 0; +} +.settings-menu .directionControl { + display: flex; + justify-content: space-between; + align-items: center; + width: 320px; +} +.settings-menu .directionControl > *{ + margin: 5px 0; +} +.settings-menu input{ + width: 100px; + cursor: pointer; + margin: 2px 0; +} +.settings-menu input[type="text"] { + width: 100px; + cursor: text; + background: none; + border: none; + border-bottom: 1px solid #f5f5f5; + font-family: "Press Start 2P"; + color: #f5f5f5; + text-align: right; + outline: none; + transition: 0.3s ease; + opacity: 0.2; + font-size: 10px; +} +.settings-menu input[type="text"]:focus { + opacity: 1; + border-bottom: 2px solid gold; + padding: 5px; +} + +.controlsInfoActive{ + opacity: 0; +} +.container{ + width: 1280px; + height: 500px; + position: relative; + display: flex; + flex-direction: column; + justify-content: flex-end; + align-items: center; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + overflow: hidden; +} +.notificationsContainer{ + /* width: 100%; */ + display: flex; + justify-content: center; + align-items: center; + position: absolute; + left: 50%; + bottom: 5px; + transform: translate(-50%, 5px); +} +.notification{ + display: flex; + justify-content: center; + align-items: center; + padding: 5px; + width: 300px; + height: 40px; + transform: translateY(100px); + font-size: 12px; + font-family: "Press Start 2P"; +} +.activeNotification{ + animation: notification 4s ease forwards; +} +.notification i { + color: #e1302a +} +.notification p { + margin-left: 5px; + color: #f5f5f5; +} +/* shield notification */ +.notification .shield { + color: #1aeb71; +} +/* health restore notification */ +.notification .health { + color: #f5f5f5; +} +/* added playime notification */ +.notification .timer{ + color: gold; +} +.time{ + width: 150px; + display: flex; + justify-content: center; + align-items: center; +} +.timeShake{ + animation: shake 0.82s cubic-bezier(.36,.07,.19,.97) both; + transform: translate3d(0, 0, 0); + backface-visibility: hidden; + perspective: 1000px; +} + + +.time > * { + margin: 0 3px; +} +.time i { + font-size: 30px; +} +#timerDisplay{ + font-size: 17px; + letter-spacing: 2px; + color: gold; + font-family: "Press Start 2P"; +} +#timerDisplay.timeLow{ + color: #b30d07; + font-size: 22px; +} + +@media (min-width: 1920px) { + #title { + font-size: 40px; + } + #startGame, #about{ + font-size: 22px; + } + #copyright{ + font-size: 16px; + } + .aboutMenu{ + width: 600px; + line-height: 20px; + } + .aboutMenu p{ + font-size: 18px; + } + .loading .info h2{ + font-size: 22px; + letter-spacing: 3px; + } + .loading .loading-text { + font-size: 18px; + } + .loading .info p { + font-size: 18px; + } +} \ No newline at end of file diff --git a/additionalpage/game.html b/additionalpage/game.html index b05237f3..9812c075 100644 --- a/additionalpage/game.html +++ b/additionalpage/game.html @@ -9677,6 +9677,54 @@

Angry Birds

+ + + + + + + +
+
+ +
+ 41 + +
+
+
+
+
+

Pop My Balloon

+

-Earth Guardian is a remake of the classic Space shooter type of games, with 8-bit (pixel art) assets. This project used free assets (music and graphics) provided by [Jonathan So](https://jonathan-so.itch.io/),[KennyNL](https://kenney.nl/) and other sources, like Google images and [OpenGameArt](https://opengameart.org). This was a learning project. There will be some updates in the near future. Hope you like it, have fun! +

+
+
+ + + + + +
+
+
+
+
+

Release Date:  

+

14.05.2024

+
+
+

Updated:  

+

Action | Desktop

+
+
+
+ Play Now +
+
+
+
+ diff --git a/assets/images/Earth_Guardian.png b/assets/images/Earth_Guardian.png new file mode 100644 index 00000000..10ee7ec1 Binary files /dev/null and b/assets/images/Earth_Guardian.png differ