npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@footgun/collide-and-slide-2d

v0.2.0

Published

slide an ellipse/sphere along a series of line segments in 2d

Downloads

77

Readme

collide-and-slide-2d

slide an ellipse/sphere along a series of line segments in 2d

https://user-images.githubusercontent.com/718067/122616942-37590f80-d040-11eb-8038-438310cb74bd.mov

why?

Lately I've been making some 2d platformers in javascript, and while there are practically endless resources for tile-based games, there is very little high quality material for collision detection and response between spheres/ellipsoids and 2d line segments. What is "high quality"?:

  • handles sliding along planes
  • provides robust contact details on collisions
  • does not leak memory
  • easy to understand
  • tiny (200 lines of code not including modules)
  • is data-oriented
  • is purely functional
  • consistent vector/matrix/line representation
  • is a pure es module

So here we are.

Note: this is a fairly high level collision response function. If you're looking for low level 2d collision tests, check out https://github.com/mreinstein/collision-2d

usage

To see a basic collide-and-slide usgage, run:

npm run demo
open http://localhost:3000

This API may seem very odd at first glance, there are many arguments to this function.

Three in particular are worth explaining a little more:

  • lines is an array of actual line segments. Each item in this array is 1 line. A line is simply an array with 2 vec2 items in it (each one is an end point on the line segment)
  • indices is a list of indexes into the lines array to actually use when handling collisions. For example, if indices is [ 2, 7 ] that means lines[2] and lines[7] will actually be used when calculating the collisions.
  • lineCount is the number of entries to use in the indices array. For example, if indices === [ 2, 7, 19, 36 ] and lineCount === 3 then only the first 3 items from indices will be used in calculating the collisions.

This API may seem clunky at first, but it's an intentional design decision because it enables collision handling in a tight simulation/game loop with memory preallocated ahead of time.

import collideAndSlide from '@footgun/collide-and-slide-2d'
import { contact }     from '@footgun/collision-2d'
import { vec2 }        from 'wgpu-matrix'


const lines = [
	// line segment 0
	[
		[ 0, 300], [ 100, 300 ]
	],

	// line segment 1
	[
		[ 100, 300 ], [ 120, 200 ]
	]
]

// contains the index into the lines array which indicates which lines to include when colliding
const indices = [
	0, // refers to line segment 0
	1  // refers to line segment 1
]

const lineCount = 2 // how many items in the indices array to include when colliding

const out = vec2.create()


const position = vec2.fromValues(50, 200) // current position of ellipsoid (center)
const ellipsoidRadius = [ 5, 10 ]         // the width and height radius of the ellipsoid
const moveVel = vec2.fromValues(10, 0)    // the horizontal movement velocity is 10 right
const gravityVel = vec2.fromValues(0, 6)  // the vertical (gravity) velocity is 6 down
const tmpContact = contact()                 // where the collision info is stored

// returns a boolean indicating if any collision happend or not
const collided = collideAndSlide(
    out,
    lines,
    indices,
    lineCount,
    position,
    ellipsoidRadius,
    moveVel,
    gravityVel,
    tmpContact
)

if (collided)
	console.log('collision occurred. contact details:', tmpContact)

// if no collision the entity is moved the full distance specified by gravity and move velocities.
// if collision, it will move and slide along any lines included in the lines list.
// either way, "out" will have this updated position (the ellipsoid's center point.)
console.log('new position:', out)

credits

This code is a re-implementation of Kasper Fauerby's incredible work: http://www.peroxide.dk/papers/collision/collision.pdf

The matrix and vector operations are standardized on Gregg Tavares's library: https://wgpu-matrix.org