2
0
Mark Sibly 9 жил өмнө
parent
commit
0b8c4854b2
23 өөрчлөгдсөн 758 нэмэгдсэн , 815 устгасан
  1. 0 144
      modules/mojo/bananas/gridshooter/fonts/gridshooter.monkey2
  2. 1 1
      modules/mojo/bananas/gridshooter/gamegraphics/README.txt
  3. BIN
      modules/mojo/bananas/gridshooter/gamegraphics/classic_sans.ttf
  4. 107 105
      modules/mojo/bananas/gridshooter/gamegraphics/gamegraphics.monkey2
  5. 0 9
      modules/mojo/bananas/gridshooter/gamegraphics/src/README.txt
  6. 45 46
      modules/mojo/bananas/gridshooter/gamegraphics/src/background.monkey2
  7. 0 106
      modules/mojo/bananas/gridshooter/gamegraphics/src/gamegraphics.monkey2
  8. 1 1
      modules/mojo/bananas/gridshooter/gamegraphics/src/sprite.monkey2
  9. 72 70
      modules/mojo/bananas/gridshooter/gridshooter.monkey2
  10. BIN
      modules/mojo/bananas/gridshooter/images/bombExplosion.png
  11. BIN
      modules/mojo/bananas/gridshooter/images/bullet.png
  12. 5 0
      modules/mojo/bananas/gridshooter/images/copyleft.txt
  13. BIN
      modules/mojo/bananas/gridshooter/images/dualbeam.png
  14. BIN
      modules/mojo/bananas/gridshooter/images/explosion.png
  15. BIN
      modules/mojo/bananas/gridshooter/images/laser.png
  16. BIN
      modules/mojo/bananas/gridshooter/images/orbSmall.png
  17. 0 12
      modules/mojo/bananas/gridshooter/renderwindow/README.txt
  18. 99 0
      modules/mojo/bananas/gridshooter/src/actor.monkey2
  19. 4 5
      modules/mojo/bananas/gridshooter/src/area.monkey2
  20. 40 0
      modules/mojo/bananas/gridshooter/src/bullet.monkey2
  21. 22 0
      modules/mojo/bananas/gridshooter/src/orb.monkey2
  22. 45 0
      modules/mojo/bananas/gridshooter/src/player.monkey2
  23. 317 316
      modules/mojo/bananas/gridshooter/src/renderwindow.monkey2

+ 0 - 144
modules/mojo/bananas/gridshooter/fonts/gridshooter.monkey2

@@ -1,144 +0,0 @@
-
-#Import "renderwindow/renderwindow"
-#Import "gamegraphics/gamegraphics"
-
-#Import "fonts/classic_sans.ttf"
-#Import "images/grid.png"
-#Import "images/starfield.png"
-#Import "images/hero.png"
-#Import "images/jet.png"
-#Import "images/bullet.png"
-
-Using mojo..
-Using std..
-
-Class Game Extends RenderWindow
-
-	Field bg:Background
-	Field bgGrid:Background
-	Field smallFont:Font
-	Field heroSprite:Sprite
-	Field jetSprite:Sprite
-	Field bulletSprite:Sprite
-	
-	Field x:Double, y:Double, speed:= 2.0
-	Field oldX:Float, oldY:Float
-	Field anim:= "idle"
-	
-	Field cameraSpeed := 5.0
-	Field colorTint:= New Color( 0.25, 1.0, 0.5 )
-	
-	Field allBullets := New Stack<Bullet>
-	Field lastFired := 0
-	
-	Method New()					
-		Super.New( "Test", 480, 270, False, True )		'name, width, height, filterTextures, renderToTexture
-	End
-	
-	Method OnStart() Override
-		canvas.Font = Font.Load( "asset::classic_sans.ttf", 10 )
-		bg = New Background( "asset::starfield.png", False )
-		bgGrid = New Background( "asset::grid.png", False )
-		
-		heroSprite = New Sprite( "asset::hero.png", 3, 32, 32, False )
-		heroSprite.AddAnimationClip( "idle", New Int[]( 0 ) )
-		heroSprite.AddAnimationClip( "up", New Int[]( 1 ) )
-		heroSprite.AddAnimationClip( "down", New Int[]( 2 ) )
-		
-		jetSprite = New Sprite( "asset::jet.png", 2, 16, 16, False )
-		jetSprite.AddAnimationClip( "idle", New Int[]( 0,1 ) )
-		jetSprite.frameRate = 30
-		
-		bulletSprite = New Sprite( "asset::bullet.png", 4, 32, 32, False )
-		bulletSprite.AddAnimationClip( "idle", New Int[] ( 0 ) )
-		bulletSprite.AddAnimationClip( "hit", New Int[] ( 1,2,3 ) )
-		
-		For Local n := 0 Until 10
-			allBullets.Push( New Bullet )
-		Next
-	End
-	
-	Method OnUpdate() Override
-		camera.X += cameraSpeed		
-		x += cameraSpeed
-		
-		If Keyboard.KeyHit( Key.D ) Then debug = Not debug
-
-		If Keyboard.KeyDown( Key.Left )
-			x -= speed
-		Else If Keyboard.KeyDown( Key.Right )
-			x += speed
-		End
-		If Keyboard.KeyDown( Key.Up )
-			y -= speed * 2
-			camera.Y -= speed
-		Else If Keyboard.KeyDown( Key.Down )
-			y += speed * 2
-			camera.Y += speed
-		End
-		
-		If Keyboard.KeyHit( Key.Space )
-			Local bullet := allBullets.Get( lastFired )
-			bullet.visible = True
-			bullet.x = x + 16
-			bullet.y = y + 4
-			lastFired += 1
-			If lastFired > 9 Then lastFired = 0
-		End
-		
-		x = Clamp( x, camera.Left, camera.Right )
-		y = Clamp( y, camera.Top, camera.Bottom )
-		
-		If y > oldY
-			anim = "down"
-		Elseif y < oldY
-			anim = "up"
-		Else
-			anim = "idle"
-		End
-		oldY = y
-	End
-	
-	Method OnDraw() Override
-		canvas.Color = colorTint
-		
-		canvas.Alpha = 1.0
-		Parallax = 0.05
-		bg.Draw( canvas, 0, 0, 1.0, CameraRect )
-		
-		canvas.Alpha = 0.25
-		Parallax = 0.2
-		bgGrid.Draw( canvas, 32, 32, 1.0, CameraRect )
-		
-		canvas.Alpha = 0.5
-		Parallax = 1.0
-		bgGrid.Draw( canvas, 0, 0, 1.0, CameraRect )
-		
-		canvas.Alpha = 1.0
-		canvas.Color= Color.White
-		jetSprite.Draw( canvas, "idle", x-16, y+2 )
-		heroSprite.Draw( canvas, anim, x, y )
-		
-		For Local b := Eachin allBullets
-			If b.visible
-				bulletSprite.Draw( canvas, "idle", b.x, b.y )
-				b.x += b.speed
-				If b.x > ( x + Width ) Then b.visible = False
-			End
-		Next
-	End
-
-End
-
-Class Bullet
-	Field visible := False
-	Field x:Float, y:Float, speed:Float = 15.0
-End
-
-Function Main()
-	New AppInstance
-	New Game()
-	App.Run()
-End
-
-

+ 1 - 1
modules/mojo/bananas/gridshooter/gamegraphics/README.txt

@@ -2,7 +2,7 @@
 
 A collection of game related drawing objects.
 
