sbiermanlytle / iioEngine

iio Engine: A JavaScript game engine for HTML5 Canvas
http://iioengine.com
455 stars 81 forks source link

Add collision detection for ioPoly #8

Closed tyilo closed 11 years ago

tyilo commented 11 years ago

Also, shouldn't ioRect inherit from ioPoly?

sbiermanlytle commented 11 years ago

I actually decided to make ioRect and ioPoly two distinct objects since a rectangle can be represented with less data than a polygon: 1 ioVec and 2 Numbers vs. 5 ioVecs

This code is very useful though. I'm going to re-implement these functions, but I'll probably use a lot of this. Thanks for sharing!

tyilo commented 11 years ago

Can't an ioPoly object exist with 3 ioVecs (a triangle)?

Also I think that making an ioRect inherit from ioPoly makes sense, it could just convert its position and size to 4 vertices and pass them to ioPoly.

It would make a lot of code easier as a rectangle is a polygon!

sbiermanlytle commented 11 years ago

Would it make a lot of code easier? I think its the other way around. You can simply the definition of a rectangle by using position, width, and height instead of 4 vertices (5 actually since ioPoly also has a position/origin vector), and this simplifies a lot of computation because we can always assume all edges are parallel.

Since a rectangle is the most frequently used object base, I think it makes sense to have a class that minimizes its data footprint and function computation costs.

Geometric hierarchies don't always translate well to CS architectures. (think Circle vs. Ellipse - basically the same argument I'm making about Rect vs. Poly)

tyilo commented 11 years ago

But ioRect could inherit from ioPoly, but define its own collision detection functions etc. to optimize for the case of two rectangles.

sbiermanlytle commented 11 years ago

But why would it need to inherit a vertex array?

tyilo commented 11 years ago

Because a rectangle has 4 vertices, so why not show it to the developer?

Collision detection between a polygon and a rectangle needs to access the 4 vertices of the rectangle to work probably. You might say that you could just calculate the vertices yourself, however isn't the meaning of this engine to make the life easier for the developer?

Also all things you can do with a polygon, you can also do with a rectangle. So it would reduce duplicated code for adding the same functions to both the polygon and the rectangle.

sbiermanlytle commented 11 years ago

The goal of iio is to ease content creation while maintaining the flexibility to allow any type of app to run as efficiently as possible, so I am always trying to prevent the introduction of unnecessary or redundant data.

Duplicate functions aren't an issue in JS - prototypal inheritance allows you to define a function once then attach it to as many classes as you need.

The functions 'left', 'right', 'top', and 'bottom' exist for ioRect to help developers get boundaries, but if its easier for a developer to work with vertices, nothing is preventing them from defining their rectangles as ioPoly objects.

The reason the ioRect alternative exists is because of scalability. Take an app that has 1000 active rectangle objects. If they were instantiated as ioPolys, the app would need 10,000 distinct Number objects to track positions. If they were instantiated as ioRects, the app would only need 4,000 distinct Number objects. I think 60% less memory usage is worth the additional class.

tyilo commented 11 years ago

Still if you have 1k rectangle objects and just 1 polygon, the collision detection between the polygon and 1k rectangle object 60 times/second, the problem would be to calculate the vertices needed for collision detection, not the amount of memory used.

And if numbers in js are doubles, 10k numbers only fills 80kb memory.

sbiermanlytle commented 11 years ago

That makes sense. But what about apps that don't require collision detection? It may be that those apps never have enough computational needs to warrant saving space like this, but I still like the idea of having minimized data structures available to use whenever its possible.

I'll make a note in the docs about the advantages of using an ioPoly for rectangle objects when constant collision detection is needed, but I do want to leave the simpler rectangle definition in the framework.

tyilo commented 11 years ago

You could make two classes; the current "fast" ioRect and the subclass of ioPoly, the "slow" one. r Maybe rename the current ioRect to ioFastRect or ioRectFast and create the new version of ioRect that inherits from ioPoly.

Alternatively you could make vertices a function and not a property of ioPoly and ioRect, which calculates the vertices for ioRect the first time it is called, caches it, and next time it is called returns the cache. That would only extra memory if the vertices are requested, but it still only calculates them once.

sbiermanlytle commented 11 years ago

How about just implement a rectangle constructor for ioPoly?

It would work to make vertices an optional variable that only gets set if you call the right constructor, but I'm still not sold on having ioRect extend ioPoly, in fact, I'm actually starting to think it might be better to do it the other way around. ioPoly needs to define a rectangle anyway so that it can tell the context where to draw. It seems that ioPoly is just extending all the data that ioRect has... Some restructuring needs to be done (though none of it will affect the user-end). I'll experiment with these options over the weekend.

sbiermanlytle commented 11 years ago

I ended up making ioRect extend ioPoly and creating a new class called ioSimpleRect that can do everything but give you its rotated vertices.

Your collision detection code has been integrated and extended to deal with rotated polygons. All these updates are available in the core on Github.