From d8be00874850d1aa6eb986528e42358e7a451e13 Mon Sep 17 00:00:00 2001 From: RobbyV2 Date: Thu, 10 Oct 2024 15:01:55 -0500 Subject: [PATCH] [Automated] Factorius (#2441) * Automated Commit - Factorius * Add tags and image * Add missing metadata --------- Co-authored-by: Alex Park Co-authored-by: Alex Park --- games/Factorius.js | 610 ++++++++++++++++++++++++++++++++++++++++ games/img/Factorius.png | Bin 0 -> 12940 bytes 2 files changed, 610 insertions(+) create mode 100644 games/Factorius.js create mode 100644 games/img/Factorius.png diff --git a/games/Factorius.js b/games/Factorius.js new file mode 100644 index 0000000000..99ef63aeb6 --- /dev/null +++ b/games/Factorius.js @@ -0,0 +1,610 @@ +/* +@title: Factorius +@author: Hitu +@description: Rudimentary clone of Factorio +@tags: ['strategy', 'survival'] +@img: "Factorius.png" +@addedOn: 2024-10-10 +*/ + +const player = "p"; +const coal = "c"; +const iron = "i"; +const turret = "t"; +const biter = "b"; +const mineIcon = "m"; +const turretIcon = "u"; +const hotbarSelection = "s"; +const hotbarSlot = "h"; +const ironCounterIcon = "x"; +const coalCounterIcon = "y"; +const timerIcon = "z"; + +const empty = "e"; + +const background = "g"; + + +setLegend( + [player, bitmap` +...6F6FF6F6... +..6F66FF66F6.. +.66F6F66F6F66. +66F66F66F66F66 +...11111111... +..1111111111.. +..1111111111.. +..1111111111.. +...11111111... +....111111.... +...LL1111LL... +..LLLLLLLLLL.. +.LLLLLLLLLLLL. +.LL.LLLLLL.LL. +.LL.CCCCCC.LL. +....CC..CC.... +`], + [turret, bitmap` +......1111...... +.....1111LLLLLLL +.....111LLL77777 +.....11LLLLLLLLL +......LLLL...... +......LLLL...... +.....000000..... +....F666666F.... +...F66666666F... +..F6666666666F.. +.FFFFFFFFFFFFFF. +0000000000000000 +`], + [biter, bitmap` +4..........4 +44........44 +.4........4. +.DDDDDDDDDD. +DDCCDDDDCCDD +DD33DDDD33DD +DDDDDDDDDDDD +DDDDDDDDDDDD +.DDDDDDDDDD. +..44444444.. +.4444444444. +.4444444444. +.D444444444. +..DDDDD444.. +...DD..DD... +...DD..DD... +`], + [mineIcon, bitmap` +...LLLLLLLLLLL. +..L11111111222L +..L11211111112L +...LLLLLLLLL11L +.........CCL11L +........CCCL11L +.......CCC.L11L +......CCC..L11L +.....CCC...L11L +....CCC....L21L +...CCC.....L11L +..CCC......L11L +.CCC........LL. +CCC............ +CC............. +`], + [turretIcon, bitmap` +......1111...... +.....1111LLLLLLL +.....111LLL77777 +.....11LLLLLLLLL +......LLLL...... +......LLLL...... +.....000000..... +....F666666F.... +...F66666666F... +..F6666666666F.. +.FFFFFFFFFFFFFF. +0000000000000000 +`], + [hotbarSelection, bitmap` +0000000000000000 +0333333333333330 +03............30 +03............30 +03............30 +03............30 +03............30 +03............30 +03............30 +03............30 +03............30 +03............30 +03............30 +03............30 +0333333333333330 +0000000000000000 +`], + [hotbarSlot, bitmap` +0000000000000000 +0000000000000000 +00............00 +00............00 +00............00 +00............00 +00............00 +00............00 +00............00 +00............00 +00............00 +00............00 +00............00 +00............00 +0000000000000000 +0000000000000000 +`], + [ironCounterIcon, bitmap` +................ +................ +......CCCC...... +.....C....C..... +.....C....C..... +.....C....C..... +.....CCCCCC..... +.....C....C..... +.....C....C..... +.....C....C..... +.....C....C..... +.....CCCCCC..... +................ +................ +................ +................`], + [coalCounterIcon, bitmap` +................ +................ +......3333...... +.....3....3..... +.....3....3..... +.....3....3..... +.....333333..... +.....3....3..... +.....3....3..... +.....3....3..... +.....3....3..... +.....333333..... +................ +................ +................ +................`], + [timerIcon, bitmap` +................ +................ +......7777...... +.....7....7..... +.....7....7..... +.....7....7..... +.....777777..... +.....7....7..... +.....7....7..... +.....7....7..... +.....7....7..... +.....777777..... +................ +................ +................ +................`], + [coal, bitmap` +....0000.... +..0000L000.. +.00000LL000. +.0LL000LL00. +00L00000L000 +00L000000L00 +000000000000 +000000001000 +.0000011100. +.0001110000. +..00000000.. +....0000.... +`], + [iron, bitmap` +....LLLL.... +..LLLLLLLL.. +.LLLL111LLL. +.L11LLL11LL. +LLLLLLLL1LLL +LLL1LLLL1LLL +LLL1LLLLLLLL +LLL11LLLL1LL +.LLL11LL11L. +.LLLL1L11LL. +..LLLLLLLL.. +....LLLL.... +`], + [background, bitmap` +CCCCCCCCCCCCCCCC +C9CCCC99CCCCCCCC +CCCCCCCCCCCCCCCC +CCCCCCCCCCCCC99C +CCCCCCCCCCCCCC9C +CCC99CCCCCCCCCCC +CCCC99CCCCCCCCCC +CCCCC99CCCCCCCCC +CCCCCCCCCCCCCCC9 +CCCCCCCCCCCCCC99 +C99CCCCCCCCCCC9C +C99CCCCCCC99CCCC +CC9CCCCCCCCCCCCC +CCCCCCCCCCCCCCCC +CCCCCCCC9CCCCC99 +CCCCCCCC99CCCCCC +`], + [empty, bitmap` +................ +................ +................ +................ +................ +................ +................ +................ +................ +................ +................ +................ +................ +................ +................ +................`] +); + +setBackground(background); + +// Initialize variables + +let ironCount = 0; +let coalCount = 0; + +let hotbar = [mineIcon, turretIcon]; +let hotbarSelectionIndex = 0; + +// Game state +let gameStarted = false; + +let mapWidth = 20; +let mapHeight = 16; + +let grid = []; +let biterSpawnInterval = 5000; // Spawn biters every 5 seconds +let biterCount = 0; +let round = 1; +let roundTime = 5000; // 5 seconds +let remainingTime = roundTime; + +function generateMap() { + // Generate an empty map + grid = []; + for (let y = 0; y < mapHeight; y++) { + let row = ""; + for (let x = 0; x < mapWidth; x++) { + row += empty; + } + grid.push(row); + } + + // Randomly place coal and iron patches + for (let i = 0; i < 10; i++) { + let x = Math.floor(Math.random() * mapWidth); + let y = Math.floor(Math.random() * mapHeight); + let resourceType = Math.random() < 0.5 ? coal : iron; + placeResourcePatch(x, y, resourceType); + } + + // Place the player in the center + grid[Math.floor(mapHeight / 2)] = replaceCharAt( + grid[Math.floor(mapHeight / 2)], + Math.floor(mapWidth / 2), + player + ); + + setMap(grid.join('\n')); +} + +function placeResourcePatch(x, y, resource) { + // Make sure x and y are within bounds + if (x < 0 || x >= mapWidth || y < 0 || y >= mapHeight) return; + + // Place resource at (x, y) + grid[y] = replaceCharAt(grid[y], x, resource); + + // Randomly expand the patch + let directions = [ + { dx: -1, dy: 0 }, + { dx: 1, dy: 0 }, + { dx: 0, dy: -1 }, + { dx: 0, dy: 1 }, + ]; + + for (let i = 0; i < 3; i++) { + let dir = directions[Math.floor(Math.random() * directions.length)]; + let newX = x + dir.dx; + let newY = y + dir.dy; + if (newX >= 0 && newX < mapWidth && newY >= 0 && newY < mapHeight) { + grid[newY] = replaceCharAt(grid[newY], newX, resource); + } + } +} + +function replaceCharAt(str, index, char) { + return str.substring(0, index) + char + str.substring(index + 1); +} + +generateMap(); + +// Handle player input + +onInput("w", () => { + if (gameStarted) { + movePlayer(0, -1); + } else { + startGame(); + } +}); + +onInput("s", () => { + if (gameStarted) { + movePlayer(0, 1); + } else { + startGame(); + } +}); + +onInput("a", () => { + if (gameStarted) { + movePlayer(-1, 0); + } else { + startGame(); + } +}); + +onInput("d", () => { + if (gameStarted) { + movePlayer(1, 0); + } else { + startGame(); + } +}); + +function movePlayer(dx, dy) { + if (!gameStarted) return; + let playerSprite = getFirst(player); + if (!playerSprite) return; + + let newX = playerSprite.x + dx; + let newY = playerSprite.y + dy; + + if (newX < 0 || newX >= mapWidth || newY < 0 || newY >= mapHeight) return; + + playerSprite.x = newX; + playerSprite.y = newY; +} + +// Cycle through hotbar +onInput("i", () => { + if (gameStarted) { + hotbarSelectionIndex = (hotbarSelectionIndex + 1) % hotbar.length; + drawHotbar(); + } else { + startGame(); + } +}); + +// Use selected hotbar item +onInput("j", () => { + if (gameStarted) { + useSelectedItem(); + } else { + startGame(); + } +}); + +function useSelectedItem() { + let selectedItem = hotbar[hotbarSelectionIndex]; + let playerSprite = getFirst(player); + let x = playerSprite.x; + let y = playerSprite.y; + if (selectedItem === mineIcon) { + let tileSprites = getTile(x, y); + let resourceSprite = tileSprites.find( + (s) => s.type === coal || s.type === iron + ); + if (resourceSprite) { + let amount = Math.floor(Math.random() * 3) + 1; + if (resourceSprite.type === coal) { + coalCount += amount; + } else if (resourceSprite.type === iron) { + ironCount += amount; + } + addText(`+${amount}`, { x: x, y: y - 1, color: color`5` }); + } + } else if (selectedItem === turretIcon) { + if (coalCount >= 50 && ironCount >= 50) { + ironCount -= 50; + coalCount -= 50; + addSprite(x, y, turret); + } else { + addText("Not enough resources", { y: 7, color: color`2` }); + } + } + updateCounters(); +} + +function updateCounters() { + addText(`Iron:${ironCount}`, { x: 1, y: 1, color: color`2` }); + addText(`Coal:${coalCount}`, { x: 1, y: 2, color: color`2` }); +} + +// Draw hotbar +function drawHotbar() { + // Remove existing hotbar + getAll(mineIcon).forEach((s) => s.remove()); + getAll(turretIcon).forEach((s) => s.remove()); + getAll(hotbarSelection).forEach((s) => s.remove()); + getAll(hotbarSlot).forEach((s) => s.remove()); + + // Draw hotbar icons + for (let i = 0; i < hotbar.length; i++) { + addSprite(i, mapHeight - 1, hotbarSlot); + addSprite(i, mapHeight - 1, hotbar[i]); + } + + // Draw selection box + addSprite(hotbarSelectionIndex, mapHeight - 1, hotbarSelection); +} + +drawHotbar(); + +// Game loop + +function gameLoop() { + if (!gameStarted) return; + + clearText(); + updateCounters(); + + // Decrease timer + remainingTime -= 1000; + if (remainingTime <= 0) { + // Start new round + round++; + remainingTime = roundTime + round * 2000; + if (round > 10) { + spawnBiters(round * 2); + } else { + spawnBiters(round + 5); + } + } + // Update timer display + addText(`Time:${Math.ceil(remainingTime / 1000)}`, { x: 1, y: 3, color: color`2` }); + // Move biters towards player + moveBiters(); + + // Player automatically shoots at biters + shootBiters(); + + // Turrets shoot at biters + turretsShoot(); + + // Loop + setTimeout(gameLoop, 1000); +} + +function spawnBiters(number) { + for (let i = 0; i < number; i++) { + let edge = Math.floor(Math.random() * 4); + let x, y; + if (edge === 0) { + // Top edge + x = Math.floor(Math.random() * mapWidth); + y = 0; + } else if (edge === 1) { + // Bottom edge + x = Math.floor(Math.random() * mapWidth); + y = mapHeight - 1; + } else if (edge === 2) { + // Left edge + x = 0; + y = Math.floor(Math.random() * mapHeight); + } else { + // Right edge + x = mapWidth - 1; + y = Math.floor(Math.random() * mapHeight); + } + addSprite(x, y, biter); + } +} + +function moveBiters() { + let playerSprite = getFirst(player); + let playerX = playerSprite.x; + let playerY = playerSprite.y; + getAll(biter).forEach((biterSprite) => { + let dx = Math.sign(playerX - biterSprite.x); + let dy = Math.sign(playerY - biterSprite.y); + biterSprite.x += dx; + biterSprite.y += dy; + + // Check if biter reached player + if (biterSprite.x === playerX && biterSprite.y === playerY) { + // Game over + gameOver(); // Call gameOver() function + } + }); +} + +function shootBiters() { + let biters = getAll(biter); + if (biters.length > 0) { + // Remove one biter + biters[0].remove(); + } +} + +function turretsShoot() { + let turrets = getAll(turret); + let biters = getAll(biter); + turrets.forEach((turretSprite) => { + if (biters.length > 0) { + // Remove a biter + biters[0].remove(); + biters.shift(); + } + }); +} + +function gameOver() { + clearText(); + gameStarted = false; + // Display game over text + addText("Game Over!", { y: 6, color: color`7` }); + addText(`You reached round ${round}`, { y: 7, color: color`7` }); + addText("Press any key", { y: 8, color: color`4` }); + addText("to restart", { y: 9, color: color`4` }); +} + +// Title screen +addText("-- Factorius --", { y: 6, color: color`6` }); +addText("Press any key", { y: 7, color: color`4` }); +addText("to start", { y: 8, color: color`4` }); + +function startGame() { + if (!gameStarted) { + // Reset variables + ironCount = 0; + coalCount = 0; + hotbarSelectionIndex = 0; + gameStarted = true; + biterSpawnInterval = 5000; + biterCount = 0; + round = 1; + roundTime = 5000; + remainingTime = roundTime; + clearText(); + clearInterval(); + drawHotbar(); + updateCounters(); + setTimeout(gameLoop, 1000); + } +} + +function removeStartInputListeners() { + onInput("w", null); + onInput("a", null); + onInput("s", null); + onInput("d", null); + onInput("i", null); + onInput("j", null); + onInput("k", null); +} + diff --git a/games/img/Factorius.png b/games/img/Factorius.png new file mode 100644 index 0000000000000000000000000000000000000000..d321d83aec020597660b76e7a5052fba68e747d9 GIT binary patch literal 12940 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 a6*zeY;U5u4!2clOICoa>O!_HvzyAXSRIGRa literal 0 HcmV?d00001