├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── content ├── .DS_Store ├── Chili_peppe.jpeg ├── Keanu-Reeves.png ├── MegaMan11.jpeg ├── Silent-Hill-3.jpeg ├── mega-man-11.html ├── mega-man.jpeg ├── mega.jpeg ├── silent-hill-2021.jpeg ├── tiger.jpeg ├── tiger2.jpeg └── woman.jpeg ├── index.html ├── src └── main.rs └── style.css /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "autocfg" 7 | version = "1.1.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 10 | 11 | [[package]] 12 | name = "boolinator" 13 | version = "2.4.0" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "cfa8873f51c92e232f9bac4065cddef41b714152812bfc5f7672ba16d6ef8cd9" 16 | 17 | [[package]] 18 | name = "bumpalo" 19 | version = "3.10.0" 20 | source = "registry+https://github.com/rust-lang/crates.io-index" 21 | checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" 22 | 23 | [[package]] 24 | name = "canvas" 25 | version = "0.1.0" 26 | dependencies = [ 27 | "getrandom", 28 | "gloo 0.3.0", 29 | "gloo-utils", 30 | "js-sys", 31 | "rand", 32 | "wasm-bindgen", 33 | "wasm-bindgen-futures", 34 | "web-sys", 35 | "yew", 36 | ] 37 | 38 | [[package]] 39 | name = "cfg-if" 40 | version = "1.0.0" 41 | source = "registry+https://github.com/rust-lang/crates.io-index" 42 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 43 | 44 | [[package]] 45 | name = "console_error_panic_hook" 46 | version = "0.1.7" 47 | source = "registry+https://github.com/rust-lang/crates.io-index" 48 | checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" 49 | dependencies = [ 50 | "cfg-if", 51 | "wasm-bindgen", 52 | ] 53 | 54 | [[package]] 55 | name = "getrandom" 56 | version = "0.2.7" 57 | source = "registry+https://github.com/rust-lang/crates.io-index" 58 | checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" 59 | dependencies = [ 60 | "cfg-if", 61 | "js-sys", 62 | "libc", 63 | "wasi", 64 | "wasm-bindgen", 65 | ] 66 | 67 | [[package]] 68 | name = "gloo" 69 | version = "0.3.0" 70 | source = "registry+https://github.com/rust-lang/crates.io-index" 71 | checksum = "0b31ec63066de893f3be98da84af50441ea35819bd7be95373802dea56293952" 72 | dependencies = [ 73 | "gloo-console 0.1.0", 74 | "gloo-dialogs", 75 | "gloo-events", 76 | "gloo-file 0.1.0", 77 | "gloo-render", 78 | "gloo-storage 0.1.0", 79 | "gloo-timers", 80 | ] 81 | 82 | [[package]] 83 | name = "gloo" 84 | version = "0.4.2" 85 | source = "registry+https://github.com/rust-lang/crates.io-index" 86 | checksum = "23947965eee55e3e97a5cd142dd4c10631cc349b48cecca0ed230fd296f568cd" 87 | dependencies = [ 88 | "gloo-console 0.2.1", 89 | "gloo-dialogs", 90 | "gloo-events", 91 | "gloo-file 0.2.1", 92 | "gloo-render", 93 | "gloo-storage 0.2.1", 94 | "gloo-timers", 95 | "gloo-utils", 96 | ] 97 | 98 | [[package]] 99 | name = "gloo-console" 100 | version = "0.1.0" 101 | source = "registry+https://github.com/rust-lang/crates.io-index" 102 | checksum = "770942b86a2ab86330201eeafc5fe526fb203e54dbc6ef82a36453cebcb90e4c" 103 | dependencies = [ 104 | "js-sys", 105 | "serde", 106 | "wasm-bindgen", 107 | "web-sys", 108 | ] 109 | 110 | [[package]] 111 | name = "gloo-console" 112 | version = "0.2.1" 113 | source = "registry+https://github.com/rust-lang/crates.io-index" 114 | checksum = "3907f786f65bbb4f419e918b0c5674175ef1c231ecda93b2dbd65fd1e8882637" 115 | dependencies = [ 116 | "js-sys", 117 | "serde", 118 | "wasm-bindgen", 119 | "web-sys", 120 | ] 121 | 122 | [[package]] 123 | name = "gloo-dialogs" 124 | version = "0.1.1" 125 | source = "registry+https://github.com/rust-lang/crates.io-index" 126 | checksum = "67062364ac72d27f08445a46cab428188e2e224ec9e37efdba48ae8c289002e6" 127 | dependencies = [ 128 | "wasm-bindgen", 129 | "web-sys", 130 | ] 131 | 132 | [[package]] 133 | name = "gloo-events" 134 | version = "0.1.2" 135 | source = "registry+https://github.com/rust-lang/crates.io-index" 136 | checksum = "68b107f8abed8105e4182de63845afcc7b69c098b7852a813ea7462a320992fc" 137 | dependencies = [ 138 | "wasm-bindgen", 139 | "web-sys", 140 | ] 141 | 142 | [[package]] 143 | name = "gloo-file" 144 | version = "0.1.0" 145 | source = "registry+https://github.com/rust-lang/crates.io-index" 146 | checksum = "8f9fecfe46b5dc3cc46f58e98ba580cc714f2c93860796d002eb3527a465ef49" 147 | dependencies = [ 148 | "gloo-events", 149 | "js-sys", 150 | "wasm-bindgen", 151 | "web-sys", 152 | ] 153 | 154 | [[package]] 155 | name = "gloo-file" 156 | version = "0.2.1" 157 | source = "registry+https://github.com/rust-lang/crates.io-index" 158 | checksum = "aa5d6084efa4a2b182ef3a8649cb6506cb4843f22cf907c6e0a799944248ae90" 159 | dependencies = [ 160 | "gloo-events", 161 | "js-sys", 162 | "wasm-bindgen", 163 | "web-sys", 164 | ] 165 | 166 | [[package]] 167 | name = "gloo-render" 168 | version = "0.1.1" 169 | source = "registry+https://github.com/rust-lang/crates.io-index" 170 | checksum = "2fd9306aef67cfd4449823aadcd14e3958e0800aa2183955a309112a84ec7764" 171 | dependencies = [ 172 | "wasm-bindgen", 173 | "web-sys", 174 | ] 175 | 176 | [[package]] 177 | name = "gloo-storage" 178 | version = "0.1.0" 179 | source = "registry+https://github.com/rust-lang/crates.io-index" 180 | checksum = "8c6cbd4f8664a9eec3d1f65de3e88d5898ef331db56efceae30fae4883ed311b" 181 | dependencies = [ 182 | "js-sys", 183 | "serde", 184 | "serde_json", 185 | "thiserror", 186 | "wasm-bindgen", 187 | "web-sys", 188 | ] 189 | 190 | [[package]] 191 | name = "gloo-storage" 192 | version = "0.2.1" 193 | source = "registry+https://github.com/rust-lang/crates.io-index" 194 | checksum = "1caa4ba51c99de680dee3ad99c32ca45e9f13311be72079154d222c3f9a6b6f5" 195 | dependencies = [ 196 | "gloo-utils", 197 | "js-sys", 198 | "serde", 199 | "serde_json", 200 | "thiserror", 201 | "wasm-bindgen", 202 | "web-sys", 203 | ] 204 | 205 | [[package]] 206 | name = "gloo-timers" 207 | version = "0.2.4" 208 | source = "registry+https://github.com/rust-lang/crates.io-index" 209 | checksum = "5fb7d06c1c8cc2a29bee7ec961009a0b2caa0793ee4900c2ffb348734ba1c8f9" 210 | dependencies = [ 211 | "js-sys", 212 | "wasm-bindgen", 213 | ] 214 | 215 | [[package]] 216 | name = "gloo-utils" 217 | version = "0.1.4" 218 | source = "registry+https://github.com/rust-lang/crates.io-index" 219 | checksum = "929c53c913bb7a88d75d9dc3e9705f963d8c2b9001510b25ddaf671b9fb7049d" 220 | dependencies = [ 221 | "js-sys", 222 | "wasm-bindgen", 223 | "web-sys", 224 | ] 225 | 226 | [[package]] 227 | name = "hashbrown" 228 | version = "0.12.1" 229 | source = "registry+https://github.com/rust-lang/crates.io-index" 230 | checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3" 231 | 232 | [[package]] 233 | name = "indexmap" 234 | version = "1.9.1" 235 | source = "registry+https://github.com/rust-lang/crates.io-index" 236 | checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" 237 | dependencies = [ 238 | "autocfg", 239 | "hashbrown", 240 | ] 241 | 242 | [[package]] 243 | name = "itoa" 244 | version = "1.0.2" 245 | source = "registry+https://github.com/rust-lang/crates.io-index" 246 | checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" 247 | 248 | [[package]] 249 | name = "js-sys" 250 | version = "0.3.58" 251 | source = "registry+https://github.com/rust-lang/crates.io-index" 252 | checksum = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27" 253 | dependencies = [ 254 | "wasm-bindgen", 255 | ] 256 | 257 | [[package]] 258 | name = "lazy_static" 259 | version = "1.4.0" 260 | source = "registry+https://github.com/rust-lang/crates.io-index" 261 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 262 | 263 | [[package]] 264 | name = "libc" 265 | version = "0.2.126" 266 | source = "registry+https://github.com/rust-lang/crates.io-index" 267 | checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" 268 | 269 | [[package]] 270 | name = "log" 271 | version = "0.4.17" 272 | source = "registry+https://github.com/rust-lang/crates.io-index" 273 | checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" 274 | dependencies = [ 275 | "cfg-if", 276 | ] 277 | 278 | [[package]] 279 | name = "ppv-lite86" 280 | version = "0.2.16" 281 | source = "registry+https://github.com/rust-lang/crates.io-index" 282 | checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" 283 | 284 | [[package]] 285 | name = "proc-macro-error" 286 | version = "1.0.4" 287 | source = "registry+https://github.com/rust-lang/crates.io-index" 288 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 289 | dependencies = [ 290 | "proc-macro-error-attr", 291 | "proc-macro2", 292 | "quote", 293 | "syn", 294 | "version_check", 295 | ] 296 | 297 | [[package]] 298 | name = "proc-macro-error-attr" 299 | version = "1.0.4" 300 | source = "registry+https://github.com/rust-lang/crates.io-index" 301 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 302 | dependencies = [ 303 | "proc-macro2", 304 | "quote", 305 | "version_check", 306 | ] 307 | 308 | [[package]] 309 | name = "proc-macro2" 310 | version = "1.0.40" 311 | source = "registry+https://github.com/rust-lang/crates.io-index" 312 | checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" 313 | dependencies = [ 314 | "unicode-ident", 315 | ] 316 | 317 | [[package]] 318 | name = "quote" 319 | version = "1.0.20" 320 | source = "registry+https://github.com/rust-lang/crates.io-index" 321 | checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" 322 | dependencies = [ 323 | "proc-macro2", 324 | ] 325 | 326 | [[package]] 327 | name = "rand" 328 | version = "0.8.5" 329 | source = "registry+https://github.com/rust-lang/crates.io-index" 330 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 331 | dependencies = [ 332 | "libc", 333 | "rand_chacha", 334 | "rand_core", 335 | ] 336 | 337 | [[package]] 338 | name = "rand_chacha" 339 | version = "0.3.1" 340 | source = "registry+https://github.com/rust-lang/crates.io-index" 341 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 342 | dependencies = [ 343 | "ppv-lite86", 344 | "rand_core", 345 | ] 346 | 347 | [[package]] 348 | name = "rand_core" 349 | version = "0.6.3" 350 | source = "registry+https://github.com/rust-lang/crates.io-index" 351 | checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" 352 | dependencies = [ 353 | "getrandom", 354 | ] 355 | 356 | [[package]] 357 | name = "ryu" 358 | version = "1.0.10" 359 | source = "registry+https://github.com/rust-lang/crates.io-index" 360 | checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" 361 | 362 | [[package]] 363 | name = "scoped-tls-hkt" 364 | version = "0.1.2" 365 | source = "registry+https://github.com/rust-lang/crates.io-index" 366 | checksum = "c2e9d7eaddb227e8fbaaa71136ae0e1e913ca159b86c7da82f3e8f0044ad3a63" 367 | 368 | [[package]] 369 | name = "serde" 370 | version = "1.0.137" 371 | source = "registry+https://github.com/rust-lang/crates.io-index" 372 | checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" 373 | dependencies = [ 374 | "serde_derive", 375 | ] 376 | 377 | [[package]] 378 | name = "serde_derive" 379 | version = "1.0.137" 380 | source = "registry+https://github.com/rust-lang/crates.io-index" 381 | checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" 382 | dependencies = [ 383 | "proc-macro2", 384 | "quote", 385 | "syn", 386 | ] 387 | 388 | [[package]] 389 | name = "serde_json" 390 | version = "1.0.81" 391 | source = "registry+https://github.com/rust-lang/crates.io-index" 392 | checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" 393 | dependencies = [ 394 | "itoa", 395 | "ryu", 396 | "serde", 397 | ] 398 | 399 | [[package]] 400 | name = "slab" 401 | version = "0.4.6" 402 | source = "registry+https://github.com/rust-lang/crates.io-index" 403 | checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" 404 | 405 | [[package]] 406 | name = "syn" 407 | version = "1.0.98" 408 | source = "registry+https://github.com/rust-lang/crates.io-index" 409 | checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd" 410 | dependencies = [ 411 | "proc-macro2", 412 | "quote", 413 | "unicode-ident", 414 | ] 415 | 416 | [[package]] 417 | name = "thiserror" 418 | version = "1.0.31" 419 | source = "registry+https://github.com/rust-lang/crates.io-index" 420 | checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" 421 | dependencies = [ 422 | "thiserror-impl", 423 | ] 424 | 425 | [[package]] 426 | name = "thiserror-impl" 427 | version = "1.0.31" 428 | source = "registry+https://github.com/rust-lang/crates.io-index" 429 | checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" 430 | dependencies = [ 431 | "proc-macro2", 432 | "quote", 433 | "syn", 434 | ] 435 | 436 | [[package]] 437 | name = "unicode-ident" 438 | version = "1.0.1" 439 | source = "registry+https://github.com/rust-lang/crates.io-index" 440 | checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c" 441 | 442 | [[package]] 443 | name = "version_check" 444 | version = "0.9.4" 445 | source = "registry+https://github.com/rust-lang/crates.io-index" 446 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 447 | 448 | [[package]] 449 | name = "wasi" 450 | version = "0.11.0+wasi-snapshot-preview1" 451 | source = "registry+https://github.com/rust-lang/crates.io-index" 452 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 453 | 454 | [[package]] 455 | name = "wasm-bindgen" 456 | version = "0.2.81" 457 | source = "registry+https://github.com/rust-lang/crates.io-index" 458 | checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994" 459 | dependencies = [ 460 | "cfg-if", 461 | "serde", 462 | "serde_json", 463 | "wasm-bindgen-macro", 464 | ] 465 | 466 | [[package]] 467 | name = "wasm-bindgen-backend" 468 | version = "0.2.81" 469 | source = "registry+https://github.com/rust-lang/crates.io-index" 470 | checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a" 471 | dependencies = [ 472 | "bumpalo", 473 | "lazy_static", 474 | "log", 475 | "proc-macro2", 476 | "quote", 477 | "syn", 478 | "wasm-bindgen-shared", 479 | ] 480 | 481 | [[package]] 482 | name = "wasm-bindgen-futures" 483 | version = "0.4.31" 484 | source = "registry+https://github.com/rust-lang/crates.io-index" 485 | checksum = "de9a9cec1733468a8c657e57fa2413d2ae2c0129b95e87c5b72b8ace4d13f31f" 486 | dependencies = [ 487 | "cfg-if", 488 | "js-sys", 489 | "wasm-bindgen", 490 | "web-sys", 491 | ] 492 | 493 | [[package]] 494 | name = "wasm-bindgen-macro" 495 | version = "0.2.81" 496 | source = "registry+https://github.com/rust-lang/crates.io-index" 497 | checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa" 498 | dependencies = [ 499 | "quote", 500 | "wasm-bindgen-macro-support", 501 | ] 502 | 503 | [[package]] 504 | name = "wasm-bindgen-macro-support" 505 | version = "0.2.81" 506 | source = "registry+https://github.com/rust-lang/crates.io-index" 507 | checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048" 508 | dependencies = [ 509 | "proc-macro2", 510 | "quote", 511 | "syn", 512 | "wasm-bindgen-backend", 513 | "wasm-bindgen-shared", 514 | ] 515 | 516 | [[package]] 517 | name = "wasm-bindgen-shared" 518 | version = "0.2.81" 519 | source = "registry+https://github.com/rust-lang/crates.io-index" 520 | checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be" 521 | 522 | [[package]] 523 | name = "web-sys" 524 | version = "0.3.58" 525 | source = "registry+https://github.com/rust-lang/crates.io-index" 526 | checksum = "2fed94beee57daf8dd7d51f2b15dc2bcde92d7a72304cdf662a4371008b71b90" 527 | dependencies = [ 528 | "js-sys", 529 | "wasm-bindgen", 530 | ] 531 | 532 | [[package]] 533 | name = "yew" 534 | version = "0.19.3" 535 | source = "registry+https://github.com/rust-lang/crates.io-index" 536 | checksum = "2a1ccb53e57d3f7d847338cf5758befa811cabe207df07f543c06f502f9998cd" 537 | dependencies = [ 538 | "console_error_panic_hook", 539 | "gloo 0.4.2", 540 | "gloo-utils", 541 | "indexmap", 542 | "js-sys", 543 | "scoped-tls-hkt", 544 | "slab", 545 | "wasm-bindgen", 546 | "wasm-bindgen-futures", 547 | "web-sys", 548 | "yew-macro", 549 | ] 550 | 551 | [[package]] 552 | name = "yew-macro" 553 | version = "0.19.3" 554 | source = "registry+https://github.com/rust-lang/crates.io-index" 555 | checksum = "5fab79082b556d768d6e21811869c761893f0450e1d550a67892b9bce303b7bb" 556 | dependencies = [ 557 | "boolinator", 558 | "lazy_static", 559 | "proc-macro-error", 560 | "proc-macro2", 561 | "quote", 562 | "syn", 563 | ] 564 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "canvas" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | gloo = "0.3" 10 | gloo-utils = "0.1" 11 | js-sys = "0.3" 12 | yew = "0.19.3" 13 | wasm-bindgen = "0.2" 14 | wasm-bindgen-futures = "0.4.30" 15 | rand = "0.8.4" 16 | getrandom = { version = "0.2", features = ["js"] } 17 | 18 | [dependencies.web-sys] 19 | version = "0.3.58" 20 | features = [ 21 | "Navigator", 22 | "Request", 23 | "RequestInit", 24 | "RequestMode", 25 | "Response", 26 | "Window", 27 | "CanvasRenderingContext2d", 28 | "HtmlCanvasElement", 29 | "ImageData", 30 | "ImageBitmap" 31 | ] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Security Union 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Ww0Xt1mAMy31Ofar0GYu8Oab0v2k0uF1XT_zTt5kPU1M8o58sT5OOXCsSxv3nNGxsG8dG4zI=w1060-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj (1)](https://user-images.githubusercontent.com/1176339/155262320-ce1406f0-d35d-418e-a8b9-60b928cceeb2.jpeg) 2 | 3 | # pixel-rain-with-rust-and-rust 4 | 5 | ![Jun-26-2022 16-22-42](https://user-images.githubusercontent.com/1176339/175844917-48a722d9-9de7-42bb-b807-7a3e3b0b6afe.gif) 6 | 7 | Inspired by https://youtu.be/RCVxXgJ8xSk I created a YEW app that applies a pixel rain effect to an image. 8 | 9 | I used no other frameworks, just the HTML canvas, and a basic particle system all written in Rust. 10 | 11 | Notice how modifying the particle system does not cause the component to refresh thanks to YEW's advanced component lifecycle. 12 | 13 | Let me know what you think! 14 | 15 | # How to run? 16 | 17 | ``` 18 | trunk serve 19 | ``` 20 | 21 | # YouTube Video 22 | 23 | https://youtu.be/NTcvWDQ1mMI 24 | 25 | [![IMAGE ALT TEXT](http://img.youtube.com/vi/NTcvWDQ1mMI/maxresdefault.jpg)](https://www.youtube.com/watch?v=NTcvWDQ1mMI "YouTube video") 26 | 27 | -------------------------------------------------------------------------------- /content/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/security-union/pixel-rain-with-rust-and-rust/e63c6d021eb2eab5e0a5db35733cd4c6dd399921/content/.DS_Store -------------------------------------------------------------------------------- /content/Chili_peppe.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/security-union/pixel-rain-with-rust-and-rust/e63c6d021eb2eab5e0a5db35733cd4c6dd399921/content/Chili_peppe.jpeg -------------------------------------------------------------------------------- /content/Keanu-Reeves.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/security-union/pixel-rain-with-rust-and-rust/e63c6d021eb2eab5e0a5db35733cd4c6dd399921/content/Keanu-Reeves.png -------------------------------------------------------------------------------- /content/MegaMan11.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/security-union/pixel-rain-with-rust-and-rust/e63c6d021eb2eab5e0a5db35733cd4c6dd399921/content/MegaMan11.jpeg -------------------------------------------------------------------------------- /content/Silent-Hill-3.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/security-union/pixel-rain-with-rust-and-rust/e63c6d021eb2eab5e0a5db35733cd4c6dd399921/content/Silent-Hill-3.jpeg -------------------------------------------------------------------------------- /content/mega-man-11.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Mega Man 11 review - Polygon 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 67 | 68 | 69 | 70 | 75 | 76 | 84 | 85 | 86 | 87 | 92 | 93 | 94 | 95 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | clock 243 | menu 244 | more-arrow 245 | no 246 | yes 247 | 248 | 249 |
250 | 262 | 263 | 264 | 267 | 268 | 269 | 270 |
271 |
272 | 273 | 280 | 281 | 282 |
283 |
284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | Key art of Mega Man and Robot Masters from Mega Man 11 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 |
311 | 312 |
313 | 314 |
315 | 316 |
317 |