-- Sprite: A basic sprite system featuring spritesheet loading, easy texture filtering, animation clips (series of frames played back sequenctially) and playback framerate.
+- Sprite: A basic sprite system featuring spritesheet loading, easy texture filtering, animation clips (series of frames played back sequentially) and playback framerate.
 
 - Background: An "infinite background" that takes a single texture and tiles it in a way that respects the Canvas translation, as long as you provide a camera Rect containing the camera corners (corrected for parallax, if necessary)
 

BIN
modules/mojo/bananas/gridshooter/gamegraphics/classic_sans.ttf


+ 107 - 105
modules/mojo/bananas/gridshooter/gamegraphics/gamegraphics.monkey2

@@ -1,106 +1,108 @@
-
-#Import "<mojo>"
-#Import "src/sprite"
-#Import "src/background"
-
-Using mojo..
-Using std..
-
-Class GameGraphics Abstract
-
-	Field images		:Image[]	'The array containing all frames
-	Field debug := False
-		
-	Protected
-	Field _handle:= New Vec2f
-
-	
-	'************************************* Instance Properties *************************************
-	
-	Public
-	
-	'Sets the handles in all sub-images
-	Property Handle:Vec2f()
-		Return _handle
-	Setter( handle:Vec2f )
-		_handle = handle
-		For Local i := Eachin images
-			i.Handle = _handle
-		Next
-	End
-
-	
-	'************************************* Instance Methods *************************************
-
-	
-	'Loads an array of Images from a sprite sheet
-	Method LoadFrames:Image[] ( path:String, numFrames:Int, cellWidth:Int, cellHeight:Int, filter:Bool = True, padded:Bool = False )
-	
-		Local flags:TextureFlags=Null
-		If filter Then flags |= TextureFlags.Filter
-		
-		Local atlasTextture := Texture.Load( path, flags )
-		Assert( atlasTextture, " ~n ~nGameGraphics: Image " + path + " not found.~n ~n" )
-		
-		Local atlasImg := New Image( atlasTextture )
-		Local imgs := New Image[ numFrames ]
-
-		If cellHeight = atlasImg.Height
-			Local x := 0
-			Local width := cellWidth
-			If padded
-				x += 1
-				width -= 2
-			End
-			For Local i := 0 Until numFrames
-				Local x0 := i * cellWidth + x
-				Local y0 := 0
-				imgs[i] = New Image( atlasImg, New Recti( x0, y0, x0 + cellWidth, cellHeight ) )
-'   				imgs[i].Handle = New Vec2f( .5,.5 )
-			Next
-		Else
-			Local x:= 0
-			Local width:= cellWidth
-			Local y:= 0
-			Local height:= cellHeight
-			Local columns:= atlasImg.Width / width
-			If padded
-				x += 1
-				y += 1
-				width -= 2
-				height -= 2
-			End If
-			For Local i:= 0 Until numFrames
-				Local fx := i Mod columns * cellWidth
-				Local fy := i / columns * cellHeight
-				imgs[i] = New Image( atlasImg, New Recti( fx + x, fy + y, fx + cellWidth, fy + cellHeight ) )
-'   				imgs[i].Handle = New Vec2f( .5,.5 )
-			Next
-		Endif
-		atlasImg = Null
-		Return imgs
-	End
-	
-	
-	Method DrawOutline( canvas:Canvas, x:Float, y:Float, width:Float, height:Float, rz:Float = 0, sx:Float = 1.0, sy:Float = 1.0 )
-		Local matrix:= canvas.Matrix
-		canvas.Translate( x, y )
-		canvas.Rotate( rz )
-		canvas.Scale( sx,sy )
-		DrawRectOutline( canvas, -( width * Handle.X ), -( height * Handle.Y ), width, height )
-		canvas.Matrix=matrix
-	End
-	
-	
-	
-	'************************************* Class Functions *************************************
-	
-
-	Method DrawRectOutline:Void(canvas:Canvas, left:Int, top:Int, width:Int, height:Int )
-		canvas.DrawLine( left, top, left+width, top )
-		canvas.DrawLine( left, top, left ,top+height )
-		canvas.DrawLine( left, top+height, left+width, top+height )
-		canvas.DrawLine( left+width, top, left+width, top+height )
-	End
-
+
+#Import "<mojo>"
+#Import "src/sprite"
+#Import "src/background"
+
+Using mojo..
+Using std..
+
+Class GameGraphics Abstract
+
+	Field images		:Image[]	'The array containing all frames
+	Field debug := False
+		
+	Protected
+	Field _handle:= New Vec2f
+	
+	'************************************* Public Properties *************************************
+	
+	Public
+	
+	'Sets the handles in all sub-images
+	Property Handle:Vec2f()
+		Return _handle
+	Setter( handle:Vec2f )
+		_handle = handle
+		For Local i := Eachin images
+			i.Handle = _handle
+		Next
+	End
+
+	Property Width:Double()
+		Return images[0].Width
+	End
+
+	Property Height:Double()
+		Return images[0].Height
+	End
+	
+	'************************************* Public Methods *************************************
+	
+	'Loads an array of Images from a sprite sheet
+	Method LoadFrames:Image[] ( path:String, numFrames:Int, cellWidth:Int, cellHeight:Int, filter:Bool = True, padded:Bool = False )
+	
+		Local flags :TextureFlags = Null
+		If filter Then flags |= TextureFlags.Filter
+		
+		Local atlasTextture := Texture.Load( path, flags )
+		Assert( atlasTextture, " ~n ~nGameGraphics: Image " + path + " not found.~n ~n" )
+		
+		Local atlasImg := New Image( atlasTextture )
+		Local imgs := New Image[ numFrames ]
+
+		If cellHeight = atlasImg.Height
+			Local x := 0
+			Local width := cellWidth
+			If padded
+				x += 1
+				width -= 2
+			End
+			For Local i := 0 Until numFrames
+				Local x0 := i * cellWidth + x
+				Local y0 := 0
+				imgs[i] = New Image( atlasImg, New Recti( x0, y0, x0 + cellWidth, cellHeight ) )
+			Next
+		Else
+			Local x:= 0
+			Local width:= cellWidth
+			Local y:= 0
+			Local height:= cellHeight
+			Local columns:= atlasImg.Width / width
+			If padded
+				x += 1
+				y += 1
+				width -= 2
+				height -= 2
+			End If
+			For Local i:= 0 Until numFrames
+				Local fx := i Mod columns * cellWidth
+				Local fy := i / columns * cellHeight
+				imgs[i] = New Image( atlasImg, New Recti( fx + x, fy + y, fx + cellWidth, fy + cellHeight ) )
+			Next
+		Endif
+		atlasImg = Null
+		Return imgs
+	End
+	
+	
+	Method DrawOutline( canvas:Canvas, x:Float, y:Float, width:Float, height:Float, rz:Float = 0, sx:Float = 1.0, sy:Float = 1.0 )
+		Local matrix:= canvas.Matrix
+		canvas.Translate( x, y )
+		canvas.Rotate( rz )
+		canvas.Scale( sx,sy )
+		DrawRectOutline( canvas, -( width * Handle.X ), -( height * Handle.Y ), width, height )
+		canvas.Matrix=matrix
+	End
+	
+	
+	
+	'************************************* Class Functions *************************************
+
+	Function DrawRectOutline:Void(canvas:Canvas, left:Int, top:Int, width:Int, height:Int )
+		canvas.DrawLine( left, top, left+width, top )
+		canvas.DrawLine( left, top, left ,top+height )
+		canvas.DrawLine( left, top+height, left+width, top+height )
+		canvas.DrawLine( left+width, top, left+width, top+height )
+	End
+
 End

