like2d 2.3.0 → 2.5.0
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/README.md +27 -18
- package/dist/adapters/callback/index.d.ts +20 -40
- package/dist/adapters/callback/index.d.ts.map +1 -1
- package/dist/adapters/callback/index.js +29 -79
- package/dist/adapters/scene/index.d.ts +6 -30
- package/dist/adapters/scene/index.d.ts.map +1 -1
- package/dist/adapters/scene/index.js +22 -77
- package/dist/adapters/scene/scene.d.ts +14 -13
- package/dist/adapters/scene/scene.d.ts.map +1 -1
- package/dist/adapters/scene/startup-scene.d.ts +9 -8
- package/dist/adapters/scene/startup-scene.d.ts.map +1 -1
- package/dist/adapters/scene/startup-scene.js +37 -17
- package/dist/core/canvas-config.d.ts +7 -7
- package/dist/core/canvas-config.d.ts.map +1 -1
- package/dist/core/canvas-manager.d.ts +7 -8
- package/dist/core/canvas-manager.d.ts.map +1 -1
- package/dist/core/canvas-manager.js +52 -71
- package/dist/core/events.d.ts +21 -49
- package/dist/core/events.d.ts.map +1 -1
- package/dist/core/graphics.d.ts +38 -32
- package/dist/core/graphics.d.ts.map +1 -1
- package/dist/core/graphics.js +192 -275
- package/dist/core/like.d.ts +54 -0
- package/dist/core/like.d.ts.map +1 -0
- package/dist/core/like.js +1 -0
- package/dist/core/player-movement.d.ts +16 -0
- package/dist/core/player-movement.d.ts.map +1 -0
- package/dist/core/player-movement.js +20 -0
- package/dist/engine.d.ts +9 -28
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +89 -63
- package/dist/index.d.ts +8 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/package.json +9 -9
package/dist/core/graphics.js
CHANGED
|
@@ -52,300 +52,217 @@ export class ImageHandle {
|
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
function parseColor(color) {
|
|
55
|
-
if (typeof color === 'string')
|
|
55
|
+
if (typeof color === 'string')
|
|
56
56
|
return color;
|
|
57
|
-
}
|
|
58
57
|
const [r, g, b, a = 1] = color;
|
|
59
58
|
return `rgba(${r * 255}, ${g * 255}, ${b * 255}, ${a})`;
|
|
60
59
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
configurable: true,
|
|
90
|
-
writable: true,
|
|
91
|
-
value: new Map()
|
|
92
|
-
});
|
|
93
|
-
Object.defineProperty(this, "defaultFont", {
|
|
94
|
-
enumerable: true,
|
|
95
|
-
configurable: true,
|
|
96
|
-
writable: true,
|
|
97
|
-
value: '16px sans-serif'
|
|
98
|
-
});
|
|
99
|
-
this.screenCtx = ctx;
|
|
100
|
-
this.ctx = ctx;
|
|
101
|
-
ctx.font = this.defaultFont;
|
|
102
|
-
}
|
|
103
|
-
applyColor(color) {
|
|
104
|
-
return parseColor(color ?? [1, 1, 1, 1]);
|
|
105
|
-
}
|
|
106
|
-
setStrokeProps(props) {
|
|
107
|
-
if (!this.ctx)
|
|
108
|
-
return;
|
|
109
|
-
// Always reset to defaults first, then apply any custom props
|
|
110
|
-
this.ctx.lineWidth = props?.lineWidth ?? 1;
|
|
111
|
-
this.ctx.lineCap = props?.lineCap ?? 'butt';
|
|
112
|
-
this.ctx.lineJoin = props?.lineJoin ?? 'miter';
|
|
113
|
-
this.ctx.miterLimit = props?.miterLimit ?? 10;
|
|
114
|
-
}
|
|
115
|
-
clear() {
|
|
116
|
-
if (!this.ctx)
|
|
117
|
-
return;
|
|
118
|
-
this.ctx.fillStyle = parseColor(this.backgroundColor);
|
|
119
|
-
this.ctx.fillRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
|
|
60
|
+
function applyColor(color) {
|
|
61
|
+
return parseColor(color ?? [1, 1, 1, 1]);
|
|
62
|
+
}
|
|
63
|
+
function setStrokeProps(ctx, props) {
|
|
64
|
+
ctx.lineWidth = props?.lineWidth ?? 1;
|
|
65
|
+
ctx.lineCap = props?.lineCap ?? 'butt';
|
|
66
|
+
ctx.lineJoin = props?.lineJoin ?? 'miter';
|
|
67
|
+
ctx.miterLimit = props?.miterLimit ?? 10;
|
|
68
|
+
}
|
|
69
|
+
export function newState(ctx) {
|
|
70
|
+
return {
|
|
71
|
+
screenCtx: ctx,
|
|
72
|
+
currentCtx: ctx,
|
|
73
|
+
canvases: new Map(),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
export function clear(s, color = [0, 0, 0, 1]) {
|
|
77
|
+
const ctx = s.currentCtx;
|
|
78
|
+
ctx.fillStyle = parseColor(color);
|
|
79
|
+
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
|
80
|
+
}
|
|
81
|
+
export function rectangle(s, mode, color, rect, props) {
|
|
82
|
+
const ctx = s.currentCtx;
|
|
83
|
+
const [x, y, w, h] = rect;
|
|
84
|
+
const c = applyColor(color);
|
|
85
|
+
if (mode === 'fill') {
|
|
86
|
+
ctx.fillStyle = c;
|
|
87
|
+
ctx.fillRect(x, y, w, h);
|
|
120
88
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
89
|
+
else {
|
|
90
|
+
setStrokeProps(ctx, props);
|
|
91
|
+
ctx.strokeStyle = c;
|
|
92
|
+
ctx.strokeRect(x, y, w, h);
|
|
124
93
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
const parsedColor = this.applyColor(color);
|
|
145
|
-
const [rx, ry] = typeof radii === 'number' ? [radii, radii] : radii;
|
|
146
|
-
const [startAngle, endAngle] = props?.arc ?? [0, Math.PI * 2];
|
|
147
|
-
const rotation = props?.angle ?? 0;
|
|
148
|
-
this.ctx.save();
|
|
149
|
-
this.ctx.translate(x, y);
|
|
150
|
-
this.ctx.rotate(rotation);
|
|
151
|
-
this.ctx.scale(rx, ry);
|
|
152
|
-
this.ctx.beginPath();
|
|
153
|
-
this.ctx.arc(0, 0, 1, startAngle, endAngle);
|
|
154
|
-
this.ctx.closePath();
|
|
155
|
-
this.ctx.restore();
|
|
156
|
-
if (mode === 'fill') {
|
|
157
|
-
this.ctx.fillStyle = parsedColor;
|
|
158
|
-
this.ctx.fill();
|
|
159
|
-
}
|
|
160
|
-
else {
|
|
161
|
-
this.setStrokeProps(props);
|
|
162
|
-
this.ctx.strokeStyle = parsedColor;
|
|
163
|
-
this.ctx.stroke();
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
line(color, points, props) {
|
|
167
|
-
if (!this.ctx || points.length < 2)
|
|
168
|
-
return;
|
|
169
|
-
const parsedColor = this.applyColor(color);
|
|
170
|
-
this.setStrokeProps(props);
|
|
171
|
-
this.ctx.beginPath();
|
|
172
|
-
const [[x0, y0], ...rest] = points;
|
|
173
|
-
this.ctx.moveTo(x0, y0);
|
|
174
|
-
rest.forEach(([x, y]) => this.ctx.lineTo(x, y));
|
|
175
|
-
this.ctx.strokeStyle = parsedColor;
|
|
176
|
-
this.ctx.stroke();
|
|
94
|
+
}
|
|
95
|
+
export function circle(s, mode, color, position, radii, props) {
|
|
96
|
+
const ctx = s.currentCtx;
|
|
97
|
+
const [x, y] = position;
|
|
98
|
+
const c = applyColor(color);
|
|
99
|
+
const [rx, ry] = typeof radii === 'number' ? [radii, radii] : radii;
|
|
100
|
+
const [startAngle, endAngle] = props?.arc ?? [0, Math.PI * 2];
|
|
101
|
+
const rotation = props?.angle ?? 0;
|
|
102
|
+
ctx.save();
|
|
103
|
+
ctx.translate(x, y);
|
|
104
|
+
ctx.rotate(rotation);
|
|
105
|
+
ctx.scale(rx, ry);
|
|
106
|
+
ctx.beginPath();
|
|
107
|
+
ctx.arc(0, 0, 1, startAngle, endAngle);
|
|
108
|
+
ctx.closePath();
|
|
109
|
+
ctx.restore();
|
|
110
|
+
if (mode === 'fill') {
|
|
111
|
+
ctx.fillStyle = c;
|
|
112
|
+
ctx.fill();
|
|
177
113
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
const { font = this.defaultFont, limit, align = 'left' } = props ?? {};
|
|
183
|
-
this.ctx.fillStyle = parseColor(color);
|
|
184
|
-
this.ctx.font = font;
|
|
185
|
-
if (limit !== undefined) {
|
|
186
|
-
const lines = this.wrapText(text, limit);
|
|
187
|
-
const lineHeight = this.getFontHeight();
|
|
188
|
-
lines.forEach((line, index) => {
|
|
189
|
-
const lineWidth = this.ctx.measureText(line).width;
|
|
190
|
-
const drawX = align === 'center' ? x + (limit - lineWidth) / 2 :
|
|
191
|
-
align === 'right' ? x + limit - lineWidth : x;
|
|
192
|
-
this.ctx.fillText(line, drawX, y + index * lineHeight);
|
|
193
|
-
});
|
|
194
|
-
}
|
|
195
|
-
else {
|
|
196
|
-
this.ctx.fillText(text, x, y);
|
|
197
|
-
}
|
|
114
|
+
else {
|
|
115
|
+
setStrokeProps(ctx, props);
|
|
116
|
+
ctx.strokeStyle = c;
|
|
117
|
+
ctx.stroke();
|
|
198
118
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
119
|
+
}
|
|
120
|
+
export function line(s, color, points, props) {
|
|
121
|
+
const ctx = s.currentCtx;
|
|
122
|
+
if (points.length < 2)
|
|
123
|
+
return;
|
|
124
|
+
setStrokeProps(ctx, props);
|
|
125
|
+
ctx.beginPath();
|
|
126
|
+
const [[x0, y0], ...rest] = points;
|
|
127
|
+
ctx.moveTo(x0, y0);
|
|
128
|
+
rest.forEach(([x, y]) => ctx.lineTo(x, y));
|
|
129
|
+
ctx.strokeStyle = applyColor(color);
|
|
130
|
+
ctx.stroke();
|
|
131
|
+
}
|
|
132
|
+
export function print(s, color, text, position, props) {
|
|
133
|
+
const ctx = s.currentCtx;
|
|
134
|
+
const [x, y] = position;
|
|
135
|
+
const { font = '16px sans-serif', limit, align = 'left' } = props ?? {};
|
|
136
|
+
ctx.fillStyle = parseColor(color);
|
|
137
|
+
ctx.font = font;
|
|
138
|
+
if (limit !== undefined) {
|
|
139
|
+
const lines = wrapText(ctx, text, limit);
|
|
140
|
+
const lineHeight = getFontHeight(ctx);
|
|
141
|
+
lines.forEach((line, i) => {
|
|
142
|
+
const lineWidth = ctx.measureText(line).width;
|
|
143
|
+
const drawX = align === 'center' ? x + (limit - lineWidth) / 2
|
|
144
|
+
: align === 'right' ? x + limit - lineWidth
|
|
145
|
+
: x;
|
|
146
|
+
ctx.fillText(line, drawX, y + i * lineHeight);
|
|
215
147
|
});
|
|
216
|
-
lines.push(currentLine);
|
|
217
|
-
return lines;
|
|
218
|
-
}
|
|
219
|
-
getFontHeight() {
|
|
220
|
-
if (!this.ctx)
|
|
221
|
-
return 16;
|
|
222
|
-
const match = this.ctx.font.match(/(\d+)px/);
|
|
223
|
-
return match ? parseInt(match[1]) : 16;
|
|
224
148
|
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
return;
|
|
228
|
-
this.defaultFont = `${size}px ${font}`;
|
|
229
|
-
this.ctx.font = this.defaultFont;
|
|
149
|
+
else {
|
|
150
|
+
ctx.fillText(text, x, y);
|
|
230
151
|
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
return handle;
|
|
241
|
-
}
|
|
242
|
-
draw(handle, position, props) {
|
|
243
|
-
if (!this.ctx)
|
|
244
|
-
return;
|
|
245
|
-
const imageHandle = this.images.get(handle.path);
|
|
246
|
-
if (!imageHandle?.isReady())
|
|
247
|
-
return;
|
|
248
|
-
const element = imageHandle.getElement();
|
|
249
|
-
if (!element)
|
|
250
|
-
return;
|
|
251
|
-
const [x, y] = position;
|
|
252
|
-
const { r = 0, scale = 1, origin = 0, quad } = props ?? {};
|
|
253
|
-
const [sx, sy] = typeof scale === 'number' ? [scale, scale] : scale;
|
|
254
|
-
const [ox, oy] = typeof origin === 'number' ? [origin, origin] : origin;
|
|
255
|
-
this.ctx.save();
|
|
256
|
-
this.ctx.translate(x, y);
|
|
257
|
-
this.ctx.rotate(r);
|
|
258
|
-
this.ctx.scale(sx, sy);
|
|
259
|
-
if (quad) {
|
|
260
|
-
const [qx, qy, qw, qh] = quad;
|
|
261
|
-
this.ctx.drawImage(element, qx, qy, qw, qh, -ox, -oy, qw, qh);
|
|
152
|
+
}
|
|
153
|
+
function wrapText(ctx, text, maxWidth) {
|
|
154
|
+
const words = text.split(' ');
|
|
155
|
+
const [first, ...rest] = words;
|
|
156
|
+
const lines = [];
|
|
157
|
+
let current = first ?? '';
|
|
158
|
+
rest.forEach(word => {
|
|
159
|
+
if (ctx.measureText(current + ' ' + word).width < maxWidth) {
|
|
160
|
+
current += ' ' + word;
|
|
262
161
|
}
|
|
263
162
|
else {
|
|
264
|
-
|
|
163
|
+
lines.push(current);
|
|
164
|
+
current = word;
|
|
265
165
|
}
|
|
266
|
-
|
|
166
|
+
});
|
|
167
|
+
lines.push(current);
|
|
168
|
+
return lines;
|
|
169
|
+
}
|
|
170
|
+
function getFontHeight(ctx) {
|
|
171
|
+
const match = ctx.font.match(/(\d+)px/);
|
|
172
|
+
return match ? parseInt(match[1]) : 16;
|
|
173
|
+
}
|
|
174
|
+
export function drawImage(s, handle, position, props) {
|
|
175
|
+
const ctx = s.currentCtx;
|
|
176
|
+
if (!handle.isReady())
|
|
177
|
+
return;
|
|
178
|
+
const element = handle.getElement();
|
|
179
|
+
if (!element)
|
|
180
|
+
return;
|
|
181
|
+
const [x, y] = position;
|
|
182
|
+
const { r = 0, scale = 1, origin = 0, quad } = props ?? {};
|
|
183
|
+
const [sx, sy] = typeof scale === 'number' ? [scale, scale] : scale;
|
|
184
|
+
const [ox, oy] = typeof origin === 'number' ? [origin, origin] : origin;
|
|
185
|
+
ctx.save();
|
|
186
|
+
ctx.translate(x, y);
|
|
187
|
+
ctx.rotate(r);
|
|
188
|
+
ctx.scale(sx, sy);
|
|
189
|
+
if (quad) {
|
|
190
|
+
const [qx, qy, qw, qh] = quad;
|
|
191
|
+
ctx.drawImage(element, qx, qy, qw, qh, -ox, -oy, qw, qh);
|
|
267
192
|
}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
const height = this.ctx?.canvas.height ?? 600;
|
|
271
|
-
return [width, height];
|
|
193
|
+
else {
|
|
194
|
+
ctx.drawImage(element, -ox, -oy);
|
|
272
195
|
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
196
|
+
ctx.restore();
|
|
197
|
+
}
|
|
198
|
+
export function getCanvasSize(s) {
|
|
199
|
+
return [s.currentCtx.canvas.width, s.currentCtx.canvas.height];
|
|
200
|
+
}
|
|
201
|
+
export function newCanvas(s, size) {
|
|
202
|
+
const [w, h] = size;
|
|
203
|
+
const element = document.createElement('canvas');
|
|
204
|
+
element.width = w;
|
|
205
|
+
element.height = h;
|
|
206
|
+
const ctx = element.getContext('2d');
|
|
207
|
+
if (!ctx)
|
|
208
|
+
throw new Error('Failed to create canvas context');
|
|
209
|
+
const canvas = { size, element, ctx };
|
|
210
|
+
s.canvases.set(canvas, true);
|
|
211
|
+
return canvas;
|
|
212
|
+
}
|
|
213
|
+
export function setCanvas(s, canvas) {
|
|
214
|
+
s.currentCtx = canvas?.ctx ?? s.screenCtx;
|
|
215
|
+
}
|
|
216
|
+
export function clip(s, rect) {
|
|
217
|
+
const ctx = s.currentCtx;
|
|
218
|
+
ctx.beginPath();
|
|
219
|
+
if (rect) {
|
|
220
|
+
const [x, y, w, h] = rect;
|
|
221
|
+
ctx.rect(x, y, w, h);
|
|
285
222
|
}
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
this.ctx = canvas.ctx;
|
|
289
|
-
}
|
|
290
|
-
else {
|
|
291
|
-
this.ctx = this.screenCtx;
|
|
292
|
-
}
|
|
223
|
+
else {
|
|
224
|
+
ctx.rect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
|
293
225
|
}
|
|
294
|
-
clip(
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
226
|
+
ctx.clip();
|
|
227
|
+
}
|
|
228
|
+
export function polygon(s, mode, color, points, props) {
|
|
229
|
+
const ctx = s.currentCtx;
|
|
230
|
+
if (points.length < 3)
|
|
231
|
+
return;
|
|
232
|
+
const c = applyColor(color);
|
|
233
|
+
ctx.beginPath();
|
|
234
|
+
const [[x0, y0], ...rest] = points;
|
|
235
|
+
ctx.moveTo(x0, y0);
|
|
236
|
+
rest.forEach(([x, y]) => ctx.lineTo(x, y));
|
|
237
|
+
ctx.closePath();
|
|
238
|
+
if (mode === 'fill') {
|
|
239
|
+
ctx.fillStyle = c;
|
|
240
|
+
ctx.fill();
|
|
308
241
|
}
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
this.ctx.beginPath();
|
|
314
|
-
const [[x0, y0], ...rest] = points;
|
|
315
|
-
this.ctx.moveTo(x0, y0);
|
|
316
|
-
rest.forEach(([x, y]) => this.ctx.lineTo(x, y));
|
|
317
|
-
this.ctx.closePath();
|
|
318
|
-
if (mode === 'fill') {
|
|
319
|
-
this.ctx.fillStyle = parsedColor;
|
|
320
|
-
this.ctx.fill();
|
|
321
|
-
}
|
|
322
|
-
else {
|
|
323
|
-
this.setStrokeProps(props);
|
|
324
|
-
this.ctx.strokeStyle = parsedColor;
|
|
325
|
-
this.ctx.stroke();
|
|
326
|
-
}
|
|
242
|
+
else {
|
|
243
|
+
setStrokeProps(ctx, props);
|
|
244
|
+
ctx.strokeStyle = c;
|
|
245
|
+
ctx.stroke();
|
|
327
246
|
}
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
247
|
+
}
|
|
248
|
+
export function points(s, color, pts) {
|
|
249
|
+
const ctx = s.currentCtx;
|
|
250
|
+
ctx.fillStyle = applyColor(color);
|
|
251
|
+
pts.forEach(([x, y]) => ctx.fillRect(x, y, 1, 1));
|
|
252
|
+
}
|
|
253
|
+
export function newImage(path) {
|
|
254
|
+
return new ImageHandle(path);
|
|
255
|
+
}
|
|
256
|
+
const graphicsFns = {
|
|
257
|
+
clear, rectangle, circle, line, print,
|
|
258
|
+
draw: drawImage, getCanvasSize, newCanvas, setCanvas,
|
|
259
|
+
clip, polygon, points,
|
|
260
|
+
};
|
|
261
|
+
export function bindGraphics(s) {
|
|
262
|
+
return new Proxy({}, {
|
|
263
|
+
get(_, prop) {
|
|
264
|
+
const fn = graphicsFns[prop];
|
|
265
|
+
return fn ? (...args) => fn(s, ...args) : undefined;
|
|
342
266
|
}
|
|
343
|
-
}
|
|
344
|
-
points(color, points) {
|
|
345
|
-
if (!this.ctx)
|
|
346
|
-
return;
|
|
347
|
-
const parsedColor = this.applyColor(color);
|
|
348
|
-
this.ctx.fillStyle = parsedColor;
|
|
349
|
-
points.forEach(([x, y]) => this.ctx.fillRect(x, y, 1, 1));
|
|
350
|
-
}
|
|
267
|
+
});
|
|
351
268
|
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { Audio } from './audio';
|
|
2
|
+
import type { Timer } from './timer';
|
|
3
|
+
import type { Input } from './input';
|
|
4
|
+
import type { Keyboard } from './keyboard';
|
|
5
|
+
import type { Mouse } from './mouse';
|
|
6
|
+
import type { Gamepad } from './gamepad';
|
|
7
|
+
import type { Vector2 } from './vector2';
|
|
8
|
+
import type { CanvasMode, PartialCanvasMode } from './canvas-config';
|
|
9
|
+
import type { BoundGraphics } from './graphics';
|
|
10
|
+
/**
|
|
11
|
+
* The Like interface provides access to all core systems and APIs
|
|
12
|
+
* that are passed to game callbacks (load, update, draw, etc.).
|
|
13
|
+
*
|
|
14
|
+
* This is the main interface for interacting with the engine's subsystems.
|
|
15
|
+
*/
|
|
16
|
+
export interface Like {
|
|
17
|
+
/** Audio system for managing and playing sounds */
|
|
18
|
+
readonly audio: Audio;
|
|
19
|
+
/** Timer system for tracking time, delta, and FPS */
|
|
20
|
+
readonly timer: Timer;
|
|
21
|
+
/** Input system for action-based input handling */
|
|
22
|
+
readonly input: Input;
|
|
23
|
+
/** Keyboard input handling */
|
|
24
|
+
readonly keyboard: Keyboard;
|
|
25
|
+
/** Mouse input handling */
|
|
26
|
+
readonly mouse: Mouse;
|
|
27
|
+
/** Gamepad input handling */
|
|
28
|
+
readonly gamepad: Gamepad;
|
|
29
|
+
/** Graphics context for rendering operations */
|
|
30
|
+
readonly gfx: BoundGraphics;
|
|
31
|
+
/**
|
|
32
|
+
* Set the canvas display mode.
|
|
33
|
+
* @param mode - Partial canvas mode configuration
|
|
34
|
+
*/
|
|
35
|
+
setMode(mode: PartialCanvasMode): void;
|
|
36
|
+
/**
|
|
37
|
+
* Get the current canvas mode configuration.
|
|
38
|
+
* @returns The current canvas mode or undefined if not available
|
|
39
|
+
*/
|
|
40
|
+
getMode(): CanvasMode | undefined;
|
|
41
|
+
/**
|
|
42
|
+
* Get the current canvas size in pixels.
|
|
43
|
+
* @returns The canvas size as a Vector2 [width, height]
|
|
44
|
+
*/
|
|
45
|
+
getCanvasSize(): Vector2;
|
|
46
|
+
}
|
|
47
|
+
export type { Audio, Source, SourceOptions } from './audio';
|
|
48
|
+
export type { Timer } from './timer';
|
|
49
|
+
export type { Input, InputBinding, InputType } from './input';
|
|
50
|
+
export type { Keyboard } from './keyboard';
|
|
51
|
+
export type { Mouse, MousePositionTransform } from './mouse';
|
|
52
|
+
export type { Gamepad, StickPosition, ButtonCallback } from './gamepad';
|
|
53
|
+
export type { CanvasMode, PartialCanvasMode } from './canvas-config';
|
|
54
|
+
//# sourceMappingURL=like.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"like.d.ts","sourceRoot":"","sources":["../../src/core/like.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD;;;;;GAKG;AACH,MAAM,WAAW,IAAI;IACnB,mDAAmD;IACnD,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IAEtB,qDAAqD;IACrD,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IAEtB,mDAAmD;IACnD,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IAEtB,8BAA8B;IAC9B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAE5B,2BAA2B;IAC3B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IAEtB,6BAA6B;IAC7B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAE1B,gDAAgD;IAChD,QAAQ,CAAC,GAAG,EAAE,aAAa,CAAC;IAE5B;;;OAGG;IACH,OAAO,CAAC,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAEvC;;;OAGG;IACH,OAAO,IAAI,UAAU,GAAG,SAAS,CAAC;IAElC;;;OAGG;IACH,aAAa,IAAI,OAAO,CAAC;CAC1B;AAGD,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC5D,YAAY,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC9D,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,YAAY,EAAE,KAAK,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAC7D,YAAY,EAAE,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACxE,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface PlayerState {
|
|
2
|
+
pos: [number, number];
|
|
3
|
+
speed: number;
|
|
4
|
+
}
|
|
5
|
+
export interface MovementInput {
|
|
6
|
+
left: boolean;
|
|
7
|
+
right: boolean;
|
|
8
|
+
up: boolean;
|
|
9
|
+
down: boolean;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Calculate new player position based on input and delta time.
|
|
13
|
+
* Handles movement in 4 directions with speed scaling and boundary clamping.
|
|
14
|
+
*/
|
|
15
|
+
export declare function updatePlayerPosition(player: PlayerState, input: MovementInput, dt: number, minBounds: [number, number], maxBounds: [number, number]): [number, number];
|
|
16
|
+
//# sourceMappingURL=player-movement.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"player-movement.d.ts","sourceRoot":"","sources":["../../src/core/player-movement.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;IACf,EAAE,EAAE,OAAO,CAAC;IACZ,IAAI,EAAE,OAAO,CAAC;CACf;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,WAAW,EACnB,KAAK,EAAE,aAAa,EACpB,EAAE,EAAE,MAAM,EACV,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAC3B,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,GAC1B,CAAC,MAAM,EAAE,MAAM,CAAC,CAalB"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Vec2 } from '../core/vector2';
|
|
2
|
+
/**
|
|
3
|
+
* Calculate new player position based on input and delta time.
|
|
4
|
+
* Handles movement in 4 directions with speed scaling and boundary clamping.
|
|
5
|
+
*/
|
|
6
|
+
export function updatePlayerPosition(player, input, dt, minBounds, maxBounds) {
|
|
7
|
+
let moveDelta = [0, 0];
|
|
8
|
+
if (input.left)
|
|
9
|
+
moveDelta = Vec2.add(moveDelta, [-1, 0]);
|
|
10
|
+
if (input.right)
|
|
11
|
+
moveDelta = Vec2.add(moveDelta, [1, 0]);
|
|
12
|
+
if (input.up)
|
|
13
|
+
moveDelta = Vec2.add(moveDelta, [0, -1]);
|
|
14
|
+
if (input.down)
|
|
15
|
+
moveDelta = Vec2.add(moveDelta, [0, 1]);
|
|
16
|
+
// Apply movement with speed scaling
|
|
17
|
+
const newPos = Vec2.add(player.pos, Vec2.mul(moveDelta, player.speed * dt));
|
|
18
|
+
// Keep player in bounds
|
|
19
|
+
return Vec2.clamp(newPos, minBounds, maxBounds);
|
|
20
|
+
}
|
package/dist/engine.d.ts
CHANGED
|
@@ -1,42 +1,23 @@
|
|
|
1
|
-
import type { Graphics } from './core/graphics';
|
|
2
|
-
import type { Audio } from './core/audio';
|
|
3
|
-
import type { Input } from './core/input';
|
|
4
|
-
import type { Timer } from './core/timer';
|
|
5
|
-
import type { Keyboard } from './core/keyboard';
|
|
6
|
-
import type { Mouse } from './core/mouse';
|
|
7
|
-
import type { Gamepad } from './core/gamepad';
|
|
8
1
|
import type { Like2DEvent } from './core/events';
|
|
9
|
-
import type {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
input: Input;
|
|
13
|
-
timer: Timer;
|
|
14
|
-
audio: Audio;
|
|
15
|
-
keyboard: Keyboard;
|
|
16
|
-
mouse: Mouse;
|
|
17
|
-
gamepad: Gamepad;
|
|
18
|
-
};
|
|
2
|
+
import type { PartialCanvasMode } from './core/canvas-config';
|
|
3
|
+
import type { Like } from './core/like';
|
|
4
|
+
export type { CanvasMode, PartialCanvasMode } from './core/canvas-config';
|
|
19
5
|
export declare class Engine {
|
|
20
6
|
private canvas;
|
|
21
7
|
private ctx;
|
|
22
|
-
private deps;
|
|
23
8
|
private isRunning;
|
|
24
9
|
private lastTime;
|
|
25
10
|
private container;
|
|
26
11
|
private canvasManager;
|
|
27
12
|
private onEvent;
|
|
13
|
+
readonly like: Like;
|
|
28
14
|
constructor(container: HTMLElement);
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
dispose(): void;
|
|
15
|
+
private handleFullscreenChange;
|
|
16
|
+
setMode(mode: PartialCanvasMode): void;
|
|
32
17
|
private dispatchEvent;
|
|
33
|
-
start(onEvent: (event: Like2DEvent) => void): void
|
|
18
|
+
start(onEvent: (event: Like2DEvent) => void): Promise<void>;
|
|
34
19
|
stop(): void;
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
getCanvas(): HTMLCanvasElement;
|
|
38
|
-
getContext(): CanvasRenderingContext2D;
|
|
39
|
-
transformMousePosition(cssX: number, cssY: number): [number, number];
|
|
40
|
-
toggleFullscreen(): void;
|
|
20
|
+
dispose(): void;
|
|
21
|
+
getCanvasSize(): [number, number];
|
|
41
22
|
}
|
|
42
23
|
//# sourceMappingURL=engine.d.ts.map
|
package/dist/engine.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,WAAW,EAAa,MAAM,eAAe,CAAC;AAC5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAGxC,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE1E,qBAAa,MAAM;IACjB,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,GAAG,CAA2B;IACtC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,SAAS,CAAc;IAC/B,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,OAAO,CAA+C;IAG9D,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;gBAER,SAAS,EAAE,WAAW;IAgElC,OAAO,CAAC,sBAAsB;IAQ9B,OAAO,CAAC,IAAI,EAAE,iBAAiB,GAAG,IAAI;IAgBtC,OAAO,CAAC,aAAa;IAMf,KAAK,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI;IAgCjD,IAAI;IAIJ,OAAO,IAAI,IAAI;IAWf,aAAa,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC;CAGlC"}
|