Skip to content

Commit

Permalink
Ellipse math (#824)
Browse files Browse the repository at this point in the history
* some work on ellipse

* spaces->tabs

* More work on ellipse collision

* Finished ellipse collision and raycasting

* These weren't supposed to be here

* Modified transform ellipse to use sandwich product

* Fix indentation
  • Loading branch information
mflerackers committed Apr 1, 2024
1 parent 446438b commit 6fb737f
Show file tree
Hide file tree
Showing 5 changed files with 713 additions and 56 deletions.
56 changes: 55 additions & 1 deletion examples/overlap.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,50 @@ add([
})
},
getShape() {
// This would be point if we had a real class for it
// This would be point if we had a real class for it
return new Rect(vec2(-1, -1).add(this.pos), 3, 3)
},
},
])

add([
pos(280, 200),
color(BLUE),
"shape",
{
getShape() {
return new Ellipse(this.pos, 80, 30)
},
draw() {
drawEllipse({
radiusX: 80,
radiusY: 30,
color: this.color,
})
},
},
])

add([
pos(340, 120),
color(BLUE),
"shape",
{
getShape() {
return new Ellipse(this.pos, 40, 15, 45)
},
draw() {
pushRotate(45)
drawEllipse({
radiusX: 40,
radiusY: 15,
color: this.color,
})
popTransform()
},
},
])

