particles.monkey2 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. '-----------------------------------------------------------------------
  2. '
  3. ' Based on BlitzMax code created by Mark Incitti
  4. '
  5. '-----------------------------------------------------------------------
  6. Namespace myapp
  7. #Import "<std>"
  8. #Import "<mojo>"
  9. Using std..
  10. Using mojo..
  11. #Import "particle.png"
  12. Global particleImage:Image
  13. Const Size:=New Vec2i( 640,360 )
  14. Const NumParticles:Int=2048
  15. Const ParticleLife:Int=40
  16. Const ParticleDecay:Float=0.95
  17. Function Main()
  18. New AppInstance
  19. New MyWindow
  20. App.Run()
  21. End
  22. Class MyWindow Extends Window
  23. Private
  24. Field _particles:Particles
  25. Field _style:Int=0
  26. Public
  27. Method New()
  28. 'Create window
  29. Super.New( "Particles!",640,480,WindowFlags.Fullscreen )
  30. Layout="letterbox"
  31. ClearColor=New Color(0,0,0)
  32. Mouse.PointerVisible=True
  33. Style.BackgroundColor=GetColor(2,2,2)
  34. 'Load image
  35. particleImage=Image.Load("asset::particle.png")
  36. particleImage.Handle=New Vec2f(0.5,0.5)
  37. 'Initialise particles
  38. _particles=New Particles()
  39. End
  40. Method OnRender( canvas:Canvas ) Override
  41. 'Features
  42. If (Keyboard.KeyHit(Key.P)) _style=(_style + 1) Mod 4
  43. 'Release particles?
  44. If(Rnd(0,100)>90) _particles.CreateFireWorks(3,_style)
  45. 'Update
  46. _particles.Update()
  47. 'Render
  48. App.RequestRender()
  49. _particles.Render(canvas)
  50. 'Text
  51. canvas.Color=Color.White
  52. canvas.DrawText("Style: "+_style,4,App.ActiveWindow.Height-40)
  53. canvas.DrawText("Press 'P' to change",4,App.ActiveWindow.Height-25)
  54. End
  55. Method OnKeyEvent( event:KeyEvent ) Override
  56. select event.Type
  57. Case EventType.KeyDown
  58. If ( event.Key=Key.Enter And event.Modifiers & Modifier.Alt )
  59. If Fullscreen EndFullscreen() Else BeginFullscreen()
  60. Endif
  61. If ( event.Key=Key.Escape ) App.Terminate()
  62. End
  63. End
  64. Method OnMeasure:Vec2i() Override
  65. Return Size
  66. End
  67. End
  68. Class Particles
  69. Private
  70. Field _points:ParticlePoint[]
  71. Field _index:Int=0
  72. Public
  73. Method New()
  74. 'Initialise
  75. _points=New ParticlePoint[NumParticles]
  76. End
  77. Method CreateParticles(x:Int,y:Int,style:Int=2,type:Int=0,particles:Int=32)
  78. 'Prepare
  79. Local r:Int=Rnd(0,4)*64
  80. Local g:Int=Rnd(0,4)*64
  81. Local b:Int=Rnd(0,4)*64
  82. 'Create
  83. Self.CreateParticles(x,y,style,type,r,g,b,particles)
  84. End
  85. Method CreateParticles(x:Int,y:Int,style:Int=2,type:Int=0,r:Int,g:Int,b:Int,particles:Int=32)
  86. 'Create
  87. For Local t:Int=0 Until particles
  88. Self.Create(x,y,style,type,r,g,b)
  89. Next
  90. End
  91. Method CreateFireWorks(position:Int,style:Int=2,type:Int=0)
  92. 'Prepare
  93. Local x:Int,y:Int
  94. Local r:Int=Rnd(0,4)*64
  95. Local g:Int=Rnd(0,4)*64
  96. Local b:Int=Rnd(0,4)*64
  97. 'Get location
  98. Select position
  99. Case 1
  100. If (Rnd(0,1))
  101. x=Rnd(100,App.ActiveWindow.Width-100)
  102. y=16
  103. If (Rnd(0,1)) y=App.ActiveWindow.Height-16
  104. Else
  105. y=Rnd(50,App.ActiveWindow.Height-50)
  106. x=16
  107. If (Rnd(0,1)) x=App.ActiveWindow.Width-16
  108. End
  109. Case 2
  110. x=App.ActiveWindow.Width/2
  111. y=App.ActiveWindow.Height/2
  112. Default
  113. x=Rnd(0,App.ActiveWindow.Width-100)
  114. y=Rnd(0,App.ActiveWindow.Height-50)
  115. End
  116. 'Create
  117. For Local t:Int=0 To 63
  118. Self.Create(x,y,style,type,r,g,b)
  119. Next
  120. End
  121. Method Update()
  122. 'Process
  123. For Local t:Int=0 To NumParticles-1
  124. If (_points[t].active>0) _points[t].Update()
  125. Next
  126. End
  127. Method Reset()
  128. 'Process
  129. For Local t:Int=0 To NumParticles-1
  130. _points[t].x=0
  131. _points[t].y=0
  132. _points[t].r=0
  133. _points[t].g=0
  134. _points[t].b=0
  135. _points[t].active=0
  136. _points[t].dx=0
  137. _points[t].dy=0
  138. Next
  139. 'Reset
  140. _index=0
  141. End
  142. Method Render(canvas:Canvas)
  143. Local r:Float,g:Float,b:Float
  144. 'Prepare
  145. canvas.BlendMode=BlendMode.Additive
  146. canvas.Alpha=1.0
  147. canvas.TextureFilteringEnabled=True
  148. canvas.LineWidth=2.0
  149. canvas.LineSmoothing=True
  150. 'Process
  151. For Local t:int=0 To NumParticles-1
  152. If (_points[t].active>0)
  153. Select _points[t].style
  154. Case 0
  155. 'Get color
  156. r=Min(_points[t].r*1.25,255.0)
  157. g=Min(_points[t].g*1.25,255.0)
  158. b=Min(_points[t].b*1.25,255.0)
  159. canvas.Color=GetColor(r,g,b)
  160. 'Draw
  161. canvas.DrawLine(_points[t].x,_points[t].y,_points[t].x+_points[t].dx,_points[t].y+_points[t].dy)
  162. Case 1
  163. 'Get color
  164. r=Min(_points[t].r*1.25,255.0)
  165. g=Min(_points[t].g*1.25,255.0)
  166. b=Min(_points[t].b*1.25,255.0)
  167. canvas.Color=GetColor(r,g,b)
  168. 'Draw
  169. canvas.LineWidth=3.0
  170. canvas.Alpha=0.9
  171. canvas.DrawLine(_points[t].x,_points[t].y,_points[t].x+_points[t].dx,_points[t].y+_points[t].dy)
  172. Case 2
  173. 'Get color
  174. r=Min(_points[t].r*1.5,255.0)
  175. g=Min(_points[t].g*1.5,255.0)
  176. b=Min(_points[t].b*1.5,255.0)
  177. canvas.Color=GetColor(r,g,b)
  178. 'Draw
  179. canvas.Alpha=1.0 '.9
  180. canvas.DrawImage(particleImage,_points[t].x+_points[t].dx,_points[t].y+_points[t].dy,0,0.5,0.5)
  181. Case 3
  182. 'BEST!
  183. Local px:Float,py:Float
  184. Local r:Float,g:Float,b:Float
  185. 'Get color
  186. r=Min(_points[t].r*1.25,255.0)
  187. g=Min(_points[t].g*1.25,255.0)
  188. b=Min(_points[t].b*1.25,255.0)
  189. canvas.Color=GetColor(r,g,b)
  190. 'Draw (line)
  191. px=_points[t].x
  192. py=_points[t].y
  193. canvas.Alpha=0.8
  194. canvas.DrawLine(px,py,px+_points[t].dx,py+_points[t].dy)
  195. 'Draw (image)
  196. Local rot:Float=ATan(_points[t].dy/_points[t].dx)
  197. px=_points[t].x
  198. py=_points[t].y
  199. canvas.Alpha=0.25
  200. canvas.DrawImage(particleImage,px+_points[t].dx*1.0,py+_points[t].dy*1.0)
  201. End
  202. End
  203. Next
  204. 'Reset
  205. canvas.BlendMode=BlendMode.Alpha
  206. canvas.Alpha=1.0
  207. canvas.LineWidth=1.0
  208. End
  209. Private
  210. Method Create(x:Float,y:Float,style:Int,type:Int,r:Int,g:Int,b:Int,rot:Float=0.0,size:Int=1)
  211. 'Prepare
  212. Local dir:Float
  213. Local mag:Float
  214. 'Set particle
  215. _points[_index].x=x
  216. _points[_index].y=y
  217. _points[_index].r=r
  218. _points[_index].g=g
  219. _points[_index].b=b
  220. _points[_index].active=Rnd(ParticleLife-20,ParticleLife)
  221. _points[_index].style=style
  222. 'Validate
  223. Select type
  224. Case 0
  225. 'Random
  226. dir=Rnd(0,360)
  227. mag=Rnd(3,11)
  228. _points[_index].dx=Cos(dir)*mag
  229. _points[_index].dy=Sin(dir)*mag
  230. Case 1
  231. mag=16
  232. _points[_index].dx=Cos(rot)*mag
  233. _points[_index].dy=Sin(rot)*mag
  234. _points[_index].active=24
  235. Case 2
  236. mag=8
  237. _points[_index].dx=Cos(rot)*mag
  238. _points[_index].dy=Sin(rot)*mag
  239. Case 3
  240. ' 3 dirs
  241. dir=120*Rnd(0,3)+rot
  242. mag=Rnd(3,10)
  243. _points[_index].dx=Cos(dir)*mag
  244. _points[_index].dy=Sin(dir)*mag
  245. Case 4
  246. ' 4 dirs
  247. dir=90*Rnd(0,4)+rot
  248. mag=Rnd(3,11)
  249. _points[_index].dx=Cos(dir)*mag
  250. _points[_index].dy=Sin(dir)*mag
  251. Case 5
  252. ' 8 dirs
  253. dir=45*Rnd(0,8)+rot
  254. mag=Rnd(3,11)
  255. _points[_index].dx=Cos(dir)*mag
  256. _points[_index].dy=Sin(dir)*mag
  257. Case 6
  258. ' any dir and speed
  259. mag=Rnd(0.5,2.0)
  260. _points[_index].dx=Cos(rot)*mag
  261. _points[_index].dy=Sin(rot)*mag
  262. Case 7
  263. ' random
  264. dir=Rnd(0,360)
  265. mag=Rnd(1,14)
  266. _points[_index].dx=Cos(dir)*mag
  267. _points[_index].dy=Sin(dir)*mag
  268. End
  269. 'Finalise
  270. _points[_index].dx=_points[_index].dx*1.5
  271. _points[_index].dy=_points[_index].dy*1.5
  272. _points[_index].x+=_points[_index].dx*size
  273. _points[_index].y+=_points[_index].dy*size
  274. 'Increment
  275. _index=(_index+1) Mod NumParticles
  276. End
  277. End Class
  278. Struct ParticlePoint
  279. Field x:Float=0.0
  280. Field y:Float=0.0
  281. Field dx:Float=0.0
  282. Field dy:Float=0.0
  283. Field r:Float=0
  284. Field g:Float=0
  285. Field b:Float=0
  286. Field active:Int=0
  287. Field style:Int=0
  288. Method Update()
  289. x=x+dx
  290. y=y+dy
  291. If (x<=dx)
  292. dx=Abs(dx)
  293. x=x+dx*2
  294. End
  295. If(x>App.ActiveWindow.Width-1-dx)
  296. dx=-Abs(dx)
  297. x=x+dx*2
  298. End
  299. If (y<=dy)
  300. dy=Abs(dy)
  301. y=y+dy*2
  302. End
  303. If (y>App.ActiveWindow.Height-1-dy)
  304. dy=-Abs(dy)
  305. y=y+dy*2
  306. End
  307. dx=dx*ParticleDecay
  308. dy=dy*ParticleDecay
  309. active-=1
  310. If (active<20)
  311. If (active<10)
  312. r*=0.8
  313. g*=0.8
  314. b*=0.8
  315. Else
  316. r*=0.97
  317. g*=0.97
  318. b*=0.97
  319. End
  320. If (r<0) r=0
  321. If (g<0) g=0
  322. If (b<0) b=0
  323. Elseif (active>200)
  324. active=200
  325. End
  326. End
  327. End Struct
  328. Function GetColor:Color(red:Float,green:Float,blue:Float)
  329. Return New Color(red/255,green/255,blue/255)
  330. End