Mouse doesn't control images

BlitzPlus Forums/BlitzPlus Programming/Mouse doesn't control images

PCBGuy(Posted 2004) [#1]
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


soja(Posted 2004) [#2]
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 ]


PCBGuy(Posted 2004) [#3]
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


soja(Posted 2004) [#4]
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



PCBGuy(Posted 2004) [#5]
Thanks Soja! It worked flawlessly. You are a great service to this community and I owe you a beer!


soja(Posted 2004) [#6]
How about a Root Beer? =)


PCBGuy(Posted 2004) [#7]
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!)


PCBGuy(Posted 2004) [#8]
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!


soja(Posted 2004) [#9]
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.


PCBGuy(Posted 2004) [#10]
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!