+ 0 - 9
modules/mojo/bananas/gridshooter/gamegraphics/src/README.txt

@@ -1,9 +0,0 @@
-#GameGraphics
-
-A collection of game related drawing objects.
-
-- Sprite: A basic sprite system featuring spritesheet loading, easy texture filtering, animation clips (series of frames played back sequenctially) and playback framerate.
-
-- Background: An "infinite background" that takes a single texture and tiles it in a way that respects the Canvas translation, as long as you provide a camera Rect containing the camera corners (corrected for parallax, if necessary)
-
-Roadmap: Add Tilemap (will use a similar system as the Background object), "9-patches", Textbox.

+ 45 - 46
modules/mojo/bananas/gridshooter/gamegraphics/src/background.monkey2

@@ -1,47 +1,46 @@
-
-#Import "tilegraphics"
-
-Class Background Extends TileGraphics
-
-	Field total:Int
-
-	Method New( path:String, filter:Bool = True )
-	
-		Local flags:TextureFlags=Null
-		If filter Then flags |= TextureFlags.Filter
-		
-		Local atlasTextture := Texture.Load( path, flags )
-		Assert( atlasTextture, " ~n ~nGameGraphics: Image " + path + " not found.~n ~n" )
-		images = New Image[]( New Image( atlasTextture ) )
-	End
-	
-	Method Draw( canvas:Canvas, x:Double, y:Double, scale:Double, camera:Rect<Double> )
-
-		total = 0
-
-		GetVisibleTiles( x, y, scale, camera )
-		
-		For Local tY := tileStartY Until tileEndY
-			For Local tX := tileStartX Until tileEndX
-				local absX := ( tX * tileWidth ) + x
-				local absY := ( tY * tileHeight ) + y
-				If images[0]
-					total += 1
-					canvas.DrawImage( images[0], absX, absY, 0, scale, scale )
-					If debug
-						DrawRectOutline( canvas, absX, absY, tileWidth, tileHeight )
-						canvas.DrawText( tX + "," + tY, absX + 4, absY + 4 )
-					End
-				End
-			Next
-		Next
-	End
-	
-	Method ToString:String()
-		Local t := ""
-		t += ( "Background: " + tileStartX + "," + tileStartY + "; " + tileEndX + "," + tileEndY + "; " )
-		t += ( "Total tiles: " + total )
-		Return t
-	End
-	
+
+#Import "tilegraphics"
+
+Class Background Extends TileGraphics
+
+	Field total:Int
+
+	Method New( path:String, filter:Bool = True )
+		Local flags:TextureFlags = Null
+		If filter Then flags |= TextureFlags.Filter
+		
+		Local atlasTextture := Texture.Load( path, flags )
+		Assert( atlasTextture, " ~n ~nGameGraphics: Image " + path + " not found.~n ~n" )
+		images = New Image[]( New Image( atlasTextture ) )
+	End
+	
+	Method Draw( canvas:Canvas, x:Double, y:Double, scale:Double, camera:Rect<Double> )
+
+		total = 0
+
+		GetVisibleTiles( x, y, scale, camera )
+		
+		For Local tY := tileStartY Until tileEndY
+			For Local tX := tileStartX Until tileEndX
+				local absX := ( tX * tileWidth ) + x
+				local absY := ( tY * tileHeight ) + y
+				If images[0]
+					total += 1
+					canvas.DrawImage( images[0], absX, absY, 0, scale, scale )
+					If debug
+						DrawRectOutline( canvas, absX, absY, tileWidth, tileHeight )
+						canvas.DrawText( tX + "," + tY, absX + 4, absY + 4 )
+					End
+				End
+			Next
+		Next
+	End
+	
+	Method ToString:String()
+		Local t := ""
+		t += ( "Background: " + tileStartX + "," + tileStartY + "; " + tileEndX + "," + tileEndY + "; " )
+		t += ( "Total tiles: " + total )
+		Return t
+	End
+	
 End

+ 0 - 106
modules/mojo/bananas/gridshooter/gamegraphics/src/gamegraphics.monkey2

@@ -1,106 +0,0 @@
-
-#Import "<mojo>"
-#Import "src/sprite"
-#Import "src/background"
-
-Using mojo..
-Using std..
-
-Class GameGraphics Abstract
-
-	Field images		:Image[]	'The array containing all frames
-	Field debug := False
-		
-	Protected
-	Field _handle:= New Vec2f
-
-	
-	'************************************* Instance Properties *************************************
-	
-	Public
-	
-	'Sets the handles in all sub-images
-	Property Handle:Vec2f()
-		Return _handle
-	Setter( handle:Vec2f )
-		_handle = handle
-		For Local i := Eachin images
-			i.Handle = _handle
-		Next
-	End
-
-	
-	'************************************* Instance Methods *************************************
-
-	
-	'Loads an array of Images from a sprite sheet
-	Method LoadFrames:Image[] ( path:String, numFrames:Int, cellWidth:Int, cellHeight:Int, filter:Bool = True, padded:Bool = False )
-	
-		Local flags:TextureFlags=Null
-		If filter Then flags |= TextureFlags.Filter
-		
-		Local atlasTextture := Texture.Load( path, flags )
-		Assert( atlasTextture, " ~n ~nGameGraphics: Image " + path + " not found.~n ~n" )
-		
-		Local atlasImg := New Image( atlasTextture )
-		Local imgs := New Image[ numFrames ]
-
-		If cellHeight = atlasImg.Height
-			Local x := 0
-			Local width := cellWidth
-			If padded
-				x += 1
-				width -= 2
-			End
-			For Local i := 0 Until numFrames
-				Local x0 := i * cellWidth + x
-				Local y0 := 0
-				imgs[i] = New Image( atlasImg, New Recti( x0, y0, x0 + cellWidth, cellHeight ) )
-'   				imgs[i].Handle = New Vec2f( .5,.5 )
-			Next
-		Else
-			Local x:= 0
-			Local width:= cellWidth
-			Local y:= 0
-			Local height:= cellHeight
-			Local columns:= atlasImg.Width / width
-			If padded
-				x += 1
-				y += 1
-				width -= 2
-				height -= 2
-			End If
-			For Local i:= 0 Until numFrames
-				Local fx := i Mod columns * cellWidth
-				Local fy := i / columns * cellHeight
-				imgs[i] = New Image( atlasImg, New Recti( fx + x, fy + y, fx + cellWidth, fy + cellHeight ) )
-'   				imgs[i].Handle = New Vec2f( .5,.5 )
-			Next
-		Endif
-		atlasImg = Null
-		Return imgs
-	End
-	
-	
-	Method DrawOutline( canvas:Canvas, x:Float, y:Float, width:Float, height:Float, rz:Float = 0, sx:Float = 1.0, sy:Float = 1.0 )
-		Local matrix:= canvas.Matrix
-		canvas.Translate( x, y )
-		canvas.Rotate( rz )
-		canvas.Scale( sx,sy )
-		DrawRectOutline( canvas, -( width * Handle.X ), -( height * Handle.Y ), width, height )
-		canvas.Matrix=matrix
-	End
-	
-	
-	
-	'************************************* Class Functions *************************************
-	
-
-	Method DrawRectOutline:Void(canvas:Canvas, left:Int, top:Int, width:Int, height:Int )
-		canvas.DrawLine( left, top, left+width, top )
-		canvas.DrawLine( left, top, left ,top+height )
-		canvas.DrawLine( left, top+height, left+width, top+height )
-		canvas.DrawLine( left+width, top, left+width, top+height )
-	End
-
-End

