Skip to content

Commit

Permalink
Makes parent configurable
Browse files Browse the repository at this point in the history
  • Loading branch information
mflerackers committed Dec 15, 2024
1 parent 57c7a96 commit ef5f71b
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 17 deletions.
56 changes: 56 additions & 0 deletions examples/parenttest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
kaplay();

loadBean();

const centerBean = add([
pos(center()),
anchor("center"),
sprite("bean"),
area(),
rotate(0),
scale(2),
{
update() {
this.angle += 20 * dt();
}
}
])

const orbitingBean = centerBean.add([
pos(vec2(100, 0)),
anchor("center"),
sprite("bean"),
area(),
rotate(0),
scale(1),
color(),
{
update() {
this.angle = -this.parent.transform.getRotation();
if (this.isHovering()) {
this.color = RED;
}
else {
this.color = WHITE;
}
}
}
])

onMousePress(() => {
if (orbitingBean.parent === centerBean/* && orbitingBean.isHovering()*/) {
orbitingBean.setParent(getTreeRoot(), { keep: 7 });
}
})

onMouseMove((pos, delta) => {
if (orbitingBean.parent !== centerBean) {
orbitingBean.pos = orbitingBean.pos.add(delta);
}
})

onMouseRelease(() => {
if (orbitingBean.parent !== centerBean) {
orbitingBean.setParent(centerBean, { keep: 7 });
}
})
45 changes: 44 additions & 1 deletion src/game/make.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,18 @@ import {
type Tag,
} from "../types";
import { KEventController, KEventHandler, uid } from "../utils";
import type { Game } from "./game";

export enum KeepFlags {
Pos = 1,
Angle = 2,
Scale = 4,
All = 7,
}

export type SetParentOpt = {
keep: KeepFlags
}

