canvasengine 2.0.0-beta.1 → 2.0.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +94 -19
- package/dist/index.js +89 -478
- package/dist/index.js.map +1 -1
- package/package.json +9 -53
- package/src/components/index.ts +2 -3
- package/src/components/types/DisplayObject.ts +1 -0
- package/src/directives/KeyboardControls.ts +1 -1
- package/src/directives/Scheduler.ts +0 -11
- package/src/index.ts +4 -4
- package/.cursorrules +0 -0
- package/README.md +0 -71
- package/dist/compiler/vite.js +0 -119
- package/dist/compiler/vite.js.map +0 -1
- package/logo.png +0 -0
- package/src/compiler/grammar.pegjs +0 -180
- package/src/compiler/vite.ts +0 -166
- package/src/components/DrawMap/index.ts +0 -65
- package/src/components/Tilemap/Tile.ts +0 -79
- package/src/components/Tilemap/TileGroup.ts +0 -207
- package/src/components/Tilemap/TileLayer.ts +0 -163
- package/src/components/Tilemap/TileSet.ts +0 -41
- package/src/components/Tilemap/index.ts +0 -80
- package/src/presets/Bar.ts +0 -89
- package/src/presets/Button.ts +0 -0
- package/src/presets/Joystick.ts +0 -286
- package/src/presets/NightAmbiant.ts +0 -122
- package/src/presets/Particle.ts +0 -53
- package/starter/assets/logo.png +0 -0
- package/starter/components/app.ce +0 -18
- package/starter/components/hello.ce +0 -34
- package/starter/index.html +0 -21
- package/starter/main.ts +0 -4
- package/starter/package.json +0 -16
- package/starter/vite.config.ts +0 -12
- package/tsconfig.json +0 -32
- package/tsconfig.node.json +0 -10
- package/tsup.config.ts +0 -28
- package/vitest.config.ts +0 -12
package/src/compiler/vite.ts
DELETED
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
import { createFilter } from "vite";
|
|
2
|
-
import { parse } from "acorn";
|
|
3
|
-
import fs from "fs";
|
|
4
|
-
import pkg from "peggy";
|
|
5
|
-
import path from "path";
|
|
6
|
-
import * as ts from "typescript"; // Import TypeScript package
|
|
7
|
-
import { fileURLToPath } from 'url';
|
|
8
|
-
|
|
9
|
-
const { generate } = pkg;
|
|
10
|
-
|
|
11
|
-
const DEV_SRC = "../../src"
|
|
12
|
-
|
|
13
|
-
export default function canvasengine() {
|
|
14
|
-
const filter = createFilter("**/*.ce");
|
|
15
|
-
|
|
16
|
-
// Convert import.meta.url to a file path
|
|
17
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
18
|
-
const __dirname = path.dirname(__filename);
|
|
19
|
-
|
|
20
|
-
const grammar = fs.readFileSync(
|
|
21
|
-
path.join(__dirname, "grammar.pegjs").replace("dist/compiler/grammar.pegjs", "src/compiler/grammar.pegjs"),
|
|
22
|
-
"utf8");
|
|
23
|
-
const parser = generate(grammar);
|
|
24
|
-
const isDev = process.env.NODE_ENV === "development";
|
|
25
|
-
const FLAG_COMMENT = "/*--[TPL]--*/";
|
|
26
|
-
|
|
27
|
-
const PRIMITIVE_COMPONENTS = [
|
|
28
|
-
"Canvas",
|
|
29
|
-
"Sprite",
|
|
30
|
-
"Text",
|
|
31
|
-
"Joystick",
|
|
32
|
-
"Viewport",
|
|
33
|
-
"Graphics",
|
|
34
|
-
"Container",
|
|
35
|
-
"ImageMap",
|
|
36
|
-
"NineSliceSprite",
|
|
37
|
-
"Rect",
|
|
38
|
-
"Circle",
|
|
39
|
-
"svg"
|
|
40
|
-
];
|
|
41
|
-
|
|
42
|
-
return {
|
|
43
|
-
name: "vite-plugin-ce",
|
|
44
|
-
transform(code: string, id: string) {
|
|
45
|
-
if (!filter(id)) return;
|
|
46
|
-
|
|
47
|
-
// Extract the script content
|
|
48
|
-
const scriptMatch = code.match(/<script>([\s\S]*?)<\/script>/);
|
|
49
|
-
let scriptContent = scriptMatch ? scriptMatch[1].trim() : "";
|
|
50
|
-
|
|
51
|
-
// Transform SVG tags to Svg components
|
|
52
|
-
let template = code.replace(/<script>[\s\S]*?<\/script>/, "")
|
|
53
|
-
.replace(/^\s+|\s+$/g, '');
|
|
54
|
-
|
|
55
|
-
// Add SVG transformation
|
|
56
|
-
template = template.replace(/<svg>([\s\S]*?)<\/svg>/g, (match, content) => {
|
|
57
|
-
return `<Svg content="${content.trim()}" />`;
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
const parsedTemplate = parser.parse(template);
|
|
61
|
-
|
|
62
|
-
// trick to avoid typescript remove imports in scriptContent
|
|
63
|
-
scriptContent += FLAG_COMMENT + parsedTemplate
|
|
64
|
-
|
|
65
|
-
let transpiledCode = ts.transpileModule(scriptContent, {
|
|
66
|
-
compilerOptions: {
|
|
67
|
-
module: ts.ModuleKind.Preserve,
|
|
68
|
-
},
|
|
69
|
-
}).outputText;
|
|
70
|
-
|
|
71
|
-
// remove code after /*---*/
|
|
72
|
-
transpiledCode = transpiledCode.split(FLAG_COMMENT)[0]
|
|
73
|
-
|
|
74
|
-
// Use Acorn to parse the script content
|
|
75
|
-
const parsed = parse(transpiledCode, {
|
|
76
|
-
sourceType: "module",
|
|
77
|
-
ecmaVersion: 2020,
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
// Extract imports
|
|
81
|
-
const imports = parsed.body.filter(
|
|
82
|
-
(node) => node.type === "ImportDeclaration"
|
|
83
|
-
);
|
|
84
|
-
|
|
85
|
-
// Extract non-import statements from scriptContent
|
|
86
|
-
const nonImportCode = parsed.body
|
|
87
|
-
.filter((node) => node.type !== "ImportDeclaration")
|
|
88
|
-
.map((node) => transpiledCode.slice(node.start, node.end))
|
|
89
|
-
.join("\n");
|
|
90
|
-
|
|
91
|
-
let importsCode = imports
|
|
92
|
-
.map((imp) => {
|
|
93
|
-
let importCode = transpiledCode.slice(imp.start, imp.end);
|
|
94
|
-
if (isDev && importCode.includes("from 'canvasengine'")) {
|
|
95
|
-
importCode = importCode.replace(
|
|
96
|
-
"from 'canvasengine'",
|
|
97
|
-
`from '${DEV_SRC}'`
|
|
98
|
-
);
|
|
99
|
-
}
|
|
100
|
-
return importCode;
|
|
101
|
-
})
|
|
102
|
-
.join("\n");
|
|
103
|
-
|
|
104
|
-
// Define an array for required imports
|
|
105
|
-
const requiredImports = ["h", "computed", "cond", "loop"];
|
|
106
|
-
|
|
107
|
-
// Check for missing imports
|
|
108
|
-
const missingImports = requiredImports.filter(
|
|
109
|
-
(importName) =>
|
|
110
|
-
!imports.some(
|
|
111
|
-
(imp) =>
|
|
112
|
-
imp.specifiers &&
|
|
113
|
-
imp.specifiers.some(
|
|
114
|
-
(spec) =>
|
|
115
|
-
spec.type === "ImportSpecifier" &&
|
|
116
|
-
spec.imported &&
|
|
117
|
-
'name' in spec.imported &&
|
|
118
|
-
spec.imported.name === importName
|
|
119
|
-
)
|
|
120
|
-
)
|
|
121
|
-
);
|
|
122
|
-
|
|
123
|
-
// Add missing imports
|
|
124
|
-
if (missingImports.length > 0) {
|
|
125
|
-
const additionalImportCode = `import { ${missingImports.join(
|
|
126
|
-
", "
|
|
127
|
-
)} } from ${isDev ? `'${DEV_SRC}'` : "'canvasengine'"};`;
|
|
128
|
-
importsCode = `${additionalImportCode}\n${importsCode}`;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// Check for primitive components in parsedTemplate
|
|
132
|
-
const primitiveImports = PRIMITIVE_COMPONENTS.filter((component) =>
|
|
133
|
-
parsedTemplate.includes(`h(${component}`)
|
|
134
|
-
);
|
|
135
|
-
|
|
136
|
-
// Add missing imports for primitive components
|
|
137
|
-
primitiveImports.forEach((component) => {
|
|
138
|
-
const importStatement = `import { ${component} } from ${
|
|
139
|
-
isDev ? `'${DEV_SRC}'` : "'canvasengine'"
|
|
140
|
-
};`;
|
|
141
|
-
if (!importsCode.includes(importStatement)) {
|
|
142
|
-
importsCode = `${importStatement}\n${importsCode}`;
|
|
143
|
-
}
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
// Generate the output
|
|
147
|
-
const output = String.raw`
|
|
148
|
-
${importsCode}
|
|
149
|
-
import { useProps, useDefineProps } from ${isDev ? `'${DEV_SRC}'` : "'canvasengine'"}
|
|
150
|
-
|
|
151
|
-
export default function component($$props) {
|
|
152
|
-
const $props = useProps($$props)
|
|
153
|
-
const defineProps = useDefineProps($$props)
|
|
154
|
-
${nonImportCode}
|
|
155
|
-
let $this = ${parsedTemplate}
|
|
156
|
-
return $this
|
|
157
|
-
}
|
|
158
|
-
`;
|
|
159
|
-
|
|
160
|
-
return {
|
|
161
|
-
code: output,
|
|
162
|
-
map: null,
|
|
163
|
-
};
|
|
164
|
-
},
|
|
165
|
-
};
|
|
166
|
-
}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { effect, signal } from "@signe/reactive";
|
|
2
|
-
import { loop } from "../../engine/reactive";
|
|
3
|
-
import { h } from "../../engine/signal";
|
|
4
|
-
import { useProps } from "../../hooks/useProps";
|
|
5
|
-
import { Container } from "../Container";
|
|
6
|
-
import { Sprite } from "../Sprite";
|
|
7
|
-
|
|
8
|
-
interface TileData {
|
|
9
|
-
id: number;
|
|
10
|
-
rect: [number, number, number, number];
|
|
11
|
-
drawIn: [number, number];
|
|
12
|
-
layerIndex: number;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function ImageMap(props) {
|
|
16
|
-
const { imageSource, tileData } = useProps(props);
|
|
17
|
-
const tiles = signal<TileData[]>([]);
|
|
18
|
-
|
|
19
|
-
effect(async () => {
|
|
20
|
-
const data = await fetch(tileData()).then((response) => response.json());
|
|
21
|
-
const objects = data;
|
|
22
|
-
if (props.objects) {
|
|
23
|
-
objects.push(...props.objects(data));
|
|
24
|
-
}
|
|
25
|
-
tiles.set(objects);
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
const createLayeredTiles = () => {
|
|
29
|
-
const layers = [createTileLayer(0), createTileLayer(1, true), createTileLayer(2)];
|
|
30
|
-
|
|
31
|
-
return h(Container, props, ...layers);
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
const createTileLayer = (layerIndex: number, sortableChildren = false) => {
|
|
35
|
-
return h(
|
|
36
|
-
Container,
|
|
37
|
-
{
|
|
38
|
-
sortableChildren,
|
|
39
|
-
},
|
|
40
|
-
loop(tiles, (object) => {
|
|
41
|
-
|
|
42
|
-
if (object.tag && layerIndex == 1) {
|
|
43
|
-
return object
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
object.layerIndex ||= 1;
|
|
47
|
-
if (object.layerIndex !== layerIndex) return null;
|
|
48
|
-
|
|
49
|
-
const [x, y, width, height] = object.rect;
|
|
50
|
-
const [drawX, drawY] = object.drawIn;
|
|
51
|
-
|
|
52
|
-
return h(Sprite, {
|
|
53
|
-
image: imageSource(),
|
|
54
|
-
x: drawX,
|
|
55
|
-
y: drawY,
|
|
56
|
-
rectangle: { x, y, width, height },
|
|
57
|
-
zIndex: drawY + height - 70,
|
|
58
|
-
// zIndex: 0
|
|
59
|
-
});
|
|
60
|
-
})
|
|
61
|
-
);
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
return createLayeredTiles();
|
|
65
|
-
}
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import { CompositeTilemap } from "@pixi/tilemap";
|
|
2
|
-
import { Tile as TiledTileClass } from '@rpgjs/tiled';
|
|
3
|
-
import { AnimatedSprite, Texture, groupD8 } from "pixi.js";
|
|
4
|
-
import { TileSet } from "./TileSet";
|
|
5
|
-
|
|
6
|
-
export class Tile extends AnimatedSprite {
|
|
7
|
-
static getTextures(tile: TiledTileClass, tileSet: TileSet) {
|
|
8
|
-
const textures: Texture[] = [];
|
|
9
|
-
|
|
10
|
-
if (tile.animations && tile.animations.length) {
|
|
11
|
-
tile.animations.forEach(frame => {
|
|
12
|
-
textures.push(tileSet.textures[frame.tileid])
|
|
13
|
-
});
|
|
14
|
-
} else {
|
|
15
|
-
textures.push(tileSet.textures[tile.gid - tileSet.firstgid])
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
return textures;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
animations: { tileid: number, duration: number }[] = []
|
|
22
|
-
_x: number = 0
|
|
23
|
-
_y: number = 0
|
|
24
|
-
pointsBufIndex: number
|
|
25
|
-
properties: any = {}
|
|
26
|
-
|
|
27
|
-
constructor(
|
|
28
|
-
private tile: TiledTileClass,
|
|
29
|
-
private tileSet: TileSet
|
|
30
|
-
) {
|
|
31
|
-
super(Tile.getTextures(tile, tileSet));
|
|
32
|
-
this.animations = tile.animations || []
|
|
33
|
-
this.properties = tile.properties
|
|
34
|
-
this.textures = Tile.getTextures(tile, tileSet)
|
|
35
|
-
this.texture = this.textures[0] as Texture
|
|
36
|
-
this.flip()
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
get gid() {
|
|
40
|
-
return this.tile.gid
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
setAnimation(frame: CompositeTilemap) {
|
|
44
|
-
const size = this.animations.length
|
|
45
|
-
if (size > 1) {
|
|
46
|
-
const offset = (this.animations[1].tileid - this.animations[0].tileid) * this.width
|
|
47
|
-
frame.tileAnimX(offset, size)
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
flip() {
|
|
52
|
-
let symmetry
|
|
53
|
-
let i = 0
|
|
54
|
-
const add = (symmetrySecond) => {
|
|
55
|
-
i++
|
|
56
|
-
if (symmetry) symmetry = groupD8.add(symmetry, symmetrySecond)
|
|
57
|
-
else symmetry = symmetrySecond
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (this.tile.horizontalFlip) {
|
|
61
|
-
add(groupD8.MIRROR_HORIZONTAL)
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (this.tile.verticalFlip) {
|
|
65
|
-
add(groupD8.MIRROR_VERTICAL)
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
if (this.tile.diagonalFlip) {
|
|
69
|
-
if (i % 2 == 0) {
|
|
70
|
-
add(groupD8.MAIN_DIAGONAL)
|
|
71
|
-
}
|
|
72
|
-
else {
|
|
73
|
-
add(groupD8.REVERSE_DIAGONAL)
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
//if (symmetry) this.texture.rotate = symmetry
|
|
78
|
-
}
|
|
79
|
-
}
|
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
interface TileOptions {
|
|
2
|
-
tilesetIndex?: number
|
|
3
|
-
tileId: number
|
|
4
|
-
x: number
|
|
5
|
-
y: number
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
interface TilesGroupOptions {
|
|
9
|
-
ignore?: boolean
|
|
10
|
-
probability?: number
|
|
11
|
-
baseHeight?: number
|
|
12
|
-
baseWidth?: number
|
|
13
|
-
rectMargin?: number
|
|
14
|
-
baseOffsetX?: number
|
|
15
|
-
baseOffsetY?: number
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export class TileInfo {
|
|
19
|
-
tilesetIndex?: number
|
|
20
|
-
tileId: number
|
|
21
|
-
flags: Map<string, any> = new Map()
|
|
22
|
-
id: number = Math.random()
|
|
23
|
-
|
|
24
|
-
constructor(obj: TileOptions) {
|
|
25
|
-
this.tilesetIndex = obj.tilesetIndex ?? 0
|
|
26
|
-
this.tileId = obj.tileId
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
addFlag(key: string, value: any) {
|
|
30
|
-
this.flags.set(key, value)
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export class TilesGroup {
|
|
35
|
-
tiles: (TileInfo | null)[][] = []
|
|
36
|
-
width: number
|
|
37
|
-
height: number
|
|
38
|
-
ignore: boolean = false
|
|
39
|
-
probability: number = 1
|
|
40
|
-
baseHeight: number = 1
|
|
41
|
-
baseWidth?: number
|
|
42
|
-
baseOffsetX: number = 0
|
|
43
|
-
baseOffsetY: number = 0
|
|
44
|
-
rectMargin: number = 0
|
|
45
|
-
|
|
46
|
-
constructor(tiles: TileOptions[], public tilesetIndex: number = 0, options: TilesGroupOptions = {}) {
|
|
47
|
-
const pointsX = tiles.map(tile => tile.x)
|
|
48
|
-
const pointsY = tiles.map(tile => tile.y)
|
|
49
|
-
const offsetX = Math.min(...pointsX)
|
|
50
|
-
const offsetY = Math.min(...pointsY)
|
|
51
|
-
this.width = Math.max(...pointsX) - offsetX + 1
|
|
52
|
-
this.height = Math.max(...pointsY) - offsetY + 1
|
|
53
|
-
this.ignore = !!options.ignore
|
|
54
|
-
this.probability = options.probability ?? 1
|
|
55
|
-
this.baseHeight = options.baseHeight ?? 1
|
|
56
|
-
this.baseWidth = options.baseWidth
|
|
57
|
-
this.rectMargin = options.rectMargin ?? 0
|
|
58
|
-
this.baseOffsetX = options.baseOffsetX ?? 0
|
|
59
|
-
this.baseOffsetY = options.baseOffsetY ?? 0
|
|
60
|
-
this.fillTiles()
|
|
61
|
-
for (let tile of tiles) {
|
|
62
|
-
this.addTile(tile.x - offsetX, tile.y - offsetY, tile)
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
getRect(x: number, y: number): { minX: number, minY: number, maxX: number, maxY: number } {
|
|
67
|
-
const margin = this.rectMargin
|
|
68
|
-
return {
|
|
69
|
-
minX: x - margin + this.baseOffsetX,
|
|
70
|
-
minY: y - this.tilesBaseHeight - margin - this.baseOffsetY,
|
|
71
|
-
maxX: x + this.tilesBaseWidth + margin,
|
|
72
|
-
maxY: y + margin
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
get tilesBase() {
|
|
77
|
-
return this.tiles[this.tiles.length - 1]
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
get tilesBaseWidth(): number {
|
|
81
|
-
return this.baseWidth ?? this.tilesBase.length
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
get tilesBaseHeight(): number {
|
|
85
|
-
return this.baseHeight
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
forEach(cb: (tileInfo: TileInfo | null, x: number, y: number) => void) {
|
|
89
|
-
for (let i = 0; i < this.tiles.length; i++) {
|
|
90
|
-
for (let j = 0; j < this.tiles[i].length; j++) {
|
|
91
|
-
cb(this.tiles[i][j], j, i)
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
find(cb: (tileInfo: TileInfo | null, x: number, y: number) => boolean): TileInfo | null {
|
|
97
|
-
let found: TileInfo | null = null
|
|
98
|
-
this.forEach((tileInfo, x, y) => {
|
|
99
|
-
const bool = cb(tileInfo, x, y)
|
|
100
|
-
if (bool) found = tileInfo
|
|
101
|
-
})
|
|
102
|
-
return found
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
getOffsetY(): number {
|
|
106
|
-
const tilesBase = this.tilesBase
|
|
107
|
-
let offset = 0
|
|
108
|
-
this.forEach((tile, x, y) => {
|
|
109
|
-
if (tile?.tileId == (tilesBase?.[0]?.tileId)) {
|
|
110
|
-
offset = y
|
|
111
|
-
}
|
|
112
|
-
})
|
|
113
|
-
return offset
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
fillTiles() {
|
|
117
|
-
for (let i = 0; i < this.height; i++) {
|
|
118
|
-
this.tiles[i] = []
|
|
119
|
-
for (let j = 0; j < this.width; j++) {
|
|
120
|
-
this.tiles[i][j] = null
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
shiftToTopLeft(): void {
|
|
126
|
-
const matrix = this.tiles
|
|
127
|
-
|
|
128
|
-
// Find the first non-undefined element and its position
|
|
129
|
-
const foundFirst = () => {
|
|
130
|
-
let firstElementRow = -1;
|
|
131
|
-
let firstElementColumn = -1;
|
|
132
|
-
|
|
133
|
-
for (let col = 0; col < matrix.length; col++) {
|
|
134
|
-
if (!matrix[col]) matrix[col] = []
|
|
135
|
-
for (let row = 0; row < matrix[col].length; row++) {
|
|
136
|
-
if (matrix[col][row] !== undefined) {
|
|
137
|
-
firstElementRow = row;
|
|
138
|
-
firstElementColumn = col;
|
|
139
|
-
return {
|
|
140
|
-
firstElementRow,
|
|
141
|
-
firstElementColumn
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
return {
|
|
148
|
-
firstElementRow,
|
|
149
|
-
firstElementColumn
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
const { firstElementRow, firstElementColumn } = foundFirst()
|
|
154
|
-
|
|
155
|
-
// If no non-undefined element is found, return the original matrix
|
|
156
|
-
if (firstElementRow === -1) {
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// Shift the matrix elements
|
|
161
|
-
const newMatrix: (TileInfo | null)[][] = [];
|
|
162
|
-
for (let col = firstElementColumn; col < matrix.length; col++) {
|
|
163
|
-
const newRow: (TileInfo | null)[] = [];
|
|
164
|
-
for (let row = firstElementRow; row < matrix[col].length; row++) {
|
|
165
|
-
newRow.push(matrix[col][row]);
|
|
166
|
-
}
|
|
167
|
-
newMatrix.push(newRow);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
this.tiles = newMatrix;
|
|
171
|
-
|
|
172
|
-
this.width = this.tiles[0].length
|
|
173
|
-
this.height = this.tiles.length
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
addTile(x: number, y: number, tileOptions: TileOptions) {
|
|
177
|
-
if (!this.tiles[y]) this.tiles[y] = []
|
|
178
|
-
this.tiles[y][x] = new TileInfo(tileOptions)
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
addTileFlag(x: number, y: number, key: string, value: any) {
|
|
182
|
-
this.getTile(x, y)?.addFlag(key, value)
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
getTile(x: number, y: number): TileInfo | null {
|
|
186
|
-
return this.tiles[y]?.[x]
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
getTilesByFlag(key: string, value: any): { tileInfo: TileInfo, x: number, y: number }[] {
|
|
190
|
-
const array: any = []
|
|
191
|
-
this.forEach((tileInfo, x, y) => {
|
|
192
|
-
const flag = tileInfo?.flags.get(key)
|
|
193
|
-
if (flag && flag == value) {
|
|
194
|
-
array.push({
|
|
195
|
-
tileInfo,
|
|
196
|
-
x,
|
|
197
|
-
y
|
|
198
|
-
})
|
|
199
|
-
}
|
|
200
|
-
})
|
|
201
|
-
return array
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
isTileBase(tileInfo: TileInfo): boolean {
|
|
205
|
-
return !!this.tilesBase.find(tile => tile?.id == tileInfo.id)
|
|
206
|
-
}
|
|
207
|
-
}
|
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
import { CompositeTilemap, POINT_STRUCT_SIZE, Tilemap, settings } from '@pixi/tilemap';
|
|
2
|
-
import { Layer, Tile as TileClass } from '@rpgjs/tiled';
|
|
3
|
-
import { createComponent, registerComponent } from '../../engine/reactive';
|
|
4
|
-
import { DisplayObject } from '../DisplayObject';
|
|
5
|
-
import { Tile } from './Tile';
|
|
6
|
-
import { TileSet } from './TileSet';
|
|
7
|
-
|
|
8
|
-
settings.use32bitIndex = true
|
|
9
|
-
|
|
10
|
-
export class CanvasTileLayer extends DisplayObject(CompositeTilemap) {
|
|
11
|
-
private _tiles: any = {}
|
|
12
|
-
tiles: (TileClass | null)[]
|
|
13
|
-
private _layer: Layer
|
|
14
|
-
|
|
15
|
-
static findTileSet(gid: number, tileSets: TileSet[]) {
|
|
16
|
-
let tileset: TileSet | undefined
|
|
17
|
-
for (let i = tileSets.length - 1; i >= 0; i--) {
|
|
18
|
-
tileset = tileSets[i]
|
|
19
|
-
if (tileset.firstgid && tileset.firstgid <= gid) {
|
|
20
|
-
break;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
return tileset;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/** @internal */
|
|
27
|
-
createTile(x: number, y: number, options: any = {}): Tile | undefined {
|
|
28
|
-
const { real, filter } = options
|
|
29
|
-
const { tilewidth, tileheight, width } = this._layer
|
|
30
|
-
if (real) {
|
|
31
|
-
x = Math.floor(x / tilewidth)
|
|
32
|
-
y = Math.floor(y / tileheight)
|
|
33
|
-
}
|
|
34
|
-
const i = x + y * width;
|
|
35
|
-
const tiledTile = this._layer.getTileByIndex(i)
|
|
36
|
-
|
|
37
|
-
if (!tiledTile || (tiledTile && tiledTile.gid == 0)) return
|
|
38
|
-
|
|
39
|
-
const tileset = CanvasTileLayer.findTileSet(
|
|
40
|
-
tiledTile.gid,
|
|
41
|
-
this.tileSets
|
|
42
|
-
)
|
|
43
|
-
|
|
44
|
-
if (!tileset) return
|
|
45
|
-
|
|
46
|
-
const tile = new Tile(
|
|
47
|
-
tiledTile,
|
|
48
|
-
tileset
|
|
49
|
-
)
|
|
50
|
-
|
|
51
|
-
tile.x = x * tilewidth;
|
|
52
|
-
tile.y =
|
|
53
|
-
y * tileheight +
|
|
54
|
-
(tileheight -
|
|
55
|
-
tile.texture.height);
|
|
56
|
-
|
|
57
|
-
tile._x = x;
|
|
58
|
-
tile._y = y;
|
|
59
|
-
|
|
60
|
-
if (tileset.tileoffset) {
|
|
61
|
-
tile.x += tileset.tileoffset.x ?? 0;
|
|
62
|
-
tile.y += tileset.tileoffset.y ?? 0;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
if (filter) {
|
|
66
|
-
const ret = filter(tile)
|
|
67
|
-
if (!ret) return
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
return tile
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/** @internal */
|
|
74
|
-
changeTile(x: number, y: number) {
|
|
75
|
-
const { tilewidth, tileheight } = this._layer
|
|
76
|
-
x = Math.floor(x / tilewidth)
|
|
77
|
-
y = Math.floor(y / tileheight)
|
|
78
|
-
const oldTile: Tile = this._tiles[x + ';' + y]
|
|
79
|
-
const newTile = this.createTile(x, y)
|
|
80
|
-
if (!oldTile && newTile) {
|
|
81
|
-
this._addFrame(newTile, x, y)
|
|
82
|
-
}
|
|
83
|
-
else {
|
|
84
|
-
if (newTile) {
|
|
85
|
-
const bufComposite: CompositeTilemap = new CompositeTilemap()
|
|
86
|
-
const frame = bufComposite.tile(newTile.texture, newTile.x, newTile.y)
|
|
87
|
-
newTile.setAnimation(frame)
|
|
88
|
-
this._tiles[x + ';' + y] = newTile
|
|
89
|
-
// @ts-ignore
|
|
90
|
-
const pointsBufComposite = (bufComposite.children[0] as Tilemap).pointsBuf
|
|
91
|
-
// Change Texture (=0, 1 and 7, rotate (=4), animX (=5), animY (=6))
|
|
92
|
-
;[0, 1, 4, 6, 7, 8].forEach((i) => {
|
|
93
|
-
if (this.pointsBuf) this.pointsBuf[oldTile.pointsBufIndex + i] = pointsBufComposite[i]
|
|
94
|
-
})
|
|
95
|
-
// @ts-ignore
|
|
96
|
-
this.children[0].modificationMarker = 0
|
|
97
|
-
this._addFrame(newTile, x, y)
|
|
98
|
-
this['modificationMarker'] = 0
|
|
99
|
-
}
|
|
100
|
-
else {
|
|
101
|
-
delete this._tiles[x + ';' + y]
|
|
102
|
-
if (this.pointsBuf) this.pointsBuf.splice(oldTile.pointsBufIndex, POINT_STRUCT_SIZE)
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/** @internal */
|
|
108
|
-
get pointsBuf(): number[] | null {
|
|
109
|
-
const child = this.children[0] as Tilemap
|
|
110
|
-
if (!child) return null
|
|
111
|
-
return child['pointsBuf']
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
private _addFrame(tile: Tile, x: number, y: number) {
|
|
115
|
-
const frame = this.tile(tile.texture, tile.x, tile.y, {
|
|
116
|
-
rotate: tile.texture.rotate
|
|
117
|
-
})
|
|
118
|
-
const pb = this.pointsBuf
|
|
119
|
-
if (!pb) return null
|
|
120
|
-
tile.pointsBufIndex = pb.length - POINT_STRUCT_SIZE
|
|
121
|
-
tile.setAnimation(frame)
|
|
122
|
-
this._tiles[x + ';' + y] = tile
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
onMount(args) {
|
|
126
|
-
const { props } = args
|
|
127
|
-
this.tileSets = props.tilesets
|
|
128
|
-
this._layer = new Layer({
|
|
129
|
-
...props
|
|
130
|
-
}, this.tileSets)
|
|
131
|
-
super.onMount(args)
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
onUpdate(props) {
|
|
135
|
-
super.onUpdate(props)
|
|
136
|
-
if (!this.isMounted) return
|
|
137
|
-
if (props.tileheight) this._layer.tileheight = props.tileheight
|
|
138
|
-
if (props.tilewidth) this._layer.tilewidth = props.tilewidth
|
|
139
|
-
if (props.width) this._layer.width = props.width
|
|
140
|
-
if (props.height) this._layer.height = props.height
|
|
141
|
-
if (props.parallaxX) this._layer.parallaxX = props.parallaxx
|
|
142
|
-
if (props.parallaxY) this._layer.parallaxY = props.parallaxy
|
|
143
|
-
|
|
144
|
-
this.removeChildren()
|
|
145
|
-
|
|
146
|
-
for (let y = 0; y < this._layer.height; y++) {
|
|
147
|
-
for (let x = 0; x < this._layer.width; x++) {
|
|
148
|
-
const tile = this.createTile(x, y)
|
|
149
|
-
if (tile) {
|
|
150
|
-
this._addFrame(tile, x, y)
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
export interface CanvasTileLayer extends CompositeTilemap { }
|
|
158
|
-
|
|
159
|
-
registerComponent('CompositeTileLayer', CanvasTileLayer)
|
|
160
|
-
|
|
161
|
-
export function CompositeTileLayer(props) {
|
|
162
|
-
return createComponent('CompositeTileLayer', props)
|
|
163
|
-
}
|