1
0
Fork 0
Browse Source

fix: repair collision detection

Signed-off-by: André Jaenisch <andre.jaenisch@posteo.de>
combat-scorched-earth-from-outer-space
André Jaenisch 10 months ago
parent
commit
4f857eeb10
Signed by: ryuno-ki
GPG Key ID: 5A668E771F1ED854
  1. BIN
      js13kgames.zip
  2. 12
      src/js/app.js
  3. 68
      src/js/collisions.js
  4. 50
      test/js/collisions.test.js
  5. 8
      types/collisions.d.ts

BIN
js13kgames.zip

Binary file not shown.

12
src/js/app.js

@ -1,4 +1,4 @@
import { testBoundaries, testCollision } from './collisions.js'
import { testCollision } from './collisions.js'
import { drawShape } from './draw.js'
import { makeAstronaut, makeBottomBoundary } from './world.js'
@ -54,14 +54,8 @@ function tick () {
drawShape(context, bottomBoundary)
drawShape(context, astronaut)
if (testBoundaries(bottomBoundary, astronaut)) {
if (testCollision(bottomBoundary, astronaut)) {
throw new Error('Game Over!')
}
}
if (astronaut.C.y - astronaut.H > canvas.height) {
throw new Error('Should have been caught earlier!')
if (testCollision(bottomBoundary, astronaut)) {
throw new Error('Game Over!')
}
window.requestAnimationFrame(tick)

68
src/js/collisions.js

@ -31,7 +31,6 @@ export function testCollision (shape1, shape2) {
const vertices = [...vertex1, ...vertex2]
if (testIntersection(vertices)) {
console.debug(shape1, shape2, vertices)
throw new Error('Intersection!')
}
})
@ -44,33 +43,6 @@ export function testCollision (shape1, shape2) {
return false
}
/**
* Computes all vertices as point-direction pairs.
*
* @param {Shape} shape
* @returns {Array<Array<Vector2D>>}
*/
function getVertices (shape) {
return [
[
shape.X[0],
subtract(shape.X[0], shape.X[1])
],
[
shape.X[0],
subtract(shape.X[0], shape.X[3])
],
[
shape.X[2],
subtract(shape.X[2], shape.X[1])
],
[
shape.X[2],
subtract(shape.X[2], shape.X[3])
]
]
}
/**
* Checks for intersection of two lines given by v1 and v2, resp. v3 and v4.
*
@ -78,15 +50,41 @@ function getVertices (shape) {
* @returns {boolean}
* @see {@link https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection#Given_two_points_on_each_line_segment}
*/
function testIntersection ([v1, v2, v3, v4]) {
const tdivident = determinant(subtract(v1, v3), subtract(v3, v4))
export function testIntersection ([v1, v2, v3, v4]) {
const tdivisor = determinant(subtract(v1, v2), subtract(v3, v4))
const t = tdivident / tdivisor
const udivident = determinant(subtract(v2, v1), subtract(v1, v3))
if (tdivisor === 0) {
// Parallel lines never intersect
return false
}
const udivisor = determinant(subtract(v1, v2), subtract(v3, v4))
const u = udivident / udivisor
console.debug(t, u)
return (t <= 0 && t <= 1) || (u <= 0 && u <= 1)
if (udivisor === 0) {
// Parallel lines never intersect
return false
}
const tdivident = determinant(subtract(v1, v3), subtract(v3, v4))
const udivident = determinant(subtract(v2, v1), subtract(v1, v3))
// + 0 turns -0 into +0
const t = tdivident / tdivisor + 0
const u = udivident / udivisor + 0
return (t >= 0 && t <= 1) && (u >= 0 && u <= 1)
}
/**
* Computes all vertices as point-direction pairs.
*
* @param {Shape} shape
* @returns {Array<Array<Vector2D>>}
*/
function getVertices (shape) {
return shape.X.map(function (vertex, index) {
return [
vertex,
shape.X[(index + 1) % 4]
]
})
}

50
test/js/collisions.test.js

@ -1,6 +1,10 @@
import { expect } from 'chai'
import { testBoundaries, testCollision } from '../../src/js/collisions.js'
import {
testBoundaries,
testCollision,
testIntersection
} from '../../src/js/collisions.js'
import { RigidShape } from '../../src/js/shape.js'
import { Vec2 } from '../../src/js/vector.js'
@ -19,6 +23,22 @@ describe('Collisions', function () {
})
})
describe('testIntersection', function () {
it('should test for intersecting line segments', function () {
// Arrange
const v1 = Vec2(97.5, 97.5)
const v2 = Vec2(-5, 0)
const v3 = Vec2(94.5, 97.5)
const v4 = Vec2(0, -5)
// Act
const haveIntersectingLineSegments = testIntersection([v1, v2, v3, v4])
// Assert
expect(haveIntersectingLineSegments).to.equal(true)
})
})
describe('testCollision', function () {
it('should test in depth for collisions', function () {
// Arrange
@ -31,11 +51,35 @@ describe('Collisions', function () {
// Assert
expect(haveCollided).to.equal(true)
})
it('should test for no contact', function () {
// Arrange
const shape1 = makeShape({ centre: Vec2(100, 100) })
const shape2 = makeShape({ centre: Vec2(94, 100) })
// Act
const haveCollided = testCollision(shape1, shape2)
// Assert
expect(haveCollided).to.equal(false)
})
it('should test for direct contact', function () {
// Arrange
const shape1 = makeShape({ centre: Vec2(100, 100) })
const shape2 = makeShape({ centre: Vec2(95, 100) })
// Act
const haveCollided = testCollision(shape1, shape2)
// Assert
expect(haveCollided).to.equal(true)
})
})
})
function makeShape () {
const center = Vec2(500, 200)
function makeShape ({ centre } = {}) {
const center = centre || Vec2(500, 200)
const friction = 20
const restitution = 0
const mass = 400

8
types/collisions.d.ts vendored

@ -16,5 +16,13 @@ export function testBoundaries(shape1: Shape, shape2: Shape): boolean;
* @returns {boolean}
*/
export function testCollision(shape1: Shape, shape2: Shape): boolean;
/**
* Checks for intersection of two lines given by v1 and v2, resp. v3 and v4.
*
* @param {Array<Vector2D>} vertices
* @returns {boolean}
* @see {@link https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection#Given_two_points_on_each_line_segment}
*/
export function testIntersection([v1, v2, v3, v4]: Array<Vector2D>): boolean;
export type Shape = import('./shape').Shape;
export type Vector2D = import('./vector').Vector2D;

Loading…
Cancel
Save