10 Commits

Author SHA1 Message Date
M1n-0
11d47caf1e fix merge 2026-03-31 13:56:58 +02:00
M1n-0
40fe732caa fix merge branch 2026-03-31 13:52:42 +02:00
M1n-0
15b585df02 testfile 2026-03-31 13:29:29 +02:00
M1n-0
f6347feff1 testfile 2026-03-31 13:29:29 +02:00
GreyRav
c7f0e747b1 fix : change port 2026-03-31 13:29:29 +02:00
GreyRav
1d28a75529 fix : html + css display 2026-03-31 13:29:29 +02:00
Sysy's
ecbf7a5b34 Add hero page HTML and responsive CSS
Add a new landing view and stylesheet for MirrorGame. Creates web/templates/view/index.html (hero layout with image, play button, and left/right ad banner iframes) and web/assets/css/index.css (CSS variables, Inter font import, hero layout, responsive breakpoints, and .hero-play-button styles). Provides responsive behavior and positioning for ads and hero components.
2026-03-31 13:29:29 +02:00
GreyRav
46660bd921 fix : path to index.html 2026-03-31 13:29:29 +02:00
Sysy's
9b1e2ccf6d Use root-relative path for index.css
Update stylesheet link in view template from '../../assets/css/index.css' to '/assets/css/index.css' so the CSS resolves from the site root. This prevents broken styling when the page is accessed from nested routes or different template contexts.
2026-03-30 15:20:49 +02:00
Sysy's
68421a71df Add hero page HTML and responsive CSS
Add a new landing view and stylesheet for MirrorGame. Creates web/templates/view/index.html (hero layout with image, play button, and left/right ad banner iframes) and web/assets/css/index.css (CSS variables, Inter font import, hero layout, responsive breakpoints, and .hero-play-button styles). Provides responsive behavior and positioning for ads and hero components.
2026-03-30 15:09:09 +02:00
14 changed files with 456 additions and 632 deletions

49
backend/Cargo.lock generated
View File

