mirror of
https://codeberg.org/ashley/poke
synced 2025-05-28 18:19:43 +00:00
Update html/gamehub.ejs
This commit is contained in:
parent
38094732ba
commit
efe0f7d758
329
html/gamehub.ejs
329
html/gamehub.ejs
@ -59,60 +59,142 @@
|
||||
--bg-start: #2c3e50;
|
||||
--bg-end: #34495e;
|
||||
--accent: #ffabcc;
|
||||
--card-bg: rgba(255,255,255,0.1);
|
||||
--card-hover: rgba(255,255,255,0.2);
|
||||
--font-main: 'PokeTube Flex', sans-serif;
|
||||
--card-bg: rgba(255,255,255,0.1);
|
||||
--card-border: rgba(255,255,255,0.6);
|
||||
--card-hover: rgba(255,255,255,0.3);
|
||||
}
|
||||
* { box-sizing: border-box; margin:0; padding:0; }
|
||||
body {
|
||||
font-family: var(--font-main);
|
||||
background: linear-gradient(135deg, var(--bg-start), var(--bg-end));
|
||||
color: #fff;
|
||||
display:flex; align-items:center; justify-content:center;
|
||||
min-height:100vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
h1 {
|
||||
font-weight:900; font-stretch:ultra-expanded; font-style:italic;
|
||||
color: var(--accent); text-align:center; margin-bottom:1rem;
|
||||
}
|
||||
.game-container {
|
||||
display:grid; grid-template-columns:repeat(auto-fit,minmax(240px,1fr));
|
||||
gap:1rem; width:90%; max-width:1000px;
|
||||
}
|
||||
.game {
|
||||
background: var(--card-bg);
|
||||
border:2px solid #fff; border-radius:10px;
|
||||
text-decoration:none; color:#fff; padding:1rem;
|
||||
text-align:center; transition:background .3s;
|
||||
}
|
||||
.game:hover { background: var(--card-hover); }
|
||||
.game h2 { margin-bottom: .5rem; }
|
||||
canvas, .board { display:none; }
|
||||
@font-face {
|
||||
font-family: var(--font-main);
|
||||
src: url("https://p.poketube.fun/.../robotoflex.ttf");
|
||||
font-display: swap;
|
||||
}
|
||||
/* Animated emoji background */
|
||||
.emoji-bg {
|
||||
position: fixed;
|
||||
top: 0; left: 0;
|
||||
width: 100%; height: 100%;
|
||||
pointer-events: none;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-content: start;
|
||||
font-size: 2rem;
|
||||
}
|
||||
.emoji-bg span {
|
||||
margin: 0.5rem;
|
||||
opacity: 0.15;
|
||||
animation: float 8s ease-in-out infinite alternate;
|
||||
}
|
||||
@keyframes float {
|
||||
to { transform: translateY(-20px) rotate(10deg); }
|
||||
}
|
||||
/* Main content wrapper */
|
||||
.wrapper {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
max-width: 1000px;
|
||||
margin: 2rem auto;
|
||||
padding: 2rem;
|
||||
background: var(--card-bg);
|
||||
border-radius: 15px;
|
||||
border: 2px solid var(--card-border);
|
||||
box-shadow: 0 8px 32px rgba(0,0,0,0.4);
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
h1 {
|
||||
font-weight: 900;
|
||||
font-stretch: ultra-expanded;
|
||||
font-style: italic;
|
||||
color: var(--accent);
|
||||
text-align: center;
|
||||
font-size: 3rem;
|
||||
margin-bottom: 1.5rem;
|
||||
text-shadow: 2px 2px 8px rgba(0,0,0,0.7);
|
||||
}
|
||||
.game-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
|
||||
gap: 1rem;
|
||||
}
|
||||
.game {
|
||||
background: rgba(255,255,255,0.2);
|
||||
border: 2px solid var(--card-border);
|
||||
border-radius: 12px;
|
||||
text-decoration: none;
|
||||
color: #fff;
|
||||
padding: 1.5rem 1rem;
|
||||
text-align: center;
|
||||
transition: transform 0.2s, background 0.3s;
|
||||
}
|
||||
.game:hover {
|
||||
background: var(--card-hover);
|
||||
transform: scale(1.05);
|
||||
}
|
||||
.game h2 {
|
||||
margin-bottom: 0.75rem;
|
||||
font-size: 1.5rem;
|
||||
text-shadow: 1px 1px 4px rgba(0,0,0,0.7);
|
||||
}
|
||||
/* Hide canvas and boards until active */
|
||||
canvas, .board { display: none; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<div class="emoji-bg">
|
||||
<span>🎮</span><span>🕹️</span><span>👾</span><span>🎧</span><span>🖥️</span>
|
||||
<span>🎲</span><span>🏆</span><span>🎯</span><span>🔥</span><span>💥</span>
|
||||
<span>🧩</span><span>🎮</span><span>🕹️</span><span>👾</span><span>🎧</span>
|
||||
<span>🖥️</span><span>🎲</span><span>🏆</span><span>🎯</span><span>🔥</span>
|
||||
<span>💥</span><span>🧩</span><span>🎮</span><span>🕹️</span><span>👾</span>
|
||||
<span>🎧</span><span>🖥️</span><span>🎲</span><span>🏆</span><span>🎯</span>
|
||||
</div>
|
||||
|
||||
<!-- main hub -->
|
||||
<div class="wrapper">
|
||||
<h1>Poke! Games Hub</h1>
|
||||
<div class="game-container">
|
||||
<a href="?game=snake" class="game"><h2>Snake</h2><canvas id="snakeCanvas"></canvas></a>
|
||||
<a href="?game=tic-tac-toe" class="game"><h2>Tic-Tac-Toe</h2><div id="message"></div><div class="board" id="board"></div></a>
|
||||
<a href="?game=sudoku" class="game"><h2>Sudoku</h2><div class="board" id="sudokuBoard"></div></a>
|
||||
<a href="?game=pong" class="game"><h2>Ping-Pong</h2><canvas id="pongCanvas"></canvas></a>
|
||||
<a href="?game=minesweeper" class="game"><h2>Minesweeper</h2><div class="board" id="minesweeperBoard"></div></a>
|
||||
<a href="?game=breakout" class="game"><h2>Breakout</h2><canvas id="breakoutCanvas"></canvas></a>
|
||||
<a href="?game=snake" class="game">
|
||||
<h2>Snake</h2>
|
||||
<canvas id="snakeCanvas"></canvas>
|
||||
</a>
|
||||
<a href="?game=tic-tac-toe" class="game">
|
||||
<h2>Tic-Tac-Toe</h2>
|
||||
<div id="message"></div>
|
||||
<div class="board" id="board"></div>
|
||||
</a>
|
||||
<a href="?game=sudoku" class="game">
|
||||
<h2>Sudoku</h2>
|
||||
<div class="board" id="sudokuBoard"></div>
|
||||
</a>
|
||||
<a href="?game=pong" class="game">
|
||||
<h2>Ping-Pong</h2>
|
||||
<canvas id="pongCanvas"></canvas>
|
||||
</a>
|
||||
<a href="?game=minesweeper" class="game">
|
||||
<h2>Minesweeper</h2>
|
||||
<div class="board" id="minesweeperBoard"></div>
|
||||
</a>
|
||||
<a href="?game=breakout" class="game">
|
||||
<h2>Breakout</h2>
|
||||
<canvas id="breakoutCanvas"></canvas>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/static/data-mobile.js?v=6000"></script>
|
||||
</body>
|
||||
</html>
|
||||
<% } %>
|
||||
|
||||
|
||||
|
||||
<% if (game === "snake") { %>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
@ -213,93 +295,144 @@
|
||||
<div id="board"></div>
|
||||
</div>
|
||||
<script>
|
||||
// GPL header omitted—see top of file
|
||||
const boardEl = document.getElementById('board');
|
||||
const msgEl = document.getElementById('message');
|
||||
const boardElement = document.getElementById("board");
|
||||
const messageElement = document.getElementById("message");
|
||||
let currentPlayer = "X";
|
||||
let board = ["", "", "", "", "", "", "", "", ""];
|
||||
|
||||
let board = Array(9).fill('');
|
||||
let currentPlayer = 'X';
|
||||
|
||||
function checkWin() {
|
||||
const lines = [
|
||||
[0,1,2],[3,4,5],[6,7,8],
|
||||
[0,3,6],[1,4,7],[2,5,8],
|
||||
[0,4,8],[2,4,6]
|
||||
function checkWinner() {
|
||||
const winningCombinations = [
|
||||
[0, 1, 2], [3, 4, 5], [6, 7, 8], // Rows
|
||||
[0, 3, 6], [1, 4, 7], [2, 5, 8], // Columns
|
||||
[0, 4, 8], [2, 4, 6] // Diagonals
|
||||
];
|
||||
return lines.some(l => l.every(i => board[i] && board[i] === board[l[0]]));
|
||||
|
||||
for (const combination of winningCombinations) {
|
||||
const [a, b, c] = combination;
|
||||
if (board[a] && board[a] === board[b] && board[a] === board[c]) {
|
||||
return board[a];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function checkDraw() {
|
||||
return board.every(cell => cell);
|
||||
return !board.includes("");
|
||||
}
|
||||
|
||||
function handleClick(index) {
|
||||
if (board[index] === "" && !checkWinner() && !checkDraw()) {
|
||||
board[index] = currentPlayer;
|
||||
renderBoard();
|
||||
const winner = checkWinner();
|
||||
if (winner) {
|
||||
messageElement.textContent = `Player ${winner} won!!!!!! woaah`;
|
||||
} else if (checkDraw()) {
|
||||
messageElement.textContent = "It's a draw! oh welp >~<";
|
||||
} else {
|
||||
currentPlayer = currentPlayer === "X" ? "O" : "X";
|
||||
messageElement.textContent = `Player ${currentPlayer}'s turn :3`;
|
||||
if (currentPlayer === "O") {
|
||||
setTimeout(makeComputerMove, 500); // AI waits for 0.5 second
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function makeComputerMove() {
|
||||
// Look for a winning move, then look to block player, otherwise, choose a random move
|
||||
const winningMove = findWinningMove();
|
||||
const blockingMove = findBlockingMove();
|
||||
|
||||
if (winningMove !== null) {
|
||||
board[winningMove] = currentPlayer;
|
||||
} else if (blockingMove !== null) {
|
||||
board[blockingMove] = currentPlayer;
|
||||
} else {
|
||||
// Randomly choose an empty cell for the computer's move
|
||||
const emptyCells = board.reduce((acc, value, index) => {
|
||||
if (value === "") {
|
||||
acc.push(index);
|
||||
}
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
if (emptyCells.length > 0) {
|
||||
const randomIndex = Math.floor(Math.random() * emptyCells.length);
|
||||
const computerMove = emptyCells[randomIndex];
|
||||
board[computerMove] = currentPlayer;
|
||||
}
|
||||
}
|
||||
|
||||
renderBoard();
|
||||
const winner = checkWinner();
|
||||
if (winner) {
|
||||
messageElement.textContent = `Player ${winner} won!!!!!! woaah`;
|
||||
} else if (checkDraw()) {
|
||||
messageElement.textContent = "It's a draw! oh welp >~<";
|
||||
} else {
|
||||
currentPlayer = currentPlayer === "X" ? "O" : "X";
|
||||
messageElement.textContent = `Player ${currentPlayer}'s turn :3`;
|
||||
}
|
||||
}
|
||||
|
||||
function findWinningMove() {
|
||||
for (let i = 0; i < board.length; i++) {
|
||||
if (board[i] === "") {
|
||||
board[i] = currentPlayer;
|
||||
if (checkWinner() === currentPlayer) {
|
||||
board[i] = ""; // Reset the move
|
||||
return i;
|
||||
}
|
||||
board[i] = ""; // Reset the move
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function findBlockingMove() {
|
||||
const opponent = currentPlayer === "X" ? "O" : "X";
|
||||
for (let i = 0; i < board.length; i++) {
|
||||
if (board[i] === "") {
|
||||
board[i] = opponent;
|
||||
if (checkWinner() === opponent) {
|
||||
board[i] = ""; // Reset the move
|
||||
return i;
|
||||
}
|
||||
board[i] = ""; // Reset the move
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function renderBoard() {
|
||||
boardEl.innerHTML = '';
|
||||
board.forEach((val, idx) => {
|
||||
const cell = document.createElement('div');
|
||||
cell.className = 'cell';
|
||||
cell.textContent = val;
|
||||
cell.onclick = () => handleMove(idx);
|
||||
boardEl.append(cell);
|
||||
boardElement.innerHTML = "";
|
||||
board.forEach((value, index) => {
|
||||
const cell = document.createElement("div");
|
||||
cell.classList.add("cell");
|
||||
cell.textContent = value;
|
||||
cell.addEventListener("click", () => handleClick(index));
|
||||
boardElement.appendChild(cell);
|
||||
});
|
||||
}
|
||||
|
||||
function handleMove(idx) {
|
||||
if (board[idx] || checkWin() || checkDraw()) return;
|
||||
|
||||
board[idx] = currentPlayer;
|
||||
function resetGame() {
|
||||
currentPlayer = "X";
|
||||
board = ["", "", "", "", "", "", "", "", ""];
|
||||
messageElement.textContent = `Player ${currentPlayer}'s turn :3`;
|
||||
renderBoard();
|
||||
|
||||
if (checkWin()) {
|
||||
msgEl.textContent = `Player ${currentPlayer} won!!!!!! woaah`;
|
||||
} else if (checkDraw()) {
|
||||
msgEl.textContent = "It's a draw! oh welp >~<";
|
||||
} else {
|
||||
currentPlayer = currentPlayer === 'X' ? 'O' : 'X';
|
||||
msgEl.textContent = `Player ${currentPlayer}’s turn :3`;
|
||||
|
||||
if (currentPlayer === 'O') {
|
||||
setTimeout(aiMove, 300);
|
||||
}
|
||||
// If AI is the starting player, make the first move
|
||||
if (currentPlayer === "O") {
|
||||
setTimeout(makeComputerMove, 500); // AI waits for 0.5 second
|
||||
}
|
||||
}
|
||||
|
||||
function aiMove() {
|
||||
// 1) Try to win
|
||||
for (let i = 0; i < 9; i++) {
|
||||
if (!board[i]) {
|
||||
board[i] = 'O';
|
||||
if (checkWin()) {
|
||||
handleMove(i);
|
||||
return;
|
||||
}
|
||||
board[i] = '';
|
||||
}
|
||||
}
|
||||
// 2) Block X
|
||||
for (let i = 0; i < 9; i++) {
|
||||
if (!board[i]) {
|
||||
board[i] = 'X';
|
||||
if (checkWin()) {
|
||||
board[i] = 'O';
|
||||
handleMove(i);
|
||||
return;
|
||||
}
|
||||
board[i] = '';
|
||||
}
|
||||
}
|
||||
// 3) Random
|
||||
const empties = board
|
||||
.map((v,i) => v === '' ? i : null)
|
||||
.filter(i => i !== null);
|
||||
const choice = empties[Math.floor(Math.random() * empties.length)];
|
||||
handleMove(choice);
|
||||
}
|
||||
|
||||
// Initial render
|
||||
renderBoard();
|
||||
// Initial setup
|
||||
resetGame();
|
||||
</script>
|
||||
</body>
|
||||
</body>
|
||||
</html>
|
||||
<% } %>
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user