Filed under:

318 | 319 | 320 | 321 | 329 | 330 | 331 | 332 |
333 | 334 | 335 |

Mega Man 11 review

336 | 337 |

Capcom recaptures the magic of Mega Man in its rock-solid sequel

338 | 339 | 384 | 385 | 386 | 387 |
388 |
389 |
390 | 391 | 392 | 393 | 394 | 395 | Capcom 396 | 397 | 398 | 399 | 400 |
401 |
402 | 403 |
404 |
405 | 406 | 407 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 |
535 |

Mega Man has struggled to find his place in the year 20XX.

536 |

In our current millennium, Capcom has remade his original adventure in the adorable Mega Man: Powered Up, gone achingly retro with the 8-bit style of Mega Man 9 and 10, and repackaged his first eight games as part of an anniversary collection.

537 |

Then there were Capcom’s infamously doomed projects in the 2000s: Mega Man Universe, Mega Man Legends 3 and Maverick Hunter, all of them scrapped mid-development. And in the void of a modernized Mega Man came attempts from creators outside of Capcom, like the second-rate Mighty No. 9, a creation of former Mega Man figurehead Keiji Inafune.

538 |

Now, with Mega Man 11, Capcom seems to have finally figured out how to bring the Blue Bomber into the modern age. Its new game is faithful to the series’ classic gameplay, while adding a few tweaks that make Mega Man feel just fresh enough to revisit, 10 proper sequels in.

