mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-16 05:39:40 +02:00
Rename games/mana-games/ to games/arcade/, update all package names (@mana-games/* → @arcade/*), appIds, display names, docker-compose service, root scripts, and documentation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
697 lines
No EOL
22 KiB
HTML
697 lines
No EOL
22 KiB
HTML
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<title>Fish Catcher</title>
|
||
<style>
|
||
body {
|
||
margin: 0;
|
||
background: linear-gradient(180deg, #87CEEB 0%, #1e90ff 30%, #0066cc 60%, #003d82 100%);
|
||
color: #fff;
|
||
font-family: 'Comic Sans MS', cursive;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
min-height: 100vh;
|
||
overflow: hidden;
|
||
}
|
||
|
||
canvas {
|
||
border: 3px solid #fff;
|
||
border-radius: 15px;
|
||
box-shadow: 0 0 20px rgba(0, 0, 0, 0.3);
|
||
}
|
||
|
||
.ui {
|
||
position: absolute;
|
||
top: 20px;
|
||
left: 20px;
|
||
font-size: 20px;
|
||
z-index: 10;
|
||
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
|
||
}
|
||
|
||
.score {
|
||
color: #ffff00;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.lives {
|
||
color: #ff6b6b;
|
||
margin-top: 10px;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.game-over {
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 50%;
|
||
transform: translate(-50%, -50%);
|
||
text-align: center;
|
||
background: rgba(0, 50, 100, 0.9);
|
||
padding: 30px;
|
||
border: 3px solid #fff;
|
||
border-radius: 20px;
|
||
z-index: 20;
|
||
display: none;
|
||
box-shadow: 0 0 30px rgba(0, 0, 0, 0.5);
|
||
}
|
||
|
||
.controls {
|
||
position: absolute;
|
||
bottom: 20px;
|
||
left: 20px;
|
||
font-size: 14px;
|
||
color: rgba(255, 255, 255, 0.8);
|
||
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
|
||
}
|
||
|
||
button {
|
||
background: linear-gradient(145deg, #4CAF50, #45a049);
|
||
color: white;
|
||
border: none;
|
||
padding: 12px 24px;
|
||
margin: 10px;
|
||
cursor: pointer;
|
||
font-family: inherit;
|
||
font-size: 16px;
|
||
border-radius: 25px;
|
||
transition: all 0.3s;
|
||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
||
}
|
||
|
||
button:hover {
|
||
transform: translateY(-2px);
|
||
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3);
|
||
}
|
||
|
||
.timer {
|
||
position: absolute;
|
||
top: 20px;
|
||
right: 20px;
|
||
font-size: 18px;
|
||
color: #ffff00;
|
||
font-weight: bold;
|
||
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<canvas id="gameCanvas" width="800" height="600"></canvas>
|
||
|
||
<div class="ui">
|
||
<div class="score">🐟 Fische: <span id="score">0</span></div>
|
||
<div class="lives">❤️ Leben: <span id="lives">3</span></div>
|
||
</div>
|
||
|
||
<div class="timer">
|
||
⏰ Zeit: <span id="timeLeft">60</span>s
|
||
</div>
|
||
|
||
<div class="controls">
|
||
A/D oder ← → : Boot bewegen | Maus: Alternative Steuerung
|
||
</div>
|
||
|
||
<div class="game-over" id="gameOver">
|
||
<h2>🎣 Angeltag beendet!</h2>
|
||
<p>Gefangene Fische: <span id="finalScore">0</span></p>
|
||
<p id="rating"></p>
|
||
<button onclick="restartGame()">🔄 Nochmal angeln</button>
|
||
</div>
|
||
|
||
<script>
|
||
// Game ID für Statistiken
|
||
const GAME_ID = 'fish-catcher';
|
||
|
||
const canvas = document.getElementById('gameCanvas');
|
||
const ctx = canvas.getContext('2d');
|
||
|
||
// Spiel-Zustand
|
||
let gameRunning = true;
|
||
let score = 0;
|
||
let lives = 3;
|
||
let timeLeft = 60;
|
||
let gameTimer;
|
||
|
||
// Eingabe
|
||
const keys = {};
|
||
let mouseX = canvas.width / 2;
|
||
|
||
// Boot (Spieler)
|
||
const boat = {
|
||
x: canvas.width / 2 - 50,
|
||
y: 20,
|
||
width: 100,
|
||
height: 40,
|
||
speed: 6,
|
||
netWidth: 80,
|
||
netActive: false,
|
||
netAnimation: 0
|
||
};
|
||
|
||
// Arrays für Spielobjekte
|
||
const fish = [];
|
||
const bubbles = [];
|
||
const powerups = [];
|
||
const splashes = [];
|
||
|
||
// Wellen für Hintergrund
|
||
const waves = [];
|
||
|
||
// Wellen erstellen
|
||
function createWaves() {
|
||
for (let i = 0; i < 8; i++) {
|
||
waves.push({
|
||
x: i * 120,
|
||
y: canvas.height - 60 + Math.sin(i) * 10,
|
||
amplitude: 8 + Math.random() * 5,
|
||
frequency: 0.02 + Math.random() * 0.01,
|
||
offset: Math.random() * Math.PI * 2
|
||
});
|
||
}
|
||
}
|
||
|
||
// Fisch erstellen
|
||
function createFish() {
|
||
const fishTypes = [
|
||
{ color: '#ff6b35', points: 10, speed: 1, size: 20 }, // Orange Fisch
|
||
{ color: '#f7931e', points: 15, speed: 1.5, size: 16 }, // Gelber Fisch
|
||
{ color: '#ff1744', points: 25, speed: 2, size: 12 }, // Roter Fisch (schnell)
|
||
{ color: '#9c27b0', points: 50, speed: 0.8, size: 25 } // Lila Fisch (groß, langsam)
|
||
];
|
||
|
||
const type = fishTypes[Math.floor(Math.random() * fishTypes.length)];
|
||
|
||
fish.push({
|
||
x: Math.random() * (canvas.width - 40) + 20,
|
||
y: canvas.height,
|
||
width: type.size,
|
||
height: type.size * 0.6,
|
||
speed: type.speed,
|
||
color: type.color,
|
||
points: type.points,
|
||
wiggle: Math.random() * Math.PI * 2,
|
||
wiggleSpeed: 0.05 + Math.random() * 0.05
|
||
});
|
||
}
|
||
|
||
// Power-up erstellen
|
||
function createPowerup() {
|
||
const types = ['bignet', 'multiplier', 'timeadd'];
|
||
const type = types[Math.floor(Math.random() * types.length)];
|
||
|
||
powerups.push({
|
||
x: Math.random() * (canvas.width - 30) + 15,
|
||
y: canvas.height,
|
||
width: 25,
|
||
height: 25,
|
||
speed: 0.8,
|
||
type: type,
|
||
rotation: 0,
|
||
pulse: 0
|
||
});
|
||
}
|
||
|
||
// Luftblasen erstellen
|
||
function createBubbles() {
|
||
for (let i = 0; i < 3; i++) {
|
||
bubbles.push({
|
||
x: Math.random() * canvas.width,
|
||
y: canvas.height,
|
||
size: Math.random() * 8 + 3,
|
||
speed: 0.5 + Math.random() * 1,
|
||
opacity: 0.3 + Math.random() * 0.4
|
||
});
|
||
}
|
||
}
|
||
|
||
// Splash-Effekt erstellen
|
||
function createSplash(x, y, color = '#87CEEB') {
|
||
for (let i = 0; i < 8; i++) {
|
||
splashes.push({
|
||
x: x,
|
||
y: y,
|
||
vx: (Math.random() - 0.5) * 8,
|
||
vy: (Math.random() - 0.5) * 8,
|
||
size: Math.random() * 4 + 2,
|
||
life: 20,
|
||
maxLife: 20,
|
||
color: color
|
||
});
|
||
}
|
||
}
|
||
|
||
// Kollisionserkennung
|
||
function checkCollision(rect1, rect2) {
|
||
return rect1.x < rect2.x + rect2.width &&
|
||
rect1.x + rect1.width > rect2.x &&
|
||
rect1.y < rect2.y + rect2.height &&
|
||
rect1.y + rect1.height > rect2.y;
|
||
}
|
||
|
||
// Event Listener
|
||
document.addEventListener('keydown', (e) => {
|
||
keys[e.key.toLowerCase()] = true;
|
||
});
|
||
|
||
document.addEventListener('keyup', (e) => {
|
||
keys[e.key.toLowerCase()] = false;
|
||
});
|
||
|
||
canvas.addEventListener('mousemove', (e) => {
|
||
const rect = canvas.getBoundingClientRect();
|
||
mouseX = e.clientX - rect.left;
|
||
});
|
||
|
||
// Boot updaten
|
||
function updateBoat() {
|
||
// Tastatur-Steuerung
|
||
if (keys['a'] || keys['arrowleft']) {
|
||
boat.x -= boat.speed;
|
||
}
|
||
if (keys['d'] || keys['arrowright']) {
|
||
boat.x += boat.speed;
|
||
}
|
||
|
||
// Maus-Steuerung (sanfter)
|
||
const targetX = mouseX - boat.width / 2;
|
||
const diff = targetX - boat.x;
|
||
boat.x += diff * 0.1;
|
||
|
||
// Grenzen
|
||
if (boat.x < 0) boat.x = 0;
|
||
if (boat.x + boat.width > canvas.width) boat.x = canvas.width - boat.width;
|
||
|
||
// Netz-Animation
|
||
if (boat.netAnimation > 0) {
|
||
boat.netAnimation--;
|
||
boat.netActive = true;
|
||
} else {
|
||
boat.netActive = false;
|
||
}
|
||
}
|
||
|
||
// Fische updaten
|
||
function updateFish() {
|
||
for (let i = fish.length - 1; i >= 0; i--) {
|
||
const f = fish[i];
|
||
|
||
// Bewegung
|
||
f.y -= f.speed;
|
||
f.wiggle += f.wiggleSpeed;
|
||
f.x += Math.sin(f.wiggle) * 0.5;
|
||
|
||
// Aus dem Bildschirm entfernt
|
||
if (f.y + f.height < 0) {
|
||
fish.splice(i, 1);
|
||
lives--;
|
||
createSplash(f.x + f.width/2, 0, '#ff6b6b');
|
||
continue;
|
||
}
|
||
|
||
// Kollision mit Netz
|
||
const netArea = {
|
||
x: boat.x + boat.width/2 - boat.netWidth/2,
|
||
y: boat.y + boat.height,
|
||
width: boat.netWidth,
|
||
height: 60
|
||
};
|
||
|
||
if (checkCollision(f, netArea)) {
|
||
score += f.points;
|
||
createSplash(f.x + f.width/2, f.y + f.height/2, f.color);
|
||
boat.netAnimation = 15;
|
||
fish.splice(i, 1);
|
||
|
||
// Sende Score Update für Statistiken
|
||
window.parent.postMessage({
|
||
type: 'GAME_EVENT',
|
||
gameId: GAME_ID,
|
||
event: 'SCORE_UPDATE',
|
||
data: { score: score }
|
||
}, '*');
|
||
}
|
||
}
|
||
}
|
||
|
||
// Power-ups updaten
|
||
function updatePowerups() {
|
||
for (let i = powerups.length - 1; i >= 0; i--) {
|
||
const p = powerups[i];
|
||
|
||
p.y -= p.speed;
|
||
p.rotation += 0.1;
|
||
p.pulse += 0.15;
|
||
|
||
if (p.y + p.height < 0) {
|
||
powerups.splice(i, 1);
|
||
continue;
|
||
}
|
||
|
||
// Kollision mit Boot
|
||
if (checkCollision(p, boat)) {
|
||
if (p.type === 'bignet') {
|
||
boat.netWidth = Math.min(boat.netWidth + 20, 150);
|
||
} else if (p.type === 'multiplier') {
|
||
// Nächste 5 Fische doppelte Punkte (vereinfacht)
|
||
score += 100;
|
||
} else if (p.type === 'timeadd') {
|
||
timeLeft += 10;
|
||
}
|
||
|
||
createSplash(p.x + p.width/2, p.y + p.height/2, '#ffff00');
|
||
powerups.splice(i, 1);
|
||
}
|
||
}
|
||
}
|
||
|
||
// Blasen updaten
|
||
function updateBubbles() {
|
||
for (let i = bubbles.length - 1; i >= 0; i--) {
|
||
const bubble = bubbles[i];
|
||
|
||
bubble.y -= bubble.speed;
|
||
bubble.x += Math.sin(bubble.y * 0.01) * 0.3;
|
||
|
||
if (bubble.y + bubble.size < 0) {
|
||
bubbles.splice(i, 1);
|
||
}
|
||
}
|
||
}
|
||
|
||
// Splash-Effekte updaten
|
||
function updateSplashes() {
|
||
for (let i = splashes.length - 1; i >= 0; i--) {
|
||
const splash = splashes[i];
|
||
|
||
splash.x += splash.vx;
|
||
splash.y += splash.vy;
|
||
splash.vy += 0.3; // Schwerkraft
|
||
splash.life--;
|
||
|
||
if (splash.life <= 0) {
|
||
splashes.splice(i, 1);
|
||
}
|
||
}
|
||
}
|
||
|
||
// Zeichnen
|
||
function draw() {
|
||
// Himmel/Wasser Gradient
|
||
const gradient = ctx.createLinearGradient(0, 0, 0, canvas.height);
|
||
gradient.addColorStop(0, '#87CEEB');
|
||
gradient.addColorStop(0.3, '#1e90ff');
|
||
gradient.addColorStop(0.6, '#0066cc');
|
||
gradient.addColorStop(1, '#003d82');
|
||
|
||
ctx.fillStyle = gradient;
|
||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||
|
||
// Wellen zeichnen
|
||
ctx.fillStyle = 'rgba(255, 255, 255, 0.2)';
|
||
for (const wave of waves) {
|
||
ctx.beginPath();
|
||
for (let x = 0; x < canvas.width; x += 5) {
|
||
const y = wave.y + Math.sin((x + wave.offset) * wave.frequency) * wave.amplitude;
|
||
if (x === 0) ctx.moveTo(x, y);
|
||
else ctx.lineTo(x, y);
|
||
}
|
||
ctx.lineTo(canvas.width, canvas.height);
|
||
ctx.lineTo(0, canvas.height);
|
||
ctx.fill();
|
||
wave.offset += 0.02;
|
||
}
|
||
|
||
// Blasen zeichnen
|
||
for (const bubble of bubbles) {
|
||
ctx.globalAlpha = bubble.opacity;
|
||
ctx.fillStyle = '#87CEEB';
|
||
ctx.beginPath();
|
||
ctx.arc(bubble.x, bubble.y, bubble.size, 0, Math.PI * 2);
|
||
ctx.fill();
|
||
}
|
||
ctx.globalAlpha = 1;
|
||
|
||
// Fische zeichnen
|
||
for (const f of fish) {
|
||
ctx.save();
|
||
ctx.translate(f.x + f.width/2, f.y + f.height/2);
|
||
|
||
// Fisch-Körper
|
||
ctx.fillStyle = f.color;
|
||
ctx.beginPath();
|
||
ctx.ellipse(0, 0, f.width/2, f.height/2, 0, 0, Math.PI * 2);
|
||
ctx.fill();
|
||
|
||
// Fisch-Schwanz
|
||
ctx.fillStyle = f.color;
|
||
ctx.beginPath();
|
||
ctx.moveTo(-f.width/2, 0);
|
||
ctx.lineTo(-f.width/2 - 8, -f.height/4);
|
||
ctx.lineTo(-f.width/2 - 8, f.height/4);
|
||
ctx.fill();
|
||
|
||
// Auge
|
||
ctx.fillStyle = '#fff';
|
||
ctx.beginPath();
|
||
ctx.arc(f.width/4, -f.height/6, 3, 0, Math.PI * 2);
|
||
ctx.fill();
|
||
|
||
ctx.fillStyle = '#000';
|
||
ctx.beginPath();
|
||
ctx.arc(f.width/4, -f.height/6, 1.5, 0, Math.PI * 2);
|
||
ctx.fill();
|
||
|
||
ctx.restore();
|
||
}
|
||
|
||
// Power-ups zeichnen
|
||
for (const p of powerups) {
|
||
ctx.save();
|
||
ctx.translate(p.x + p.width/2, p.y + p.height/2);
|
||
ctx.rotate(p.rotation);
|
||
|
||
const pulseSize = p.width + Math.sin(p.pulse) * 3;
|
||
|
||
if (p.type === 'bignet') {
|
||
ctx.fillStyle = '#4CAF50';
|
||
} else if (p.type === 'multiplier') {
|
||
ctx.fillStyle = '#ffff00';
|
||
} else {
|
||
ctx.fillStyle = '#ff69b4';
|
||
}
|
||
|
||
ctx.fillRect(-pulseSize/2, -pulseSize/2, pulseSize, pulseSize);
|
||
|
||
// Symbol
|
||
ctx.fillStyle = '#000';
|
||
ctx.font = '12px Arial';
|
||
ctx.textAlign = 'center';
|
||
if (p.type === 'bignet') ctx.fillText('🕸️', 0, 4);
|
||
else if (p.type === 'multiplier') ctx.fillText('×2', 0, 4);
|
||
else ctx.fillText('+T', 0, 4);
|
||
|
||
ctx.restore();
|
||
}
|
||
|
||
// Boot zeichnen
|
||
ctx.fillStyle = '#8B4513';
|
||
ctx.fillRect(boat.x, boat.y, boat.width, boat.height);
|
||
|
||
// Boot-Details
|
||
ctx.fillStyle = '#A0522D';
|
||
ctx.fillRect(boat.x + 10, boat.y + 5, boat.width - 20, boat.height - 10);
|
||
|
||
// Netz zeichnen
|
||
if (boat.netActive || boat.netAnimation > 0) {
|
||
const netY = boat.y + boat.height;
|
||
const netX = boat.x + boat.width/2 - boat.netWidth/2;
|
||
|
||
ctx.strokeStyle = '#654321';
|
||
ctx.lineWidth = 2;
|
||
ctx.globalAlpha = 0.7;
|
||
|
||
// Netz-Muster
|
||
for (let i = 0; i < 6; i++) {
|
||
for (let j = 0; j < 4; j++) {
|
||
const x = netX + (i * boat.netWidth/5);
|
||
const y = netY + (j * 15);
|
||
ctx.strokeRect(x, y, boat.netWidth/5, 15);
|
||
}
|
||
}
|
||
|
||
ctx.globalAlpha = 1;
|
||
}
|
||
|
||
// Splash-Effekte zeichnen
|
||
for (const splash of splashes) {
|
||
ctx.globalAlpha = splash.life / splash.maxLife;
|
||
ctx.fillStyle = splash.color;
|
||
ctx.beginPath();
|
||
ctx.arc(splash.x, splash.y, splash.size, 0, Math.PI * 2);
|
||
ctx.fill();
|
||
}
|
||
ctx.globalAlpha = 1;
|
||
}
|
||
|
||
// Spawn-System
|
||
let fishSpawnTimer = 0;
|
||
let powerupSpawnTimer = 0;
|
||
let bubbleSpawnTimer = 0;
|
||
|
||
function handleSpawning() {
|
||
fishSpawnTimer++;
|
||
powerupSpawnTimer++;
|
||
bubbleSpawnTimer++;
|
||
|
||
// Fische spawnen
|
||
if (fishSpawnTimer >= 90) {
|
||
createFish();
|
||
fishSpawnTimer = 0;
|
||
}
|
||
|
||
// Power-ups spawnen
|
||
if (powerupSpawnTimer >= 600 && powerups.length < 1) {
|
||
createPowerup();
|
||
powerupSpawnTimer = 0;
|
||
}
|
||
|
||
// Blasen spawnen
|
||
if (bubbleSpawnTimer >= 30) {
|
||
createBubbles();
|
||
bubbleSpawnTimer = 0;
|
||
}
|
||
}
|
||
|
||
// Spiel-Loop
|
||
function gameLoop() {
|
||
if (!gameRunning) return;
|
||
|
||
updateBoat();
|
||
updateFish();
|
||
updatePowerups();
|
||
updateBubbles();
|
||
updateSplashes();
|
||
handleSpawning();
|
||
|
||
draw();
|
||
|
||
// UI updaten
|
||
document.getElementById('score').textContent = score;
|
||
document.getElementById('lives').textContent = lives;
|
||
document.getElementById('timeLeft').textContent = timeLeft;
|
||
|
||
// Spiel beenden
|
||
if (lives <= 0 || timeLeft <= 0) {
|
||
gameOver();
|
||
}
|
||
|
||
requestAnimationFrame(gameLoop);
|
||
}
|
||
|
||
// Timer
|
||
function startTimer() {
|
||
gameTimer = setInterval(() => {
|
||
if (gameRunning && timeLeft > 0) {
|
||
timeLeft--;
|
||
}
|
||
}, 1000);
|
||
}
|
||
|
||
// Game Over
|
||
function gameOver() {
|
||
gameRunning = false;
|
||
clearInterval(gameTimer);
|
||
|
||
document.getElementById('finalScore').textContent = score;
|
||
|
||
let rating = '';
|
||
if (score >= 500) rating = '🏆 Meister-Angler!';
|
||
else if (score >= 300) rating = '🥈 Profi-Fischer!';
|
||
else if (score >= 150) rating = '🥉 Guter Fang!';
|
||
else rating = '🎣 Weiter üben!';
|
||
|
||
document.getElementById('rating').textContent = rating;
|
||
document.getElementById('gameOver').style.display = 'block';
|
||
|
||
// Sende Game Over Event
|
||
window.parent.postMessage({
|
||
type: 'GAME_EVENT',
|
||
gameId: GAME_ID,
|
||
event: 'GAME_OVER',
|
||
data: { score: score }
|
||
}, '*');
|
||
|
||
// Achievement prüfen
|
||
if (score >= 500) {
|
||
window.parent.postMessage({
|
||
type: 'GAME_EVENT',
|
||
gameId: GAME_ID,
|
||
event: 'ACHIEVEMENT_UNLOCKED',
|
||
data: {
|
||
achievementId: 'master_angler',
|
||
name: 'Master Angler',
|
||
description: 'Score 500 points in Fish Catcher',
|
||
icon: '🏆'
|
||
}
|
||
}, '*');
|
||
}
|
||
|
||
if (lives === 3 && score >= 300) {
|
||
window.parent.postMessage({
|
||
type: 'GAME_EVENT',
|
||
gameId: GAME_ID,
|
||
event: 'ACHIEVEMENT_UNLOCKED',
|
||
data: {
|
||
achievementId: 'perfect_fishing',
|
||
name: 'Perfect Fishing',
|
||
description: 'Score 300 points without losing a life',
|
||
icon: '🌟'
|
||
}
|
||
}, '*');
|
||
}
|
||
}
|
||
|
||
// Neustart
|
||
function restartGame() {
|
||
gameRunning = true;
|
||
score = 0;
|
||
lives = 3;
|
||
timeLeft = 60;
|
||
|
||
// Arrays leeren
|
||
fish.length = 0;
|
||
powerups.length = 0;
|
||
bubbles.length = 0;
|
||
splashes.length = 0;
|
||
|
||
// Boot zurücksetzen
|
||
boat.x = canvas.width / 2 - 50;
|
||
boat.netWidth = 80;
|
||
boat.netActive = false;
|
||
boat.netAnimation = 0;
|
||
|
||
// Timer zurücksetzen
|
||
fishSpawnTimer = 0;
|
||
powerupSpawnTimer = 0;
|
||
bubbleSpawnTimer = 0;
|
||
|
||
clearInterval(gameTimer);
|
||
startTimer();
|
||
|
||
document.getElementById('gameOver').style.display = 'none';
|
||
gameLoop();
|
||
}
|
||
|
||
// Spiel starten
|
||
createWaves();
|
||
startTimer();
|
||
gameLoop();
|
||
|
||
// Sende Game Loaded Event für Statistiken
|
||
window.parent.postMessage({
|
||
type: 'GAME_LOADED',
|
||
gameId: GAME_ID
|
||
}, '*');
|
||
</script>
|
||
</body>
|
||
</html> |