Refine Pixel Landing Page with Tír na nÓg spatial architecture
- Implement Doors and Alleys spatial navigation system - Add Tír na nÓg pixel-art aesthetic and smooth transitions - Support keyboard (WASD/Arrows) and mouse-based navigation - Restructure HTML into a navigable 2D grid of rooms Co-authored-by: micmug <185775013+micmug@users.noreply.github.com>
This commit is contained in:
+63
@@ -0,0 +1,63 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>faebits | Tír na nÓg</title>
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="viewport">
|
||||
<div id="world">
|
||||
<!-- Room (0,0): The Gate -->
|
||||
<section id="room-0-0" class="room active">
|
||||
<div class="content">
|
||||
<h1>Tír na nÓg</h1>
|
||||
<p>Welcome to the Land of Eternal Youth.</p>
|
||||
</div>
|
||||
<div class="doors">
|
||||
<button class="door door-east" data-target="1,0">To the Meadow →</button>
|
||||
<button class="door door-south" data-target="0,1">Down the Alleys ↓</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Room (1,0): The Meadow -->
|
||||
<section id="room-1-0" class="room">
|
||||
<div class="content">
|
||||
<h2>The Meadow</h2>
|
||||
<p>Where pixels bloom and legends grow.</p>
|
||||
</div>
|
||||
<div class="doors">
|
||||
<button class="door door-west" data-target="0,0">← Back to the Gate</button>
|
||||
<button class="door door-south" data-target="1,1">To the Portal ↓</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Room (0,1): The Alleys -->
|
||||
<section id="room-0-1" class="room">
|
||||
<div class="content">
|
||||
<h2>The Alleys</h2>
|
||||
<p>Navigating the narrow paths of creation.</p>
|
||||
</div>
|
||||
<div class="doors">
|
||||
<button class="door door-north" data-target="0,0">↑ Up to the Gate</button>
|
||||
<button class="door door-east" data-target="1,1">To the Portal →</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Room (1,1): The Portal -->
|
||||
<section id="room-1-1" class="room">
|
||||
<div class="content">
|
||||
<h2>The Portal</h2>
|
||||
<p>Step through to join the faebits.</p>
|
||||
</div>
|
||||
<div class="doors">
|
||||
<button class="door door-north" data-target="1,0">↑ Up to the Meadow</button>
|
||||
<button class="door door-west" data-target="0,1">← Back to the Alleys</button>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
<script src="script.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
* Tír na nÓg - Spatial Navigation
|
||||
* Logic for moving through the grid of rooms using doors and keys.
|
||||
*/
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const world = document.getElementById('world');
|
||||
const doors = document.querySelectorAll('.door');
|
||||
const rooms = document.querySelectorAll('.room');
|
||||
|
||||
let currentPos = { x: 0, y: 0 };
|
||||
const gridSize = { width: 2, height: 2 };
|
||||
|
||||
/**
|
||||
* Updates the viewport position based on current x, y coordinates
|
||||
*/
|
||||
function updateView() {
|
||||
const translateX = -currentPos.x * 100;
|
||||
const translateY = -currentPos.y * 100;
|
||||
world.style.transform = `translate(${translateX}vw, ${translateY}vh)`;
|
||||
|
||||
// Update active class for rooms
|
||||
rooms.forEach(room => {
|
||||
const id = `room-${currentPos.x}-${currentPos.y}`;
|
||||
if (room.id === id) {
|
||||
room.classList.add('active');
|
||||
} else {
|
||||
room.classList.remove('active');
|
||||
}
|
||||
});
|
||||
|
||||
console.log(`Moved to room: ${currentPos.x}, ${currentPos.y}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles navigation to a specific target coordinate
|
||||
*/
|
||||
function navigateTo(targetStr) {
|
||||
const [x, y] = targetStr.split(',').map(Number);
|
||||
if (!isNaN(x) && !isNaN(y)) {
|
||||
currentPos.x = x;
|
||||
currentPos.y = y;
|
||||
updateView();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the position relative to current pos
|
||||
*/
|
||||
function moveRelative(dx, dy) {
|
||||
const newX = currentPos.x + dx;
|
||||
const newY = currentPos.y + dy;
|
||||
|
||||
if (newX >= 0 && newX < gridSize.width && newY >= 0 && newY < gridSize.height) {
|
||||
currentPos.x = newX;
|
||||
currentPos.y = newY;
|
||||
updateView();
|
||||
}
|
||||
}
|
||||
|
||||
// Door Click Listeners
|
||||
doors.forEach(door => {
|
||||
door.addEventListener('click', (e) => {
|
||||
const target = e.target.getAttribute('data-target');
|
||||
navigateTo(target);
|
||||
});
|
||||
});
|
||||
|
||||
// Keyboard Listeners (WASD + Arrows)
|
||||
document.addEventListener('keydown', (e) => {
|
||||
switch(e.key.toLowerCase()) {
|
||||
case 'arrowup':
|
||||
case 'w':
|
||||
moveRelative(0, -1);
|
||||
break;
|
||||
case 'arrowdown':
|
||||
case 's':
|
||||
moveRelative(0, 1);
|
||||
break;
|
||||
case 'arrowleft':
|
||||
case 'a':
|
||||
moveRelative(-1, 0);
|
||||
break;
|
||||
case 'arrowright':
|
||||
case 'd':
|
||||
moveRelative(1, 0);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
console.log('Tír na nÓg navigation initialized');
|
||||
});
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
/* Tír na nÓg - Pixel Art Theme */
|
||||
:root {
|
||||
--gold: #f1c40f;
|
||||
--emerald: #2ecc71;
|
||||
--dark-green: #1b4d3e;
|
||||
--night: #2c3e50;
|
||||
--cloud: #ecf0f1;
|
||||
--pixel-border: 4px;
|
||||
}
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
image-rendering: pixelated;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
background-color: var(--night);
|
||||
color: var(--cloud);
|
||||
overflow: hidden; /* Viewport handles navigation */
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
#viewport {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#world {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 100vw);
|
||||
grid-template-rows: repeat(2, 100vh);
|
||||
transition: transform 0.6s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
width: 200vw;
|
||||
height: 200vh;
|
||||
}
|
||||
|
||||
.room {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
border: var(--pixel-border) solid var(--gold);
|
||||
background: linear-gradient(135deg, var(--dark-green) 0%, var(--night) 100%);
|
||||
text-align: center;
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
.content {
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
padding: 2rem;
|
||||
border: var(--pixel-border) double var(--emerald);
|
||||
box-shadow: 10px 10px 0px var(--dark-green);
|
||||
max-width: 80%;
|
||||
}
|
||||
|
||||
h1, h2 {
|
||||
color: var(--gold);
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 1rem;
|
||||
font-size: 3rem;
|
||||
text-shadow: 4px 4px 0px var(--dark-green);
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 1.2rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
/* Doors - Navigation UI */
|
||||
.doors {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.door {
|
||||
pointer-events: auto;
|
||||
position: absolute;
|
||||
padding: 1rem;
|
||||
background: var(--gold);
|
||||
color: var(--night);
|
||||
border: var(--pixel-border) solid var(--dark-green);
|
||||
cursor: pointer;
|
||||
font-family: inherit;
|
||||
font-weight: bold;
|
||||
font-size: 1rem;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.door:hover {
|
||||
background: var(--emerald);
|
||||
color: white;
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.door-north { top: 20px; left: 50%; transform: translateX(-50%); }
|
||||
.door-south { bottom: 20px; left: 50%; transform: translateX(-50%); }
|
||||
.door-east { right: 20px; top: 50%; transform: translateY(-50%); }
|
||||
.door-west { left: 20px; top: 50%; transform: translateY(-50%); }
|
||||
|
||||
/* Mobile optimization */
|
||||
@media (max-width: 768px) {
|
||||
h1, h2 { font-size: 2rem; }
|
||||
.content { max-width: 95%; }
|
||||
}
|
||||
Reference in New Issue
Block a user