539 |

So much about Mega Man 11 supplicates before the franchise’s carved-in-stone formula. Eight rogue Robot Masters under the control of the evil Dr. Wily need vanquishing. Mega Man must take out each renegade bot, acquire their unique ability, move on to the next, and then finally take down Dr. Wily himself. Mega Man can shoot, slide and call upon his robot dog Rush to scoot through levels. There are deadly spike traps, bottomless pits and a mechanized insurrection to put down.

540 |
541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | Mega Man 11 - Mega Man slides under Block Man’s punch in a boss fight 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 |
Mega Man slides under Block Man’s punch in a boss fight.
564 | 565 | 566 | Capcom 567 | 568 |
569 | 570 |
571 | 572 |
573 |

Where Mega Man 11 deviates in its gameplay is with a new system called the Double Gear. In a flashback to Dr. Wily and Mega Man creator Dr. Light’s younger days, we learn that Wily helped develop the Double Gear system, believing it to be the next evolution for robotkind. Light, on the other hand, believed that robot progress lay in artificial intelligence, a disagreement that led to their decadeslong rift.

574 |

In practice, the Double Gear system is one of many ways in which Capcom has made the devilishly hard Mega Man series slightly easier — or, for more skilled players, a new mechanic with which to optimize and perfect speedruns. The Double Gear mechanic comprises the Speed Gear, which lets players briefly slow down time, and the Power Gear, which momentarily boosts our hero’s Mega Buster arm cannon (and other weapons) to deal more damage. In my initial playthrough of Mega Man 11, neither felt absolutely essential to succeeding, but both were helpful contingencies during particularly difficult situations.

