infernojs 0.0.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.
@@ -0,0 +1,211 @@
1
+ import { Entity, Shape, Circle, Point, Rectangle } from './types.js';
2
+ export { AABB, CollisionConfig, CollisionResult, ContactPoint, ShapeType, Vector2D } from './types.js';
3
+ export { aabbIntersect, add, cellToId, circleToAABB, cross, distance, distanceSquared, dot, length, lengthSquared, normalize, positionToCell, rectToAABB, scale, subtract, vec2 } from './utils.js';
4
+
5
+ /**
6
+ * Base class for collision detectors that implements common functionality
7
+ */
8
+ declare abstract class BaseCollisionDetector {
9
+ /**
10
+ * The entities to check collisions against
11
+ */
12
+ protected entities: Entity[];
13
+ /**
14
+ * Create a new collision detector
15
+ * @param entities The entities to check collisions against
16
+ */
17
+ constructor(entities: Entity[]);
18
+ /**
19
+ * Get all entities that collide with the given shape
20
+ * @param shape The shape to check collisions against
21
+ * @returns Array of entity IDs that collide with the shape
22
+ */
23
+ abstract getCollisions(shape: Shape): (string | number)[];
24
+ }
25
+
26
+ /**
27
+ * Collision detector that uses a brute force approach
28
+ * Checks every entity against the given shape
29
+ *
30
+ * Best used when:
31
+ * - You have a small number of entities
32
+ * - You only need to check collisions occasionally
33
+ * - You want the simplest implementation
34
+ */
35
+ declare function BruteForceCollisionDetector({ entities, }: {
36
+ entities: Entity[];
37
+ }): BruteForceCollisionDetectorImpl;
38
+ declare class BruteForceCollisionDetectorImpl extends BaseCollisionDetector {
39
+ /**
40
+ * Get all entities that collide with the given shape
41
+ * @param shape The shape to check collisions against
42
+ * @returns Array of entity IDs that collide with the shape
43
+ */
44
+ getCollisions(shape: Shape): (string | number)[];
45
+ }
46
+
47
+ /**
48
+ * Configuration options for the spatial grid collision detector
49
+ */
50
+ interface SpatialGridConfig {
51
+ /** Size of each grid cell */
52
+ cellSize: number;
53
+ }
54
+ /**
55
+ * Collision detector that uses spatial partitioning for efficient collision detection
56
+ *
57
+ * Best used when:
58
+ * - You have a large number of entities
59
+ * - Entities are distributed across the space
60
+ * - You need to check collisions frequently
61
+ */
62
+ declare function SpatialGridCollisionDetector({ entities, cellSize, }: {
63
+ entities: Entity[];
64
+ cellSize?: number;
65
+ }): SpatialGridCollisionDetectorImpl;
66
+ declare class SpatialGridCollisionDetectorImpl extends BaseCollisionDetector {
67
+ /** The spatial hash grid for quick lookups */
68
+ private grid;
69
+ /** Configuration for the spatial grid */
70
+ private config;
71
+ /**
72
+ * Create a new spatial grid collision detector
73
+ */
74
+ constructor(entities: Entity[], config: SpatialGridConfig);
75
+ /**
76
+ * Get all entities that collide with the given shape
77
+ */
78
+ getCollisions(shape: Shape): (string | number)[];
79
+ /**
80
+ * Rebuild the spatial grid with the current entities
81
+ */
82
+ rebuildGrid(): void;
83
+ /**
84
+ * Insert an entity into the spatial grid
85
+ */
86
+ private insertEntityIntoGrid;
87
+ /**
88
+ * Get all cells that an AABB overlaps
89
+ */
90
+ private getCellsForAABB;
91
+ /**
92
+ * Get the AABB for an entity
93
+ */
94
+ private getAABB;
95
+ /**
96
+ * Get the AABB for a shape
97
+ */
98
+ private getAABBForShape;
99
+ }
100
+
101
+ /**
102
+ * Check if two entities are colliding
103
+ * @param shapeA First shape
104
+ * @param shapeB Second shape
105
+ * @returns True if the shapes are colliding
106
+ */
107
+ declare function checkShapeCollision(shapeA: Shape, shapeB: Shape): boolean;
108
+
109
+ /**
110
+ * Style options for rendering shapes
111
+ */
112
+ type ShapeStyle = {
113
+ /** Fill color (CSS color string) */
114
+ fillColor?: string;
115
+ /** Stroke color (CSS color string) */
116
+ strokeColor?: string;
117
+ /** Stroke width in pixels */
118
+ strokeWidth?: number;
119
+ /** Alpha/opacity (0-1) */
120
+ alpha?: number;
121
+ /** Shadow blur radius */
122
+ shadowBlur?: number;
123
+ /** Shadow color */
124
+ shadowColor?: string;
125
+ /** Shadow offset X */
126
+ shadowOffsetX?: number;
127
+ /** Shadow offset Y */
128
+ shadowOffsetY?: number;
129
+ };
130
+ /**
131
+ * A renderable entity with shape and style
132
+ */
133
+ type RenderableShape = {
134
+ shape: Shape;
135
+ style: ShapeStyle;
136
+ };
137
+ /**
138
+ * Configuration options for the renderer
139
+ */
140
+ type RendererOptions = {
141
+ /** Background color of the canvas */
142
+ backgroundColor?: string;
143
+ /** Default style to apply to shapes without specific styling */
144
+ defaultStyle?: ShapeStyle;
145
+ /** Whether to clear the canvas before each render */
146
+ clearBeforeRender?: boolean;
147
+ };
148
+
149
+ /**
150
+ * Apply style settings to the canvas context
151
+ */
152
+ declare function applyStyle(ctx: CanvasRenderingContext2D, style: ShapeStyle): void;
153
+ /**
154
+ * Restore the canvas context to its previous state
155
+ */
156
+ declare function restoreContext(ctx: CanvasRenderingContext2D): void;
157
+ /**
158
+ * Render a circle shape
159
+ */
160
+ declare function renderCircle(ctx: CanvasRenderingContext2D, circle: Circle, style: ShapeStyle): void;
161
+ /**
162
+ * Render a point shape
163
+ */
164
+ declare function renderPoint(ctx: CanvasRenderingContext2D, point: Point, style: ShapeStyle): void;
165
+ /**
166
+ * Render a rectangle shape
167
+ */
168
+ declare function renderRectangle(ctx: CanvasRenderingContext2D, rectangle: Rectangle, style: ShapeStyle): void;
169
+ /**
170
+ * Render any shape based on its type
171
+ */
172
+ declare function renderShape(ctx: CanvasRenderingContext2D, shape: Shape, style: ShapeStyle): void;
173
+ /**
174
+ * Main renderer function to render multiple shapes
175
+ */
176
+ declare function renderShapes(ctx: CanvasRenderingContext2D, shapes: RenderableShape[], options: RendererOptions): void;
177
+
178
+ /**
179
+ * pepperjs
180
+ * A spicy, high-performance library for building 2D games in JavaScript
181
+ *
182
+ * @packageDocumentation
183
+ */
184
+
185
+ declare const VERSION = "0.0.1";
186
+ /**
187
+ * @internal
188
+ * Rendering capabilities
189
+ */
190
+ declare const Renderer: {
191
+ notImplemented: boolean;
192
+ info: string;
193
+ };
194
+ /**
195
+ * @internal
196
+ * Future game loop management API
197
+ */
198
+ declare const GameLoop: {
199
+ notImplemented: boolean;
200
+ info: string;
201
+ };
202
+ /**
203
+ * @internal
204
+ * Future input handling API
205
+ */
206
+ declare const Input: {
207
+ notImplemented: boolean;
208
+ info: string;
209
+ };
210
+
211
+ export { BaseCollisionDetector, BruteForceCollisionDetector, Circle, Entity, GameLoop, Input, Point, Rectangle, Renderer, Shape, SpatialGridCollisionDetector, type SpatialGridConfig, VERSION, applyStyle, checkShapeCollision, renderCircle, renderPoint, renderRectangle, renderShape, renderShapes, restoreContext };
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";var B=Object.defineProperty;var z=Object.getOwnPropertyDescriptor;var j=Object.getOwnPropertyNames;var H=Object.prototype.hasOwnProperty;var U=(t,o)=>{for(var e in o)B(t,e,{get:o[e],enumerable:!0})},L=(t,o,e,n)=>{if(o&&typeof o=="object"||typeof o=="function")for(let i of j(o))!H.call(t,i)&&i!==e&&B(t,i,{get:()=>o[i],enumerable:!(n=z(o,i))||n.enumerable});return t};var N=t=>L(B({},"__esModule",{value:!0}),t);var ut={};U(ut,{BaseCollisionDetector:()=>p,BruteForceCollisionDetector:()=>it,GameLoop:()=>ct,Input:()=>dt,Renderer:()=>at,SpatialGridCollisionDetector:()=>rt,VERSION:()=>lt,aabbIntersect:()=>P,add:()=>J,applyStyle:()=>b,cellToId:()=>V,checkShapeCollision:()=>g,circleToAABB:()=>A,cross:()=>Q,distance:()=>Z,distanceSquared:()=>f,dot:()=>C,length:()=>v,lengthSquared:()=>E,normalize:()=>y,positionToCell:()=>R,rectToAABB:()=>h,renderCircle:()=>X,renderPoint:()=>Y,renderRectangle:()=>G,renderShape:()=>F,renderShapes:()=>st,restoreContext:()=>w,scale:()=>K,subtract:()=>x,vec2:()=>$});module.exports=N(ut);function $(t,o){return{x:t,y:o}}function J(t,o){return{x:t.x+o.x,y:t.y+o.y}}function x(t,o){return{x:t.x-o.x,y:t.y-o.y}}function K(t,o){return{x:t.x*o,y:t.y*o}}function C(t,o){return t.x*o.x+t.y*o.y}function Q(t,o){return t.x*o.y-t.y*o.x}function E(t){return t.x*t.x+t.y*t.y}function v(t){return Math.sqrt(E(t))}function y(t){let o=v(t);return o<1e-10?{x:0,y:0}:{x:t.x/o,y:t.y/o}}function f(t,o){let e=o.x-t.x,n=o.y-t.y;return e*e+n*n}function Z(t,o){return Math.sqrt(f(t,o))}function h(t){return{min:{x:t.position.x,y:t.position.y},max:{x:t.position.x+t.width,y:t.position.y+t.height}}}function A(t){return{min:{x:t.center.x-t.radius,y:t.center.y-t.radius},max:{x:t.center.x+t.radius,y:t.center.y+t.radius}}}function P(t,o){return!(t.max.x<o.min.x||t.min.x>o.max.x||t.max.y<o.min.y||t.min.y>o.max.y)}function R(t,o){return[Math.floor(t.x/o),Math.floor(t.y/o)]}function V(t,o){return(t+o)*(t+o+1)/2+o}var p=class{constructor(o){this.entities=o}};function q(t,o){let e=f(t.center,o.center),n=t.radius+o.radius;return{colliding:e<=n*n}}function k(t,o){return{colliding:f(t.center,o.position)<=t.radius*t.radius}}function S(t,o){if(o.rotationDeg!==0)return _(t,o);let e=Math.max(o.position.x,Math.min(t.center.x,o.position.x+o.width)),n=Math.max(o.position.y,Math.min(t.center.y,o.position.y+o.height));return{colliding:f(t.center,{x:e,y:n})<=t.radius*t.radius}}function _(t,o){let e=o.rotationDeg*Math.PI/180,n=Math.cos(-e),i=Math.sin(-e),r=o.position.x+o.width/2,s=o.position.y+o.height/2,l=t.center.x-r,a=t.center.y-s,c=n*l-i*a,d=i*l+n*a,m={type:"circle",center:{x:c+r,y:d+s},radius:t.radius},u={type:"rectangle",position:o.position,width:o.width,height:o.height,rotationDeg:0};return S(m,u)}function D(t,o){return t.rotationDeg!==0?tt(t,o):{colliding:o.position.x>=t.position.x&&o.position.x<=t.position.x+t.width&&o.position.y>=t.position.y&&o.position.y<=t.position.y+t.height}}function tt(t,o){let e=t.rotationDeg*Math.PI/180,n=Math.cos(-e),i=Math.sin(-e),r=t.position.x+t.width/2,s=t.position.y+t.height/2,l=o.position.x-r,a=o.position.y-s,c=n*l-i*a,d=i*l+n*a,m={type:"point",position:{x:c+r,y:d+s}},u={type:"rectangle",position:{x:t.position.x,y:t.position.y},width:t.width,height:t.height,rotationDeg:0};return D(u,m)}function O(t,o){return t.rotationDeg===0&&o.rotationDeg===0?ot(t,o):nt(t,o)}function ot(t,o){return{colliding:P(h(t),h(o))}}function T(t){let{position:o,width:e,height:n,rotationDeg:i}=t,r=e/2,s=n/2,l={x:o.x+r,y:o.y+s},a=i*Math.PI/180,c=Math.cos(a),d=Math.sin(a);return[{x:-r,y:-s},{x:r,y:-s},{x:r,y:s},{x:-r,y:s}].map(u=>({x:l.x+(u.x*c-u.y*d),y:l.y+(u.x*d+u.y*c)}))}function et(t,o){let e=[];for(let n=0;n<t.length;n++){let i=t[n],r=t[(n+1)%t.length],s=x(r,i),l=y({x:-s.y,y:s.x});e.push(l)}for(let n=0;n<o.length;n++){let i=o[n],r=o[(n+1)%o.length],s=x(r,i),l=y({x:-s.y,y:s.x});e.push(l)}return e}function W(t,o){let e=C(t[0],o),n=e;for(let i=1;i<t.length;i++){let r=C(t[i],o);r<e&&(e=r),r>n&&(n=r)}return{min:e,max:n}}function nt(t,o){let e=T(t),n=T(o),i=et(e,n);for(let r of i){let s=W(e,r),l=W(n,r);if(s.max<l.min||l.max<s.min)return{colliding:!1}}return{colliding:!0}}function g(t,o){let e=t.type,n=o.type;return e==="circle"&&n==="circle"?q(t,o).colliding:e==="circle"&&n==="point"?k(t,o).colliding:e==="point"&&n==="circle"?k(o,t).colliding:e==="circle"&&n==="rectangle"?S(t,o).colliding:e==="rectangle"&&n==="circle"?S(o,t).colliding:e==="rectangle"&&n==="rectangle"?O(t,o).colliding:e==="rectangle"&&n==="point"?D(t,o).colliding:e==="point"&&n==="rectangle"?D(o,t).colliding:!1}function it({entities:t}){return new I(t)}var I=class extends p{getCollisions(o){let e=[];for(let n of this.entities)g(o,n.shape)&&e.push(n.id);return e}};function rt({entities:t,cellSize:o=64}){return new M(t,{cellSize:o})}var M=class extends p{constructor(o,e){super(o),this.config=e,this.grid=new Map,this.rebuildGrid()}getCollisions(o){let e=this.getAABBForShape(o),n=this.getCellsForAABB(e),i=new Set;for(let s of n){let l=this.grid.get(s);if(l)for(let a of l)i.add(a)}let r=[];for(let s of i)g(o,s.shape)&&r.push(s.id);return r}rebuildGrid(){this.grid.clear();for(let o of this.entities)this.insertEntityIntoGrid(o)}insertEntityIntoGrid(o){let e=this.getAABB(o),n=this.getCellsForAABB(e);for(let i of n)this.grid.has(i)||this.grid.set(i,[]),this.grid.get(i).push(o)}getCellsForAABB(o){let{cellSize:e}=this.config,[n,i]=R(o.min,e),[r,s]=R(o.max,e),l=new Array((r-n+1)*(s-i+1)),a=0;for(let c=n;c<=r;c++)for(let d=i;d<=s;d++)l[a++]=V(c,d);return l}getAABB(o){return this.getAABBForShape(o.shape)}getAABBForShape(o){let e=o.type;if(e==="circle")return A(o);if(e==="rectangle")return h(o);if(e==="point")return{min:{x:o.position.x,y:o.position.y},max:{x:o.position.x,y:o.position.y}};throw new Error(`Unsupported shape type: ${e}`)}};function b(t,o){t.save(),o.fillColor&&(t.fillStyle=o.fillColor),o.strokeColor&&(t.strokeStyle=o.strokeColor),o.strokeWidth!==void 0&&(t.lineWidth=o.strokeWidth),o.alpha!==void 0&&(t.globalAlpha=o.alpha),o.shadowBlur!==void 0&&(t.shadowBlur=o.shadowBlur),o.shadowColor&&(t.shadowColor=o.shadowColor),o.shadowOffsetX!==void 0&&(t.shadowOffsetX=o.shadowOffsetX),o.shadowOffsetY!==void 0&&(t.shadowOffsetY=o.shadowOffsetY)}function w(t){t.restore()}function X(t,o,e){b(t,e),t.beginPath(),t.arc(o.center.x,o.center.y,o.radius,0,Math.PI*2),e.fillColor&&t.fill(),e.strokeColor&&e.strokeWidth&&e.strokeWidth>0&&t.stroke(),w(t)}function Y(t,o,e){let n=e.strokeWidth||4;b(t,e),t.beginPath(),t.arc(o.position.x,o.position.y,n/2,0,Math.PI*2),e.fillColor&&t.fill(),e.strokeColor&&e.strokeWidth&&e.strokeWidth>0&&t.stroke(),w(t)}function G(t,o,e){if(b(t,e),t.save(),t.translate(o.position.x,o.position.y),o.rotationDeg!==0){let r=o.rotationDeg*Math.PI/180;t.rotate(r)}let n=o.width/2,i=o.height/2;e.fillColor&&t.fillRect(-n,-i,o.width,o.height),e.strokeColor&&e.strokeWidth&&e.strokeWidth>0&&t.strokeRect(-n,-i,o.width,o.height),t.restore(),w(t)}function F(t,o,e){switch(o.type){case"circle":X(t,o,e);break;case"rectangle":G(t,o,e);break;case"point":Y(t,o,e);break;default:console.warn("Unknown shape type encountered");break}}function st(t,o,e){for(let{shape:n,style:i}of o){let r={...e.defaultStyle,...i};F(t,n,r)}}var lt="0.0.1",at={notImplemented:!1,info:"Basic rendering capabilities are now available"},ct={notImplemented:!0,info:"Game loop management will be added in a future version"},dt={notImplemented:!0,info:"Input handling will be added in a future version"};0&&(module.exports={BaseCollisionDetector,BruteForceCollisionDetector,GameLoop,Input,Renderer,SpatialGridCollisionDetector,VERSION,aabbIntersect,add,applyStyle,cellToId,checkShapeCollision,circleToAABB,cross,distance,distanceSquared,dot,length,lengthSquared,normalize,positionToCell,rectToAABB,renderCircle,renderPoint,renderRectangle,renderShape,renderShapes,restoreContext,scale,subtract,vec2});
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/utils.ts","../src/collision/CollisionDetector.ts","../src/collision/shapeCollisions/circleCircle/index.ts","../src/collision/shapeCollisions/circlePoint/index.ts","../src/collision/shapeCollisions/circleRect/index.ts","../src/collision/shapeCollisions/rectPoint/index.ts","../src/collision/shapeCollisions/rectRect/index.ts","../src/collision/shapeCollisions/checkShapeCollision.ts","../src/collision/BruteForceCollisionDetector.ts","../src/collision/SpatialGridCollisionDetector.ts","../src/render/index.ts"],"sourcesContent":["/**\n * pepperjs\n * A spicy, high-performance library for building 2D games in JavaScript\n *\n * @packageDocumentation\n */\n\n// ----- Collision Detection System -----\n// Export types\nexport * from \"./types\";\n\n// Export utility functions\nexport * from \"./utils\";\n\n// Export collision detection system\nexport * from \"./collision\";\n\n// Export rendering system\nexport * from \"./render\";\n\n// ----- Library Information -----\nexport const VERSION = \"0.0.1\";\n\n// ----- Future modules (placeholders) -----\n// These will be implemented in future versions\n\n/**\n * @internal\n * Rendering capabilities\n */\nexport const Renderer = {\n // Renderer is now implemented\n notImplemented: false,\n\n // Information about implementation\n info: \"Basic rendering capabilities are now available\",\n};\n\n/**\n * @internal\n * Future game loop management API\n */\nexport const GameLoop = {\n // Placeholder for future game loop module\n notImplemented: true,\n\n // Information about planned implementation\n info: \"Game loop management will be added in a future version\",\n};\n\n/**\n * @internal\n * Future input handling API\n */\nexport const Input = {\n // Placeholder for future input handling module\n notImplemented: true,\n\n // Information about planned implementation\n info: \"Input handling will be added in a future version\",\n};\n","import { Vector2D, AABB, Circle, Rectangle } from \"./types\";\n\n/**\n * Create a new vector\n */\nexport function vec2(x: number, y: number): Vector2D {\n return { x, y };\n}\n\n/**\n * Vector addition\n */\nexport function add(a: Vector2D, b: Vector2D): Vector2D {\n return { x: a.x + b.x, y: a.y + b.y };\n}\n\n/**\n * Vector subtraction\n */\nexport function subtract(a: Vector2D, b: Vector2D): Vector2D {\n return { x: a.x - b.x, y: a.y - b.y };\n}\n\n/**\n * Vector scaling\n */\nexport function scale(v: Vector2D, scalar: number): Vector2D {\n return { x: v.x * scalar, y: v.y * scalar };\n}\n\n/**\n * Dot product of two vectors\n */\nexport function dot(a: Vector2D, b: Vector2D): number {\n return a.x * b.x + a.y * b.y;\n}\n\n/**\n * Cross product magnitude of two 2D vectors\n */\nexport function cross(a: Vector2D, b: Vector2D): number {\n return a.x * b.y - a.y * b.x;\n}\n\n/**\n * Get squared length of a vector (avoids sqrt for performance)\n */\nexport function lengthSquared(v: Vector2D): number {\n return v.x * v.x + v.y * v.y;\n}\n\n/**\n * Get vector length\n */\nexport function length(v: Vector2D): number {\n return Math.sqrt(lengthSquared(v));\n}\n\n/**\n * Normalize a vector (make it unit length)\n */\nexport function normalize(v: Vector2D): Vector2D {\n const len = length(v);\n // Avoid division by zero\n if (len < 1e-10) return { x: 0, y: 0 };\n return { x: v.x / len, y: v.y / len };\n}\n\n/**\n * Distance squared between two points (avoids sqrt for performance)\n */\nexport function distanceSquared(a: Vector2D, b: Vector2D): number {\n const dx = b.x - a.x;\n const dy = b.y - a.y;\n return dx * dx + dy * dy;\n}\n\n/**\n * Distance between two points\n */\nexport function distance(a: Vector2D, b: Vector2D): number {\n return Math.sqrt(distanceSquared(a, b));\n}\n\n/**\n * Create an AABB from a rectangle\n */\nexport function rectToAABB(rect: Rectangle): AABB {\n return {\n min: { x: rect.position.x, y: rect.position.y },\n max: { x: rect.position.x + rect.width, y: rect.position.y + rect.height },\n };\n}\n\n/**\n * Create an AABB from a circle\n */\nexport function circleToAABB(circle: Circle): AABB {\n return {\n min: {\n x: circle.center.x - circle.radius,\n y: circle.center.y - circle.radius,\n },\n max: {\n x: circle.center.x + circle.radius,\n y: circle.center.y + circle.radius,\n },\n };\n}\n\n/**\n * Check if two AABBs intersect\n */\nexport function aabbIntersect(a: AABB, b: AABB): boolean {\n // Exit with no intersection if separated along an axis\n if (a.max.x < b.min.x || a.min.x > b.max.x) return false;\n if (a.max.y < b.min.y || a.min.y > b.max.y) return false;\n\n // Overlapping on all axes means AABBs are intersecting\n return true;\n}\n\n/**\n * Calculate cell indices for a position in a spatial grid\n */\nexport function positionToCell(\n position: Vector2D,\n cellSize: number,\n): [number, number] {\n return [Math.floor(position.x / cellSize), Math.floor(position.y / cellSize)];\n}\n\n/**\n * Calculate a unique cell ID from grid coordinates\n * Uses a spatial hashing function to convert 2D coordinates to 1D\n */\nexport function cellToId(x: number, y: number): number {\n // Cantor pairing function - maps two non-negative integers to a unique non-negative integer\n return ((x + y) * (x + y + 1)) / 2 + y;\n}\n","import { Entity, Shape } from \"../types\";\n\n/**\n * Base class for collision detectors that implements common functionality\n */\nexport abstract class BaseCollisionDetector {\n /**\n * The entities to check collisions against\n */\n protected entities: Entity[];\n\n /**\n * Create a new collision detector\n * @param entities The entities to check collisions against\n */\n constructor(entities: Entity[]) {\n this.entities = entities;\n }\n\n /**\n * Get all entities that collide with the given shape\n * @param shape The shape to check collisions against\n * @returns Array of entity IDs that collide with the shape\n */\n abstract getCollisions(shape: Shape): (string | number)[];\n}\n","import { Circle, CollisionResult } from \"../../../types\";\nimport { distanceSquared } from \"../../../utils\";\n\n/**\n * Detects collision between two circles\n * @param circleA First circle\n * @param circleB Second circle\n * @returns Collision result with contact information\n */\nexport function circleCircleCollision(\n circleA: Circle,\n circleB: Circle,\n): CollisionResult {\n const distSquared = distanceSquared(circleA.center, circleB.center);\n\n const radiusSum = circleA.radius + circleB.radius;\n\n const colliding = distSquared <= radiusSum * radiusSum;\n\n return {\n colliding,\n };\n}\n","import { Circle, CollisionResult, Point } from \"../../../types\";\nimport { distanceSquared } from \"../../../utils\";\n\n/**\n * Detects collision between a circle and a point\n * @param circle Circle\n * @param point Point\n * @returns Collision result with contact information\n */\nexport function circlePointCollision(\n circle: Circle,\n point: Point,\n): CollisionResult {\n const distSquared = distanceSquared(circle.center, point.position);\n\n const colliding = distSquared <= circle.radius * circle.radius;\n\n return {\n colliding,\n };\n}\n","import { Circle, CollisionResult, Rectangle } from \"../../../types\";\nimport { distanceSquared } from \"../../../utils\";\n\n/**\n * Detects collision between a circle and a rectangle\n * @param circle Circle\n * @param rect Rectangle\n * @returns Collision result with contact information\n */\nexport function circleRectCollision(\n circle: Circle,\n rect: Rectangle,\n): CollisionResult {\n // Handle rotation if present\n if (rect.rotationDeg !== 0) {\n return circleRotatedRectCollision(circle, rect);\n }\n\n // Find the closest point on the rectangle to the circle center\n const closestX = Math.max(\n rect.position.x,\n Math.min(circle.center.x, rect.position.x + rect.width),\n );\n const closestY = Math.max(\n rect.position.y,\n Math.min(circle.center.y, rect.position.y + rect.height),\n );\n\n const distSquared = distanceSquared(circle.center, {\n x: closestX,\n y: closestY,\n });\n\n // Check if the circle is colliding with the rectangle\n const colliding = distSquared <= circle.radius * circle.radius;\n\n return {\n colliding,\n };\n}\n\n/**\n * Detects collision between a circle and a rotated rectangle\n * @param circle Circle\n * @param rect Rotated rectangle\n * @returns Collision result with contact information\n */\nfunction circleRotatedRectCollision(\n circle: Circle,\n rect: Rectangle,\n): CollisionResult {\n // Convert rotation from degrees to radians\n const rotationRad = (rect.rotationDeg * Math.PI) / 180;\n const cos = Math.cos(-rotationRad);\n const sin = Math.sin(-rotationRad);\n\n // Translate circle center to rectangle's local space (unrotated)\n const rectCenterX = rect.position.x + rect.width / 2;\n const rectCenterY = rect.position.y + rect.height / 2;\n\n // Vector from rectangle center to circle center\n const dx = circle.center.x - rectCenterX;\n const dy = circle.center.y - rectCenterY;\n\n // Rotate the vector to align with the rectangle's local axes\n const rotatedX = cos * dx - sin * dy;\n const rotatedY = sin * dx + cos * dy;\n\n // Create a circle in the rectangle's local space\n const localCircle: Circle = {\n type: \"circle\",\n center: {\n x: rotatedX + rectCenterX,\n y: rotatedY + rectCenterY,\n },\n radius: circle.radius,\n };\n\n // Create an unrotated rectangle\n const localRect: Rectangle = {\n type: \"rectangle\",\n position: rect.position,\n width: rect.width,\n height: rect.height,\n rotationDeg: 0,\n };\n\n // Check collision with the unrotated rectangle\n return circleRectCollision(localCircle, localRect);\n}\n","import { CollisionResult, Point, Rectangle } from \"../../../types\";\n\n/**\n * Detects collision between a rectangle and a point\n * @param rect Rectangle\n * @param point Point\n * @returns Collision result with contact information\n */\nexport function rectPointCollision(\n rect: Rectangle,\n point: Point,\n): CollisionResult {\n // Handle rotation if present\n if (rect.rotationDeg !== 0) {\n return rotatedRectPointCollision(rect, point);\n }\n\n // Check if the point is inside the rectangle\n const colliding =\n point.position.x >= rect.position.x &&\n point.position.x <= rect.position.x + rect.width &&\n point.position.y >= rect.position.y &&\n point.position.y <= rect.position.y + rect.height;\n\n return {\n colliding,\n };\n}\n\n/**\n * Detects collision between a rotated rectangle and a point\n * @param rect Rotated rectangle\n * @param point Point\n * @returns Collision result with contact information\n */\nfunction rotatedRectPointCollision(\n rect: Rectangle,\n point: Point,\n): CollisionResult {\n // Convert rotation from degrees to radians\n const rotationRad = (rect.rotationDeg * Math.PI) / 180;\n const cos = Math.cos(-rotationRad);\n const sin = Math.sin(-rotationRad);\n\n // Calculate rectangle center\n const rectCenterX = rect.position.x + rect.width / 2;\n const rectCenterY = rect.position.y + rect.height / 2;\n\n // Vector from rectangle center to point\n const dx = point.position.x - rectCenterX;\n const dy = point.position.y - rectCenterY;\n\n // Rotate the vector to align with the rectangle's local axes\n const rotatedX = cos * dx - sin * dy;\n const rotatedY = sin * dx + cos * dy;\n\n // Create a point in the rectangle's local space\n const localPoint: Point = {\n type: \"point\",\n position: {\n x: rotatedX + rectCenterX,\n y: rotatedY + rectCenterY,\n },\n };\n\n // Create an unrotated rectangle\n const localRect: Rectangle = {\n type: \"rectangle\",\n position: {\n x: rect.position.x,\n y: rect.position.y,\n },\n width: rect.width,\n height: rect.height,\n rotationDeg: 0,\n };\n\n // Check collision with the unrotated rectangle\n return rectPointCollision(localRect, localPoint);\n}\n","import { Rectangle, CollisionResult, Vector2D } from \"../../../types\";\nimport {\n subtract,\n normalize,\n dot,\n rectToAABB,\n aabbIntersect,\n} from \"../../../utils\";\n\n/**\n * Detect collision between two rectangles\n * This implementation handles rotated rectangles using the Separating Axis Theorem (SAT)\n */\nexport function rectRectCollision(\n rectA: Rectangle,\n rectB: Rectangle,\n): CollisionResult {\n // If both rectangles have zero rotation, use a simpler AABB check\n if (rectA.rotationDeg === 0 && rectB.rotationDeg === 0) {\n return aabbRectRectCollision(rectA, rectB);\n }\n\n // For rotated rectangles, use Separating Axis Theorem (SAT)\n return satRectRectCollision(rectA, rectB);\n}\n\n/**\n * Collision detection for axis-aligned (non-rotated) rectangles\n */\nfunction aabbRectRectCollision(\n rectA: Rectangle,\n rectB: Rectangle,\n): CollisionResult {\n return {\n colliding: aabbIntersect(rectToAABB(rectA), rectToAABB(rectB)),\n };\n}\n\n/**\n * Get the corners of a rotated rectangle\n */\nfunction getRectangleCorners(rect: Rectangle): Vector2D[] {\n const { position, width, height, rotationDeg } = rect;\n const halfWidth = width / 2;\n const halfHeight = height / 2;\n\n // Calculate center of the rectangle\n const center = {\n x: position.x + halfWidth,\n y: position.y + halfHeight,\n };\n\n // Convert rotation to radians\n const rotationRad = (rotationDeg * Math.PI) / 180;\n const cos = Math.cos(rotationRad);\n const sin = Math.sin(rotationRad);\n\n // Calculate corners relative to center\n const corners: Vector2D[] = [\n { x: -halfWidth, y: -halfHeight }, // Top-left\n { x: halfWidth, y: -halfHeight }, // Top-right\n { x: halfWidth, y: halfHeight }, // Bottom-right\n { x: -halfWidth, y: halfHeight }, // Bottom-left\n ];\n\n // Rotate and translate corners\n return corners.map((corner) => ({\n x: center.x + (corner.x * cos - corner.y * sin),\n y: center.y + (corner.x * sin + corner.y * cos),\n }));\n}\n\n/**\n * Get the axes to test for the SAT algorithm\n */\nfunction getAxes(cornersA: Vector2D[], cornersB: Vector2D[]): Vector2D[] {\n const axes: Vector2D[] = [];\n\n // Add the normals of each edge of the first rectangle\n for (let i = 0; i < cornersA.length; i++) {\n const p1 = cornersA[i];\n const p2 = cornersA[(i + 1) % cornersA.length];\n const edge = subtract(p2, p1);\n // The normal is perpendicular to the edge\n const normal = normalize({ x: -edge.y, y: edge.x });\n axes.push(normal);\n }\n\n // Add the normals of each edge of the second rectangle\n for (let i = 0; i < cornersB.length; i++) {\n const p1 = cornersB[i];\n const p2 = cornersB[(i + 1) % cornersB.length];\n const edge = subtract(p2, p1);\n // The normal is perpendicular to the edge\n const normal = normalize({ x: -edge.y, y: edge.x });\n axes.push(normal);\n }\n\n return axes;\n}\n\n/**\n * Project a shape onto an axis\n */\nfunction projectShapeOntoAxis(\n corners: Vector2D[],\n axis: Vector2D,\n): { min: number; max: number } {\n let min = dot(corners[0], axis);\n let max = min;\n\n for (let i = 1; i < corners.length; i++) {\n const projection = dot(corners[i], axis);\n if (projection < min) min = projection;\n if (projection > max) max = projection;\n }\n\n return { min, max };\n}\n\n/**\n * Collision detection for rotated rectangles using Separating Axis Theorem (SAT)\n */\nfunction satRectRectCollision(\n rectA: Rectangle,\n rectB: Rectangle,\n): CollisionResult {\n // Get corners of both rectangles\n const cornersA = getRectangleCorners(rectA);\n const cornersB = getRectangleCorners(rectB);\n\n // Get axes to test\n const axes = getAxes(cornersA, cornersB);\n\n // Test each axis\n for (const axis of axes) {\n const projectionA = projectShapeOntoAxis(cornersA, axis);\n const projectionB = projectShapeOntoAxis(cornersB, axis);\n\n // Check for separation\n if (\n projectionA.max < projectionB.min ||\n projectionB.max < projectionA.min\n ) {\n // Shapes are separated along this axis\n return { colliding: false };\n }\n }\n\n // If we get here, the shapes are colliding\n return { colliding: true };\n}\n","import { Circle, Point, Rectangle, Shape } from \"../../types\";\nimport { circleCircleCollision } from \"./circleCircle\";\nimport { circlePointCollision } from \"./circlePoint\";\nimport { circleRectCollision } from \"./circleRect\";\nimport { rectPointCollision } from \"./rectPoint\";\nimport { rectRectCollision } from \"./rectRect\";\n\n/**\n * Check if two entities are colliding\n * @param shapeA First shape\n * @param shapeB Second shape\n * @returns True if the shapes are colliding\n */\nexport function checkShapeCollision(shapeA: Shape, shapeB: Shape): boolean {\n const shapeAType = shapeA.type;\n const shapeBType = shapeB.type;\n\n // Circle vs Circle\n if (shapeAType === \"circle\" && shapeBType === \"circle\") {\n return circleCircleCollision(shapeA as Circle, shapeB as Circle).colliding;\n }\n\n if (shapeAType === \"circle\" && shapeBType === \"point\") {\n return circlePointCollision(shapeA as Circle, shapeB as Point).colliding;\n }\n if (shapeAType === \"point\" && shapeBType === \"circle\") {\n return circlePointCollision(shapeB as Circle, shapeA as Point).colliding;\n }\n\n if (shapeAType === \"circle\" && shapeBType === \"rectangle\") {\n return circleRectCollision(shapeA as Circle, shapeB as Rectangle).colliding;\n }\n if (shapeAType === \"rectangle\" && shapeBType === \"circle\") {\n return circleRectCollision(shapeB as Circle, shapeA as Rectangle).colliding;\n }\n\n if (shapeAType === \"rectangle\" && shapeBType === \"rectangle\") {\n return rectRectCollision(shapeA as Rectangle, shapeB as Rectangle)\n .colliding;\n }\n\n if (shapeAType === \"rectangle\" && shapeBType === \"point\") {\n return rectPointCollision(shapeA as Rectangle, shapeB as Point).colliding;\n }\n if (shapeAType === \"point\" && shapeBType === \"rectangle\") {\n return rectPointCollision(shapeB as Rectangle, shapeA as Point).colliding;\n }\n\n return false;\n}\n","import { Entity, Shape } from \"../types\";\nimport { BaseCollisionDetector } from \"./CollisionDetector\";\nimport { checkShapeCollision } from \"./shapeCollisions/checkShapeCollision\";\n\n/**\n * Collision detector that uses a brute force approach\n * Checks every entity against the given shape\n *\n * Best used when:\n * - You have a small number of entities\n * - You only need to check collisions occasionally\n * - You want the simplest implementation\n */\nexport function BruteForceCollisionDetector({\n entities,\n}: {\n entities: Entity[];\n}) {\n return new BruteForceCollisionDetectorImpl(entities);\n}\n\nclass BruteForceCollisionDetectorImpl extends BaseCollisionDetector {\n /**\n * Get all entities that collide with the given shape\n * @param shape The shape to check collisions against\n * @returns Array of entity IDs that collide with the shape\n */\n getCollisions(shape: Shape): (string | number)[] {\n const collisions: (string | number)[] = [];\n\n // Check each entity against the given shape\n for (const entity of this.entities) {\n // Check if the shapes collide\n if (checkShapeCollision(shape, entity.shape)) {\n collisions.push(entity.id);\n }\n }\n\n return collisions;\n }\n}\n","import { AABB, Circle, Entity, Point, Rectangle, Shape } from \"../types\";\nimport { BaseCollisionDetector } from \"./CollisionDetector\";\nimport { checkShapeCollision } from \"./shapeCollisions/checkShapeCollision\";\nimport { cellToId, circleToAABB, positionToCell, rectToAABB } from \"../utils\";\n\ntype CellId = number;\n\n/**\n * Configuration options for the spatial grid collision detector\n */\nexport interface SpatialGridConfig {\n /** Size of each grid cell */\n cellSize: number;\n}\n\n/**\n * Collision detector that uses spatial partitioning for efficient collision detection\n *\n * Best used when:\n * - You have a large number of entities\n * - Entities are distributed across the space\n * - You need to check collisions frequently\n */\nexport function SpatialGridCollisionDetector({\n entities,\n cellSize = 64,\n}: {\n entities: Entity[];\n cellSize?: number;\n}) {\n return new SpatialGridCollisionDetectorImpl(entities, { cellSize });\n}\n\nclass SpatialGridCollisionDetectorImpl extends BaseCollisionDetector {\n /** The spatial hash grid for quick lookups */\n private grid: Map<CellId, Entity[]>;\n /** Configuration for the spatial grid */\n private config: SpatialGridConfig;\n\n /**\n * Create a new spatial grid collision detector\n */\n constructor(entities: Entity[], config: SpatialGridConfig) {\n super(entities);\n this.config = config;\n this.grid = new Map();\n\n // Initialize the grid with entities\n this.rebuildGrid();\n }\n\n /**\n * Get all entities that collide with the given shape\n */\n getCollisions(shape: Shape): (string | number)[] {\n // Get the AABB for the shape\n const aabb = this.getAABBForShape(shape);\n\n // Get all cells that the AABB overlaps\n const cells = this.getCellsForAABB(aabb);\n\n // Get all entities in those cells\n const potentialCollisions = new Set<Entity>();\n\n for (const cellId of cells) {\n const entitiesInCell = this.grid.get(cellId);\n if (entitiesInCell) {\n for (const entity of entitiesInCell) {\n potentialCollisions.add(entity);\n }\n }\n }\n\n // Check for actual collisions\n const collisions: (string | number)[] = [];\n\n for (const entity of potentialCollisions) {\n if (checkShapeCollision(shape, entity.shape)) {\n collisions.push(entity.id);\n }\n }\n\n return collisions;\n }\n\n /**\n * Rebuild the spatial grid with the current entities\n */\n rebuildGrid(): void {\n // Clear the grid\n this.grid.clear();\n\n // Add all entities to the grid\n for (const entity of this.entities) {\n this.insertEntityIntoGrid(entity);\n }\n }\n\n /**\n * Insert an entity into the spatial grid\n */\n private insertEntityIntoGrid(entity: Entity): void {\n // Get the AABB for the entity\n const aabb = this.getAABB(entity);\n\n // Get all cells that the AABB overlaps\n const cells = this.getCellsForAABB(aabb);\n\n // Add the entity to each cell\n for (const cellId of cells) {\n if (!this.grid.has(cellId)) {\n this.grid.set(cellId, []);\n }\n\n this.grid.get(cellId)!.push(entity);\n }\n }\n\n /**\n * Get all cells that an AABB overlaps\n */\n private getCellsForAABB(aabb: AABB): CellId[] {\n const { cellSize } = this.config;\n\n // Calculate the min and max cell coordinates\n const [minCellX, minCellY] = positionToCell(aabb.min, cellSize);\n const [maxCellX, maxCellY] = positionToCell(aabb.max, cellSize);\n\n // Get all cells in the range\n const cells: CellId[] = new Array(\n (maxCellX - minCellX + 1) * (maxCellY - minCellY + 1),\n );\n let index = 0;\n\n for (let x = minCellX; x <= maxCellX; x++) {\n for (let y = minCellY; y <= maxCellY; y++) {\n cells[index++] = cellToId(x, y);\n }\n }\n\n return cells;\n }\n\n /**\n * Get the AABB for an entity\n */\n private getAABB(entity: Entity): AABB {\n return this.getAABBForShape(entity.shape);\n }\n\n /**\n * Get the AABB for a shape\n */\n private getAABBForShape(shape: Shape): AABB {\n const shapeType = shape.type;\n\n if (shapeType === \"circle\") {\n return circleToAABB(shape as Circle);\n } else if (shapeType === \"rectangle\") {\n return rectToAABB(shape as Rectangle);\n } else if (shapeType === \"point\") {\n // For a point, create a tiny AABB\n return {\n min: { x: (shape as Point).position.x, y: (shape as Point).position.y },\n max: { x: (shape as Point).position.x, y: (shape as Point).position.y },\n };\n }\n\n throw new Error(`Unsupported shape type: ${shapeType}`);\n }\n}\n","import { Circle, Point, Rectangle, Shape } from \"../types\";\nimport { ShapeStyle, RendererOptions, RenderableShape } from \"./types\";\n\n/**\n * Apply style settings to the canvas context\n */\nexport function applyStyle(ctx: CanvasRenderingContext2D, style: ShapeStyle) {\n // Save the current context state\n ctx.save();\n\n // Apply fill and stroke styles\n if (style.fillColor) {\n ctx.fillStyle = style.fillColor;\n }\n\n if (style.strokeColor) {\n ctx.strokeStyle = style.strokeColor;\n }\n\n if (style.strokeWidth !== undefined) {\n ctx.lineWidth = style.strokeWidth;\n }\n\n if (style.alpha !== undefined) {\n ctx.globalAlpha = style.alpha;\n }\n\n // Apply shadow settings if provided\n if (style.shadowBlur !== undefined) {\n ctx.shadowBlur = style.shadowBlur;\n }\n\n if (style.shadowColor) {\n ctx.shadowColor = style.shadowColor;\n }\n\n if (style.shadowOffsetX !== undefined) {\n ctx.shadowOffsetX = style.shadowOffsetX;\n }\n\n if (style.shadowOffsetY !== undefined) {\n ctx.shadowOffsetY = style.shadowOffsetY;\n }\n}\n\n/**\n * Restore the canvas context to its previous state\n */\nexport function restoreContext(ctx: CanvasRenderingContext2D) {\n ctx.restore();\n}\n\n/**\n * Render a circle shape\n */\nexport function renderCircle(\n ctx: CanvasRenderingContext2D,\n circle: Circle,\n style: ShapeStyle,\n) {\n applyStyle(ctx, style);\n\n ctx.beginPath();\n ctx.arc(circle.center.x, circle.center.y, circle.radius, 0, Math.PI * 2);\n\n if (style.fillColor) {\n ctx.fill();\n }\n\n if (style.strokeColor && style.strokeWidth && style.strokeWidth > 0) {\n ctx.stroke();\n }\n\n restoreContext(ctx);\n}\n\n/**\n * Render a point shape\n */\nexport function renderPoint(\n ctx: CanvasRenderingContext2D,\n point: Point,\n style: ShapeStyle,\n) {\n // Points are rendered as small circles\n const pointSize = style.strokeWidth || 4;\n\n applyStyle(ctx, style);\n\n ctx.beginPath();\n ctx.arc(point.position.x, point.position.y, pointSize / 2, 0, Math.PI * 2);\n\n if (style.fillColor) {\n ctx.fill();\n }\n\n if (style.strokeColor && style.strokeWidth && style.strokeWidth > 0) {\n ctx.stroke();\n }\n\n restoreContext(ctx);\n}\n\n/**\n * Render a rectangle shape\n */\nexport function renderRectangle(\n ctx: CanvasRenderingContext2D,\n rectangle: Rectangle,\n style: ShapeStyle,\n) {\n applyStyle(ctx, style);\n\n // Save the current transformation matrix\n ctx.save();\n\n // Translate to the rectangle's position\n ctx.translate(rectangle.position.x, rectangle.position.y);\n\n // Rotate if needed\n if (rectangle.rotationDeg !== 0) {\n const rotationRad = (rectangle.rotationDeg * Math.PI) / 180;\n ctx.rotate(rotationRad);\n }\n\n // Draw the rectangle centered at the origin\n const halfWidth = rectangle.width / 2;\n const halfHeight = rectangle.height / 2;\n\n if (style.fillColor) {\n ctx.fillRect(-halfWidth, -halfHeight, rectangle.width, rectangle.height);\n }\n\n if (style.strokeColor && style.strokeWidth && style.strokeWidth > 0) {\n ctx.strokeRect(-halfWidth, -halfHeight, rectangle.width, rectangle.height);\n }\n\n // Restore the transformation matrix\n ctx.restore();\n\n // Restore the style context\n restoreContext(ctx);\n}\n\n/**\n * Render any shape based on its type\n */\nexport function renderShape(\n ctx: CanvasRenderingContext2D,\n shape: Shape,\n style: ShapeStyle,\n) {\n switch (shape.type) {\n case \"circle\":\n renderCircle(ctx, shape, style);\n break;\n case \"rectangle\":\n renderRectangle(ctx, shape, style);\n break;\n case \"point\":\n renderPoint(ctx, shape, style);\n break;\n default:\n // This should never happen if all shape types are handled\n console.warn(\"Unknown shape type encountered\");\n break;\n }\n}\n\n/**\n * Main renderer function to render multiple shapes\n */\nexport function renderShapes(\n ctx: CanvasRenderingContext2D,\n shapes: RenderableShape[],\n options: RendererOptions,\n) {\n // Render each shape\n for (const { shape, style } of shapes) {\n // Merge with default style if provided\n const mergedStyle = {\n ...options.defaultStyle,\n ...style,\n };\n\n renderShape(ctx, shape, mergedStyle);\n }\n}\n"],"mappings":"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","names":["index_exports","__export","BaseCollisionDetector","BruteForceCollisionDetector","GameLoop","Input","Renderer","SpatialGridCollisionDetector","VERSION","aabbIntersect","add","applyStyle","cellToId","checkShapeCollision","circleToAABB","cross","distance","distanceSquared","dot","length","lengthSquared","normalize","positionToCell","rectToAABB","renderCircle","renderPoint","renderRectangle","renderShape","renderShapes","restoreContext","scale","subtract","vec2","__toCommonJS","vec2","x","y","add","a","b","subtract","scale","v","scalar","dot","cross","lengthSquared","length","normalize","len","distanceSquared","dx","dy","distance","rectToAABB","rect","circleToAABB","circle","aabbIntersect","positionToCell","position","cellSize","cellToId","BaseCollisionDetector","entities","circleCircleCollision","circleA","circleB","distSquared","distanceSquared","radiusSum","circlePointCollision","circle","point","distanceSquared","circleRectCollision","circle","rect","circleRotatedRectCollision","closestX","closestY","distanceSquared","rotationRad","cos","sin","rectCenterX","rectCenterY","dx","dy","rotatedX","rotatedY","localCircle","localRect","rectPointCollision","rect","point","rotatedRectPointCollision","rotationRad","cos","sin","rectCenterX","rectCenterY","dx","dy","rotatedX","rotatedY","localPoint","localRect","rectRectCollision","rectA","rectB","aabbRectRectCollision","satRectRectCollision","aabbIntersect","rectToAABB","getRectangleCorners","rect","position","width","height","rotationDeg","halfWidth","halfHeight","center","rotationRad","cos","sin","corner","getAxes","cornersA","cornersB","axes","i","p1","p2","edge","subtract","normal","normalize","projectShapeOntoAxis","corners","axis","min","dot","max","projection","projectionA","projectionB","checkShapeCollision","shapeA","shapeB","shapeAType","shapeBType","circleCircleCollision","circlePointCollision","circleRectCollision","rectRectCollision","rectPointCollision","BruteForceCollisionDetector","entities","BruteForceCollisionDetectorImpl","BaseCollisionDetector","shape","collisions","entity","checkShapeCollision","SpatialGridCollisionDetector","entities","cellSize","SpatialGridCollisionDetectorImpl","BaseCollisionDetector","config","shape","aabb","cells","potentialCollisions","cellId","entitiesInCell","entity","collisions","checkShapeCollision","minCellX","minCellY","positionToCell","maxCellX","maxCellY","index","x","y","cellToId","shapeType","circleToAABB","rectToAABB","applyStyle","ctx","style","restoreContext","renderCircle","circle","renderPoint","point","pointSize","renderRectangle","rectangle","rotationRad","halfWidth","halfHeight","renderShape","shape","renderShapes","shapes","options","mergedStyle","VERSION","Renderer","GameLoop","Input"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,2 @@
1
+ function L(t,o){return{x:t,y:o}}function N(t,o){return{x:t.x+o.x,y:t.y+o.y}}function y(t,o){return{x:t.x-o.x,y:t.y-o.y}}function $(t,o){return{x:t.x*o,y:t.y*o}}function R(t,o){return t.x*o.x+t.y*o.y}function J(t,o){return t.x*o.y-t.y*o.x}function T(t){return t.x*t.x+t.y*t.y}function W(t){return Math.sqrt(T(t))}function S(t){let o=W(t);return o<1e-10?{x:0,y:0}:{x:t.x/o,y:t.y/o}}function f(t,o){let e=o.x-t.x,n=o.y-t.y;return e*e+n*n}function K(t,o){return Math.sqrt(f(t,o))}function h(t){return{min:{x:t.position.x,y:t.position.y},max:{x:t.position.x+t.width,y:t.position.y+t.height}}}function V(t){return{min:{x:t.center.x-t.radius,y:t.center.y-t.radius},max:{x:t.center.x+t.radius,y:t.center.y+t.radius}}}function k(t,o){return!(t.max.x<o.min.x||t.min.x>o.max.x||t.max.y<o.min.y||t.min.y>o.max.y)}function D(t,o){return[Math.floor(t.x/o),Math.floor(t.y/o)]}function I(t,o){return(t+o)*(t+o+1)/2+o}var p=class{constructor(o){this.entities=o}};function M(t,o){let e=f(t.center,o.center),n=t.radius+o.radius;return{colliding:e<=n*n}}function b(t,o){return{colliding:f(t.center,o.position)<=t.radius*t.radius}}function m(t,o){if(o.rotationDeg!==0)return O(t,o);let e=Math.max(o.position.x,Math.min(t.center.x,o.position.x+o.width)),n=Math.max(o.position.y,Math.min(t.center.y,o.position.y+o.height));return{colliding:f(t.center,{x:e,y:n})<=t.radius*t.radius}}function O(t,o){let e=o.rotationDeg*Math.PI/180,n=Math.cos(-e),i=Math.sin(-e),r=o.position.x+o.width/2,s=o.position.y+o.height/2,l=t.center.x-r,a=t.center.y-s,c=n*l-i*a,d=i*l+n*a,g={type:"circle",center:{x:c+r,y:d+s},radius:t.radius},u={type:"rectangle",position:o.position,width:o.width,height:o.height,rotationDeg:0};return m(g,u)}function x(t,o){return t.rotationDeg!==0?X(t,o):{colliding:o.position.x>=t.position.x&&o.position.x<=t.position.x+t.width&&o.position.y>=t.position.y&&o.position.y<=t.position.y+t.height}}function X(t,o){let e=t.rotationDeg*Math.PI/180,n=Math.cos(-e),i=Math.sin(-e),r=t.position.x+t.width/2,s=t.position.y+t.height/2,l=o.position.x-r,a=o.position.y-s,c=n*l-i*a,d=i*l+n*a,g={type:"point",position:{x:c+r,y:d+s}},u={type:"rectangle",position:{x:t.position.x,y:t.position.y},width:t.width,height:t.height,rotationDeg:0};return x(u,g)}function q(t,o){return t.rotationDeg===0&&o.rotationDeg===0?Y(t,o):F(t,o)}function Y(t,o){return{colliding:k(h(t),h(o))}}function E(t){let{position:o,width:e,height:n,rotationDeg:i}=t,r=e/2,s=n/2,l={x:o.x+r,y:o.y+s},a=i*Math.PI/180,c=Math.cos(a),d=Math.sin(a);return[{x:-r,y:-s},{x:r,y:-s},{x:r,y:s},{x:-r,y:s}].map(u=>({x:l.x+(u.x*c-u.y*d),y:l.y+(u.x*d+u.y*c)}))}function G(t,o){let e=[];for(let n=0;n<t.length;n++){let i=t[n],r=t[(n+1)%t.length],s=y(r,i),l=S({x:-s.y,y:s.x});e.push(l)}for(let n=0;n<o.length;n++){let i=o[n],r=o[(n+1)%o.length],s=y(r,i),l=S({x:-s.y,y:s.x});e.push(l)}return e}function v(t,o){let e=R(t[0],o),n=e;for(let i=1;i<t.length;i++){let r=R(t[i],o);r<e&&(e=r),r>n&&(n=r)}return{min:e,max:n}}function F(t,o){let e=E(t),n=E(o),i=G(e,n);for(let r of i){let s=v(e,r),l=v(n,r);if(s.max<l.min||l.max<s.min)return{colliding:!1}}return{colliding:!0}}function C(t,o){let e=t.type,n=o.type;return e==="circle"&&n==="circle"?M(t,o).colliding:e==="circle"&&n==="point"?b(t,o).colliding:e==="point"&&n==="circle"?b(o,t).colliding:e==="circle"&&n==="rectangle"?m(t,o).colliding:e==="rectangle"&&n==="circle"?m(o,t).colliding:e==="rectangle"&&n==="rectangle"?q(t,o).colliding:e==="rectangle"&&n==="point"?x(t,o).colliding:e==="point"&&n==="rectangle"?x(o,t).colliding:!1}function mt({entities:t}){return new w(t)}var w=class extends p{getCollisions(o){let e=[];for(let n of this.entities)C(o,n.shape)&&e.push(n.id);return e}};function St({entities:t,cellSize:o=64}){return new B(t,{cellSize:o})}var B=class extends p{constructor(o,e){super(o),this.config=e,this.grid=new Map,this.rebuildGrid()}getCollisions(o){let e=this.getAABBForShape(o),n=this.getCellsForAABB(e),i=new Set;for(let s of n){let l=this.grid.get(s);if(l)for(let a of l)i.add(a)}let r=[];for(let s of i)C(o,s.shape)&&r.push(s.id);return r}rebuildGrid(){this.grid.clear();for(let o of this.entities)this.insertEntityIntoGrid(o)}insertEntityIntoGrid(o){let e=this.getAABB(o),n=this.getCellsForAABB(e);for(let i of n)this.grid.has(i)||this.grid.set(i,[]),this.grid.get(i).push(o)}getCellsForAABB(o){let{cellSize:e}=this.config,[n,i]=D(o.min,e),[r,s]=D(o.max,e),l=new Array((r-n+1)*(s-i+1)),a=0;for(let c=n;c<=r;c++)for(let d=i;d<=s;d++)l[a++]=I(c,d);return l}getAABB(o){return this.getAABBForShape(o.shape)}getAABBForShape(o){let e=o.type;if(e==="circle")return V(o);if(e==="rectangle")return h(o);if(e==="point")return{min:{x:o.position.x,y:o.position.y},max:{x:o.position.x,y:o.position.y}};throw new Error(`Unsupported shape type: ${e}`)}};function A(t,o){t.save(),o.fillColor&&(t.fillStyle=o.fillColor),o.strokeColor&&(t.strokeStyle=o.strokeColor),o.strokeWidth!==void 0&&(t.lineWidth=o.strokeWidth),o.alpha!==void 0&&(t.globalAlpha=o.alpha),o.shadowBlur!==void 0&&(t.shadowBlur=o.shadowBlur),o.shadowColor&&(t.shadowColor=o.shadowColor),o.shadowOffsetX!==void 0&&(t.shadowOffsetX=o.shadowOffsetX),o.shadowOffsetY!==void 0&&(t.shadowOffsetY=o.shadowOffsetY)}function P(t){t.restore()}function z(t,o,e){A(t,e),t.beginPath(),t.arc(o.center.x,o.center.y,o.radius,0,Math.PI*2),e.fillColor&&t.fill(),e.strokeColor&&e.strokeWidth&&e.strokeWidth>0&&t.stroke(),P(t)}function j(t,o,e){let n=e.strokeWidth||4;A(t,e),t.beginPath(),t.arc(o.position.x,o.position.y,n/2,0,Math.PI*2),e.fillColor&&t.fill(),e.strokeColor&&e.strokeWidth&&e.strokeWidth>0&&t.stroke(),P(t)}function H(t,o,e){if(A(t,e),t.save(),t.translate(o.position.x,o.position.y),o.rotationDeg!==0){let r=o.rotationDeg*Math.PI/180;t.rotate(r)}let n=o.width/2,i=o.height/2;e.fillColor&&t.fillRect(-n,-i,o.width,o.height),e.strokeColor&&e.strokeWidth&&e.strokeWidth>0&&t.strokeRect(-n,-i,o.width,o.height),t.restore(),P(t)}function U(t,o,e){switch(o.type){case"circle":z(t,o,e);break;case"rectangle":H(t,o,e);break;case"point":j(t,o,e);break;default:console.warn("Unknown shape type encountered");break}}function Vt(t,o,e){for(let{shape:n,style:i}of o){let r={...e.defaultStyle,...i};U(t,n,r)}}var It="0.0.1",Mt={notImplemented:!1,info:"Basic rendering capabilities are now available"},Et={notImplemented:!0,info:"Game loop management will be added in a future version"},vt={notImplemented:!0,info:"Input handling will be added in a future version"};export{p as BaseCollisionDetector,mt as BruteForceCollisionDetector,Et as GameLoop,vt as Input,Mt as Renderer,St as SpatialGridCollisionDetector,It as VERSION,k as aabbIntersect,N as add,A as applyStyle,I as cellToId,C as checkShapeCollision,V as circleToAABB,J as cross,K as distance,f as distanceSquared,R as dot,W as length,T as lengthSquared,S as normalize,D as positionToCell,h as rectToAABB,z as renderCircle,j as renderPoint,H as renderRectangle,U as renderShape,Vt as renderShapes,P as restoreContext,$ as scale,y as subtract,L as vec2};
2
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils.ts","../src/collision/CollisionDetector.ts","../src/collision/shapeCollisions/circleCircle/index.ts","../src/collision/shapeCollisions/circlePoint/index.ts","../src/collision/shapeCollisions/circleRect/index.ts","../src/collision/shapeCollisions/rectPoint/index.ts","../src/collision/shapeCollisions/rectRect/index.ts","../src/collision/shapeCollisions/checkShapeCollision.ts","../src/collision/BruteForceCollisionDetector.ts","../src/collision/SpatialGridCollisionDetector.ts","../src/render/index.ts","../src/index.ts"],"sourcesContent":["import { Vector2D, AABB, Circle, Rectangle } from \"./types\";\n\n/**\n * Create a new vector\n */\nexport function vec2(x: number, y: number): Vector2D {\n return { x, y };\n}\n\n/**\n * Vector addition\n */\nexport function add(a: Vector2D, b: Vector2D): Vector2D {\n return { x: a.x + b.x, y: a.y + b.y };\n}\n\n/**\n * Vector subtraction\n */\nexport function subtract(a: Vector2D, b: Vector2D): Vector2D {\n return { x: a.x - b.x, y: a.y - b.y };\n}\n\n/**\n * Vector scaling\n */\nexport function scale(v: Vector2D, scalar: number): Vector2D {\n return { x: v.x * scalar, y: v.y * scalar };\n}\n\n/**\n * Dot product of two vectors\n */\nexport function dot(a: Vector2D, b: Vector2D): number {\n return a.x * b.x + a.y * b.y;\n}\n\n/**\n * Cross product magnitude of two 2D vectors\n */\nexport function cross(a: Vector2D, b: Vector2D): number {\n return a.x * b.y - a.y * b.x;\n}\n\n/**\n * Get squared length of a vector (avoids sqrt for performance)\n */\nexport function lengthSquared(v: Vector2D): number {\n return v.x * v.x + v.y * v.y;\n}\n\n/**\n * Get vector length\n */\nexport function length(v: Vector2D): number {\n return Math.sqrt(lengthSquared(v));\n}\n\n/**\n * Normalize a vector (make it unit length)\n */\nexport function normalize(v: Vector2D): Vector2D {\n const len = length(v);\n // Avoid division by zero\n if (len < 1e-10) return { x: 0, y: 0 };\n return { x: v.x / len, y: v.y / len };\n}\n\n/**\n * Distance squared between two points (avoids sqrt for performance)\n */\nexport function distanceSquared(a: Vector2D, b: Vector2D): number {\n const dx = b.x - a.x;\n const dy = b.y - a.y;\n return dx * dx + dy * dy;\n}\n\n/**\n * Distance between two points\n */\nexport function distance(a: Vector2D, b: Vector2D): number {\n return Math.sqrt(distanceSquared(a, b));\n}\n\n/**\n * Create an AABB from a rectangle\n */\nexport function rectToAABB(rect: Rectangle): AABB {\n return {\n min: { x: rect.position.x, y: rect.position.y },\n max: { x: rect.position.x + rect.width, y: rect.position.y + rect.height },\n };\n}\n\n/**\n * Create an AABB from a circle\n */\nexport function circleToAABB(circle: Circle): AABB {\n return {\n min: {\n x: circle.center.x - circle.radius,\n y: circle.center.y - circle.radius,\n },\n max: {\n x: circle.center.x + circle.radius,\n y: circle.center.y + circle.radius,\n },\n };\n}\n\n/**\n * Check if two AABBs intersect\n */\nexport function aabbIntersect(a: AABB, b: AABB): boolean {\n // Exit with no intersection if separated along an axis\n if (a.max.x < b.min.x || a.min.x > b.max.x) return false;\n if (a.max.y < b.min.y || a.min.y > b.max.y) return false;\n\n // Overlapping on all axes means AABBs are intersecting\n return true;\n}\n\n/**\n * Calculate cell indices for a position in a spatial grid\n */\nexport function positionToCell(\n position: Vector2D,\n cellSize: number,\n): [number, number] {\n return [Math.floor(position.x / cellSize), Math.floor(position.y / cellSize)];\n}\n\n/**\n * Calculate a unique cell ID from grid coordinates\n * Uses a spatial hashing function to convert 2D coordinates to 1D\n */\nexport function cellToId(x: number, y: number): number {\n // Cantor pairing function - maps two non-negative integers to a unique non-negative integer\n return ((x + y) * (x + y + 1)) / 2 + y;\n}\n","import { Entity, Shape } from \"../types\";\n\n/**\n * Base class for collision detectors that implements common functionality\n */\nexport abstract class BaseCollisionDetector {\n /**\n * The entities to check collisions against\n */\n protected entities: Entity[];\n\n /**\n * Create a new collision detector\n * @param entities The entities to check collisions against\n */\n constructor(entities: Entity[]) {\n this.entities = entities;\n }\n\n /**\n * Get all entities that collide with the given shape\n * @param shape The shape to check collisions against\n * @returns Array of entity IDs that collide with the shape\n */\n abstract getCollisions(shape: Shape): (string | number)[];\n}\n","import { Circle, CollisionResult } from \"../../../types\";\nimport { distanceSquared } from \"../../../utils\";\n\n/**\n * Detects collision between two circles\n * @param circleA First circle\n * @param circleB Second circle\n * @returns Collision result with contact information\n */\nexport function circleCircleCollision(\n circleA: Circle,\n circleB: Circle,\n): CollisionResult {\n const distSquared = distanceSquared(circleA.center, circleB.center);\n\n const radiusSum = circleA.radius + circleB.radius;\n\n const colliding = distSquared <= radiusSum * radiusSum;\n\n return {\n colliding,\n };\n}\n","import { Circle, CollisionResult, Point } from \"../../../types\";\nimport { distanceSquared } from \"../../../utils\";\n\n/**\n * Detects collision between a circle and a point\n * @param circle Circle\n * @param point Point\n * @returns Collision result with contact information\n */\nexport function circlePointCollision(\n circle: Circle,\n point: Point,\n): CollisionResult {\n const distSquared = distanceSquared(circle.center, point.position);\n\n const colliding = distSquared <= circle.radius * circle.radius;\n\n return {\n colliding,\n };\n}\n","import { Circle, CollisionResult, Rectangle } from \"../../../types\";\nimport { distanceSquared } from \"../../../utils\";\n\n/**\n * Detects collision between a circle and a rectangle\n * @param circle Circle\n * @param rect Rectangle\n * @returns Collision result with contact information\n */\nexport function circleRectCollision(\n circle: Circle,\n rect: Rectangle,\n): CollisionResult {\n // Handle rotation if present\n if (rect.rotationDeg !== 0) {\n return circleRotatedRectCollision(circle, rect);\n }\n\n // Find the closest point on the rectangle to the circle center\n const closestX = Math.max(\n rect.position.x,\n Math.min(circle.center.x, rect.position.x + rect.width),\n );\n const closestY = Math.max(\n rect.position.y,\n Math.min(circle.center.y, rect.position.y + rect.height),\n );\n\n const distSquared = distanceSquared(circle.center, {\n x: closestX,\n y: closestY,\n });\n\n // Check if the circle is colliding with the rectangle\n const colliding = distSquared <= circle.radius * circle.radius;\n\n return {\n colliding,\n };\n}\n\n/**\n * Detects collision between a circle and a rotated rectangle\n * @param circle Circle\n * @param rect Rotated rectangle\n * @returns Collision result with contact information\n */\nfunction circleRotatedRectCollision(\n circle: Circle,\n rect: Rectangle,\n): CollisionResult {\n // Convert rotation from degrees to radians\n const rotationRad = (rect.rotationDeg * Math.PI) / 180;\n const cos = Math.cos(-rotationRad);\n const sin = Math.sin(-rotationRad);\n\n // Translate circle center to rectangle's local space (unrotated)\n const rectCenterX = rect.position.x + rect.width / 2;\n const rectCenterY = rect.position.y + rect.height / 2;\n\n // Vector from rectangle center to circle center\n const dx = circle.center.x - rectCenterX;\n const dy = circle.center.y - rectCenterY;\n\n // Rotate the vector to align with the rectangle's local axes\n const rotatedX = cos * dx - sin * dy;\n const rotatedY = sin * dx + cos * dy;\n\n // Create a circle in the rectangle's local space\n const localCircle: Circle = {\n type: \"circle\",\n center: {\n x: rotatedX + rectCenterX,\n y: rotatedY + rectCenterY,\n },\n radius: circle.radius,\n };\n\n // Create an unrotated rectangle\n const localRect: Rectangle = {\n type: \"rectangle\",\n position: rect.position,\n width: rect.width,\n height: rect.height,\n rotationDeg: 0,\n };\n\n // Check collision with the unrotated rectangle\n return circleRectCollision(localCircle, localRect);\n}\n","import { CollisionResult, Point, Rectangle } from \"../../../types\";\n\n/**\n * Detects collision between a rectangle and a point\n * @param rect Rectangle\n * @param point Point\n * @returns Collision result with contact information\n */\nexport function rectPointCollision(\n rect: Rectangle,\n point: Point,\n): CollisionResult {\n // Handle rotation if present\n if (rect.rotationDeg !== 0) {\n return rotatedRectPointCollision(rect, point);\n }\n\n // Check if the point is inside the rectangle\n const colliding =\n point.position.x >= rect.position.x &&\n point.position.x <= rect.position.x + rect.width &&\n point.position.y >= rect.position.y &&\n point.position.y <= rect.position.y + rect.height;\n\n return {\n colliding,\n };\n}\n\n/**\n * Detects collision between a rotated rectangle and a point\n * @param rect Rotated rectangle\n * @param point Point\n * @returns Collision result with contact information\n */\nfunction rotatedRectPointCollision(\n rect: Rectangle,\n point: Point,\n): CollisionResult {\n // Convert rotation from degrees to radians\n const rotationRad = (rect.rotationDeg * Math.PI) / 180;\n const cos = Math.cos(-rotationRad);\n const sin = Math.sin(-rotationRad);\n\n // Calculate rectangle center\n const rectCenterX = rect.position.x + rect.width / 2;\n const rectCenterY = rect.position.y + rect.height / 2;\n\n // Vector from rectangle center to point\n const dx = point.position.x - rectCenterX;\n const dy = point.position.y - rectCenterY;\n\n // Rotate the vector to align with the rectangle's local axes\n const rotatedX = cos * dx - sin * dy;\n const rotatedY = sin * dx + cos * dy;\n\n // Create a point in the rectangle's local space\n const localPoint: Point = {\n type: \"point\",\n position: {\n x: rotatedX + rectCenterX,\n y: rotatedY + rectCenterY,\n },\n };\n\n // Create an unrotated rectangle\n const localRect: Rectangle = {\n type: \"rectangle\",\n position: {\n x: rect.position.x,\n y: rect.position.y,\n },\n width: rect.width,\n height: rect.height,\n rotationDeg: 0,\n };\n\n // Check collision with the unrotated rectangle\n return rectPointCollision(localRect, localPoint);\n}\n","import { Rectangle, CollisionResult, Vector2D } from \"../../../types\";\nimport {\n subtract,\n normalize,\n dot,\n rectToAABB,\n aabbIntersect,\n} from \"../../../utils\";\n\n/**\n * Detect collision between two rectangles\n * This implementation handles rotated rectangles using the Separating Axis Theorem (SAT)\n */\nexport function rectRectCollision(\n rectA: Rectangle,\n rectB: Rectangle,\n): CollisionResult {\n // If both rectangles have zero rotation, use a simpler AABB check\n if (rectA.rotationDeg === 0 && rectB.rotationDeg === 0) {\n return aabbRectRectCollision(rectA, rectB);\n }\n\n // For rotated rectangles, use Separating Axis Theorem (SAT)\n return satRectRectCollision(rectA, rectB);\n}\n\n/**\n * Collision detection for axis-aligned (non-rotated) rectangles\n */\nfunction aabbRectRectCollision(\n rectA: Rectangle,\n rectB: Rectangle,\n): CollisionResult {\n return {\n colliding: aabbIntersect(rectToAABB(rectA), rectToAABB(rectB)),\n };\n}\n\n/**\n * Get the corners of a rotated rectangle\n */\nfunction getRectangleCorners(rect: Rectangle): Vector2D[] {\n const { position, width, height, rotationDeg } = rect;\n const halfWidth = width / 2;\n const halfHeight = height / 2;\n\n // Calculate center of the rectangle\n const center = {\n x: position.x + halfWidth,\n y: position.y + halfHeight,\n };\n\n // Convert rotation to radians\n const rotationRad = (rotationDeg * Math.PI) / 180;\n const cos = Math.cos(rotationRad);\n const sin = Math.sin(rotationRad);\n\n // Calculate corners relative to center\n const corners: Vector2D[] = [\n { x: -halfWidth, y: -halfHeight }, // Top-left\n { x: halfWidth, y: -halfHeight }, // Top-right\n { x: halfWidth, y: halfHeight }, // Bottom-right\n { x: -halfWidth, y: halfHeight }, // Bottom-left\n ];\n\n // Rotate and translate corners\n return corners.map((corner) => ({\n x: center.x + (corner.x * cos - corner.y * sin),\n y: center.y + (corner.x * sin + corner.y * cos),\n }));\n}\n\n/**\n * Get the axes to test for the SAT algorithm\n */\nfunction getAxes(cornersA: Vector2D[], cornersB: Vector2D[]): Vector2D[] {\n const axes: Vector2D[] = [];\n\n // Add the normals of each edge of the first rectangle\n for (let i = 0; i < cornersA.length; i++) {\n const p1 = cornersA[i];\n const p2 = cornersA[(i + 1) % cornersA.length];\n const edge = subtract(p2, p1);\n // The normal is perpendicular to the edge\n const normal = normalize({ x: -edge.y, y: edge.x });\n axes.push(normal);\n }\n\n // Add the normals of each edge of the second rectangle\n for (let i = 0; i < cornersB.length; i++) {\n const p1 = cornersB[i];\n const p2 = cornersB[(i + 1) % cornersB.length];\n const edge = subtract(p2, p1);\n // The normal is perpendicular to the edge\n const normal = normalize({ x: -edge.y, y: edge.x });\n axes.push(normal);\n }\n\n return axes;\n}\n\n/**\n * Project a shape onto an axis\n */\nfunction projectShapeOntoAxis(\n corners: Vector2D[],\n axis: Vector2D,\n): { min: number; max: number } {\n let min = dot(corners[0], axis);\n let max = min;\n\n for (let i = 1; i < corners.length; i++) {\n const projection = dot(corners[i], axis);\n if (projection < min) min = projection;\n if (projection > max) max = projection;\n }\n\n return { min, max };\n}\n\n/**\n * Collision detection for rotated rectangles using Separating Axis Theorem (SAT)\n */\nfunction satRectRectCollision(\n rectA: Rectangle,\n rectB: Rectangle,\n): CollisionResult {\n // Get corners of both rectangles\n const cornersA = getRectangleCorners(rectA);\n const cornersB = getRectangleCorners(rectB);\n\n // Get axes to test\n const axes = getAxes(cornersA, cornersB);\n\n // Test each axis\n for (const axis of axes) {\n const projectionA = projectShapeOntoAxis(cornersA, axis);\n const projectionB = projectShapeOntoAxis(cornersB, axis);\n\n // Check for separation\n if (\n projectionA.max < projectionB.min ||\n projectionB.max < projectionA.min\n ) {\n // Shapes are separated along this axis\n return { colliding: false };\n }\n }\n\n // If we get here, the shapes are colliding\n return { colliding: true };\n}\n","import { Circle, Point, Rectangle, Shape } from \"../../types\";\nimport { circleCircleCollision } from \"./circleCircle\";\nimport { circlePointCollision } from \"./circlePoint\";\nimport { circleRectCollision } from \"./circleRect\";\nimport { rectPointCollision } from \"./rectPoint\";\nimport { rectRectCollision } from \"./rectRect\";\n\n/**\n * Check if two entities are colliding\n * @param shapeA First shape\n * @param shapeB Second shape\n * @returns True if the shapes are colliding\n */\nexport function checkShapeCollision(shapeA: Shape, shapeB: Shape): boolean {\n const shapeAType = shapeA.type;\n const shapeBType = shapeB.type;\n\n // Circle vs Circle\n if (shapeAType === \"circle\" && shapeBType === \"circle\") {\n return circleCircleCollision(shapeA as Circle, shapeB as Circle).colliding;\n }\n\n if (shapeAType === \"circle\" && shapeBType === \"point\") {\n return circlePointCollision(shapeA as Circle, shapeB as Point).colliding;\n }\n if (shapeAType === \"point\" && shapeBType === \"circle\") {\n return circlePointCollision(shapeB as Circle, shapeA as Point).colliding;\n }\n\n if (shapeAType === \"circle\" && shapeBType === \"rectangle\") {\n return circleRectCollision(shapeA as Circle, shapeB as Rectangle).colliding;\n }\n if (shapeAType === \"rectangle\" && shapeBType === \"circle\") {\n return circleRectCollision(shapeB as Circle, shapeA as Rectangle).colliding;\n }\n\n if (shapeAType === \"rectangle\" && shapeBType === \"rectangle\") {\n return rectRectCollision(shapeA as Rectangle, shapeB as Rectangle)\n .colliding;\n }\n\n if (shapeAType === \"rectangle\" && shapeBType === \"point\") {\n return rectPointCollision(shapeA as Rectangle, shapeB as Point).colliding;\n }\n if (shapeAType === \"point\" && shapeBType === \"rectangle\") {\n return rectPointCollision(shapeB as Rectangle, shapeA as Point).colliding;\n }\n\n return false;\n}\n","import { Entity, Shape } from \"../types\";\nimport { BaseCollisionDetector } from \"./CollisionDetector\";\nimport { checkShapeCollision } from \"./shapeCollisions/checkShapeCollision\";\n\n/**\n * Collision detector that uses a brute force approach\n * Checks every entity against the given shape\n *\n * Best used when:\n * - You have a small number of entities\n * - You only need to check collisions occasionally\n * - You want the simplest implementation\n */\nexport function BruteForceCollisionDetector({\n entities,\n}: {\n entities: Entity[];\n}) {\n return new BruteForceCollisionDetectorImpl(entities);\n}\n\nclass BruteForceCollisionDetectorImpl extends BaseCollisionDetector {\n /**\n * Get all entities that collide with the given shape\n * @param shape The shape to check collisions against\n * @returns Array of entity IDs that collide with the shape\n */\n getCollisions(shape: Shape): (string | number)[] {\n const collisions: (string | number)[] = [];\n\n // Check each entity against the given shape\n for (const entity of this.entities) {\n // Check if the shapes collide\n if (checkShapeCollision(shape, entity.shape)) {\n collisions.push(entity.id);\n }\n }\n\n return collisions;\n }\n}\n","import { AABB, Circle, Entity, Point, Rectangle, Shape } from \"../types\";\nimport { BaseCollisionDetector } from \"./CollisionDetector\";\nimport { checkShapeCollision } from \"./shapeCollisions/checkShapeCollision\";\nimport { cellToId, circleToAABB, positionToCell, rectToAABB } from \"../utils\";\n\ntype CellId = number;\n\n/**\n * Configuration options for the spatial grid collision detector\n */\nexport interface SpatialGridConfig {\n /** Size of each grid cell */\n cellSize: number;\n}\n\n/**\n * Collision detector that uses spatial partitioning for efficient collision detection\n *\n * Best used when:\n * - You have a large number of entities\n * - Entities are distributed across the space\n * - You need to check collisions frequently\n */\nexport function SpatialGridCollisionDetector({\n entities,\n cellSize = 64,\n}: {\n entities: Entity[];\n cellSize?: number;\n}) {\n return new SpatialGridCollisionDetectorImpl(entities, { cellSize });\n}\n\nclass SpatialGridCollisionDetectorImpl extends BaseCollisionDetector {\n /** The spatial hash grid for quick lookups */\n private grid: Map<CellId, Entity[]>;\n /** Configuration for the spatial grid */\n private config: SpatialGridConfig;\n\n /**\n * Create a new spatial grid collision detector\n */\n constructor(entities: Entity[], config: SpatialGridConfig) {\n super(entities);\n this.config = config;\n this.grid = new Map();\n\n // Initialize the grid with entities\n this.rebuildGrid();\n }\n\n /**\n * Get all entities that collide with the given shape\n */\n getCollisions(shape: Shape): (string | number)[] {\n // Get the AABB for the shape\n const aabb = this.getAABBForShape(shape);\n\n // Get all cells that the AABB overlaps\n const cells = this.getCellsForAABB(aabb);\n\n // Get all entities in those cells\n const potentialCollisions = new Set<Entity>();\n\n for (const cellId of cells) {\n const entitiesInCell = this.grid.get(cellId);\n if (entitiesInCell) {\n for (const entity of entitiesInCell) {\n potentialCollisions.add(entity);\n }\n }\n }\n\n // Check for actual collisions\n const collisions: (string | number)[] = [];\n\n for (const entity of potentialCollisions) {\n if (checkShapeCollision(shape, entity.shape)) {\n collisions.push(entity.id);\n }\n }\n\n return collisions;\n }\n\n /**\n * Rebuild the spatial grid with the current entities\n */\n rebuildGrid(): void {\n // Clear the grid\n this.grid.clear();\n\n // Add all entities to the grid\n for (const entity of this.entities) {\n this.insertEntityIntoGrid(entity);\n }\n }\n\n /**\n * Insert an entity into the spatial grid\n */\n private insertEntityIntoGrid(entity: Entity): void {\n // Get the AABB for the entity\n const aabb = this.getAABB(entity);\n\n // Get all cells that the AABB overlaps\n const cells = this.getCellsForAABB(aabb);\n\n // Add the entity to each cell\n for (const cellId of cells) {\n if (!this.grid.has(cellId)) {\n this.grid.set(cellId, []);\n }\n\n this.grid.get(cellId)!.push(entity);\n }\n }\n\n /**\n * Get all cells that an AABB overlaps\n */\n private getCellsForAABB(aabb: AABB): CellId[] {\n const { cellSize } = this.config;\n\n // Calculate the min and max cell coordinates\n const [minCellX, minCellY] = positionToCell(aabb.min, cellSize);\n const [maxCellX, maxCellY] = positionToCell(aabb.max, cellSize);\n\n // Get all cells in the range\n const cells: CellId[] = new Array(\n (maxCellX - minCellX + 1) * (maxCellY - minCellY + 1),\n );\n let index = 0;\n\n for (let x = minCellX; x <= maxCellX; x++) {\n for (let y = minCellY; y <= maxCellY; y++) {\n cells[index++] = cellToId(x, y);\n }\n }\n\n return cells;\n }\n\n /**\n * Get the AABB for an entity\n */\n private getAABB(entity: Entity): AABB {\n return this.getAABBForShape(entity.shape);\n }\n\n /**\n * Get the AABB for a shape\n */\n private getAABBForShape(shape: Shape): AABB {\n const shapeType = shape.type;\n\n if (shapeType === \"circle\") {\n return circleToAABB(shape as Circle);\n } else if (shapeType === \"rectangle\") {\n return rectToAABB(shape as Rectangle);\n } else if (shapeType === \"point\") {\n // For a point, create a tiny AABB\n return {\n min: { x: (shape as Point).position.x, y: (shape as Point).position.y },\n max: { x: (shape as Point).position.x, y: (shape as Point).position.y },\n };\n }\n\n throw new Error(`Unsupported shape type: ${shapeType}`);\n }\n}\n","import { Circle, Point, Rectangle, Shape } from \"../types\";\nimport { ShapeStyle, RendererOptions, RenderableShape } from \"./types\";\n\n/**\n * Apply style settings to the canvas context\n */\nexport function applyStyle(ctx: CanvasRenderingContext2D, style: ShapeStyle) {\n // Save the current context state\n ctx.save();\n\n // Apply fill and stroke styles\n if (style.fillColor) {\n ctx.fillStyle = style.fillColor;\n }\n\n if (style.strokeColor) {\n ctx.strokeStyle = style.strokeColor;\n }\n\n if (style.strokeWidth !== undefined) {\n ctx.lineWidth = style.strokeWidth;\n }\n\n if (style.alpha !== undefined) {\n ctx.globalAlpha = style.alpha;\n }\n\n // Apply shadow settings if provided\n if (style.shadowBlur !== undefined) {\n ctx.shadowBlur = style.shadowBlur;\n }\n\n if (style.shadowColor) {\n ctx.shadowColor = style.shadowColor;\n }\n\n if (style.shadowOffsetX !== undefined) {\n ctx.shadowOffsetX = style.shadowOffsetX;\n }\n\n if (style.shadowOffsetY !== undefined) {\n ctx.shadowOffsetY = style.shadowOffsetY;\n }\n}\n\n/**\n * Restore the canvas context to its previous state\n */\nexport function restoreContext(ctx: CanvasRenderingContext2D) {\n ctx.restore();\n}\n\n/**\n * Render a circle shape\n */\nexport function renderCircle(\n ctx: CanvasRenderingContext2D,\n circle: Circle,\n style: ShapeStyle,\n) {\n applyStyle(ctx, style);\n\n ctx.beginPath();\n ctx.arc(circle.center.x, circle.center.y, circle.radius, 0, Math.PI * 2);\n\n if (style.fillColor) {\n ctx.fill();\n }\n\n if (style.strokeColor && style.strokeWidth && style.strokeWidth > 0) {\n ctx.stroke();\n }\n\n restoreContext(ctx);\n}\n\n/**\n * Render a point shape\n */\nexport function renderPoint(\n ctx: CanvasRenderingContext2D,\n point: Point,\n style: ShapeStyle,\n) {\n // Points are rendered as small circles\n const pointSize = style.strokeWidth || 4;\n\n applyStyle(ctx, style);\n\n ctx.beginPath();\n ctx.arc(point.position.x, point.position.y, pointSize / 2, 0, Math.PI * 2);\n\n if (style.fillColor) {\n ctx.fill();\n }\n\n if (style.strokeColor && style.strokeWidth && style.strokeWidth > 0) {\n ctx.stroke();\n }\n\n restoreContext(ctx);\n}\n\n/**\n * Render a rectangle shape\n */\nexport function renderRectangle(\n ctx: CanvasRenderingContext2D,\n rectangle: Rectangle,\n style: ShapeStyle,\n) {\n applyStyle(ctx, style);\n\n // Save the current transformation matrix\n ctx.save();\n\n // Translate to the rectangle's position\n ctx.translate(rectangle.position.x, rectangle.position.y);\n\n // Rotate if needed\n if (rectangle.rotationDeg !== 0) {\n const rotationRad = (rectangle.rotationDeg * Math.PI) / 180;\n ctx.rotate(rotationRad);\n }\n\n // Draw the rectangle centered at the origin\n const halfWidth = rectangle.width / 2;\n const halfHeight = rectangle.height / 2;\n\n if (style.fillColor) {\n ctx.fillRect(-halfWidth, -halfHeight, rectangle.width, rectangle.height);\n }\n\n if (style.strokeColor && style.strokeWidth && style.strokeWidth > 0) {\n ctx.strokeRect(-halfWidth, -halfHeight, rectangle.width, rectangle.height);\n }\n\n // Restore the transformation matrix\n ctx.restore();\n\n // Restore the style context\n restoreContext(ctx);\n}\n\n/**\n * Render any shape based on its type\n */\nexport function renderShape(\n ctx: CanvasRenderingContext2D,\n shape: Shape,\n style: ShapeStyle,\n) {\n switch (shape.type) {\n case \"circle\":\n renderCircle(ctx, shape, style);\n break;\n case \"rectangle\":\n renderRectangle(ctx, shape, style);\n break;\n case \"point\":\n renderPoint(ctx, shape, style);\n break;\n default:\n // This should never happen if all shape types are handled\n console.warn(\"Unknown shape type encountered\");\n break;\n }\n}\n\n/**\n * Main renderer function to render multiple shapes\n */\nexport function renderShapes(\n ctx: CanvasRenderingContext2D,\n shapes: RenderableShape[],\n options: RendererOptions,\n) {\n // Render each shape\n for (const { shape, style } of shapes) {\n // Merge with default style if provided\n const mergedStyle = {\n ...options.defaultStyle,\n ...style,\n };\n\n renderShape(ctx, shape, mergedStyle);\n }\n}\n","/**\n * pepperjs\n * A spicy, high-performance library for building 2D games in JavaScript\n *\n * @packageDocumentation\n */\n\n// ----- Collision Detection System -----\n// Export types\nexport * from \"./types\";\n\n// Export utility functions\nexport * from \"./utils\";\n\n// Export collision detection system\nexport * from \"./collision\";\n\n// Export rendering system\nexport * from \"./render\";\n\n// ----- Library Information -----\nexport const VERSION = \"0.0.1\";\n\n// ----- Future modules (placeholders) -----\n// These will be implemented in future versions\n\n/**\n * @internal\n * Rendering capabilities\n */\nexport const Renderer = {\n // Renderer is now implemented\n notImplemented: false,\n\n // Information about implementation\n info: \"Basic rendering capabilities are now available\",\n};\n\n/**\n * @internal\n * Future game loop management API\n */\nexport const GameLoop = {\n // Placeholder for future game loop module\n notImplemented: true,\n\n // Information about planned implementation\n info: \"Game loop management will be added in a future version\",\n};\n\n/**\n * @internal\n * Future input handling API\n */\nexport const Input = {\n // Placeholder for future input handling module\n notImplemented: true,\n\n // Information about planned implementation\n info: \"Input handling will be added in a future version\",\n};\n"],"mappings":"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","names":["vec2","x","y","add","a","b","subtract","scale","v","scalar","dot","cross","lengthSquared","length","normalize","len","distanceSquared","dx","dy","distance","rectToAABB","rect","circleToAABB","circle","aabbIntersect","positionToCell","position","cellSize","cellToId","BaseCollisionDetector","entities","circleCircleCollision","circleA","circleB","distSquared","distanceSquared","radiusSum","circlePointCollision","circle","point","distanceSquared","circleRectCollision","circle","rect","circleRotatedRectCollision","closestX","closestY","distanceSquared","rotationRad","cos","sin","rectCenterX","rectCenterY","dx","dy","rotatedX","rotatedY","localCircle","localRect","rectPointCollision","rect","point","rotatedRectPointCollision","rotationRad","cos","sin","rectCenterX","rectCenterY","dx","dy","rotatedX","rotatedY","localPoint","localRect","rectRectCollision","rectA","rectB","aabbRectRectCollision","satRectRectCollision","aabbIntersect","rectToAABB","getRectangleCorners","rect","position","width","height","rotationDeg","halfWidth","halfHeight","center","rotationRad","cos","sin","corner","getAxes","cornersA","cornersB","axes","i","p1","p2","edge","subtract","normal","normalize","projectShapeOntoAxis","corners","axis","min","dot","max","projection","projectionA","projectionB","checkShapeCollision","shapeA","shapeB","shapeAType","shapeBType","circleCircleCollision","circlePointCollision","circleRectCollision","rectRectCollision","rectPointCollision","BruteForceCollisionDetector","entities","BruteForceCollisionDetectorImpl","BaseCollisionDetector","shape","collisions","entity","checkShapeCollision","SpatialGridCollisionDetector","entities","cellSize","SpatialGridCollisionDetectorImpl","BaseCollisionDetector","config","shape","aabb","cells","potentialCollisions","cellId","entitiesInCell","entity","collisions","checkShapeCollision","minCellX","minCellY","positionToCell","maxCellX","maxCellY","index","x","y","cellToId","shapeType","circleToAABB","rectToAABB","applyStyle","ctx","style","restoreContext","renderCircle","circle","renderPoint","point","pointSize","renderRectangle","rectangle","rotationRad","halfWidth","halfHeight","renderShape","shape","renderShapes","shapes","options","mergedStyle","VERSION","Renderer","GameLoop","Input"]}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Basic vector type for 2D coordinates
3
+ */
4
+ type Vector2D = {
5
+ x: number;
6
+ y: number;
7
+ };
8
+ /**
9
+ * Axis-Aligned Bounding Box
10
+ */
11
+ type AABB = {
12
+ min: Vector2D;
13
+ max: Vector2D;
14
+ };
15
+ /**
16
+ * Circle shape
17
+ */
18
+ type Circle = {
19
+ type: "circle";
20
+ center: Vector2D;
21
+ radius: number;
22
+ };
23
+ /**
24
+ * Circle shape
25
+ */
26
+ type Point = {
27
+ type: "point";
28
+ position: Vector2D;
29
+ };
30
+ /**
31
+ * Rectangle shape with position and dimensions
32
+ */
33
+ type Rectangle = {
34
+ type: "rectangle";
35
+ position: Vector2D;
36
+ width: number;
37
+ height: number;
38
+ rotationDeg: number;
39
+ };
40
+ /**
41
+ * Shape types supported by the collision system
42
+ */
43
+ type Shape = Circle | Rectangle | Point;
44
+ type ShapeType = Shape["type"];
45
+ /**
46
+ * Contact point data for collision resolution
47
+ */
48
+ type ContactPoint = {
49
+ point: Vector2D;
50
+ normal: Vector2D;
51
+ depth: number;
52
+ };
53
+ /**
54
+ * Collision detection result
55
+ */
56
+ type CollisionResult = {
57
+ colliding: boolean;
58
+ };
59
+ /**
60
+ * Entity with a collision shape and identifier
61
+ */
62
+ type Entity = {
63
+ id: number | string;
64
+ shape: Shape;
65
+ };
66
+ /**
67
+ * Configuration options for the collision system
68
+ */
69
+ type CollisionConfig = {
70
+ /** Grid cell size for spatial partitioning */
71
+ cellSize: number;
72
+ /** Maximum number of entities to track */
73
+ maxEntities?: number;
74
+ /** Whether to use broad-phase spatial partitioning */
75
+ useBroadPhase?: boolean;
76
+ };
77
+
78
+ export type { AABB, Circle, CollisionConfig, CollisionResult, ContactPoint, Entity, Point, Rectangle, Shape, ShapeType, Vector2D };
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Basic vector type for 2D coordinates
3
+ */
4
+ type Vector2D = {
5
+ x: number;
6
+ y: number;
7
+ };
8
+ /**
9
+ * Axis-Aligned Bounding Box
10
+ */
11
+ type AABB = {
12
+ min: Vector2D;
13
+ max: Vector2D;
14
+ };
15
+ /**
16
+ * Circle shape
17
+ */
18
+ type Circle = {
19
+ type: "circle";
20
+ center: Vector2D;
21
+ radius: number;
22
+ };
23
+ /**
24
+ * Circle shape
25
+ */
26
+ type Point = {
27
+ type: "point";
28
+ position: Vector2D;
29
+ };
30
+ /**
31
+ * Rectangle shape with position and dimensions
32
+ */
33
+ type Rectangle = {
34
+ type: "rectangle";
35
+ position: Vector2D;
36
+ width: number;
37
+ height: number;
38
+ rotationDeg: number;
39
+ };
40
+ /**
41
+ * Shape types supported by the collision system
42
+ */
43
+ type Shape = Circle | Rectangle | Point;
44
+ type ShapeType = Shape["type"];
45
+ /**
46
+ * Contact point data for collision resolution
47
+ */
48
+ type ContactPoint = {
49
+ point: Vector2D;
50
+ normal: Vector2D;
51
+ depth: number;
52
+ };
53
+ /**
54
+ * Collision detection result
55
+ */
56
+ type CollisionResult = {
57
+ colliding: boolean;
58
+ };
59
+ /**
60
+ * Entity with a collision shape and identifier
61
+ */
62
+ type Entity = {
63
+ id: number | string;
64
+ shape: Shape;
65
+ };
66
+ /**
67
+ * Configuration options for the collision system
68
+ */
69
+ type CollisionConfig = {
70
+ /** Grid cell size for spatial partitioning */
71
+ cellSize: number;
72
+ /** Maximum number of entities to track */
73
+ maxEntities?: number;
74
+ /** Whether to use broad-phase spatial partitioning */
75
+ useBroadPhase?: boolean;
76
+ };
77
+
78
+ export type { AABB, Circle, CollisionConfig, CollisionResult, ContactPoint, Entity, Point, Rectangle, Shape, ShapeType, Vector2D };
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";var p=Object.defineProperty;var i=Object.getOwnPropertyDescriptor;var c=Object.getOwnPropertyNames;var a=Object.prototype.hasOwnProperty;var l=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of c(e))!a.call(t,o)&&o!==n&&p(t,o,{get:()=>e[o],enumerable:!(r=i(e,o))||r.enumerable});return t};var y=t=>l(p({},"__esModule",{value:!0}),t);var m={};module.exports=y(m);
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/types.ts"],"sourcesContent":["/**\n * Basic vector type for 2D coordinates\n */\nexport type Vector2D = {\n x: number;\n y: number;\n};\n\n/**\n * Axis-Aligned Bounding Box\n */\nexport type AABB = {\n min: Vector2D;\n max: Vector2D;\n};\n\n/**\n * Circle shape\n */\nexport type Circle = {\n type: \"circle\";\n center: Vector2D;\n radius: number;\n};\n\n/**\n * Circle shape\n */\nexport type Point = {\n type: \"point\";\n position: Vector2D;\n};\n\n/**\n * Rectangle shape with position and dimensions\n */\nexport type Rectangle = {\n type: \"rectangle\";\n position: Vector2D;\n width: number;\n height: number;\n rotationDeg: number;\n};\n\n/**\n * Shape types supported by the collision system\n */\nexport type Shape = Circle | Rectangle | Point;\nexport type ShapeType = Shape[\"type\"];\n\n/**\n * Contact point data for collision resolution\n */\nexport type ContactPoint = {\n point: Vector2D;\n normal: Vector2D;\n depth: number;\n};\n\n/**\n * Collision detection result\n */\nexport type CollisionResult = {\n colliding: boolean;\n};\n\n/**\n * Entity with a collision shape and identifier\n */\nexport type Entity = {\n id: number | string;\n shape: Shape;\n};\n\n/**\n * Configuration options for the collision system\n */\nexport type CollisionConfig = {\n /** Grid cell size for spatial partitioning */\n cellSize: number;\n /** Maximum number of entities to track */\n maxEntities?: number;\n /** Whether to use broad-phase spatial partitioning */\n useBroadPhase?: boolean;\n};\n"],"mappings":"+WAAA,IAAAA,EAAA,kBAAAC,EAAAD","names":["types_exports","__toCommonJS"]}
package/dist/types.mjs ADDED
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=types.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}