Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length

 
Advanced search

1066901 Posts in 43551 Topics- by 35595 Members - Latest Member: OneSidedDice

November 26, 2014, 04:08:44 PM
TIGSource ForumsDeveloperTechnical (Moderators: Glaiel-Gamer, ThemsAllTook)Pointing to an offscreen point!
Pages: [1]
Print
Author Topic: Pointing to an offscreen point!  (Read 328 times)
Quarry
Level 10
*****



View Profile WWW
« on: May 09, 2013, 11:23:04 AM »

http://i.imgur.com/5MxciYH.png

I'm trying to achieve this for 2D but I have no idea how. I tried limiting the positions to screen positions with if above x max set to x max etc but that doesn't give me results on the gray line

How do the fastest way?
Logged

 
z84c00
Level 0
***


View Profile
« Reply #1 on: May 09, 2013, 11:35:37 AM »

Google 'line clipping' and you should get a wealth of solutions. Bunch of different ways to do it but it boils down to taking the deltas, a division and two multiplies.

Hope this helps...

-Z8
Logged
Quarry
Level 10
*****



View Profile WWW
« Reply #2 on: May 09, 2013, 11:43:56 AM »

Thanks!
Logged

 
ThemsAllTook
Moderator
Level 10
******


Alex Diener


View Profile WWW
« Reply #3 on: May 09, 2013, 12:15:11 PM »

I was trying to solve this with line intersection tests and projection, but then I realized there are some easy shortcuts you can take since you know the screen edges are rectangular and axis aligned. You just need to find the closest nonnegative screen edge (if any) and interpolate along the line from player to target. Simple implementation (C-like pseudocode, untested):

Code:
point2f edgePosition(point2f player, point2f target, bool * outIsOffscreen) {
float distanceLeft   = (screenLeft   - player.x) / (target.x - player.x);
float distanceRight  = (screenRight  - player.x) / (target.x - player.x);
float distanceTop    = (screenTop    - player.y) / (target.y - player.y);
float distanceBottom = (screenBottom - player.y) / (target.y - player.y);

if (distanceLeft > 0) {
if (distanceTop > 0 && distanceTop < distanceLeft) {
// Top side is closest
*outIsOffscreen = true;
return player + (target - player) * distanceTop / (target.y - player.y);
}

if (distanceBottom > 0 && distanceBottom < distanceLeft) {
// Bottom side is closest
*outIsOffscreen = true;
return player + (target - player) * distanceBottom / (target.y - player.y);
}

// Left side is closest
*outIsOffscreen = true;
return player + (target - player) * distanceLeft / (target.x - player.x);
}

if (distanceRight > 0) {
if (distanceTop > 0 && distanceTop < distanceRight) {
// Top side is closest
*outIsOffscreen = true;
return player + (target - player) * distanceTop / (target.y - player.y);
}

if (distanceBottom > 0 && distanceBottom < distanceRight) {
// Bottom side is closest
*outIsOffscreen = true;
return player + (target - player) * distanceBottom / (target.y - player.y);
}

// Right side is closest
*outIsOffscreen = true;
return player + (target - player) * distanceRight / (target.x - player.x);
}

if (distanceTop > 0) {
// Top side is closest
*outIsOffscreen = true;
return player + (target - player) * distanceTop / (target.y - player.y);
}

if (distanceBottom > 0) {
// Bottom side is closest
*outIsOffscreen = true;
return player + (target - player) * distanceBottom / (target.y - player.y);
}

// Target is onscreen
*outIsOffscreen = false;
return target;
}

It's a bit messy and redundant because there isn't really a good way to structure the control flow, but should do the trick. I figured you might want to draw something different if the target is offscreen than if it's within the player's sight, so I included the outIsOffscreen parameter for convenience.
Logged
JakobProgsch
Level 1
*



View Profile Email
« Reply #4 on: May 10, 2013, 05:20:11 AM »

seems overly complicated... shouldnt something like this do it?
Code:
point2f edgePosition(point2f start, point2f end) {
   point2f diff = end-start;
   point2f bound;
   bound.x = diff.x>0?screenRight:screenLeft;
   bound.y = diff.y>0?screenBottom:screenTop;
   float s = min(1, min((bound.x-start.x)/diff.x, (bound.y-start.y)/diff.y));
   return start + s*(end-start);
}
Logged

ThemsAllTook
Moderator
Level 10
******


Alex Diener


View Profile WWW
« Reply #5 on: May 10, 2013, 11:09:08 AM »

Clever! That's definitely much better. I had a feeling there was an easier way, but couldn't quite wrap my head around it.
Logged
TheLastBanana
Level 8
***



View Profile WWW Email
« Reply #6 on: May 10, 2013, 12:09:13 PM »

I looked at this topic the other day and thought "come on, that's not even a difficult problem." Today, I had to actually implement this for my game and was halfway through writing a solution similar to ThemsAllTook's, when I realized that getting an elegant solution is the hard part. Cheesy

Thanks, JakobProgsch. That's a way better method.
Logged

Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic