Basic map editor!
This commit is contained in:
parent
194209f18f
commit
f8b3f5d645
1
carts/tmp/maptest.fx
Normal file
1
carts/tmp/maptest.fx
Normal file
File diff suppressed because one or more lines are too long
@ -9,6 +9,7 @@ import { inRect } from "./util.ts";
|
||||
import { sheetsIcon, trashIcon } from "./icons.ts";
|
||||
import { SheetType, setSheet } from "./sheet.ts";
|
||||
import { nonetab } from "./nonetab.ts";
|
||||
import { maptab } from "./maptab.ts";
|
||||
|
||||
type TabName = SheetType; // "code" | "sprite" | "map" | "sfx" | "music" | "sheet";
|
||||
|
||||
@ -61,6 +62,8 @@ const update = () => {
|
||||
codetab.update();
|
||||
} else if (page.tab === "spritesheet") {
|
||||
spritetab.update();
|
||||
} else if (page.tab === "map") {
|
||||
maptab.update();
|
||||
} else if (page.tab === "sheet") {
|
||||
viewsheets.update();
|
||||
} else if (page.tab === "none") {
|
||||
@ -74,6 +77,8 @@ const draw = () => {
|
||||
codetab.draw();
|
||||
} else if (page.tab === "spritesheet") {
|
||||
spritetab.draw();
|
||||
} else if (page.tab === "map") {
|
||||
maptab.draw();
|
||||
} else if (page.tab === "sheet") {
|
||||
viewsheets.draw();
|
||||
} else if (page.tab === "none") {
|
||||
|
11
icons.ts
11
icons.ts
@ -20,6 +20,17 @@ export const spriteIcon = [
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
];
|
||||
|
||||
export const mapIcon = [
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 1, 1, 1, 1, 1, 1, 0,
|
||||
0, 1, 0, 1, 0, 0, 1, 0,
|
||||
0, 1, 0, 1, 1, 1, 1, 0,
|
||||
0, 1, 1, 1, 0, 0, 1, 0,
|
||||
0, 1, 0, 1, 0, 0, 1, 0,
|
||||
0, 1, 1, 1, 1, 1, 1, 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,
|
||||
|
162
maptab.ts
Normal file
162
maptab.ts
Normal file
@ -0,0 +1,162 @@
|
||||
import { clearScreen, fillRect } from "./window.ts";
|
||||
import { drawSprite, drawText } from "./builtins.ts";
|
||||
import { COLOR } from "./colors.ts";
|
||||
import { getMapSheet, getSheet, getSpriteSheet, setSheet } from "./sheet.ts";
|
||||
import { mouseHeld, mousePos } from "./mouse.ts";
|
||||
import { inRect, reGrid } from "./util.ts";
|
||||
import { page } from "./viewsheets.ts";
|
||||
import { useSpritesheet } from "./builtins.ts";
|
||||
|
||||
const state = {
|
||||
selectedSpriteSheet: 2,
|
||||
selectedSprite: 0,
|
||||
selectedPatch: 0,
|
||||
get map() {
|
||||
return getMapSheet(page.activeSheet);
|
||||
},
|
||||
set map(val) {
|
||||
setSheet(page.activeSheet, "map", val);
|
||||
},
|
||||
setInPatch(i: number, sprsheet: number, sprite: number) {
|
||||
const xx = this.selectedPatch%overviewW;
|
||||
const yy = Math.floor(this.selectedPatch/overviewW);
|
||||
const cell = (yy+patchH*Math.floor(i/patchW))*overviewW*patchW+xx*patchW+i%patchW;
|
||||
console.log({i, cell, xx, yy});
|
||||
this.map[cell] = [sprsheet, sprite];
|
||||
},
|
||||
get patch() {
|
||||
const xx = this.selectedPatch%overviewW;
|
||||
const yy = Math.floor(this.selectedPatch/overviewW);
|
||||
return Array(overviewH).fill(0).flatMap((_, i) => {
|
||||
const start = (yy+patchH*i)*overviewW*patchW+xx*patchW;
|
||||
return this.map.slice(start, start+patchW);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const overviewX = 88;
|
||||
const overviewY = 12;
|
||||
const miniPatchW = 4;
|
||||
const miniPatchH = 4;
|
||||
const overviewW = 8;
|
||||
const overviewH = 8;
|
||||
|
||||
const patchX = 8;
|
||||
const patchY = 12;
|
||||
const patchW = 8;
|
||||
const patchH = 8;
|
||||
|
||||
const spriteW = 8;
|
||||
const spriteH = 8;
|
||||
|
||||
const spriteSheetX = 0;
|
||||
const spriteSheetY = 88;
|
||||
const spriteSheetW = 16;
|
||||
const spriteSheetH = 4;
|
||||
|
||||
const spriteSheetPickerX = 0;
|
||||
const spriteSheetPickerY = 79;
|
||||
const spriteSheetPickerW = 16;
|
||||
const spriteSheetPickerH = 1;
|
||||
const spriteSheetPickerTabW = 8;
|
||||
const spriteSheetPickerTabH = 8;
|
||||
|
||||
const update = () => {
|
||||
if (mouseHeld()) {
|
||||
const {x: mouseX, y: mouseY} = mousePos();
|
||||
const inOverview = inRect(mouseX, mouseY, overviewX, overviewY, overviewW*miniPatchW, overviewH*miniPatchH);
|
||||
const inPatch = inRect(mouseX, mouseY, patchX, patchY, patchW*spriteW, patchH*spriteH);
|
||||
const inSpriteSheetPicker = inRect(mouseX, mouseY, spriteSheetPickerX, spriteSheetPickerY, spriteSheetPickerW*spriteSheetPickerTabW, spriteSheetPickerH*spriteSheetPickerTabH);
|
||||
const inSpriteSheet = inRect(mouseX, mouseY, spriteSheetX, spriteSheetY, spriteSheetW*spriteW, spriteSheetH*spriteH);
|
||||
if (inOverview) {
|
||||
const {x, y} = reGrid(mouseX, mouseY, overviewX, overviewY, miniPatchW, miniPatchH);
|
||||
state.selectedPatch = overviewW*y+x;
|
||||
}
|
||||
if (inPatch) {
|
||||
const {x, y} = reGrid(mouseX, mouseY, patchX, patchY, spriteW, spriteH);
|
||||
const cellNumber = spriteW*y+x;
|
||||
state.setInPatch(cellNumber, state.selectedSpriteSheet, state.selectedSprite);
|
||||
}
|
||||
if (inSpriteSheetPicker) {
|
||||
const {x, y} = reGrid(mouseX, mouseY, spriteSheetPickerX, spriteSheetPickerY, spriteSheetPickerTabW, spriteSheetPickerTabH);
|
||||
state.selectedSpriteSheet = spriteSheetPickerW*y+x;
|
||||
}
|
||||
if (inSpriteSheet) {
|
||||
const {x, y} = reGrid(mouseX, mouseY, spriteSheetX, spriteSheetY, spriteW, spriteH);
|
||||
state.selectedSprite = spriteSheetW*y+x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const outlineRect = (x: number, y: number, w: number, h: number, color: number) => {
|
||||
fillRect(x, y, w, 1, color);
|
||||
fillRect(x, y, 1, h, color);
|
||||
fillRect(x+w-1, y, 1, h, color);
|
||||
fillRect(x, y+h-1, w, 1, color);
|
||||
}
|
||||
|
||||
const draw = () => {
|
||||
const {
|
||||
selectedSpriteSheet,
|
||||
selectedSprite,
|
||||
selectedPatch
|
||||
} = state;
|
||||
clearScreen();
|
||||
fillRect(0, 8, 128, 112, COLOR.DARKGRAY);
|
||||
|
||||
// Draw the overview
|
||||
fillRect(overviewX-1, overviewY-1, (overviewW*miniPatchW)+2, (overviewH*miniPatchH)+2, COLOR.BLACK);
|
||||
Array(overviewW*overviewH).fill(0).forEach((_, i) => {
|
||||
const miniPatchX = overviewX+miniPatchW*(i%overviewW);
|
||||
const miniPatchY = overviewY+miniPatchH*Math.floor(i/overviewW);
|
||||
if (i === selectedPatch) {
|
||||
outlineRect(miniPatchX, miniPatchY, miniPatchW, miniPatchH, COLOR.WHITE);
|
||||
}
|
||||
});
|
||||
|
||||
// Draw the current patch
|
||||
fillRect(patchX-1, patchY-1, (patchW*spriteW)+2, (patchH*spriteH)+2, COLOR.BLACK);
|
||||
state.patch.forEach(([sprsheet, sprite], i) => {
|
||||
const spriteX = patchX+spriteW*(i%patchW);
|
||||
const spriteY = patchY+spriteH*Math.floor(i/patchW);
|
||||
if (getSheet(sprsheet).sheet_type === "spritesheet") {
|
||||
useSpritesheet(sprsheet);
|
||||
drawSprite(spriteX, spriteY, sprite);
|
||||
}
|
||||
});
|
||||
|
||||
// Draw the spritesheet picker
|
||||
fillRect(spriteSheetPickerX, spriteSheetPickerY, spriteSheetPickerTabW*spriteSheetPickerW, spriteSheetPickerTabW, COLOR.BLACK);
|
||||
Array(spriteSheetPickerW*spriteSheetPickerH).fill(0).forEach((_, i) => {
|
||||
const tabX = spriteSheetPickerX+spriteSheetPickerTabW*(i%spriteSheetPickerW);
|
||||
const tabY = spriteSheetPickerY+spriteSheetPickerTabH*Math.floor(i/spriteSheetPickerW);
|
||||
let color = COLOR.DARKGREEN;
|
||||
if (getSheet(i).sheet_type !== "spritesheet") {
|
||||
color = COLOR.BROWN;
|
||||
}
|
||||
if (i === selectedSpriteSheet) {
|
||||
color = color === COLOR.BROWN ? COLOR.TAN : COLOR.GREEN;
|
||||
}
|
||||
fillRect(tabX, tabY, spriteSheetPickerTabW, spriteSheetPickerTabH, color);
|
||||
drawText(tabX+2, tabY+1, ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"][i]);
|
||||
});
|
||||
|
||||
// Draw the spritesheet
|
||||
fillRect(spriteSheetX, spriteSheetY-1, (spriteSheetW*spriteW), (spriteSheetH*spriteH)+1, COLOR.BLACK);
|
||||
if (getSheet(selectedSpriteSheet).sheet_type === "spritesheet") {
|
||||
useSpritesheet(selectedSpriteSheet);
|
||||
getSpriteSheet(selectedSpriteSheet).forEach((_sprite, i) => {
|
||||
const sprX = spriteSheetX+spriteW*(i%spriteSheetW);
|
||||
const sprY = spriteSheetY+spriteH*Math.floor(i/spriteSheetW);
|
||||
drawSprite(sprX, sprY, i);
|
||||
if (i === selectedSprite) {
|
||||
outlineRect(sprX, sprY, spriteW, spriteH, COLOR.WHITE);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const maptab = {
|
||||
update,
|
||||
draw,
|
||||
}
|
@ -6,7 +6,7 @@ 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";
|
||||
import { codeIcon, mapIcon, spriteIcon } from "./icons.ts";
|
||||
|
||||
const gridX = 8;
|
||||
const gridY = 40;
|
||||
@ -15,10 +15,11 @@ const cellH = 8;
|
||||
const gapX = 8;
|
||||
const gapY = 8;
|
||||
|
||||
const sheetTypes = ["code", "spritesheet"] as const;
|
||||
const sheetTypes = ["code", "spritesheet", "map"] as const;
|
||||
const defaultSheetVal = {
|
||||
code: () => "",
|
||||
spritesheet: () => Array(64).fill(0).map(() => Array(64).fill(0)),
|
||||
map: () => Array(64*64).fill(0).map(() => [0, 0]),
|
||||
none: () =>null,
|
||||
}
|
||||
|
||||
@ -49,6 +50,7 @@ const draw = () => {
|
||||
const icon = {
|
||||
code: codeIcon,
|
||||
spritesheet: spriteIcon,
|
||||
map: mapIcon,
|
||||
none: null,
|
||||
}[sheetType];
|
||||
drawIcon(sx, sy, icon, COLOR.BLUE);
|
||||
|
13
sheet.ts
13
sheet.ts
@ -8,6 +8,9 @@ export type Sheet = {
|
||||
} | {
|
||||
sheet_type: "spritesheet",
|
||||
value: Array<Array<number>>,
|
||||
} | {
|
||||
sheet_type: "map",
|
||||
value: Array<[number, number]>,
|
||||
} | {
|
||||
sheet_type: "none",
|
||||
value: null,
|
||||
@ -34,7 +37,15 @@ export const getCodeSheet = (sheet: number) => {
|
||||
export const getSpriteSheet = (sheet: number) => {
|
||||
const {sheet_type, value} = getSheet(sheet);
|
||||
if (sheet_type !== "spritesheet") {
|
||||
throw "Trying to use a non-sprite sheet as a spritesheet."
|
||||
throw Error("Trying to use a non-sprite sheet as a spritesheet.");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
export const getMapSheet = (sheet: number) => {
|
||||
const {sheet_type, value} = getSheet(sheet);
|
||||
if (sheet_type !== "map") {
|
||||
throw "Trying to use a non-map sheet as a map."
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import { getSheet } from "./sheet.ts";
|
||||
import { mouseClick, mousePos } from "./mouse.ts";
|
||||
import { getCart } from "./cart.ts";
|
||||
import { font } from "./font.ts";
|
||||
import { codeIcon, spriteIcon } from "./icons.ts";
|
||||
import { codeIcon, spriteIcon, mapIcon } from "./icons.ts";
|
||||
import { reGridWithGap } from "./util.ts";
|
||||
|
||||
const fontHeight = font.height;
|
||||
@ -44,6 +44,7 @@ const draw = () => {
|
||||
const icon = {
|
||||
code: codeIcon,
|
||||
spritesheet: spriteIcon,
|
||||
map: mapIcon,
|
||||
none: null,
|
||||
}[sheet.sheet_type];
|
||||
if (icon) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user