demo.monkey2 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  1. ' MX2 demo by Playniax!
  2. ' Title: Shoot-out
  3. ' Version: 1.0
  4. ' Release date: 21-06-2016
  5. ' Programming : Tony Smits
  6. ' Graphics : Peter van Driel
  7. ' This demo uses outtakes from the Pyro framework!
  8. ' For more information about Playniax and Playniax products please visit our website (http://www.playniax.com)!
  9. ' Import the assets
  10. #Import "assets/playniax.png"
  11. #Import "assets/bg1.png"
  12. #Import "assets/planet.png"
  13. #Import "assets/p10000.png"
  14. #Import "assets/p10001.png"
  15. #Import "assets/p20000.png"
  16. #Import "assets/p20001.png"
  17. #Import "assets/bullet.png"
  18. #Import "assets/explosion_0.png"
  19. #Import "assets/explosion_1.png"
  20. #Import "assets/explosion_0.txt"
  21. #Import "assets/explosion_1.txt"
  22. ' Import some Monkey stuff
  23. #Import "<std>"
  24. #Import "<mojo>"
  25. ' And use it
  26. Using std..
  27. Using mojo..
  28. Const VWIDTH:=1024
  29. Const VHEIGHT:=768
  30. Const PLAYER_HITS:=10 ' Number of hits the spaceship can take
  31. ' Some backing globas
  32. Global font:Font
  33. Global explosion:=New Image[77] ' Explosion animation
  34. Global planet:Sprite
  35. Global player:=New Player[2] ' Players global
  36. Global removeSprites:=New Stack<Sprite> ' Sprites that need to be removed end up here
  37. Global sprites:=New Stack<Sprite> ' Contains all the sprites displayed on the screen
  38. Global window:PlayniaxGame
  39. Class PlayniaxGame Extends Window
  40. ' Constructor
  41. Method New( title:String,width:Int,height:Int,flags:WindowFlags=WindowFlags.Resizable )
  42. Super.New( title,width,height,flags )
  43. Layout="letterbox"
  44. font=Font.Load( "asset::mojo/Roboto-Regular.ttf",32 )
  45. LoadExplosion()
  46. ' Create the background
  47. Local bg1:=New Sprite( Image.Load( "asset::bg1.png" ),VWIDTH*.5,VHEIGHT*.5 )
  48. planet=New Sprite( Image.Load( "asset::planet.png" ),VWIDTH*.5,VHEIGHT*.5 )
  49. ' Create the player sprites
  50. player[0]=New Player( New Image[]( Image.Load( "asset::p10000.png" ),Image.Load( "asset::p10001.png" ) ),VWIDTH*.25,VHEIGHT*.5,Key.Left,Key.Right,Key.Up,Key.M )
  51. player[1]=New Player( New Image[]( Image.Load( "asset::p20000.png" ),Image.Load( "asset::p20001.png" ) ),VWIDTH*.75,VHEIGHT*.5,Key.Z,Key.X,Key.C,Key.V )
  52. ' Create the little Playniax logo in the right corner of the screen
  53. Local playniax:=Image.Load( "asset::playniax.png" )
  54. Local x:=VWIDTH-playniax.Width/2-8
  55. Local y:=VHEIGHT-playniax.Height/2-8
  56. New Sprite( playniax,x,y )
  57. End
  58. Method OnMeasure:Vec2i() Override
  59. Return New Vec2i( VWIDTH,VHEIGHT )
  60. End
  61. Method OnRender( canvas:Canvas ) Override
  62. ' Update game logic
  63. UpdateSprites()
  64. PlayerCollisions()
  65. BullitsCollisions()
  66. RemoveManager()
  67. planet.rotation+=.0005 ' Rotate the planet
  68. ' Reset player 1 if Key 1 is pressed
  69. If player[0].enabled=False And Keyboard.KeyHit( Key.Key1 )
  70. player[0].position=New Vec2f( VWIDTH*.25,VHEIGHT*.5 )
  71. player[0].rotation=270/360.0*TwoPi
  72. player[0].speed=New Vec2f()
  73. player[0].hits=PLAYER_HITS
  74. player[0].enabled=True
  75. Endif
  76. ' Reset player 2 if Key 2 is pressed
  77. If player[1].enabled=False And Keyboard.KeyHit( Key.Key2 )
  78. player[1].position=New Vec2f( VWIDTH*.75,VHEIGHT*.5 )
  79. player[1].rotation=270/360.0*TwoPi
  80. player[1].speed=New Vec2f()
  81. player[1].hits=PLAYER_HITS
  82. player[1].enabled=True
  83. Endif
  84. App.RequestRender()
  85. canvas.Clear( New Color( 0,0,0 ) )
  86. ' Draw sprites, scoreboard and help screen
  87. DrawSprites( canvas )
  88. DrawScores( canvas )
  89. DrawHelp( canvas )
  90. End
  91. ' Draw all sprites
  92. Method DrawSprites( canvas:Canvas )
  93. For Local i:=0 Until sprites.Length
  94. If sprites[i].enabled=True sprites[i].Draw( canvas )
  95. Next
  96. End
  97. Method DrawHelp( canvas:Canvas )
  98. canvas.BlendMode=BlendMode.Alpha
  99. canvas.Font=font
  100. If Keyboard.KeyDown( Key.F1 )
  101. ' Display spaceship controls
  102. canvas.Color=New Color( 0,0,0,.75 )
  103. canvas.DrawRect( 0,0,window.Width,window.Height )
  104. Local x:=window.Width/2-140,y:=window.Height/2-172
  105. canvas.Color=New Color( 1,0,0,1 )
  106. canvas.DrawText( "PLAYER 1",x,y ) ; y+=canvas.Font.Height+4
  107. canvas.DrawText( "Cursor up = throttle",x,y ) ; y+=canvas.Font.Height
  108. canvas.DrawText( "Cursor left = turn left",x,y ) ; y+=canvas.Font.Height
  109. canvas.DrawText( "Cursor right = turn right",x,y ) ; y+=canvas.Font.Height
  110. canvas.DrawText( "M = fire",x,y ) ; y+=canvas.Font.Height
  111. y+=16
  112. canvas.Color=New Color( 0,0,1,1 )
  113. canvas.DrawText( "PLAYER 2",x,y ) ; y+=canvas.Font.Height+4
  114. canvas.DrawText( "C = throttle",x,y ) ; y+=canvas.Font.Height
  115. canvas.DrawText( "Z = turn left",x,y ) ; y+=canvas.Font.Height
  116. canvas.DrawText( "X = turn right",x,y ) ; y+=canvas.Font.Height
  117. canvas.DrawText( "V = fire",x,y ) ; y+=canvas.Font.Height
  118. Else
  119. ' Display help key
  120. canvas.Color=New Color( 1,1,1,1 )
  121. canvas.DrawText( "F1 = Help",8,VHEIGHT-8-canvas.Font.Height )
  122. Endif
  123. End
  124. ' Display progress bar hit counter and points
  125. Method DrawScores( canvas:Canvas )
  126. Const spaceX:=256
  127. Local score:=""
  128. canvas.BlendMode=BlendMode.Alpha
  129. canvas.Font=font
  130. If player[0].enabled=False score="Press 1 to play" Else score=player[0].score
  131. DrawProgressBar( canvas,spaceX,8,50,8,player[0].hits,PLAYER_HITS,New Color( .5,0,0,1 ),New Color( 1,0,0,1 ) )
  132. canvas.Color=New Color( 1,0,0,1 )
  133. canvas.DrawText( score,spaceX,8+8+2 )
  134. If player[1].enabled=False score="Press 2 to play" Else score=player[1].score
  135. DrawProgressBar( canvas,window.Width-50-spaceX,8,50,8,player[1].hits,PLAYER_HITS,New Color( 0,0,.5,1 ),New Color( 0,0,1,1 ) )
  136. canvas.Color=New Color( 0,0,1,1 )
  137. canvas.DrawText( score,window.Width-50-spaceX,8+8+2 )
  138. End
  139. ' Removes sprites from the stacks
  140. Method RemoveManager()
  141. For Local i:=0 Until removeSprites.Length
  142. If sprites.Length sprites.RemoveEach( removeSprites[i] )
  143. If player[0].bullets.Length player[0].bullets.RemoveEach( removeSprites[i] )
  144. If player[1].bullets.Length player[1].bullets.RemoveEach( removeSprites[i] )
  145. Next
  146. removeSprites.Clear()
  147. End
  148. ' Update all sprites
  149. Method UpdateSprites()
  150. For Local i:=0 Until sprites.Length
  151. If sprites[i].enabled=True sprites[i].Update()
  152. Next
  153. End
  154. ' Collision logic between players
  155. Method PlayerCollisions()
  156. If player[0].enabled And player[1].enabled And CheckCollision( player[0].position.X,player[0].position.Y,21,player[1].position.X,player[1].position.Y,21 )
  157. Local hits1:=player[0].hits
  158. Local hits2:=player[1].hits
  159. player[0].hits-=hits2
  160. player[1].hits-=hits1
  161. If player[0].hits<=0
  162. player[0].enabled=False
  163. New Explosion( explosion,player[0].position.X,player[0].position.Y,New Vec2f( 2,2 ) )
  164. Endif
  165. If player[1].hits<=0
  166. player[1].enabled=False
  167. New Explosion( explosion,player[1].position.X,player[1].position.Y,New Vec2f( 2,2 ) )
  168. Endif
  169. Endif
  170. End
  171. Method BullitsCollisions()
  172. ' Collision logic between player 1 bullets and player 2
  173. For Local i:=0 Until player[0].bullets.Length
  174. If player[1].enabled And player[0].bullets.Get( i ).enabled
  175. If CheckCollision( player[1].position.X,player[1].position.Y,21,player[0].bullets.Get( i ).position.X,player[0].bullets.Get( i ).position.Y,8 )
  176. player[0].bullets.Get( i ).enabled=False
  177. removeSprites.Push( player[0].bullets.Get( i ) )
  178. player[1].hits-=1
  179. player[0].score+=1
  180. New Explosion( explosion,player[0].bullets.Get( i ).position.X,player[0].bullets.Get( i ).position.Y,New Vec2f( .15,.15 ) )
  181. If player[1].hits<=0
  182. player[1].enabled=False
  183. New Explosion( explosion,player[1].position.X,player[1].position.Y,New Vec2f( 2,2 ) )
  184. Endif
  185. Endif
  186. Endif
  187. Next
  188. ' Collision logic between player 2 bullets and player 1
  189. For Local i:=0 Until player[1].bullets.Length
  190. If player[0].enabled And player[1].bullets.Get( i ).enabled
  191. If CheckCollision( player[0].position.X,player[0].position.Y,21,player[1].bullets.Get( i ).position.X,player[1].bullets.Get( i ).position.Y,8 )
  192. player[1].bullets.Get( i ).enabled=False
  193. removeSprites.Push( player[1].bullets.Get( i ) )
  194. player[0].hits-=1
  195. player[1].score+=1
  196. New Explosion( explosion,player[1].bullets.Get( i ).position.X,player[1].bullets.Get( i ).position.Y,New Vec2f( .15,.15 ) )
  197. If player[0].hits<=0
  198. player[0].enabled=False
  199. New Explosion( explosion,player[0].position.X,player[0].position.Y,New Vec2f( 2,2 ) )
  200. Endif
  201. Endif
  202. Endif
  203. Next
  204. End
  205. End
  206. ' The base sprite (the other sprites extend Sprite)
  207. Class Sprite
  208. ' Sprite backing fields
  209. Field blendMode:=BlendMode.Alpha
  210. Field color:=New Color( 1,1,1,1 )
  211. Field images:Image[]
  212. Field enabled:=True
  213. Field frame:=0.0
  214. Field rotation:=0.0
  215. Field scale:=New Vec2f( 1,1 )
  216. Field position:=New Vec2f
  217. Method New()
  218. End
  219. ' Constructor
  220. Method New( image:Image,x:Int,y:Int )
  221. Self.images=New Image[]( image )
  222. Self.position.X=x
  223. Self.position.Y=y
  224. ' Set image handles to center
  225. For Local i:=0 Until Self.images.Length
  226. Self.images[i].Handle=New Vec2f( .5,.5 )
  227. Next
  228. ' Add sprite to the sprites stack
  229. sprites.Push( Self )
  230. End
  231. ' Constructor
  232. Method New( images:Image[],x:Int,y:Int )
  233. Self.images=images
  234. Self.position.X=x
  235. Self.position.Y=y
  236. ' Set image handles to center
  237. For Local i:=0 Until Self.images.Length
  238. Self.images[i].Handle=New Vec2f( .5,.5 )
  239. Next
  240. sprites.Push( Self )
  241. End
  242. ' Draw sprite
  243. Method Draw( canvas:Canvas )
  244. canvas.BlendMode=blendMode
  245. canvas.Color=color
  246. canvas.DrawImage( images[frame],position,-rotation,scale )
  247. End
  248. ' Update code goes here
  249. Method Update() Virtual
  250. End
  251. End
  252. ' The player sprite
  253. Class Player Extends Sprite
  254. Field bullets:=New Stack<Sprite>
  255. Field hits:=PLAYER_HITS
  256. Field fire:=Key.None
  257. Field fireDelay:=0
  258. Field left:=Key.None
  259. Field right:=Key.None
  260. Field score:=0
  261. Field speed:=New Vec2f
  262. Field throttle:=Key.None
  263. ' Constructor
  264. Method New( images:Image[],x:Int,y:Int,left:Key=Key.None,right:Key=Key.None,throttle:Key=Key.None,fire:Key=Key.None )
  265. Self.images=images
  266. Self.position.X=x
  267. Self.position.Y=y
  268. Self.rotation=270/360.0*TwoPi
  269. Self.left=left
  270. Self.right=right
  271. Self.throttle=throttle
  272. Self.fire=fire
  273. ' Set image handles to center
  274. For Local i:=0 Until Self.images.Length
  275. Self.images[i].Handle=New Vec2f( .5,.5 )
  276. Next
  277. ' Add sprite to the sprites stack
  278. sprites.Push( Self )
  279. End
  280. Method Update() Override
  281. ' Player turn control
  282. If Keyboard.KeyDown( left ) rotation-=.1
  283. If Keyboard.KeyDown( right ) rotation+=.1
  284. ' Player throttle control
  285. If Keyboard.KeyDown( throttle )
  286. speed.X+=Cos( rotation )*.2
  287. speed.Y+=Sin( rotation )*.2
  288. Endif
  289. position.X+=speed.X
  290. position.Y+=speed.Y
  291. ' Control ship borders
  292. If position.X<0 position.X=window.Width
  293. If position.Y<0 position.Y=window.Height
  294. If position.X>window.Width position.X=0
  295. If position.Y>window.Height position.Y=0
  296. ' Fire bullets
  297. If Keyboard.KeyDown( fire ) And fireDelay<Millisecs()
  298. Local bullet:=New Bullet( Image.Load( "asset::bullet.png" ),position.X,position.Y )
  299. bullets.Push( bullet )
  300. bullet.speed.X=Cos( rotation )*16
  301. bullet.speed.Y=Sin( rotation )*16
  302. bullet.rotation=rotation
  303. fireDelay=Millisecs()+100
  304. Endif
  305. ' Animate
  306. frame+=.5
  307. frame=frame Mod images.Length
  308. ' Slow down
  309. speed.X*=.98
  310. speed.Y*=.98
  311. End
  312. End
  313. ' Player bullet sprite
  314. Class Bullet Extends Sprite
  315. Field speed:=New Vec2f
  316. Method New( image:Image,x:Int,y:Int )
  317. Super.New (image,x,y )
  318. End
  319. Method Update() Override
  320. position.X+=speed.X
  321. position.Y+=speed.Y
  322. ' Control bullet borders (remove when it leaves the screen)
  323. If position.X<0 Or position.Y<0 Or position.X>window.Width Or position.Y>window.Height
  324. enabled=False
  325. removeSprites.Push( Self )
  326. Endif
  327. End
  328. End
  329. ' Explosion sprite
  330. Class Explosion Extends Sprite
  331. ' Constructor
  332. Method New( images:Image[],x:Int,y:Int,scale:Vec2f )
  333. Super.New (images,x,y )
  334. Self.blendMode=BlendMode.Additive
  335. Self.scale=scale
  336. End
  337. Method Update() Override
  338. ' Animate
  339. frame+=.5
  340. If frame>=images.Length removeSprites.Push( Self )
  341. End
  342. End
  343. ' Draws the players progress bar (outtake from the Pyro framework)
  344. Function DrawProgressBar( canvas:Canvas,x:Int,y:Int,width:Int,height:Int,value:Int,maximum:Int,surfaceColor:Color=New Color( 0,.5,0,1 ),color:Color=New Color( 0,1,0,1 ) )
  345. Local s:=Float( maximum )/Float( width )
  346. canvas.Color=surfaceColor
  347. canvas.DrawRect( x,y,width,height )
  348. If value>0
  349. canvas.Color=color
  350. If value<width*s
  351. canvas.DrawRect( x,y,value/s,height )
  352. Else
  353. canvas.DrawRect( x,y,width,height )
  354. Endif
  355. Endif
  356. End
  357. ' Checks if circles overlap (outtake from the Pyro framework)
  358. Function CheckCollision:Bool( x1:Float,y1:Float,radius1:Float,x2:Float,y2:Float,radius2:Float )
  359. Return ( ( x2-x1 )*( x2-x1 )+( y2-y1 )*( y2-y1 ) )<( radius1+radius2 )*( radius1+radius2 )
  360. End
  361. ' Grab sprite from sprite sheet (outtake from the Pyro framework)
  362. Function GrabSprite:Image( image:Image,path:String,name:String )
  363. For Local l:=Eachin path.Split( "~n" )
  364. If l.StartsWith( name )
  365. Local f:=l.Split( ":" )
  366. If f.Length=5 Return New Image( image,New Recti( Int( f[1] ),Int( f[2] ),Int( f[1] )+Int( f[3] ),Int( f[2] )+Int( f[4] ) ) )
  367. Endif
  368. Next
  369. Return Null
  370. End
  371. ' Load the explosions using a sprite sheet and txt file (outtake from the Pyro framework)
  372. Function LoadExplosion()
  373. Local image:=Image.Load( "asset::explosion_0.png" )
  374. Local data:=LoadString( "asset::explosion_0.txt" )
  375. For Local i:=0 To 48
  376. explosion[i]=GrabSprite( image,data,"explosion"+i+".png" )
  377. explosion[i].Handle=New Vec2f( .5,.5 )
  378. Next
  379. image=Image.Load( "asset::explosion_1.png" )
  380. data=LoadString( "asset::explosion_1.txt" )
  381. For Local i:=49 To 76
  382. explosion[i]=GrabSprite( image,data,"explosion"+i+".png" )
  383. explosion[i].Handle=New Vec2f( .5,.5 )
  384. Next
  385. End
  386. ' Some init code
  387. Function Main()
  388. New AppInstance
  389. window=New PlayniaxGame( "Shoot-out",640,480 )
  390. App.Run()
  391. End