Quote from: @rjen on March 30, 2026, 08:06:48 PMSeeing the same thing, must be something that changed in TP3.0.3, will check

<html lang="en">
<head>
<meta charset="UTF-8">
<title>Space Invaders - TinyPortal</title>
<style>
body { margin:0; font-family:monospace; background:black; color:#00ff66; text-align:center; }
canvas { background:black; border:6px solid #00ff66; box-shadow:0 0 30px #00ff66 inset; display:block; margin:0 auto; }
#startScreen {
position:absolute; top:0; left:0; width:100%; height:100%;
background:black; color:#00ff66; display:flex;
flex-direction:column; justify-content:center; align-items:center;
}
#startScreen h1 { font-size:48px; margin:0; }
#startScreen p { font-size:24px; margin:5px 0 30px; }
#pressStart { font-size:20px; margin-top:20px; }
#gameContainer { display:none; }
#muteBtn { position:absolute; top:10px; right:10px; width:80px; height:35px; font-size:16px; }
#highscore { font-size:16px; margin-bottom:5px; }
button { width:60px; height:40px; margin:5px; font-size:18px; }
</style>
</head>
<body>
<div id="startScreen">
<h1>SPACE INVADERS</h1>
<p>Kernal Coded - TinyPortal 2026</p>
<div id="pressStart">PRESS START</div>
</div>
<div id="gameContainer">
<div id="highscore">High Score: 0 Kernal Coded For TinyPortal</div>
<canvas id="game" width="360" height="440"></canvas>
<div>
<button id="leftBtn">⬅</button>
<button id="fireBtn">🔥</button>
<button id="rightBtn">➡</button>
</div>
<p>⬅ ➡ Move | HOLD FIRE | R Restart</p>
<audio id="bgMusic" src="https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3" loop autoplay></audio>
<button id="muteBtn">🔊 Mute</button>
</div>
<script>
const startScreen = document.getElementById("startScreen");
const pressStart = document.getElementById("pressStart");
const gameContainer = document.getElementById("gameContainer");
const bgMusic = document.getElementById("bgMusic");
const muteBtn = document.getElementById("muteBtn");
let blink = true;
setInterval(() => {
pressStart.style.visibility = blink ? 'visible' : 'hidden';
blink = !blink;
}, 500);
document.addEventListener("keydown", startGame);
document.addEventListener("click", startGame);
function startGame() {
startScreen.style.display = "none";
gameContainer.style.display = "block";
draw();
document.removeEventListener("keydown", startGame);
document.removeEventListener("click", startGame);
}
muteBtn.onclick = () => {
if(bgMusic.paused){ bgMusic.play(); muteBtn.textContent="🔊 Mute"; }
else{ bgMusic.pause(); muteBtn.textContent="🔇 Unmute"; }
};
const canvas = document.getElementById("game");
const x = canvas.getContext("2d");
const leftBtn = document.getElementById("leftBtn");
const rightBtn = document.getElementById("rightBtn");
const fireBtn = document.getElementById("fireBtn");
const stars=[];
for(let i=0;i<80;i++) stars.push({x:Math.random()*360,y:Math.random()*440,r:Math.random()*2+1,speed:Math.random()*0.5+0.2});
function drawStars(){ x.fillStyle="white"; stars.forEach(s=>{ x.fillRect(s.x,s.y,s.r,s.r); s.y+=s.speed; if(s.y>440){ s.y=0; s.x=Math.random()*360 } }); }
let player={x:170,y:400,w:24,h:12,s:4};
let bullets=[], enemyBullets=[], invaders=[], explosions=[], shields=[], ufo=null;
let keys={}, firing=false, lastShot=0, fireDelay=120;
let level=1, score=0, dir=1, speed=0.6, gameOver=false;
const alien1=["00111100","01111110","11011011","11111111","01111110","01000010"];
const alien2=["00111100","01111110","11111111","11011011","11111111","00100100"];
const ship=["00100","01110","11111"];
const ufoSprite=["00111100","01111110","11111111","01111110"];
let anim=0, animTick=0;
const A=new (window.AudioContext||window.webkitAudioContext)();
function beep(f,d=0.1){ let o=A.createOscillator(),g=A.createGain(); o.connect(g);g.connect(A.destination); o.frequency.value=f;o.start();o.stop(A.currentTime+d) }
function drawSprite(s,xp,yp,sc,col){ x.fillStyle=col; for(let r=0;r<s.length;r++) for(let d=0;d<s[r].length;d++) if(s[r][d]=="1") x.fillRect(xp+d*sc,yp+r*sc,sc,sc); }
function makeInvaders(){ invaders=[]; for(let r=0;r<5;r++) for(let c=0;c<10;c++) invaders.push({x:40+c*28,y:50+r*26,a:true}); }
function makeShields(){ shields=[]; for(let i=0;i<3;i++) shields.push({x:50+i*90,y:340,hp:40}); }
function drawShields(){ x.fillStyle="#00ff66"; shields.forEach(s=>{ for(let i=0;i<s.hp;i++) x.fillRect(s.x+(i%8)*4,s.y+Math.floor(i/8)*4,3,3) }); }
function movePlayer(){ if(keys["ArrowLeft"]||keys["TouchLeft"]) player.x-=player.s; if(keys["ArrowRight"]||keys["TouchRight"]) player.x+=player.s; player.x=Math.max(0,Math.min(336,player.x)) }
function shoot(){ let now=Date.now(); if(firing && now-lastShot>fireDelay){ bullets.push({x:player.x+11,y:player.y}); lastShot=now; beep(800,0.05) } }
function updateBullets(){
bullets.forEach(b=>b.y-=5);
enemyBullets.forEach(b=>b.y+=3);
bullets.forEach(b=>{
// INVADERS
invaders.forEach(i=>{
if(i.a && b.x>i.x && b.x<i.x+16 && b.y>i.y && b.y<i.y+16){
i.a=false;
score+=10;
explode(i.x,i.y);
b.y=-100;
}
});
// 🚀 UFO HIT FIX
if (ufo && b.x > ufo.x && b.x < ufo.x + 32 && b.y > ufo.y && b.y < ufo.y + 16) {
score += 100;
explode(ufo.x, ufo.y);
ufo = null;
b.y = -100;
beep(1200, 0.2);
}
// SHIELDS
shields.forEach(s=>{
if(s.hp>0 && b.x>s.x && b.x<s.x+32 && b.y>s.y && b.y<s.y+32){
s.hp--;
b.y=-100;
}
});
});
enemyBullets.forEach(b=>{
if(b.x>player.x && b.x<player.x+24 && b.y>player.y){
explode(player.x,player.y);
gameOver=true;
}
shields.forEach(s=>{
if(s.hp>0 && b.x>s.x && b.x<s.x+32 && b.y>s.y && b.y<s.y+32){
s.hp--;
b.y=999;
}
});
});
bullets=bullets.filter(b=>b.y>0);
enemyBullets=enemyBullets.filter(b=>b.y<440);
}
function alienShoot(){ let alive=invaders.filter(i=>i.a); if(alive.length && Math.random()<0.02+(level*0.01)){ let s=alive[Math.floor(Math.random()*alive.length)]; enemyBullets.push({x:s.x+8,y:s.y+12}); beep(400,0.05); } }
function moveInvaders(){ let edge=false; invaders.forEach(i=>{ if(!i.a) return; i.x+=dir*speed; if(i.x<10||i.x>320) edge=true; shields.forEach(s=>{ if(s.hp>0 && i.y+16>=s.y && i.x+16>s.x && i.x<s.x+32){ s.hp--; i.a=false; explode(i.x,i.y); } }); if(i.y+16>=player.y) gameOver=true; }); if(edge){ dir*=-1; invaders.forEach(i=>i.y+=10) } }
function explode(xp,yp){ for(let i=0;i<12;i++) explosions.push({x:xp,y:yp,vx:Math.random()*4-2,vy:Math.random()*4-2,l:20}); beep(300,0.1) }
function drawExplosions(){ explosions.forEach(e=>{ x.fillStyle="yellow"; x.fillRect(e.x,e.y,2,2); e.x+=e.vx;e.y+=e.vy;e.l--; }); explosions=explosions.filter(e=>e.l>0) }
function drawBullets(){ x.fillStyle="cyan"; bullets.forEach(b=>x.fillRect(b.x,b.y,4,10)); x.fillStyle="orange"; enemyBullets.forEach(b=>x.fillRect(b.x,b.y,3,8)) }
function drawUFO(){ if(ufo){ ufo.x+=2; drawSprite(ufoSprite,ufo.x,ufo.y,2,"red"); if(ufo.x>400) ufo=null; } }
function spawnUFO(){ if(!ufo && Math.random()<0.002){ ufo={x:-40,y:25}; } }
function draw(){
x.clearRect(0,0,360,440);
drawStars();
movePlayer();
shoot();
updateBullets();
moveInvaders();
alienShoot();
spawnUFO();
drawUFO();
animTick++;
if(animTick>20){ animTick=0; anim=(anim+1)%2 }
invaders.forEach(i=>{ if(i.a) drawSprite(anim?alien1:alien2,i.x,i.y,2,"white") });
drawSprite(ship,player.x,player.y-6,4,"#00ff66");
drawBullets();
drawShields();
drawExplosions();
x.font = "14px monospace";
x.fillStyle = "#00ff66";
x.fillText("Score " + score, 10, 20);
x.fillText("Level " + level, 280, 20);
if(!invaders.some(i=>i.a)){ level++; speed+=0.2; makeInvaders(); makeShields(); }
if(gameOver) reset();
requestAnimationFrame(draw);
}
function reset(){ score=0; level=1; speed=0.6; bullets=[]; enemyBullets=[]; explosions=[]; makeInvaders(); makeShields(); gameOver=false }
document.addEventListener("keydown", e=>{ keys[e.key]=true; if(e.key===" ") firing=true; if(e.key==="r") reset() });
document.addEventListener("keyup", e=>{ keys[e.key]=false; if(e.key===" ") firing=false });
leftBtn.ontouchstart=()=>keys["TouchLeft"]=true; leftBtn.ontouchend=()=>keys["TouchLeft"]=false;
rightBtn.ontouchstart=()=>keys["TouchRight"]=true; rightBtn.ontouchend=()=>keys["TouchRight"]=false;
fireBtn.ontouchstart=()=>firing=true; fireBtn.ontouchend=()=>firing=false;
makeInvaders();
makeShields();
</script>
</body>
Page created in 0.081 seconds with 20 queries.