575 |

The addition will certainly benefit newcomers, because Mega Man 11 is difficult. I’ve spent hours mastering each stage, making slow but satisfying progress as I memorize enemy placement and boss attack patterns. Some levels and Robot Masters, however, are maddeningly hard on normal, particularly sections of the game with instant kills. More than a few times, a one-hit-kill mechanism, like a column of flame or a screen-sized Wily-built death machine, will chase Mega Man through a level. Making your way through a tricky section only to be steamrolled by one of these pursuing instant death dealers is never fun.

576 |
577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | Mega Man 11 - Mega Man runs from a wall of flame in Torch Man’s stage 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 |
Mega Man runs from a wall of flame in Torch Man’s stage.
600 | 601 | 602 | Capcom 603 | 604 |
605 | 606 |
607 | 608 |
609 |

For the faint of heart, Capcom provides “casual” and “newcomer” settings that make things easier by granting extra or infinite lives, respectively. Dr. Light also offers assistance through an in-game shop where players can buy chips for Mega Man, boosting his arm cannon; extra parts that make it easier to walk on slippery surfaces or reduce knockback; and a cooling system that recharges his Double Gear functions more quickly. Capcom doesn’t make these power-ups feel like you’re cheating the system somehow; they’re presented as bonuses that can help frustrated players overcome Mega Man 11’s robust challenge a bit faster.

