Monday, November 14, 2011
I'm really happy with the Widgets I added to GMod. They're working really well. They're fully predicted so they feel smooth and awesome in multiplayer, just the same as in single player.
I started coding them completely clientside. The vision was GUI type controls in a 3D world. I'd pretty much done them and they worked really well - except for one thing. On actually using them, say to move an entity, you'd have to send the command to the server to move it using a console command or something. Which works but it isn't predicted properly. Blah. So I had a good think and I made them entities instead.
This works much, MUCH better. There were a few challenges here though, the biggest being hit detection.
I've never pretended to be good at maths. Those formula images they show on wikipedia to explain what some maths thing means, I have no idea what they are or how to read them. But I can muddle my way through.
The hit detection on the arrow was kind of a bitch. The source engine has a function I wanted to use, "IntersectRayWithOBB". It basically detects a collision between a ray and a rotated box. This is perfect for the arrow because we'd represent the collision with a long box.
Except Valve's function doesn't work properly. Scouring the source for uses shows a few times it's used in functions in Portal, but not to the extent that we're using it. So I gets to thinking. And eventually it hits me.
There's a function called IntersectRayWithBox - which is used pretty much everywhere in the source engine. So it definitiely works. It's the same as we want except the box isn't rotated. So what if we keep the box unrotated but rotate the ray before we send it in. Then we could get the hitpoint using the fraction - which will always be the same.
And I did it. And it worked the first time. I shot finger guns into the air. Peow!
I added a rotating disc too. I wanted this to work so it would collide if you were touching the radius. Obviously there isn't a function for this, so here's how it's done.
First you test your ray against a plane, which is basically in the same position and normal as the quad drawing the circle. If that hits you move onto step 2.
You take the hitpos and you take away the center of the circle. Now you have the distance from the center of the circle.
If it's higher than the radius, you didn't hit the circle, bail out. If it's less, you're inside the circle. So if it's less than radius*0.9 - it's not on the line - so bail out.
Boosh. Also worked first time. More imaginary finger guns shooting all over the place.
I done maths.