Destructable Landscapes

Blitz3D Forums/Blitz3D Beginners Area/Destructable Landscapes

Crazy4Code(Posted 2005) [#1]
How could you make 2D destructable landscapes like in Worms or Dome Wars? I'm thinking of making a Dome Wars remake depending on how hard this is.


Ross C(Posted 2005) [#2]
You would need to calculate the explosion size, then subtract the image of the explosion from the landscape. Say, drawing a black oval onto the landscape image, would probably do the trick, as long as black is your masking colour :o)


Crazy4Code(Posted 2005) [#3]
How would you manipulate images like that? Or do you mean just draw a black oval over the image?


Matty(Posted 2005) [#4]
setbuffer imagebuffer(mylandscapeimage)
color 0,0,0
oval x,y,width,height,1
setbuffer backbuffer()



Crazy4Code(Posted 2005) [#5]
I've never understood that image buffer thing. I guess it's time to learn. So, that kindof like... opens the image for editing in a way? And then you can draw an oval on it?


Matty(Posted 2005) [#6]
setbuffer() sets the (I probably should have had some brackets above) current drawing buffer. Using an imagebuffer allows you to draw to an image rather than to the back or front buffer.


Crazy4Code(Posted 2005) [#7]
Oh cool. I never took the time to learn that. Now I understand it. Thanks. I think I can figure out the rest now.


Crazy4Code(Posted 2005) [#8]
I've run into a problem. The drawing the oval on the landscape works, but it draws the oval in the wrong place. It's supposed to draw the oval right where the shot landed on the ground, but it shows the oval a little to the left and farther down. I'm wondering if drawing on the image does not use the same coordinates? Does 0 become the corner of the image instead of the corner of the screen when I setbuffer to the image? If you need to see it to help me, you can download it here http://www.antibox.net/grant/Test.zip


Right now, I'm just testing all the aspects of the game in that .bb file. I'm going to restart after I figure them all out because that file isn't coded very well and it's very messy. Just wanted everyone to know that :-)

Also, how do you make links that aren't the whole url. HTML doesn't seem to work in these forums.


big10p(Posted 2005) [#9]
Does 0 become the corner of the image instead of the corner of the screen when I setbuffer to the image?

Yes.

Also, how do you make links that aren't the whole url.

http://www.blitzbasic.com/faq/faq_entry.php?id=2


Crazy4Code(Posted 2005) [#10]
If 0 becomes the corner of the image, how can I tell it to make an oval at the right coordinate? The coordinates of the shot that hit the ground won't work.


octothorpe(Posted 2005) [#11]
Subtract the image's coordinates from your target coordinates.

If your image's top left corner is at (100,100) and you want to draw an oval on that image at (101,101), then you'd want to centre your oval at (1,1) on the image.


Crazy4Code(Posted 2005) [#12]
Well, I found a way around that anyways for now. But, the collisions aren't right at all. I can't explain it. You'll have to download the test from the post a little ways up.

It's like, sometimes the collisions make an oval and sometimes they don't.


octothorpe(Posted 2005) [#13]
Your program always draws an oval at the wrong place. There are two reasons for this:

1. The x,y coordinates you pass to oval() are for the top-left corner. If you want the oval centred, you need to subtract half the width and height from its origin.

2. Much more importantly, you aren't subtracting the background image's offset as I explained in my last post. Exasperating the problem is the fact that you're using AutoMidHandle True and positioning your background image arbitrarily: the image size is 1152,684 and you're positioning its midpoint at 512,350 - this means you have an offset of -64,-82.


Crazy4Code(Posted 2005) [#14]
Oops, I forgot to update the images size. I had made the image the same size as the window so I didn't need to subtact the background image's offset. Sorry about that. It's updated now if you want to download it again and try it. I'll try to fix number 1 while I wait though.


Ross C(Posted 2005) [#15]
Hey man, change your function TestShotsGround() to :


Function TestShotsGround()
For s.shot = Each shot
If ImagesCollide(s\Image,s\x,s\y,0,TestForg,512,350,0)
SetBuffer ImageBuffer(TestForg)
Color 0,0,0
Oval s\x-50,s\y-50,100,100,1 ; 
SetBuffer BackBuffer()
Delete s
End If 
Next 
End Function 


I would also encourage you to tab your code. It helps alot when debuging and following th program flow. So you code looks like:

;Initialize Graphics Mode
Graphics 1024,700
SetBuffer BackBuffer()
AutoMidHandle True
SeedRnd MilliSecs()


;Load Graphics
Global Silo1 = LoadImage("p1silo.bmp")
MaskImage Silo1,255,255,255

Global Turret1 = LoadImage("p1turret.bmp")

Global shot = LoadImage("shot.bmp")
MaskImage shot,0,0,0

Global TestForg = LoadImage("Testforg.bmp")
MaskImage TestForg,0,0,0

;Arrays
Dim tur1(45)
RotateImage Turret1,-45
tur1(0) = Turret1

For i = 1 To 45
	tur1(i) = CopyImage(Turret1)
	RotateImage tur1(i),2 * i
Next 

;Turret direction Array
Dim dir(45)
dir(0) = 135

For i = 1 To 45
	dir(i) = dir(i-1) + 2
Next 




;Variables
Global x = 400
Global y = -10
Global rot = 0
Global velocity
Global gravity# = 0.2

;Types
Type shot
	Field x,y
	Field vx#,vy#
	Field id$
	Field Image
	Field radius
End Type 

While Not ImagesCollide(Silo1,x,y,0,TestForg,512,350,0)
	y = y + 1
Wend 

;Main Loop
While Not KeyHit(1)
	TestInput()
	DrawGrounds()
	DrawPlayers()
	UpdateShots()
	TestShotsGround()
	
	Flip
	Cls
Wend 
End 


Function TestInput()
	rot = rot + MouseXSpeed()

	If rot < 0
		rot = 0
	Else If rot > 45
		rot = 45
	End If 

	If MouseHit(1)
		s.shot = New shot
		s\x = x
		s\y = y
		s\vx# = -Sin(dir(rot)) * 9
		s\vy# = Cos(dir(rot)) * 9
		s\id$ = "ICBM"
		s\Image = CopyImage(shot)
		s\radius = 5
	End If 

End Function 

Function DrawGrounds()
	DrawImage TestForg,512,350
End Function 

Function DrawPlayers()
	DrawImage tur1(rot),x,y -6
	DrawImage Silo1,x,y
End Function 

Function UpdateShots()
	For s.shot = Each shot
		DrawImage s\Image,s\x,s\y
		s\x = s\x + s\vx#
		s\y = s\y + s\vy#
		
		s\vy# = s\vy# + gravity#
		
	Next
End Function 

Function TestShotsGround()
	For s.shot = Each shot
		If ImagesCollide(s\Image,s\x,s\y,0,TestForg,512,350,0)
			SetBuffer ImageBuffer(TestForg)
			Color 0,0,0
			Oval s\x-50,s\y-50,100,100,1 ; 
			SetBuffer BackBuffer()
			Delete s
		End If 
	Next 
End Function 



Ross C(Posted 2005) [#16]
I've slightly changed your aiming control, just incase you think it's better. Basically, moving the mouse to a place on the screen and the cannon will roughly aim that way. I've marked the lines i've changed and added.

;Initialize Graphics Mode
Graphics 1024,768
SetBuffer BackBuffer()
AutoMidHandle True
SeedRnd MilliSecs()


;Load Graphics
Global Silo1 = LoadImage("p1silo.bmp")
MaskImage Silo1,255,255,255

Global Turret1 = LoadImage("p1turret.bmp")

Global shot = LoadImage("shot.bmp")
MaskImage shot,0,0,0

Global TestForg = LoadImage("Testforg.bmp")
MaskImage TestForg,0,0,0

;Arrays
Dim tur1(45)
RotateImage Turret1,-45
tur1(0) = Turret1

For i = 1 To 45
	tur1(i) = CopyImage(Turret1)
	RotateImage tur1(i),2 * i
Next 

;Turret direction Array
Dim dir(45)
dir(0) = 135

For i = 1 To 45
	dir(i) = dir(i-1) + 2
Next 




;Variables
Global x = 400
Global y = -10
Global rot% = 0
Global velocity
Global gravity# = 0.2

;Types
Type shot
	Field x,y
	Field vx#,vy#
	Field id$
	Field Image
	Field radius
End Type 

While Not ImagesCollide(Silo1,x,y,0,TestForg,512,350,0)
	y = y + 1
Wend 

;Main Loop
While Not KeyHit(1)
	TestInput()
	DrawGrounds()
	DrawPlayers()
	UpdateShots()
	TestShotsGround()
	
	Flip
	Cls
Wend 
End 


Function TestInput()
	temp# = (MouseX()/1024.0)*45.0 ; ADDED********
	rot = temp ; CHANGED**********************

	If rot < 0
		rot = 0
	Else If rot > 45
		rot = 45
	End If 

	If MouseHit(1)
		s.shot = New shot
		s\x = x
		s\y = y
		s\vx# = -Sin(dir(rot)) * 9
		s\vy# = Cos(dir(rot)) * 9
		s\id$ = "ICBM"
		s\Image = CopyImage(shot)
		s\radius = 5
	End If 

End Function 

Function DrawGrounds()
	DrawImage TestForg,512,350
End Function 

Function DrawPlayers()
	DrawImage tur1(rot),x,y -6
	DrawImage Silo1,x,y
End Function 

Function UpdateShots()
	For s.shot = Each shot
		DrawImage s\Image,s\x,s\y
		s\x = s\x + s\vx#
		s\y = s\y + s\vy#
		
		s\vy# = s\vy# + gravity#
		
	Next
End Function 

Function TestShotsGround()
	For s.shot = Each shot
		If ImagesCollide(s\Image,s\x,s\y,0,TestForg,512,350,0)
			SetBuffer ImageBuffer(TestForg)
			Color 0,0,0
			Oval s\x-50,s\y-50,100,100,1 ; 
			SetBuffer BackBuffer()
			Delete s
		End If 
	Next 
End Function