610 |

While the Speed Gear initially seems like the more useful half of Mega Man’s new abilities, the Power Gear becomes more instrumental as you defeat more Robot Masters and acquire their special abilities. The Power Gear modifies each ability in fun and additive ways. For example, upon defeating the ice-skating robot Tundra Man, Mega Man will gain the ability to unleash a sub-zero blizzard that creates an icy column of destruction. Flip on the Power Gear, and that blizzard becomes a screen-clearing wintry blast.

611 |

Like the new weapons that Mega Man can steal from them, the new Robot Masters in Mega Man 11 are inventive and inspired. There are some familiar archetypes, like the explosive Blast Man, icy Tundra Man, electrified Fuse Man and fiery Torch Man, but most have characteristics that help differentiate them from similar bosses in previous games. Torch Man, for example, is a camping safety robot, and his outdoorsy, barbecue-inspired level helps him stand out from past fire-based Robot Masters. Other standouts include Bounce Man, whose stage is full of trampolines and bouncy balls, where Mega Man is forced to platform his way through the stage boinging to and fro; and Blast Man, whose stage is wired with explosives, many of which have to be triggered by launching the level’s combustible enemies into them in order to progress.

612 |
613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | Mega Man 11 - Mega Man bounces off a ball to avoid cannon fire in Bounce Man’s stage 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 |
Mega Man bounces off a ball to avoid cannon fire in Bounce Man’s stage.
636 | 637 | 638 | Capcom 639 | 640 |
641 | 642 |
643 | 644 |
645 |

