|
Post by joeschmoe on Jun 19, 2011 18:26:30 GMT -5
Working on a pretty basic overhead 2D turn-based tank game. Mostly working well but I'm having a problem determining if enemy tanks are visible.
Game maps are hex-based, some hexes are clumps of trees or buildings that, naturally, will block view. The way I've tried to solve it is to plot a shot from one tank to another, using the LERP function that I was shown here, and then sampling at each iteration to see if an invisible "bullet" passes through any hex that would block view. If not, tank(s) become visible.
Problems I'm having: Each side has 20 tanks, so every time a tank moves I check (per above) to see if any tanks have become visible...so 20 checks per tank move. It kind of works but if I set the step in the function too low it seems to jump over some hexes and obviously visually blocked tanks are revealed...if I set the step too high, it takes way too much time for each check.
As usual, I'm betting somebody knows a better, faster way to do this.
Game is nearly finished but this is holding things up.
Thanks!
|
|
lal7777
Posts
if all.knowledge = orange then: seed = mankind.knowledge: grow(seed,time): endif
Posts: 88
|
Post by lal7777 on Jun 19, 2011 23:19:34 GMT -5
Are you using sprites for the tanks? If so, then I'd recommend that you just store the depth that everything is being drawn @ in an array with the lower values (closer to zero) for items behind everything.(like the ground) something like: depth_of_items(number_of_items)
Then just draw the objects(2d sprites) from highest to lowest values using SprSetZOrder function.
If you're not using sprites then I don't know what you should do.
I haven't worked with the sprite library for a while so i hope this helps...
|
|
|
Post by joeschmoe on Jun 20, 2011 0:02:06 GMT -5
Hi,
I am using sprites, but no 3D effect of like a FPS game, just a sort of high, overhead view, very "old school" hex map. So, tanks just sit on top of the hexes and I'm trying to determine what each tank can "see" if there are no hexes that represent trees or buildings between them and any enemy tanks.
I hope this even makes sense.
Thanks for the input.
|
|
|
Post by Adam on Jun 20, 2011 2:06:45 GMT -5
I understand what you are saying and i think something that might help is setting a constant that is used to limit the tanks sight, with that you can use a simple check to see how far the tanks are from one another, then if the distance is less than or equal to your constant it will check the line of sight with your previous form of detection. It isn't really a good fix, but it will definitely cut down on the amount of checks per frame, especially if the tanks are spaced out. Made the picture below to help explain what i mean. and since the img tag refuses to work for me, here: lh5.googleusercontent.com/-FSPA8MKAp0M/Tf7yuqoo9-I/AAAAAAAABxc/o72NTTKO_G0/Untitled.jpg
|
|
|
Post by joeschmoe on Jun 20, 2011 11:57:21 GMT -5
Thanks, Adam. That would boost speed of the check, for sure.
Problem is that my map is only 35x20 hexes, with each hex representing about 30 meters. On that scale, the farthest a line of sight could be is maybe 1500 meters. Maybe I'm trying for too much realism (how realistic can a turn-based game on a map that's a bunch of hexes really be?).
If I have to, I think I could make that work. One problem is that the defending tanks tend to cluster around the center of the map and most of them aren't very far from any edge that invaders are coming from.
I was just testing the program a little more and saw that, sometimes, I could drive my tank right up to an enemy tank sitting on a road and it would disappear, so maybe my "algorithm" is just screwed, though it seems to make sense in my mind. I've been wandering around some other programming sites but haven't found anything helpful.
|
|
|
Post by matthew on Jun 25, 2011 15:34:51 GMT -5
Couldn't you take the A* Pathfinding program that djlinux wrote & modify that to solve your LoS problem?
|
|
|
Post by joeschmoe on Jul 14, 2011 5:24:52 GMT -5
Hi Matthew. I don't want to pretend that I fully understand DJ's code but I do kind of understand the basic concept that A* uses and I'm thinking that it could be used but seems a little complex for this simple problem. In my case I'd just want to go until I hit the wall, then it's no line of sight and the object stays invisible.
The way I'm trying to do it seems, intuitively, easy...project a line between two objects, sample along the way and, if something (say, a building) shows up between them, they can't see each other. But doesn't work that way very well. Sometimes, it's obvious that there's a lot in the way and the two tanks still see each other, sometimes two tanks are in hexes right next to each other with nothing in the way and they don't see each other. Twitchy as hell.
I've played around with it, trying different things, limiting or increasing sampling which changes the speed but not the accuracy. I've gone on coding other parts of the game but it's never going to be right (or any fun) until I get a handle on this (and figuring out how to use Sine, Cosine, etc., which is my next question for later).
Thanks for your help.
|
|
|
Post by DJLinux on Jul 15, 2011 10:35:11 GMT -5
post a picture of your 2D map with the tanks and buildings and the rest of environment objects (if any)
may be you need a "simple" line<->box intersection test. (or 2D line<->rectangle intersection test)
but first let me show your map
Joshy
|
|
|
Post by joeschmoe on Jul 17, 2011 3:23:50 GMT -5
Joshy, Best I can do is attach a screen shot from one of my test maps. Not sure how to embed it into the text. This shot shows about half the tanks revealed but with no obstacles in the way. The rest are behind trees or buildings, or in plain sight but not showing up. Thanks for taking a look. J~ OK- I see now, after posting, how it works with the graphic! Attachments:
|
|
|
Post by joeschmoe on Jul 17, 2011 15:09:11 GMT -5
Sorry, forgot to ask:
"may be you need a "simple" line<->box intersection test. (or 2D line<->rectangle intersection test)"
Please elaborate.
|
|
|
Post by shadow008 on Jul 17, 2011 19:34:10 GMT -5
I have a question:
From the picture you posted, it seems like there is only 6 different rotational directions the tanks can be pointing. Is that so? Or is there full 360 degree rotation on all the tanks? If its just the 6 point rotation, then this could be quite easily solved.
|
|
|
Post by joeschmoe on Jul 17, 2011 19:50:30 GMT -5
Hi Shadow, Pretty much, yes, only 6 directions for the hull of the tanks and normal rotation of the turrets (when a tank targets another, the turret will rotate to correct angle...not functioning properly just yet). Tell me what you have in mind. It's likely better than what I'm trying to do.
|
|
|
Post by shadow008 on Jul 18, 2011 21:28:21 GMT -5
Alright, what I am ASSUMING is that the hexmap is drawn/stored using an array. And the following would go MUCH easier with pictures, but... Here's my idea of what to do: First off, get the position of the tank/turret in the array. Lets say theres a tank at position (5,5). And lets say its pointing straight forward ("up" in the 2D sence). What you do is test the position(s) in the direction its pointing. First you would check the array point (5,6) - which is one space ahead of the tank (in its current direction). If theres nothing at that point, you check (5,7) , (5,8) , (5,9) ... ect. until you either: Hit a wall, hit another tank/turret, or go off the edge of the map. This idea also works if the tanks is pointing some diagonal direction. Just be sure to test the spaces that the tank is pointing at. Such as if that same tank (position (5,5)), were pointing north/west ("up" and to the left), then all you have to do is test the points (4,6) then (3,7), and so on, and use the same algorithm as if it were a single direction. That can all be boiled down into a couple simple for/next loops. So long as there is only 6 points of rotation, this will work very nicely. And using this technique will save you the cost of testing all the tanks to all the other tanks. Good luck with the project. Hope to see some demo's soon
|
|
|
Post by joeschmoe on Jul 19, 2011 15:26:31 GMT -5
Shadow, I like your idea. I wanted to get back to you as quickly as possible and let you know that I'm working on it. I've been trying to implement it by tweaking the code that I've already written but have been running into little (but fatal) compatibility issues. I'm sure you know how that goes. I think I may have to step back and rethink a bunch of stuff, rip out the old code and crappy concepts and just rewrite a lot of it. So much for my lazy approach. Anyway, the basics are there and, if I can stay focused and hammer away at it, I hope to have something that works and is interesting by the end of the month. But, damn...staying focused... Thanks for your help.
|
|
|
Post by shadow008 on Jul 20, 2011 21:49:49 GMT -5
Would this help you? function angle(x1#,y1#,x2#,y2#)
dim angle#,x#,y# x# = x2# - x1# y# = y2# - y1# if x# = 0 then 'dont let it divide by 0 angle# = 0 '... elseif y# = 0 then 'likewise angle# = 90 else angle# = atnd(abs(x#)/abs(y#)) endif if y1# > y2# then if x1# >= x2# then angle# = atnd(abs(y#)/abs(x#)) angle# = angle# + 90 elseif x1# < x2# then angle# = angle# + 180 endif elseif y1# <= y2# then if x1# >= x2# then elseif x1# < x2# then angle# = atnd(abs(y#)/abs(x#)) angle# = angle# + 270 endif endif return angle# endfunction It gets the angle between point A (x1# and y1#) and point B(x2# and y2#). Not sure if its perfect (or fully optimized), but I remember making it from a long time ago to use in my 2D ninja demo. I think it also had one problem where the rotation angle was wrong if the two points were linear along some axis (cant remember which one ) Happy coding!
|
|