Skip to content

Commit

Permalink
Merge branch 'master' into fix-fromScreen-not-scale
Browse files Browse the repository at this point in the history
  • Loading branch information
niceEli authored Oct 30, 2024
2 parents 7381226 + 66c8ff0 commit 894d9df
Show file tree
Hide file tree
Showing 97 changed files with 3,002 additions and 1,547 deletions.
34 changes: 0 additions & 34 deletions .devcontainer/devcontainer.json

This file was deleted.

28 changes: 28 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Publish to NPM

on:
push:
tags:
- '4000*'

jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Node.js
uses: actions/setup-node@v4
with:
registry-url: "https://registry.npmjs.org"
node-version: 20
- uses: pnpm/action-setup@v4
name: Install pnpm
with:
run_install: false
- name: Install dependencies
run: pnpm install
- name: Publish to NPM
run: npm publish --tag next
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
29 changes: 22 additions & 7 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
# v4000.0.0

- Added clipLineToRect
- Replaced the Separating Axis Theorem (SAT) with the Gilbert–Johnson–Keerthi
(GJK) distance algorithm.
- Added circle and (rotated) ellipse collision shapes.
- Added an ellipse component.
- Added `ellipse()` component.
- Circle area is no longer a box.
- Added a fake cursor API.
- Added restitution and friction.

- Added a fake cursor API.
```js
const myCursor = add([fakeMouse(), sprite("kat"), pos(100, 100)]);
const myCursor = add([
fakeMouse(),
sprite("kat"),
pos(100, 100),
]);

myCursor.press(); // trigger onClick events if the mouse is over
myCursor.release();
Expand All @@ -20,7 +24,7 @@

## Input

- added input bindings, `onButtonPress`, `onButtonRelease`, `onButtonDown`, and
- Added input bindings, `onButtonPress`, `onButtonRelease`, `onButtonDown`, and
it's corresponding boolean versions, `isButtonPressed`, `isButtonDown` and
`isButtonReleased`.
Expand Down Expand Up @@ -63,6 +67,14 @@
});
```
- added `pressButton(btn)` and `releaseButton(btn)` to simulate button press and
release
```js
pressButton("jump"); // triggers onButtonPress and starts onButtonDown
releaseButton("jump"); // triggers onButtonRelease and stops onButtonDown
```
- added the possibility of use arrays in all input handlers
```js
Expand All @@ -87,7 +99,7 @@
- added `patrol()` component to move along a list of waypoints.
- added `sentry()` component to notify when certain objects are in sight.
- added `NavMesh` class for pathfinding on a mesh.
- added `navigation()` component to calculate a list of waypoints on a graph.
- added `pathfinder()` component to calculate a list of waypoints on a graph.
- now collision checks are only done if there's area objects.
## Game Object
Expand Down Expand Up @@ -221,9 +233,12 @@

- fix error screen not showing with not Error object

- Added `SpriteComp.animFrame` to get the frame of the current animation (not on
the spritesheet)

## Audio

- now you can pass an `AudioBuffer` to `loadSound()` (**v4000**)
- now you can pass an `AudioBuffer` to `loadSound()`
- added `loadMusic()` to load streaming audio (doesn't block in loading screen).
```js
Expand Down
21 changes: 17 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,23 @@ pnpm install # to install dependencies.

## Documentation

Most KAPLAY docs are written on every component file in `src/components`, and
`src/types.ts` as
[jsDoc](https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html)
above each KAPLAY component entry.
KAPLAY API documentation is auto-generated by JSDoc comments in the source code.

Normally the definitions of components, types, interfaces (i.e: `SpriteComp`,
`Vec2`, `RectComp`, `LifespanCompOpt`) are on their own files. For example

- `src/components/draw/sprite.ts` for `SpriteComp`
- `src/math/math.ts` for `Vec2`
- `src/components/draw/rect.ts` for `RectComp`
- `src/components/misc/lifespan.ts` for `LifespanCompOpt`

