Rotating collision boxes

Started by
2 comments, last by MrRowl 9 years, 6 months ago

Hello
Let me start with a simple explanation of my collision system. Every object in my game is just a sprite with a defined vertexes. For example a triangle block is made of 3 vertexes. The collision between a ball (that is my player) and the triangle is done by calculating shortest distance between every edge of the triangle, and every edge is made of 2 vertexes. I am sure you know what I mean.

Until now everything was fine, but now I want to rotate some of the objects. And here comes the problem: when rotating the sprite, how to calculate new positions for for the vertexes.

2cgijk1.png

Picture as an example. Red dots are the vertexes for calculating collision. Blue dot represents anchor, around which the sprite rotates (so the sprite rotates around its center). (1) is the object without any rotation. After the rotation i want to move the vertexes so they fit the actual display (2), and not stay as they stood before (3). I would appreciate any help smile.png

##EDIT##
I was messing around with a piece of paper and probably found a solution. Every vertex <-> center distance is const. Assuming that I increase angle by 5 degrees i can use basic trigonometry (sinus and cosinus) to calculate new X and Y for every vertex.

Correct me if I am wrong. Also I don't know how calculating sin/cos every frame would consume the processing power. I am afraid it would be pretty devastating for the processor (creating a mobile game). Another idea is to keep x/y offsets for every vertex, for every degree, for every type of object. Like a mini-database. But... duh.. i hope there is a better solution..

Advertisement

Also I don't know how calculating sin/cos every frame would consume the processing power. I am afraid it would be pretty devastating for the processor (creating a mobile game).

First question: what happened when you tried it? That is, a general rule for any app development is to optimize only when it's needed. Do you need to improve your method for performance purposes?

IF your app's performance needs to be improved, the process for determining where your code needs to be revised is called profiling. The possibility exists that the calculations you think may be the culprit may, in fact, not be where your app is inefficient. There's no sense in rewriting a section of code for optimization if that's not where optimization is needed. In your case, for instance, better gains may be had by culling collision possibilities with AABBs or bounding spheres. It may turn out that, by doing so, your sine/cosine functions calls may only be needed once per update and you needn't optimize that code.

If you're concerned with your app's performance, you should learn the profiling process. There are tools available for doing just that which you may be able to find by googling for something like (e.g.) "mobile apps profiling." For mobile apps, you may also be concerned with battery consumption, and the results of a google search should provide information in that regard, also.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Just recalculate the vertices with the new angle - but you need to keep track of your original vertices!

or

Add two unit vectors to every sprite which defines the rotation for X and Y and use these for the axis-test based on projection (Separating Axis Theorem). Calculating the local projection is done like this:


function RectShape(x, y, w, h) {
  this.pos = new Vec2(x, y);
  this.size = new Vec2(w, h);
  this.axis = [new Vec2(1, 0), new Vec2(0, 1)];
}

RectShape.prototype.project = function (axis) {
  var p = Math.abs(axis.dot(this.axis[0])) * this.size.x * 0.5 + Math.abs(axis.dot(this.axis[1])) * this.size.y * 0.5;
  return new Vec2(-p, p);
};

When you rotate your sprites, you just need to update this two unit vectors:


this.axis[0].set(Math.cos(angle), Math.sin(angle));
this.axis[1].set(-Math.sin(angle), Math.cos(angle));

Dont worry about performance, cos and sin are fast... most languages use CPU optimizations for that.

If you convert your vertices into world space and then do the collision checks between the player and the shape, you will need to transform N vertices (N = 4 for your rectangle)

If you convert your player position into the space of the object you only need to do one transformation. Then if there's intersection you just need to do one (or a few) transformation(s) to get the result back into world space.

If your sprites are represented by more than a few vertices, that's a big saving.

This topic is closed to new replies.

Advertisement