| 08-20-2010, 07:01 PM | #1 |
Is there an easier way to find out whether a unit is on a rect, rather than vice versa? My current plan is to use rects to track my grid-based movement. I have a 16x16 rect rectangle and I need to find out where units are on the "grid". There's the function RectContainsUnit() but I need to find out whether a unit is on a rect, not whether the rect has the unit in it. While I could use it... I'd have to call this boolean 256 times. It'd get even worse as the grid gets bigger. I planned on having larger grids such as 40x40. I'm not calling that 1600 times. That's kinda ridiculous especially considering that I'd have about 4000 lines of code. lol This situation leads me to believe that I have to make my own function. However, I don't really where to start. I thought that naming the rects would allow me track them via their coordinate names by using string references, but I don't think it's possible with rects. If it is, please tell me how to do that, because I fear the worse, which is the first idea. The other idea I had on how to make my life easier is to get the X and Y coordinates of the (00, 00) and find out the distance between grid spaces. I've done that and it's approximately 250 horizontally and vertically (no need for diagonals, it makes more complicated than it should be). Then, I could use those to track where each grid space is... but I still end up having 256 stored variables. I have dimmed circles of power to indicate grid spaces. Another idea I thought of was tracking each circle of power because it is also a unit. However, unlike units that you can control, the circles of power are just dummy units that act as indicators for grid spacing, so they stay stationary. Wherever there's a circle of power, there's a rect that shares the same exact X/Y coordinates. This doesn't really work though because we can't detect units are walking on top of other units... There has to be an easier way, right? Currently, all of the rects are labeled by their grid coordinates, so (00, 00) is the name of the rect on the bottom left corner, (15, 15) at the top right, etc. I know that no matter what, I'll end up having to deal with 256-somethings, but I want to find a way that makes this as painless as possible. Please help. ![]() |
| 08-20-2010, 07:42 PM | #2 |
You can use one region per rect (the jass type not the gui one) and the enter region event, assuming your rects don't share any points between us. And use a struck linked to your unit which contains the region which the unit is currently inside it. Ofc since we don't have GetTriggeringRect but GetTriggeringRegion you will also have to link your rects with the associated region. |
| 08-20-2010, 08:01 PM | #3 |
Yes, that's right. None of the 256 rects share any coordinate points. One of the things I had thought of previously was using the Enter Region event as well. The only problem with the Enter Region event is the fact that preplaced units do not count as "entering a region". I could get rid of them, since I have everything necessary to recreate them with identical stats. I wonder if I can abuse the Enter Region event. If I move a unit out of it, then move it back in an instant inside the rect it was in, it should still trigger the event because it technically entered and did not start in the space as with preplaced units. Hmm... That's interesting an idea... I should try that. EDIT: Oh, wait. You're right. There is no GetTriggeringRect. Uugh... Does this mean I'll end up with 256 regions and rects? lol I did made this as a potential solution to my problem: JASS:function GetUnitOnGrid takes unit c returns rect local group g = CreateGroup() local rect r local real x = GetRectCenterX(gg_rct_00_00) local real y = GetRectCenterY(gg_rct_00_00) local integer xm = -1 //horizontal space multiplier local integer ym = 0 //vertical space multiplier local real dx = x + GetRectCenterX(gg_rct_00_01) local real dy = y + GetRectCenterX(gg_rct_00_01) local boolean b = false loop if xm == 15 then set xm = -1 set ym = ym + 1 endif if xm == -1 then set xm = 0 else set xm = xm + 1 endif call GroupEnumUnitsInRange(g, x+dx*xm, y+dy*ym, 100., null) if FirstOfGroup(g) == c then set b = true endif exitwhen b == true endloop return Rect(0., 0., 0., 0.) endfunction That's great and all, but how do I go from coordinates to a rect that the unit is in? Even then, I don't know how fast it will go through 256 coordinates. |
| 08-20-2010, 09:08 PM | #4 |
I see no problems using as many regions as rects, but if you have problems on how to use them friendly and efficiently, let me know. |
| 08-20-2010, 09:43 PM | #5 |
Yeah. Am still thinking of work arounds instead of work throughs. I won't be able to work on this again until Sunday afternoon, though. I'll keep thinking about it, of course. I found something that might work. I started up a test using a rect array and storing numbers based on their UnitUserData. Since this map is a project demonstration for a Grid-Based Strategy RPG, I hope to add a story to it as well. I can do cinematics, but I can't work on them until this is done. It's so tempting because I know how to do that and am stuck with this. Haha |
| 08-21-2010, 01:24 AM | #6 |
There are many easier ways to do this. Working with static rects is the wrong approach. First of all, you said this was a grid. That means that it is easy to deduce the field a unit is on from the unit's coordinates alone, no need to loop through all the rects, just convert the unit coordinates to grid coordinates (terrain grid points are 128.0 units apart). You don't need to bother placing circles of power/rects in the editor at all, just use triggers to generate them for you. Again, if it's all a simple square grid, that's a piece of cake. Also, consider whether you need rects and/or circles of power at all. I can not go into more detail unless you post more details about what you are trying to do. However, if you are placing grid stuff manually in the editor, you are definitely doing it wrong. |
| 08-21-2010, 07:00 AM | #7 |
Oh, good. I actually hoped that I would be able to avoid the rect/region thing all together. It'd definitely save me loads of time. I'm going to leave it there, though. Technically, I can still use them if I want to. If not, I can throw them out whenever. I'd actually prefer making them via the trigger editor so I make them and keep track of them as they're being made on the spot rather than making all of them and them trying track all of the points. The circles of power are dummy units to indicate points on the grid, but they are there for a functional reason. The rects I can do without and would prefer to avoid, but the circles of power have an initial transparency value when no action is being taken any unit. What I exactly need from the grid is being able to find out where the unit is on the grid so I can issue move commands to it and have that unit walk to places according to the grid. The rest follows naturally (attacking, spells, etc.). When orders are issued to units, the CoP's light up to show how far the unit can move and what you can do. To give you a better idea of what players will see, I'll have to take screenshots to simulate the events. However, that will have to wait until Saturday afternoon. EDIT: Oh, yeah. And, thank you for your interest, Anitarf. |
| 08-21-2010, 09:29 AM | #8 |
It depends the unit movement, by trigger (i mean SetUnitX/Y/Position) or not, the accuracy you need and when/how many times you need to know where the unit is. Ofc i wasn't talking about creating rects with the terrain editor but with the trigger editor. Can be done with a simple loop if it's just a grid. But again it all depends what you want to do exactly, you could have no utility of rects. |
| 08-22-2010, 11:55 AM | #10 |
why make clumsy workarounds with buffs? Just store the moving unit to a variable. |
| 08-22-2010, 03:47 PM | #11 |
Hey. I'm half-thinking of this as I go. I didn't say that I had finalized any decision, yet. I want moving and actions to be smoother than Soul Chess. I know that much for sure. |
| 08-24-2010, 04:15 AM | #12 |
Cool. After a few days, got it working. No need for rects or regions, either! Now I can get rid of them. Thanks for putting me in the right direction, guys. |
| 09-02-2010, 03:50 AM | #14 |
Well, the range enum will pick all units in a circular area; therefore, SquareRoot(dx*dx+dy*dy) will be less than or equal the unit's move range, which is 5 in your case. As a result, points up to seven moves away (4 in the x direction and 3 in the y direction) are considered to be in range. What you want is for dx+dy to be less than or equal to the unit's move range; you need to add that condition to your group enum filter, which will require you to store the origin coordinates to global variables so you can calculate dx and dy in the filter. |