Your best option is use **ctrl + click** on the type to go to the definition and
see the JSDoc comments. Other option is to use the search feature of your IDE.

Types like the components one (`sprite()`, `rect()`, `lifespan()`) are defined
on `types.ts` file, in the `KAPLAYCtx` interface, this is because what
`kaplay()` returns is a `KAPLAYCtx` object. So even if component files has the
definition, the JSDoc comments are on `types.ts`.

**Help on improving the documentation is appreciated!**

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# KAPLAY

![KAPLAY](assets/brand/kaplay-o.webp)
![KAPLAY](/kaplay.webp)

[**KAPLAY**](https://kaplayjs.com/) is a JavaScript library that helps you make
games fast and fun!
Expand Down
2 changes: 1 addition & 1 deletion examples/add.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const player = add([
anchor("center"), // anchor() component defines the pivot point (defaults to "topleft")
]);

// .onUpdate() is a method on all game objects, it registers an event that runs every frame
// .onUpdate() is a method that's found in all game objects, it registers an event that runs every frame
player.onUpdate(() => {
// .angle is a property provided by rotate() component, here we're incrementing the angle by 120 degrees per second, dt() is the time elapsed since last frame in seconds
player.angle += 120 * dt();
Expand Down
9 changes: 6 additions & 3 deletions examples/ai.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

// Use state() component to handle basic AI

// Start kaboom
// Start kaplay
kaplay();

// Load assets
Expand Down Expand Up @@ -54,18 +54,21 @@ enemy.onStateEnter("attack", async () => {
]);
}

// Waits 1 second to make the enemy enter in "move" state
await wait(1);
enemy.enterState("move");
});

// When we enter "move" state, we stay there for 2 sec and then go back to "idle"
enemy.onStateEnter("move", async () => {
await wait(2);
enemy.enterState("idle");
});