onUpdate(() => {
const shapes = get("shape")
shapes.forEach(s1 => {
Expand Down Expand Up @@ -141,3 +179,19 @@ onMouseMove((pos, delta) => {
onMouseRelease(() => {
selection = null
})

onDraw(() => {
if (selection) {
const rect = selection.getShape().bbox()
drawRect({
pos: rect.pos,
width: rect.width,
height: rect.height,
outline: {
width: 1,
color: YELLOW,
},
fill: false,
})
}
})
52 changes: 45 additions & 7 deletions examples/raycastShape.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,50 @@ add([
})
},
getShape() {
// This would be point if we had a real class for it
// This would be point if we had a real class for it
return new Rect(vec2(-1, -1).add(this.pos), 3, 3)
},
},
])

add([
pos(280, 200),
color(BLUE),
"shape",
{
getShape() {
return new Ellipse(this.pos, 80, 30)
},
draw() {
drawEllipse({
radiusX: 80,
radiusY: 30,
color: this.color,
})
},
},
])

add([
pos(340, 120),
color(BLUE),
"shape",
{
getShape() {
return new Ellipse(this.pos, 40, 15, 45)
},
draw() {
pushRotate(45)
drawEllipse({
radiusX: 40,
radiusY: 15,
color: this.color,
})
popTransform()
},
},
])

function rayCastShapes(origin, direction) {
let minHit
const shapes = get("shape")
Expand Down Expand Up @@ -210,30 +248,30 @@ function laser() {
break
}
const pos = hit.point.sub(this.pos)
// Draw hit point
// Draw hit point
drawCircle({
pos: pos,
radius: 4,
color: this.color,
})
// Draw hit normal
// Draw hit normal
drawLine({
p1: pos,
p2: pos.add(hit.normal.scale(20)),
width: 1,
color: BLUE,
})
// Draw hit distance
// Draw hit distance
drawLine({
p1: origin.sub(this.pos),
p2: pos,
width: 1,
color: this.color,
})
// Offset the point slightly, otherwise it might be too close to the surface
// and give internal reflections
// Offset the point slightly, otherwise it might be too close to the surface
// and give internal reflections
origin = hit.point.add(hit.normal.scale(0.001))
// Reflect vector
// Reflect vector
direction = direction.reflect(hit.normal)
traceDepth++
}
Expand Down
71 changes: 36 additions & 35 deletions src/kaboom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
Polygon,
Line,
Circle,
Ellipse,
Color,
Vec2,
Mat4,
Expand Down Expand Up @@ -448,7 +449,7 @@ export default (gopt: KaboomOpt = {}): KaboomCtx => {
// we use a texture for those so we can use only 1 pipeline for drawing sprites + shapes
const emptyTex = Texture.fromImage(
ggl,
new ImageData(new Uint8ClampedArray([ 255, 255, 255, 255 ]), 1, 1),
new ImageData(new Uint8ClampedArray([255, 255, 255, 255]), 1, 1),
)

const frameBuffer = (gopt.width && gopt.height)
Expand Down Expand Up @@ -532,7 +533,7 @@ export default (gopt: KaboomOpt = {}): KaboomCtx => {
class SpriteData {

tex: Texture
frames: Quad[] = [ new Quad(0, 0, 1, 1) ]
frames: Quad[] = [new Quad(0, 0, 1, 1)]
anims: SpriteAnims = {}
slice9: NineSlice | null = null

Expand Down Expand Up @@ -1148,8 +1149,7 @@ export default (gopt: KaboomOpt = {}): KaboomCtx => {
| BitmapFontData
| Asset<BitmapFontData>
| string
| void
{
| void {
if (!src) {
return resolveFont(gopt.font ?? DEF_FONT)
}
Expand Down Expand Up @@ -2171,7 +2171,7 @@ export default (gopt: KaboomOpt = {}): KaboomCtx => {

if (opt.outline) {
drawLines({
pts: [ ...opt.pts, opt.pts[0] ],
pts: [...opt.pts, opt.pts[0]],
radius: opt.radius,
width: opt.outline.width,
color: opt.outline.color,
Expand Down Expand Up @@ -3438,7 +3438,7 @@ export default (gopt: KaboomOpt = {}): KaboomCtx => {
function follow(obj: GameObj, offset?: Vec2): FollowComp {
return {
id: "follow",
require: [ "pos" ],
require: ["pos"],
follow: {
obj: obj,
offset: offset ?? vec2(0),
Expand All @@ -3460,7 +3460,7 @@ export default (gopt: KaboomOpt = {}): KaboomCtx => {
const d = typeof dir === "number" ? Vec2.fromAngle(dir) : dir.unit()
return {
id: "move",
require: [ "pos" ],
require: ["pos"],
update(this: GameObj<PosComp>) {
this.move(d.scale(speed))
},
Expand All @@ -3474,7 +3474,7 @@ export default (gopt: KaboomOpt = {}): KaboomCtx => {
let isOut = false
return {
id: "offscreen",
require: [ "pos" ],
require: ["pos"],
isOffScreen(this: GameObj<PosComp>): boolean {
const pos = this.screenPos()
const screenRect = new Rect(vec2(0), width(), height())
Expand Down Expand Up @@ -3852,24 +3852,24 @@ export default (gopt: KaboomOpt = {}): KaboomCtx => {
const h2 = 1 - h1 - h3
const quads = [
// uv
quad(0, 0, w1, h1),
quad(w1, 0, w2, h1),
quad(w1 + w2, 0, w3, h1),
quad(0, h1, w1, h2),
quad(w1, h1, w2, h2),
quad(w1 + w2, h1, w3, h2),
quad(0, h1 + h2, w1, h3),
quad(w1, h1 + h2, w2, h3),
quad(0, 0, w1, h1),
quad(w1, 0, w2, h1),
quad(w1 + w2, 0, w3, h1),
quad(0, h1, w1, h2),
quad(w1, h1, w2, h2),
quad(w1 + w2, h1, w3, h2),
quad(0, h1 + h2, w1, h3),
quad(w1, h1 + h2, w2, h3),
quad(w1 + w2, h1 + h2, w3, h3),
// transform
quad(0, 0, left, top),
quad(left, 0, iw, top),
quad(left + iw, 0, right, top),
quad(0, top, left, ih),
quad(left, top, iw, ih),
quad(left + iw, top, right, ih),
quad(0, top + ih, left, bottom),
quad(left, top + ih, iw, bottom),
quad(0, 0, left, top),
quad(left, 0, iw, top),
quad(left + iw, 0, right, top),
quad(0, top, left, ih),
quad(left, top, iw, ih),
quad(left + iw, top, right, ih),
quad(0, top + ih, left, bottom),
quad(left, top + ih, iw, bottom),
quad(left + iw, top + ih, right, bottom),
]
for (let i = 0; i < 9; i++) {
Expand Down Expand Up @@ -4017,15 +4017,15 @@ export default (gopt: KaboomOpt = {}): KaboomCtx => {
loop: false,
pingpong: false,
speed: 0,
onEnd: () => {},
onEnd: () => { },
}
: {
name: name,
timer: 0,
loop: opt.loop ?? anim.loop ?? false,
pingpong: opt.pingpong ?? anim.pingpong ?? false,
speed: opt.speed ?? anim.speed ?? 10,
onEnd: opt.onEnd ?? (() => {}),
onEnd: opt.onEnd ?? (() => { }),
}

curAnimDir = typeof anim === "number"
Expand Down Expand Up @@ -4155,7 +4155,7 @@ export default (gopt: KaboomOpt = {}): KaboomCtx => {
}

function polygon(pts: Vec2[], opt: PolygonCompOpt = {}): PolygonComp {
if(pts.length < 3) throw new Error(`Polygon's need more than two points, ${pts.length} points provided`)
if (pts.length < 3) throw new Error(`Polygon's need more than two points, ${pts.length} points provided`)
return {
id: "polygon",
pts,
Expand Down Expand Up @@ -4360,7 +4360,7 @@ export default (gopt: KaboomOpt = {}): KaboomCtx => {
return {

id: "body",
require: [ "pos" ],
require: ["pos"],
vel: new Vec2(0),
drag: opt.drag ?? 0,
jumpForce: opt.jumpForce ?? DEF_JUMP_FORCE,
Expand Down Expand Up @@ -4443,7 +4443,7 @@ export default (gopt: KaboomOpt = {}): KaboomCtx => {

},

update(this: GameObj<PosComp | BodyComp | AreaComp >) {
update(this: GameObj<PosComp | BodyComp | AreaComp>) {

if (game.gravity && !this.isStatic) {

Expand Down Expand Up @@ -4546,7 +4546,7 @@ export default (gopt: KaboomOpt = {}): KaboomCtx => {
let jumpsLeft = numJumps
return {
id: "doubleJump",
require: [ "body" ],
require: ["body"],
numJumps: numJumps,
add(this: GameObj<BodyComp | DoubleJumpComp>) {
this.onGround(() => {
Expand Down Expand Up @@ -4784,7 +4784,7 @@ export default (gopt: KaboomOpt = {}): KaboomCtx => {
let t = 0
let done = false
return {
require: [ "opacity" ],
require: ["opacity"],
add(this: GameObj<OpacityComp>) {
this.opacity = 0
},
Expand Down Expand Up @@ -5506,7 +5506,7 @@ export default (gopt: KaboomOpt = {}): KaboomCtx => {

}

function agent(opts: AgentCompOpt = {}) : AgentComp {
function agent(opts: AgentCompOpt = {}): AgentComp {
let target: Vec2 | null = null
let path: Vec2[] | null = null
let index: number | null = null
Expand Down Expand Up @@ -5686,7 +5686,7 @@ export default (gopt: KaboomOpt = {}): KaboomCtx => {
function boom(speed: number = 2, size: number = 1): Comp {
let time = 0
return {
require: [ "scale" ],
require: ["scale"],
update(this: GameObj<ScaleComp>) {
const s = Math.sin(time * speed) * size
if (s < 0) {
Expand Down Expand Up @@ -5820,10 +5820,10 @@ export default (gopt: KaboomOpt = {}): KaboomCtx => {
// insert & check against all covered grids
for (let x = xmin; x <= xmax; x++) {
for (let y = ymin; y <= ymax; y++) {
if(!grid[x]) {
if (!grid[x]) {
grid[x] = {}
grid[x][y] = [aobj]
} else if(!grid[x][y]) {
} else if (!grid[x][y]) {
grid[x][y] = [aobj]
} else {
const cell = grid[x][y]
Expand Down Expand Up @@ -6602,6 +6602,7 @@ export default (gopt: KaboomOpt = {}): KaboomCtx => {
Line,
Rect,
Circle,
Ellipse,
Polygon,
Vec2,
Color,
Expand Down

0 comments on commit 6fb737f

Please sign in to comment.