<div style="text-align:center;font-family:Arial;color:white;">
<h3>Space Invaders</h3>
<div id="highscore">High Score: 0 | Kernal Coded 2026 for TinyPortal</div>
<canvas id="game" width="320" height="400" style="background:black;border:3px solid #444;margin-top:10px;"></canvas>
<p>
⬅️ ➡️ Move SPACE = Fire R = Restart
</p>
</div>
<script>
const canvas = document.getElementById("game");
const ctx = canvas.getContext("2d");
let player = {x:150,y:360,width:20,height:10,speed:4};
let bullets = [];
let invaders = [];
let score = 0;
let highScore = localStorage.getItem("tpInvaderHighScore") || 0;
let gameOver = false;
let exploding = false;
let explosionFrame = 0;
let keys = {};
const invaderSprite = [
"00111100",
"11111111",
"11011011",
"11111111",
"00111100",
"01011010",
"10000001",
"01000010"
];
function updateHighScore(){
if(score > highScore){
highScore = score;
localStorage.setItem("tpInvaderHighScore", highScore);
}
document.getElementById("highscore").innerHTML =
"High Score: " + highScore + " | Kernal Coded 2026 for TinyPortal";
}
updateHighScore();
function drawSprite(sprite,x,y,size,color){
ctx.fillStyle=color;
for(let r=0;r<sprite.length;r++){
for(let c=0;c<sprite[r].length;c++){
if(sprite[r][c]=="1"){
ctx.fillRect(x+c*size,y+r*size,size,size);
}
}
}
}
function createInvaders(){
invaders=[];
for(let r=0;r<4;r++){
for(let c=0;c<8;c++){
invaders.push({
x:40+c*30,
y:40+r*25,
alive:true
});
}
}
}
createInvaders();
let direction = 1;
function movePlayer(){
if(keys["ArrowLeft"]){
player.x -= player.speed;
}
if(keys["ArrowRight"]){
player.x += player.speed;
}
if(player.x < 0) player.x = 0;
if(player.x > canvas.width - player.width) player.x = canvas.width - player.width;
}
function drawPlayer(){
if(exploding){
drawExplosion();
return;
}
ctx.fillStyle="lime";
ctx.fillRect(player.x,player.y,player.width,player.height);
ctx.fillRect(player.x+7,player.y-5,6,5);
}
function drawExplosion(){
ctx.fillStyle="orange";
for(let i=0;i<12;i++){
ctx.fillRect(
player.x + Math.random()*20,
player.y + Math.random()*15,
3,
3
);
}
explosionFrame++;
if(explosionFrame > 25){
gameOver = true;
}
}
function drawBullets(){
ctx.fillStyle="yellow";
bullets.forEach(b=>{
ctx.fillRect(b.x,b.y,3,10);
});
}
function drawInvaders(){
invaders.forEach(i=>{
if(i.alive){
drawSprite(invaderSprite,i.x,i.y,2,"white");
}
});
}
function moveInvaders(){
let hitEdge=false;
invaders.forEach(i=>{
if(!i.alive) return;
i.x += direction;
if(i.x < 10 || i.x > 280){
hitEdge = true;
}
});
if(hitEdge){
direction *= -1;
invaders.forEach(i=>{
i.y += 10;
});
}
}
function updateBullets(){
bullets.forEach(b=> b.y -= 5);
bullets.forEach(b=>{
invaders.forEach(i=>{
if(i.alive &&
b.x > i.x &&
b.x < i.x + 16 &&
b.y > i.y &&
b.y < i.y + 16){
i.alive = false;
b.y = -100;
score += 10;
updateHighScore();
}
});
});
bullets = bullets.filter(b=> b.y > 0);
}
function checkPlayerHit(){
invaders.forEach(i=>{
if(i.alive && i.y + 16 >= player.y){
exploding = true;
}
});
}
function drawScore(){
ctx.fillStyle="white";
ctx.fillText("Score: " + score,10,15);
}
function drawGameOver(){
ctx.fillStyle="red";
ctx.font="20px Arial";
ctx.fillText("GAME OVER",100,200);
ctx.fillStyle="white";
ctx.font="14px Arial";
ctx.fillText("Press R to Restart",95,230);
}
function gameLoop(){
ctx.clearRect(0,0,canvas.width,canvas.height);
movePlayer();
drawPlayer();
drawBullets();
drawInvaders();
drawScore();
if(!exploding){
updateBullets();
moveInvaders();
checkPlayerHit();
}
if(gameOver){
drawGameOver();
return;
}
requestAnimationFrame(gameLoop);
}
document.addEventListener("keydown",e=>{
keys[e.key] = true;
if(e.key === " "){
bullets.push({
x:player.x+10,
y:player.y
});
}
if(e.key==="r" || e.key==="R"){
restartGame();
}
});
document.addEventListener("keyup",e=>{
keys[e.key] = false;
});
function restartGame(){
score = 0;
bullets = [];
exploding = false;
explosionFrame = 0;
gameOver = false;
createInvaders();
gameLoop();
}
gameLoop();
</script>
Quote from: timberguy on February 28, 2026, 08:11:01 PMTrying to get logged in so I could message Lurksalot!I did at least get logged in. Password reminder would not send to me.
I`ve had my Daughter on the phone saying thankyou and that just made my heart melt.
for me.
<!--Space Invaders Kernal coded for fun 2026 -->
<div id="tp-spaceinvader" style="width:320px; height:400px; background:#000; position:relative; overflow:hidden; border:2px solid #ccc; border-radius:5px;">
<canvas id="invaderCanvas" width="320" height="400"></canvas>
<div id="scoreDisplay" style="position:absolute; top:5px; left:5px; color:#fff; font-family:monospace; font-size:14px;">Score: 0</div>
</div>
<script>
(function(){
const canvas = document.getElementById('invaderCanvas');
const ctx = canvas.getContext('2d');
const scoreDisplay = document.getElementById('scoreDisplay');
const WIDTH = canvas.width;
const HEIGHT = canvas.height;
// Player
const player = {
x: WIDTH/2 - 15,
y: HEIGHT - 30,
width: 30,
height: 10,
color: 'lime',
speed: 5,
dx: 0
};
// Bullets
const bullets = [];
// Invader settings
const rows = 3;
const cols = 6;
const invaderWidth = 25;
const invaderHeight = 15;
const invaderSpacingX = 10;
const invaderSpacingY = 20;
let invaderDirection = 1; // 1 = right, -1 = left
let invaderSpeed = 0.5;
// Game state
let invaders = [];
let score = 0;
let gameOver = false;
let gameWon = false;
function initInvaders(){
invaders = [];
for(let r=0;r<rows;r++){
for(let c=0;c<cols;c++){
invaders.push({
x: c*(invaderWidth+invaderSpacingX)+20,
y: r*(invaderHeight+invaderSpacingY)+20,
width: invaderWidth,
height: invaderHeight,
alive: true,
color: 'red'
});
}
}
}
initInvaders();
// Key controls
document.addEventListener('keydown', e => {
if(e.key === 'ArrowLeft') player.dx = -player.speed;
if(e.key === 'ArrowRight') player.dx = player.speed;
if((e.key === ' ' || e.key === 'ArrowUp') && !gameOver) shoot();
if(e.key === 'r' && (gameOver || gameWon)) restart();
});
document.addEventListener('keyup', e => {
if(e.key === 'ArrowLeft' || e.key === 'ArrowRight') player.dx = 0;
});
// Mobile touch controls
canvas.addEventListener('touchstart', e => {
const touch = e.touches[0];
if(touch.clientX < WIDTH/2) player.dx = -player.speed;
else player.dx = player.speed;
shoot();
e.preventDefault();
});
canvas.addEventListener('touchend', e => {
player.dx = 0;
e.preventDefault();
});
function shoot(){
bullets.push({x: player.x + player.width/2 - 2, y: player.y, width: 4, height: 10, color:'yellow'});
}
function update(){
if(gameOver || gameWon) return;
// Move player
player.x += player.dx;
if(player.x < 0) player.x = 0;
if(player.x + player.width > WIDTH) player.x = WIDTH - player.width;
// Move bullets
for(let i = bullets.length-1;i>=0;i--){
bullets[i].y -= 6;
if(bullets[i].y < 0) bullets.splice(i,1);
}
// Move invaders
let moveDown = false;
for(let inv of invaders){
if(!inv.alive) continue;
inv.x += invaderDirection * invaderSpeed;
if(inv.x + inv.width >= WIDTH || inv.x <=0) moveDown = true;
}
if(moveDown){
invaderDirection *= -1;
for(let inv of invaders){
inv.y += 10;
if(inv.y + inv.height >= player.y) gameOver = true;
}
}
// Collision detection
for(let i = bullets.length-1;i>=0;i--){
for(let j = 0;j<invaders.length;j++){
let inv = invaders[j];
if(inv.alive && bullets[i].x < inv.x+inv.width && bullets[i].x+bullets[i].width>inv.x && bullets[i].y<inv.y+inv.height && bullets[i].y+bullets[i].height>inv.y){
inv.alive = false;
bullets.splice(i,1);
score += 10;
break;
}
}
}
// Check victory
if(invaders.every(inv=>!inv.alive)) gameWon = true;
scoreDisplay.textContent = "Score: " + score;
}
function draw(){
ctx.clearRect(0,0,WIDTH,HEIGHT);
// Draw player
ctx.fillStyle = player.color;
ctx.fillRect(player.x, player.y, player.width, player.height);
// Draw bullets
for(let b of bullets){
ctx.fillStyle = b.color;
ctx.fillRect(b.x,b.y,b.width,b.height);
}
// Draw invaders
for(let inv of invaders){
if(inv.alive){
ctx.fillStyle = inv.color;
ctx.fillRect(inv.x,inv.y,inv.width,inv.height);
}
}
// Game over / victory text
if(gameOver || gameWon){
ctx.fillStyle = 'white';
ctx.font = '20px monospace';
ctx.textAlign = 'center';
if(gameOver) ctx.fillText("GAME OVER Sucker lol! Press R", WIDTH/2, HEIGHT/2);
if(gameWon) ctx.fillText("YOU WIN Dam! Press R", WIDTH/2, HEIGHT/2);
}
}
function loop(){
update();
draw();
requestAnimationFrame(loop);
}
function restart(){
bullets.length = 0;
player.x = WIDTH/2 - player.width/2;
player.dx = 0;
score = 0;
gameOver = false;
gameWon = false;
initInvaders();
}
loop();
})();
</script>
Page created in 0.108 seconds with 21 queries.