+ 1 - 1
modules/mojo/bananas/gridshooter/gamegraphics/src/sprite.monkey2

@@ -57,7 +57,7 @@ Class Sprite Extends GameGraphics
 			Return
 		End
 		
-		'Override _time with any time value above 0
+		'Override _time with any time value above -1
 		If time < 0
 			_time = Millisecs() - _startTime
 		Else

+ 72 - 70
modules/mojo/bananas/gridshooter/gridshooter.monkey2

@@ -1,6 +1,14 @@
+'   Copyleft notice: All code created by Leo Santos (www.leosantos.com)
+'   Feel free to use it in any form, but please include a credit.
+'   More importantly, do not claim to have created any of it, unless you modify it substantially.
+'   Thanks!
 
-#Import "renderwindow/renderwindow"
 #Import "gamegraphics/gamegraphics"
+#Import "src/renderwindow"
+#Import "src/actor"
+#Import "src/player"
+#Import "src/bullet"
+#Import "src/orb"
 
 #Import "fonts/classic_sans.ttf"
 #Import "images/grid.png"
@@ -8,132 +16,126 @@
 #Import "images/hero.png"
 #Import "images/jet.png"
 #Import "images/bullet.png"
+#Import "images/orbSmall.png"
 
 Using mojo..
 Using std..
 
+'To do: move out of collision
+
 Class Game Extends RenderWindow
 
+	Global scrollSpeed := 5.0
+	Global scrollLimitY:Double = 60
+	Global cameraSpeed := 1.0
+	
+	Field hero:Player	
 	Field bg:Background
 	Field bgGrid:Background
 	Field smallFont:Font
-	Field heroSprite:Sprite
-	Field jetSprite:Sprite
-	Field bulletSprite:Sprite
-	
-	Field x:Double, y:Double, speed:= 2.0
-	Field oldX:Float, oldY:Float
-	Field anim:= "idle"
-	
-	Field cameraSpeed := 5.0
+
 	Field colorTint:= New Color( 0.25, 1.0, 0.5 )
-	
-	Field allBullets := New Stack<Bullet>
-	Field lastFired := 0
-	
+		
 	Method New()					
-		Super.New( "Test", 480, 270, False, True )		'name, width, height, filterTextures, renderToTexture
+		Super.New( "Test", 420, 240, False, True )		'name, width, height, filterTextures, renderToTexture
+		Layout = "letterbox-int"
 	End
 	
 	Method OnStart() Override
+		Actor.camera = camera
+	
+		'Load sprites & font
 		canvas.Font = Font.Load( "asset::classic_sans.ttf", 10 )
 		bg = New Background( "asset::starfield.png", False )
 		bgGrid = New Background( "asset::grid.png", False )
 		
-		heroSprite = New Sprite( "asset::hero.png", 3, 32, 32, False )
+		Local heroSprite := New Sprite( "asset::hero.png", 3, 32, 32, False )
 		heroSprite.AddAnimationClip( "idle", New Int[]( 0 ) )
 		heroSprite.AddAnimationClip( "up", New Int[]( 1 ) )
 		heroSprite.AddAnimationClip( "down", New Int[]( 2 ) )
 		
-		jetSprite = New Sprite( "asset::jet.png", 2, 16, 16, False )
+		Local jetSprite := New Sprite( "asset::jet.png", 2, 16, 16, False )
 		jetSprite.AddAnimationClip( "idle", New Int[]( 0,1 ) )
 		jetSprite.frameRate = 30
 		
-		bulletSprite = New Sprite( "asset::bullet.png", 4, 32, 32, False )
+		Local bulletSprite := New Sprite( "asset::bullet.png", 5, 32, 32, False )
 		bulletSprite.AddAnimationClip( "idle", New Int[] ( 0 ) )
-		bulletSprite.AddAnimationClip( "hit", New Int[] ( 1,2,3 ) )
+		bulletSprite.AddAnimationClip( "hit", New Int[] ( 1,2,3,4 ), False )
+		bulletSprite.frameRate = 15
+		
+		Local orbSprite := New Sprite( "asset::orbSmall.png", 5, 16, 16, False )
+		orbSprite.AddAnimationClip( "idle", New Int[] ( 0,1,2,3 ) )
+		
+		'Create player sprite
+		hero = New Player( heroSprite )
+		
+		'Create reusable enemy orbs
+		SeedRnd( 12345 )
+		Local offset:= 0
+		For Local n := 0 Until 20
+			Local neworb := New Orb( orbSprite )
+			neworb.Reset()
+			neworb.position.X += offset
+			offset += 16
+		Next
 		
+		'Pool of 10 reusable bullets
 		For Local n := 0 Until 10
-			allBullets.Push( New Bullet )
+			Local b := New Bullet( bulletSprite )
+			Actor.bulletPool.Push( b )
 		Next
+		Bullet.player = hero
+		Bullet.cullDistance = Width
+		
+		canvas.TextureFilteringEnabled = False	'New feature in v009
 	End
 	
+	
 	Method OnUpdate() Override
-		camera.X += cameraSpeed		
-		x += cameraSpeed
-		
-		If Keyboard.KeyHit( Key.D ) Then debug = Not debug
-
-		If Keyboard.KeyDown( Key.Left )
-			x -= speed
-		Else If Keyboard.KeyDown( Key.Right )
-			x += speed
-		End
+		'camera scrolls up & down a bit, 90's shooter style
+		camera.X += scrollSpeed			
 		If Keyboard.KeyDown( Key.Up )
-			y -= speed * 2
-			camera.Y -= speed
+			camera.Y -= cameraSpeed
 		Else If Keyboard.KeyDown( Key.Down )
-			y += speed * 2
-			camera.Y += speed
-		End
-		
-		If Keyboard.KeyHit( Key.Space )
-			Local bullet := allBullets.Get( lastFired )
-			bullet.visible = True
-			bullet.x = x + 16
-			bullet.y = y + 4
-			lastFired += 1
-			If lastFired > 9 Then lastFired = 0
+			camera.Y += cameraSpeed
 		End
+		camera.Y = Clamp( camera.Y, -scrollLimitY, scrollLimitY )
 		
-		x = Clamp( x, camera.Left, camera.Right )
-		y = Clamp( y, camera.Top, camera.Bottom )
+		'Update all actors
+		Actor.UpdateAll()
 		
-		If y > oldY
-			anim = "down"
-		Elseif y < oldY
-			anim = "up"
-		Else
-			anim = "idle"
-		End
-		oldY = y
+		'Display debug info
+		If Keyboard.KeyHit( Key.D ) Then debug = Not debug
 	End
 	
+	
 	Method OnDraw() Override
 		canvas.Color = colorTint
-		
+
+		'Draw bg objects in three layers with different parallax
 		canvas.Alpha = 1.0
-		Parallax = 0.05
+		Parallax = 0.1
 		bg.Draw( canvas, 0, 0, 1.0, CameraRect )
 		
+		canvas.Alpha = 0.5
+		canvas.DrawText( "Monkey2 Side Scrolling Demo by Leo Santos. Press space to shoot!", 260, 100 )
+		
 		canvas.Alpha = 0.25
