daft 2d graphics question

BlitzMax Forums/BlitzMax Beginners Area/daft 2d graphics question

QuietBloke(Posted 2005) [#1]
I needed something to do to get into coding in BlitzMax so I figured I would write yet another space invaders clone. It was all going well till I get to the bit where I have to apply damage to the shields when a bullet or bomb hits them.
Each shield is a TImage. Im probably being a div but I cant see how I can delete a group of pixels from the shield image. Initially I just thought I would have a small explosion bitmap and I could just remove my explosion image from my shield image. But looking through the help I cant see how I can do it.
So.. please.. can someone explain to me how I am supposed to achieve what Im after ?

Thanx


ImaginaryHuman(Posted 2005) [#2]
a) there are no buffers that you can intermix

b) you would be better off having several smaller images that you combine to make a shield and then remove one image at a time to represent a damage being made


JazzieB(Posted 2005) [#3]
Or you could use LockImage/UnlockImage to remove pixels with WritePixel (you can't draw to a locked image). Not sure if there's a speed issue here, but it should be plenty fast enough for your purposes.


Dreamora(Posted 2005) [#4]
There is a very bad speed drop if you do LockImage / UnlockImage. In this case you better stay on pixmap with the graphic if it happens often. (as lockimage will convert to image and back where back is the slowest part in the whole thing)


QuietBloke(Posted 2005) [#5]
ok.. here is another weird problem Im getting. Im probably juts doing things wrong.
At the start of the program I loadimage('filename') into a Tpixmap.
I have a shield type which has an TImage field which I use LoadImage ( pixmap, DYNAMICIMAGE ) to populate it in the New() method.
When a shot hits the shield I then do a LockImage to a pixmap. I write some blank pixels then unlock it.
The problem is very odd. I hit the first shield a few times and all is as it should be.
Then when I move across and hit the next shield this shield now appears to contain all the damage from the first image plus the damage just inflicted.
As so on on all the shields.
Its as if the lockimage always locks the original image.
As a final resort I changed the code so instead of the loadimage(pixmap) for each shield type i used loadimage('filename') and now everything works perfectly.
Am I just doing it wrong or is this a bug of some sort ?
I just wanted to load the image once then use a copy of it for each shield.

Im sorry if the explanation is confusing. When I get some time I can try to reduce the code into a simple example.


Dreamora(Posted 2005) [#6]
If you only have 1 shield image every damage will be drawn to that. If it shall be a different for any ship you will have to hold one for each of them, as you did. (doing over loading or copying. Just set it to all types does not help as this does not copy it, they all access the same image


QuietBloke(Posted 2005) [#7]
well.. I can see what you are saying. But.. if each loadimage(Piximage) really just creates a single TImage and all the shields point to the same image I would expect that when I hit the first shield and applied the damage to it then ALL the shields on the screen would show the same damage. But they do not. What happens on screen is :
I hit the first shield.
I do the lockimage on it.. apply the damage.. and unlock it.
On the screen only the first shield shows damage. the other three are still undamaged.
When I shoot the second shield.. I lock it.. apply the damage.. unlock it..
Now the first shield still has the original damage.. the second shield has the same damage as the first shield + the damage I just inflicted.
it is almost like the lockimage is remembering the previous lockimage <shrug>.
I guess its hard to explain. Hopefully when I get a working ( non working) simple example it might make more sense.


Dreamora(Posted 2005) [#8]
Ah
Now I got it ...

That's indeed really strange ...
The behavior that should happen ... at least if working "normal", it should be drawn to all images when applied to 1 shield as all point to the same image reference.
But you say that this "backreference" happens on the pixmap step of lockimage which indicates that somehow the other images are not refreshed ...
assuming that unlock creates a new reference still does not explain, why the change of the 2nd shield "knows" of the damage to the first. if the behavior with not refreshing was meant this way, then this is the bug, otherwise the not refreshing

Are you using image:TIMAGE pixmap:TPixmap or int handles btw?
in later it might be an error with that ...


QuietBloke(Posted 2005) [#9]
Im using TImage and TPixmap

here is an example I knocked together.
press space to cause damage to each shield in turn.
press escape to end the program.

Im now pretty sure Im doing something stupid.
when you run it as it is the typeshield does a loadimage(pixmap,DYNAMICIMAGE). The damage appears as red blocks and carry over between shields.
If you comment the loadimage and uncomment the loadimage line above that does not use the DYNAMICIMAGE parameter the damage appears as black dots and now work correctly.

the image is a 44 x 32 4bit per pixel png.

Global PixmapShield:TPixmap


Type typeShield
	Field image:TImage
	Field x,y
	
	Method New()
'		image = LoadImage(PixmapShield)
		image = LoadImage(PixmapShield,DYNAMICIMAGE)
	End Method
	
	Method draw()
		DrawImage(image,x,y)
	End Method

	Method hit(xhit, yhit)
		Local shieldPix:TPixmap
	
		shieldPix = LockImage( image,0 ) 

		' remove hit pixel
		WritePixel(shieldPix, xhit,yhit,255 Shl 16 )
		WritePixel(shieldPix, xhit+1,yhit,255 Shl 16 )
		WritePixel(shieldPix, xhit,yhit+1,255 Shl 16 )
		WritePixel(shieldPix, xhit+1,yhit+1,255 Shl 16 )

		UnlockImage(image,0)		
	End Method	

End Type

Graphics 640,480,0

loadGraphics()

Global shieldList:typeShield[4]

init()

play()

End

Function play()
Local shield:typeShield
Local s
Local currentShield


	While Not KeyHit(KEY_Escape)
		Cls
		
		If KeyHit(KEY_Space) Then
			Local x,y
			x = Rand(0,20) * 2
			y = Rand(0,20) * 2
		
			shieldList[currentShield].hit(x,y)
			currentShield = ( currentShield + 1 ) Mod 4
		End If
		For s = 0 To 3
			shieldList[s].draw() 
		Next
		Flip
	End While
End Function

Function loadGraphics()
	PixmapShield = LoadPixmap("images\shield.png")
End Function

Function init()
	Local shield:typeShield

	shield = New typeShield
	shield.x = 50
	shield.y = 300
	shieldList[0] = shield

	shield = New typeShield
	shield.x = 150
	shield.y = 300
	shieldList[1] = shield

	shield = New typeShield
	shield.x = 250
	shield.y = 300
	shieldList[2] = shield

	shield = New typeShield
	shield.x = 350
	shield.y = 300
	shieldList[3] = shield

End Function



QuietBloke(Posted 2005) [#10]
OK.. so I changed my program so each new shield does a LoadImage(pixmap) without the DYNAMICIMAGE parameter and everything works fine now. Which is odd because I thought you had to supply the DYNAMICIMAGE parameter if you wanted to lock it.