November 24, 2020, 06:46:45 AM

### Author Topic: [bmx] Deformable terrain by matibee [ 1+ years ago ]  (Read 877 times)

#### BlitzBot

• Jr. Member
• Posts: 1
##### [bmx] Deformable terrain by matibee [ 1+ years ago ]
« on: June 29, 2017, 12:28:38 AM »
Title : Deformable terrain
Author : matibee
Posted : 1+ years ago

Description : The terrain is made up of horizontal line segments while a second, smaller shape is used as an eraser and some falling particles are added for effect.

Subtracting one line segment from another is really simple..  Depending on how they intersect; the start could be changed, the end could be changed, it could be deleted altogether or split into two.

<strike>It's completely unoptimised but still runs quite well.</strike>

Edit:  Now updated to sort the line segments by height, allowing the subtract and collision tests to exit once they've reached lines higher than the test height.

Edit 2:  I've uploaded a textured and slightly updated version <a href="http://www.matibee.co.uk/wpsite/?p=39" target="_blank">here[/url].

Cheers
Matt

Code :
Code: BlitzMax
1. SuperStrict
2.
3. ' Horizontal line type
4. Type hline
5.         Field _start:Int
6.         Field _end:Int
7.         Field y:Int
8.
9.         Method draw()
10.                 DrawLine( _start, y, _end, y )
11.         End Method
12.
13.         Function Create:hline ( s:Int, e:Int, y:Int )
14.                 Local hl:hline = New hline
15.                 hl._start = s
16.                 hl._end = e
17.                 hl.y = y
18.                 Return hl
19.         End Function
20.
21.         ' Subtract another hline from this one, if this line is
22.         ' deleted completely this function returns true.
23.         '
24.         ' If this line is split, hlDest contains the newly created
25.         ' line.
26.         Method Split:Int ( hl:hline, hlDest:hline Var )
27.                 If ( hl.y <> y ) Return False
28.                 If ( _start < hl._start )
29.                         If ( _end > hl._end )
30.                                 hlDest = hline.Create( hl._end, _end, y )
31.                                 _end = hl._start
32.                         Else If ( _end > hl._start )
33.                                 _end = hl._start
34.                         End If
35.                 Else If ( _start < hl._end )
36.                         If ( _end < hl._end )
37.                                 Return True
38.                         Else
39.                                 _start = hl._end
40.                         End If
41.                 End If
42.                 Return False
43.         End Method
44.
45.         Method Move( _x:Int, _y:Int )
46.                 _start :+ _x
47.                 _end :+ _x
48.                 y :+ _y
49.         End Method
50.
51.         Method Collide:Int ( _x:Int, _y:Int )
52.                 If ( _y = y )
53.                         If ( _x >= _start And _x <= _end )
54.                                 Return True
55.                         End If
56.                 End If
57.                 Return False
58.         End Method
59.
60. End Type
61.
62. ' A shape created from the horizontal lines..
63. Type hshape
64.         Field lines:TList
65.         Field x:Int, y:Int
66.
67.         Function Create:hshape ()
68.                 Local hs:hshape = New hshape
69.                 hs.lines = New TList
70.                 Return hs
71.         End Function
72.
73.         Method Draw()
74.                 For Local hl:hline = EachIn lines
75.                         hl.Draw()
76.                 Next
77.         End Method
78.
79.         Method AddLine( s:Float, e:Float, y:Float )
80.                 lines.AddLast( hline.Create( s, e, y ) )
81.                 SortList( lines, True, hshape.SortLinesByHeight )
82.         End Method
83.
84.         Function SortLinesByHeight:Int ( h0:Object, h1:Object )
85.                 Return hline(h1).y < hline(h0).y
86.         End Function
87.
88.         Method Position( _x:Int, _y:Int )
89.                 Local xmove:Int = _x - x
90.                 Local ymove:Int = _y - y
91.                 x :+ xmove
92.                 y :+ ymove
93.                 If ( xmove Or ymove )
94.                         For Local hlThis:hline = EachIn lines
95.                                 hlThis.Move( xmove, ymove )
96.                         Next
97.                 End If
98.         End Method
99.
100.         Method Subtract( hs:hshape )
101.                 For Local hlOther:hline = EachIn hs.lines
102.                         For Local hlThis:hline = EachIn lines
103.                                 Local hlNew:hline
104.                                 If ( hlOther.y < hlThis.y ) Exit
105.                                 If ( hlThis.Split( hlOther, hlNew ) )
106.                                         lines.Remove( hlThis )
107.                                 End If
108.                                 If ( hlNew )
110.                                         SortList( lines, True, hshape.SortLinesByHeight )
111.                                 End If
112.                         Next
113.                 Next
114.         End Method
115.
116.         Method CollidePixel:Int ( x:Int, y:Int )
117.                 For Local hlThis:hline = EachIn lines
118.                         If ( hlThis.y > y )
119.                                 Return False
120.                         Else If ( hlThis.y = y And hlThis.Collide( x, y ) )
121.                                 Return True
122.                         End If
123.                 Next
124.                 Return False
125.         End Method
126.
127. End Type
128.
129. Type phyxel ' simple physics pixel
130.         Field x:Float
131.         Field y:Float
132.         Field vel:Float
133.
134.         Function Create:phyxel ( x:Float, y:Float )
135.                 Local p:phyxel = New phyxel
136.                 p.x = x
137.                 p.y = y
138.                 Return p
139.         End Function
140.
141.         Method Draw()
142.                 DrawRect( x, y, 1, 1 )
143.         End Method
144.
145.         Method Update( terrain:hshape )
146.                 If ( Not terrain.CollidePixel( x, y + vel + 0.5 ) )
147.                         vel :+ 0.1
148.                         If ( vel > 0.98 ) vel = 0.98
149.                 Else
150.                         vel :* -( 0.4 + RndFloat() * 0.5 )
151.                 End If
152.                 y :+ vel
153.                 If ( y > 600 ) y = 600
154.         End Method
155.
156. End Type
157.
158.
159.
160. ' Simple test
161. Graphics 800, 600
162.
163. ' The first shape is the terrain
164. Local hs1:hshape = hshape.Create()
165. For Local t:Int = 300 To 599
166.         hs1.AddLine( 0, 799, t )
167. Next
168.
169. ' The second shape is the eraser
170. Local hs2:hshape = hshape.Create()
171. For Local t:Int = 0 To 30
172.         hs2.AddLine( 0, 40, t )
173. Next
174. hs2.AddLine( 1, 39, 31 )
175. hs2.AddLine( 2, 38, 32 )
176. hs2.AddLine( 4, 36, 33 )
177. hs2.AddLine( 6, 34, 34 )
178. hs2.AddLine( 8, 32, 35 )
179. hs2.AddLine( 11, 29, 36 )
180. hs2.AddLine( 15, 25, 37 )
181.
182. ' a list of falling pixels.
183. Local phyxelList:TList = New TList
184. For Local t:Int = 0 To 200
185.         phyxelList.AddLast( phyxel.Create( Rand( 5, 795 ), Rand( 20, 80 ) ) )
186. Next
187.
188.
189. While Not AppTerminate()
190.         hs1.Subtract( hs2 )
191.         Cls
192.         SetColor( 0,0,255 )
193.         hs1.draw()
194.         SetColor( 255, 0, 0 )
195.         hs2.Position( MouseX(), MouseY() )
196.         hs2.draw()
197.         DrawText( "Line segments: " + hs1.lines.Count() , 0, 0 )
198.         SetColor( 0, 255, 0 )
199.         For Local p:phyxel = EachIn phyxelList
200.                 p.Update( hs1 )
201.                 p.Draw()
202.         Next
203.         Flip
204. Wend

AndrewT(Posted 1+ years ago)

Awesome! I'm very tempted to make a Worms clone now .

Ethan(Posted 1+ years ago)

Which program did you do this in. In my blitz plus it does not work?

Yasha(Posted 1+ years ago)

This is BlitzMax code. It's not compatible with BlitzPlus.BlitzPlus can use those Archive entries that are marked as ".bb" format in the index, as opposed to ".bmx" like this one (at least, when people remember to tag them correctly).

matibee(Posted 1+ years ago)

As Yasha says it is Blitzmax but the description of how it works is here: <a href="http://www.matibee.co.uk/wpsite/2010/04/04/2d-deformable-terrain-in-blitzmax/" target="_blank">http://www.matibee.co.uk/wpsite/2010/04/04/2d-deformable-terrain-in-blitzmax/[/url](Not sure why the original link above isn't working)