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.
@@ -1,41 +0,0 @@
1
- import { TiledTileset, Tileset as TiledTilesetClass } from "@rpgjs/tiled";
2
- import { Assets, Rectangle, Texture } from "pixi.js";
3
-
4
- export class TileSet extends TiledTilesetClass {
5
- public textures: Texture[] = [];
6
- private tileGroups = {};
7
-
8
- constructor(tileSet: TiledTileset) {
9
- super(tileSet);
10
- }
11
-
12
- loadGroup() {
13
- // for (let tile of this.tileset.tiles) {
14
- // }
15
- }
16
-
17
- /** @internal */
18
- async load(image: string) {
19
- const texture = await Assets.load(image);
20
- for (
21
- let y = this.margin;
22
- y < this.image.height;
23
- y += this.tileheight + this.spacing
24
- ) {
25
- for (
26
- let x = this.margin;
27
- x < this.image.width;
28
- x += this.tilewidth + this.spacing
29
- ) {
30
- this.textures.push(
31
- new Texture({
32
- source: texture.source,
33
- frame: new Rectangle(+x, +y, +this.tilewidth, +this.tileheight),
34
- })
35
- );
36
- }
37
- }
38
- this.loadGroup();
39
- return this;
40
- }
41
- }
@@ -1,80 +0,0 @@
1
- import { TiledLayer, TiledLayerType, TiledMap, TiledParserFile, TiledTileset } from "@rpgjs/tiled"
2
- import { effect, signal } from '@signe/reactive'
3
- import { loop } from "../../engine/reactive"
4
- import { h } from "../../engine/signal"
5
- import { useProps } from "../../hooks/useProps"
6
- import { Container } from "../Container"
7
- import { TilingSprite } from "../TilingSprite"
8
- import { CompositeTileLayer } from "./TileLayer"
9
- import { TileSet } from "./TileSet"
10
-
11
- export function TiledMap(props) {
12
- const { map } = useProps(props)
13
- const layers = signal<TiledLayer[]>([])
14
- const objectLayer = props.objectLayer
15
- let tilesets: TiledTileset[] = []
16
- let mapData: TiledMap = {} as TiledMap
17
-
18
- const parseTmx = async (file: string, relativePath: string = '') => {
19
- if (typeof file !== 'string') {
20
- return file
21
- }
22
- // @ts-ignore
23
- const parser = new TiledParserFile(
24
- file,
25
- {
26
- basePath: '',
27
- staticDir: '',
28
- relativePath
29
- }
30
- )
31
- const data = await parser.parseFilePromise({
32
- getOnlyBasename: false
33
- })
34
-
35
- return data
36
- }
37
-
38
- effect(async () => {
39
- mapData = await parseTmx(map())
40
- for (let tileSet of mapData.tilesets) {
41
- tilesets.push(await new TileSet(tileSet).load(tileSet.image.source))
42
- }
43
- layers.set(mapData.layers)
44
- })
45
-
46
- const createLayer = (layers, props = {}) => {
47
- return h(Container, props, loop(layers, (layer) => {
48
- switch (layer.type) {
49
- case TiledLayerType.Tile:
50
- return h(CompositeTileLayer, {
51
- tilewidth: mapData.tilewidth,
52
- tileheight: mapData.tileheight,
53
- // @ts-ignore
54
- width: mapData.width,
55
- // @ts-ignore
56
- height: mapData.height,
57
- ...layer,
58
- tilesets
59
- })
60
- case TiledLayerType.Image:
61
- const { width, height, source } = layer.image
62
- return h(TilingSprite, {
63
- image: source,
64
- ...layer,
65
- width: layer.repeatx ? layer.width * layer.tilewidth : width,
66
- height: layer.repeaty ? layer.height * layer.tileheight : height
67
- })
68
- case TiledLayerType.Group:
69
- return createLayer(signal(layer.layers), layer)
70
- case TiledLayerType.ObjectGroup:
71
- const child = objectLayer?.(layer)
72
- return h(Container, layer, child)
73
- default:
74
- return h(Container)
75
- }
76
- }))
77
- }
78
-
79
- return createLayer(layers)
80
- }
@@ -1,89 +0,0 @@
1
- import { Graphics } from "../components";
2
- import { h } from "../engine/signal";
3
- import * as PIXI from "pixi.js";
4
- import { useProps } from "../hooks/useProps";
5
-
6
- interface BarProps {
7
- backgroundColor?: string;
8
- foregroundColor?: string;
9
- value: number;
10
- maxValue: number;
11
- width: number;
12
- height: number;
13
- }
14
-
15
- function componentToHex(c) {
16
- var hex = c.toString(16);
17
- return hex.length == 1 ? "0" + hex : hex;
18
- }
19
-
20
- function rgbToHex(r, g, b) {
21
- return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
22
- }
23
-
24
- export function Bar(opts: BarProps) {
25
- const {
26
- width,
27
- height,
28
- value,
29
- maxValue,
30
- backgroundColor,
31
- foregroundColor,
32
- border,
33
- innerMargin,
34
- borderRadius,
35
- } = useProps(opts, {
36
- backgroundColor: "#000000",
37
- foregroundColor: "#FFFFFF",
38
- innerMargin: 0,
39
- borderRadius: 0,
40
- });
41
-
42
- return h(
43
- Graphics,
44
- {
45
- ...opts,
46
- width,
47
- height,
48
- draw(g: PIXI.Graphics) {
49
- if (borderRadius()) {
50
- g.roundRect(0, 0, width(), height(), borderRadius());
51
- } else {
52
- g.rect(0, 0, width(), height());
53
- }
54
- if (border) {
55
- g.stroke(border);
56
- }
57
- g.fill(backgroundColor());
58
- },
59
- },
60
- h(Graphics, {
61
- width,
62
- height,
63
- draw(g: PIXI.Graphics) {
64
- const margin = innerMargin();
65
- const _borderRadius = borderRadius();
66
- const w = Math.max(
67
- 0,
68
- Math.min(
69
- width() - 2 * margin,
70
- (value() / maxValue()) * (width() - 2 * margin)
71
- )
72
- );
73
- const h = height() - 2 * margin;
74
- if (borderRadius) {
75
- g.roundRect(margin, margin, w, h, _borderRadius);
76
- } else {
77
- g.rect(margin, margin, w, h);
78
- }
79
- const color = foregroundColor();
80
- if (color.startsWith("rgba")) {
81
- const [r, g, b, a] = color.match(/\d+(\.\d+)?/g).map(Number);
82
- g.fill({ color: rgbToHex(r, g, b), alpha: a });
83
- } else {
84
- g.fill(color);
85
- }
86
- },
87
- })
88
- );
89
- }
File without changes
@@ -1,286 +0,0 @@
1
- /*
2
- * Joystick
3
- *
4
- * Inspired by https://github.com/endel/pixi-virtual-joystick
5
- */
6
-
7
- import * as PIXI from "pixi.js";
8
- import { Container, Graphics, Sprite } from "../components";
9
- import { h } from "../engine/signal";
10
- import { signal } from "@signe/reactive";
11
-
12
- export interface JoystickChangeEvent {
13
- angle: number;
14
- direction: Direction;
15
- power: number;
16
- }
17
-
18
- export enum Direction {
19
- LEFT = "left",
20
- TOP = "top",
21
- BOTTOM = "bottom",
22
- RIGHT = "right",
23
- TOP_LEFT = "top_left",
24
- TOP_RIGHT = "top_right",
25
- BOTTOM_LEFT = "bottom_left",
26
- BOTTOM_RIGHT = "bottom_right",
27
- }
28
-
29
- export interface JoystickSettings {
30
- outer?: string;
31
- inner?: string;
32
- outerScale?: { x: number; y: number };
33
- innerScale?: { x: number; y: number };
34
- onChange?: (data: JoystickChangeEvent) => void;
35
- onStart?: () => void;
36
- onEnd?: () => void;
37
- }
38
-
39
- export function Joystick(opts: JoystickSettings = {}) {
40
- const settings = Object.assign(
41
- {
42
- outerScale: { x: 1, y: 1 },
43
- innerScale: { x: 1, y: 1 },
44
- },
45
- opts
46
- );
47
-
48
- let outerRadius = 70;
49
- let innerRadius = 10;
50
- const innerAlphaStandby = 0.5;
51
-
52
- let dragging = false;
53
- let startPosition: PIXI.PointData | null = null;
54
- let power = 0;
55
-
56
- const innerPositionX = signal(0);
57
- const innerPositionY = signal(0);
58
- const innerAlpha = signal(innerAlphaStandby);
59
-
60
- function getPower(centerPoint: PIXI.Point) {
61
- const a = centerPoint.x - 0;
62
- const b = centerPoint.y - 0;
63
- return Math.min(1, Math.sqrt(a * a + b * b) / outerRadius);
64
- }
65
-
66
- function getDirection(center: PIXI.Point) {
67
- let rad = Math.atan2(center.y, center.x); // [-PI, PI]
68
- if ((rad >= -Math.PI / 8 && rad < 0) || (rad >= 0 && rad < Math.PI / 8)) {
69
- return Direction.RIGHT;
70
- } else if (rad >= Math.PI / 8 && rad < (3 * Math.PI) / 8) {
71
- return Direction.BOTTOM_RIGHT;
72
- } else if (rad >= (3 * Math.PI) / 8 && rad < (5 * Math.PI) / 8) {
73
- return Direction.BOTTOM;
74
- } else if (rad >= (5 * Math.PI) / 8 && rad < (7 * Math.PI) / 8) {
75
- return Direction.BOTTOM_LEFT;
76
- } else if (
77
- (rad >= (7 * Math.PI) / 8 && rad < Math.PI) ||
78
- (rad >= -Math.PI && rad < (-7 * Math.PI) / 8)
79
- ) {
80
- return Direction.LEFT;
81
- } else if (rad >= (-7 * Math.PI) / 8 && rad < (-5 * Math.PI) / 8) {
82
- return Direction.TOP_LEFT;
83
- } else if (rad >= (-5 * Math.PI) / 8 && rad < (-3 * Math.PI) / 8) {
84
- return Direction.TOP;
85
- } else {
86
- return Direction.TOP_RIGHT;
87
- }
88
- }
89
-
90
- function handleDragStart(event: PIXI.FederatedPointerEvent) {
91
- startPosition = event.getLocalPosition(this);
92
- dragging = true;
93
- innerAlpha.set(1);
94
- settings.onStart?.();
95
- }
96
-
97
- function handleDragEnd() {
98
- if (!dragging) return;
99
- innerPositionX.set(0);
100
- innerPositionY.set(0);
101
- dragging = false;
102
- innerAlpha.set(innerAlphaStandby);
103
- settings.onEnd?.();
104
- }
105
-
106
- function handleDragMove(event: PIXI.FederatedPointerEvent) {
107
- if (dragging == false) {
108
- return;
109
- }
110
-
111
- let newPosition = event.getLocalPosition(this);
112
-
113
- let sideX = newPosition.x - (startPosition?.x ?? 0);
114
- let sideY = newPosition.y - (startPosition?.y ?? 0);
115
-
116
- let centerPoint = new PIXI.Point(0, 0);
117
- let angle = 0;
118
-
119
- if (sideX == 0 && sideY == 0) {
120
- return;
121
- }
122
-
123
- let calRadius = 0;
124
-
125
- if (sideX * sideX + sideY * sideY >= outerRadius * outerRadius) {
126
- calRadius = outerRadius;
127
- } else {
128
- calRadius = outerRadius - innerRadius;
129
- }
130
-
131
- /**
132
- * x: -1 <-> 1
133
- * y: -1 <-> 1
134
- * Y
135
- * ^
136
- * |
137
- * 180 | 90
138
- * ------------> X
139
- * 270 | 360
140
- * |
141
- * |
142
- */
143
-
144
- let direction = Direction.LEFT;
145
-
146
- if (sideX == 0) {
147
- if (sideY > 0) {
148
- centerPoint.set(0, sideY > outerRadius ? outerRadius : sideY);
149
- angle = 270;
150
- direction = Direction.BOTTOM;
151
- } else {
152
- centerPoint.set(
153
- 0,
154
- -(Math.abs(sideY) > outerRadius ? outerRadius : Math.abs(sideY))
155
- );
156
- angle = 90;
157
- direction = Direction.TOP;
158
- }
159
- innerPositionX.set(centerPoint.x);
160
- innerPositionY.set(centerPoint.y);
161
- power = getPower(centerPoint);
162
- settings.onChange?.({ angle, direction, power });
163
- return;
164
- }
165
-
166
- if (sideY == 0) {
167
- if (sideX > 0) {
168
- centerPoint.set(
169
- Math.abs(sideX) > outerRadius ? outerRadius : Math.abs(sideX),
170
- 0
171
- );
172
- angle = 0;
173
- direction = Direction.LEFT;
174
- } else {
175
- centerPoint.set(
176
- -(Math.abs(sideX) > outerRadius ? outerRadius : Math.abs(sideX)),
177
- 0
178
- );
179
- angle = 180;
180
- direction = Direction.RIGHT;
181
- }
182
-
183
- innerPositionX.set(centerPoint.x);
184
- innerPositionY.set(centerPoint.y);
185
- power = getPower(centerPoint);
186
- settings.onChange?.({ angle, direction, power });
187
- return;
188
- }
189
-
190
- let tanVal = Math.abs(sideY / sideX);
191
- let radian = Math.atan(tanVal);
192
- angle = (radian * 180) / Math.PI;
193
-
194
- let centerX = 0;
195
- let centerY = 0;
196
-
197
- if (sideX * sideX + sideY * sideY >= outerRadius * outerRadius) {
198
- centerX = outerRadius * Math.cos(radian);
199
- centerY = outerRadius * Math.sin(radian);
200
- } else {
201
- centerX = Math.abs(sideX) > outerRadius ? outerRadius : Math.abs(sideX);
202
- centerY = Math.abs(sideY) > outerRadius ? outerRadius : Math.abs(sideY);
203
- }
204
-
205
- if (sideY < 0) {
206
- centerY = -Math.abs(centerY);
207
- }
208
- if (sideX < 0) {
209
- centerX = -Math.abs(centerX);
210
- }
211
-
212
- if (sideX > 0 && sideY < 0) {
213
- // < 90
214
- } else if (sideX < 0 && sideY < 0) {
215
- // 90 ~ 180
216
- angle = 180 - angle;
217
- } else if (sideX < 0 && sideY > 0) {
218
- // 180 ~ 270
219
- angle = angle + 180;
220
- } else if (sideX > 0 && sideY > 0) {
221
- // 270 ~ 369
222
- angle = 360 - angle;
223
- }
224
- centerPoint.set(centerX, centerY);
225
- power = getPower(centerPoint);
226
-
227
- direction = getDirection(centerPoint);
228
- innerPositionX.set(centerPoint.x);
229
- innerPositionY.set(centerPoint.y);
230
-
231
- settings.onChange?.({ angle, direction, power });
232
- }
233
-
234
- let innerElement;
235
- let outerElement;
236
-
237
- if (!settings.outer) {
238
- outerElement = h(Graphics, {
239
- draw: (g) => {
240
- g.circle(0, 0, outerRadius).fill(0x000000);
241
- },
242
- alpha: 0.5,
243
- });
244
- } else {
245
- outerElement = h(Sprite, {
246
- image: settings.outer,
247
- anchor: { x: 0.5, y: 0.5 },
248
- scale: settings.outerScale,
249
- });
250
- }
251
-
252
- const innerOptions: any = {
253
- scale: settings.innerScale,
254
- x: innerPositionX,
255
- y: innerPositionY,
256
- alpha: innerAlpha,
257
- };
258
-
259
- if (!settings.inner) {
260
- innerElement = h(Graphics, {
261
- draw: (g) => {
262
- g.circle(0, 0, innerRadius * 2.5).fill(0x000000);
263
- },
264
- ...innerOptions,
265
- });
266
- } else {
267
- innerElement = h(Sprite, {
268
- image: settings.inner,
269
- anchor: { x: 0.5, y: 0.5 },
270
- ...innerOptions,
271
- });
272
- }
273
-
274
- return h(
275
- Container,
276
- {
277
- ...opts,
278
- pointerdown: handleDragStart,
279
- pointerup: handleDragEnd,
280
- pointerupoutside: handleDragEnd,
281
- pointermove: handleDragMove,
282
- },
283
- outerElement,
284
- innerElement
285
- );
286
- }
@@ -1,122 +0,0 @@
1
- import { Container, Graphics } from "../components";
2
- import { h, mount } from "../engine/signal";
3
- import { animatedSignal } from "../engine/animation";
4
- import { RadialGradient } from "../utils/RadialGradient";
5
- import { effect, isSignal, signal } from "@signe/reactive";
6
- import { useProps } from "../hooks/useProps";
7
- import { isObservable } from "rxjs";
8
-
9
- export function LightSpot(opts) {
10
- const { radius } = useProps(opts);
11
- const scale = animatedSignal(1);
12
-
13
- const minScale = 1;
14
- const maxScale = 2; // Reduced max scale for subtler effect
15
- const scintillationSpeed = 0.001; // Significantly reduced for slower scintillation
16
-
17
- const animate = () => {
18
- // Use time-based animation for smoother, slower scintillation
19
- const time = Date.now() * scintillationSpeed;
20
-
21
- // Combine multiple sine waves for a more natural, less predictable effect
22
- const scintillationFactor =
23
- (Math.sin(time) + Math.sin(time * 1.3) + Math.sin(time * 0.7)) / 3;
24
-
25
- // Map the scintillation factor to the scale range
26
- const newScale =
27
- minScale + (maxScale - minScale) * (scintillationFactor * 0.5 + 0.5);
28
-
29
- scale.update(() => newScale);
30
-
31
- requestAnimationFrame(animate);
32
- };
33
-
34
- animate();
35
-
36
- const draw = (g) => {
37
- const size = radius() * 2;
38
- const gradient = new RadialGradient(size, size, 0, size, size, 0);
39
- gradient.addColorStop(0, "rgba(255, 255, 0, 1)");
40
- gradient.addColorStop(0.5, "rgba(255, 255, 0, 0.3)");
41
- gradient.addColorStop(0.8, "rgba(255, 255, 0, 0)");
42
-
43
- const translate = size / 2;
44
-
45
- g.rect(-translate, -translate, size, size).fill(
46
- gradient.render({ translate: { x: translate, y: translate } })
47
- );
48
- };
49
-
50
- return h(Graphics, {
51
- draw,
52
- ...opts,
53
- scale,
54
- });
55
- }
56
-
57
- export function NightAmbiant(props) {
58
- const { children } = props;
59
- let el
60
- const width = signal(0);
61
- const height = signal(0);
62
- let subscription
63
- const draw = (rectAndHole) => {
64
- const margin = 80
65
- rectAndHole.rect(-margin, -margin, width() + margin*2, height() + margin*2);
66
- rectAndHole.fill(0x000000);
67
- const applyChildren = (child) => {
68
- const x = isSignal(child.propObservables.x)
69
- ? child.propObservables.x()
70
- : child.props.x;
71
- const y = isSignal(child.propObservables.y)
72
- ? child.propObservables.y()
73
- : child.props.y;
74
- const radius = isSignal(child.propObservables.radius)
75
- ? child.propObservables.radius()
76
- : child.props.radius;
77
- rectAndHole.circle(x, y, radius);
78
- rectAndHole.cut();
79
- }
80
- for (let child of children) {
81
- if (isObservable(child)) {
82
- if (subscription) {
83
- subscription.unsubscribe()
84
- }
85
- subscription = child.subscribe((event) => {
86
- for (let child of event.fullElements) {
87
- applyChildren(child)
88
- }
89
- })
90
- return
91
- }
92
- applyChildren(child)
93
- }
94
- };
95
-
96
- mount((el) => {
97
- effect(() => {
98
- const { displayWidth, displayHeight } = el.componentInstance
99
- const w = +displayWidth()
100
- const h = +displayHeight()
101
- setTimeout(() => {
102
- width.update(() => w)
103
- height.update(() => h)
104
- }, 0) // hack
105
- });
106
- });
107
-
108
- return h(
109
- Container,
110
- {
111
- width: "100%",
112
- height: "100%",
113
- ...props,
114
- },
115
- h(Graphics, {
116
- draw,
117
- alpha: 0.8,
118
- blur: 80,
119
- }),
120
- ...children
121
- );
122
- }
@@ -1,53 +0,0 @@
1
- import * as PIXI from "pixi.js";
2
- import { FX } from "revolt-fx";
3
- import { h, mount, tick } from "../engine/signal";
4
- import { Container } from "../components";
5
- import { on } from "../engine/trigger";
6
- import { useProps } from "../hooks/useProps";
7
-
8
- export function Particle(options) {
9
- const { emit, settings = {} } = options;
10
- const { name } = useProps(options);
11
- const fx = new FX();
12
- let element;
13
-
14
- PIXI.Assets.add({ alias: "fx_settings", src: "/default-bundle.json" });
15
- PIXI.Assets.add({
16
- alias: "fx_spritesheet",
17
- src: "/revoltfx-spritesheet.json",
18
- });
19
-
20
- tick(({deltaRatio}) => {
21
- fx.update(deltaRatio);
22
- });
23
-
24
- mount(async (_element) => {
25
- element = _element;
26
-
27
- const data = await PIXI.Assets.load(["fx_settings", "fx_spritesheet"]);
28
- let fxSettings = {...data.fx_settings};
29
-
30
- if (settings.emitters) {
31
- const lastId = 10000;
32
- const emittersWithIds = settings.emitters.map((emitter, index) => ({
33
- ...emitter,
34
- id: lastId + index
35
- }));
36
-
37
- fxSettings.emitters = [
38
- ...fxSettings.emitters,
39
- ...emittersWithIds,
40
- ];
41
-
42
- }
43
-
44
- fx.initBundle(fxSettings, true);
45
- });
46
-
47
- on(emit, () => {
48
- const emitter = fx.getParticleEmitter(name());
49
- emitter.init(element.componentInstance);
50
- });
51
-
52
- return h(Container);
53
- }
Binary file
@@ -1,18 +0,0 @@
1
- <Canvas
2
- backgroundColor="#fff"
3
- width="100%"
4
- height="100%"
5
- antialias="true"
6
- >
7
- <Container
8
- width="100%"
9
- height="100%"
10
- justifyContent="center"
11
- alignItems="center">
12
- <HelloWorld text="CanvasEngine" />
13
- </Container>
14
- </Canvas>
15
-
16
- <script>
17
- import HelloWorld from "./hello.ce";
18
- </script>