-		Parallax = 0.2
+		Parallax = 0.25
 		bgGrid.Draw( canvas, 32, 32, 1.0, CameraRect )
 		
 		canvas.Alpha = 0.5
 		Parallax = 1.0
 		bgGrid.Draw( canvas, 0, 0, 1.0, CameraRect )
 		
+		'Draw all actors
 		canvas.Alpha = 1.0
 		canvas.Color= Color.White
-		jetSprite.Draw( canvas, "idle", x-16, y+2 )
-		heroSprite.Draw( canvas, anim, x, y )
-		
-		For Local b := Eachin allBullets
-			If b.visible
-				bulletSprite.Draw( canvas, "idle", b.x, b.y )
-				b.x += b.speed
-				If b.x > ( x + Width ) Then b.visible = False
-			End
-		Next
+		Actor.DrawAll( canvas )
 	End
 
 End
 
-Class Bullet
-	Field visible := False
-	Field x:Float, y:Float, speed:Float = 15.0
-End
 
 Function Main()
 	New AppInstance

BIN
modules/mojo/bananas/gridshooter/images/bombExplosion.png


BIN
modules/mojo/bananas/gridshooter/images/bullet.png


+ 5 - 0
modules/mojo/bananas/gridshooter/images/copyleft.txt

@@ -0,0 +1,5 @@
+Copyleft notice: All images created by Leo Santos (www.leosantos.com)
+
+Feel free to use them in any form, but please, include a credit.
+More importantly, do not claim to have created any of it, unless you modify it substantially.
+Thanks!

BIN
modules/mojo/bananas/gridshooter/images/dualbeam.png


BIN
modules/mojo/bananas/gridshooter/images/explosion.png


BIN
modules/mojo/bananas/gridshooter/images/laser.png


BIN
modules/mojo/bananas/gridshooter/images/enemyBulletSmall.png → modules/mojo/bananas/gridshooter/images/orbSmall.png


+ 0 - 12
modules/mojo/bananas/gridshooter/renderwindow/README.txt

@@ -1,12 +0,0 @@
-# RenderWindow
-A Window class for Monkey2 that simplifies some tasks like parallax layers and render to texture.
-
-Features:
-- Simple camera coordinates. Any x and y drawing coordinate becomes a world coordinate.
-- Easy to use Parallax
-- "World space" mouse coordinates
-- Render to texture, allows "pixel perfect" games
-- Display debug info on screen with Echo( "info" )
-
-Check the examples folder for a simple test usage.
-

+ 99 - 0
modules/mojo/bananas/gridshooter/src/actor.monkey2

@@ -0,0 +1,99 @@
+Class Actor
+
+	'******************************* Static Globals *******************************
+
+	Global catalog := New Stack<Actor>
+	Global bulletPool := New Stack<Bullet>
+	
+	Global camera:Area<Double>
+	Global player:Actor
+	
+	Global scrollSpeed := 5.0
+	Global currentBullet := 0
+	Global cullDistance:Double
+	
+	'******************************* Public fields *******************************
+	
+	Field name := ""
+	Field visible := True
+	Field speed:Double = 3.0
+	Field anim:= "idle"
+	Field detectCollision := True
+	
+	Field sprite:Sprite
+	Field position := New Vec2<Double>
+	
+	Field collider :Area<Double>
+	
+	'******************************* Protected fields *******************************
+	
+	Field _hide := False
+	Field _hideTimer := 0
+	Field _hideTimerStart := 0
+	Field _hideWait := 0
+	
+	'******************************* Public methods *******************************
+		
+	Method New( sprite:Sprite )
+		Self.sprite = sprite
+		catalog.Push( Self )
+		collider= New Area<Double>( 0, 0, sprite.Width, sprite.Height )
+		Reset()
+	End
+	
+	Method Hide( time:Int )
+		_hide = True
+		_hideTimerStart = Millisecs()
+		_hideWait = time
+	End
+	
+	Method Reset()
+		sprite.Reset()
+		_hide = False
+		detectCollision = True
+		OnReset()
+	End
+	
+	
+	
+	'******************************* Static functions *******************************
+
+	Function UpdateAll()
+		For Local a := Eachin catalog
+			If a.visible
+				If a._hide
+					a._hideTimer = Millisecs() - a._hideTimerStart
+					If a._hideTimer > a._hideWait
+						a.visible = False
+						a._hide = False
+					End				
+				End
+				a.position.X += scrollSpeed
+				a.OnUpdate()
+				a.collider.Position( a.position.X, a.position.Y )
+			End
+		Next
+	End
+
+	Function DrawAll( canvas:Canvas )
+		For Local a := Eachin catalog
+			If a.visible
+				a.sprite.Draw( canvas, a.anim, a.position.X, a.position.Y )
+'   				GameGraphics.DrawRectOutline( canvas, a.collider.Left, a.collider.Top, a.collider.Width, a.collider.Height )
+				a.OnDraw( canvas )
+			End
+		Next
+	End
+	
+	'******************************* Virtual methods *******************************
+	
+	Method OnUpdate() Virtual
+	End
+	
+	Method OnDraw( canvas:Canvas ) Virtual
+	End
+	
+	Method OnReset() Virtual
+	End
+	
+End

+ 4 - 5
modules/mojo/bananas/gridshooter/renderwindow/area.monkey2 → modules/mojo/bananas/gridshooter/src/area.monkey2

@@ -1,5 +1,5 @@
 
-Struct Area<T>
+Class Area<T>
 
 	Private
 	
@@ -85,7 +85,7 @@ Struct Area<T>
 	Method New( x:T, y:T, _width:T, _height:T )
 		X = x
 		Y = y
-		SetSize( _width, _height )
+		Size( _width, _height )
 		_rect = New Rect<T>
 	End
 	
@@ -94,7 +94,7 @@ Struct Area<T>
 		Y = y
 	End
 
-	Method SetSize(_width:T, _height:T )
+	Method Size(_width:T, _height:T )
 		Self._width = _width
 		Self._height = _height
 		_pivotX = ( _width * _handle.x )
@@ -152,8 +152,7 @@ Struct Area<T>
 	End
 	
 	Method ToString:String()
-'   		Return "Area("+_vec.X+","+_vec.Y+","+_width+","+_height+")"
-		Return "("+Int(_x0)+","+Int(_y0)+","+Int(_x1)+","+Int(_y1)+")"
+		Return "Area("+_vec.X+","+_vec.Y+"; "+_width+"x"+_height+")"
 	End
 	
 

+ 40 - 0
modules/mojo/bananas/gridshooter/src/bullet.monkey2

@@ -0,0 +1,40 @@
+
+Class Bullet Extends Actor
+	
+	Method New( sprite:Sprite )
+		Super.New( sprite )
+		visible = False
+		speed = 15
+		name = "bullet"
+	End	
+	
+	Method OnUpdate() Override
+		position.X += speed
+		collider.Position( position.X, position.Y )
+		If position.X > ( player.position.X + cullDistance ) Then visible = False
+		
+		For Local other := Eachin Actor.catalog
+			If detectCollision
+				If other.visible And Not ( other.name = "bullet" ) And Not ( other = player )
+					If collider.Overlaps( other.collider )
+						speed = 0
+						anim = "hit"
+						detectCollision = False
+						sprite.Reset()
+						Hide( 200 )
+						other.Reset()
+					End
+				End
+			End
+		End
+		
+	End
+	
+	
+	Method OnReset() Override
+		collider.Size( 8, 8 )
+		speed = 8
+		anim = "idle"
+	End
+	
+End

