Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: layers and layer component #121

Merged
merged 3 commits into from
Jun 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
167 changes: 51 additions & 116 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
- added quadratic bezier and Catmull-Rom evaluation
- added evaluation of the first and second derivatives for all splines
- added higher order easing functions linear, steps and cubic-bezier
- added layers and the layer component

### Deprecated

Expand Down Expand Up @@ -80,10 +81,7 @@ loadFont("apl386", "/examples/fonts/apl386.ttf", {
- setting `obj.text` with `text()` component now immediately updates `width` and `height` property

```js
const obj = add([
text("oh hi"),
pos(100, 200),
]);
const obj = add([text("oh hi"), pos(100, 200)]);

// before
obj.text = "bye";
Expand Down Expand Up @@ -146,12 +144,7 @@ getSprite("bean").then((spr) => {
// add a scene game object
const scene = add([]);

const bean = scene.add([
sprite("bean"),
pos(100, 200),
area(),
body(),
]);
const bean = scene.add([sprite("bean"), pos(100, 200), area(), body()]);

scene.onKeyPress("space", () => {
bean.jump();
Expand Down Expand Up @@ -182,18 +175,17 @@ const evs = [];
scene.onDestroy(() => {
evs.forEach((ev) => ev.cancel());
});
evs.push(k.onKeyPress("space", () => {
doSomeSceneSpecificStuff();
}));
evs.push(
k.onKeyPress("space", () => {
doSomeSceneSpecificStuff();
}),
);
```

- added `make()` to create game object without adding to the scene

```js
const obj = make([
sprite("bean"),
pos(120, 60),
]);
const obj = make([sprite("bean"), pos(120, 60)]);

add(obj);
```
Expand All @@ -202,9 +194,7 @@ add(obj);

```js
// before
const ui = add([
fixed(),
]);
const ui = add([fixed()]);

ui.add([
rect(),
Expand All @@ -213,14 +203,10 @@ ui.add([
]);

// now
const ui = add([
fixed(),
]);
const ui = add([fixed()]);

// you don't have to add fixed() to children
ui.add([
rect(100, 100),
]);
ui.add([rect(100, 100)]);
```

- fixed `AreaComp#onClick()` event not getting cleaned up when game object is destroyed
Expand All @@ -238,10 +224,7 @@ ui.add([
- added scene graph, game objects are now stored in a tree-like structure and can have children with `obj.add()`

```js
const bean = add([
sprite("bean"),
pos(160, 120),
]);
const bean = add([sprite("bean"), pos(160, 120)]);

const sword = bean.add([
sprite("sword"),
Expand Down Expand Up @@ -275,10 +258,7 @@ const enemies = get("enemy", {

console.log(enemies.length); // 3

add([
sprite("bigbird"),
"enemy",
]);
add([sprite("bigbird"), "enemy"]);

console.log(enemies.length); // 4
```
Expand Down Expand Up @@ -385,7 +365,7 @@ const player = add([
sprite("bean"),
// will calculate and send u_time every frame
shader("flashy", () => ({
"u_time": time(),
u_time: time(),
})),
]);
```
Expand Down Expand Up @@ -485,9 +465,7 @@ loadSprite("grass", "/sprites/grass.png", {
},
});

const g = add([
sprite("grass"),
]);
const g = add([sprite("grass")]);

onMouseMove(() => {
const mpos = mousePos();
Expand Down Expand Up @@ -538,51 +516,33 @@ music.loop = true;

```js
// before
addLevel([
"@ ^ $$",
"=======",
], {
addLevel(["@ ^ $$", "======="], {
width: 32,
height: 32,
"=": () => [
sprite("grass"),
area(),
body({ isStatic: true }),
],
"$": () => [
sprite("coin"),
area(),
"coin",
],
"=": () => [sprite("grass"), area(), body({ isStatic: true })],
$: () => [sprite("coin"), area(), "coin"],
any: (symbol) => {
if (symbol === "@") {
return [/* ... */];
return [
/* ... */
];
}
},
});

// v3000
addLevel([
"@ ^ $$",
"=======",
], {
addLevel(["@ ^ $$", "======="], {
tileWidth: 32,
tileHeight: 32,
tiles: {
"=": () => [
sprite("grass"),
area(),
body({ isStatic: true }),
],
"$": () => [
sprite("coin"),
area(),
"coin",
],
"=": () => [sprite("grass"), area(), body({ isStatic: true })],
$: () => [sprite("coin"), area(), "coin"],
},
wildcardTile: (symbol) => {
if (symbol === "@") {
return [/* ... */];
return [
/* ... */
];
}
},
});
Expand Down Expand Up @@ -626,14 +586,14 @@ onMousePress(() => {
bean.pos.x,
mousePos().x,
1,
(val) => bean.pos.x = val,
(val) => (bean.pos.x = val),
easings.easeOutBounce,
);
tween(
bean.pos.y,
mousePos().y,
1,
(val) => bean.pos.y = val,
(val) => (bean.pos.y = val),
easings.easeOutBounce,
);
});
Expand All @@ -643,23 +603,31 @@ onMousePress(() => {

```js
// before
const cancel = onUpdate(() => {/* ... */});
const cancel = onUpdate(() => {
/* ... */
});
cancel();

// v3000
const ev = onUpdate(() => {/* ... */});
const ev = onUpdate(() => {
/* ... */
});
ev.paused = true;
ev.cancel();
```

- timers can now be paused

```js
const timer = wait(4, () => {/* ... */});
const timer = wait(4, () => {
/* ... */
});
timer.paused = true;
timer.resume();

const timer = loop(1, () => {/* ... */});
const timer = loop(1, () => {
/* ... */
});
timer.paused = true;
timer.resume();
```
Expand Down Expand Up @@ -829,15 +797,9 @@ timer.resume();

```js
// before
add([
sprite("player"),
area(),
]);
add([sprite("player"), area()]);

add([
sprite("rock"),
solid(),
]);
add([sprite("rock"), solid()]);

keyDown("left", () => {
player.move(-120, 0);
Expand All @@ -848,18 +810,10 @@ player.action(() => {
});

// after
const player = add([
sprite("player"),
area(),
solid(),
]);
const player = add([sprite("player"), area(), solid()]);

// both should be solid
add([
sprite("rock"),
area(),
solid(),
]);
add([sprite("rock"), area(), solid()]);

keyDown("left", () => {
// this will handle collision resolution for you, if the other obj is also "solid"
Expand Down Expand Up @@ -887,17 +841,10 @@ keyDown("left", () => {

```js
// before
add([
rotate(Math.PI / 2),
color(0, 0.5, 1.0, 0.5),
]);
add([rotate(Math.PI / 2), color(0, 0.5, 1.0, 0.5)]);

// after
add([
rotate(90),
color(0, 127, 255),
opacity(0.5),
]);
add([rotate(90), color(0, 127, 255), opacity(0.5)]);
```

- `global` and `debug` flag now are enabled by default, need to turn off manually if you don't want
Expand Down Expand Up @@ -1004,21 +951,9 @@ loadSprite("hero", "hero.png", {
- **BREAK** now every symbol definition in `addLevel()` should be a function returning the component list, to ensure there's no weird shared states

```js
addLevel([
"* *",
"* *",
"======",
], {
"*": () => [
sprite("wall"),
area(),
solid(),
],
"=": () => [
sprite("floor"),
area(),
solid(),
],
addLevel(["* *", "* *", "======"], {
"*": () => [sprite("wall"), area(), solid()],
"=": () => [sprite("floor"), area(), solid()],
});
```

Expand Down
34 changes: 34 additions & 0 deletions examples/layers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
kaplay();

layers(["bg", "game", "ui"], "game");

// bg layer
add([
rect(width(), height()),
layer("bg"),
color(rgb(64, 128, 255)),
// opacity(0.5)
]).add([text("BG")]);

// game layer explicit
add([
pos(width() / 5, height() / 5),
rect(width() / 3, height() / 3),
layer("game"),
color(rgb(255, 128, 64)),
]).add([text("GAME")]);

// game layer implicit
add([
pos(3 * width() / 5, 3 * height() / 5),
rect(width() / 3, height() / 3),
color(rgb(255, 128, 64)),
]).add([pos(width() / 3, height() / 3), text("GAME"), anchor("botright")]);

// ui layer
add([
pos(center()),
rect(width() / 2, height() / 2),
anchor("center"),
color(rgb(64, 255, 128)),
]).add([text("UI"), anchor("center")]);
1 change: 1 addition & 0 deletions src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export * from "./physics/doubleJump";
export * from "./transform/anchor";
export * from "./transform/fixed";
export * from "./transform/follow";
export * from "./transform/layer";
export * from "./transform/move";
export * from "./transform/offscreen";
export * from "./transform/pos";
Expand Down
24 changes: 24 additions & 0 deletions src/components/transform/layer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { getInternalContext, getKaboomContext } from "@/kaboom";
import type { LayerComp } from "@/types";

export function layer(layer: string): LayerComp {
const k = getKaboomContext(this);
const internal = getInternalContext(k);
let _layerIndex = internal.game.layers.indexOf(layer);
return {
id: "layer",
get layerIndex() {
return _layerIndex;
},
get layer(): string {
return k.layers[_layerIndex];
},
set layer(value: string) {
_layerIndex = internal.game.layers.indexOf(value);
if (_layerIndex == -1) throw Error("Invalid layer name");
},
inspect() {
return `${this.layer}`;
},
};
}
Loading