@litecanvas/utils 0.4.0 → 0.5.1
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 +2 -1
- package/dist/actor.js +156 -0
- package/dist/actor.min.js +1 -0
- package/dist/all.js +117 -0
- package/dist/all.min.js +2 -2
- package/package.json +1 -1
- package/src/actor/README.md +140 -0
- package/src/actor/_web.js +3 -0
- package/src/actor/index.js +135 -0
- package/src/grid/README.md +3 -1
- package/src/index.js +1 -0
package/README.md
CHANGED
|
@@ -6,7 +6,8 @@ Small collection of tools for developing games with [Litecanvas](https://github.
|
|
|
6
6
|
|
|
7
7
|
- **Camera**: Move-, zoom- and rotatable camera with shake. [Usage & Docs](https://github.com/litecanvas/utils/tree/main/src/camera)
|
|
8
8
|
- **Vector**: Modular 2D vector. [Usage & Docs](https://github.com/litecanvas/utils/tree/main/src/vector)
|
|
9
|
-
- **
|
|
9
|
+
- **Actor**: class to represent game entities. [Usage & Docs](https://github.com/litecanvas/utils/tree/main/src/actor)
|
|
10
|
+
- **Grid**: class to handle retangular grid areas. [Usage & Docs](https://github.com/litecanvas/utils/tree/main/src/grid)
|
|
10
11
|
- **Collision** utilities. [Usage & Docs](https://github.com/litecanvas/utils/tree/main/src/collision)
|
|
11
12
|
- And [some math utilities](https://github.com/litecanvas/utils/tree/main/src/math)
|
|
12
13
|
|
package/dist/actor.js
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
(() => {
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __export = (target, all) => {
|
|
4
|
+
for (var name in all)
|
|
5
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
// src/actor/index.js
|
|
9
|
+
var actor_exports = {};
|
|
10
|
+
__export(actor_exports, {
|
|
11
|
+
ANCHOR_BOT_LEFT: () => ANCHOR_BOT_LEFT,
|
|
12
|
+
ANCHOR_BOT_RIGHT: () => ANCHOR_BOT_RIGHT,
|
|
13
|
+
ANCHOR_CENTER: () => ANCHOR_CENTER,
|
|
14
|
+
ANCHOR_TOP_LEFT: () => ANCHOR_TOP_LEFT,
|
|
15
|
+
ANCHOR_TOP_RIGHT: () => ANCHOR_TOP_RIGHT,
|
|
16
|
+
Actor: () => Actor
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
// src/vector/index.js
|
|
20
|
+
var Vector = class {
|
|
21
|
+
/** @type {number} */
|
|
22
|
+
x;
|
|
23
|
+
/** @type {number} */
|
|
24
|
+
y;
|
|
25
|
+
/**
|
|
26
|
+
* @param {number} x
|
|
27
|
+
* @param {number} y
|
|
28
|
+
*/
|
|
29
|
+
constructor(x = 0, y = x) {
|
|
30
|
+
this.x = x;
|
|
31
|
+
this.y = y;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* @returns {string}
|
|
35
|
+
*/
|
|
36
|
+
toString() {
|
|
37
|
+
return `Vector (${this.x}, ${this.y})`;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
var vec = (x = 0, y = x) => new Vector(x, y);
|
|
41
|
+
var veccopy = (v) => vec(v.x, v.y);
|
|
42
|
+
|
|
43
|
+
// src/actor/index.js
|
|
44
|
+
var ANCHOR_CENTER = vec(0.5, 0.5);
|
|
45
|
+
var ANCHOR_TOP_LEFT = vec(0, 0);
|
|
46
|
+
var ANCHOR_TOP_RIGHT = vec(1, 0);
|
|
47
|
+
var ANCHOR_BOT_LEFT = vec(0, 1);
|
|
48
|
+
var ANCHOR_BOT_RIGHT = vec(1, 1);
|
|
49
|
+
var Actor = class {
|
|
50
|
+
/** @type {Image|HTMLCanvasElement|OffscreenCanvas} */
|
|
51
|
+
sprite;
|
|
52
|
+
/** @type {Vector} The actor position */
|
|
53
|
+
_p;
|
|
54
|
+
/** @type {Vector} The actor anchor (origin) */
|
|
55
|
+
_o;
|
|
56
|
+
/** @type {Vector} The actor scale */
|
|
57
|
+
_s;
|
|
58
|
+
/** @type {number} The actor angle (in radians) */
|
|
59
|
+
angle = 0;
|
|
60
|
+
/** @type {number} The actor opacity */
|
|
61
|
+
opacity = 1;
|
|
62
|
+
/** @type {boolean} If `true` the actor will not be drawn. */
|
|
63
|
+
hidden = false;
|
|
64
|
+
/**
|
|
65
|
+
* @param {Image|HTMLCanvasElement|OffscreenCanvas} sprite
|
|
66
|
+
* @param {Vector} position
|
|
67
|
+
*/
|
|
68
|
+
constructor(sprite, position) {
|
|
69
|
+
this.sprite = sprite;
|
|
70
|
+
this._p = position || vec(0);
|
|
71
|
+
this._o = veccopy(ANCHOR_TOP_LEFT);
|
|
72
|
+
this._s = vec(1, 1);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* @param {number}
|
|
76
|
+
*/
|
|
77
|
+
set x(value) {
|
|
78
|
+
this._p.x = value;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* @returns {number}
|
|
82
|
+
*/
|
|
83
|
+
get x() {
|
|
84
|
+
return this._p.x;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* @param {number}
|
|
88
|
+
*/
|
|
89
|
+
set y(value) {
|
|
90
|
+
this._p.y = value;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* @returns {number}
|
|
94
|
+
*/
|
|
95
|
+
get y() {
|
|
96
|
+
return this._p.y;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* @param {Vector}
|
|
100
|
+
*/
|
|
101
|
+
set anchor(vec2) {
|
|
102
|
+
this._o.x = vec2.x;
|
|
103
|
+
this._o.y = vec2.y;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* @returns {Vector}
|
|
107
|
+
*/
|
|
108
|
+
get anchor() {
|
|
109
|
+
return this._o;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* @returns {number}
|
|
113
|
+
*/
|
|
114
|
+
get width() {
|
|
115
|
+
return this.sprite.width * this._s.y;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* @returns {number}
|
|
119
|
+
*/
|
|
120
|
+
get height() {
|
|
121
|
+
return this.sprite.height * this._s.y;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* @retuns {Vector}
|
|
125
|
+
*/
|
|
126
|
+
get scale() {
|
|
127
|
+
return this._s;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Update the transformation matrix, sets the opacity and draw the actor sprite image.
|
|
131
|
+
*
|
|
132
|
+
* @param {LitecanvasInstance} [litecanvas]
|
|
133
|
+
*/
|
|
134
|
+
draw(litecanvas = globalThis) {
|
|
135
|
+
if (this.hidden || this.opacity <= 0) return;
|
|
136
|
+
litecanvas.push();
|
|
137
|
+
this.transform(litecanvas);
|
|
138
|
+
const anchorX = this.sprite.width * this.anchor.x;
|
|
139
|
+
const anchorY = this.sprite.height * this.anchor.y;
|
|
140
|
+
litecanvas.image(-anchorX, -anchorY, this.sprite);
|
|
141
|
+
litecanvas.pop();
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* @param {LitecanvasInstance} litecanvas
|
|
145
|
+
*/
|
|
146
|
+
transform(litecanvas) {
|
|
147
|
+
litecanvas.translate(this._p.x, this._p.y);
|
|
148
|
+
litecanvas.rotate(this.angle);
|
|
149
|
+
litecanvas.scale(this._s.x, this._s.y);
|
|
150
|
+
litecanvas.alpha(this.opacity);
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
// src/actor/_web.js
|
|
155
|
+
globalThis.utils = Object.assign(globalThis.utils || {}, actor_exports);
|
|
156
|
+
})();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(()=>{var f=Object.defineProperty;var p=(e,t)=>{for(var r in t)f(e,r,{get:t[r],enumerable:!0})};var a={};p(a,{ANCHOR_BOT_LEFT:()=>d,ANCHOR_BOT_RIGHT:()=>x,ANCHOR_CENTER:()=>u,ANCHOR_TOP_LEFT:()=>c,ANCHOR_TOP_RIGHT:()=>h,Actor:()=>n});var s=class{x;y;constructor(t=0,r=t){this.x=t,this.y=r}toString(){return`Vector (${this.x}, ${this.y})`}},o=(e=0,t=e)=>new s(e,t);var i=e=>o(e.x,e.y);var u=o(.5,.5),c=o(0,0),h=o(1,0),d=o(0,1),x=o(1,1),n=class{sprite;_p;_o;_s;angle=0;opacity=1;hidden=!1;constructor(t,r){this.sprite=t,this._p=r||o(0),this._o=i(c),this._s=o(1,1)}set x(t){this._p.x=t}get x(){return this._p.x}set y(t){this._p.y=t}get y(){return this._p.y}set anchor(t){this._o.x=t.x,this._o.y=t.y}get anchor(){return this._o}get width(){return this.sprite.width*this._s.y}get height(){return this.sprite.height*this._s.y}get scale(){return this._s}draw(t=globalThis){if(this.hidden||this.opacity<=0)return;t.push(),this.transform(t);let r=this.sprite.width*this.anchor.x,l=this.sprite.height*this.anchor.y;t.image(-r,-l,this.sprite),t.pop()}transform(t){t.translate(this._p.x,this._p.y),t.rotate(this.angle),t.scale(this._s.x,this._s.y),t.alpha(this.opacity)}};globalThis.utils=Object.assign(globalThis.utils||{},a);})();
|
package/dist/all.js
CHANGED
|
@@ -8,6 +8,12 @@
|
|
|
8
8
|
// src/index.js
|
|
9
9
|
var src_exports = {};
|
|
10
10
|
__export(src_exports, {
|
|
11
|
+
ANCHOR_BOT_LEFT: () => ANCHOR_BOT_LEFT,
|
|
12
|
+
ANCHOR_BOT_RIGHT: () => ANCHOR_BOT_RIGHT,
|
|
13
|
+
ANCHOR_CENTER: () => ANCHOR_CENTER,
|
|
14
|
+
ANCHOR_TOP_LEFT: () => ANCHOR_TOP_LEFT,
|
|
15
|
+
ANCHOR_TOP_RIGHT: () => ANCHOR_TOP_RIGHT,
|
|
16
|
+
Actor: () => Actor,
|
|
11
17
|
Camera: () => Camera,
|
|
12
18
|
DOWN: () => DOWN,
|
|
13
19
|
Grid: () => Grid,
|
|
@@ -521,6 +527,117 @@
|
|
|
521
527
|
var DOWN = /* @__PURE__ */ vec(0, 1);
|
|
522
528
|
var LEFT = /* @__PURE__ */ vec(-1, 0);
|
|
523
529
|
|
|
530
|
+
// src/actor/index.js
|
|
531
|
+
var ANCHOR_CENTER = vec(0.5, 0.5);
|
|
532
|
+
var ANCHOR_TOP_LEFT = vec(0, 0);
|
|
533
|
+
var ANCHOR_TOP_RIGHT = vec(1, 0);
|
|
534
|
+
var ANCHOR_BOT_LEFT = vec(0, 1);
|
|
535
|
+
var ANCHOR_BOT_RIGHT = vec(1, 1);
|
|
536
|
+
var Actor = class {
|
|
537
|
+
/** @type {Image|HTMLCanvasElement|OffscreenCanvas} */
|
|
538
|
+
sprite;
|
|
539
|
+
/** @type {Vector} The actor position */
|
|
540
|
+
_p;
|
|
541
|
+
/** @type {Vector} The actor anchor (origin) */
|
|
542
|
+
_o;
|
|
543
|
+
/** @type {Vector} The actor scale */
|
|
544
|
+
_s;
|
|
545
|
+
/** @type {number} The actor angle (in radians) */
|
|
546
|
+
angle = 0;
|
|
547
|
+
/** @type {number} The actor opacity */
|
|
548
|
+
opacity = 1;
|
|
549
|
+
/** @type {boolean} If `true` the actor will not be drawn. */
|
|
550
|
+
hidden = false;
|
|
551
|
+
/**
|
|
552
|
+
* @param {Image|HTMLCanvasElement|OffscreenCanvas} sprite
|
|
553
|
+
* @param {Vector} position
|
|
554
|
+
*/
|
|
555
|
+
constructor(sprite, position) {
|
|
556
|
+
this.sprite = sprite;
|
|
557
|
+
this._p = position || vec(0);
|
|
558
|
+
this._o = veccopy(ANCHOR_TOP_LEFT);
|
|
559
|
+
this._s = vec(1, 1);
|
|
560
|
+
}
|
|
561
|
+
/**
|
|
562
|
+
* @param {number}
|
|
563
|
+
*/
|
|
564
|
+
set x(value) {
|
|
565
|
+
this._p.x = value;
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* @returns {number}
|
|
569
|
+
*/
|
|
570
|
+
get x() {
|
|
571
|
+
return this._p.x;
|
|
572
|
+
}
|
|
573
|
+
/**
|
|
574
|
+
* @param {number}
|
|
575
|
+
*/
|
|
576
|
+
set y(value) {
|
|
577
|
+
this._p.y = value;
|
|
578
|
+
}
|
|
579
|
+
/**
|
|
580
|
+
* @returns {number}
|
|
581
|
+
*/
|
|
582
|
+
get y() {
|
|
583
|
+
return this._p.y;
|
|
584
|
+
}
|
|
585
|
+
/**
|
|
586
|
+
* @param {Vector}
|
|
587
|
+
*/
|
|
588
|
+
set anchor(vec2) {
|
|
589
|
+
this._o.x = vec2.x;
|
|
590
|
+
this._o.y = vec2.y;
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* @returns {Vector}
|
|
594
|
+
*/
|
|
595
|
+
get anchor() {
|
|
596
|
+
return this._o;
|
|
597
|
+
}
|
|
598
|
+
/**
|
|
599
|
+
* @returns {number}
|
|
600
|
+
*/
|
|
601
|
+
get width() {
|
|
602
|
+
return this.sprite.width * this._s.y;
|
|
603
|
+
}
|
|
604
|
+
/**
|
|
605
|
+
* @returns {number}
|
|
606
|
+
*/
|
|
607
|
+
get height() {
|
|
608
|
+
return this.sprite.height * this._s.y;
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* @retuns {Vector}
|
|
612
|
+
*/
|
|
613
|
+
get scale() {
|
|
614
|
+
return this._s;
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* Update the transformation matrix, sets the opacity and draw the actor sprite image.
|
|
618
|
+
*
|
|
619
|
+
* @param {LitecanvasInstance} [litecanvas]
|
|
620
|
+
*/
|
|
621
|
+
draw(litecanvas = globalThis) {
|
|
622
|
+
if (this.hidden || this.opacity <= 0) return;
|
|
623
|
+
litecanvas.push();
|
|
624
|
+
this.transform(litecanvas);
|
|
625
|
+
const anchorX = this.sprite.width * this.anchor.x;
|
|
626
|
+
const anchorY = this.sprite.height * this.anchor.y;
|
|
627
|
+
litecanvas.image(-anchorX, -anchorY, this.sprite);
|
|
628
|
+
litecanvas.pop();
|
|
629
|
+
}
|
|
630
|
+
/**
|
|
631
|
+
* @param {LitecanvasInstance} litecanvas
|
|
632
|
+
*/
|
|
633
|
+
transform(litecanvas) {
|
|
634
|
+
litecanvas.translate(this._p.x, this._p.y);
|
|
635
|
+
litecanvas.rotate(this.angle);
|
|
636
|
+
litecanvas.scale(this._s.x, this._s.y);
|
|
637
|
+
litecanvas.alpha(this.opacity);
|
|
638
|
+
}
|
|
639
|
+
};
|
|
640
|
+
|
|
524
641
|
// src/_web.js
|
|
525
642
|
globalThis.utils = src_exports;
|
|
526
643
|
})();
|
package/dist/all.min.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
(()=>{var
|
|
2
|
-
`)}};function
|
|
1
|
+
(()=>{var L=Object.defineProperty;var v=(e,t)=>{for(var s in t)L(e,s,{get:t[s],enumerable:!0})};var A={};v(A,{ANCHOR_BOT_LEFT:()=>it,ANCHOR_BOT_RIGHT:()=>nt,ANCHOR_CENTER:()=>ot,ANCHOR_TOP_LEFT:()=>W,ANCHOR_TOP_RIGHT:()=>rt,Actor:()=>I,Camera:()=>p,DOWN:()=>et,Grid:()=>u,LEFT:()=>st,ONE:()=>K,RIGHT:()=>tt,UP:()=>Q,Vector:()=>d,ZERO:()=>J,diff:()=>M,fract:()=>P,intersection:()=>g,isvector:()=>c,resolve:()=>O,vec:()=>i,vecadd:()=>S,vecconfig:()=>w,veccopy:()=>H,veccross:()=>V,vecdir:()=>$,vecdist:()=>B,vecdist2:()=>j,vecdiv:()=>_,vecdot:()=>q,veceq:()=>k,veclerp:()=>U,veclimit:()=>F,vecmag:()=>R,vecmag2:()=>Y,vecmult:()=>E,vecnorm:()=>N,vecrand:()=>Z,vecrot:()=>G,vecset:()=>z,vecsub:()=>X,wave:()=>b});var M=(e,t)=>Math.abs(t-e)||0;var P=e=>e%1||0;var b=(e,t,s,o=Math.sin)=>e+(o(s)+1)/2*(t-e);var g=(e,t,s,o,n,r,a,h)=>{let l=Math.max(e,n),D=Math.min(e+s,n+a)-l,x=Math.max(t,r),m=Math.min(t+o,r+h)-x;return[l,x,D,m]};var O=(e,t,s,o,n,r,a,h)=>{let[l,D,x,m]=g(e,t,s,o,n,r,a,h),f="",y=e,T=t;return x<m?e<n?(f="right",y=n-s):(f="left",y=n+a):t<r?(f="bottom",T=r-o):(f="top",T=r+h),{direction:f,x:y,y:T}};var p=class{_engine=null;x=0;y=0;width=0;height=0;rotation=0;scale=1;_shake={x:0,y:0,removeListener:null};constructor(t=null){t=t||globalThis,this._engine=t,this.size(t.WIDTH||0,t.HEIGHT||0),this.x=this.width/2,this.y=this.height/2}size(t,s){this.width=t,this.height=s}start(t=!1){let s=this.width/2,o=this.height/2;this._engine.push(),this._engine.translate(s,o),this._engine.scale(this.scale),this._engine.rotate(this.rotation),this._engine.translate(-this.x+this._shake.x,-this.y+this._shake.y),t&&this._engine.cliprect(this.x,this.y,this.width,this.height)}end(){this._engine.pop()}lookAt(t,s){this.x=t,this.y=s}move(t,s){this.x+=t,this.y+=s}zoom(t){this.scale*=t}zoomTo(t){this.scale=t}rotate(t){this.rotation+=t}rotateTo(t){this.rotation=t}shake(t=.3,s=1){this.shaking()||(this._shake.removeListener=this._engine.listen("update",o=>{this._shake.x=this._engine.randi(-s,s),this._shake.y=this._engine.randi(-s,s),t-=o,t<=0&&this.unshake()}))}unshake(){this.shaking()&&(this._shake.removeListener(),this._shake.removeListener=null,this._shake.x=this._shake.y=0)}shaking(){return this._shake.removeListener!==null}};var u=class e{_w;_h;_c;static fromArray(t,s,o){let n=new e(t,s);for(let r=0;r<o.length;r++)n._c[r]=o[r];return n}constructor(t,s){this.width=t,this.height=s,this.clear()}clear(){this._c=Array(this._w*this._h)}set width(t){this._w=Math.max(1,~~t)}get width(){return this._w}set height(t){this._h=Math.max(1,~~t)}get height(){return this._h}set(t,s,o){this._c[this.pointToIndex(t,s)]=o}get(t,s){return this._c[this.pointToIndex(t,s)]}has(t,s){return this.get(t,s)!=null}get length(){return this._w*this._h}pointToIndex(t,s){return this.clampX(~~t)+this.clampY(~~s)*this._w}indexToPointX(t){return t%this._w}indexToPointY(t){return Math.floor(t/this._w)}forEach(t,s=!1){let o=s?this.length-1:0,n=s?-1:this.length,r=s?-1:1;for(;o!==n;){let a=this.indexToPointX(o),h=this.indexToPointY(o),l=this._c[o];if(t(a,h,l,this)===!1)break;o+=r}}fill(t){this.forEach((s,o)=>{this.set(s,o,t)})}clone(){return e.fromArray(this._w,this._h,this._c)}clampX(t){return C(t,0,this._w-1)}clampY(t){return C(t,0,this._h-1)}toArray(){return this._c.slice(0)}toString(t=" ",s=!0){if(!s)return this._c.join(t);let o=[];return this.forEach((n,r,a)=>{o[r]=o[r]||"",o[r]+=a+t}),o.join(`
|
|
2
|
+
`)}};function C(e,t,s){return e<t?t:e>s?s:e}var d=class{x;y;constructor(t=0,s=t){this.x=t,this.y=s}toString(){return`Vector (${this.x}, ${this.y})`}},i=(e=0,t=e)=>new d(e,t),k=(e,t,s=t)=>c(t)?k(e,t.x,t.y):e.x===t&&e.y===s,H=e=>i(e.x,e.y),z=(e,t,s=t)=>{c(t)?z(e,t.x,t.y):(e.x=t,e.y=s)},S=(e,t,s=t)=>{c(t)?S(e,t.x,t.y):(e.x+=t,e.y+=s)},X=(e,t,s=t)=>{c(t)?X(e,t.x,t.y):(e.x-=t,e.y-=s)},E=(e,t,s=t)=>{c(t)?E(e,t.x,t.y):(e.x*=t,e.y*=s)},_=(e,t,s=t)=>{c(t)?_(e,t.x,t.y):(e.x/=t,e.y/=s)},G=(e,t)=>{let s=Math.cos(t),o=Math.sin(t);e.x=s*e.x-o*e.y,e.y=o*e.x+s*e.y},R=e=>Math.sqrt(e.x*e.x+e.y*e.y),Y=e=>e.x*e.x+e.y*e.y,N=e=>{let t=R(e);t>0&&_(e,t)},F=(e,t)=>{let s=Y(e);s>t*t&&(_(e,Math.sqrt(s)),E(e,t))},B=(e,t)=>{let s=e.x-t.x,o=e.y-t.y;return Math.sqrt(s*s+o*o)},j=(e,t)=>{let s=e.x-t.x,o=e.y-t.y;return s*s+o*o},$=e=>Math.atan2(e.y,e.x),q=(e,t)=>e.x*t.x+e.y*t.y,V=(e,t)=>e.x*t.y-e.y*t.x,U=(e,t,s)=>{e.x+=(t.x-e.x)*s||0,e.y+=(t.y-e.y)*s||0},Z=(e=1,t=e)=>{let s=w.random()*2*Math.PI,o=w.random()*(t-e)+e;return i(Math.cos(s)*o,Math.sin(s)*o)},c=e=>e instanceof d,w={random:()=>globalThis.rand?rand():Math.random()},J=i(0,0),K=i(1,1),Q=i(0,-1),tt=i(1,0),et=i(0,1),st=i(-1,0);var ot=i(.5,.5),W=i(0,0),rt=i(1,0),it=i(0,1),nt=i(1,1),I=class{sprite;_p;_o;_s;angle=0;opacity=1;hidden=!1;constructor(t,s){this.sprite=t,this._p=s||i(0),this._o=H(W),this._s=i(1,1)}set x(t){this._p.x=t}get x(){return this._p.x}set y(t){this._p.y=t}get y(){return this._p.y}set anchor(t){this._o.x=t.x,this._o.y=t.y}get anchor(){return this._o}get width(){return this.sprite.width*this._s.y}get height(){return this.sprite.height*this._s.y}get scale(){return this._s}draw(t=globalThis){if(this.hidden||this.opacity<=0)return;t.push(),this.transform(t);let s=this.sprite.width*this.anchor.x,o=this.sprite.height*this.anchor.y;t.image(-s,-o,this.sprite),t.pop()}transform(t){t.translate(this._p.x,this._p.y),t.rotate(this.angle),t.scale(this._s.x,this._s.y),t.alpha(this.opacity)}};globalThis.utils=A;})();
|
package/package.json
CHANGED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# Actor
|
|
2
|
+
|
|
3
|
+
**CDN**: https://unpkg.com/@litecanvas/utils/dist/actor.js
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```js
|
|
8
|
+
import litecanvas from "@litecanvas"
|
|
9
|
+
import { Actor } from "@litecanvas/utils"
|
|
10
|
+
|
|
11
|
+
let player, mySprite
|
|
12
|
+
|
|
13
|
+
litecanvas({
|
|
14
|
+
loop: { init, tapped, draw },
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
// create a sprite image
|
|
18
|
+
mySprite = paint(3, 3, ["303", "030", "303"], { scale: 10 })
|
|
19
|
+
|
|
20
|
+
function init() {
|
|
21
|
+
// create a actor
|
|
22
|
+
player = new Actor(mySprite)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function tapped(tapx, tapy) {
|
|
26
|
+
// update the actor position
|
|
27
|
+
player.x = tapx
|
|
28
|
+
player.y = tapy
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function draw() {
|
|
32
|
+
cls(0)
|
|
33
|
+
|
|
34
|
+
// draw the actor sprite
|
|
35
|
+
player.draw()
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Actor#x / Actor#y
|
|
40
|
+
|
|
41
|
+
Set or get the actor position
|
|
42
|
+
|
|
43
|
+
```js
|
|
44
|
+
player.x = 100
|
|
45
|
+
player.y = 200
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Actor#scale
|
|
49
|
+
|
|
50
|
+
Set or get the actor scale/size
|
|
51
|
+
|
|
52
|
+
```js
|
|
53
|
+
// twice bigger
|
|
54
|
+
player.scale.x = 2
|
|
55
|
+
player.scale.y = 2
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Actor#anchor
|
|
59
|
+
|
|
60
|
+
Set or get the actor anchor (origin). By default, the anchor is a vector `(0, 0)` (meaning anchor Top Left).
|
|
61
|
+
|
|
62
|
+
```js
|
|
63
|
+
// position the sprite based on their center
|
|
64
|
+
player.anchor.x = 0.5
|
|
65
|
+
player.anchor.y = 0.5
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
```js
|
|
69
|
+
// alternatively
|
|
70
|
+
import { ANCHOR_CENTER } from "@litecanvas/utils"
|
|
71
|
+
|
|
72
|
+
player.anchor = ANCHOR_CENTER
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
> Note:
|
|
76
|
+
> You can import and use the following constants to help you choose an actor anchor: , `ANCHOR_TOP_LEFT` (default), `ANCHOR_TOP_RIGHT`, `ANCHOR_BOT_LEFT`, `ANCHOR_BOT_RIGHT` or `ANCHOR_CENTER`.
|
|
77
|
+
|
|
78
|
+
## Actor#angle
|
|
79
|
+
|
|
80
|
+
Set or get the actor angle (in radians).
|
|
81
|
+
|
|
82
|
+
```js
|
|
83
|
+
player.angle = HALF_PI / 2 // 45 degrees
|
|
84
|
+
|
|
85
|
+
// or use the litecanvas' `deg2rad()` helper
|
|
86
|
+
player.angle = deg2rad(45)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Actor#opacity
|
|
90
|
+
|
|
91
|
+
Set or get the actor opacity (alpha).
|
|
92
|
+
|
|
93
|
+
```js
|
|
94
|
+
player.opacity = 0.5 // 50% transparent
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Actor#hidden
|
|
98
|
+
|
|
99
|
+
Set or get the actor hidden (`boolean`) state.
|
|
100
|
+
|
|
101
|
+
```js
|
|
102
|
+
player.hidden = true // hides the actor image
|
|
103
|
+
player.hidden = false // display the actor image
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Actor#width
|
|
107
|
+
|
|
108
|
+
Get (not set) the actor current width.
|
|
109
|
+
|
|
110
|
+
```js
|
|
111
|
+
console.log(player.width) // => 30
|
|
112
|
+
|
|
113
|
+
player.scale.x = 1.5
|
|
114
|
+
|
|
115
|
+
console.log(player.width) // => 45
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Actor#height
|
|
119
|
+
|
|
120
|
+
Get (not set) the actor current height.
|
|
121
|
+
|
|
122
|
+
```js
|
|
123
|
+
console.log(player.height) // => 30
|
|
124
|
+
|
|
125
|
+
player.scale.x = 2
|
|
126
|
+
|
|
127
|
+
console.log(player.height) // => 60
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Actor#sprite
|
|
131
|
+
|
|
132
|
+
Set or get the actor sprite image. Useful to make animations.
|
|
133
|
+
|
|
134
|
+
```js
|
|
135
|
+
player.sprite = anotherSprite
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
> The actor sprite must be a `Image`, `HTMLCanvas` or `OffscreenCanvas`.
|
|
139
|
+
>
|
|
140
|
+
> Remember, you can create a image using the litecanvas' `paint()` built-in helper or [load a image](https://github.com/litecanvas/plugin-asset-loader?tab=readme-ov-file#loading-images) with plugins.
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { Vector, vec, veccopy } from "../vector/index.js"
|
|
2
|
+
import "litecanvas"
|
|
3
|
+
|
|
4
|
+
export const ANCHOR_CENTER = vec(0.5, 0.5)
|
|
5
|
+
export const ANCHOR_TOP_LEFT = vec(0, 0)
|
|
6
|
+
export const ANCHOR_TOP_RIGHT = vec(1, 0)
|
|
7
|
+
export const ANCHOR_BOT_LEFT = vec(0, 1)
|
|
8
|
+
export const ANCHOR_BOT_RIGHT = vec(1, 1)
|
|
9
|
+
|
|
10
|
+
export class Actor {
|
|
11
|
+
/** @type {Image|HTMLCanvasElement|OffscreenCanvas} */
|
|
12
|
+
sprite
|
|
13
|
+
|
|
14
|
+
/** @type {Vector} The actor position */
|
|
15
|
+
_p
|
|
16
|
+
|
|
17
|
+
/** @type {Vector} The actor anchor (origin) */
|
|
18
|
+
_o
|
|
19
|
+
|
|
20
|
+
/** @type {Vector} The actor scale */
|
|
21
|
+
_s
|
|
22
|
+
|
|
23
|
+
/** @type {number} The actor angle (in radians) */
|
|
24
|
+
angle = 0
|
|
25
|
+
|
|
26
|
+
/** @type {number} The actor opacity */
|
|
27
|
+
opacity = 1
|
|
28
|
+
|
|
29
|
+
/** @type {boolean} If `true` the actor will not be drawn. */
|
|
30
|
+
hidden = false
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @param {Image|HTMLCanvasElement|OffscreenCanvas} sprite
|
|
34
|
+
* @param {Vector} position
|
|
35
|
+
*/
|
|
36
|
+
constructor(sprite, position) {
|
|
37
|
+
this.sprite = sprite
|
|
38
|
+
this._p = position || vec(0)
|
|
39
|
+
this._o = veccopy(ANCHOR_TOP_LEFT)
|
|
40
|
+
this._s = vec(1, 1)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @param {number}
|
|
45
|
+
*/
|
|
46
|
+
set x(value) {
|
|
47
|
+
this._p.x = value
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @returns {number}
|
|
52
|
+
*/
|
|
53
|
+
get x() {
|
|
54
|
+
return this._p.x
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @param {number}
|
|
59
|
+
*/
|
|
60
|
+
set y(value) {
|
|
61
|
+
this._p.y = value
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* @returns {number}
|
|
66
|
+
*/
|
|
67
|
+
get y() {
|
|
68
|
+
return this._p.y
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* @param {Vector}
|
|
73
|
+
*/
|
|
74
|
+
set anchor(vec) {
|
|
75
|
+
this._o.x = vec.x
|
|
76
|
+
this._o.y = vec.y
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* @returns {Vector}
|
|
81
|
+
*/
|
|
82
|
+
get anchor() {
|
|
83
|
+
return this._o
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* @returns {number}
|
|
88
|
+
*/
|
|
89
|
+
get width() {
|
|
90
|
+
return this.sprite.width * this._s.y
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* @returns {number}
|
|
95
|
+
*/
|
|
96
|
+
get height() {
|
|
97
|
+
return this.sprite.height * this._s.y
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* @retuns {Vector}
|
|
102
|
+
*/
|
|
103
|
+
get scale() {
|
|
104
|
+
return this._s
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Update the transformation matrix, sets the opacity and draw the actor sprite image.
|
|
109
|
+
*
|
|
110
|
+
* @param {LitecanvasInstance} [litecanvas]
|
|
111
|
+
*/
|
|
112
|
+
draw(litecanvas = globalThis) {
|
|
113
|
+
if (this.hidden || this.opacity <= 0) return
|
|
114
|
+
|
|
115
|
+
litecanvas.push()
|
|
116
|
+
|
|
117
|
+
this.transform(litecanvas)
|
|
118
|
+
|
|
119
|
+
const anchorX = this.sprite.width * this.anchor.x
|
|
120
|
+
const anchorY = this.sprite.height * this.anchor.y
|
|
121
|
+
litecanvas.image(-anchorX, -anchorY, this.sprite)
|
|
122
|
+
|
|
123
|
+
litecanvas.pop()
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* @param {LitecanvasInstance} litecanvas
|
|
128
|
+
*/
|
|
129
|
+
transform(litecanvas) {
|
|
130
|
+
litecanvas.translate(this._p.x, this._p.y)
|
|
131
|
+
litecanvas.rotate(this.angle)
|
|
132
|
+
litecanvas.scale(this._s.x, this._s.y)
|
|
133
|
+
litecanvas.alpha(this.opacity)
|
|
134
|
+
}
|
|
135
|
+
}
|
package/src/grid/README.md
CHANGED
|
@@ -7,8 +7,10 @@
|
|
|
7
7
|
Lets build an arena with [ASCII graphics](https://en.wikipedia.org/wiki/ASCII_art) like in classic roguelikes.
|
|
8
8
|
|
|
9
9
|
```js
|
|
10
|
+
import { Grid } from "@litecanvas/utils"
|
|
11
|
+
|
|
10
12
|
// make a grid 13x13
|
|
11
|
-
let grid = new
|
|
13
|
+
let grid = new Grid(13, 13)
|
|
12
14
|
|
|
13
15
|
// fill the entire grid with "."
|
|
14
16
|
grid.fill(".")
|
package/src/index.js
CHANGED