Starting on sprite editor
This commit is contained in:
parent
b87529bf56
commit
f2b5978cae
3
cart.ts
3
cart.ts
@ -1,6 +1,7 @@
|
|||||||
import fakeCart from "./cart_unpacked.json" assert { type: "json" };
|
import fakeCart from "./cart_unpacked.json" assert { type: "json" };
|
||||||
|
import { Sheet } from "./sheet.ts";
|
||||||
|
|
||||||
const cart = fakeCart;
|
const cart = fakeCart as Array<Sheet>;
|
||||||
|
|
||||||
export const loadCart = (_name: string) => {
|
export const loadCart = (_name: string) => {
|
||||||
return;
|
return;
|
||||||
|
@ -5,6 +5,41 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"sheet_type": "code",
|
"sheet_type": "code",
|
||||||
"value": "speed = 2; return (8)"
|
"value": "speed = 2;\nreturn 8;"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sheet_type": "spritesheet",
|
||||||
|
"value": [
|
||||||
|
[
|
||||||
|
2, 2, 2, 2, 2, 2, 2, 2,
|
||||||
|
2, 1, 1, 1, 1, 1, 1, 2,
|
||||||
|
2, 1, 1, 1, 1, 1, 1, 2,
|
||||||
|
2, 1, 1, 1, 1, 1, 1, 2,
|
||||||
|
2, 1, 1, 1, 1, 1, 1, 2,
|
||||||
|
2, 1, 1, 1, 1, 1, 1, 2,
|
||||||
|
2, 1, 1, 1, 1, 1, 1, 2,
|
||||||
|
2, 2, 2, 2, 2, 2, 2, 2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
2, 2, 2, 2, 2, 2, 2, 2,
|
||||||
|
2, 3, 3, 1, 1, 3, 3, 2,
|
||||||
|
2, 3, 3, 1, 1, 3, 3, 2,
|
||||||
|
2, 1, 1, 1, 1, 1, 1, 2,
|
||||||
|
2, 1, 1, 1, 1, 1, 1, 2,
|
||||||
|
2, 3, 3, 1, 1, 3, 3, 2,
|
||||||
|
2, 3, 3, 1, 1, 3, 3, 2,
|
||||||
|
2, 2, 2, 2, 2, 2, 2, 2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
2, 2, 2, 2, 2, 2, 2, 2,
|
||||||
|
2, 4, 4, 4, 4, 5, 5, 2,
|
||||||
|
2, 4, 4, 4, 5, 5, 5, 2,
|
||||||
|
2, 4, 4, 5, 5, 5, 6, 2,
|
||||||
|
2, 4, 5, 5, 5, 6, 6, 2,
|
||||||
|
2, 5, 5, 5, 6, 6, 6, 2,
|
||||||
|
2, 5, 5, 6, 6, 6, 6, 2,
|
||||||
|
2, 2, 2, 2, 2, 2, 2, 2
|
||||||
|
]
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
222
codetab.ts
Normal file
222
codetab.ts
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
import { clearScreen, fillRect } from "./window.ts";
|
||||||
|
import { fontWidth, fontHeight } from "./font.ts";
|
||||||
|
import { drawText } from "./builtins.ts";
|
||||||
|
import { COLOR } from "./colors.ts";
|
||||||
|
import {getSheet, setSheet} from "./sheet.ts";
|
||||||
|
import { K, getKeyboardString, keyPressed, shiftKeyDown } from "./keyboard.ts";
|
||||||
|
|
||||||
|
// TODO: Make scrolling work
|
||||||
|
const state = {
|
||||||
|
scrollX: 0,
|
||||||
|
scrollY: 0,
|
||||||
|
anchor: 0,
|
||||||
|
focus: 0,
|
||||||
|
get focusX() {return indexToGrid(this.code, this.focus).x;},
|
||||||
|
get focusY() {return indexToGrid(this.code, this.focus).y;},
|
||||||
|
get anchorX() {return indexToGrid(this.code, this.anchor).x;},
|
||||||
|
get anchorY() {return indexToGrid(this.code, this.anchor).y;},
|
||||||
|
isCollapsed() {
|
||||||
|
return this.anchor === this.focus;
|
||||||
|
},
|
||||||
|
clampInRange(n: number) {
|
||||||
|
return Math.max(0, Math.min(n, this.code.length))
|
||||||
|
},
|
||||||
|
setSelection(anchor: number | {x: number, y: number}, focus?: number | {x: number, y: number}) {
|
||||||
|
if (typeof anchor !== "number") {
|
||||||
|
anchor = gridToIndex(this.code, anchor.x, anchor.y);
|
||||||
|
}
|
||||||
|
focus = focus ?? anchor;
|
||||||
|
if (typeof focus !== "number") {
|
||||||
|
focus = gridToIndex(this.code, focus.x, focus.y);
|
||||||
|
}
|
||||||
|
this.anchor = this.clampInRange(anchor),
|
||||||
|
this.focus = this.clampInRange(focus);
|
||||||
|
},
|
||||||
|
setFocus(focus: number | {x: number, y: number}) {
|
||||||
|
if (typeof focus !== "number") {
|
||||||
|
focus = gridToIndex(this.code, focus.x, focus.y);
|
||||||
|
}
|
||||||
|
this.focus = this.clampInRange(focus);
|
||||||
|
},
|
||||||
|
insertText(text: string) {
|
||||||
|
const {code, anchor, focus} = this;
|
||||||
|
this.code = code.slice(0, Math.min(anchor, focus)) + text + code.slice(Math.max(anchor, focus));
|
||||||
|
this.setSelection(Math.min(anchor, focus) + text.length);
|
||||||
|
},
|
||||||
|
indent(indentString: string) {
|
||||||
|
const lines = this.code.split("\n");
|
||||||
|
const {focusX, focusY, anchorX, anchorY} = this;
|
||||||
|
const newLines = lines.map((line, i) => {
|
||||||
|
if (i >= Math.min(focusY, anchorY) && i <= Math.max(focusY, anchorY)) {
|
||||||
|
return indentString+line;
|
||||||
|
} else {
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.code = newLines.join("\n");
|
||||||
|
this.setSelection({x: anchorX+1, y: anchorY}, {x: focusX+1, y: focusY});
|
||||||
|
},
|
||||||
|
outdent(outdentRegex: RegExp) {
|
||||||
|
const lines = this.code.split("\n");
|
||||||
|
const {focusX, focusY, anchorX, anchorY} = this;
|
||||||
|
const newLines = lines.map((line, i) => {
|
||||||
|
const match = line.match(outdentRegex);
|
||||||
|
if (i >= Math.min(focusY, anchorY) && i <= Math.max(focusY, anchorY) && match) {
|
||||||
|
return line.slice(match[0].length);
|
||||||
|
} else {
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.code = newLines.join("\n");
|
||||||
|
this.setSelection({x: Math.max(0,anchorX-1), y: anchorY}, {x: Math.max(0,focusX-1), y: focusY});
|
||||||
|
},
|
||||||
|
backspace() {
|
||||||
|
const {code, focus} = this;
|
||||||
|
if (this.isCollapsed()) {
|
||||||
|
if (focus > 0) {
|
||||||
|
this.code = code.slice(0, focus-1) + code.slice(focus);
|
||||||
|
this.setSelection(focus-1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.insertText("");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
delete() {
|
||||||
|
const {code, focus} = this;
|
||||||
|
if (this.isCollapsed()) {
|
||||||
|
if (focus < code.length) {
|
||||||
|
this.code = code.slice(0, focus) + code.slice(1+focus);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.insertText("");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
get code() {
|
||||||
|
const {sheet_type, value} = getSheet(0);
|
||||||
|
if (sheet_type !== "code") {
|
||||||
|
throw "Trying to run a non-code sheet as code."
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
set code(val) {
|
||||||
|
setSheet(0, "code", val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const indexToGrid = (str: string, index: number) => {
|
||||||
|
const linesUpTo = str.slice(0,index).split("\n");
|
||||||
|
return {
|
||||||
|
x: linesUpTo[linesUpTo.length-1].length,
|
||||||
|
y: linesUpTo.length - 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const gridToIndex = (str: string, x: number, y: number) => {
|
||||||
|
const lines = str.split("\n");
|
||||||
|
if (y < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (y >= lines.length) {
|
||||||
|
return str.length;
|
||||||
|
}
|
||||||
|
return lines.slice(0, y).join("\n").length+Math.min(x, lines[y].length)+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const drawCodeField = (code: string, x: number, y: number, w: number, h: number) => {
|
||||||
|
const {
|
||||||
|
scrollX,
|
||||||
|
scrollY,
|
||||||
|
anchor,
|
||||||
|
focus,
|
||||||
|
} = state;
|
||||||
|
const {
|
||||||
|
x: focusX,
|
||||||
|
y: focusY,
|
||||||
|
} = indexToGrid(code, focus);
|
||||||
|
const {
|
||||||
|
x: anchorX,
|
||||||
|
y: anchorY,
|
||||||
|
} = indexToGrid(code, anchor);
|
||||||
|
fillRect(x, y, w, h, COLOR.DARKBLUE);
|
||||||
|
if (anchor === focus) {
|
||||||
|
fillRect(x+focusX*fontWidth-scrollX, y+focusY*(fontHeight+1)-scrollY, fontWidth+1, fontHeight+1, COLOR.RED);
|
||||||
|
} else {
|
||||||
|
// TODO: Draw this selection better
|
||||||
|
fillRect(x+anchorX*fontWidth-scrollX, y+anchorY*(fontHeight+1)-scrollY, fontWidth+1, fontHeight+1, COLOR.GREEN);
|
||||||
|
fillRect(x+focusX*fontWidth-scrollX, y+focusY*(fontHeight+1)-scrollY, fontWidth+1, fontHeight+1, COLOR.YELLOW);
|
||||||
|
}
|
||||||
|
// TODO: Add syntax highlighting use "npm:js-tokens" maybe?
|
||||||
|
code.split("\n").forEach((line, i) => {
|
||||||
|
drawText(x-scrollX, 1+y+i*(fontHeight+1)-scrollY, line);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const update = () => {
|
||||||
|
const { focus, focusX, focusY} = state;
|
||||||
|
const keyboardString = getKeyboardString();
|
||||||
|
if (keyboardString) {
|
||||||
|
state.insertText(keyboardString);
|
||||||
|
}
|
||||||
|
// TODO: Handle ctrl-C, ctrl-V, ctrl-X, ctrl-Z
|
||||||
|
// TODO: Make ctrl-/ do commenting out (take inspiration from tab)
|
||||||
|
|
||||||
|
if (keyPressed(K.ENTER)) {
|
||||||
|
// TODO: Make this play nicely with indentation
|
||||||
|
state.insertText("\n");
|
||||||
|
}
|
||||||
|
if (keyPressed(K.TAB)) {
|
||||||
|
if (!shiftKeyDown()) {
|
||||||
|
if (state.isCollapsed()) {
|
||||||
|
state.insertText("\t");
|
||||||
|
} else {
|
||||||
|
state.indent("\t");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
state.outdent(/^(\t| )/);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (keyPressed(K.BACKSPACE)) {
|
||||||
|
state.backspace();
|
||||||
|
}
|
||||||
|
if (keyPressed(K.DELETE)) {
|
||||||
|
state.delete();
|
||||||
|
}
|
||||||
|
if (keyPressed(K.ARROW_RIGHT)) {
|
||||||
|
if (shiftKeyDown()) {
|
||||||
|
state.setFocus(focus+1);
|
||||||
|
} else {
|
||||||
|
state.setSelection(focus+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (keyPressed(K.ARROW_LEFT)) {
|
||||||
|
if (shiftKeyDown()) {
|
||||||
|
state.setFocus(focus-1);
|
||||||
|
} else {
|
||||||
|
state.setSelection(focus-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (keyPressed(K.ARROW_DOWN)) {
|
||||||
|
if (shiftKeyDown()) {
|
||||||
|
state.setFocus({x: focusX, y: focusY+1});
|
||||||
|
} else {
|
||||||
|
state.setSelection({x: focusX, y: focusY+1});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (keyPressed(K.ARROW_UP)) {
|
||||||
|
if (shiftKeyDown()) {
|
||||||
|
state.setFocus({x: focusX, y: focusY-1});
|
||||||
|
} else {
|
||||||
|
state.setSelection({x: focusX, y: focusY-1});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const draw = () => {
|
||||||
|
clearScreen();
|
||||||
|
drawCodeField(state.code, 0, 8, 128, 112);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const codetab = {
|
||||||
|
update,
|
||||||
|
draw,
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
const colors = {
|
const colors = {
|
||||||
|
TRANSPARENT: [0, 0, 0],
|
||||||
BLACK: [0, 0, 0],
|
BLACK: [0, 0, 0],
|
||||||
WHITE: [1, 1, 1],
|
WHITE: [1, 1, 1],
|
||||||
RED: [1, 0, 0],
|
RED: [1, 0, 0],
|
||||||
@ -6,6 +7,7 @@ const colors = {
|
|||||||
GREEN: [0, 1, 0],
|
GREEN: [0, 1, 0],
|
||||||
BLUE: [0, 0, 1],
|
BLUE: [0, 0, 1],
|
||||||
DARKBLUE: [0.1, 0.05, 0.4],
|
DARKBLUE: [0.1, 0.05, 0.4],
|
||||||
|
BROWN: [0.6, 0.5, 0.4],
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export const palette: Array<[number, number, number, number]> = Object.values(colors).map(val => [...val, 1]);
|
export const palette: Array<[number, number, number, number]> = Object.values(colors).map(val => [...val, 1]);
|
||||||
|
215
editmode.ts
215
editmode.ts
@ -1,221 +1,28 @@
|
|||||||
import { clearScreen, fillRect } from "./window.ts";
|
import { clearScreen, fillRect } from "./window.ts";
|
||||||
import { fontWidth, fontHeight } from "./font.ts";
|
import { codetab } from "./codetab.ts";
|
||||||
import { drawText } from "./builtins.ts";
|
import { spritetab } from "./spritetab.ts";
|
||||||
import { COLOR } from "./colors.ts";
|
import { COLOR } from "./colors.ts";
|
||||||
import {getSheet, setSheet} from "./sheet.ts";
|
|
||||||
import { K, getKeyboardString, keyPressed, shiftKeyDown } from "./keyboard.ts";
|
|
||||||
|
|
||||||
// deno-lint-ignore prefer-const
|
// deno-lint-ignore prefer-const
|
||||||
let tab: "code" | "sprite" | "map" | "sfx" | "music" = "code";
|
let tab: "code" | "sprite" | "map" | "sfx" | "music" = "sprite";
|
||||||
|
|
||||||
// TODO: Make scrolling work
|
|
||||||
const codeTabState = {
|
|
||||||
scrollX: 0,
|
|
||||||
scrollY: 0,
|
|
||||||
anchor: 0,
|
|
||||||
focus: 0,
|
|
||||||
get focusX() {return indexToGrid(this.code, this.focus).x;},
|
|
||||||
get focusY() {return indexToGrid(this.code, this.focus).y;},
|
|
||||||
get anchorX() {return indexToGrid(this.code, this.anchor).x;},
|
|
||||||
get anchorY() {return indexToGrid(this.code, this.anchor).y;},
|
|
||||||
isCollapsed() {
|
|
||||||
return this.anchor === this.focus;
|
|
||||||
},
|
|
||||||
clampInRange(n: number) {
|
|
||||||
return Math.max(0, Math.min(n, this.code.length))
|
|
||||||
},
|
|
||||||
setSelection(anchor: number | {x: number, y: number}, focus?: number | {x: number, y: number}) {
|
|
||||||
if (typeof anchor !== "number") {
|
|
||||||
anchor = gridToIndex(this.code, anchor.x, anchor.y);
|
|
||||||
}
|
|
||||||
focus = focus ?? anchor;
|
|
||||||
if (typeof focus !== "number") {
|
|
||||||
focus = gridToIndex(this.code, focus.x, focus.y);
|
|
||||||
}
|
|
||||||
this.anchor = this.clampInRange(anchor),
|
|
||||||
this.focus = this.clampInRange(focus);
|
|
||||||
},
|
|
||||||
setFocus(focus: number | {x: number, y: number}) {
|
|
||||||
if (typeof focus !== "number") {
|
|
||||||
focus = gridToIndex(this.code, focus.x, focus.y);
|
|
||||||
}
|
|
||||||
this.focus = this.clampInRange(focus);
|
|
||||||
},
|
|
||||||
insertText(text: string) {
|
|
||||||
const {code, anchor, focus} = this;
|
|
||||||
this.code = code.slice(0, Math.min(anchor, focus)) + text + code.slice(Math.max(anchor, focus));
|
|
||||||
this.setSelection(Math.min(anchor, focus) + text.length);
|
|
||||||
},
|
|
||||||
indent(indentString: string) {
|
|
||||||
const lines = this.code.split("\n");
|
|
||||||
const {focusX, focusY, anchorX, anchorY} = this;
|
|
||||||
const newLines = lines.map((line, i) => {
|
|
||||||
if (i >= Math.min(focusY, anchorY) && i <= Math.max(focusY, anchorY)) {
|
|
||||||
return indentString+line;
|
|
||||||
} else {
|
|
||||||
return line;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.code = newLines.join("\n");
|
|
||||||
this.setSelection({x: anchorX+1, y: anchorY}, {x: focusX+1, y: focusY});
|
|
||||||
},
|
|
||||||
outdent(outdentRegex: RegExp) {
|
|
||||||
const lines = this.code.split("\n");
|
|
||||||
const {focusX, focusY, anchorX, anchorY} = this;
|
|
||||||
const newLines = lines.map((line, i) => {
|
|
||||||
const match = line.match(outdentRegex);
|
|
||||||
if (i >= Math.min(focusY, anchorY) && i <= Math.max(focusY, anchorY) && match) {
|
|
||||||
return line.slice(match[0].length);
|
|
||||||
} else {
|
|
||||||
return line;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.code = newLines.join("\n");
|
|
||||||
this.setSelection({x: Math.max(0,anchorX-1), y: anchorY}, {x: Math.max(0,focusX-1), y: focusY});
|
|
||||||
},
|
|
||||||
backspace() {
|
|
||||||
const {code, focus} = this;
|
|
||||||
if (this.isCollapsed()) {
|
|
||||||
if (focus > 0) {
|
|
||||||
this.code = code.slice(0, focus-1) + code.slice(focus);
|
|
||||||
this.setSelection(focus-1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.insertText("");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
delete() {
|
|
||||||
const {code, focus} = this;
|
|
||||||
if (this.isCollapsed()) {
|
|
||||||
if (focus < code.length) {
|
|
||||||
this.code = code.slice(0, focus) + code.slice(1+focus);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.insertText("");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
get code() {
|
|
||||||
return getSheet(0);
|
|
||||||
},
|
|
||||||
set code(val) {
|
|
||||||
setSheet(0, "code", val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const indexToGrid = (str: string, index: number) => {
|
|
||||||
const linesUpTo = str.slice(0,index).split("\n");
|
|
||||||
return {
|
|
||||||
x: linesUpTo[linesUpTo.length-1].length,
|
|
||||||
y: linesUpTo.length - 1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const gridToIndex = (str: string, x: number, y: number) => {
|
|
||||||
const lines = str.split("\n");
|
|
||||||
if (y < 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (y >= lines.length) {
|
|
||||||
return str.length;
|
|
||||||
}
|
|
||||||
return lines.slice(0, y).join("\n").length+Math.min(x, lines[y].length)+1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const drawCodeField = (code: string, x: number, y: number, w: number, h: number) => {
|
|
||||||
const {
|
|
||||||
scrollX,
|
|
||||||
scrollY,
|
|
||||||
anchor,
|
|
||||||
focus,
|
|
||||||
} = codeTabState;
|
|
||||||
const {
|
|
||||||
x: focusX,
|
|
||||||
y: focusY,
|
|
||||||
} = indexToGrid(code, focus);
|
|
||||||
const {
|
|
||||||
x: anchorX,
|
|
||||||
y: anchorY,
|
|
||||||
} = indexToGrid(code, anchor);
|
|
||||||
fillRect(x, y, w, h, COLOR.DARKBLUE);
|
|
||||||
if (anchor === focus) {
|
|
||||||
fillRect(x+focusX*fontWidth-scrollX, y+focusY*(fontHeight+1)-scrollY, fontWidth+1, fontHeight+1, COLOR.RED);
|
|
||||||
} else {
|
|
||||||
// TODO: Draw this selection better
|
|
||||||
fillRect(x+anchorX*fontWidth-scrollX, y+anchorY*(fontHeight+1)-scrollY, fontWidth+1, fontHeight+1, COLOR.GREEN);
|
|
||||||
fillRect(x+focusX*fontWidth-scrollX, y+focusY*(fontHeight+1)-scrollY, fontWidth+1, fontHeight+1, COLOR.YELLOW);
|
|
||||||
}
|
|
||||||
code.split("\n").forEach((line, i) => {
|
|
||||||
drawText(x-scrollX, 1+y+i*(fontHeight+1)-scrollY, line);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const update = () => {
|
const update = () => {
|
||||||
if (tab === "code") {
|
if (tab === "code") {
|
||||||
const { focus, focusX, focusY} = codeTabState;
|
codetab.update();
|
||||||
const keyboardString = getKeyboardString();
|
} else if (tab === "sprite") {
|
||||||
if (keyboardString) {
|
spritetab.update();
|
||||||
codeTabState.insertText(keyboardString);
|
|
||||||
}
|
|
||||||
// TODO: Handle ctrl-C, ctrl-V, ctrl-X, ctrl-Z
|
|
||||||
// TODO: Make ctrl-/ do commenting out (take inspiration from tab)
|
|
||||||
|
|
||||||
if (keyPressed(K.ENTER)) {
|
|
||||||
// TODO: Make this play nicely with indentation
|
|
||||||
codeTabState.insertText("\n");
|
|
||||||
}
|
|
||||||
if (keyPressed(K.TAB)) {
|
|
||||||
if (!shiftKeyDown()) {
|
|
||||||
if (codeTabState.isCollapsed()) {
|
|
||||||
codeTabState.insertText("\t");
|
|
||||||
} else {
|
|
||||||
codeTabState.indent("\t");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
codeTabState.outdent(/^(\t| )/);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (keyPressed(K.BACKSPACE)) {
|
|
||||||
codeTabState.backspace();
|
|
||||||
}
|
|
||||||
if (keyPressed(K.DELETE)) {
|
|
||||||
codeTabState.delete();
|
|
||||||
}
|
|
||||||
if (keyPressed(K.ARROW_RIGHT)) {
|
|
||||||
if (shiftKeyDown()) {
|
|
||||||
codeTabState.setFocus(focus+1);
|
|
||||||
} else {
|
|
||||||
codeTabState.setSelection(focus+1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (keyPressed(K.ARROW_LEFT)) {
|
|
||||||
if (shiftKeyDown()) {
|
|
||||||
codeTabState.setFocus(focus-1);
|
|
||||||
} else {
|
|
||||||
codeTabState.setSelection(focus-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (keyPressed(K.ARROW_DOWN)) {
|
|
||||||
if (shiftKeyDown()) {
|
|
||||||
codeTabState.setFocus({x: focusX, y: focusY+1});
|
|
||||||
} else {
|
|
||||||
codeTabState.setSelection({x: focusX, y: focusY+1});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (keyPressed(K.ARROW_UP)) {
|
|
||||||
if (shiftKeyDown()) {
|
|
||||||
codeTabState.setFocus({x: focusX, y: focusY-1});
|
|
||||||
} else {
|
|
||||||
codeTabState.setSelection({x: focusX, y: focusY-1});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const draw = () => {
|
const draw = () => {
|
||||||
clearScreen();
|
clearScreen();
|
||||||
if (tab === "code") {
|
if (tab === "code") {
|
||||||
drawCodeField(getSheet(0), 0, 8, 128, 112);
|
codetab.draw();
|
||||||
|
} else if (tab === "sprite") {
|
||||||
|
spritetab.draw();
|
||||||
}
|
}
|
||||||
|
fillRect(0, 0, 128, 8, COLOR.RED);
|
||||||
|
fillRect(0, 120, 128, 8, COLOR.RED);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const editmode = {
|
export const editmode = {
|
||||||
|
19
sheet.ts
19
sheet.ts
@ -1,10 +1,18 @@
|
|||||||
import { getCart } from "./cart.ts";
|
import { getCart } from "./cart.ts";
|
||||||
import { runCode, addToContext } from "./runcode.ts";
|
import { runCode, addToContext } from "./runcode.ts";
|
||||||
|
|
||||||
export type SheetType = "code" | "spritesheet" | "map" | "sfx" | "patterns" | "fonts";
|
// "code" | "spritesheet" | "map" | "sfx" | "patterns" | "fonts"
|
||||||
|
export type Sheet = {
|
||||||
|
sheet_type: "code",
|
||||||
|
value: string,
|
||||||
|
} | {
|
||||||
|
sheet_type: "spritesheet",
|
||||||
|
value: Array<Array<number>>,
|
||||||
|
}
|
||||||
|
export type SheetType = Sheet["sheet_type"];
|
||||||
|
|
||||||
export const getSheet = (n: number) => {
|
export const getSheet = (n: number) => {
|
||||||
return getCart()[n].value;
|
return getCart()[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
// deno-lint-ignore no-explicit-any
|
// deno-lint-ignore no-explicit-any
|
||||||
@ -13,8 +21,11 @@ export const setSheet = (n: number, type: SheetType, value: any) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const codeSheet = (sheet: number) => {
|
export const codeSheet = (sheet: number) => {
|
||||||
const code = getSheet(sheet);
|
const {sheet_type, value} = getSheet(sheet);
|
||||||
return runCode(code);
|
if (sheet_type !== "code") {
|
||||||
|
throw "Trying to run a non-code sheet as code."
|
||||||
|
}
|
||||||
|
return runCode(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
addToContext("code_sheet", codeSheet);
|
addToContext("code_sheet", codeSheet);
|
64
spritetab.ts
Normal file
64
spritetab.ts
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
import { clearScreen, fillRect, setPixelColor } from "./window.ts";
|
||||||
|
import { fontWidth, fontHeight } from "./font.ts";
|
||||||
|
import { drawText, drawSprite } from "./builtins.ts";
|
||||||
|
import { COLOR } from "./colors.ts";
|
||||||
|
import {getSheet, setSheet} from "./sheet.ts";
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
selectedIndex: 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;
|
||||||
|
},
|
||||||
|
set sprites(val) {
|
||||||
|
setSheet(0, "spritesheet", val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const update = () => {
|
||||||
|
}
|
||||||
|
|
||||||
|
const draw = () => {
|
||||||
|
const {sprites, selectedIndex} = state;
|
||||||
|
clearScreen();
|
||||||
|
fillRect(0, 8, 128, 112, COLOR.BROWN);
|
||||||
|
// Draw the palette
|
||||||
|
const paletteX = 88;
|
||||||
|
const paletteY = 12;
|
||||||
|
fillRect(paletteX-1, paletteY-1, 32+2, 32+2, COLOR.BLACK);
|
||||||
|
Object.keys(COLOR).forEach((name, i) => {
|
||||||
|
const swatchX = paletteX+8*(i%4);
|
||||||
|
const swatchY = paletteY+8*Math.floor(i/4);
|
||||||
|
fillRect(swatchX, swatchY, 8, 8, COLOR[name as keyof typeof COLOR]);
|
||||||
|
if (i === 0) {
|
||||||
|
// transparent
|
||||||
|
Array(64).fill(0).map((_z, j) => {
|
||||||
|
const jx = j%8;
|
||||||
|
const jy = Math.floor(j/8);
|
||||||
|
setPixelColor(swatchX+jx, swatchY+jy, (jx+jy)%2 ? COLOR.BLACK : COLOR.WHITE);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Draw the current sprite
|
||||||
|
const spriteX = 8;
|
||||||
|
const spriteY = 12;
|
||||||
|
fillRect(spriteX-1, spriteY-1, 64+2, 64+2, COLOR.BLACK);
|
||||||
|
sprites[selectedIndex].forEach((pix, i) => {
|
||||||
|
fillRect(spriteX+8*(i%8), spriteY+8*Math.floor(i/8), 8, 8, pix);
|
||||||
|
});
|
||||||
|
// Draw the spritesheet
|
||||||
|
const sheetX = 0;
|
||||||
|
const sheetY = 88;
|
||||||
|
fillRect(sheetX, sheetY-1, 128, 64+1, COLOR.BLACK);
|
||||||
|
sprites.forEach((_sprite, i) => {
|
||||||
|
drawSprite(sheetX+8*(i%16), sheetY+8*Math.floor(i/16), i);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export const spritetab = {
|
||||||
|
update,
|
||||||
|
draw,
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user