diff --git a/assets/tilemap.ase b/assets/tilemap.ase index e545cf9a93ce4fedf02adda9e6c9a90f6b484759..bfdc857bcbadc9022c2e857a1314f74fee583435 100644 Binary files a/assets/tilemap.ase and b/assets/tilemap.ase differ diff --git a/src/img/hampsterfont.webp b/src/img/hampsterfont.webp index a8eddc36fba2ac0e66216ed0d11b68c0bdb77315..e90999eb673f6ae56434899a04c48a89ba5cb4a7 100644 Binary files a/src/img/hampsterfont.webp and b/src/img/hampsterfont.webp differ diff --git a/src/img/t.webp b/src/img/t.webp index 339d2d21457c3d7eb3f6d13ba8a9baaa83a56075..2b34fe83084e7f51ed6e01bf8c9c5b3762c919ac 100644 Binary files a/src/img/t.webp and b/src/img/t.webp differ diff --git a/src/index.html b/src/index.html index 18edcf31ddb53f0c6172f2eb13bebdc0384c2fd4..83a0e4d46e1591b6bb35528855f33ccf78b605b5 100644 --- a/src/index.html +++ b/src/index.html @@ -2,7 +2,7 @@ <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1"> <style> - :root { color-scheme: dark; } + :root { color-scheme: light dark; } body { display: flex; justify-content: center; align-items: center; height: 100vh;} canvas, body { margin: 0; @@ -10,8 +10,8 @@ user-select: none; } canvas { - width: 768px; - height: 768px; + width: 100%; + max-height: 100vh; object-fit: contain; image-rendering: pixelated; margin: auto; @@ -19,6 +19,5 @@ </style> <body> <canvas id=c></canvas> - <script src="lzs.js"></script> <script type="module" src=game.js></script> </body> \ No newline at end of file diff --git a/src/js/canvas.js b/src/js/canvas.js index e688f02ce59e969addf7afcf1e5a43512846998a..6cb40fc758990a119f13039f053c6844c7535bc0 100644 --- a/src/js/canvas.js +++ b/src/js/canvas.js @@ -1,7 +1,5 @@ // Holds canvas, context and adds endpoints for graphics - -import { pi } from "./utils.js" class Canvas { constructor(id="c", w=128, h=128) { this.canvas = document.getElementById(id); diff --git a/src/js/config.js b/src/js/config.js index ddaf8616da372a1d3cce76009c90dc8eb2a05c79..40a6ff3702a7ed34173af5702b047391223dfac0 100644 --- a/src/js/config.js +++ b/src/js/config.js @@ -4,6 +4,3 @@ export const GAME_TITLE = "Untitled JS13K23 Game." export const WIDTH = 256; // pixels export const HEIGHT = 240; // pixels - -export const SCALE = 2<<4; - diff --git a/src/js/game.js b/src/js/game.js index ec2c1f1b7553313aca37ecc37ad5f376eb045281..3ebfd40eeda805e897508b8629cc7079b34cf78e 100644 --- a/src/js/game.js +++ b/src/js/game.js @@ -1,31 +1,17 @@ -import { WIDTH, HEIGHT, GAME_TITLE, SCALE } from "./config.js"; +import { WIDTH, HEIGHT, GAME_TITLE } from "./config.js"; import { Canvas } from "./canvas.js"; import { TextRenderer } from "./text.js"; import { Room, Object } from "./objects.js"; -import { whichKeyDown } from "./keyboard.js"; -import { convertTileToScreen, getParameter, hash } from "./utils.js"; +import { isKeyUp, whichKeyDown } from "./keyboard.js"; +import { getParameter } from "./utils.js"; let assets = { images: { splash: "../img/splash1.webp", font: "../img/hampsterfont.webp", - tiles: "../img/t.webp", selector: "../img/selector.webp", }, - spritesheets: { - player: [ - {x: 0}, // looking up - {x: 16}, // looking right - {x: 32}, // looking down - {x: 48} // looking left - ] - } -} - -const tileTypes = { - 1: 1, // floor - 2: 2, // wall } let running = 1; @@ -90,6 +76,7 @@ let searchForRoom = (name) => { const changeRoom = (index) => { currentRoom = rooms[index]; roomIndex = index; + currentRoom.init(); } const loadingRoom = new Room("loading"); @@ -101,20 +88,21 @@ loadingRoom.updateStatus = (status) => { } const debugRoom = new Room("debug"); +debugRoom.init = () => { + if (!debug) changeRoom(searchForRoom("menu")); +} debugRoom.draw = () => { canvas.fill("black"); } debugRoom.drawGUI = () => { debugStatuses.push("Current Frame:"+currentFrame+`(~${Math.round((currentFrame/targetFrames)*100)/100} sec)`); } -debugRoom.keyDown = (key) => { - if (key == "Escape") changeRoom(searchForRoom("menu")); -} const menuRoom = new Room("menu"); menuRoom.options = [ {"label": "Start Game", "action": _ => {changeRoom(searchForRoom("game"))}}, ]; +if (debug) menuRoom.options.push({"label": "Debug Room", "action": _ => {changeRoom(searchForRoom("debug"))}}); menuRoom.index = 0; menuRoom.draw = () => { @@ -143,105 +131,8 @@ menuRoom.keyDown = (key) => { if (menuRoom.index >= menuRoom.options.length) menuRoom.index = 0; if (menuRoom.index < 0) menuRoom.index = menuRoom.options.length-1; } - -const getTileType = (x, y, data) => { - for (let i = 0; i < data.tiles.length; i++) { - let tile = data.tiles[i]; - if (tile.x == x && tile.y == y) return tileTypes[tile.id]; - } - return 0; -} - - -const renderTiles = (data) => { - for (let i = 0; i < data.tiles.length; i++) { - let tile = data.tiles[i]; - let tileLocation = convertTileToScreen(tile.x, tile.y); - let tId = tile.id; - - if (tile.id == 2) { - tId = 3; - // connect walls to each other. - // check the tile above, below, left, and right of this one. if it is also id 2, then set the corresponding variable to 1 - getTileType(tile.x, tile.y-1, data) == 2 ? tId += 1 : tId += 0; - getTileType(tile.x, tile.y+1, data) == 2 ? tId += 2 : tId += 0; - getTileType(tile.x-1, tile.y, data) == 2 ? tId += 4 : tId += 0; - getTileType(tile.x+1, tile.y, data) == 2 ? tId += 8 : tId += 0; - } - - canvas.sliceImage(assets.images.tiles, tileLocation.x, tileLocation.y, SCALE, SCALE, tId*16, 0, 16, 16); - } -} - -const gameRoom = new Room("game"); -gameRoom.data = { tiles: [ ] }; -gameRoom.draw = () => { - canvas.fill("black"); - - renderTiles(gameRoom.data); -} - -const levelEditor = new Room("editor"); -levelEditor.currentTile = { x: 0, y: 0, id: 0 }; -levelEditor.data = { tiles : [] }; -levelEditor.step = _ => { - - // place the camera at the center of the current tile if it is outside the screen - let tileLocation = convertTileToScreen(levelEditor.currentTile.x, levelEditor.currentTile.y); - if (tileLocation.x < canvas.cX) canvas.cX = tileLocation.x; - if (tileLocation.x >= canvas.cX+256) canvas.cX = tileLocation.x-canvas.width; - if (tileLocation.y < canvas.cY) canvas.cY = tileLocation.y; - if (tileLocation.y > canvas.cY+224) canvas.cY = tileLocation.y-canvas.height; - - - debugStatuses.push("Current tile:"+levelEditor.currentTile.x+","+levelEditor.currentTile.y); - debugStatuses.push("Current tile ID:"+levelEditor.currentTile.id); - debugStatuses.push("Camera:"+canvas.cX+","+canvas.cY); -} -levelEditor.keyDown = (key) => { - if (pressedLastFrame.includes(key)) return; - - const { currentTile, data } = levelEditor; - const { x, y, id } = currentTile; - - const keyActions = { - ArrowUp: () => currentTile.y--, - ArrowDown: () => currentTile.y++, - ArrowLeft: () => currentTile.x--, - ArrowRight: () => currentTile.x++, - PageUp: () => currentTile.id++, - PageDown: () => currentTile.id--, - KeyP: () => console.log(data), - Enter: () => { - data.tiles = data.tiles.filter(tile => tile.x !== x || tile.y !== y); - data.tiles.push({ id, x, y }); - }, - }; - - const action = keyActions[key]; - if (action) action(); -}; - -levelEditor.draw = () => { - canvas.fill("#010101"); - - renderTiles(levelEditor.data); - - canvas.drawLine(-canvas.width*100, 0, canvas.width*100, 0, "white"); - canvas.drawLine(0, -canvas.height*100, 0, canvas.height*100, "white"); - text.render("(0,0)", 1-canvas.cX, 1-canvas.cY) - - let tileLocation = convertTileToScreen(levelEditor.currentTile.x, levelEditor.currentTile.y); - canvas.ctx.globalAlpha = 0.5; - canvas.sliceImage(assets.images.tiles, tileLocation.x, tileLocation.y, SCALE, SCALE, levelEditor.currentTile.id*16, 0, 16, 16); - canvas.ctx.globalAlpha = 1; - canvas.drawImage(assets.images.selector, tileLocation.x, tileLocation.y, SCALE, SCALE); -} - rooms.push(loadingRoom); rooms.push(menuRoom); -rooms.push(gameRoom); -rooms.push(levelEditor); rooms.push(debugRoom); currentRoom = rooms[roomIndex]; @@ -264,6 +155,7 @@ let main = () => { // main game loop let currentKeys = whichKeyDown(); for (let i = 0; i < currentKeys.length; i++) { + if (isKeyUp(currentKeys[i]) && pressedLastFrame.includes(currentKeys[i])) continue; if (debug) debugStatuses.push(currentKeys[i]); currentRoom.keyDown(currentKeys[i]); } @@ -272,7 +164,7 @@ let main = () => { // main game loop if (debug) { text.render("FPS:" + Math.round(1000 / delta), 0, 0); - text.render(currentRoom.name, canvas.width-8*(currentRoom.name.length), 0); + text.render(currentRoom.name, canvas.width-(text.charWidth*(currentRoom.name.length)), 0); debugStatuses.push("Debug mode"); if (currentFrame <= 60*5) { @@ -282,7 +174,10 @@ let main = () => { // main game loop } for (let i = 0; i < debugStatuses.length; i++) { - text.render(debugStatuses[i], 0, canvas.height-7*(debugStatuses.length-i)); + // console.debug(debugStatuses[i]); + if (typeof(debugStatuses[i]) == "string") text.render(debugStatuses[i], 0, canvas.height-text.charHeight*(debugStatuses.length-i)); + if (typeof(debugStatuses[i]) == "object") {text.render(debugStatuses[i].msg, 0, canvas.height-text.charHeight*(debugStatuses.length-i)); debugStatuses[i].ttl--;} + } lastFrameTime = now; @@ -302,8 +197,7 @@ let init = () => { console.log("Images loaded.") currentRoom.updateStatus("Loading complete!"); setTimeout(() => { - let rm = getParameter("room") - (rm ? changeRoom(searchForRoom(rm)) : changeRoom(searchForRoom("menu"))); + (getParameter("room") ? changeRoom(searchForRoom(getParameter("room"))) : changeRoom(searchForRoom("menu"))); main(); }, 1000); } diff --git a/src/js/objects.js b/src/js/objects.js index 9113a0b8b884f786697217ecfa32682b76ff9531..f1941091b405183685b8c6ce3bb0c87165da43f6 100644 --- a/src/js/objects.js +++ b/src/js/objects.js @@ -11,6 +11,8 @@ class Room extends Object { this.name = name; // needs to be unique, otherwise the searching code will just use the first one it finds. } + init(){} + draw() { for (let i = 0; i < this.objects.length; i++) { this.objects[i].draw(); diff --git a/src/js/text.js b/src/js/text.js index cbe816deed3bea64952879fce8baf42737e00fa6..9fd464c6f1e0d0b203ce3e4d3b6c2354e16b199d 100644 --- a/src/js/text.js +++ b/src/js/text.js @@ -3,8 +3,11 @@ class TextRenderer { constructor(canvas, fontimg) { this.fontimg = fontimg; // MUST BE AN IMAGE OBJECT - this.fontWidth = 7; - this.fontHeight = 7; + this.fontWidth = 5; + this.fontHeight = 5; + this.spacing = 1; + this.charWidth = this.fontWidth + this.spacing; + this.charHeight = this.fontHeight + this.spacing; this.fontChars = "abcdefghijklmnopqrstuvwxyz1234567890.,!?:;)(~>"; this.canvas = canvas; } @@ -39,7 +42,7 @@ class TextRenderer { xOffset = 0; continue; } - this.drawLetter(text[i], x + (xOffset * this.fontWidth), y + (heightOffset * this.fontHeight)); + this.drawLetter(text[i], (x + (xOffset * (this.fontWidth + this.spacing))), y + (heightOffset * this.fontHeight)); xOffset++; } } diff --git a/src/js/utils.js b/src/js/utils.js index 15051afa7be70d7ddc1768ec7c16284e8e5caad9..9f6bcc2dc300571f93f105896930cd3a33bb702c 100644 --- a/src/js/utils.js +++ b/src/js/utils.js @@ -1,36 +1,8 @@ // random shit -import { SCALE } from "./config"; - const params = new URLSearchParams(location.search); export const pi = Math.PI; -export const convertTileToScreen = (x, y) => ({x: x*SCALE, y: y*SCALE}); export const getParameter = key => key ? params.get(key) : 0; -export const hash = window.location.hash.split("?")[0].slice(1); - -// The following code is responsible for building levels. -const lineToCoords=(x0,y0,x1,y1,id=2)=>{const c=[];let dx=Math.abs(x1-x0),dy=Math.abs(y1-y0),sx=(x0<x1)?1:-1,sy=(y0<y1)?1:-1,err=dx-dy;while(true){c.push({x:x0,y:y0,id:id});if(x0===x1&&y0===y1)break;const e2=2*err;if(e2>-dy){err-=dy;x0+=sx}if(e2<dx){err+=dx;y0+=sy}}return c}; - -const generateBox = (x, y, width, height, fillTileId=1) => { - const box = []; - - for (let y = y; y < height; y++) { - for (let x = x; x < width; x++) { - box.push({ x, y, id: fillTileId }); - } - } - - return box; -} - -export const generateRoom = (x,y,width,height,lineId=2,fillId=1) => { - let top = lineToCoords(x, y, x+width, y, lineId); - let bottom = lineToCoords(x, y+height, x+width, y+height, lineId); - let left = lineToCoords(x, y, x, y+height, lineId); - let right = lineToCoords(x+width, y, x+width, y+height, lineId); - - let fill = generateBox(x+1, y+1, x+width-1, y+height-1, fillId); - - return [...top, ...bottom, ...left, ...right, ...fill]; -} +export const hash = _ => window.location.hash; +export const setHash = string => window.location.hash = string;