// Like .onUpdate() which runs every frame, but only runs when the current state is "move"
// Here we move towards the player every frame if the current state is "move"
// .onStateUpdate() is similar to .onUpdate(), it'll run every frame, but in this case
// Only when the current state is "move"
enemy.onStateUpdate("move", () => {
// We move the enemy in the direction of the player
if (!player.exists()) return;
const dir = player.pos.sub(enemy.pos).unit();
enemy.move(dir.scale(ENEMY_SPEED));
Expand Down
51 changes: 35 additions & 16 deletions examples/animation.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// @ts-check

// Start kaboom
// Start kaplay
kaplay();

loadSprite("bean", "sprites/bean.png");
loadSprite("bag", "sprites/bag.png");
// We use the default function to load the bean sprite
loadBean();

// Rotating
// We add a bean that rotates with the animate component
const rotatingBean = add([
sprite("bean"),
pos(50, 50),
Expand All @@ -15,22 +15,24 @@ const rotatingBean = add([
animate(),
]);

// Trying sprite change
rotatingBean.sprite = "bag";

// We use the 'animate()' function provided by the animate component
// This will rotate the bean from 0 to 360 degrees in 2 seconds
// The direction "forwards" means it will go back to 0 when it ends, which makes this a loop
rotatingBean.animate("angle", [0, 360], {
duration: 2,
direction: "forward",
});

// Moving right to left using ping-pong
// Now we'll move this bean from left to right
const movingBean = add([
sprite("bean"),
pos(50, 150),
anchor("center"),
animate(),
]);

// This will animate the bean from left to right in 2 seconds
// The direction "ping-pong" means that when it goes to the right, it will move back to the left
movingBean.animate("pos", [vec2(50, 150), vec2(150, 150)], {
duration: 2,
direction: "ping-pong",
Expand All @@ -44,12 +46,14 @@ const secondMovingBean = add([
animate({ relative: true }),
]);

// The fact that is relative, means that instead of setting the bean to these positions (vec2(50, 150), vec2(150, 150))
// It will ADD those positions to the position the bean was spawned in
secondMovingBean.animate("pos", [vec2(50, 150), vec2(150, 150)], {
duration: 2,
direction: "ping-pong",
});

// Changing color using a color list
// We'll change the color of the bean using a list of colors
const coloringBean = add([
sprite("bean"),
pos(50, 300),
Expand All @@ -58,11 +62,14 @@ const coloringBean = add([
animate(),
]);

// It will animate the color the bean color from white to red to green to blue to white
// In 8 seconds, and when it's over i'll start over again
coloringBean.animate("color", [WHITE, RED, GREEN, BLUE, WHITE], {
duration: 8,
direction: "forward",
});

// Changing opacity using an opacity list
// We'll change the opacity of the bean using a list of opacities
const opacitingBean = add([
sprite("bean"),
pos(150, 300),
Expand All @@ -71,19 +78,22 @@ const opacitingBean = add([
animate(),
]);

// We'll animate the opacity from 1, to 0, to 1 during 8 seconds
// This time, we'll be using an easing!
opacitingBean.animate("opacity", [1, 0, 1], {
duration: 8,
easing: easings.easeInOutCubic,
});

// Moving in a square like motion
// We'll move this bean in a square shape
const squaringBean = add([
sprite("bean"),
pos(50, 400),
anchor("center"),
animate(),
]);

// Passing an array of keyframes (the positions) it'll move in a square shape
squaringBean.animate(
"pos",
[
Expand All @@ -96,14 +106,16 @@ squaringBean.animate(
{ duration: 8 },
);

// Moving in a square like motion, but with custom spaced keyframes
// We'll move the bean in a square shape again, but this time we'll be using timing
const timedSquaringBean = add([
sprite("bean"),
pos(50, 400),
anchor("center"),
animate(),
]);

// This will move the bean in the same positions as before in the same time
// But the timings will make the movement from one keyframe to another quicker or slower
timedSquaringBean.animate(
"pos",
[
Expand All @@ -125,6 +137,7 @@ timedSquaringBean.animate(
},
);

// We'll move this bean in a curve
// Using spline interpolation to move according to a smoothened path
const curvingBean = add([
sprite("bean"),
Expand All @@ -134,6 +147,7 @@ const curvingBean = add([
rotate(0),
]);

// This will move bean in these positions, but using a different interpolation
curvingBean.animate(
"pos",
[
Expand All @@ -146,37 +160,42 @@ curvingBean.animate(
{ duration: 8, direction: "ping-pong", interpolation: "spline" },
);

// We'll animate a little bean to rotate around the curvingBean!
// Here we're creating a pivot
const littleBeanPivot = curvingBean.add([
animate(),
rotate(0),
named("littlebeanpivot"),
]);

// And animating the pivot, you know this!
littleBeanPivot.animate("angle", [0, 360], {
duration: 2,
direction: "reverse",
});

// We'll animate a little bean to rotate around the pivot
const littleBean = littleBeanPivot.add([
sprite("bean"),
pos(50, 50),
anchor("center"),
scale(0.25),
animate(),
rotate(0),
named("littlebean"),
]);

// And here we animate the little bean
littleBean.animate("angle", [0, 360], {
duration: 2,
direction: "forward",
});

console.log(JSON.stringify(serializeAnimation(curvingBean, "root"), "", 2));
// We'll the serialize an animation and log it to the console so we can see all the current animation channels
console.log(JSON.stringify(serializeAnimation(curvingBean, "root"), null, 2));

// Debug piece of code that draws a line in the curve that the curving bean goes through, don't mind it
/*onDraw(() => {
drawCurve(t => evaluateCatmullRom(
vec2(200, 400),\
vec2(200, 400),
vec2(250, 500),
vec2(300, 400),
vec2(350, 500), t), { color: RED })
Expand Down
Loading

0 comments on commit 894d9df

Please sign in to comment.