+ 22 - 0
modules/mojo/bananas/gridshooter/src/orb.monkey2

@@ -0,0 +1,22 @@
+
+Class Orb Extends Actor
+
+	Global cullDistance:Double
+	
+	Method New( sprite:Sprite )
+		Super.New( sprite )
+		name = "orb"
+	End	
+	
+	Method OnUpdate() Override
+		position.X -= 1.0
+		If position.X < camera.Left - sprite.Width Then Reset()
+	End
+	
+	Method OnReset() Override
+		position.X = camera.Right + sprite.Width
+		Local n := ( Rnd() * 240 ) - 120
+		position.Y = n
+	End
+	
+End

+ 45 - 0
modules/mojo/bananas/gridshooter/src/player.monkey2

@@ -0,0 +1,45 @@
+Class Player Extends Actor
+
+	Field  oldY:Double
+	Field limitY:Double = 180
+	
+	Method New( sprite:Sprite )
+		Super.New( sprite )
+		name = "player"
+	End	
+	
+	Method OnUpdate() Override		
+		If Keyboard.KeyDown( Key.Left )
+			position.X -= speed
+		Else If Keyboard.KeyDown( Key.Right )
+			position.X += speed
+		End
+		If Keyboard.KeyDown( Key.Up )
+			position.Y -= speed
+		Else If Keyboard.KeyDown( Key.Down )
+			position.Y += speed
+		End
+		
+		If Keyboard.KeyHit( Key.Space )
+			Local bullet := bulletPool.Get( currentBullet )
+			bullet.Reset()
+			bullet.visible = True
+			bullet.position.X = position.X
+			bullet.position.Y = position.Y + 4
+			currentBullet += 1
+			If currentBullet > 9 Then currentBullet = 0
+		End
+		
+		position.X = Clamp( position.X, camera.Left, camera.Right )
+		position.Y = Clamp( position.Y, camera.Top, camera.Bottom)
+		
+		If position.Y > oldY
+			anim = "down"
+		Elseif position.Y < oldY
+			anim = "up"
+		Else
+			anim = "idle"
+		End
+		oldY = position.Y
+	End
+End

+ 317 - 316
modules/mojo/bananas/gridshooter/renderwindow/renderwindow.monkey2 → modules/mojo/bananas/gridshooter/src/renderwindow.monkey2

