├── .babelrc.js ├── .eslintrc ├── .gitignore ├── .postcssrc.json ├── .stylelintrc ├── README.md ├── gameboy-css.png ├── package-lock.json ├── package.json └── src ├── assets ├── bits.png ├── hit.mp3 ├── intro.mp3 ├── level1.mp3 ├── level2.mp3 ├── level3.mp3 ├── ljn.png ├── pretendo.ttf ├── pretendo.woff ├── pretendo.woff2 ├── startup.mp3 ├── t2.png ├── t2.ttf ├── t2.woff ├── t2.woff2 └── title.png ├── components ├── GameboyConsole.js ├── GameboyControlsButtons.js ├── GameboyControlsCross.js ├── GameboyControlsGame.js └── GameboyScreen.js ├── index.css ├── index.html └── index.js /.babelrc.js: -------------------------------------------------------------------------------- 1 | const postcssOptions = require("./.postcssrc.json"); 2 | 3 | module.exports = { 4 | plugins: [["postcss-template-literals", { tag: "css", ...postcssOptions }]], 5 | }; 6 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es6": true 5 | }, 6 | "extends": [ 7 | "standard", 8 | "prettier" 9 | ], 10 | "globals": { 11 | "Atomics": "readonly", 12 | "SharedArrayBuffer": "readonly" 13 | }, 14 | "parserOptions": { 15 | "ecmaVersion": 2018, 16 | "sourceType": "module" 17 | }, 18 | "rules": { 19 | "semi": [ 20 | "error", 21 | "always" 22 | ] 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .cache/ 3 | .parcel-cache/ 4 | dist/ 5 | build/ 6 | -------------------------------------------------------------------------------- /.postcssrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "postcss-nesting", 4 | "autoprefixer" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /.stylelintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "stylelint-config-standard" 4 | ], 5 | "rules": { 6 | "indentation": 2, 7 | "selector-nested-pattern": "^&", 8 | "declaration-colon-newline-after": "always-multi-line", 9 | "value-list-comma-newline-after": "always-multi-line", 10 | "value-list-comma-space-after": "always-single-line", 11 | "value-list-comma-space-before": "never" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GameBoy CSS 2 | 3 | A Visual/Interactive Nintendo GameBoy using HTML, CSS, Javascript & WebComponents. 4 | 5 |  6 | 7 | Created by **[@Manz](https://twitter.com/Manz)** 8 | 9 | Others demos: https://manzdev.github.io/ 10 | 11 | #### Tools & libraries 12 | 13 | - Native technologies: [HTML](https://lenguajehtml.com/), [CSS](https://lenguajecss.com/) & [Javascript](https://lenguajejs.com/) (cheatsheets here!) 14 | - WebComponents using Google [LitElement](https://lit-element.polymer-project.org/) 15 | - Powered with PostCSS, Babel, ESLint, Stylelint, Prettier and Parcel. 16 | - [HowlerJS](https://howlerjs.com/) for music 17 | - [DatGUI](https://github.com/dataarts/dat.gui) for interactive widget 18 | - [Audacity](https://www.audacityteam.org/), free sound editor 19 | - [create-lit-app](https://gist.github.com/ManzDev/f36766103a69a54fa6f1c7cc7ff98355), my own script for create LitElement app scaffold 20 | 21 | #### Fonts 22 | 23 | - [Terminator 2: Judgment Day (Mega Drive) by Patrick Lauke](https://fontstruct.com/fontstructions/show/1536530/terminator-2-judgment-day-mega-drive) 24 | - [Pretendo](http://www.abstractfonts.com/font/11800?text=Nintendo) 25 | - [Press Start 2P](https://fonts.google.com/specimen/Press+Start+2P) 26 | - [Lato](https://fonts.google.com/specimen/Lato) 27 | 28 | #### Images & Music 29 | 30 | - Original game from **Terminator 2: Judgment day** for _Nintendo GameBoy_. 31 | - Original music from **Terminator 2: Judgment day** from _David Whittaker_. 32 | -------------------------------------------------------------------------------- /gameboy-css.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManzDev/gameboycss/154b795f61ab8b0f70c573bb32c0ce9cebf674ce/gameboy-css.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gameboycss", 3 | "version": "1.0.0", 4 | "description": "A Visual Nintendo GameBoy using HTML, CSS, Javascript & WebComponents", 5 | "main": "src/index.html", 6 | "scripts": { 7 | "start": "parcel serve src/index.html", 8 | "build": "parcel build src/index.html -d build --public-url /$npm_package_name/ && gh-pages -d build" 9 | }, 10 | "keywords": [ 11 | "nintendo", 12 | "gameboy", 13 | "terminator 2", 14 | "judgment day", 15 | "games", 16 | "retro", 17 | "videogames", 18 | "html", 19 | "css", 20 | "javascript", 21 | "webcomponents", 22 | "lit-element", 23 | "howler" 24 | ], 25 | "author": "ManzDev", 26 | "license": "ISC", 27 | "devDependencies": { 28 | "@babel/core": "^7.12.16", 29 | "@types/dat.gui": "^0.7.6", 30 | "@types/howler": "^2.2.1", 31 | "autoprefixer": "^10.2.4", 32 | "babel-plugin-postcss-template-literals": "^1.0.0-alpha.2", 33 | "cssnano": "^4.1.10", 34 | "eslint": "^7.20.0", 35 | "eslint-config-prettier": "^7.2.0", 36 | "eslint-config-standard": "^16.0.2", 37 | "eslint-plugin-import": "^2.22.1", 38 | "eslint-plugin-node": "^11.1.0", 39 | "eslint-plugin-promise": "^4.3.1", 40 | "gh-pages": "^3.1.0", 41 | "postcss-nesting": "^7.0.1", 42 | "prettier": "^2.2.1", 43 | "stylelint": "^13.10.0", 44 | "stylelint-config-standard": "^20.0.0" 45 | }, 46 | "dependencies": { 47 | "dat.gui": "^0.7.7", 48 | "howler": "^2.2.1", 49 | "lit-element": "^2.4.0" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/assets/bits.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManzDev/gameboycss/154b795f61ab8b0f70c573bb32c0ce9cebf674ce/src/assets/bits.png -------------------------------------------------------------------------------- /src/assets/hit.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManzDev/gameboycss/154b795f61ab8b0f70c573bb32c0ce9cebf674ce/src/assets/hit.mp3 -------------------------------------------------------------------------------- /src/assets/intro.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManzDev/gameboycss/154b795f61ab8b0f70c573bb32c0ce9cebf674ce/src/assets/intro.mp3 -------------------------------------------------------------------------------- /src/assets/level1.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManzDev/gameboycss/154b795f61ab8b0f70c573bb32c0ce9cebf674ce/src/assets/level1.mp3 -------------------------------------------------------------------------------- /src/assets/level2.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManzDev/gameboycss/154b795f61ab8b0f70c573bb32c0ce9cebf674ce/src/assets/level2.mp3 -------------------------------------------------------------------------------- /src/assets/level3.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManzDev/gameboycss/154b795f61ab8b0f70c573bb32c0ce9cebf674ce/src/assets/level3.mp3 -------------------------------------------------------------------------------- /src/assets/ljn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManzDev/gameboycss/154b795f61ab8b0f70c573bb32c0ce9cebf674ce/src/assets/ljn.png -------------------------------------------------------------------------------- /src/assets/pretendo.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManzDev/gameboycss/154b795f61ab8b0f70c573bb32c0ce9cebf674ce/src/assets/pretendo.ttf -------------------------------------------------------------------------------- /src/assets/pretendo.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManzDev/gameboycss/154b795f61ab8b0f70c573bb32c0ce9cebf674ce/src/assets/pretendo.woff -------------------------------------------------------------------------------- /src/assets/pretendo.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManzDev/gameboycss/154b795f61ab8b0f70c573bb32c0ce9cebf674ce/src/assets/pretendo.woff2 -------------------------------------------------------------------------------- /src/assets/startup.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManzDev/gameboycss/154b795f61ab8b0f70c573bb32c0ce9cebf674ce/src/assets/startup.mp3 -------------------------------------------------------------------------------- /src/assets/t2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManzDev/gameboycss/154b795f61ab8b0f70c573bb32c0ce9cebf674ce/src/assets/t2.png -------------------------------------------------------------------------------- /src/assets/t2.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManzDev/gameboycss/154b795f61ab8b0f70c573bb32c0ce9cebf674ce/src/assets/t2.ttf -------------------------------------------------------------------------------- /src/assets/t2.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManzDev/gameboycss/154b795f61ab8b0f70c573bb32c0ce9cebf674ce/src/assets/t2.woff -------------------------------------------------------------------------------- /src/assets/t2.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManzDev/gameboycss/154b795f61ab8b0f70c573bb32c0ce9cebf674ce/src/assets/t2.woff2 -------------------------------------------------------------------------------- /src/assets/title.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManzDev/gameboycss/154b795f61ab8b0f70c573bb32c0ce9cebf674ce/src/assets/title.png -------------------------------------------------------------------------------- /src/components/GameboyConsole.js: -------------------------------------------------------------------------------- 1 | import "./GameboyControlsCross.js"; 2 | import "./GameboyControlsButtons.js"; 3 | import "./GameboyControlsGame.js"; 4 | import "./GameboyScreen.js"; 5 | 6 | import { LitElement, html, css } from "lit-element"; 7 | import { classMap } from "lit-html/directives/class-map"; 8 | import { Howler } from "howler"; 9 | 10 | export default class GameboyConsole extends LitElement { 11 | static get properties() { 12 | return { 13 | isOn: { type: Boolean }, 14 | }; 15 | } 16 | 17 | constructor() { 18 | super(); 19 | this.isOn = false; 20 | this.width = 380; 21 | this.height = 625; 22 | this.batteryLevel = 1; 23 | 24 | this.addEventListener("GAMEBOY_SELECT_PRESSED", () => this.nextSongTheme()); 25 | } 26 | 27 | setBackgroundColor(col) { 28 | this.style.setProperty("--gameboy-bgcolor", col); 29 | console.log(col); 30 | } 31 | 32 | setBatteryLevel(level) { 33 | this.batteryLevel = level; 34 | this.style.setProperty("--gameboy-battery-level", Math.min(1, level * 1.5)); 35 | this.style.setProperty("--gameboy-overlay-level", level * 1.5); 36 | } 37 | 38 | setVolumeLevel(level) { 39 | Howler.volume(level); 40 | } 41 | 42 | nextSongTheme() { 43 | this.shadowRoot.querySelector("gameboy-screen").nextSongTheme(); 44 | } 45 | 46 | static get styles() { 47 | // prettier-ignore 48 | return css` 49 | :host { 50 | --gameboy-bgcolor: #d3ccd3; 51 | --gameboy-battery-level: 1; 52 | --gameboy-overlay-level: 1.5; 53 | 54 | width: var(--gameboy-width); 55 | height: var(--gameboy-height); 56 | position: relative; 57 | } 58 | 59 | /* GameBoy console body */ 60 | .gameboy { 61 | background-color: var(--gameboy-bgcolor); 62 | background-image: linear-gradient(transparent 95%, rgba(0, 0, 0, 0.5) 98%, rgba(0, 0, 0, 0.4) 99%); 63 | overflow: hidden; 64 | border-radius: 12px 12px 75px 12px; 65 | box-shadow: 66 | 0 0 10px rgba(0, 0, 0, 0.5), 67 | 0 0 25px rgba(0, 0, 0, 0.25) inset, 68 | -2px -2px 10px rgba(0, 0, 0, 0.8) inset, 69 | 0 0 15px rgba(0, 0, 0, 0.75) inset; 70 | display: flex; 71 | flex-direction: column; 72 | justify-content: space-between; 73 | position: relative; 74 | } 75 | 76 | .power { 77 | width: 30px; 78 | height: 15px; 79 | border-radius: 50%; 80 | background-color: var(--gameboy-bgcolor); 81 | background-image: linear-gradient(to right, rgba(0, 0, 0, 0.05) 10%, rgba(0, 0, 0, 0.1) 30% 70%, rgba(0, 0, 0, 0.05) 90%); 82 | box-shadow: 0 0 4px rgba(0, 0, 0, 0.5) inset; 83 | position: absolute; 84 | top: -7px; 85 | left: 50px; 86 | cursor: pointer; 87 | 88 | &.on { 89 | left: 75px; 90 | } 91 | } 92 | 93 | .gbtop { 94 | display: flex; 95 | padding-bottom: 5px; 96 | margin-bottom: 5px; 97 | border-bottom: 1px solid rgba(0, 0, 0, 0.1); 98 | 99 | & .corner { 100 | width: 25px; 101 | height: 20px; 102 | } 103 | 104 | & .corner.left { 105 | margin-right: 5px; 106 | } 107 | 108 | & .corner.right { 109 | margin-left: 5px; 110 | } 111 | 112 | & .top { 113 | width: 100%; 114 | 115 | & span { 116 | font-family: Arial, sans-serif; 117 | font-size: 12px; 118 | box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.5) inset; 119 | text-shadow: 2px 1px 2px rgba(0, 0, 0, 1); 120 | color: #eee; 121 | border-radius: 15px; 122 | margin: 0 6px; 123 | padding: 2px 5px; 124 | opacity: 0.25; 125 | } 126 | } 127 | 128 | & .left, 129 | & .top, 130 | & .right { 131 | border-radius: 0 0 2px 2px; 132 | border: 1px solid rgba(0, 0, 0, 0.1); 133 | box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.25); 134 | } 135 | } 136 | 137 | /* GameBoy complete screen (gray + green) */ 138 | .screen { 139 | background: #767189; 140 | width: calc(var(--gameboy-height) / 1.9); 141 | box-shadow: 0 0 2px #514c65; 142 | border-radius: 10px 10px 35px 10px; 143 | border: 1px solid #666; 144 | border-width: 0 1px 0 1px; 145 | height: 250px; 146 | margin: 0.1em auto; 147 | 148 | & .minitext { 149 | font-family: Arial, sans-serif; 150 | font-size: 10px; 151 | color: #fff; 152 | } 153 | 154 | & .top { 155 | margin: 0 15px; 156 | height: 30px; 157 | background: 158 | linear-gradient( 159 | transparent 10px, 160 | #7d1a4a 10px 12px, 161 | transparent 12px 16px, 162 | #35224e 16px 18px, 163 | transparent 18px 164 | ); 165 | position: relative; 166 | 167 | & span { 168 | padding: 0 8px; 169 | background: #767189; 170 | position: absolute; 171 | right: 30px; 172 | top: 8px; 173 | } 174 | } 175 | 176 | & .bottom { 177 | display: flex; 178 | 179 | & .led { 180 | width: 10px; 181 | height: 10px; 182 | background: #4a4748; 183 | border-radius: 50%; 184 | margin: 6px; 185 | 186 | &.on { 187 | background: rgba(216, 30, 7, var(--gameboy-battery-level)); 188 | box-shadow: 0 0 5px #d81e07; 189 | } 190 | } 191 | 192 | & .battery { 193 | padding: 0 10px; 194 | display: flex; 195 | flex-direction: column; 196 | justify-content: center; 197 | align-items: flex-start; 198 | 199 | & .minitext { 200 | font-size: 9px; 201 | } 202 | } 203 | } 204 | } 205 | 206 | /* Brand Nintendo GameBoy text */ 207 | .brand { 208 | margin: 5px 30px; 209 | 210 | & .company, 211 | & .type { 212 | font-family: Pretendo, sans-serif; 213 | font-size: 14px; 214 | color: #302058; 215 | } 216 | 217 | & .type { 218 | font-family: Lato, sans-serif; 219 | font-weight: bold; 220 | font-style: italic; 221 | font-size: 22px; 222 | } 223 | } 224 | 225 | /* Main controls: Cross and A/B buttons */ 226 | .controls { 227 | display: flex; 228 | justify-content: space-between; 229 | } 230 | 231 | /* Gameboy bottom body part */ 232 | .gameboy > .bottom { 233 | display: flex; 234 | flex-direction: column; 235 | align-items: center; 236 | position: relative; 237 | left: -20px; 238 | } 239 | 240 | .speaker { 241 | display: flex; 242 | width: 120px; 243 | justify-content: space-around; 244 | position: absolute; 245 | right: 10px; 246 | bottom: 35px; 247 | transform: rotate(-30deg); 248 | 249 | &::after { 250 | content: ""; 251 | width: 200px; 252 | height: 60px; 253 | position: absolute; 254 | background: rgba(0, 0, 0, 0.1); 255 | top: 50px; 256 | } 257 | 258 | & .band { 259 | width: 8px; 260 | height: 60px; 261 | border-radius: 8px; 262 | box-shadow: 3px 6px 1px rgba(0, 0, 0, 0.6) inset; 263 | background: rgba(0, 0, 0, 0.35); 264 | } 265 | } 266 | 267 | .gbbottom { 268 | transform: translateX(6px); 269 | } 270 | 271 | .phones { 272 | font-family: Arial, sans-serif; 273 | font-size: 10px; 274 | opacity: 0.5; 275 | text-align: center; 276 | border: 1px solid #aaa; 277 | border-radius: 40px; 278 | padding: 2px 6px; 279 | box-shadow: 0 0 5px rgba(0, 0, 0, 0.5) inset; 280 | } 281 | 282 | .slot { 283 | margin: auto; 284 | } 285 | 286 | .slot, 287 | .slot::before, 288 | .slot::after { 289 | width: 5px; 290 | height: 10px; 291 | background-color: var(--gameboy-bgcolor); 292 | background-image: 293 | linear-gradient( 294 | to left, 295 | rgba(0, 0, 0, 0.65) 1px, 296 | rgba(0, 0, 0, 0.6) 2px, 297 | rgba(0, 0, 0, 0.65) 4px 298 | ); 299 | } 300 | 301 | .slot::before, 302 | .slot::after { 303 | content: ""; 304 | display: block; 305 | width: 5px; 306 | height: 10px; 307 | position: absolute; 308 | } 309 | 310 | .slot::before { 311 | transform: translateX(-8px); 312 | } 313 | 314 | .slot::after { 315 | transform: translateX(8px); 316 | } 317 | `; 318 | } 319 | 320 | clickPower() { 321 | this.isOn = !this.isOn; 322 | } 323 | 324 | render() { 325 | return html` 326 | 332 |
333 |Terminator 2
Judgment Day
© 1991 CAROLCO
© 1991 LJN LTD.
Programming
Copyright B.I.T.S.
LICENSED BY NINTENDO
268 |