Ooops
November 24, 2020, 06:46:45 AM

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

Offline 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 )
  109.                                         lines.AddLast( 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


Comments :


AndrewT(Posted 1+ years ago)

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


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)


 

SimplePortal 2.3.6 © 2008-2014, SimplePortal