There’s a cleverness and care that seems infused throughout Mega Man 11, and numerous creative touches surprised me as I played. Bounce Man’s rubbery body is flecked with bits of metallic confetti, like a bouncy ball from a toy vending machine. Block Man’s level is inspired by Mayan art and architecture, supporting the robot’s backstory in which he fantasizes about building his own temple. Each of the game’s new Robot Masters is given dozens of catchphrases and punny quips. “Prepare to diode!” Fuse Man will say, appealing to my inner dad joke enthusiast.

646 |

And though it’s been divisive leading to the game’s release, I love Mega Man 11’s lightly cel-shaded visual style. Mega Man and Wily’s robot army look spectacular in 3D, supported by lovely 2D and 3D backgrounds. Classic enemies like the construction hat robot Metall, the bat-shaped Batton and Sniper Joe look authentic to their 8-bit origins.

647 |

Mega Man 11 isn’t a surprising sequel, but it is a respectful one. Capcom has stuck to its well-worn formula, giving a once-great series deserved care and attention, while wisely shying away from retro kitsch this time. Mega Man 11 is a franchise hitting its mark again, and, better still, an investment in the future of the series.

648 |

Mega Man 11 was reviewed using a final “retail” Nintendo Switch download code provided by Capcom. You can find additional information about Polygon’s ethics policy here.

649 | 650 |
651 | 652 | 653 | 654 |
655 | 656 |
657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 |
665 |
666 |
667 | 668 |
669 | 670 | 671 | 672 |
673 |
674 | 675 | 711 | 712 |
713 | 714 |
715 | 734 |
735 | 736 | 737 |
738 |
739 |
740 |
741 | 742 |

743 | Sign up for the 744 | 745 | newsletter 746 | 747 | Sign up for Patch Notes 748 |

