kippy 0.2.2 → 0.3.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 CHANGED
@@ -64,8 +64,7 @@ import { Entity } from "kippy";
64
64
 
65
65
  const entity = new Entity({
66
66
  sprite, // Entity's sprite to be rendered, type Sprite
67
- x, // Entity's x position (centered), type number
68
- y, // Entity's y position (centered), type number
67
+ position, // Entity's position (centered), type Vector2
69
68
  rotation, // Entity's rotation in radians, type number
70
69
  body, // Entity's physical body, type EntityBody
71
70
  });
@@ -76,8 +75,10 @@ scene.addEntity(entity);
76
75
  scene.removeEntity(entity);
77
76
 
78
77
  // These props contain movement info and you can mutate them to edit its position
79
- entity.x; // Initialized from the "x" param above, 0 if not specified
80
- entity.y; // Initialized from the "y" param above, 0 if not specified
78
+ entity.position; // Initialized from the "position" param above, Vector2(0, 0) if not specified
79
+ // You can mutate these directly:
80
+ entity.position.x;
81
+ entity.position.y;
81
82
  entity.rotation; // Initialized from the "rotation" param above, 0 if not specified
82
83
  ```
83
84
 
@@ -118,19 +119,55 @@ input.pointerX; // Current X position of mouse/touch
118
119
  input.pointerY; // Current Y position of mouse/touch
119
120
  ```
120
121
 
122
+ ### Vectors
123
+
124
+ To work with positions and movements in Kippy, it is best to know about `Vector2` first. Positions, velocities, forces, etc are all represented as vectors in Kippy. And here is how you can create a 2D vector and some vector math utilities that comes along with it:
125
+ ```js
126
+ import { Vector2 } from "kippy";
127
+
128
+ const vect = new Vector2(/* x coordinate, number */, /*y coordinate, number */);
129
+
130
+ // Props
131
+ vect.x; // X coordinate
132
+ vect.y; // Y coordinate
133
+
134
+ // Utilities
135
+ vect.add(otherVect); // Add another vector and return the result vector
136
+ vect.sub(otherVect); // Subtract another vector and return the result vector
137
+ vect.scale(scale); // Multiply with scale and return the result vector
138
+ vect.magnitude(); // Return the magnitude/length of vector
139
+ vect.normalize(); // Return the normalized vector by magnitude
140
+ vect.dot(otherVect); // Return dot product with another vector
141
+ vect.distance(otherVect); // Return distance to another vector
142
+ vect.copy(); // Return a copy (same coordinates, different reference)
143
+ vect.lerp(otherVect, scale); // Apply linear interpolation and return
144
+ vect.clamp(maxLength); // Clamp vector to have length below maxLength
145
+ vect.rotate(angle); // Return rotated vector by provided angle
146
+ vect.angle(); // Return angle of vector.
147
+ vect.angleTo(otherVec); // Return angle between this and another vector
148
+ vect.reflect(otherVect); // Return reflection/bounce back vector
149
+ vect.equals(otherVect); // Check if two vectors are equal
150
+
151
+ // Useful constants
152
+ Vector2.ZERO; // Vector2(0, 0)
153
+ Vector2.ONE; // Vector2(1, 1);
154
+ Vector2.UP; // Vector2(0, -1);
155
+ Vector2.DOWN; // Vector2(0, 1);
156
+ Vector2.LEFT; // Vector2(-1, 0);
157
+ Vector2.RIGHT; // Vector2(1, 0);
158
+ ```
159
+
121
160
  ### Physics
122
161
 
123
162
  For movements, currently you can create a `RigidBody`:
124
163
  ```js
125
164
  // Create a rigid body
126
165
  const rigidBody = new RigidBody({
127
- velocityX, // X velocity, type number
128
- velocityY, // Y velocity, type number
129
- rotationVelocity, // Angular/rotation velocity, type number
166
+ velocity, // Entity's velocity vector, type Vector2
167
+ rotationVelocity, // Entity's ngular/rotation velocity, type number
130
168
  mass, // Entity's mass, type number
131
169
  inertia, // Entity's inertia, type number
132
- forceX, // Entity's force on X axis, type number
133
- forceY, // Entity's force on Y axis, type number
170
+ force, // Entity's force vector, type Vector2
134
171
  torque, // Entity's torque/rotational force, type number
135
172
  });
136
173
 
@@ -138,13 +175,12 @@ const rigidBody = new RigidBody({
138
175
  entity.body = rigidBody;
139
176
 
140
177
  // And you can mutate these props to update movement every frame
141
- entity.body.velocityX; // Set with the matching parameter above, default is 0
142
- entity.body.velocityY; // Set with the matching parameter above, default is 0
178
+ entity.body.velocity; // Set with the matching parameter above, default is Vector2(0, 0)
143
179
  entity.body.rotationVelocity; // Set with the matching parameter above, default is 0
144
180
  entity.body.mass; // Set with the matching parameter above, default is 1
145
181
  entity.body.inertia; // Set with the matching parameter above, default is 1
146
- entity.body.forceX; // Set with the matching parameter above, default is 0
147
- entity.body.forceY; // Set with the matching parameter above, default is 0
182
+ // Note that forces are reset after every frame
183
+ entity.body.force; // Set with the matching parameter above, default is Vector2(0, 0)
148
184
  entity.body.torque; // Set with the matching parameter above, default is 0
149
185
  ```
