Mouse doesn't control images
BlitzPlus Forums/BlitzPlus Programming/Mouse doesn't control images
| ||
OK heres the code of this simple 2D game. Please read the comments carefully. This code works but only draws the first image of the file. The two functions in this code are nessesary to control the image and cannot be overstepped or ignored. The purpose: Once each images is drawn they can be picked up and placed in another location over and over again just like a counter on a game board. Also each image has data attached to them for the next step of the game. The problem: Only one of the images is drawn over and over again. Global arrays don't work. The DrawCounter function will not take a variable. So I only get the first image of the file each time it draws an image. Also the functions make it difficult to add data to these images. Can someone solve this problem. I would gladly email them the image. the image is (5) 32 pixel pictures in a row, thats it. I would like to add more images in the future. So far all attempts failed miserably, so please try this code before sending suggestions. Graphics 1280,1024,16,2 ; Create size of map SetBuffer BackBuffer() Global imgcounter = LoadAnimImage("AAshipcounter_all5.bmp",43,32,0,5) ;Loads the image with 5 seperate images attached in a row Global imgcounter2 = LoadAnimImage("KEshipcounter_all5.bmp",43,32,0,5) ;Currently not used I Would like to eventually add this one and 3 more Global CurrentCounter.FleetCounter = New FleetCounter ;Creates counter to be used as place holder for image CurrentCounter\X = -1 Type Fleetcounter Field X% Field Y% Field Image End Type Dim Board(39,31) ; Dimensions the game board For n = 1 To 5 ;Makes 5 places on the game board that "=1" or True x=x+1 ;Initial x location on gameboard, I can put anything here but its not important for now y=y+1 ;Initial Y location on gameboard Board (x, y)=1 ;Counter 1 ="true" 0 = "False" for use in Function Next While Not MouseHit(3) ;Start of main loop CheckInput() ;Checks for control of moving image DrawCounters1() ;Initially draws image then continues to draw as image is selected to a new location Flip Cls ;Removes last placement of current image Wend End Function CheckInput() ;if Left mouse button is pressed If MouseHit(1) Then ;if there is no current counter If CurrentCounter\X < 0 Then ;if a tile is under the mouse If Board(MouseX()/32,MouseY()/32) = 1 Then CurrentCounter\X = MouseX()/32 Currentcounter\Y = MouseY()/32 Currentcounter\image = imgcounter EndIf Else ;there is already a current counter If Board(MouseX()/32,MouseY()/32) = 0 Then ;move it to the new location Board(CurrentCounter\X,CurrentCounter\Y) = 0 Board(MouseX()/32,MouseY()/32) = 1 CurrentCounter\X = -1 Currentcounter\Y = -1 EndIf EndIf EndIf If MouseHit(2) Then CurrentCounter\X = -1 EndIf End Function Function DrawCounters1() ; Problem:This loop will not allow me to change the image not mater how many times it loops For x = 0 To 39 For y = 0 To 31 If Board(x,y) = 1 Then DrawImage imgcounter, ((x*32)-6),(y*32),2 ;last number determines which counter in image file is drawn MaskImage imgcounter,001,001,001 Next Next End Function |
| ||
The problem: Only one of the images is drawn over and over again. Well that's exactly what you told it to do here. You've told it to always draw the third image (which you even specified in the comment): If Board(x,y) = 1 Then DrawImage imgcounter, ((x*32)-6),(y*32),2 ;last number determines which counter in image file is drawn I think you're making it too hard on yourself. For instance, instead of looking at each square on the board to determine if there's a counter there, then what kind, and then drawing it, your entire DrawCounters() function should be something simple like this: For f.Fleetcounter = Each Fleetcounter DrawImage(imgcounter, f\x, f\y, f\image) Next ...where imgcounter is your 160x32 image (you should change the 43 to 32 in your LoadAnimImage statement, by the way), f\x is the x position of the counter, f\y is the y position of the counter, and f\image is the index (0-4) that tells you which 32x32 section to draw. The trick is that you need to make sure that EVERY time you update the location of a Fleetcounter, you need to change that Fleetcounter's x and y value. As for the Image value, you should set that up (and the initial x and y values) before your main loop, so that's it's already set up when it tries to draw it the first time. I would also lose the implementation in your CheckInput where you check the board. I would check the location of the mouseclick and then go through each Fleetcounter object, comparing x and y values to determine if one was clicked on. The advantage of this, is that you will have a pointer to the Fleetobject that is currently being selected/dropped, and you can easily update the x and y values. Let me know if you have any questions. <EDIT> PS: You should also enclose your code in code tags (<code> put code here </code>) Just change the < to [ and > to ] |
| ||
Thanks Soja ... its starting to make some sense. Actually the functions I got from another designer and not sure how it works exactly. Can you write out the "Checkinput function" you suggested so i can see what you mean. Once I get a sample I'll better understand it. Sorry I'm a newbee and this is a little confusing right off without samples to study. Thanks |
| ||
I would do something like this. Make sure you know what every single line, parameter and function does. If you don't know for sure, then do ask. A good exercise for you now would be: 1) Make the counters have initial random positions on the board 2) Make it so that 2 counters cannot share the same space Graphics 1280,1024,16,2 ; Create size of map Global imgcounter Global CurrentCounter.FleetCounter Type Fleetcounter Field X% Field Y% Field Image End Type InitGame() While Not MouseHit(3) ; Main loop quits on middle mouse button CheckInput() DrawCounters() Flip : Cls Wend End Function CheckInput() If MouseHit(1) Then ; Left click occurred (pick up or drop counter) If CurrentCounter = Null Then ; a counter is not already "picked up", do so ; check to see which counter is being clicked on, if any For f.fleetcounter = Each fleetcounter If (MouseX()/32 = f\x/32) And (MouseY()/32 = f\y/32) Then ; found one CurrentCounter = f EndIf Next Else ; a fleetcounter is picked up, so drop it CurrentCounter\x = (MouseX()/32)*32 ; Make sure it is dropped on grid square CurrentCounter\y = (MouseY()/32)*32 ; Make sure it is dropped on grid square CurrentCounter = Null ; Nothing is "picked up" now EndIf EndIf End Function Function DrawCounters() ; If a fleetcounter is picked up, put it under the mouse If CurrentCounter <> Null Then CurrentCounter\x = MouseX()-16 ; Centered on cursor CurrentCounter\y = MouseY()-16 ; Centered on cursor EndIf ; Draw them all For f.Fleetcounter = Each Fleetcounter DrawImage(imgcounter, f\x, f\y, f\image) Next ; Make sure the clicked counter (if there is one) is drawn last (on top of all the others) If CurrentCounter <> Null Then DrawImage(imgcounter, CurrentCounter\x, CurrentCounter\y, CurrentCounter\image) End Function Function InitGame() SetBuffer BackBuffer() imgcounter = LoadAnimImage("AAshipcounter_all5.bmp",32,32,0,5) CurrentCounter.FleetCounter = Null ; If a counter is clicked on, this will equal it, or else NULL ; Put 5 counters on the board For i% = 1 To 5 f.fleetcounter = New fleetcounter f\x = i*32 f\y = i*32 f\image = i-1 Next End Function |
| ||
Thanks Soja! It worked flawlessly. You are a great service to this community and I owe you a beer! |
| ||
How about a Root Beer? =) |
| ||
Hey, I hate to bother you again and I hope your not tired of me but I am back in the pit I added the following type\data and checked it and other new command lines I added with text commands (Not shown here) and it works great: ************************************************* [code> Type BGcountertype ;BattleGroup counter type Field BGName$ Field Races$ Field WhichBattleGroup$ Field Whichgroup% Field OrigX% Field OrigY% End Type Restore ShipData bData = True While bData Read BGName$ If BGName$ = "STOP" bData = False Else Read Races$ Read WhichBattleGroup$ Read Whichgroup% Read OrigX% Read OrigY% CurrentBG.BGcountertype = New BGcountertype If CurrentBG.BGcountertype <> Null CurrentBG\BGName$ = BGName$ CurrentBG\Races$ = Races$ CurrentBG\WhichBattleGroup$ = WhichBattleGroup$ CurrentBG\Whichgroup% = Whichgroup% CurrentBG\OrigX% = OrigX% CurrentBG\OrigY% = OrigY% Else Text 0,0, "Error BGcountertype could not build a CurrentBG instance of itself" bData = False EndIf EndIf Wend Cls .ShipData Data "Talon" ,"Avari" ,"Fleets" ,1,34,4 Data "Saber" ,"Karn" ,"Fleets" ,2,34,5 Data "Puma" ,"Karn" ,"Fleets" ,3,34,6 Data "STOP" /<code] *************************************************** But I can't get it to work with your init loop. Here is what I tried so far. The following works good! ************************************************** [code] imgcounter = LoadAnimImage(Race$+WhichBattleGroup$+".bmp",43,32,0,5) Race$ = Races$ ;Avari,Aqid,Entog,Repton,Karn WhichBattlegroup$ = WhichBattleGroup$ ;Fleets,Patrols,SConvoys Howmanygroups=Whichgroup%;From 1-5 ;The next area is where the problem begins. I used my fields in type "BGcountertype" to prep the loop but the data doesn't come out as I expect. I thought the "Each BGcountertype" command below, loads every order of the type data as it is in ".shipdata" but it doesn't! For current turn = 1 to 3 ; sample game with 3 turns For i% = 1 To Howmanygroups For CurrentBG.BGcountertype = Each BGcountertype f.fleetcounterorder = New fleetcounterorder f\x = OrigX%*32 ;change "i" to an actual placement f\y = OrigY%*32 ;change "i" to an actual placement f\image = i-1 Next Next Next /[code] ************************************************* The problem is it simply draws the last data set from .shipdata. Also as you can see I would like to loop the whole init loop to replace the counters each turn but the loop adds more counters each turn instaed of using the original ones. Also I still can't figure out how to do this with the <code> thingy, In preview it shows nothing. You can email me a sample clausbohm@... if you want? (P.S. By the way the 43 pixels is nessesary due to the way I built the image as a circle with a little overhang. It looks great on the board!) |
| ||
Soja (Scratch the last post!) I got the types to work in the functions perfectly. All are placed at original locations and I can update the counter amounts and which ones I want any time I want. I can move them just once though. I am having a time with the 'Each" type variable in the check/Draw functions. It lets me make only one pass over all the data, then stops. How can I get to loop through the data again to re-place the counters to another location for each turn of the game? I tried setting up For/Next loops in all locations of the main program and even in the functions themselves but it doesn't work on rereading the data. Any help would be greatly appreciated! |
| ||
Hi again, I'm glad you figured all that out. As for data, if you must read it again, you can use Restore, but generally, data is usually read just once, and then stored in some other data type for later use. |
| ||
Soja, You helped me more then I thought! The 43x32 pixels was screwing up the ability of the mouse to find the counter once it "put it down". I redesigned the counter for 32x32 to match the "board/32" grid. Now everything works out great. So basically all I had to do was to take your sample and replace your f.Fleetcounter with my constructed type "CurrentBG.BGcountertype" and replace all the existing fields in the functions with my fields. I also brought the functions out to the main program. That did the trick! Thanks again. If anyone else has a similar problem with "functions" I suggest to first write all functions as a part of the main program then afterward see if they work as a function! This way any limitations of the functions won't slow or interrupt the pace of the code writing and this suggestion will prevent pulling hair out of your head like I did. This is the end of this thread. If this thread helped anyone else then it was more then worth going through this! |