Created
February 24, 2024 19:51
-
-
Save rebane2001/5201f7cfa0b8ee45cf465df2f94429fe to your computer and use it in GitHub Desktop.
Pikem versioon Maalehe mängust
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<link rel="icon" href="https://r.muu.ee/39109/73149/index.hyperesources/homoteerull_1.png"> | |
<meta content="Maalehe Mäng Lõputu" property="og:title" /> | |
<meta content="Pikem versioon Maalehe mängust" property="og:description" /> | |
<meta content="https://lyra.horse/misc/maalehe_mäng_lõputu.html" property="og:url" /> | |
<meta content="https://r.muu.ee/39109/73149/index.hyperesources/homoteerull_1.png" property="og:image" /> | |
<meta content="#47A95D" data-react-helmet="true" name="theme-color" /> | |
<title>Maalehe Mäng Lõputu</title> | |
<style type="text/css"> | |
html, body { | |
width: 100%; | |
height: 100%; | |
margin: 0; | |
overflow: hidden; | |
font-family: sans-serif; | |
} | |
a { | |
color: green; | |
} | |
#kaart { | |
width: 100%; | |
height: 100%; | |
user-select: none; | |
} | |
.pawn { | |
position: absolute; | |
max-width: 15%; | |
max-height: 15%; | |
width: auto; | |
height: auto; | |
top: 0; | |
left: 0; | |
right: 0; | |
bottom: 0; | |
margin: auto; | |
opacity: 0; | |
transition: transform linear 6s, opacity linear 1s; | |
cursor: pointer; | |
user-select: none; | |
} | |
#dialog { | |
position: absolute; | |
z-index: 1; | |
top: 0; | |
left: 0; | |
right: 0; | |
bottom: 0; | |
margin: auto; | |
width: 300px; | |
height: fit-content; | |
text-align: center; | |
background: #EEEE; | |
border-radius: 40px; | |
padding: 32px; | |
font-weight: bold; | |
} | |
#header { | |
position: absolute; | |
z-index: 1; | |
top: 20px; | |
left: 0; | |
right: 0; | |
margin: 0 auto; | |
width: 500px; | |
height: fit-content; | |
color: #50A748; | |
text-align: center; | |
font-weight: bold; | |
transition: opacity linear 1s; | |
} | |
#header h1 { | |
font-size: 48px; | |
color: #377834; | |
line-height: 0; | |
} | |
#dialog button { | |
background: green; | |
font-size: 30px; | |
color: white; | |
border: none; | |
border-radius: 10px; | |
cursor: pointer; | |
} | |
#dialog p { | |
margin-top: 0; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="dialog"> | |
<p id="dialogText">Kliki erinevatel elementidel, et need oma koduõuelt eemal hoida. Iga kaitsmine annab sekundi aega juurde, aga iga element mis koduõuele jõuab võtab 30 sekundit aega vähemaks.<br>(<a href="https://maaleht.delfi.ee/artikkel/92649377/suur-vabariigi-aastapaeva-mang-mitte-minu-aia-taha">originaalne versioon</a>)</p> | |
<button id="dialogBtn" onclick="start()">Alusta</button> | |
</div> | |
<div id="header"> | |
<h2>Maalehe mäng (lõputu versioon)</h2> | |
<h1>Mitte minu aia taha!</h1> | |
</div> | |
<canvas id="kaart"></canvas> | |
<script type="text/javascript"> | |
const assetsBaseURI = "https://r.muu.ee/39109/73149/index.hyperesources"; | |
const assets = { | |
"5g": "5g_1.png", | |
"arst": "arst_1.png", | |
"eesti_kaart": "eesti_kaart_1.png", | |
"harvester": "harvester_1.png", | |
"homoteerull": "homoteerull_1.png", | |
"hooldekodu": "hooldekodu_1.png", | |
"joala": "joala_1.png", | |
"joala_nope": "joala_nope_1.png", | |
"kopp": "kopp_1.png", | |
"korsten": "korsten_1.png", | |
"maja": "maja_1.png", | |
"tiivikud": "tiivikud_1.png", | |
"ukrainlane": "ukrainlane_1.png", | |
"rong": "rong_1.png", | |
"lipp_1": "lipp_1.png", | |
"lipp_2": "lipp_2.png", | |
"nope_1": "nope_1.png", | |
"nope_2": "nope_2_2x.png", | |
"tutt_1": "tutt_1.png", | |
"tutt_2": "tutt_2.png", | |
"tutt_3": "tutt_3.png", | |
}; | |
function getAsset(assetName) { | |
return `${assetsBaseURI}/${assets[assetName]}`; | |
} | |
const audioContext = new AudioContext(); | |
function beep(t, f, l, v) { | |
const vol = audioContext.createGain(); | |
const oscillator = audioContext.createOscillator(); | |
oscillator.type = t; | |
oscillator.frequency.value = f; | |
oscillator.connect(vol); | |
vol.connect(audioContext.destination); | |
vol.gain.value = v; | |
oscillator.start(); | |
setTimeout(() => oscillator.stop(), l); | |
} | |
const kaart = document.getElementById("kaart"); | |
function createImg(assetName, classes) { | |
const img = document.createElement("img"); | |
img.src = getAsset(assetName); | |
classes.forEach(c => img.classList.add(c)); | |
return img; | |
} | |
const loadedAssets = Object.keys(assets).reduce((o, key) => { | |
const img = new Image(); | |
img.src = getAsset(key); | |
return { ...o, [key]: img }; | |
}, {}); | |
function drawImgC(ctx, img, x, y, w) { | |
const aspect = img.height / img.width; | |
const h = w*aspect; | |
ctx.drawImage(img, x - (w/2), y - (h/2), w, h); | |
} | |
function isGameRunning() { | |
return Date.now() < gameEnd && !gameFinished; | |
} | |
function takeDamage(pawn) { | |
if (!isGameRunning()) return; | |
if (Date.now() - gameStart < 5000) return; | |
if (pawn.src.includes("homoteerull")) { | |
if (homo > 2) { | |
setTimeout(()=>beep("sawtooth", 52, 200, 0.4),16); | |
} | |
homo = 0; | |
} | |
if (homo > 1 && !pawn.src.includes("homoteerull")) return; | |
beep("sawtooth", 112, 100, 0.4); | |
gameEnd -= 30*1000; | |
} | |
function pawnDestroyed(pawn) { | |
if (isGameRunning()) { | |
score += 1; | |
gameEnd += (homo > 10 ? 10 : 1)*1000; | |
if (pawn.src.includes("homoteerull")) { | |
homo += 1; | |
} else { | |
homo = 0; | |
} | |
if (homo > 1) { | |
score += 9; | |
beep("sine", 295 + Math.random()*25, 150, 0.3); | |
} else { | |
beep("square", 100 + Math.random()*100, 50, 0.2); | |
} | |
pawn.src = getAsset("nope_2"); | |
} | |
pawn.style.transform = getComputedStyle(pawn).transform; | |
pawn.style.opacity = "0"; | |
pawn.style.pointerEvents = "none"; | |
setTimeout(() => { | |
pawn.remove(); | |
}, 1000); | |
} | |
const possiblePawns = [ | |
"5g", | |
"arst", | |
"harvester", | |
"homoteerull", | |
"hooldekodu", | |
"joala", | |
"kopp", | |
"korsten", | |
"tiivikud", | |
"ukrainlane", | |
"rong", | |
]; | |
function spawnPawn() { | |
const pawn = document.createElement("img"); | |
pawn.classList.add("pawn"); | |
pawn.src = getAsset(possiblePawns[Math.floor(Math.random()*possiblePawns.length)]); | |
pawn.draggable = false; | |
const offsetA = `${100*Math.random() - 50}`; | |
const offsetB = `${Math.random() > 0.5 ? 50 : -50}`; | |
pawn.style.transform = Math.random() > 0.5 ? `translate(${offsetA}vw, ${offsetB}vh)` : `translate(${offsetB}vw, ${offsetA}vh)`; | |
let pawnExists = true; | |
pawn.onmousedown = () => { | |
if (isGameRunning() && pawnExists) { | |
pawnExists = false; | |
pawnDestroyed(pawn); | |
} | |
} | |
pawn.ontouchstart = () => { | |
if (isGameRunning() && pawnExists) { | |
pawnExists = false; | |
pawnDestroyed(pawn); | |
} | |
} | |
setTimeout(() => { | |
if (!pawnExists) return; | |
takeDamage(pawn); | |
pawn.remove(); | |
}, 5000); | |
document.body.appendChild(pawn); | |
setTimeout(() => { | |
pawn.style.transform = "translate(0, 0)"; | |
pawn.style.opacity = "1"; | |
}, 32); | |
} | |
let gameStart = 0; | |
let gameEnd = 0; | |
let score = 0; | |
let homo = 0; | |
let lastPawnSpawn = 0; | |
let gameFinished = true; | |
function start() { | |
gameStart = Date.now(); | |
gameEnd = Date.now() + 60*1000; | |
score = 0; | |
homo = 0; | |
gameFinished = false; | |
document.getElementById("dialog").style.display = "none"; | |
document.getElementById("header").style.opacity = 0; | |
setTimeout(() => { | |
document.getElementById("header").style.display = "none"; | |
}, 1000); | |
gameLoop(); | |
} | |
function end() { | |
gameFinished = true; | |
beep("square", 550, 100, 0.3); | |
document.getElementById("dialogText").innerHTML = `Said koduõue vapra kaitsmise eest<br><span style="font-size: 40px; color: green">${score}</span><br>punkti!`; | |
document.getElementById("dialogBtn").innerText = "Proovi uuesti!"; | |
document.getElementById("dialog").style.display = "block"; | |
document.querySelectorAll(".pawn").forEach(pawn => pawnDestroyed(pawn)); | |
} | |
function gameLoop() { | |
if (!isGameRunning()) { | |
if (!gameFinished) end(); | |
return; | |
} | |
if (homo >= 50) { | |
gameFinished = true; | |
end(); | |
document.getElementById("dialogText").innerHTML = `Saavutasid Eestis abieluvõrdsuse, palju õnne!`; | |
return; | |
} | |
if (Date.now() > lastPawnSpawn + 500 - (1 - Math.pow(Math.max(0, 1 - score/1000), 1.8))*270) { | |
spawnPawn(); | |
lastPawnSpawn = Date.now(); | |
} | |
} | |
function homoLipp(ctx) { | |
if (homo < 3) return; | |
ctx.globalAlpha = ((homo-2)/100); | |
["#E40303", "#FF8C00", "#FFED00", "#008026", "#24408E", "#732982"].forEach((c,i) => { | |
ctx.fillStyle = c; | |
ctx.fillRect(0, window.innerHeight/6*i, window.innerWidth, window.innerHeight/6); | |
}); | |
ctx.fillStyle = "black"; | |
ctx.globalAlpha = 1; | |
} | |
function draw() { | |
const ctx = kaart.getContext("2d"); | |
ctx.canvas.width = window.innerWidth; | |
ctx.canvas.height = window.innerHeight; | |
const aspect = window.innerWidth / window.innerHeight; | |
const desiredAspect = 20 / 12; | |
const actualWidth = aspect > desiredAspect ? window.innerHeight*desiredAspect : window.innerWidth; | |
const actualHeight = aspect < desiredAspect ? window.innerWidth/desiredAspect : window.innerHeight; | |
const offsetX = (window.innerWidth - actualWidth) / 2; | |
const offsetY = (window.innerHeight - actualHeight) / 2; | |
homoLipp(ctx); | |
ctx.drawImage(loadedAssets["eesti_kaart"], offsetX, offsetY, actualWidth, actualHeight); | |
homoLipp(ctx); | |
const majaPos = [offsetX + actualWidth/2, offsetY + actualHeight/2]; | |
drawImgC(ctx, loadedAssets["maja"], ...majaPos, actualWidth*0.32); | |
const lipp_o = Math.sin(Date.now()/400); | |
ctx.globalAlpha = Math.min(1, Math.max(0, (lipp_o + 0.25)*2)); | |
drawImgC(ctx, loadedAssets[`lipp_1`], ...majaPos.map((e, i) => e-[actualWidth*0.0282, actualWidth*0.072][i]), actualWidth*0.32/8.89); | |
ctx.globalAlpha = Math.min(1, Math.max(0, (-lipp_o + 0.25)*2)); | |
drawImgC(ctx, loadedAssets[`lipp_2`], ...majaPos.map((e, i) => e-[actualWidth*0.027, actualWidth*0.072][i]), actualWidth*0.32/8.89); | |
for (const tutt of [1,2,3]) { | |
const prog = ((Date.now()/1500) + tutt*0.2) % 1; | |
ctx.globalAlpha = 1 - Math.max(0, Math.abs(prog - 0.5) - 0.25)*4; | |
drawImgC(ctx, loadedAssets[`tutt_${tutt}`], ...majaPos.map((e, i) => e-[-actualWidth*0.026 - prog*actualWidth*0.01, actualWidth*0.058 + prog*actualWidth*0.06][i]), actualWidth*0.32/12.35); | |
} | |
ctx.globalAlpha = 1; | |
ctx.font = "48px sans-serif"; | |
ctx.fillText(`Aeg: ${Math.max(0,Math.floor((gameEnd - Date.now())/1000))}`, 10, 50); | |
ctx.fillText(`Skoor: ${score}`, 10, 100); | |
gameLoop(); | |
requestAnimationFrame(draw); | |
} | |
document.body.onload = () => { | |
draw(); | |
}; | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment