Maps
bnorton916Newbie question. Designing an app where the user need to click on an map(say US), but I need to know which state the user clicked. What is the best way to do this? Create 50 images piece them together to form map? Another easier way?
Sr. GuapoThe 50 images wouldn't work... All the images would overlap. You could give each state a slightly diffent color, then when the user clicks the map, get the pixel color at that location. You could then use select case to find the state. That seems to be one of the easiest to me, although it may look a little weird... [:)]
masterboodaYes I agree, the color would be best or you can even use polygons to represent the maps, and then with a little math see where the point is...........but the colors are by far the easiest and most accurate, the only thing you have to worry about though is that some people still run a 16bit color depth, and any color returns, will only be accurate to the 4th one... If you have rgb(0,1,0) it will return(0,0,0) all the way up to (0,3,0), so I would use colors by increments of 4 just to make sure, or not allow them to run the program from a 16bit color depth. DaBooda out...
masterboodaAlso I forgot one thing, If you do not wish your map to look like a pot of melted crayons, you can have two images, Have the one that represents the map, then the one to represent the color coded one, when the mouse moves on the main map, just check the same x and y on the color coded map... I have done this before with a game I made a long time ago, so it is pretty efficient and easy to do, you just have to create 2 maps, instead of 1. DaBooda out...
bnorton916The color idea seem like it would work but that would be alot of different colors to look. The two map idea seems to be an excellent one. I will try that. Thanks for the tip.
VBBRI have seen somewhere the exact same thing you are describing, a US map where the program wants to know where the user clicked. I think I have it on a CD here, but if I'm right the code is for VB4...
bnorton916Hey I am new willing to look at anything. VB4 whatever
Sr. GuapoCan VB6 upgrade the code? I know VB .NET can supposedly upgrade my VB6 code, though I've never got it to work quite right... [:)]
ken_foust@hotmail.comThe color idea is short and sweet, but you may run into problems with people's palettes. Instead, create regions for all 50 states, then all you have to do is see if the point is in the region. I often use this in games that require irregular shaped spaces.
masterboodapalletes? isn't rgb value (0,4,0) the same on all computers? Is there something I do not know about? Honestly, I have never heard of such a thing.... I know that you can set a pallete in the form properties, but that should be the same pallete for all computers... Dabooda out...
bnorton916Regions also sound good. A ny tutorial that you know of that explain regions? Do you create regions in you photo editor or vb? both?
BrykovianI did exactly this type of program back a few years ago (coded in BlitzBasic) ... I setup a series of points (X,Y pixel locations) on the map picture and assigned each point to a state. Basically, the points were located just inside that state's side of the border at major border junctions. I think I had around 300 points defined on the map. The bigger, more rectangular western states needed fewer points than the small, lumpy eastern states ... In any case, when the user was moving his cursor around, I'd get the cursor's X,Y and find the closest point in the list to it -- that state won. It worked a treat. [:D] -Bryk
Sr. GuapoThat sounds much better than my idea... honestly, I've never done this sort of thing, that was just the first idea that popped into my head...
Eric ColemanYeah, you'll have problems if you use the colored image format. Using regions are pretty easy. [code] 'The x,y coordinate are pixel coordinates, not twips. Type POINTAPI x As Long y As Long End Type ' PolyFill() Modes Const ALTERNATE = 1 Const WINDING = 2 Const POLYFILL_LAST = 2 Public Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long Public Declare Function ScreenToClient Lib "user32" (ByVal hWnd As Long, lpPoint As POINTAPI) As Long Public Declare Function CreatePolygonRgn Lib "gdi32" (lpPoint As POINTAPI, ByVal nCount As Long, ByVal nPolyFillMode As Long) As Long Public Declare Function PtInRegion Lib "gdi32" (ByVal hRgn As Long, ByVal x As Long, ByVal y As Long) As Long Public Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long Public Regions(50) As Long 'Init Regions Public Function InitRegions() Dim pnt() As POINTAPI ReDim pnt(0 To 5) pnt(0).x = 31: pnt(0).y = 111 'This should be the outline of a state. pnt(1).x = 60: pnt(1).y = 118 pnt(2).x = 88: pnt(2).y = 111 pnt(3).x = 72: pnt(3).y = 83 pnt(4).x = 59: pnt(4).y = 87 pnt(5).x = 47: pnt(5).y = 83 Regions(1) = CreatePolygonRgn(pnt(0), 6, WINDING) [point data] ReDim pnt(0 To 23) Regions(2) = CreatePolygonRgn(pnt(0), 24, WINDING) [point data] ReDim pnt(0 To 10) Regions(3) = CreatePolygonRgn(pnt(0), 11, WINDING) etc... End Function Public Function UnloadRegions() ' you must unload the regions so that you dont' leak memory. Dim N as Long For N = 1 to 50 Call DeleteObject(Regions(N)) Next Public Function CheckHit(x As Long, y As Long) As Long Dim nt As Long, ht As Long CheckHit = -1 'no hit. For nt = 1 To 50 ht = PtInRegion(Regions(nt), x, y) If ht = 1 Then CheckHit = nt 'return index of region where there is an intersection. End If Next 'function will return -1 if there is no hit, otherwise a number from 1 to 50 End Function [/code]
Sr. GuapoThe reason I liked the color idea was it was so easy. You didn't have to enter a thousand little coordinates to define all the states. This way is much more "professional" and will work alot better than the colors idea though..
masterboodaI am still confused on the different pallete argument... I am probably lacking something in knowledge on this area, but could anybody clarify that for me... I am curious... DaBooda Out...
Eric ColemanWell, if you want 50 different hotspots on the map, then you'll have to use at least 51 different unique colors, one for every state and one for when the user clicks out of bounds. A 24bit color image will have its color count reduced on a system that isn't using 24 or 32 bit color modes. You have to worry about when the user's monitor is in 16, 15, or 8 bit color because you can't be 100% sure that the 51 colors that you picked will remain unique. What could happen is that two similar colors will be approximated to be the same color. Even though windows does have a standard color pallette, it's hardly ever used because windows generally adapts to the current active application. The only time you should use the color-pick method is when you have total control over the color depth of the system, which is generally when you program a game in fullscreen with directx. The color pick method is popular with isometric and hex tile games because you can use extremly different colors becuase you only need 5 of them, and you can also be certain of the color depth of the system. Even in 8bit color mode, you have control of the pallette.
masterboodaOk, I was thinking Color Pallette, not Bit depth, but I guess the bit depth could be considered the pallete also.... but the region is the most compatible method, except it is much harder, but you can I guess make another program on your system that will create the regions according to the color of the states, and then save it to disk and have the map program load it.... That would be the way I go, let the computer do all the work with the regions.... A problem with the regions is I was using them to do sprite collision, and there is a big problem with memory leaks, but even after fixing that, the fix cause them to be really slow.... so checking 50 regions on a slow computer with every pass of the loop, might slow the app down quite a bit... I would suggest making the maps colors complient with 8bit mode, that way you can cover all of your bases.... because even in 8bit color depth you will have enough colors to represent all 50 states.... just make sure you use colors that will be displayed at an 8 bit resolution...If someone cannot run anything but 16 colors then there is something wrong... because even your oldest cards can run at least 256 colors... DaBooda out..
Sr. GuapoYou could make a lookup table by looping through all the colors on your own computer and save it to disk , then you would just have to reference the file in the actual application. The file may be fairly large though... I would recommend the regions, they seem to be the most compatible, and they aren't hard to use, it just takes a little up front time to punch in all the numbers...
masterboodaOk I will let the color thing go...lol.... but I thought of another way, although not best, but easy, was to do the map virtually. What I mean is set up an array that represents all the pixels and just have the number of the state for each pixel.... of course this will be overbearing on the memory, and in essence is a dumb idea... but I just thought that maybe somebody could get some use out of it... DaBooda out...
VBBRIt isn't that hard to define the areas, just a matter of creating a procedure that takes the mouse position on click and sets a new line. Then a spacebar hit or something would close it. (see, I'm at 247 posts now... whats the next ranking name again? Hum I guess I will discover 3 posts from now... [:D])
masterboodaI would use the click and drag method..... but that is just my 2cents.... anymore 2cents and this site will be rich... (god, I have to wait to 250 to go up in rank......lol.... oh and post away VBBR, post away and god speed) DaBooda out...
Sr. GuapoThis isn't going to be in a tight game loop or something is it? If not, the speed issues with the regions that masterbooda mentioned wouldn't really matter. If it is, however, I would recommend using an array/lookup table that stores all the pixels, like masterbooda suggested... PS - VBBR, Guessing from Eric, it is a "gladiator". Sounds cool...
VBBRI won't be a Gladiator... As Eric said once, his rank name is always "gladiator" just because he wants. As he is an admin, he can edit the rank names manually. So he put "gladiator" on his because this is the name of a game he was working on. Indeed his rank name would be "administrator" if he didn't edit it (like Peter).
masterboodaI think eric should change his rank name to BigPappa.... but of course that would be what I would change it too.... I wonder what the next rank after warrior is, and am wondering if another debug session is in order to achieve that rank..... just kidding sr. guapo...lol There is one good use for the array/lookup tables, that is when you are creating a graphic editing program... I used this method when I was manually resizing images for a game, its 10 times faster than grabbing each pixel value from the picture box when you are manipulating it.. This way you grab the image info once, do whatever it is you are doing to it, then update the image with the new values.. DaBooda out...
PeterYeah, regions are the way to go. You know, they dont even really have to be completely exact, you can probably use a dozen lines or so to approximate the area around each state. It wont be perfect but it really will be "good enough". To speed things up you can use a rectangle based collision system to get an approximate area of where the user clicked, which would narrow things down to maybe 2 or 3 states and then use the polygon collision detection to further refine the solution. That would work best. I bet you guys really wish you lived in Canada now, we only have a few provinces to worry about ;)
PeterYou know, it escaped me that we even could change our Administrator tag. I wouldnt know what to change it to though, I'm seriously bad at that sort of stuff. I always liked the VVB ranking system we had with its hidden surprises. You could go from Code Monkey to Arseclown and back with a few posts ;)