@@ -1,316 +1,317 @@
-
-#Rem
-Features:
-- Simple camera coordinates. Any x and y drawing coordinate becomes a world coordinate.
-- Easy to use Parallax
-- "World space" mouse coordinates
-- Render to texture, allows "pixel perfect" games
-- Display debug info on screen with Echo( "info" )
-#End
-
-'To Do: camera is a rect. SHould it be a Vec2f? Of should I take advantage of the rect and change the code?
-'To do: Integer scaling
-
-#Import "<mojo>"
-#Import "area"
-
-Using mojo..
-Using std..
-
-Class RenderWindow Extends Window
-
-	Field canvas :Canvas						'Main canvas currently in use
-	Field camera :Area<Double>					'Camera coordinates
-	
-	Field renderToTexture := False				'Causes all canvas rendering to be directed to a fixed size texture
-	Field filterTextures := True				'Turns on/off texture smoothing. Off for pixel art.
-	Field bgColor := Color.DarkGrey				'Background color
-	Field borderColor := Color.Black 			'Letterboxing border color
-	Field debug := False						'Toggles display of debug info ( Echo() )
-	
-	Protected
-	Field _init := False
-	
-	Field _parallax := 1.0
-	Field _parallaxCam :Area<Double>
-	
-	Field _virtualRes:= New Vec2i				'Virtual rendering size
-	Field _mouse := New Vec2i					'temporarily stores mouse coords
-	Field _adjustedMouse := New Vec2i			'Mouse corrected for layout style and camera position
-	Field _layerInitiated := False
-
-	Field _echoStack:= New Stack<String>		'Contains all the text messages to be displayed
-	Field _flags :TextureFlags					'flags used on the render texture
-	
-	Field _fps	:= 60							'fps counter
-	Field _fpscount	:= 0.0						'temporary fps counter
-	Field _tick := 0							'Only stores the current time once every second
-	
-	Field _renderImage :Image					'Image that uses the render target
-	Field _textureCanvas :Canvas				'Canvas that uses _renderImage
-	Field _windowCanvas: Canvas					'main window canvas
-	
-	Public
-	
-	
-	'**************************************************** Properties ****************************************************
-	
-	'Mouse coordinates in WORLD units, corrected for camera
-	Property Mouse:Vec2i()						
-		Return _adjustedMouse
-	End
-	
-	'You can set the parallax before any drawing operation
-	Property Parallax:Float()					
-		Return _parallax
-	Setter( value:Float )
-		_parallax = value
-		_parallaxCam.Position( camera.X * _parallax, camera.Y * _parallax )
-		If _layerInitiated
-			canvas.PopMatrix()
-			_layerInitiated = False
-		End
-		canvas.PushMatrix()
-'   		canvas.Translate( ( -camera.X * _parallax ) + _cameraOffset.X, ( -camera.Y * _parallax ) + _cameraOffset.Y  )
-		canvas.Translate( ( -camera.X * _parallax ) + camera.Width/2.0, ( -camera.Y * _parallax ) + camera.Height/2.0  )
-
-		_layerInitiated = True
-	End
-	
-	'Returns the camera corrected for current parallax 
-	Property CameraRect:Rect<Double>()
-		Return _parallaxCam.Rect
-	End
-	
-	'Flags used by the Render Texture
-	Property Flags:TextureFlags()
-		Return _flags
-	End
-	
-	'Efective frame rate
-	Property FPS:Int()
-		Return _fps
-	End
-	
-	'corner window coordinates	
-	Property Left:Float()
-		Return -Width/2.0
-	End
-	
-	Property Right:Float()
-		Return Width/2.0
-	End
-	
-	Property Top:Float()
-		Return -Height/2.0
-	End
-	
-	Property Bottom:Float()
-		Return Height/2.0
-	End
-	
-	
-	'**************************************************** Public methods ****************************************************
-	
-	
-	Method New( title:String, width:Int, height:Int, filterTextures:Bool = True, renderToTexture:Bool = False, flags:WindowFlags = WindowFlags.Resizable )
-		Super.New( title, width, height, flags )
-		Layout = "letterbox-int"
-		ClearColor = borderColor
-		Style.BackgroundColor = bgColor
-		
-		_flags = Null
-		If filterTextures Then _flags |= TextureFlags.Filter		
-
-'		_flags=Null
-'		If filterTextures Then _flags|=TextureFlags.Filter
-		
-		Self.renderToTexture = renderToTexture
-		Self.filterTextures = filterTextures
-		
-		camera = New Area<Double>( 0, 0, width, height )
-		_parallaxCam = New Area<Double>( 0, 0, width, height )
-		
-		SetVirtualResolution( width, height )
-'   		SelectCanvas()
-	End
-	
-
-	Method OnRender( windowCanvas:Canvas ) Override
-		App.RequestRender()
-		
-		If Not _init
-			_init = True
-'   			canvas = windowCanvas
-			SelectCanvas()
-			WindowStart()
-			Return
-		End
-		
-		FrameUpdate()
-		
-		Style.BackgroundColor = bgColor
-		Self._windowCanvas = windowCanvas
-		
-		'Picks current drawing canvas based on renderToTexture
-		SelectCanvas()
-
-		'Mouse in world coordinates
-		_mouse = TransformPointFromView( App.MouseLocation, Null )
-		_adjustedMouse.x = _mouse.x + camera.Left
-		_adjustedMouse.y = _mouse.y + camera.Top
-		
-		'the Parallax property will always set the canvas translation before drawing.
-		Parallax = 1.0		
-		FrameDraw()
-		
-		''Closes' the drawing for any parallax layer
-		If _layerInitiated
-			canvas.PopMatrix()
-			_layerInitiated = False
-		End
-		
-		'Draws render to texture image onto _windowCanvas
-		If renderToTexture
-			canvas.Flush()
-			_windowCanvas.DrawImage( _renderImage, 0, 0 )
-		End
-		
-		'Resets canvas colors for each frame
-		_textureCanvas.Color = Color.White
-		_windowCanvas.Color = Color.White
-		
-		'Draw message stack, then clear it every frame
-		If debug Then DebugInfo()
-		Local y := 2
-		For Local t := Eachin _echoStack
-			_windowCanvas.DrawText( t, 5, y )
-			y += _windowCanvas.Font.Height
-		Next
-		_echoStack.Clear()
-		
-		'App quit
-		If ( Keyboard.KeyDown( Key.LeftGui ) And Keyboard.KeyHit( Key.Q ) ) Or ( Keyboard.KeyDown( Key.LeftAlt ) And Keyboard.KeyHit( Key.W ) )
-			App.Terminate()
-		End
-		
-		'Basic fps counter
-		If Millisecs() - _tick > 1008
-			_fps = _fpscount
-			_tick = Millisecs()
-			_fpscount=0
-		Else
-			_fpscount +=1
-		End
-	End
-	
-	
-	Method OnMeasure:Vec2i() Override
-		Return _virtualRes
-	End
-	
-	
-	Method OnWindowEvent(event:WindowEvent) Override
-		Select event.Type
-			Case EventType.WindowMoved
-			Case EventType.WindowResized
-				App.RequestRender()
-			Case EventType.WindowGainedFocus
-			Case EventType.WindowLostFocus
-			Default
-				Super.OnWindowEvent(event)
-		End
-	End
-	
-
-	Method SetVirtualResolution( width:Int, height:Int )
-		_virtualRes = New Vec2i( width, height )
-		MinSize = New Vec2i( width/2, height/2 )
-		
-		camera.Width = width
-		camera.Height = height
-		_parallaxCam.Width = Width
-		_parallaxCam.Height = Height
-		
-		_renderImage = New Image( width,height,TextureFlags.Dynamic )
-		_textureCanvas = New Canvas( _renderImage )
-		_textureCanvas.Font = App.DefaultFont
-	End
-	
-	
-	Method Echo( text:String )
-		_echoStack.Push( text )
-	End
-	
-
-	Method CycleLayout()
-		Select Layout
-		Case "fill"
-			Layout="letterbox-int"
-		Case "letterbox-int"
-			Layout="stretch"
-		Case "stretch"
-			Layout="float"
-		Case "float"
-'   			Layout="fill"
-			Layout = "letterbox-int"
-		End
-	End
-	
-	
-	'**************************************************** Protected Methods ****************************************************
-	'These allow RenderWindow to be extended without the need for OnUpdate and OnDraw to call Super.xxx().
-	'i.e: A MyGameEngine class can extend RenderWindow and override FrameDraw() and add specific features, leaving OnDraw() alone, as long as it is called somewhere.
-	
-	Protected
-	
-	Method WindowStart() Virtual
-		OnStart()
-	End
-	
-	Method FrameUpdate() Virtual
-		OnUpdate()
-	End
-	
-	Method FrameDraw() Virtual
-		OnDraw()
-	End
-	
-	Method DebugInfo() Virtual
-		Echo( "Window resolution: " + Frame.Width + ", " + Frame.Height )
-		Echo( "Virtual resolution: " + Width + ", " + Height )
-		Echo( "Mouse:" + Mouse.x + "," + Mouse.y )
-		Echo( "Camera:" + Int( camera.X ) + "," + Int( camera.Y ) )
-		Echo( "Layout: " + Layout )
-		If renderToTexture
-			Echo( "renderToTexture = True" )
-		Else
-			Echo( "renderToTexture = False" )
-		End
-		Echo( "Camera: " + camera.ToString() )
-		Echo( "FPS: " + FPS )
-	End
-	
-	Method SelectCanvas()
-		If renderToTexture
-			canvas = _textureCanvas
-		Else
-			canvas = _windowCanvas
-		End
-		canvas.Clear( bgColor )
-	End
-	
-	'**************************************************** Virtual Methods ****************************************************
-	Public
-	
-	Method OnStart() Virtual
-	End
-	
-	Method OnUpdate() Virtual
-	End
-	
-	Method OnDraw() Virtual
-	End
-	
-End
-
+
+#Rem
+Features:
+- Simple camera coordinates. Any x and y drawing coordinate becomes a world coordinate.
+- Easy to use Parallax
+- "World space" mouse coordinates
+- Render to texture, allows "pixel perfect" games
+- Display debug info on screen with Echo( "info" )
+#End
+
+#Import "<mojo>"
+#Import "area"
+
+Using mojo..
+Using std..
+
+Class RenderWindow Extends Window
+
+	Field canvas :Canvas						'Main canvas currently in use
+	Field camera :Area<Double>					'Camera coordinates
+	
+	Field renderToTexture := False				'Causes all canvas rendering to be directed to a fixed size texture
+	Field filterTextures := True				'Turns on/off texture smoothing. Off for pixel art.
+	Field bgColor := Color.DarkGrey				'Background color
+	Field borderColor := Color.Black 			'Letterboxing border color
+	Field debug := False						'Toggles display of debug info ( Echo() )
+	
+	Protected
+	
+	Global _echoStack:= New Stack<String>		'Contains all the text messages to be displayed
+	
+	Field _init := False
+	Field _flags :TextureFlags					'flags used on the render texture
+	
+	Field _parallax := 1.0
+	Field _parallaxCam :Area<Double>
+	
+	Field _virtualRes:= New Vec2i				'Virtual rendering size
+	Field _mouse := New Vec2i					'temporarily stores mouse coords
+	Field _adjustedMouse := New Vec2i			'Mouse corrected for layout style and camera position
+	Field _layerInitiated := False
+
+	
+	Field _fps	:= 60							'fps counter
+	Field _fpscount	:= 0.0						'temporary fps counter
+	Field _tick := 0							'Only stores the current time once every second
+	
+	Field _renderTexture :Texture				'Render target for renderToTexture
+	Field _renderImage :Image					'Image that uses the render target
+	Field _textureCanvas :Canvas				'Canvas that uses _renderImage
+	Field _windowCanvas: Canvas					'main window canvas
+	
+	Public
+	
+	
+	'**************************************************** Properties ****************************************************
+	
+	'Mouse coordinates in WORLD units, corrected for camera
+	Property Mouse:Vec2i()						
+		Return _adjustedMouse
+	End
+	
+	'You can set the parallax before any drawing operation
+	Property Parallax:Float()					
+		Return _parallax
+	Setter( value:Float )
+		_parallax = value
+		_parallaxCam.Position( camera.X * _parallax, camera.Y * _parallax )
+		If _layerInitiated
+			canvas.PopMatrix()
+			_layerInitiated = False
+		End
+		canvas.PushMatrix()
+'   		canvas.Translate( ( -camera.X * _parallax ) + _cameraOffset.X, ( -camera.Y * _parallax ) + _cameraOffset.Y  )
+		canvas.Translate( ( -camera.X * _parallax ) + camera.Width/2.0, ( -camera.Y * _parallax ) + camera.Height/2.0  )
+
+		_layerInitiated = True
+	End
+	
+	'Returns the camera corrected for current parallax 
+	Property CameraRect:Rect<Double>()
+		Return _parallaxCam.Rect
+	End
+	
+	'Flags used by the Render Texture
+	Property Flags:TextureFlags()
+		Return _flags
+	End
+	
+	'Efective frame rate
+	Property FPS:Int()
+		Return _fps
+	End
+	
+	'corner window coordinates	
+	Property Left:Float()
+		Return -Width/2.0
+	End
+	
+	Property Right:Float()
+		Return Width/2.0
+	End
+	
+	Property Top:Float()
+		Return -Height/2.0
+	End
+	
+	Property Bottom:Float()
+		Return Height/2.0
+	End
+	
+	
+	'**************************************************** Public methods ****************************************************
+	
+	
+	Method New( title:String, width:Int, height:Int, filterTextures:Bool = True, renderToTexture:Bool = False, flags:WindowFlags = WindowFlags.Resizable )
+		Super.New( title, width, height, flags )
+		Layout = "letterbox"
+		ClearColor = borderColor
+		Style.BackgroundColor = bgColor
+		
+		_flags = Null
+		If filterTextures Then _flags|=TextureFlags.Filter
+		
+		Self.renderToTexture = renderToTexture
+		Self.filterTextures = filterTextures
+		
+		camera = New Area<Double>( 0, 0, width, height )
+		_parallaxCam = New Area<Double>( 0, 0, width, height )
+		
+		SetVirtualResolution( width, height )
+'   		SelectCanvas()
+	End
+	
+
+	Method OnRender( windowCanvas:Canvas ) Override
+		App.RequestRender()
+		
+		If Not _init
+			_init = True
+'   			canvas = windowCanvas
+			SelectCanvas()
+			WindowStart()
+			Return
+		End
+		
+		FrameUpdate()
+		
+		Style.BackgroundColor = bgColor
+		Self._windowCanvas = windowCanvas
+		
+		'Picks current drawing canvas based on renderToTexture
+		SelectCanvas()
+
+		'Mouse in world coordinates
+		_mouse = TransformPointFromView( App.MouseLocation, Null )
+		_adjustedMouse.x = _mouse.x + camera.Left
+		_adjustedMouse.y = _mouse.y + camera.Top
+		
+		'the Parallax property will always set the canvas translation before drawing.
+		Parallax = 1.0		
+		FrameDraw()
+		
+		''Closes' the drawing for any parallax layer
+		If _layerInitiated
+			canvas.PopMatrix()
+			_layerInitiated = False
+		End
+		
+		'Draws render to texture image onto _windowCanvas
+		If renderToTexture
+			canvas.Flush()
+			_windowCanvas.DrawImage( _renderImage, 0, 0 )
+		End
+		
+		'Resets canvas colors for each frame
+		_textureCanvas.Color = Color.White
+		_windowCanvas.Color = Color.White
+		
+		'Draw message stack, then clear it every frame
+		If debug Then DebugInfo()
+		Local y := 2
+		For Local t := Eachin _echoStack
+			_windowCanvas.DrawText( t, 5, y )
+			y += _windowCanvas.Font.Height
+		Next
+		_echoStack.Clear()
+		
+		'Basic fps counter
+		If Millisecs() - _tick > 1008
+			_fps = _fpscount
+			_tick = Millisecs()
+			_fpscount=0
+		Else
+			_fpscount +=1
+		End
+		
+		'App quit
+		If ( Keyboard.KeyHit( Key.Escape ) ) 
+			App.Terminate()
+		End
+	End
+	
+	
+	Method OnMeasure:Vec2i() Override
+		Return _virtualRes
+	End		
+
+	
+	
+	Method OnWindowEvent(event:WindowEvent) Override
+		Select event.Type
+			Case EventType.WindowMoved
+			Case EventType.WindowResized
+				App.RequestRender()
+			Case EventType.WindowGainedFocus
+			Case EventType.WindowLostFocus
+			Default
+				Super.OnWindowEvent(event)
+		End
+	End
+	
+
+	Method SetVirtualResolution( width:Int, height:Int )
+		_virtualRes = New Vec2i( width, height )
+		MinSize = New Vec2i( width/2, height/2 )
+		
+		camera.Width = width
+		camera.Height = height
+		_parallaxCam.Width = Width
+		_parallaxCam.Height = Height
+		
+		_renderTexture = New Texture( width, height, PixelFormat.RGBA32, _flags )
+		_renderImage = New Image( _renderTexture )
+		_renderImage.Handle=New Vec2f( 0, 0 )
+		_textureCanvas = New Canvas( _renderImage )
+		_textureCanvas.Font = App.DefaultFont
+	End
+
+
+	Method CycleLayout()
+		Select Layout
+		Case "fill"
+			Layout="letterbox"
+		Case "letterbox"
+			Layout="stretch"
+		Case "stretch"
+			Layout="float"
+		Case "float"
+'   			Layout="fill"
+			Layout = "letterbox"
+		End
+	End
+	
+	
+	'**************************************************** Protected Methods ****************************************************
+	'These allow RenderWindow to be extended without the need for OnUpdate and OnDraw to call Super.xxx().
+	'i.e: A MyGameEngine class can extend RenderWindow and override FrameDraw() and add specific features, leaving OnDraw() alone, as long as it is called somewhere.
+	
+	Protected
+	
+	Method WindowStart() Virtual
+		OnStart()
+	End
+	
+	Method FrameUpdate() Virtual
+		OnUpdate()
+	End
+	
+	Method FrameDraw() Virtual
+		OnDraw()
+	End
+	
+	Method DebugInfo() Virtual
+		Echo( "Window resolution: " + Frame.Width + ", " + Frame.Height )
+		Echo( "Virtual resolution: " + Width + ", " + Height )
+		Echo( "Mouse:" + Mouse.x + "," + Mouse.y )
+		Echo( "Camera:" + Int( camera.X ) + "," + Int( camera.Y ) )
+		Echo( "Layout: " + Layout )
+		If renderToTexture
+			Echo( "renderToTexture = True" )
+		Else
+			Echo( "renderToTexture = False" )
+		End
+		Echo( "Camera: " + camera.ToString() )
+		Echo( "FPS: " + FPS )
+	End
+	
+	Method SelectCanvas()
+		If renderToTexture
+			canvas = _textureCanvas
+		Else
+			canvas = _windowCanvas
+		End
+		canvas.Clear( bgColor )
+	End
+	
+	'**************************************************** Virtual Methods ****************************************************
+	Public
+	
+	Method OnStart() Virtual
+	End
+	
+	Method OnUpdate() Virtual
+	End
+	
+	Method OnDraw() Virtual
+	End
+
+	'**************************************************** Static functions ****************************************************
+	
+	Function Echo( text:String )
+		_echoStack.Push( text )
+	End
+	
+End
+