kippy 0.1.0 → 0.2.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 CHANGED
@@ -31,6 +31,9 @@ const game = new Game({
31
31
 
32
32
  // Start the game loop
33
33
  game.start();
34
+
35
+ // You can also swap canvas if you want
36
+ // game.setCanvas(someOtherCanvas);
34
37
  ```
35
38
 
36
39
  ### Create a scene
@@ -63,7 +66,8 @@ const entity = new Entity({
63
66
  sprite, // Entity's sprite to be rendered, type Sprite
64
67
  x, // Entity's x position (centered), type number
65
68
  y, // Entity's y position (centered), type number
66
- rotation // Entity's rotation in radians, type number
69
+ rotation, // Entity's rotation in radians, type number
70
+ body, // Entity's physical body, type EntityBody
67
71
  });
68
72
 
69
73
  // Add it to a scene
@@ -81,50 +85,74 @@ entity.rotation; // Initialized from the "rotation" param above, 0 if not specif
81
85
 
82
86
  A sprite represents what an entity looks like, the "graphics part", you can create a sprite like this:
83
87
  ```js
88
+ import { Sprite } from "kippy";
89
+
84
90
  const sprite = new Sprite({
85
- texture, // Sprite's texture, can be HTMLImageElement, HTMLCanvasElement, OffscreenCanvas, ImageBitmap
91
+ texture, // Sprite's texture - HTMLImageElement, HTMLCanvasElement, OffscreenCanvas, ImageBitmap
86
92
  width, // Sprite's width, type number
87
93
  height // Sprite's height, type number
88
94
  });
89
95
 
90
96
  // Set sprite for an entity
91
- entity.setSprite(sprite);
97
+ entity.sprite = sprite;
92
98
  ```
93
99
 
94
100
  ### Add controls
95
101
 
96
- Game controls like mouse presses, key presses, and mouse cursor traking (in the game canvas, not the web window) can be done with the `Input` class:
102
+ Game controls like mouse presses, key presses, and mouse cursor traking (in the game canvas, not the web window) can be done by using the input handler from your `game` instance:
97
103
  ```js
98
- const input = new Input({
99
- canvas
100
- });
101
-
102
- // You can assign it into a game during initialization
103
- const game = new Game({
104
- // other stuff
105
- input
106
- })
107
- // or after
108
- game.setInput(input);
104
+ const input = game.input;
109
105
  ```
110
106
 
111
107
  Then in a scene's `update` method, you can use these utilities to check for key presses:
112
108
  ```js
113
109
  // Keyboard
114
- input.isKeyDown(/* Character/key here */); // Key hold
115
- input.isKeyPressed(/* Character/key here */); // Key press
116
- input.isKeyReleased(/* Character/key here */); // Key released
110
+ input.isKeyDown(/* Character/key here */); // true if key is held, false otherwise
111
+ input.isKeyPressed(/* Character/key here */); // true if key is pressed, false otherwise
112
+ input.isKeyReleased(/* Character/key here */); // true if key is released, false otherwise
117
113
  // Mouse
118
- input.isMouseDown(/* 0 for left, 1 for right */); // Mouse hold
119
- input.isMousePressed(/* 0 for left, 1 for right */); // Mouse press
120
- input.isMouseReleased(/* 0 for left, 1 for right */); // Mouse released
114
+ input.isMouseDown(/* 0 for left, 1 for right */); // true if mouse is held, false otherwise
115
+ input.isMousePressed(/* 0 for left, 1 for right */); // true if mouse is pressed, false otherwise
116
+ input.isMouseReleased(/* 0 for left, 1 for right */); // true if mouse is released, false otherwise
121
117
  input.mouseX; // Current X position of mouse
122
118
  input.mouseY; // Current Y position of mouse
123
119
  ```
124
120
 
125
121
  ### Physics
126
122
 
127
- To be added, will have rigidBody for entities with collision and movement-related stuff.
123
+ For movements, currently you can create a `RigidBody`:
124
+ ```js
125
+ // Create a rigid body
126
+ const rigidBody = new RigidBody({
127
+ velocityX, // X velocity, type number
128
+ velocityY, // Y velocity, type number
129
+ rotationVelocity, // Angular/rotation velocity, type number
130
+ mass, // Entity's mass, type number
131
+ 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
134
+ torque, // Entity's torque/rotational force, type number
135
+ });
136
+
137
+ // Attach body to an entity
138
+ entity.body = rigidBody;
139
+
140
+ // 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
143
+ entity.body.rotationVelocity; // Set with the matching parameter above, default is 0
144
+ entity.body.mass; // Set with the matching parameter above, default is 1
145
+ 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
148
+ entity.body.torque; // Set with the matching parameter above, default is 0
149
+ ```
150
+
151
+ Collisions to be added.
152
+
153
+ ### Animation
154
+
155
+ To be added, for now mutate `entity.sprite` to swap sprites and create animations manually.
128
156
 
129
157
  ### Audio
130
158
 
package/dist/entity.d.ts CHANGED
@@ -1,16 +1,18 @@
1
+ import { EntityBody } from "./physics.js";
1
2
  import { Sprite } from "./sprite.js";
2
3
  export interface EntityOptions {
3
4
  sprite?: Sprite;
4
5
  x?: number;
5
6
  y?: number;
6
7
  rotation?: number;
8
+ body?: EntityBody;
7
9
  }
8
10
  export declare class Entity {
9
11
  sprite?: Sprite;
10
12
  x: number;
11
13
  y: number;
12
14
  rotation: number;
13
- constructor(options: EntityOptions);
14
- setSprite(sprite: Sprite): void;
15
+ body?: EntityBody;
16
+ constructor(options?: EntityOptions);
15
17
  render(ctx: CanvasRenderingContext2D): void;
16
18
  }
package/dist/entity.js CHANGED
@@ -3,14 +3,13 @@ export class Entity {
3
3
  x;
4
4
  y;
5
5
  rotation;
6
- constructor(options) {
6
+ body;
7
+ constructor(options = {}) {
7
8
  this.sprite = options.sprite;
8
- this.x = options.x || 0;
9
- this.y = options.y || 0;
10
- this.rotation = options.rotation || 0;
11
- }
12
- setSprite(sprite) {
13
- this.sprite = sprite;
9
+ this.x = options.x ?? 0;
10
+ this.y = options.y ?? 0;
11
+ this.rotation = options.rotation ?? 0;
12
+ this.body = options.body;
14
13
  }
15
14
  render(ctx) {
16
15
  if (this.sprite) {
package/dist/game.d.ts CHANGED
@@ -1,18 +1,21 @@
1
1
  import { Input } from "./input.js";
2
+ import { Physics } from "./physics.js";
2
3
  import { Scene } from "./scene.js";
3
4
  export interface GameOptions {
4
5
  canvas: HTMLCanvasElement;
5
6
  input?: Input;
7
+ physics?: Physics;
6
8
  }
7
9
  export declare class Game {
8
10
  canvas: HTMLCanvasElement;
9
11
  ctx: CanvasRenderingContext2D;
10
12
  scene?: Scene;
11
13
  lastTime: number;
12
- input?: Input;
14
+ input: Input;
15
+ physics: Physics;
13
16
  constructor(options: GameOptions);
17
+ setCanvas(canvas: HTMLCanvasElement): void;
14
18
  setScene(scene: Scene): void;
15
- setInput(input: Input): void;
16
19
  start(): void;
17
20
  loop(timestamp: number): void;
18
21
  }
package/dist/game.js CHANGED
@@ -1,22 +1,27 @@
1
+ import { Input } from "./input.js";
2
+ import { Physics } from "./physics.js";
1
3
  export class Game {
2
4
  canvas;
3
5
  ctx;
4
6
  scene;
5
7
  lastTime = 0;
6
8
  input;
9
+ physics;
7
10
  constructor(options) {
8
11
  this.canvas = options.canvas;
9
12
  this.ctx = this.canvas.getContext("2d");
10
- this.input = options.input;
13
+ this.input = options.input ?? new Input({ canvas: this.canvas });
14
+ this.physics = options.physics ?? new Physics();
15
+ }
16
+ setCanvas(canvas) {
17
+ this.canvas = canvas;
18
+ this.ctx = this.canvas.getContext("2d");
11
19
  }
12
20
  setScene(scene) {
13
21
  this.scene?.exit();
14
22
  this.scene = scene;
15
23
  this.scene.init();
16
24
  }
17
- setInput(input) {
18
- this.input = input;
19
- }
20
25
  start() {
21
26
  requestAnimationFrame(this.loop.bind(this));
22
27
  }
@@ -24,12 +29,20 @@ export class Game {
24
29
  loop(timestamp) {
25
30
  const dt = (timestamp - this.lastTime) / 1000;
26
31
  this.lastTime = timestamp;
27
- // Update state, clear canvas, re-render
28
- this.scene?.update(dt);
29
- this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
30
- this.scene?.render(this.ctx);
31
- // Update input info
32
- this.input?.update();
32
+ if (this.scene) {
33
+ // Update input info
34
+ this.input.update();
35
+ // Update game logic
36
+ this.scene.update(dt);
37
+ // Update physics info
38
+ this.physics.update(this.scene.entities);
39
+ // Render
40
+ this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
41
+ this.scene.render(this.ctx);
42
+ }
43
+ else {
44
+ throw new Error("Can not run game loop without a scene");
45
+ }
33
46
  requestAnimationFrame(this.loop.bind(this));
34
47
  }
35
48
  }
@@ -0,0 +1,26 @@
1
+ import { Entity } from "./entity";
2
+ export interface RigidBodyOptions {
3
+ velocityX?: number;
4
+ velocityY?: number;
5
+ rotationVelocity?: number;
6
+ mass?: number;
7
+ inertia?: number;
8
+ forceX?: number;
9
+ forceY?: number;
10
+ torque?: number;
11
+ }
12
+ export declare class RigidBody {
13
+ velocityX: number;
14
+ velocityY: number;
15
+ rotationVelocity: number;
16
+ mass: number;
17
+ inertia: number;
18
+ forceX: number;
19
+ forceY: number;
20
+ torque: number;
21
+ constructor(options?: RigidBodyOptions);
22
+ }
23
+ export type EntityBody = RigidBody;
24
+ export declare class Physics {
25
+ update(entities: Entity[]): void;
26
+ }
@@ -0,0 +1,36 @@
1
+ export class RigidBody {
2
+ velocityX;
3
+ velocityY;
4
+ rotationVelocity;
5
+ mass;
6
+ inertia;
7
+ forceX;
8
+ forceY;
9
+ torque;
10
+ constructor(options = {}) {
11
+ this.velocityX = options.velocityX ?? 0;
12
+ this.velocityY = options.velocityY ?? 0;
13
+ this.rotationVelocity = options.rotationVelocity ?? 0;
14
+ this.mass = options.mass ?? 1;
15
+ this.inertia = options.inertia ?? 1;
16
+ this.forceX = options.forceX ?? 0;
17
+ this.forceY = options.forceY ?? 0;
18
+ this.torque = options.torque ?? 0;
19
+ }
20
+ }
21
+ export class Physics {
22
+ update(entities) {
23
+ for (const entity of entities) {
24
+ if (entity.body instanceof RigidBody) {
25
+ // Acceleration/apply force
26
+ entity.body.velocityX += entity.body.forceX / entity.body.mass;
27
+ entity.body.velocityY += entity.body.forceY / entity.body.mass;
28
+ entity.body.rotationVelocity += entity.body.torque / entity.body.inertia;
29
+ // Positional update
30
+ entity.x += entity.body.velocityX;
31
+ entity.y += entity.body.velocityY;
32
+ entity.rotation += entity.body.rotationVelocity;
33
+ }
34
+ }
35
+ }
36
+ }
package/dist/sprite.js CHANGED
@@ -4,7 +4,7 @@ export class Sprite {
4
4
  height;
5
5
  constructor(options) {
6
6
  this.texture = options.texture;
7
- this.width = options.width || this.texture.width;
8
- this.height = options.height || this.texture.height;
7
+ this.width = options.width ?? this.texture.width;
8
+ this.height = options.height ?? this.texture.height;
9
9
  }
10
10
  }
package/index.d.ts CHANGED
@@ -3,3 +3,4 @@ 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";
package/index.js CHANGED
@@ -3,3 +3,4 @@ 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";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kippy",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "description": "Kippy 2D web game engine for JS",
5
5
  "keywords": [
6
6
  "kippy",