particles.monkey2 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  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 ) Fullscreen=Not Fullscreen
  59. If ( event.Key=Key.Escape ) App.Terminate()
  60. End
  61. End
  62. Method OnMeasure:Vec2i() Override
  63. Return Size
  64. End
  65. End
  66. Class Particles
  67. Private
  68. Field _points:ParticlePoint[]
  69. Field _index:Int=0
  70. Public
  71. Method New()
  72. 'Initialise
  73. _points=New ParticlePoint[NumParticles]
  74. End
  75. Method CreateParticles(x:Int,y:Int,style:Int=2,type:Int=0,particles:Int=32)
  76. 'Prepare
  77. Local r:Int=Rnd(0,4)*64
  78. Local g:Int=Rnd(0,4)*64
  79. Local b:Int=Rnd(0,4)*64
  80. 'Create
  81. Self.CreateParticles(x,y,style,type,r,g,b,particles)
  82. End
  83. Method CreateParticles(x:Int,y:Int,style:Int=2,type:Int=0,r:Int,g:Int,b:Int,particles:Int=32)
  84. 'Create
  85. For Local t:Int=0 Until particles
  86. Self.Create(x,y,style,type,r,g,b)
  87. Next
  88. End
  89. Method CreateFireWorks(position:Int,style:Int=2,type:Int=0)
  90. 'Prepare
  91. Local x:Int,y:Int
  92. Local r:Int=Rnd(0,4)*64
  93. Local g:Int=Rnd(0,4)*64
  94. Local b:Int=Rnd(0,4)*64
  95. 'Get location
  96. Select position
  97. Case 1
  98. If (Rnd(0,1))
  99. x=Rnd(100,App.ActiveWindow.Width-100)
  100. y=16
  101. If (Rnd(0,1)) y=App.ActiveWindow.Height-16
  102. Else
  103. y=Rnd(50,App.ActiveWindow.Height-50)
  104. x=16
  105. If (Rnd(0,1)) x=App.ActiveWindow.Width-16
  106. End
  107. Case 2
  108. x=App.ActiveWindow.Width/2
  109. y=App.ActiveWindow.Height/2
  110. Default
  111. x=Rnd(0,App.ActiveWindow.Width-100)
  112. y=Rnd(0,App.ActiveWindow.Height-50)
  113. End
  114. 'Create
  115. For Local t:Int=0 To 63
  116. Self.Create(x,y,style,type,r,g,b)
  117. Next
  118. End
  119. Method Update()
  120. 'Process
  121. For Local t:Int=0 To NumParticles-1
  122. If (_points[t].active>0) _points[t].Update()
  123. Next
  124. End
  125. Method Reset()
  126. 'Process
  127. For Local t:Int=0 To NumParticles-1
  128. _points[t].x=0
  129. _points[t].y=0
  130. _points[t].r=0
  131. _points[t].g=0
  132. _points[t].b=0
  133. _points[t].active=0
  134. _points[t].dx=0
  135. _points[t].dy=0
  136. Next
  137. 'Reset
  138. _index=0
  139. End
  140. Method Render(canvas:Canvas)
  141. Local r:Float,g:Float,b:Float
  142. 'Prepare
  143. canvas.BlendMode=BlendMode.Additive
  144. canvas.Alpha=1.0
  145. canvas.TextureFilteringEnabled=True
  146. canvas.LineWidth=2.0
  147. 'Process
  148. For Local t:int=0 To NumParticles-1
  149. If (_points[t].active>0)
  150. Select _points[t].style
  151. Case 0
  152. 'Get color
  153. r=Min(_points[t].r*1.25,255.0)
  154. g=Min(_points[t].g*1.25,255.0)
  155. b=Min(_points[t].b*1.25,255.0)
  156. canvas.Color=GetColor(r,g,b)
  157. 'Draw
  158. canvas.DrawLine(_points[t].x,_points[t].y,_points[t].x+_points[t].dx,_points[t].y+_points[t].dy)
  159. Case 1
  160. 'Get color
  161. r=Min(_points[t].r*1.25,255.0)
  162. g=Min(_points[t].g*1.25,255.0)
  163. b=Min(_points[t].b*1.25,255.0)
  164. canvas.Color=GetColor(r,g,b)
  165. 'Draw
  166. canvas.LineWidth=3.0
  167. canvas.Alpha=0.9
  168. canvas.DrawLine(_points[t].x,_points[t].y,_points[t].x+_points[t].dx,_points[t].y+_points[t].dy)
  169. Case 2
  170. 'Get color
  171. r=Min(_points[t].r*1.5,255.0)
  172. g=Min(_points[t].g*1.5,255.0)
  173. b=Min(_points[t].b*1.5,255.0)
  174. canvas.Color=GetColor(r,g,b)
  175. 'Draw
  176. canvas.Alpha=1.0 '.9
  177. canvas.DrawImage(particleImage,_points[t].x+_points[t].dx,_points[t].y+_points[t].dy,0,0.5,0.5)
  178. Case 3
  179. 'BEST!
  180. Local px:Float,py:Float
  181. Local r:Float,g:Float,b:Float
  182. 'Get color
  183. r=Min(_points[t].r*1.25,255.0)
  184. g=Min(_points[t].g*1.25,255.0)
  185. b=Min(_points[t].b*1.25,255.0)
  186. canvas.Color=GetColor(r,g,b)
  187. 'Draw (line)
  188. px=_points[t].x
  189. py=_points[t].y
  190. canvas.Alpha=0.8
  191. canvas.DrawLine(px,py,px+_points[t].dx,py+_points[t].dy)
  192. 'Draw (image)
  193. Local rot:Float=ATan(_points[t].dy/_points[t].dx)
  194. px=_points[t].x
  195. py=_points[t].y
  196. canvas.Alpha=0.25
  197. canvas.DrawImage(particleImage,px+_points[t].dx*1.0,py+_points[t].dy*1.0)
  198. End
  199. End
  200. Next
  201. 'Reset
  202. canvas.BlendMode=BlendMode.Alpha
  203. canvas.Alpha=1.0
  204. canvas.LineWidth=1.0
  205. End
  206. Private
  207. Method Create(x:Float,y:Float,style:Int,type:Int,r:Int,g:Int,b:Int,rot:Float=0.0,size:Int=1)
  208. 'Prepare
  209. Local dir:Float
  210. Local mag:Float
  211. 'Set particle
  212. _points[_index].x=x
  213. _points[_index].y=y
  214. _points[_index].r=r
  215. _points[_index].g=g
  216. _points[_index].b=b
  217. _points[_index].active=Rnd(ParticleLife-20,ParticleLife)
  218. _points[_index].style=style
  219. 'Validate
  220. Select type
  221. Case 0
  222. 'Random
  223. dir=Rnd(0,360)
  224. mag=Rnd(3,11)
  225. _points[_index].dx=Cos(dir)*mag
  226. _points[_index].dy=Sin(dir)*mag
  227. Case 1
  228. mag=16
  229. _points[_index].dx=Cos(rot)*mag
  230. _points[_index].dy=Sin(rot)*mag
  231. _points[_index].active=24
  232. Case 2
  233. mag=8
  234. _points[_index].dx=Cos(rot)*mag
  235. _points[_index].dy=Sin(rot)*mag
  236. Case 3
  237. ' 3 dirs
  238. dir=120*Rnd(0,3)+rot
  239. mag=Rnd(3,10)
  240. _points[_index].dx=Cos(dir)*mag
  241. _points[_index].dy=Sin(dir)*mag
  242. Case 4
  243. ' 4 dirs
  244. dir=90*Rnd(0,4)+rot
  245. mag=Rnd(3,11)
  246. _points[_index].dx=Cos(dir)*mag
  247. _points[_index].dy=Sin(dir)*mag
  248. Case 5
  249. ' 8 dirs
  250. dir=45*Rnd(0,8)+rot
  251. mag=Rnd(3,11)
  252. _points[_index].dx=Cos(dir)*mag
  253. _points[_index].dy=Sin(dir)*mag
  254. Case 6
  255. ' any dir and speed
  256. mag=Rnd(0.5,2.0)
  257. _points[_index].dx=Cos(rot)*mag
  258. _points[_index].dy=Sin(rot)*mag
  259. Case 7
  260. ' random
  261. dir=Rnd(0,360)
  262. mag=Rnd(1,14)
  263. _points[_index].dx=Cos(dir)*mag
  264. _points[_index].dy=Sin(dir)*mag
  265. End
  266. 'Finalise
  267. _points[_index].dx=_points[_index].dx*1.5
  268. _points[_index].dy=_points[_index].dy*1.5
  269. _points[_index].x+=_points[_index].dx*size
  270. _points[_index].y+=_points[_index].dy*size
  271. 'Increment
  272. _index=(_index+1) Mod NumParticles
  273. End
  274. End Class
  275. Struct ParticlePoint
  276. Field x:Float=0.0
  277. Field y:Float=0.0
  278. Field dx:Float=0.0
  279. Field dy:Float=0.0
  280. Field r:Float=0
  281. Field g:Float=0
  282. Field b:Float=0
  283. Field active:Int=0
  284. Field style:Int=0
  285. Method Update()
  286. x=x+dx
  287. y=y+dy
  288. If (x<=dx)
  289. dx=Abs(dx)
  290. x=x+dx*2
  291. End
  292. If(x>App.ActiveWindow.Width-1-dx)
  293. dx=-Abs(dx)
  294. x=x+dx*2
  295. End
  296. If (y<=dy)
  297. dy=Abs(dy)
  298. y=y+dy*2
  299. End
  300. If (y>App.ActiveWindow.Height-1-dy)
  301. dy=-Abs(dy)
  302. y=y+dy*2
  303. End
  304. dx=dx*ParticleDecay
  305. dy=dy*ParticleDecay
  306. active-=1
  307. If (active<20)
  308. If (active<10)
  309. r*=0.8
  310. g*=0.8
  311. b*=0.8
  312. Else
  313. r*=0.97
  314. g*=0.97
  315. b*=0.97
  316. End
  317. If (r<0) r=0
  318. If (g<0) g=0
  319. If (b<0) b=0
  320. Elseif (active>200)
  321. active=200
  322. End
  323. End
  324. End Struct
  325. Function GetColor:Color(red:Float,green:Float,blue:Float)
  326. Return New Color(red/255,green/255,blue/255)
  327. End