diff --git a/builtins.ts b/builtins.ts index ec79209..88fe81d 100644 --- a/builtins.ts +++ b/builtins.ts @@ -10,8 +10,17 @@ import { resetRepl } from "./repl.ts"; import { COLOR } from "./colors.ts"; import { getSheet, getCodeSheet } from "./sheet.ts"; +let spritesheet: number | null = null; + +export const useSpritesheet = (sheet: number) => { + spritesheet = sheet; +} + export const drawSprite = (x: number, y: number, spr: number) => { - const {sheet_type, value: sprites} = getSheet(2); + if (!spritesheet) { + return; + } + const {sheet_type, value: sprites} = getSheet(spritesheet); if (sheet_type !== "spritesheet") { throw "Trying to run a non-code sheet as code." } @@ -37,6 +46,7 @@ const faux = { resetRepl(); clearScreen(); }, + sprsht: useSpritesheet, spr: drawSprite, txt: drawText, rect: fillRect, diff --git a/cart_unpacked.json b/cart_unpacked.json index 972d159..a992d83 100644 --- a/cart_unpacked.json +++ b/cart_unpacked.json @@ -5,7 +5,59 @@ }, { "sheet_type": "code", - "value": "speed = 2;\nreturn 8;" + "value": "sprsht(15);\nspeed = 2;\nreturn 8;" + }, + { + "sheet_type": "none", + "value": null + }, + { + "sheet_type": "none", + "value": null + }, + { + "sheet_type": "none", + "value": null + }, + { + "sheet_type": "none", + "value": null + }, + { + "sheet_type": "none", + "value": null + }, + { + "sheet_type": "none", + "value": null + }, + { + "sheet_type": "none", + "value": null + }, + { + "sheet_type": "none", + "value": null + }, + { + "sheet_type": "none", + "value": null + }, + { + "sheet_type": "none", + "value": null + }, + { + "sheet_type": "none", + "value": null + }, + { + "sheet_type": "none", + "value": null + }, + { + "sheet_type": "none", + "value": null }, { "sheet_type": "spritesheet", diff --git a/codetab.ts b/codetab.ts index cc14861..01f8966 100644 --- a/codetab.ts +++ b/codetab.ts @@ -2,15 +2,16 @@ import { clearScreen, fillRect } from "./window.ts"; import { fontWidth, fontHeight } from "./font.ts"; import { drawText } from "./builtins.ts"; import { COLOR } from "./colors.ts"; -import {getCodeSheet, setSheet} from "./sheet.ts"; +import { getCodeSheet, setSheet } from "./sheet.ts"; import { K, ctrlKeyDown, getKeyboardString, keyPressed, shiftKeyDown } from "./keyboard.ts"; import { clipboard, tokenize } from "./deps.ts"; import { getContext } from "./runcode.ts"; +import { page } from "./viewsheets.ts"; const historyDebounceFrames = 20; const state = { - history: [{code: getCodeSheet(0), anchor: 0, focus: 0}], + history: [{code: getCodeSheet(page.activeSheet), anchor: 0, focus: 0}], historyDebounce: 0, historyIndex: 0, undo() { @@ -201,10 +202,10 @@ const state = { return match[0]; }, get code() { - return getCodeSheet(0); + return getCodeSheet(page.activeSheet); }, set code(val) { - setSheet(0, "code", val); + setSheet(page.activeSheet, "code", val); } } diff --git a/editmode.ts b/editmode.ts index 595daa5..44f9355 100644 --- a/editmode.ts +++ b/editmode.ts @@ -1,72 +1,61 @@ import { clearScreen, fillRect } from "./window.ts"; import { codetab } from "./codetab.ts"; import { spritetab } from "./spritetab.ts"; +import { viewsheets, page } from "./viewsheets.ts"; import { COLOR } from "./colors.ts"; import { mouseClick, mousePos } from "./mouse.ts"; import { drawIcon } from "./builtins.ts"; import { inRect } from "./util.ts"; +import { sheetsIcon } from "./icons.ts"; +import { SheetType } from "./sheet.ts"; +import { nonetab } from "./nonetab.ts"; -type TabName = "code" | "sprite" | "map" | "sfx" | "music"; - -let tab: TabName = "code"; - -const codeIcon = [ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 1, 0, 0, - 0, 1, 1, 0, 0, 1, 1, 0, - 0, 1, 0, 0, 0, 0, 1, 0, - 0, 1, 0, 0, 0, 0, 1, 0, - 0, 1, 1, 0, 0, 1, 1, 0, - 0, 0, 1, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -]; - -const spriteIcon = [ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 1, 1, 1, 0, 0, - 0, 1, 1, 0, 1, 1, 1, 0, - 0, 1, 1, 1, 1, 0, 0, 0, - 0, 1, 1, 1, 0, 0, 0, 0, - 0, 1, 1, 1, 1, 1, 1, 0, - 0, 0, 1, 1, 1, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -]; +type TabName = SheetType; // "code" | "sprite" | "map" | "sfx" | "music" | "sheet"; const buttons: Array<{update: () => void, draw: () => void}> = []; -const makeTabButton = (tabname: TabName, x: number, y: number, icon: Array) => { +const makeTabButton = (tabname: TabName | "sheet", x: number, y: number, icon: Array) => { buttons.push({ update() { if (mouseClick()) { const {x: mouseX, y: mouseY} = mousePos(); if (inRect(mouseX, mouseY, x, y, 8, 8)) { - tab = tabname; + page.tab = tabname; } } }, draw() { - drawIcon(x, y, icon, tab === tabname ? COLOR.YELLOW : COLOR.WHITE); + drawIcon(x, y, icon, page.tab === tabname ? COLOR.YELLOW : COLOR.WHITE); } }) } -makeTabButton("code", 88, 0, codeIcon); -makeTabButton("sprite", 88+8, 0, spriteIcon); +// makeTabButton("code", 88, 0, codeIcon); +// makeTabButton("sprite", 88+8, 0, spriteIcon); +makeTabButton("sheet", 120, 0, sheetsIcon); const update = () => { buttons.forEach(button => button.update()); - if (tab === "code") { + if (page.tab === "code") { codetab.update(); - } else if (tab === "sprite") { + } else if (page.tab === "spritesheet") { spritetab.update(); + } else if (page.tab === "sheet") { + viewsheets.update(); + } else if (page.tab === "none") { + nonetab.update(); } } const draw = () => { clearScreen(); - if (tab === "code") { + if (page.tab === "code") { codetab.draw(); - } else if (tab === "sprite") { + } else if (page.tab === "spritesheet") { spritetab.draw(); + } else if (page.tab === "sheet") { + viewsheets.draw(); + } else if (page.tab === "none") { + nonetab.draw(); } fillRect(0, 0, 128, 8, COLOR.RED); fillRect(0, 120, 128, 8, COLOR.RED); diff --git a/icons.ts b/icons.ts new file mode 100644 index 0000000..0b91aea --- /dev/null +++ b/icons.ts @@ -0,0 +1,32 @@ +export const codeIcon = [ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, + 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +]; + +export const spriteIcon = [ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +]; + +export const sheetsIcon = [ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +]; diff --git a/index.ts b/index.ts index 11ec162..1ac7bb3 100644 --- a/index.ts +++ b/index.ts @@ -32,7 +32,6 @@ await mainloop(async (_t) => { edit: "repl", repl: "edit", } as const)[mode]; - console.log(`pressed escape (${mode} -> ${modeTo})`); if (mode === "play") { resetRepl(); } diff --git a/nonetab.ts b/nonetab.ts new file mode 100644 index 0000000..ba86bfa --- /dev/null +++ b/nonetab.ts @@ -0,0 +1,58 @@ +import { clearScreen, fillRect } from "./window.ts"; +import { drawIcon } from "./builtins.ts"; +import { COLOR } from "./colors.ts"; +import { getSheet, setSheet } from "./sheet.ts"; +import { mouseClick, mousePos } from "./mouse.ts"; +import { reGridWithGap } from "./util.ts"; +import { page } from "./viewsheets.ts"; +import { useSpritesheet } from "./builtins.ts"; +import { codeIcon, spriteIcon } from "./icons.ts"; + +const gridX = 8; +const gridY = 16; +const cellW = 8; +const cellH = 8; +const gapX = 8; +const gapY = 8; + +const sheetTypes = ["code", "spritesheet"] as const; +const defaultSheetVal = { + code: () => "", + spritesheet: () => Array(64).fill(0).map(() => Array(64).fill(0)), + none: () =>null, +} + +const update = () => { + if (mouseClick()) { + const {x: mouseX, y: mouseY} = mousePos(); + const g = reGridWithGap(mouseX, mouseY, gridX, gridY, cellW, cellH, gapX, gapY); + if (g) { + const {x, y: _y} = g; + const sheetType = sheetTypes[x]; + setSheet(page.activeSheet, sheetType, defaultSheetVal[sheetType]()); + page.tab = getSheet(page.activeSheet).sheet_type; + } + } +} +const draw = () => { + clearScreen(); + useSpritesheet(page.activeSheet); + fillRect(0, 8, 128, 112, COLOR.BLACK); + + // Draw the spritesheet + sheetTypes.forEach((sheetType, i) => { + const sx = gridX+(cellW+gapX)*(i%6); + const sy = gridY+(cellH+gapY)*Math.floor(i/6); + const icon = { + code: codeIcon, + spritesheet: spriteIcon, + none: null, + }[sheetType]; + drawIcon(sx, sy, icon, COLOR.BLUE); + }); +} + +export const nonetab = { + update, + draw, +} \ No newline at end of file diff --git a/sheet.ts b/sheet.ts index 08704dc..cf21b85 100644 --- a/sheet.ts +++ b/sheet.ts @@ -8,6 +8,9 @@ export type Sheet = { } | { sheet_type: "spritesheet", value: Array>, +} | { + sheet_type: "none", + value: null, } export type SheetType = Sheet["sheet_type"]; diff --git a/spritetab.ts b/spritetab.ts index cb89019..aeca556 100644 --- a/spritetab.ts +++ b/spritetab.ts @@ -1,22 +1,20 @@ import { clearScreen, fillRect, setPixelColor } from "./window.ts"; import { drawSprite } from "./builtins.ts"; import { COLOR } from "./colors.ts"; -import {getSheet, setSheet} from "./sheet.ts"; +import { getSpriteSheet, setSheet } from "./sheet.ts"; import { mouseHeld, mousePos } from "./mouse.ts"; -import { inRect } from "./util.ts"; +import { inRect, reGrid } from "./util.ts"; +import { page } from "./viewsheets.ts"; +import { useSpritesheet } from "./builtins.ts"; const state = { selectedSprite: 0, selectedColor: 0, get sprites() { - const {sheet_type, value} = getSheet(2); - if (sheet_type !== "spritesheet") { - throw "Trying to use a non-sprite sheet as a spritesheet." - } - return value; + return getSpriteSheet(page.activeSheet); }, set sprites(val) { - setSheet(0, "spritesheet", val); + setSheet(page.activeSheet, "spritesheet", val); } } @@ -40,13 +38,6 @@ const sheetY = 88; const sheetW = 16; const sheetH = 4; -const reGrid = (x: number, y: number, gridX: number, gridY: number, cellW: number, cellH: number) => { - return { - x: Math.floor((x-gridX)/cellW), - y: Math.floor((y-gridY)/cellH), - } -} - const update = () => { if (mouseHeld()) { const {x: mouseX, y: mouseY} = mousePos(); @@ -87,6 +78,7 @@ const drawTransparentRect = (x: number, y: number, w: number, h: number) => { const draw = () => { const {sprites, selectedSprite, selectedColor} = state; clearScreen(); + useSpritesheet(page.activeSheet); fillRect(0, 8, 128, 112, COLOR.BROWN); // Draw the palette diff --git a/util.ts b/util.ts index f839908..a656ed8 100644 --- a/util.ts +++ b/util.ts @@ -5,4 +5,25 @@ export const inRect = (x: number, y: number, rectX: number, rectY: number, rectW y >= rectY && y < rectY+rectH ) +} + +export function reGridWithGap (x: number, y: number, gridX: number, gridY: number, cellW: number, cellH: number, gapX: number, gapY: number): {x: number, y: number} | null { + const gx = Math.floor((x-gridX)/(cellW+gapX)); + const gy = Math.floor((y-gridY)/(cellH+gapY)); + if (x >= gridX+(cellW+gapX)*gx+cellW || y >= gridY+(cellH+gapY)*gy+cellH) { + return null; + } + return { + x: Math.floor((x-gridX)/(cellW+gapX)), + y: Math.floor((y-gridY)/(cellH+gapY)), + } +} + +export function reGrid (x: number, y: number, gridX: number, gridY: number, cellW: number, cellH: number): {x: number, y: number} { + const gx = Math.floor((x-gridX)/(cellW)); + const gy = Math.floor((y-gridY)/(cellH)); + return { + x: gx, + y: gy, + } } \ No newline at end of file diff --git a/viewsheets.ts b/viewsheets.ts new file mode 100644 index 0000000..716dfb4 --- /dev/null +++ b/viewsheets.ts @@ -0,0 +1,56 @@ +import { clearScreen, fillRect } from "./window.ts"; +import { drawIcon, drawText } from "./builtins.ts"; +import { COLOR } from "./colors.ts"; +import { getSheet } from "./sheet.ts"; +import { mouseClick, mousePos } from "./mouse.ts"; +import { getCart } from "./cart.ts"; +import { fontHeight } from "./font.ts"; +import { codeIcon, spriteIcon } from "./icons.ts"; +import { reGridWithGap } from "./util.ts"; + +export const page = {activeSheet: 0, tab: "sheet"}; + +const gridX = 8; +const gridY = 20; +const cellW = 22; +const cellH = 16; +const gapX = 8; +const gapY = 8; + +const update = () => { + if (mouseClick()) { + const {x: mouseX, y: mouseY} = mousePos(); + const g = reGridWithGap(mouseX, mouseY, gridX, gridY, cellW, cellH, gapX, gapY); + if (g) { + const {x, y} = g; + page.activeSheet = 4*y+x; + page.tab = getSheet(page.activeSheet).sheet_type; + } + } +} + +const draw = () => { + clearScreen(); + fillRect(0, 8, 128, 112, COLOR.BROWN); + + // Draw the sheet grid + getCart().forEach((sheet, i) => { + const x = gridX+(cellW+gapX)*(i%4); + const y = gridY+(cellH+gapY)*Math.floor(i/4); + fillRect(x, y, cellW, cellH, i===page.activeSheet ? COLOR.PURPLE : COLOR.BLACK); + drawText(x+(cellW)/2, y+(cellH-fontHeight)/2, i.toString().padStart(2,"0")); + const icon = { + code: codeIcon, + spritesheet: spriteIcon, + none: null, + }[sheet.sheet_type]; + if (icon) { + drawIcon(x+2, y+4, icon, COLOR.WHITE); + } + }); +} + +export const viewsheets = { + update, + draw, +} \ No newline at end of file