150
186
 
@@ -158,6 +194,10 @@ To be added, for now mutate `entity.sprite` to swap sprites and create animation
158
194
 
159
195
  To be added, for now use web's built-in `Audio` class.
160
196
 
197
+ ### Asset management
198
+
199
+ To be added.
200
+
161
201
  ## Copyrights and License
162
202
 
163
203
  Copyrights © 2026 Nguyen Phu Minh.
package/dist/entity.d.ts CHANGED
@@ -1,16 +1,15 @@
1
1
  import { EntityBody } from "./physics.js";
2
2
  import { Sprite } from "./sprite.js";
3
+ import { Vector2 } from "./vector.js";
3
4
  export interface EntityOptions {
4
5
  sprite?: Sprite;
5
- x?: number;
6
- y?: number;
6
+ position?: Vector2;
7
7
  rotation?: number;
8
8
  body?: EntityBody;
9
9
  }
10
10
  export declare class Entity {
11
11
  sprite?: Sprite;
12
- x: number;
13
- y: number;
12
+ position: Vector2;
14
13
  rotation: number;
15
14
  body?: EntityBody;
16
15
  constructor(options?: EntityOptions);
package/dist/entity.js CHANGED
@@ -1,20 +1,19 @@
1
+ import { Vector2 } from "./vector.js";
1
2
  export class Entity {
2
3
  sprite;
3
- x;
4
- y;
4
+ position;
5
5
  rotation;
6
6
  body;
7
7
  constructor(options = {}) {
8
8
  this.sprite = options.sprite;
9
- this.x = options.x ?? 0;
10
- this.y = options.y ?? 0;
9
+ this.position = options.position ?? new Vector2(0, 0);
11
10
  this.rotation = options.rotation ?? 0;
12
11
  this.body = options.body;
13
12
  }
14
13
  render(ctx) {
15
14
  if (this.sprite) {
16
15
  ctx.save();
17
- ctx.translate(this.x, this.y);
16
+ ctx.translate(this.position.x, this.position.y);
18
17
  ctx.rotate(this.rotation);
19
18
  ctx.drawImage(this.sprite.texture, -this.sprite.width / 2, -this.sprite.height / 2);
20
19
  ctx.restore();
package/dist/physics.d.ts CHANGED
@@ -1,22 +1,19 @@
1
1
  import { Entity } from "./entity";
2
+ import { Vector2 } from "./vector";
2
3
  export interface RigidBodyOptions {
3
- velocityX?: number;
4
- velocityY?: number;
4
+ velocity?: Vector2;
5
5
  rotationVelocity?: number;
6
6
  mass?: number;
7
7
  inertia?: number;
8
- forceX?: number;
9
- forceY?: number;
8
+ force?: Vector2;
10
9
  torque?: number;
11
10
  }
12
11
  export declare class RigidBody {
13
- velocityX: number;
14
- velocityY: number;
12
+ velocity: Vector2;
15
13
  rotationVelocity: number;
16
14
  mass: number;
17
15
  inertia: number;
18
- forceX: number;
19
- forceY: number;
16
+ force: Vector2;
20
17
  torque: number;
21
18
  constructor(options?: RigidBodyOptions);
22
19
  }
package/dist/physics.js CHANGED
@@ -1,20 +1,17 @@
1
+ import { Vector2 } from "./vector";
1
2
  export class RigidBody {
2
- velocityX;
3
- velocityY;
3
+ velocity;
4
4
  rotationVelocity;
5
5
  mass;
6
6
  inertia;
7
- forceX;
8
- forceY;
7
+ force;
9
8
  torque;
10
9
  constructor(options = {}) {
11
- this.velocityX = options.velocityX ?? 0;
12
- this.velocityY = options.velocityY ?? 0;
10
+ this.velocity = options.velocity ?? new Vector2(0, 0);
13
11
  this.rotationVelocity = options.rotationVelocity ?? 0;
14
12
  this.mass = options.mass ?? 1;
15
13
  this.inertia = options.inertia ?? 1;
16
- this.forceX = options.forceX ?? 0;
17
- this.forceY = options.forceY ?? 0;
14
+ this.force = options.force ?? new Vector2(0, 0);
18
15
  this.torque = options.torque ?? 0;
19
16
  }
20
17
  }
@@ -23,13 +20,17 @@ export class Physics {
23
20
  for (const entity of entities) {
24
21
  if (entity.body instanceof RigidBody) {
25
22
  // Acceleration/apply force
26
- entity.body.velocityX += entity.body.forceX / entity.body.mass;
27
- entity.body.velocityY += entity.body.forceY / entity.body.mass;
23
+ entity.body.velocity.x += entity.body.force.x / entity.body.mass;
24
+ entity.body.velocity.y += entity.body.force.y / entity.body.mass;
28
25
  entity.body.rotationVelocity += entity.body.torque / entity.body.inertia;
29
26
  // Positional update
30
- entity.x += entity.body.velocityX;
31
- entity.y += entity.body.velocityY;
27
+ entity.position.x += entity.body.velocity.x;
28
+ entity.position.y += entity.body.velocity.y;
32
29
  entity.rotation += entity.body.rotationVelocity;
30
+ // Clear force
31
+ entity.body.force.x = 0;
32
+ entity.body.force.y = 0;
33
+ entity.body.torque = 0;
33
34
  }
34
35
  }
35
36
  }
@@ -0,0 +1,26 @@
1
+ export declare class Vector2 {
2
+ x: number;
3
+ y: number;
4
+ static ZERO: Vector2;
5
+ static ONE: Vector2;
6
+ static UP: Vector2;
7
+ static DOWN: Vector2;
8
+ static LEFT: Vector2;
9
+ static RIGHT: Vector2;
10
+ constructor(x: number, y: number);
11
+ add(other: Vector2): Vector2;
12
+ sub(other: Vector2): Vector2;
13
+ scale(scale: number): Vector2;
14
+ magnitude(): number;
15
+ normalize(): Vector2;
16
+ dot(other: Vector2): number;
17
+ distance(other: Vector2): number;
18
+ copy(): Vector2;
19
+ lerp(other: Vector2, scale: number): Vector2;
20
+ clamp(maxLength: number): Vector2;
21
+ rotate(angle: number): Vector2;
22
+ angle(): number;
23
+ angleTo(other: Vector2): number;
24
+ reflect(normal: Vector2): Vector2;
25
+ equals(other: Vector2): boolean;
26
+ }
package/dist/vector.js ADDED
@@ -0,0 +1,64 @@
1
+ export class Vector2 {
2
+ x;
3
+ y;
4
+ static ZERO = new Vector2(0, 0);
5
+ static ONE = new Vector2(1, 1);
6
+ static UP = new Vector2(0, -1);
7
+ static DOWN = new Vector2(0, 1);
8
+ static LEFT = new Vector2(-1, 0);
9
+ static RIGHT = new Vector2(1, 0);
10
+ constructor(x, y) {
11
+ this.x = x;
12
+ this.y = y;
13
+ }
14
+ add(other) {
15
+ return new Vector2(this.x + other.x, this.y + other.y);
16
+ }
17
+ sub(other) {
18
+ return new Vector2(this.x - other.x, this.y - other.y);
19
+ }
20
+ scale(scale) {
21
+ return new Vector2(this.x * scale, this.y * scale);
22
+ }
23
+ magnitude() {
24
+ return Math.sqrt(this.x * this.x + this.y * this.y);
25
+ }
26
+ normalize() {
27
+ const mag = this.magnitude();
28
+ return mag > 0 ? new Vector2(this.x / mag, this.y / mag) : new Vector2(0, 0);
29
+ }
30
+ dot(other) {
31
+ return this.x * other.x + this.y * other.y;
32
+ }
33
+ distance(other) {
34
+ return Math.sqrt((this.x - other.x) ** 2 + (this.y - other.y) ** 2);
35
+ }
36
+ copy() {
37
+ return new Vector2(this.x, this.y);
38
+ }
39
+ lerp(other, scale) {
40
+ return this.add(other.sub(this).scale(scale));
41
+ }
42
+ clamp(maxLength) {
43
+ const mag = this.magnitude();
44
+ return mag > maxLength ? this.scale(maxLength / mag) : this.copy();
45
+ }
46
+ rotate(angle) {
47
+ const cos = Math.cos(angle);
48
+ const sin = Math.sin(angle);
49
+ return new Vector2(this.x * cos - this.y * sin, this.x * sin + this.y * cos);
50
+ }
51
+ angle() {
52
+ return Math.atan2(this.y, this.x);
53
+ }
54
+ angleTo(other) {
55
+ return Math.atan2(other.y - this.y, other.x - this.x);
56
+ }
57
+ reflect(normal) {
58
+ const d = this.dot(normal);
59
+ return this.sub(normal.scale(2 * d));
60
+ }
61
+ equals(other) {
62
+ return this.x === other.x && this.y === other.y;
63
+ }
64
+ }
package/index.d.ts CHANGED
@@ -3,4 +3,5 @@ export * from "./dist/scene.js";
3
3
  export * from "./dist/entity.js";
4
4
  export * from "./dist/sprite.js";
5
5
  export * from "./dist/input.js";
6
- export * from "./dist/physics.js";
6
+ export * from "./dist/physics.js";
7
+ export * from "./dist/vector.js";
package/index.js CHANGED
@@ -4,3 +4,4 @@ export * from "./dist/entity.js";
4
4
  export * from "./dist/sprite.js";
5
5
  export * from "./dist/input.js";
6
6
  export * from "./dist/physics.js";
7
+ export * from "./dist/vector.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kippy",
3
- "version": "0.2.2",
3
+ "version": "0.3.0",
4
4
  "description": "Kippy 2D web game engine for JS",
5
5
  "keywords": [
6
6
  "kippy",