-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathgames.html
More file actions
212 lines (203 loc) · 10 KB
/
games.html
File metadata and controls
212 lines (203 loc) · 10 KB
1
2
3
4
5
6
7
8
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
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
<!DOCTYPE html>
<html lang="en" class="bg-black text-white">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Games – mroxq</title>
<!-- Tailwind CDN -->
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: '#7c3aed',
accent: '#a78bfa',
glass: 'rgba(255,255,255,0.08)'
},
backgroundImage: theme => ({
'hero-gradient': 'radial-gradient(at 50% 50%, rgba(124,58,237,0.3), transparent 70%)'
})
}
}
};
</script>
<style>
.bg-futuristic { background: #000; background: radial-gradient(circle at 20% 30%, rgba(124,58,237,0.2), transparent 40%),
radial-gradient(circle at 80% 70%, rgba(124,58,237,0.15), transparent 45%),
radial-gradient(circle at 50% 80%, rgba(124,58,237,0.1), transparent 50%); }
.glow-card { backdrop-filter: blur(12px); background: rgba(255,255,255,0.05); border: 1px solid rgba(255,255,255,0.1); }
.glow-button { background: linear-gradient(135deg, #7c3aed, #a78bfa); box-shadow: 0 0 10px rgba(124,58,237,0.6); }
</style>
</head>
<body class="bg-futuristic font-sans antialiased">
<!-- Nav with Settings (reuse) -->
<nav class="flex items-center justify-between p-4 glass rounded-b-lg shadow-md">
<button id="backBtn" class="p-2 hover:bg-white/10 rounded mr-2 cursor-pointer" aria-label="Back"><svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"/></svg></button>
<h1 class="text-5xl md:text-6xl font-extrabold mb-4 bg-clip-text text-transparent bg-gradient-to-r from-primary to-accent">Games</h1>
<button id="settingsBtn" class="p-2 hover:bg-white/10 rounded" aria-label="Settings">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3-.895 3-2-1.343-2-3-2z"/></svg>
</button>
</nav>
<!-- Settings modal (same as index) -->
<div id="settingsModal" class="fixed inset-0 flex items-center justify-center bg-black/50 hidden">
<div class="bg-gray-900 p-6 rounded glass w-80">
<h2 class="text-xl mb-4 text-accent">Accent Color</h2>
<div class="grid grid-cols-2 gap-4">
<button class="accent-option py-2 px-4 rounded" data-color="#3b82f6" style="background:#3b82f6">Blue</button>
<button class="accent-option py-2 px-4 rounded" data-color="#8b5cf6" style="background:#8b5cf6">Purple</button>
<button class="accent-option py-2 px-4 rounded" data-color="#ef4444" style="background:#ef4444">Red</button>
<button class="accent-option py-2 px-4 rounded" data-color="#22c55e" style="background:#22c55e">Green</button>
</div>
<button id="closeSettings" class="mt-4 w-full py-2 bg-gray-800 rounded hover:bg-gray-700">Close</button>
</div>
</div>
<!-- Search and category tabs -->
<section class="p-4 flex flex-col items-center">
<input id="searchInput" type="text" placeholder="Search games..." class="w-2/3 p-2 mb-4 rounded bg-gray-800 text-white focus:outline-none" />
<div id="categoryTabs" class="flex space-x-2 mb-4">
<button data-filter="all" class="px-3 py-1 rounded-full bg-glass text-sm text-gray-300 hover:bg-primary hover:text-white">All</button>
<button data-filter="arcade" class="px-3 py-1 rounded-full bg-glass text-sm text-gray-300 hover:bg-primary hover:text-white">Arcade</button>
<button data-filter="puzzle" class="px-3 py-1 rounded-full bg-glass text-sm text-gray-300 hover:bg-primary hover:text-white">Puzzle</button>
<button data-filter="strategy" class="px-3 py-1 rounded-full bg-glass text-sm text-gray-300 hover:bg-primary hover:text-white">Strategy</button>
<button data-filter="favorites" class="px-3 py-1 rounded-full bg-glass text-sm text-gray-300 hover:bg-primary hover:text-white">Favorites</button>
</div>
</section>
<section class="p-4 text-center">
<div id="xpDisplay" class="mb-4">XP: <span id="xpValue">0</span> | Level: <span id="levelValue">1</span></div>
<div class="w-64 bg-gray-700 rounded h-3 mx-auto">
<div id="xpBar" class="h-3 bg-accent rounded" style="width:0%"></div>
</div>
</section>
<!-- Games grid -->
<section class="p-4 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<!-- Placeholder cards – will be populated by JS from games.json -->
</section>
<script>
// Theme handling (same as index)
const savedAccent = localStorage.getItem('mroxq_accent');
if (savedAccent) document.documentElement.style.setProperty('--accent', savedAccent);
const settingsBtn = document.getElementById('settingsBtn');
const modal = document.getElementById('settingsModal');
const closeBtn = document.getElementById('closeSettings');
settingsBtn.addEventListener('click', () => modal.classList.remove('hidden'));
closeBtn.addEventListener('click', () => modal.classList.add('hidden'));
// Navigation buttons (All / Proxy / Games)
document.querySelectorAll('section button').forEach(btn => {
btn.addEventListener('click', () => {
const lbl = btn.textContent.trim().toLowerCase();
if (lbl === 'all') location.href='index.html';
else if (lbl === 'proxy') location.href='proxy.html';
else if (lbl === 'games') location.href='games.html';
});
});
document.querySelectorAll('.accent-option').forEach(btn => {
btn.addEventListener('click', () => {
const color = btn.dataset.color;
document.documentElement.style.setProperty('--accent', color);
localStorage.setItem('mroxq_accent', color);
});
});
// Search and category filtering
const searchInput = document.getElementById('searchInput');
const categoryTabs = document.getElementById('categoryTabs');
let currentFilter = 'all';
function filterGames() {
const query = searchInput.value.trim().toLowerCase();
const cards = document.querySelectorAll('.game-card');
cards.forEach(card => {
const title = card.dataset.title.toLowerCase();
const category = card.dataset.category;
const isFav = card.dataset.favorite === 'true';
let visible = true;
if (currentFilter === 'favorites') {
visible = isFav;
} else if (currentFilter !== 'all') {
visible = category === currentFilter;
}
if (query && !title.includes(query)) visible = false;
card.classList.toggle('hidden', !visible);
});
}
searchInput.addEventListener('input', filterGames);
categoryTabs.addEventListener('click', e => {
if (e.target.tagName === 'BUTTON') {
currentFilter = e.target.dataset.filter;
filterGames();
}
});
// XP module
const xpKey = 'mroxq_xp';
function loadXP() {
const data = JSON.parse(localStorage.getItem(xpKey) || '{"xp":0,"level":1}');
return data;
}
function saveXP(data) {
localStorage.setItem(xpKey, JSON.stringify(data));
}
function updateXPDisplay() {
const {xp, level} = loadXP();
document.getElementById('xpValue').textContent = xp;
document.getElementById('levelValue').textContent = level;
const percent = Math.min(100, (xp % 1000) / 10);
document.getElementById('xpBar').style.width = percent + '%';
}
updateXPDisplay();
// Favorites handling
function toggleFavorite(id, card) {
const favKey = 'mroxq_fav';
const arr = JSON.parse(localStorage.getItem(favKey) || '[]');
const idx = arr.indexOf(id);
let isFav;
if (idx === -1) { arr.push(id); isFav = true; } else { arr.splice(idx,1); isFav = false; }
localStorage.setItem(favKey, JSON.stringify(arr));
card.dataset.favorite = isFav;
card.classList.toggle('border-2', isFav);
card.classList.toggle('border-accent', isFav);
}
// Load games.json and render cards
fetch('games.json')
.then(r => r.json())
.then(games => {
const container = document.querySelector('section.grid');
const favKey = 'mroxq_fav';
const favArr = JSON.parse(localStorage.getItem(favKey) || '[]');
games.forEach(game => {
const card = document.createElement('div');
const isFav = favArr.includes(game.id);
card.className = 'glow-card glass p-4 rounded card flex flex-col items-center game-card';
card.dataset.title = game.title;
card.dataset.category = game.category;
card.dataset.favorite = isFav;
if (isFav) { card.classList.add('border-2','border-accent'); }
const title = document.createElement('h3');
title.className = 'text-accent mb-2';
title.textContent = game.title;
const iframe = document.createElement('iframe');
iframe.src = game.embedUrl;
iframe.className = 'w-full h-48 border border-gray-600 rounded';
iframe.loading = 'lazy';
const favBtn = document.createElement('button');
favBtn.innerHTML = '❤️';
favBtn.className = 'mt-2';
favBtn.addEventListener('click', (e)=>{ e.stopPropagation(); toggleFavorite(game.id, card); });
card.appendChild(title);
card.appendChild(iframe);
card.appendChild(favBtn);
card.addEventListener('click', () => { window.open(game.embedUrl, '_blank'); });
container.appendChild(card);
});
});
// XP accrual simulation
setInterval(() => {
const data = loadXP();
data.xp += 10;
if (data.xp >= data.level * 1000) { data.level += 1; }
saveXP(data);
updateXPDisplay();
}, 10000);
<script>
const backBtn = document.getElementById('backBtn');
if (backBtn) backBtn.addEventListener('click', () => history.back());
</script>
</html>