Allow sensors to detect sides

Benk10

  • Posts: 21
Hi,

For some reason you cannot use "the top/bottom/left/right of actor was hit" with sensors. This is quite counter-intuitive - it means the sensor doesn't sense where a hit occurred - and also makes it difficult/impossible to implement things that would otherwise be easy to do.  For example, suppose you want an actor to pass through a block but different things happen depending on which side it passed through. It really makes no sense that this part of collision logic doesn't work with sensors, which otherwise detect collisions normally.  Please fix this.

update: It also appears that "for each collision point" doesn't work either.

« Last Edit: November 14, 2014, 12:14:30 am by Benk10 »

irock

  • *
  • Posts: 2891
(If you don't want to hear a workaround or already have come up with one, please disregard this post)

What you could do is keep a cache of the coordinates of whatever actors you want to collide with the sensor. When they collide, you can use that information to determine which side it probably entered the sensor from.

Benk10

  • Posts: 21
This would help some.

Does this involve Haxe coding? I'm not afraid of programming, I just don't know how to do it with Stencyl yet.

irock

  • *
  • Posts: 2891
Not necessarily. You could easily do it in design mode. You'll just need to use the "[x/y] of [actor]" block, some number attributes and some conditionals.

Benk10

  • Posts: 21
Ok. The thing is, this wouldn't work for complex shapes, or would at least be really complicated.

Worse, x/y normals don't work for sensors. I know this because I implemented refraction of a photon (only outside-to-in) using the surface normal and Snell's law. The surface normal is arctan2(y-normal of collision, x-normal or collision).
Even though the x and y normals in Stencyl are actually the impulse normals, not surface normals, it seems that this formula does in fact give the surface normal, at least for a ball colliding with a plane.
When trying to implement inside-to-out refraction, i decided to make my prism into a sensor, so that the photons can pass through. But this one change broke the refraction code because the x/y normals of the collision are no longer correct. This is similar to the sensor not being able to detect which side a collision occurred in.

This really baffles me. Sensors should be exactly the same in every respect as ordinary collision except that they do not automatically apply any physics. If this were the case, then my refraction problem, and lots of other use cases, would be easily solved. It seems from the description that sensors are supposed to be this way, but they actually are not. This ought to be fixed.


Benk10

  • Posts: 21
If I understood the engine well enough I could fix it myself, assuming the changes to the sensors doesn't break something else.
The code for the Stencyl engine is available on Github. Does anybody know where to look for sensors and for general collision events?

Actually, I'm not sure if this is a Stencyl issue or a Box2d issue. I'm reading up on Box2d now. If I don't find an answer after a while, I'll ask on the Box2D forums.

update: It appears that sensors in Box2d do not call the pre-collision and post-collision callback functions. In other words,  certain information about the collision or derivable from it is not available.
However, sensors do have the BeginContact and EndContact functions (or else they couldn't sense!) and these do have some physics info.
One difference between Begin/EndContact and Pre/Post solve is that there can be multiple physics events in a single collision, so multiple pairs of begin/end contact callbacks can be called between one pair of begin/end contact.
See here for some more info about how collisions work in Box2d.

So basically, if the info I want is in pre/post solve but not begin/end contact, I am screwed (not really, but the solution would involve modifying the Box2d sensors or else creating a new type of sensor).

« Last Edit: November 16, 2014, 07:20:15 pm by Benk10 »

mdotedot

  • Posts: 1654
Hello Benk10,

In one of my games I had the same 'problem'. I had an actor which I wanted to do my own physics on rather then using the standard.
There were two ways I used to 'work-around' it.

For some objects that needed to move only when I wanted them and normally block the player I used a physics setting.

Apply such a heavy physics setting on the object that it didn't move and that only by applying enough force that it could move.
* Physics - Heaviness: Mass: 40, which is too heavy for standard actor push to move
* Genaral: Normal: No rotation, yes on gravity
* Material: Friction=1, Bounce=0
* In collision event : push sharply at 800

For another object I choose the sensor and used the following blocks to create a region and an according 'enters a region' event:


There was one other technique I used, but it is specific to my platform layout and that is to assign a 'layer'-collision group which I could dynamically alter to switch between different groups so that collision would be active and not-active for some time. I could give you specifics on how I did this, but I assume that it is not usuable for your project.

Hope these work-around might give you some hand.



Best regards from
M.E.
Proud member of the League of Idiotic Stencylers! Doing things in Stencyl that probably shouldn't be done.

Benk10

  • Posts: 21
I thought about the region trick, but the thing is I need some angles when the actor enters/leaves another actor.
Specifically I need the  surface normal of the actor being hit at the point of impact and the collider's angle of incidence with that surface normal. I don't see any way to get these with regions. In fact, i suspect that regions in Stencyl are internally just invisible Box2d sensors.

After reading a bit more on how box2d works and looking at its code, it seems that there is a data structure called a manifold that is generated by colliding objects that contains information like where the collision occurred. Sensors do not create manifolds. This would explain why, for a sensor, in Stencyl you cannot get the x-y normal of collisions or check which side the collision occurred on.
There might be a solution that involves modifying the box2d code so that sensors do create manifolds but nothing is done with them. I'm not sure if this is possible yet; I'll have to study the code some more.

sixpackli

  • *
  • Posts: 1
Just wasted a couple of hours figuring out that x,y co-ordinates and the for each collison point block does not work with sensors. If this isn't going to be fixed it really needs to say so in the documentation.