export function make<T>(comps: CompList<T> = []): GameObj<T> {
const compStates = new Map<string, Comp>();
Expand All @@ -39,6 +51,7 @@ export function make<T>(comps: CompList<T> = []): GameObj<T> {
const treatTagsAsComponents = _k.globalOpt.tagsAsComponents;
let onCurCompCleanup: Function | null = null;
let paused = false;
let _parent: GameObj;

// the game object without the event methods, added later
const obj: Omit<GameObj, keyof typeof evs> = {
Expand All @@ -47,7 +60,37 @@ export function make<T>(comps: CompList<T> = []): GameObj<T> {
hidden: false,
transform: new Mat23(),
children: [],
parent: null,

get parent() {
return _parent!;
},

set parent(p: GameObj) {
if (_parent === p) { return; }
const index = _parent ? _parent.children.indexOf(this as GameObj) : -1;
if (index !== -1) {
_parent.children.splice(index, 1);
}
_parent = p;
p.children.push(this as GameObj);
},

setParent(p: GameObj, opt: SetParentOpt) {
if (_parent === p) { return; }
const oldTransform = _parent.transform
const newTransform = p.transform
if ((opt.keep & KeepFlags.Pos) && this.pos !== undefined) {
oldTransform.transformPoint(this.pos, this.pos)
newTransform.inverse.transformPoint(this.pos, this.pos)
}
if ((opt.keep & KeepFlags.Angle) && this.angle !== undefined) {
this.angle += newTransform.getRotation() - oldTransform.getRotation();
}
if ((opt.keep & KeepFlags.Scale) && this.scale !== undefined) {
this.scale = this.scale.scale(oldTransform.getScale().invScale(newTransform.getScale()));
}
this.parent = p;
},

set paused(p) {
if (p === paused) return;
Expand Down
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,11 @@ export type {
Game,
GameObjEventMap,
GameObjEventNames,
KeepFlags,
LevelOpt,
SceneDef,
SceneName,
SetParentOpt,
TupleWithoutFirst,
} from "./game";
export type {
Expand Down
36 changes: 21 additions & 15 deletions src/math/math.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,8 @@ export class Vec2 {
return Math.abs(this.x) > Math.abs(this.y)
? this.x < 0 ? Vec2.LEFT : Vec2.RIGHT
: this.y < 0
? Vec2.UP
: Vec2.DOWN;
? Vec2.UP
: Vec2.DOWN;
}

/** Clone the vector */
Expand Down Expand Up @@ -259,6 +259,12 @@ export class Vec2 {
return out;
}

/** Scale by the inverse of another vector. or a single number */
invScale(...args: Vec2Args): Vec2 {
const s = vec2(...args);
return new Vec2(this.x / s.x, this.y / s.y);
}

/** Get distance between another vector */
dist(...args: Vec2Args): number {
const p2 = vec2(...args);
Expand Down Expand Up @@ -1379,7 +1385,7 @@ export class Mat4 {
const r = Math.sqrt(this.m[0] * this.m[0] + this.m[1] * this.m[1]);
return new Vec2(
Math.atan(this.m[0] * this.m[4] + this.m[1] * this.m[5])
/ (r * r),
/ (r * r),
0,
);
}
Expand All @@ -1388,7 +1394,7 @@ export class Mat4 {
return new Vec2(
0,
Math.atan(this.m[0] * this.m[4] + this.m[1] * this.m[5])
/ (s * s),
/ (s * s),
);
}
else {
Expand Down Expand Up @@ -1927,7 +1933,7 @@ export function testPolygonPoint(poly: Polygon, pt: Vec2): boolean {
((p[i].y > pt.y) != (p[j].y > pt.y))
&& (pt.x
< (p[j].x - p[i].x) * (pt.y - p[i].y) / (p[j].y - p[i].y)
+ p[i].x)
+ p[i].x)
) {
c = !c;
}
Expand All @@ -1945,7 +1951,7 @@ export function testEllipsePoint(ellipse: Ellipse, pt: Vec2): boolean {
const vx = pt.x * c + pt.y * s;
const vy = -pt.x * s + pt.y * c;
return vx * vx / (ellipse.radiusX * ellipse.radiusX)
+ vy * vy / (ellipse.radiusY * ellipse.radiusY) < 1;
+ vy * vy / (ellipse.radiusY * ellipse.radiusY) < 1;
}

export function testEllipseCircle(ellipse: Ellipse, circle: Circle): boolean {
Expand Down Expand Up @@ -2882,7 +2888,7 @@ export class Ellipse {
const vx = point.x * c + point.y * s;
const vy = -point.x * s + point.y * c;
return vx * vx / (this.radiusX * this.radiusX)
+ vy * vy / (this.radiusY * this.radiusY) < 1;
+ vy * vy / (this.radiusY * this.radiusY) < 1;
}
raycast(origin: Vec2, direction: Vec2): RaycastResult {
return raycastEllipse(origin, direction, this);
Expand Down Expand Up @@ -3281,21 +3287,21 @@ export function kochanekBartels(
const hx = h(
pt2.x,
0.5 * (1 - tension) * (1 + bias) * (1 + continuity) * (pt2.x - pt1.x)
+ 0.5 * (1 - tension) * (1 - bias) * (1 - continuity)
* (pt3.x - pt2.x),
+ 0.5 * (1 - tension) * (1 - bias) * (1 - continuity)
* (pt3.x - pt2.x),
0.5 * (1 - tension) * (1 + bias) * (1 - continuity) * (pt3.x - pt2.x)
+ 0.5 * (1 - tension) * (1 - bias) * (1 + continuity)
* (pt4.x - pt3.x),
+ 0.5 * (1 - tension) * (1 - bias) * (1 + continuity)
* (pt4.x - pt3.x),
pt3.x,
);
const hy = h(
pt2.y,
0.5 * (1 - tension) * (1 + bias) * (1 + continuity) * (pt2.y - pt1.y)
+ 0.5 * (1 - tension) * (1 - bias) * (1 - continuity)
* (pt3.y - pt2.y),
+ 0.5 * (1 - tension) * (1 - bias) * (1 - continuity)
* (pt3.y - pt2.y),
0.5 * (1 - tension) * (1 + bias) * (1 - continuity) * (pt3.y - pt2.y)
+ 0.5 * (1 - tension) * (1 - bias) * (1 + continuity)
* (pt4.y - pt3.y),
+ 0.5 * (1 - tension) * (1 - bias) * (1 + continuity)
* (pt4.y - pt3.y),
pt3.y,
);
return (t: number) => {
Expand Down
9 changes: 8 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ import type {
LevelOpt,
SceneDef,
SceneName,
SetParentOpt,
TupleWithoutFirst,
} from "./game";
import type {
Expand Down Expand Up @@ -6006,11 +6007,17 @@ export interface GameObjRaw {
*/
query(opt: QueryOpt): GameObj[];
/**
* Get the parent game obj, if have any.
* Get or set the parent game obj.
*
* @since v3000.0
*/
parent: GameObj | null;
/**
* Set the parent game obj.
*
* @since v4000.0
*/
setParent(p: GameObj, opt: SetParentOpt): void;
/**
* @readonly
* Get all children game objects.
Expand Down

0 comments on commit ef5f71b

Please sign in to comment.