Jump to content

Are there other ways of achieving this? (aka "Collisions, updates, and you!")


sjg
 Share

Recommended Posts

I'm working on finding a better way to find out if two entities are (a) close to each other and (b) facing each other. Initially I thought it was a good idea to bolt a trigger onto them, offset on the local Z-axis and have each entity "carry" one around in front of them but I've now noticed that the physics timestep doesn't line up with the UPS, so if the framerate goes above 60 or so, my game loop doesn't detect a collision during some of those frames. It's probably an overly expensive way of calculating it as well.

 

Ideally I'd like to have some simple detection happening that ticks those first two boxes above, but which I can put in my game loop so it's called once each App::Loop frame, rather than with a collision hook which is only called every physics update. I'm reasonably new to programming (a year or so) and haven't done much in the way of game stuff before, so there are a lot of concepts I'm ignorant about, but is raycasting something I should be reading up on to help me with this or am I barking up the wrong tree?

Link to comment
Share on other sites

Maybe just try a simple raycast via World:Pick()or Entity:Pick()? Granted the API Reference recommends a World:Pick() over an Entity:Pick() because it would be faster, but both give the ability for you to control the length of the raycast which you can indirectly use as a way control how close you have to be to trigger a conversation.

  • Upvote 1

Win7 64bit / Intel i7-2600 CPU @ 3.9 GHz / 16 GB DDR3 / NVIDIA GeForce GTX 590

LE / 3DWS / BMX / Hexagon

macklebee's channel

Link to comment
Share on other sites

Couldn't you just check the distance between the two entities, and then get the dot product of their directions? The entity Z direction is returned by Transform:Normal(0,0,1,entity,nil).

  • Upvote 2

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

Whew! So far I've done what Josh recommended and I'm also reading up on how to use Pick()... still trying to get my head around it, as I've never really used anything like it before.

 

Josh's suggestion works well, but I'm missing something in my implementation of it because it returns a lot of (not false) positives (such as in the case of two entities standing back to back - they're close and facing opposite directions, after all). It's probably simple to narrow it down, it's just not apparent to me right at this second.

 

Thank you for the swift suggestions! You'll make a man of me yet.

Link to comment
Share on other sites

I did it! Not only that, but also in the most immature way possible.

 

First I thought trigonometry could help me... somehow. I'm horrible at maths, so I abandoned that idea. Then I remembered there was more than one way to skin a cat. I went back to the old idea of bolting a pivot onto the front of an entity, but this time I used two empty ones, slightly offset on -x and +x, and I did a check to see which was closest to the target entity: the left pivot, the right pivot, or the main pivot; this told me in a very cheap and nasty way if the target entity was in front or behind the player (or whatever entity for that matter). Couple that with the priceless "facing directions dot product" tip, and I now have something that can be used every game loop frame.

Link to comment
Share on other sites

The dot product returns 1.0 when two vectors are the same and -1.0 when they are opposite (or the reverse, I can't remember!). If the dot product is zero, then the vectors are at 90 degrees from each other.

 

So your test would be something like if dot()<-0.5 the entities can see each other, or possibly if dot()>0.5.

  • Upvote 2

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

Yeah, I checked it more or less as such, but the thing I hadn't taken into account was that if they're standing back to back it's also -1. That's why I had to also chech which side of the player was closest to the other entity. As I mentioned, I'm not much chop when it comes to mathematics, I tend to MacGyver my way through that area. That's been slowly changing since I got into programming; I come from a musical background.

 

Here's what I tested for after I worked out which entity was closest to the player. I don't usually comment my code but there is a shoutout.

 

if (closest != nullptr) {

double testIfFacing = facingDirection.Dot(closest->getFacingDirection()); // 1 same, -1 opposite... cheers once again, josh

offset = body->getChestPivotLeft()->GetPosition(true) - closest->getBody()->getMainPivot()->GetPosition();
distance = std::sqrt(std::pow(offset.x, 2) + std::pow(offset.y, 2) + std::pow(offset.z, 2));

offset = body->getChestPivotRight()->GetPosition(true) - closest->getBody()->getMainPivot()->GetPosition();
double distance2 = std::sqrt(std::pow(offset.x, 2) + std::pow(offset.y, 2) + std::pow(offset.z, 2));

bool distanceTest = Leadwerks::Math::Min(distance, distance2) < closest->getDistanceFromPlayer();

if (testIfFacing <= -0.6 && distanceTest) { // tweak this
setConTarget(closest);
}

}

 

edit::WHOA, just caught a massive bug. Glad I pasted that in a public forum. Fixed. Whew.

Link to comment
Share on other sites

There is a command to get the distance between two entities, which will make your code above a bit simpler:

http://www.leadwerks.com/werkspace/page/api-reference/_/entity/entitygetdistance-r800

 

This is the source code for the Vec3::Dot command:

float Vec3::Dot(const Vec3& v)

{

return x * v.x + y * v.y + z * v.z;

}

  • Upvote 1

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

I use GetDistance to check when two characters are close and I use Point to make one face the other. Dead simple.

 

You meant you do this?

  • store the current rotation
  • turn the source to point at the target
  • log the rotation
  • compare original rotation to rotation to target
  • turn back to original heading so everthing appears as it was for the screen refresh?

 

If that's what you mean then that is what I ended up recently to do an enemy FOV check, though I suspected that using 'proper' math, vectors and trigonometry may be faster and potentially more useful for me to understand.

 

I stumbled one or two articles I think but I've yet to read through it properly and get a grip of this.

 

I suspect it will all be terribly useful for constructing a 'radar' or in-game dynamic map.

Link to comment
Share on other sites

In my game I needed a character to warn my main character not to go into a nearby castle because it was dangerous.

I used the GetDistance command to check when the character was close to the main character and I used point command to make character face main character when at the required distance. Nothing more. But maybe you need some other requirements.

  • Upvote 1

amd quad core 4 ghz / geforce 660 ti 2gb / win 10

Blender,gimp,silo2,ac3d,,audacity,Hexagon / using c++

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...