749 | 750 |
751 | A weekly roundup of the best things from Polygon 752 |
753 |
754 | 755 |
756 | 800 | 801 |
802 | 803 |
804 | 809 |
810 |
811 |
812 |
813 | 814 | 815 | 883 | 884 |
885 | 936 | 937 | 938 | 969 | 970 | 971 | 972 | 973 | 974 |
975 | 976 |
977 | 978 | 979 | 980 | 981 |
982 | 983 | 984 | 985 | 986 | 987 | 1004 | 1005 | 1006 | 1007 | 1008 | 1009 | 1010 | 1011 | 1017 | 1018 | 1019 | 1020 | 1021 | 1022 | 1023 | 1024 | 1035 | -------------------------------------------------------------------------------- /content/mega-man.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/security-union/pixel-rain-with-rust-and-rust/e63c6d021eb2eab5e0a5db35733cd4c6dd399921/content/mega-man.jpeg -------------------------------------------------------------------------------- /content/mega.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/security-union/pixel-rain-with-rust-and-rust/e63c6d021eb2eab5e0a5db35733cd4c6dd399921/content/mega.jpeg -------------------------------------------------------------------------------- /content/silent-hill-2021.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/security-union/pixel-rain-with-rust-and-rust/e63c6d021eb2eab5e0a5db35733cd4c6dd399921/content/silent-hill-2021.jpeg -------------------------------------------------------------------------------- /content/tiger.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/security-union/pixel-rain-with-rust-and-rust/e63c6d021eb2eab5e0a5db35733cd4c6dd399921/content/tiger.jpeg -------------------------------------------------------------------------------- /content/tiger2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/security-union/pixel-rain-with-rust-and-rust/e63c6d021eb2eab5e0a5db35733cd4c6dd399921/content/tiger2.jpeg -------------------------------------------------------------------------------- /content/woman.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/security-union/pixel-rain-with-rust-and-rust/e63c6d021eb2eab5e0a5db35733cd4c6dd399921/content/woman.jpeg -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | RUST Canvas manipulation 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use gloo::console::log; 2 | use rand::{thread_rng, Rng}; 3 | use wasm_bindgen::{prelude::Closure, JsCast, JsValue}; 4 | use wasm_bindgen_futures::JsFuture; 5 | use web_sys::{window, Blob, ImageBitmap, RequestInit}; 6 | use web_sys::{CanvasRenderingContext2d, HtmlCanvasElement, Request, Response}; 7 | use yew::prelude::*; 8 | pub enum Msg { 9 | FetchOk(ImageBitmap), 10 | FetchFail(SomeError), 11 | Render, 12 | } 13 | 14 | struct Particle { 15 | x: f64, 16 | y: f64, 17 | velocity: f64, 18 | size: f32, 19 | speed: f64, 20 | max_height: usize, 21 | } 22 | 23 | impl Particle { 24 | fn new(width: usize, height: usize) -> Self { 25 | let mut randy = thread_rng(); 26 | let y = 0 as f64; 27 | let x = randy.gen_range(0f64..width as f64); 28 | let velocity = randy.gen_range(0.5..3.0); 29 | let size = randy.gen_range(0.5..1.0); 30 | Self { 31 | x, 32 | y, 33 | velocity, 34 | size, 35 | speed: 0.0, 36 | max_height: height, 37 | } 38 | } 39 | 40 | fn update(&mut self, map: &[Vec<(u8, u8, u8, f64)>]) { 41 | let x = self.x as usize; 42 | let y = self.y as usize; 43 | let (_r, _g, _b, brightness) = map[y][x]; 44 | self.speed = brightness; 45 | let delta_y = 2.0 - self.speed + self.velocity; 46 | self.y += delta_y; 47 | if self.y >= self.max_height as f64 { 48 | self.y = 0f64; 49 | } 50 | } 51 | 52 | fn render(&self, ctx: &CanvasRenderingContext2d, map: &[Vec<(u8, u8, u8, f64)>]) { 53 | ctx.begin_path(); 54 | let x = self.x as usize; 55 | let y = self.y as usize; 56 | let (r, g, b, _b) = map[y][x]; 57 | let js_rgb = format!("rgb({r}, {g}, {b})", r = r, g = g, b = b); 58 | ctx.set_fill_style(&JsValue::from_str(js_rgb.as_ref())); 59 | ctx.arc( 60 | self.x, 61 | self.y, 62 | self.size.into(), 63 | 0.0, 64 | std::f64::consts::PI * 2.0, 65 | ) 66 | .unwrap(); 67 | ctx.fill(); 68 | } 69 | } 70 | 71 | pub struct SomeError { 72 | err: JsValue, 73 | } 74 | 75 | impl From for SomeError { 76 | fn from(v: JsValue) -> Self { 77 | Self { err: v } 78 | } 79 | } 80 | 81 | pub async fn fetch_image(file_path: &str) -> Result { 82 | let mut opts = RequestInit::new(); 83 | opts.method("GET"); 84 | let request = Request::new_with_str_and_init(file_path, &opts)?; 85 | let window = window().unwrap(); 86 | let resp_js_value = JsFuture::from(window.fetch_with_request(&request)).await?; 87 | let resp: Response = resp_js_value.dyn_into()?; 88 | let blob: Blob = JsFuture::from(resp.blob()?).await?.dyn_into()?; 89 | 90 | let image_bitmap_prom = window.create_image_bitmap_with_blob(&blob)?; 91 | Ok(JsFuture::from(image_bitmap_prom).await?.dyn_into()?) 92 | } 93 | 94 | pub fn relative_brightness(r: f64, g: f64, b: f64) -> f64 { 95 | js_sys::Math::sqrt((r * r * 0.229) + (g * g * 0.587) + (b * b * 0.114)) / 100.0 96 | } 97 | struct AnimationCanvas { 98 | canvas: NodeRef, 99 | particles: Vec, 100 | callback: Closure, 101 | brightness_map: Vec>, 102 | } 103 | 104 | impl Component for AnimationCanvas { 105 | type Message = Msg; 106 | type Properties = (); 107 | fn create(ctx: &Context) -> Self { 108 | ctx.link().send_future(async { 109 | match fetch_image("content/woman.jpeg").await { 110 | Ok(image) => Msg::FetchOk(image), 111 | Err(err) => Msg::FetchFail(err), 112 | } 113 | }); 114 | let comp_ctx = ctx.link().clone(); 115 | let callback = 116 | Closure::wrap(Box::new(move || comp_ctx.send_message(Msg::Render)) as Box); 117 | Self { 118 | canvas: NodeRef::default(), 119 | particles: vec![], 120 | callback, 121 | brightness_map: vec![], 122 | } 123 | } 124 | 125 | fn update(&mut self, ctx: &Context, msg: Self::Message) -> bool { 126 | match msg { 127 | Msg::FetchOk(image) => { 128 | let width: usize = image.width().try_into().unwrap(); 129 | let height: usize = image.height().try_into().unwrap(); 130 | let canvas: HtmlCanvasElement = self.canvas.cast().unwrap(); 131 | canvas.set_width(width.try_into().unwrap()); 132 | canvas.set_height(height.try_into().unwrap()); 133 | self.particles = (0..10000).map(|_| Particle::new(width, height)).collect(); 134 | let ctxx: CanvasRenderingContext2d = 135 | canvas.get_context("2d").unwrap().unwrap().unchecked_into(); 136 | 137 | ctxx.draw_image_with_image_bitmap(&image, 0.0, 0.0).unwrap(); 138 | let image_data = ctxx 139 | .get_image_data(0.0, 0.0, width as f64, height as f64) 140 | .unwrap(); 141 | ctxx.clear_rect(0.0, 0.0, width as f64, height as f64); 142 | let buffer = (*image_data.data()).clone(); 143 | self.brightness_map = Vec::new(); 144 | for y in 0usize..height { 145 | let mut brightness_row = Vec::new(); 146 | brightness_row.reserve(width); 147 | for x in 0usize..width { 148 | let red = buffer[(y * 4usize * width) + (x * 4)]; 149 | let green = buffer[(y * 4usize * width) + (x * 4 + 1)]; 150 | let blue = buffer[(y * 4usize * width) + (x * 4 + 2)]; 151 | let brightness = relative_brightness(red as f64, green as f64, blue as f64); 152 | brightness_row.push((red, green, blue, brightness)); 153 | } 154 | self.brightness_map.push(brightness_row); 155 | } 156 | 157 | ctx.link().send_message(Msg::Render); 158 | true 159 | } 160 | Msg::FetchFail(e) => { 161 | log!(e.err); 162 | true 163 | } 164 | Msg::Render => { 165 | self.render(); 166 | false 167 | } 168 | } 169 | } 170 | 171 | fn view(&self, _ctx: &Context) -> Html { 172 | html! { 173 |
174 | 177 | 178 |
179 | } 180 | } 181 | } 182 | 183 | impl AnimationCanvas { 184 | fn render(&mut self) { 185 | let canvas: HtmlCanvasElement = self.canvas.cast().unwrap(); 186 | let ctx: CanvasRenderingContext2d = 187 | canvas.get_context("2d").unwrap().unwrap().unchecked_into(); 188 | ctx.set_global_alpha(0.05); 189 | ctx.set_fill_style(&JsValue::from("rgb(0,0,0)")); 190 | ctx.fill_rect(0.0, 0.0, canvas.width().into(), canvas.height().into()); 191 | ctx.set_global_alpha(0.5); 192 | let map = &self.brightness_map; 193 | self.particles.iter_mut().for_each(|particle| { 194 | particle.update(map); 195 | let x = particle.x as usize; 196 | let y = particle.y as usize; 197 | let (_r, _g, _b, brightness) = map[y][x]; 198 | ctx.set_global_alpha(brightness * 0.3); // higher velocity higher alpha 199 | particle.render(&ctx, map); 200 | }); 201 | window() 202 | .unwrap() 203 | .request_animation_frame(self.callback.as_ref().unchecked_ref()) 204 | .unwrap(); 205 | } 206 | } 207 | 208 | #[function_component(App)] 209 | fn app_body() -> Html { 210 | html! { 211 | <> 212 | 213 | 214 | } 215 | } 216 | 217 | fn main() { 218 | yew::start_app::(); 219 | } 220 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | html { 2 | background-color: black; 3 | } 4 | 5 | canvas { 6 | width: 100%; 7 | } --------------------------------------------------------------------------------