@@ -91,6 +91,7 @@ dependencies = [
"axum-server",
"serde",
"tokio",
"tower-http",
"tracing-subscriber",
]
@@ -256,6 +257,12 @@ dependencies = [
"pin-project-lite",
]
[[package]]
name = "http-range-header"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9171a2ea8a68358193d15dd5d70c1c10a2afc3e7e4c5bc92bc9f025cebd7359c"
[[package]]
name = "httparse"
version = "1.10.1"
@@ -366,6 +373,16 @@ version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
[[package]]
name = "mime_guess"
version = "2.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e"
dependencies = [
"mime",
"unicase",
]
[[package]]
name = "mio"
version = "1.2.0"
@@ -661,6 +678,32 @@ dependencies = [
"tracing",
]
[[package]]
name = "tower-http"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8"
dependencies = [
"bitflags",
"bytes",
"futures-core",
"futures-util",
"http",
"http-body",
"http-body-util",
"http-range-header",
"httpdate",
"mime",
"mime_guess",
"percent-encoding",
"pin-project-lite",
"tokio",
"tokio-util",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "tower-layer"
version = "0.3.3"
@@ -719,6 +762,12 @@ dependencies = [
"tracing-log",
]
[[package]]
name = "unicase"
version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142"
[[package]]
name = "unicode-ident"
version = "1.0.24"

View File

@@ -9,3 +9,4 @@ axum-server = "0.8.0"
serde = "1.0.228"
tokio = { version = "1.50.0", features = ["full"] }
tracing-subscriber = "0.3.23"
tower-http = { version = "0.6", features = ["fs"] }

View File

@@ -1,14 +0,0 @@
struct Laser {
color : array,
}
struct Mirror {
color : array,
x : int,
y : int,
}
struct Spawn {
x : int,
y : int,
}

View File

@@ -1,14 +1,34 @@
use axum::{routing::get, Router};
use axum::{Router, response::Html, routing::get};
use std::net::SocketAddr;
use std::path::Path;
use tokio::fs::File;
use tokio::io::{self, AsyncReadExt};
use tower_http::services::ServeDir;
#[tokio::main]
async fn main() {
let app = Router::new().route("/", get(|| async { "Hello, world!" }));
let app = Router::new()
.route("/", get(handler))
.nest_service("/assets", ServeDir::new("../web/assets"));
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
let addr = SocketAddr::from(([127, 0, 0, 1], 3500));
println!("listening on {}", addr);
axum_server::bind(addr)
.serve(app.into_make_service())
.await
.unwrap();
}
async fn handler() -> Html<String> {
let html_content = read_html_from_file("../web/templates/view/index.html")
.await
.unwrap_or_else(|_| "<h1>Error loading HTML file</h1>".to_string());
Html(html_content)
}
async fn read_html_from_file<P: AsRef<Path>>(path: P) -> io::Result<String> {
let mut file = File::open(path).await?;
let mut contents = String::new();
file.read_to_string(&mut contents).await?;
Ok(contents)
}

View File

@@ -20,71 +20,6 @@ body {
user-select: none;
}
.level-menu-shell {
position: fixed;
top: 24px;
right: 24px;
z-index: 1100;
display: flex;
align-items: flex-start;
gap: 10px;
}
.level-menu-toggle {
border: none;
border-radius: 999px;
background: #223;
color: #fff;
padding: 12px 18px;
font-size: 0.95rem;
font-weight: 700;
cursor: pointer;
box-shadow: 0 8px 20px rgba(34, 51, 68, 0.18);
}
.level-menu-panel {
min-width: 180px;
background: rgba(255, 255, 255, 0.96);
border-radius: 18px;
padding: 14px;
box-shadow: 0 18px 40px rgba(34, 51, 68, 0.18);
border: 1px solid rgba(34, 51, 68, 0.08);
}
.level-menu-panel h2 {
font-size: 0.95rem;
color: #223;
margin-bottom: 10px;
}
.level-menu-list {
display: flex;
flex-direction: column;
gap: 8px;
}
.level-menu-item {
border: none;
border-radius: 10px;
padding: 10px 12px;
text-align: left;
background: #dfe5f8;
color: #223;
font-weight: 700;
cursor: pointer;
}
.level-menu-item.is-current {
background: #223;
color: #fff;
}
.level-menu-item:disabled {
background: #eceff7;
color: #8a92a3;
cursor: not-allowed;
}
main {
display: flex;
flex-direction: column;
@@ -173,7 +108,7 @@ main {
.laser {
background-color: #DADEEF;
background-image: url("/web/assets/img/tiles/Laser.svg");
background-image: url("../img/tiles/Laser.svg");
background-size: 80%;
background-repeat: no-repeat;
background-position: center;
@@ -182,7 +117,7 @@ main {
.colored-laser {
background-color: #DADEEF;
background-image: url("/web/assets/img/tiles/Prisme.svg");
background-image: url("../img/tiles/Prisme.svg");
background-size: 80%;
background-repeat: no-repeat;
background-position: center;
@@ -202,31 +137,15 @@ main {
.wall {
background-color: #DADEEF;
background-image: url("/web/assets/img/tiles/Tuile.svg");
background-image: url("../img/tiles/Tuile.svg");
background-size: 100%;
background-repeat: no-repeat;
background-position: center;
}
.wall-semi-angle {
background-color: #DADEEF;
background-image: url("/web/assets/img/tiles/BottomLeft.svg");
background-size: 100%;
background-repeat: no-repeat;
background-position: center;
}
.horizontal-semi {
background-color: #DADEEF;
background-image: url("/web/assets/img/tiles/HorizontaleSemi.svg");
background-size: 100%;
background-repeat: no-repeat;
background-position: bottom;
}
.captor {
background-color: #DADEEF;
background-image: url("/web/assets/img/tiles/Capteur-1.svg");
background-image: url("../img/tiles/Capteur-1.svg");
background-size: 100%;
background-repeat: no-repeat;
background-position: center;
@@ -235,24 +154,7 @@ main {
.captor-turn {
background-color: #DADEEF;
background-image: url("/web/assets/img/tiles/Capteur-2.svg");
background-size: 100%;
background-repeat: no-repeat;
background-position: center;
}
.captor-turn-reverse {
background-color: #DADEEF;
background-image: url("/web/assets/img/tiles/Capteur-2.svg");
background-size: 100%;
background-repeat: no-repeat;
background-position: center;
transform: rotate(180deg);
}
.captor-turn-horizontale2 {
background-color: #DADEEF;
background-image: url("/web/assets/img/tiles/Capteur-1.svg");
background-image: url("../img/tiles/Capteur-2.svg");
background-size: 100%;
background-repeat: no-repeat;
background-position: center;
@@ -260,55 +162,31 @@ main {
.cable {
background-color: #DADEEF;
background-image: url("/web/assets/img/tiles/CableH.svg");
background-size: 100%;
background-repeat: no-repeat;
background-position: center;
}
.cable-turn {
background-color: #DADEEF;
background-image: url("/web/assets/img/tiles/CableBottomLeft.svg");
background-image: url("../img/tiles/CableV.svg");
background-size: 100%;
background-repeat: no-repeat;
background-position: center;
transform: rotate(90deg);
}
.cable-vertical {
background-color: #DADEEF;
background-image: url("/web/assets/img/tiles/CableV.svg");
background-image: url("../img/tiles/CableV.svg");
background-size: 100%;
background-repeat: no-repeat;
background-position: center;
}
.cable-turn-horizontale {
background-color: #DADEEF;
background-image: url("/web/assets/img/tiles/CableTopLeft.svg");
background-size: 100%;
background-repeat: no-repeat;
background-position: center;
}
.cable-turn-horizontale2 {
background-color: #DADEEF;
background-image: url("/web/assets/img/tiles/CableTopLeft.svg");
background-size: 100%;
background-repeat: no-repeat;
background-position: center;
transform: rotate(180deg);
}
.door {
background-color: #DADEEF;
background-image: url("/web/assets/img/tiles/WoodenDoor.svg");
background-image: url("../img/tiles/WoodenDoor.svg");
background-size: contain;
background-repeat: no-repeat;
background-position: end;
}
.door-open {
background-image: url("/web/assets/img/tiles/WoodenDoor_openned.svg");
background-image: url("../img/tiles/WoodenDoor_openned.svg");
background-size: contain;
background-repeat: no-repeat;
background-position: end;
@@ -316,7 +194,7 @@ main {
.button {
background-color: #DADEEF;
background-image: url("/web/assets/img/tiles/ButtonComplete.svg"), url("/web/assets/img/tiles/Tuile.svg");
background-image: url("../img/tiles/ButtonComplete.svg"), url("../img/tiles/Tuile.svg");
background-size: 100% 100%;
background-repeat: no-repeat;
background-position: center;
@@ -324,7 +202,7 @@ main {
.button-2 {
background-color: #DADEEF;
background-image: url("/web/assets/img/tiles/ButtonQuarter.svg"), url("/web/assets/img/tiles/Tuile.svg");
background-image: url("../img/tiles/ButtonQuarter.svg"), url("../img/tiles/Tuile.svg");
background-size: 100% 100%;
background-repeat: no-repeat;
background-position: center;
@@ -332,7 +210,7 @@ main {
.button-rotator {
background-color: #DADEEF;
background-image: url("/web/assets/img/tiles/ButtonProfile.svg"), url("/web/assets/img/tiles/Tuile.svg");
background-image: url("../img/tiles/ButtonProfile.svg"), url("../img/tiles/Tuile.svg");
background-size: 100% 100%;
background-repeat: no-repeat;
background-position: center;
@@ -344,7 +222,7 @@ main {
.target {
background-color: #DADEEF;
background-image: url("/web/assets/img/tiles/Trigger.svg");
background-image: url("../img/tiles/Trigger.svg");
background-size: 80%;
background-repeat: no-repeat;
background-position: center;
@@ -352,7 +230,7 @@ main {
.demi-wall-corner-up-left {
background-color: #DADEEF;
background-image: url("/web/assets/img/tiles/TopLeft.svg");
background-image: url("../img/tiles/TopLeft.svg");
background-size: 100%;
background-repeat: no-repeat;
background-position: center;
@@ -360,7 +238,7 @@ main {
.demi-wall-corner-up-right {
background-color: #DADEEF;
background-image: url("/web/assets/img/tiles/TopRight.svg");
background-image: url("../img/tiles/TopRight.svg");
background-size: 100%;
background-repeat: no-repeat;
background-position: center;
@@ -368,7 +246,7 @@ main {
.demi-wall-corner-down-left {
background-color: #DADEEF;
background-image: url("/web/assets/img/tiles/BottomLeftAngle.svg");
background-image: url("../img/tiles/BottomLeft.svg");
background-size: 100%;
background-repeat: no-repeat;
background-position: center;
@@ -376,7 +254,7 @@ main {
.demi-wall-corner-down-right {
background-color: #DADEEF;
background-image: url("/web/assets/img/tiles/BottomRightAngle.svg");
background-image: url("../img/tiles/BottomRight.svg");
background-size: 100%;
background-repeat: no-repeat;
background-position: center;
@@ -463,24 +341,6 @@ main {
font-weight: bold;
}
.glass-item:disabled {
cursor: not-allowed;
opacity: 0.45;
}
.glass-item-label {
position: absolute;
right: 4px;
bottom: 3px;
z-index: 2;
font-size: 0.7rem;
font-weight: 700;
color: #223;
background: rgba(255, 255, 255, 0.88);
padding: 1px 5px;
border-radius: 999px;
}
.glass-item::after,
.cell-glass::after {
content: "";

244
web/assets/css/index.css Normal file
View File

@@ -0,0 +1,244 @@
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap');
* {
--clr-light-a0: #ffffff;
--clr-light-a10: #f4f4f4;
--clr-light-a20: #e0e0e0;
--clr-light-a30: #c2c2c2;
--clr-light-a40: #a3a3a3;
--clr-light-a50: #858585;
--clr-dark: #000000;
--clr-surface-a0: #FFF6E5;
--clr-surface-a10: #f7f7f7;
--clr-surface-a20: #DADEEF;
--clr-surface-a30: #e0e0e0;
--clr-surface-a40: #d1d1d1;
--clr-surface-a50: #c2c2c2;
box-sizing: border-box;
}
html {
font-size: 100%;
}
body {
background-color: var(--clr-surface-a0);
font-family: 'Inter', sans-serif;
margin: 0;
padding: 0;
}
.hero {
position: relative;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
min-height: 100vh;
gap: 3rem;
padding: 2rem clamp(1rem, 4vw, 3rem);
box-sizing: border-box;
background: var(--clr-surface-a10);
}
.adsbanner {
position: absolute;
top: 50%;
left: clamp(0.75rem, 3vw, 2.5rem);
transform: translateY(-50%);
z-index: 5;
width: clamp(160px, 22vw, 300px);
aspect-ratio: 9 / 16;
box-shadow: 0 18px 40px rgba(0,0,0,0.18);
}
.adsbanner.is-hidden {
display: none;
}
.leftadsbanner {
position: absolute;
top: 50%;
right: clamp(0.75rem, 3vw, 2.5rem);
transform: translateY(-50%);
z-index: 5;
width: clamp(160px, 22vw, 300px);
aspect-ratio: 9 / 16;
}
.hero-content {
max-width: 90vw;
text-align: left;
display: flex;
flex-direction: column;
align-items: center;
background: var(--clr-surface-a20);
border-radius: 1.5rem;
padding: 2rem clamp(2rem, 8vw, 10rem);
box-shadow: 0px 0px 27px 14px rgba(0,0,0,0.2);
}
.hero-content-text {
width: 100%;
}
.hero h1 {
color: var(--clr-dark);
font-size: clamp(2.5rem, 7vw, 4rem);
margin: 0 0 1rem 0;
line-height: 1.1;
word-break: break-word;
text-shadow: none;
}
.hero-content button {
margin-top: 2rem;
align-self: center;
}
.hero img {
max-width: 400px;
width: 35vw;
min-width: 180px;
height: auto;
border-radius: 1.5rem;
box-shadow: 0 6px 32px rgba(0,0,0,.10);
flex-shrink: 1;
background: var(--clr-surface-a0);
}
/* --- RESPONSIVE HERO-PLAY-BUTTON FIXES --- */
@media (max-width: 900px) {
.hero {
flex-direction: column;
text-align: center;
gap: 2rem;
padding: 1.5rem;
}
.hero-content {
max-width: 100vw;
text-align: center;
padding: 2rem;
}
.hero-content {
align-items: center;
}
.adsbanner {
left: 1rem;
width: clamp(130px, 24vw, 220px);
}
.leftadsbanner {
right: 1rem;
width: clamp(130px, 24vw, 220px);
}
.hero img {
max-width: 70vw;
min-width: 0;
}
.hero-play-button {
padding: 1rem 4vw;
font-size: 1.1rem;
min-width: min(220px, 70vw);
max-width: 90vw;
}
.hero-play-button svg {
width: 2em;
height: 1em;
min-width: 1.25em;
min-height: 1em;
margin-right: 0.5em;
flex-shrink: 0;
}
}
@media (max-width: 600px) {
.hero {
min-height: 70vh;
padding: 0.5rem;
}
.hero-content {
padding: 1.5rem;
}
.hero h1 {
font-size: clamp(2rem, 9vw, 2.5rem);
}
.hero p {
font-size: clamp(1rem, 5vw, 1.15rem);
}
.adsbanner {
top: 1rem;
left: 0.75rem;
transform: none;
width: clamp(110px, 30vw, 170px);
border-radius: 1rem;
}
.leftadsbanner {
right: 0.75rem;
width: clamp(110px, 30vw, 170px);
border-radius: 1rem;
}
.hero img {
max-width: 100%;
border-radius: 1rem;
box-shadow: 0 2px 12px rgba(0,0,0,.07);
}
.hero-play-button {
padding: 0.85rem 3vw;
min-width: min(120px, 92vw);
max-width: 96vw;
font-size: 1rem;
}
.hero-play-button svg {
width: 1.3em;
height: 1em;
min-width: 1em;
min-height: 1em;
margin-right: 0.45em;
flex-shrink: 0;
}
}
.hero-play-button {
font-family: inherit;
font-size: 20px;
background: #8ea3fd;
color: white;
padding: 1rem 10rem;
display: flex;
align-items: center;
justify-content: center; /* Ensure SVG/button content is horizontally centered */
border: none;
border-radius: 50px;
overflow: hidden;
transition: all 0.2s;
cursor: pointer;
box-shadow: 0 2px 8px rgba(30, 80, 255, 0.10);
/* Button grows/shrinks with container at low widths */
width: 100%;
max-width: 500px;
min-width: 180px;
box-sizing: border-box;
}
.hero-play-button:hover {
background: #7286e0;
transform: translateY(-2px);
}
.hero-play-button:active {
transform: scale(0.95);
}
.hero-play-button svg {
width: 2em;
height: 1em;
min-width: 1.2em;
min-height: 1em;
margin-right: 0.6em;
color: var(--clr-surface-a0);
flex-shrink: 0;
flex-grow: 0;
display: inline-block;
vertical-align: middle;
}

View File

@@ -1,19 +1,17 @@
<svg width="100" height="100" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1 99L1 1.61816L99 50.6182V99L1 99Z" fill="url(#paint0_linear_35_19)" stroke="url(#paint1_linear_35_19)" stroke-width="2"/>
<path d="M1 99L1 2.41406L97.5859 99L1 99Z" fill="url(#paint0_linear_17_89)" stroke="url(#paint1_linear_17_89)" stroke-width="2"/>
<circle cx="5.5" cy="94.5" r="1.5" transform="rotate(-180 5.5 94.5)" fill="#4A4A4A"/>
<circle cx="5.5" cy="94.5" r="1" transform="rotate(-180 5.5 94.5)" fill="#898989"/>
<circle cx="4.5" cy="8.5" r="1.5" transform="rotate(-180 4.5 8.5)" fill="#4A4A4A"/>
<circle cx="4.5" cy="8.5" r="1" transform="rotate(-180 4.5 8.5)" fill="#898989"/>
<circle cx="94.5" cy="94.5" r="1.5" transform="rotate(-180 94.5 94.5)" fill="#4A4A4A"/>
<circle cx="94.5" cy="94.5" r="1" transform="rotate(-180 94.5 94.5)" fill="#898989"/>
<circle cx="94.5" cy="53.5" r="1.5" transform="rotate(-180 94.5 53.5)" fill="#4A4A4A"/>
<circle cx="94.5" cy="53.5" r="1" transform="rotate(-180 94.5 53.5)" fill="#898989"/>
<circle cx="5.5" cy="13.5" r="1.5" transform="rotate(-180 5.5 13.5)" fill="#4A4A4A"/>
<circle cx="5.5" cy="13.5" r="1" transform="rotate(-180 5.5 13.5)" fill="#898989"/>
<circle cx="86.5" cy="94.5" r="1.5" transform="rotate(-180 86.5 94.5)" fill="#4A4A4A"/>
<circle cx="86.5" cy="94.5" r="1" transform="rotate(-180 86.5 94.5)" fill="#898989"/>
<defs>
<linearGradient id="paint0_linear_35_19" x1="0" y1="0" x2="40" y2="80" gradientUnits="userSpaceOnUse">
<linearGradient id="paint0_linear_17_89" x1="0" y1="0" x2="100" y2="100" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="#747474"/>
</linearGradient>
<linearGradient id="paint1_linear_35_19" x1="100" y1="50" x2="60" y2="-30" gradientUnits="userSpaceOnUse">
<linearGradient id="paint1_linear_17_89" x1="100" y1="100" x2="0" y2="0" gradientUnits="userSpaceOnUse">
<stop stop-color="#A8A8A8"/>
<stop offset="1" stop-color="#848484"/>
</linearGradient>

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -1,19 +0,0 @@
<svg width="100" height="100" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1 99L1 2.41406L97.5859 99L1 99Z" fill="url(#paint0_linear_17_89)" stroke="url(#paint1_linear_17_89)" stroke-width="2"/>
<circle cx="5.5" cy="94.5" r="1.5" transform="rotate(-180 5.5 94.5)" fill="#4A4A4A"/>
<circle cx="5.5" cy="94.5" r="1" transform="rotate(-180 5.5 94.5)" fill="#898989"/>
<circle cx="5.5" cy="13.5" r="1.5" transform="rotate(-180 5.5 13.5)" fill="#4A4A4A"/>
<circle cx="5.5" cy="13.5" r="1" transform="rotate(-180 5.5 13.5)" fill="#898989"/>
<circle cx="86.5" cy="94.5" r="1.5" transform="rotate(-180 86.5 94.5)" fill="#4A4A4A"/>
<circle cx="86.5" cy="94.5" r="1" transform="rotate(-180 86.5 94.5)" fill="#898989"/>
<defs>
<linearGradient id="paint0_linear_17_89" x1="0" y1="0" x2="100" y2="100" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="#747474"/>
</linearGradient>
<linearGradient id="paint1_linear_17_89" x1="100" y1="100" x2="0" y2="0" gradientUnits="userSpaceOnUse">
<stop stop-color="#A8A8A8"/>
<stop offset="1" stop-color="#848484"/>
</linearGradient>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -1,19 +1,17 @@
<svg width="100" height="100" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M99 99H1V50.6182L99 1.61816V99Z" fill="url(#paint0_linear_35_30)" stroke="url(#paint1_linear_35_30)" stroke-width="2"/>
<path d="M99 99H2.41406L99 2.41406V99Z" fill="url(#paint0_linear_19_190)" stroke="url(#paint1_linear_19_190)" stroke-width="2"/>
<circle cx="94.5" cy="94.5" r="1.5" transform="rotate(90 94.5 94.5)" fill="#4A4A4A"/>
<circle cx="94.5" cy="94.5" r="1" transform="rotate(90 94.5 94.5)" fill="#898989"/>
<circle cx="5.5" cy="94.5" r="1.5" transform="rotate(90 5.5 94.5)" fill="#4A4A4A"/>
<circle cx="5.5" cy="94.5" r="1" transform="rotate(90 5.5 94.5)" fill="#898989"/>
<circle cx="5.5" cy="53.5" r="1.5" transform="rotate(90 5.5 53.5)" fill="#4A4A4A"/>
<circle cx="5.5" cy="53.5" r="1" transform="rotate(90 5.5 53.5)" fill="#898989"/>
<circle cx="94.5" cy="9.5" r="1.5" transform="rotate(90 94.5 9.5)" fill="#4A4A4A"/>
<circle cx="94.5" cy="9.5" r="1" transform="rotate(90 94.5 9.5)" fill="#898989"/>
<circle cx="13.5" cy="94.5" r="1.5" transform="rotate(90 13.5 94.5)" fill="#4A4A4A"/>
<circle cx="13.5" cy="94.5" r="1" transform="rotate(90 13.5 94.5)" fill="#898989"/>
<circle cx="94.5" cy="13.5" r="1.5" transform="rotate(90 94.5 13.5)" fill="#4A4A4A"/>
<circle cx="94.5" cy="13.5" r="1" transform="rotate(90 94.5 13.5)" fill="#898989"/>
<defs>
<linearGradient id="paint0_linear_35_30" x1="8.9049e-06" y1="1.50801e-06" x2="40" y2="80" gradientUnits="userSpaceOnUse">
<linearGradient id="paint0_linear_19_190" x1="0" y1="0" x2="100" y2="100" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="#747474"/>
</linearGradient>
<linearGradient id="paint1_linear_35_30" x1="100" y1="50" x2="60" y2="-30" gradientUnits="userSpaceOnUse">
<linearGradient id="paint1_linear_19_190" x1="100" y1="100" x2="0" y2="0" gradientUnits="userSpaceOnUse">
<stop stop-color="#A8A8A8"/>
<stop offset="1" stop-color="#848484"/>
</linearGradient>

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -1,19 +0,0 @@
<svg width="100" height="100" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M99 99H2.41406L99 2.41406V99Z" fill="url(#paint0_linear_19_190)" stroke="url(#paint1_linear_19_190)" stroke-width="2"/>
<circle cx="94.5" cy="94.5" r="1.5" transform="rotate(90 94.5 94.5)" fill="#4A4A4A"/>
<circle cx="94.5" cy="94.5" r="1" transform="rotate(90 94.5 94.5)" fill="#898989"/>
<circle cx="13.5" cy="94.5" r="1.5" transform="rotate(90 13.5 94.5)" fill="#4A4A4A"/>
<circle cx="13.5" cy="94.5" r="1" transform="rotate(90 13.5 94.5)" fill="#898989"/>
<circle cx="94.5" cy="13.5" r="1.5" transform="rotate(90 94.5 13.5)" fill="#4A4A4A"/>
<circle cx="94.5" cy="13.5" r="1" transform="rotate(90 94.5 13.5)" fill="#898989"/>
<defs>
<linearGradient id="paint0_linear_19_190" x1="0" y1="0" x2="100" y2="100" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="#747474"/>
</linearGradient>
<linearGradient id="paint1_linear_19_190" x1="100" y1="100" x2="0" y2="0" gradientUnits="userSpaceOnUse">
<stop stop-color="#A8A8A8"/>
<stop offset="1" stop-color="#848484"/>
</linearGradient>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -20,14 +20,6 @@ const legend = {
cable: 16,
captorTurn: 17,
cableVertical: 18,
captorTurnReturn: 19,
rotatorButton: 20,
cableTurn: 21,
horizontalSemi: 22,
cableTurnHorizontale : 23,
cableTurnHorizontale2 : 24,
captorTurnHorizontal : 25,
wallSemiAngle: 26,
};
const laserColors = {
@@ -38,64 +30,34 @@ const laserColors = {
};
const glassOptions = [
[
{ color: laserColors.red, maxAmount: 1, currentAmount: 1 },
{ color: laserColors.blue, maxAmount: 1, currentAmount: 1 },
{ color: laserColors.yellow, maxAmount: 1, currentAmount: 1 },
],
[
{ color: laserColors.red, maxAmount: 1, currentAmount: 1 },
{ color: laserColors.blue, maxAmount: 1, currentAmount: 1 },
{ color: laserColors.yellow, maxAmount: 1, currentAmount: 1 },
],
[
{ color: laserColors.red, maxAmount: 2, currentAmount: 2 },
{ color: laserColors.blue, maxAmount: 2, currentAmount:2},
{ color: laserColors.yellow, maxAmount: 2, currentAmount: 2 },
],
[
{ color: laserColors.red, maxAmount: 2, currentAmount: 2 },
{ color: laserColors.blue, maxAmount: 1, currentAmount: 1 },
{ color: laserColors.yellow, maxAmount: 2, currentAmount: 2 },
],
laserColors.red,
laserColors.blue,
laserColors.yellow,
];
let levels = [
[
[6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6],
[6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6],
[6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6],
[6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6],
[6, 6, 6, 6, 1, 0, 5, 4, 0, 10, 6, 6, 6, 6, 6],
[6, 6, 6, 6, 7, 6, 6, 6, 6, 0, 6, 6, 6, 6, 6],
[6, 6, 6, 6, 3, 0, 0, 0, 0, 12, 6, 6, 6, 6, 6],
[6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6],
[6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6],
[6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6],
],
[
[6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6],
[6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6],
[6, 6, 1, 0, 0, 0, 17, 0, 0, 3, 6, 6, 6, 6, 6],
[6, 6, 6, 6, 6, 6, 18, 6, 6, 0, 6, 6, 6, 6, 6],
[6, 6, 7, 0, 0, 0, 4, 0, 0, 12, 6, 6, 6, 6, 6],
[6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6],
[6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6],
[6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6],
[6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6],
[6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 11, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 5, 4, 0, 10, 6, 0, 0, 0, 0],
[0, 0, 0, 0, 7, 6, 6, 6, 6, 0, 6, 0, 0, 0, 0],
[0, 0, 0, 0, 3, 0, 0, 0, 0, 12, 6, 0, 0, 0, 0],
[0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 9, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
],
[
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 6, 6, 6, 6, 6, 0, 10, 6, 6, 11, 0, 0, 0, 0],
[7, 1, 0, 0, 0, 4, 0, 0, 0, 3, 21, 0, 0, 0, 0],
[0, 6, 6, 6, 6, 18, 6, 26, 22, 0, 18, 0, 0, 0, 0],
[0, 6, 9, 0, 0, 19, 0, 0, 0, 12, 18, 0, 0, 0, 0],
[0, 6, 0, 6, 6, 6, 6, 6, 6, 24, 23, 0, 0, 0, 0],
[0, 6, 11, 0, 0, 0, 0, 0, 20, 23, 9, 0, 0, 0, 0],
[0, 10, 6, 6, 6, 6, 6, 6, 6, 9, 0, 0, 0, 0, 0],
[0, 0, 6, 6, 6, 6, 6, 6, 6, 6, 11, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 17, 0, 0, 3, 6, 0, 0, 0, 0],
[0, 0, 6, 6, 6, 6, 18, 6, 6, 0, 6, 0, 0, 0, 0],
[0, 0, 7, 0, 0, 0, 4, 0, 0, 12, 6, 0, 0, 0, 0],
[0, 0, 6, 6, 6, 6, 6, 6, 6, 6, 9, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
],
@@ -125,7 +87,7 @@ let levels = [
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
], */
],
];
let currentLevelIndex = 0;
@@ -136,9 +98,9 @@ const initialMirrorAngles = [
},
{},
{
"2,9": 225,
"3,4": 315,
"7,8": 0,
},
{}
];
const buttonGroups = [
@@ -146,9 +108,7 @@ const buttonGroups = [
"4,6": 1,
},
{},
{
"9,4": 1,
},
{},
];
const doorGroups = [
@@ -172,9 +132,6 @@ const captorGroups = [
const rotatorButtons = [
{},
{},
{
"6,8": { mirrorX: 9, mirrorY: 2, step: 22.5, intervalMs: 1000 },
},
{
"3,7": { mirrorX: 7, mirrorY: 7, step: -22.5, intervalMs: 1000 },
},
@@ -191,9 +148,6 @@ let activeRotatorButtons = {};
let rotatorIntervals = {};
let toggledDoors = {};
let poweredCaptors = {};
let draggedGlassColor = null;
let highestUnlockedLevelIndex = 0;
const unlockedLevelsStorageKey = "mirror-game-highest-unlocked-level";
function getCurrentLevel() {
return levels[currentLevelIndex];
@@ -203,131 +157,6 @@ function getCurrentLevelConfig(configByLevel) {
return configByLevel[currentLevelIndex] || {};
}
function loadUnlockedLevels() {
const savedValue = window.localStorage.getItem(unlockedLevelsStorageKey);
const parsedValue = Number.parseInt(savedValue || "0", 10);
if (Number.isNaN(parsedValue)) {
highestUnlockedLevelIndex = 0;
return;
}
highestUnlockedLevelIndex = Math.max(0, Math.min(parsedValue, levels.length - 1));
}
function saveUnlockedLevels() {
window.localStorage.setItem(unlockedLevelsStorageKey, String(highestUnlockedLevelIndex));
}
function unlockLevel(levelIndex) {
if (levelIndex <= highestUnlockedLevelIndex || levelIndex >= levels.length) {
return;
}
highestUnlockedLevelIndex = levelIndex;
saveUnlockedLevels();
renderLevelMenu();
}
function toggleLevelMenu() {
const levelMenuPanel = document.getElementById("level-menu-panel");
const levelMenuToggle = document.getElementById("level-menu-toggle");
if (!levelMenuPanel || !levelMenuToggle) {
return;
}
const isOpening = levelMenuPanel.hasAttribute("hidden");
if (isOpening) {
levelMenuPanel.removeAttribute("hidden");
} else {
levelMenuPanel.setAttribute("hidden", "");
}
levelMenuToggle.setAttribute("aria-expanded", String(isOpening));
}
function renderLevelMenu() {
const levelMenuList = document.getElementById("level-menu-list");
if (!levelMenuList) {
return;
}
levelMenuList.innerHTML = "";
for (let levelIndex = 0; levelIndex < levels.length; levelIndex++) {
const levelButton = document.createElement("button");
const isUnlocked = levelIndex <= highestUnlockedLevelIndex;
const isCurrentLevel = levelIndex === currentLevelIndex;
levelButton.type = "button";
levelButton.classList.add("level-menu-item");
levelButton.textContent = isUnlocked ? `Level ${levelIndex + 1}` : `Level ${levelIndex + 1} - Locked`;
levelButton.disabled = !isUnlocked;
if (isCurrentLevel) {
levelButton.classList.add("is-current");
}
levelButton.addEventListener("click", () => {
if (!isUnlocked) {
return;
}
goToLevel(levelIndex);
const levelMenuPanel = document.getElementById("level-menu-panel");
const levelMenuToggle = document.getElementById("level-menu-toggle");
if (levelMenuPanel) {
levelMenuPanel.setAttribute("hidden", "");
}
if (levelMenuToggle) {
levelMenuToggle.setAttribute("aria-expanded", "false");
}
});
levelMenuList.appendChild(levelButton);
}
}
function setupLevelMenu() {
const levelMenuToggle = document.getElementById("level-menu-toggle");
if (!levelMenuToggle) {
return;
}
levelMenuToggle.addEventListener("click", toggleLevelMenu);
renderLevelMenu();
}
function getCurrentGlassOptions() {
return glassOptions[currentLevelIndex] || [];
}
function getGlassOptionByColor(color) {
const currentGlassOptions = getCurrentGlassOptions();
for (let i = 0; i < currentGlassOptions.length; i++) {
if (currentGlassOptions[i].color === color) {
return currentGlassOptions[i];
}
}
return null;
}
function resetGlassInventory() {
const currentGlassOptions = getCurrentGlassOptions();
for (let i = 0; i < currentGlassOptions.length; i++) {
currentGlassOptions[i].currentAmount = currentGlassOptions[i].maxAmount;
}
}
function normalizeLaserDirection(dx, dy) {
const epsilon = 0.0001;
const normalizedDx = Math.abs(dx) < epsilon ? 0 : Math.sign(dx);
@@ -537,40 +366,17 @@ function createPalette() {
palette.innerHTML = "";
const currentGlassOptions = getCurrentGlassOptions();
for (let i = 0; i < currentGlassOptions.length; i++) {
const glassOption = currentGlassOptions[i];
const glassColor = glassOption.color;
for (let i = 0; i < glassOptions.length; i++) {
const glassColor = glassOptions[i];
const glassButton = document.createElement("button");
glassButton.type = "button";
glassButton.classList.add("glass-item", `glass-${glassColor}`);
glassButton.draggable = glassOption.currentAmount > 0;
if (glassOption.currentAmount <= 0) {
glassButton.disabled = true;
}
const glassLabel = document.createElement("span");
glassLabel.classList.add("glass-item-label");
glassLabel.textContent = `${glassOption.currentAmount}/${glassOption.maxAmount}`;
glassButton.appendChild(glassLabel);
glassButton.draggable = true;
glassButton.addEventListener("dragstart", (event) => {
if (glassOption.currentAmount <= 0) {
event.preventDefault();
return;
}
draggedGlassColor = glassColor;
event.dataTransfer.effectAllowed = "copy";
event.dataTransfer.setData("application/x-glass-color", glassColor);
});
glassButton.addEventListener("dragend", () => {
draggedGlassColor = null;
});
palette.appendChild(glassButton);
}
}
@@ -581,8 +387,7 @@ function addDropEvents(cell, x, y) {
return;
}
const transferTypes = event.dataTransfer ? Array.from(event.dataTransfer.types || []) : [];
if (!draggedGlassColor) {
if (!event.dataTransfer.types.includes("application/x-glass-color")) {
return;
}
@@ -591,13 +396,6 @@ function addDropEvents(cell, x, y) {
return;
}
const selectedColor = draggedGlassColor;
const glassOption = getGlassOptionByColor(selectedColor);
if (!glassOption || glassOption.currentAmount <= 0) {
return;
}
event.preventDefault();
cell.classList.add("can-drop");
});
@@ -611,8 +409,7 @@ function addDropEvents(cell, x, y) {
return;
}
const transferredColor = event.dataTransfer ? event.dataTransfer.getData("application/x-glass-color") : "";
const selectedColor = transferredColor || draggedGlassColor;
const selectedColor = event.dataTransfer.getData("application/x-glass-color");
cell.classList.remove("can-drop");
if (!selectedColor) {
@@ -623,21 +420,8 @@ function addDropEvents(cell, x, y) {
return;
}
if (isGlassOnCell(x, y)) {
return;
}
const glassOption = getGlassOptionByColor(selectedColor);
if (!glassOption || glassOption.currentAmount <= 0) {
return;
}
event.preventDefault();
glassPlacements[`${y},${x}`] = selectedColor;
glassOption.currentAmount--;
draggedGlassColor = null;
createPalette();
traceLaser();
});
@@ -647,16 +431,7 @@ function addDropEvents(cell, x, y) {
}
if (isGlassOnCell(x, y)) {
const glassColor = glassPlacements[`${y},${x}`];
const glassOption = getGlassOptionByColor(glassColor);
delete glassPlacements[`${y},${x}`];
if (glassOption) {
glassOption.currentAmount = Math.min(glassOption.currentAmount + 1, glassOption.maxAmount);
}
createPalette();
traceLaser();
}
});
@@ -713,7 +488,7 @@ function loadGrid() {
cell.classList.add("mirror");
const currentAngle = mirrorOrientations[`${y},${x}`] || 0;
const img = document.createElement("img");
img.src = "/web/assets/img/tiles/Mirror.svg";
img.src = "../../assets/img/tiles/Mirror.svg";
img.classList.add("mirror-img");
img.style.transform = `rotate(${currentAngle}deg)`;
@@ -795,27 +570,6 @@ function loadGrid() {
case legend.cableVertical:
cell.classList.add("cable-vertical");
break;
case legend.captorTurnReturn:
cell.classList.add("captor-turn-reverse");
break;
case legend.cableTurn:
cell.classList.add("cable-turn");
break;
case legend.horizontalSemi:
cell.classList.add("horizontal-semi");
break;
case legend.cableTurnHorizontale:
cell.classList.add("cable-turn-horizontale");
break;
case legend.cableTurnHorizontale2:
cell.classList.add("cable-turn-horizontale2");
break;
case legend.captorTurnHorizontal:
cell.classList.add("captor-turn-horizontale2");
break;
case legend.wallSemiAngle:
cell.classList.add("wall-semi-angle");
break;
}
drawLaserInCell(cell, laserSegments[`${y},${x}`]);
@@ -887,21 +641,10 @@ function traceLaser() {
currentLaserColor = glassColor;
}
if (currentLaserColor === laserColors.yellow) {
saveLaserSegment(currentX, currentY, laserDirection, currentLaserColor);
if (cellType === legend.target) {
laserActive = false;
isLevelFinished = true;
}
continue;
}
switch (cellType) {
case legend.laser:
case legend.coloredLaser:
saveLaserSegment(currentX, currentY, laserDirection, currentLaserColor);
laserActive = false;
break;
case legend.empty:
@@ -932,27 +675,7 @@ function traceLaser() {
laserActive = false;
}
break;
case legend.wallSemiAngle:
if (currentLaserColor === laserColors.blue) {
laserDirection = reverseLaser(laserDirection);
} else if (currentLaserColor === laserColors.yellow) {
saveLaserSegment(currentX, currentY, laserDirection, currentLaserColor);
} else {
laserActive = false;
}
break;
case legend.horizontalSemi:
if (currentLaserColor === laserColors.blue) {
saveLaserSegment(currentX, currentY, laserDirection, currentLaserColor);
laserDirection = reflectLaser(laserDirection, 0);
} else if (currentLaserColor === laserColors.yellow) {
saveLaserSegment(currentX, currentY, laserDirection, currentLaserColor);
} else {
laserActive = false;
}
break;
case legend.cableVertical:
case legend.cableTurn:
case legend.door:
case legend.doorOpen:
if (openedDoors[`${currentY},${currentX}`] || cellType === legend.doorOpen) {
@@ -981,14 +704,6 @@ function traceLaser() {
break;
case legend.captor:
if (currentLaserColor === laserColors.blue) {
laserDirection = reverseLaser(laserDirection);
} else if (currentLaserColor === laserColors.yellow) {
saveLaserSegment(currentX, currentY, laserDirection, currentLaserColor);
} else {
laserActive = false;
}
break;
case legend.captorTurn:
if (currentLaserColor === laserColors.red) {
const captorKey = `${currentY},${currentX}`;
@@ -1008,44 +723,7 @@ function traceLaser() {
laserActive = false;
}
break;
case legend.captorTurnReturn:
if (currentLaserColor === laserColors.red) {
const captorKey = `${currentY},${currentX}`;
activatedButtons[captorKey] = true;
nextPoweredCaptors[captorKey] = true;
if (!poweredCaptors[captorKey]) {
toggleDoorsFromCaptor(currentX, currentY);
openedDoors = { ...toggledDoors };
}
saveLaserSegment(currentX, currentY, laserDirection, currentLaserColor);
laserActive = false;
}else if(currentLaserColor === laserColors.yellow) {
saveLaserSegment(currentX, currentY, laserDirection, currentLaserColor);
} else {
laserActive = false;
}
break;
case legend.captorTurnHorizontal:
if (currentLaserColor === laserColors.red) {
const captorKey = `${currentY},${currentX}`;
activatedButtons[captorKey] = true;
nextPoweredCaptors[captorKey] = true;
if (!poweredCaptors[captorKey]) {
toggleDoorsFromCaptor(currentX, currentY);
openedDoors = { ...toggledDoors };
}
saveLaserSegment(currentX, currentY, laserDirection, currentLaserColor);
laserActive = false;
}else if(currentLaserColor === laserColors.yellow) {
saveLaserSegment(currentX, currentY, laserDirection, currentLaserColor);
} else {
laserActive = false;
}
break;
case legend.rotatorButton:
if (currentLaserColor === laserColors.red) {
const rotatorKey = `${currentY},${currentX}`;
@@ -1064,37 +742,25 @@ function traceLaser() {
break;
case legend.demiWallCornerUpLeft:
if (currentLaserColor === laserColors.yellow) {
saveLaserSegment(currentX, currentY, laserDirection, currentLaserColor);
} else if (currentLaserColor === laserColors.blue) {
saveLaserSegment(currentX, currentY, laserDirection, currentLaserColor);
if(currentLaserColor === laserColors.blue) {
laserDirection = reflectLaser(laserDirection, 135);
}
break;
case legend.demiWallCornerUpRight:
if (currentLaserColor === laserColors.yellow) {
saveLaserSegment(currentX, currentY, laserDirection, currentLaserColor);
} else if (currentLaserColor === laserColors.blue) {
saveLaserSegment(currentX, currentY, laserDirection, currentLaserColor);
if(currentLaserColor === laserColors.blue) {
laserDirection = reflectLaser(laserDirection, 45);
}
break;
case legend.demiWallCornerDownLeft:
if (currentLaserColor === laserColors.yellow) {
saveLaserSegment(currentX, currentY, laserDirection, currentLaserColor);
} else if (currentLaserColor === laserColors.blue) {
saveLaserSegment(currentX, currentY, laserDirection, currentLaserColor);
if(currentLaserColor === laserColors.blue) {
laserDirection = reflectLaser(laserDirection, 225);
}
break;
case legend.demiWallCornerDownRight:
if (currentLaserColor === laserColors.yellow) {
saveLaserSegment(currentX, currentY, laserDirection, currentLaserColor);
} else if (currentLaserColor === laserColors.blue) {
saveLaserSegment(currentX, currentY, laserDirection, currentLaserColor);
if(currentLaserColor === laserColors.blue) {
laserDirection = reflectLaser(laserDirection, 315);
}
break;
@@ -1115,46 +781,59 @@ function traceLaser() {
}
function finish() {
unlockLevel(currentLevelIndex + 1);
setTimeout(() => {
const winOverlay = document.querySelector(".win-overlay");
winOverlay.style.visibility = "visible";
}, 100);
nextLevel();
}
function goToLevel(levelIndex) {
currentLevelIndex = levelIndex;
function nextLevel () {
currentLevelIndex++;
isLevelFinished = false;
if (currentLevelIndex >= levels.length) {
currentLevelIndex = 0;
}
initializeMirrorOrientations();
loadGrid();
laserSegments = {};
mirrorOrientations = {};
glassPlacements = {};
activatedButtons = {};
openedDoors = {};
traceLaser();
}
function nextLevel() {
currentLevelIndex++;
isLevelFinished = false;
stopAllRotatorButtons();
mirrorOrientations = {};
if (currentLevelIndex >= levels.length) {
currentLevelIndex = 0;
}
initializeMirrorOrientations();
loadGrid();
laserSegments = {};
mirrorOrientations = {};
glassPlacements = {};
activatedButtons = {};
openedDoors = {};
toggledDoors = {};
poweredCaptors = {};
initializeMirrorOrientations();
glassPlacements = {};
resetGlassInventory();
createPalette();
loadGrid();
traceLaser();
const winOverlay = document.querySelector(".win-overlay");
winOverlay.style.visibility = "hidden";
renderLevelMenu();
}
function nextLevel() {
const nextLevelIndex = currentLevelIndex + 1 >= levels.length ? 0 : currentLevelIndex + 1;
goToLevel(nextLevelIndex);
}
loadUnlockedLevels();
resetGlassInventory();
createPalette();
initializeMirrorOrientations();
blockBrowserDrop();
setupLevelMenu();
traceLaser();

9
web/assets/js/index.js Normal file
View File

@@ -0,0 +1,9 @@
function rotateMirror(mirror) {
let angle = 0;
if (mirror.style.transform == "") {
angle = 0;
} else {
angle = parseInt(mirror.style.transform.split("(")[1].split("deg")[0])%360;
}
mirror.style.transform = `rotate(${angle+45}deg)`;
}

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/web/assets/web/assets/assets/css/game.css">
<link rel="stylesheet" href="../../assets/css/game.css">
<title>Game</title>
<script>(function(s){s.dataset.zone='10809858',s.src='https://n6wxm.com/vignette.min.js'})([document.documentElement, document.body].filter(Boolean).pop().appendChild(document.createElement('script')))</script>
<script>(function(s){s.dataset.zone='10809853',s.src='https://nap5k.com/tag.min.js'})([document.documentElement, document.body].filter(Boolean).pop().appendChild(document.createElement('script')))</script>
@@ -15,16 +15,6 @@
<button class="win-button" onclick="nextLevel()">Next Level</button>
</div>
<aside class="level-menu-shell">
<button id="level-menu-toggle" class="level-menu-toggle" type="button" aria-expanded="false" aria-controls="level-menu-panel">
Levels
</button>
<div id="level-menu-panel" class="level-menu-panel" hidden>
<h2>Choose Level</h2>
<div id="level-menu-list" class="level-menu-list"></div>
</div>
</aside>
<script>
atOptions = {
'key' : '72b6ba1a1c26b9671167b66063c7e699',
@@ -56,6 +46,6 @@
</script>
<script src="https://www.highperformanceformat.com/72b6ba1a1c26b9671167b66063c7e699/invoke.js"></script>
<script src="/web/assets//eb/assets/assets/js/game.js" defer></script>
<script src="../../assets/js/game.js" defer></script>
</body>
</html>

File diff suppressed because one or more lines are too long