2
0
Mark Sibly 9 жил өмнө
parent
commit
9d420780e6

BIN
modules/mojo/bananas/commanche/assets/C1W.png


BIN
modules/mojo/bananas/commanche/assets/D1.png


BIN
modules/mojo/bananas/commanche/commanche.monkey2


+ 50 - 0
modules/mojo/bananas/joystick/joystick.monkey2

@@ -0,0 +1,50 @@
+
+Namespace test
+
+#Import "<std>"
+#Import "<mojo>"
+
+Using std..
+Using mojo..
+
+Class MyWindow Extends Window
+
+	Method New()
+		Super.New( "Joystick test",640,480 )
+	End
+
+	Method OnRender( canvas:Canvas ) Override
+	
+		App.RequestRender()
+	
+		canvas.DrawText( "NumJoysticks="+JoystickDevice.NumJoysticks(),0,0 )
+		
+		For Local i:=0 Until 4
+		
+			Local joy:=JoystickDevice.Open( i )
+			If Not joy Exit
+			
+			Local x:=i*160
+			
+			canvas.DrawText( "Name="+joy.Name,x,16 )
+			canvas.DrawText( "GUID="+joy.GUID,x,32 )
+			
+			For Local axis:=0 Until 6
+				canvas.DrawText( "Axis "+axis+"="+joy.GetAxis( axis ),x,(axis+3)*16 )
+			Next
+			
+		Next
+		
+	End
+	
+End
+
+Function Main()
+
+	New AppInstance
+	
+	New MyWindow
+	
+	App.Run()
+	
+End

+ 525 - 0
modules/mojo/bananas/life/life.monkey2

@@ -0,0 +1,525 @@
+'An implementation of Conway's Game of Life
+
+'http://en.wikipedia.org/wiki/Conway's_Game_of_Life
+
+'To try different patterns, pause the 'game', click cells,
+'then unpause.
+
+'For best performance run in "Release" mode.
+
+#Import "<std.monkey2>"
+#Import "<mojo.monkey2>"
+
+Using std..
+Using mojo..
+
+Function Main()
+
+	New AppInstance
+	
+	New LifeApp(1280, 720)
+	
+	App.Run()
+End
+
+'------------------------------
+
+Class LifeApp Extends Window
+
+	Field iterations:UInt				'number of iterations
+	Field lastMS:ULong					'time of last iteration 
+	
+	Field speed:UInt					'iterations per second
+	Field speedMin:UInt = 1
+	Field speedMax:UInt = 20	
+	
+	Field paused:Bool
+	Field suspended:Bool
+
+	Field grid:CellGrid					
+	Field gridRenderer:GridRenderer	
+	Field gridArea:Recti				'canvas area to draw the grid image onto
+	Field initialized:Bool = False		'false if grid and gridRenderer objects not yet created 
+
+	Field fontHeight:UInt = 30			'should be able to get this value from canvas.Font.Height but can't yet?
+
+	Field cellWidthPixels:UInt = 16
+	Field cellHeightPixels:UInt = 16
+
+	Method New(width:Int, height:Int)
+
+		'*** Resizing above certain values causes a crash, so disabled for now.
+		'Super.New("Conway's Game of Life", width, height, WindowFlags.Resizable)		
+		Super.New("Conway's Game of Life", width, height)
+		
+		ClearColor = Color.Black
+
+		'Disable vsync if possible.
+		SwapInterval = 0
+
+	End
+	
+	'Create and initialize a cell grid and an associated Grid rendering object.
+	Method Start:Void()
+		
+		paused = True
+		
+		iterations = 0
+		speed = speedMax / 2
+		
+		'Grid's top left pixel coordinate
+		Local gridTL := New Vec2i(10, fontHeight + 10)
+		
+		'Grid's bottom right pixel coordinate
+		Local gridBR := New Vec2i(Width - 10, Height - fontHeight - 10)
+		
+		'Define a target area on which to draw the grid, using the above vectors
+		gridArea = New Recti(gridTL, gridBR)
+		
+		'Calculate grid size based on the draw area's dimensions 
+		'and desired cell size in pixels.
+		Local gridCols := Floor(gridArea.Width / cellWidthPixels)
+		Local gridRows := Floor(gridArea.Height / cellHeightPixels)
+		
+		'Create the grid of cells.
+		grid = New CellGrid(gridCols, gridRows)		
+		
+		'Create the grid renderer, passing in a reference to the grid and the cell pixel dimensions.
+		gridRenderer = New GridRenderer(grid, cellWidthPixels, cellHeightPixels)
+
+		SeedRnd(Microsecs())
+		
+		paused = False
+		
+		lastMS = Millisecs()
+	
+		'Call the garbage collector. Maybe it can free some memory (or maybe not) 
+		'if this Start method was called during a WindowResize event.
+		GCCollect()
+	
+	End
+	
+	Method OnWindowEvent(event:WindowEvent) Override
+	
+		If event.Type = EventType.WindowResized
+
+			'Make a new grid and associated grid renderer based
+			'on the window's new dimensions.
+			Start()
+			
+			App.RequestRender()
+				
+		Elseif event.Type = EventType.WindowClose
+			
+			App.Terminate()
+			
+		Elseif event.Type=EventType.WindowGainedFocus
+		
+			suspended=False
+			
+			App.RequestRender()	'kick start rendering...
+			
+		Elseif event.Type=EventType.WindowLostFocus
+		
+			suspended=True
+					
+		Endif
+		
+	End
+	
+	Method OnKeyEvent( event:KeyEvent ) Override
+	
+		If event.Type = EventType.KeyUp
+				
+			Select event.Key
+		
+				Case Key.Escape
+					App.Terminate()
+		
+				Case Key.Space
+					paused = Not paused	
+					
+				Case Key.Up
+					SpeedUp()
+					
+				Case Key.Down
+					SpeedDown()
+					
+				Case Key.Tab
+					gridRenderer.ToggleGridOverlay()	
+					
+				Case Key.Enter
+					'Reset, but retain the current speed.
+					grid.Init()
+					iterations = 0
+					
+				Case Key.C
+					grid.Clear()
+
+			End
+		
+		Endif
+		
+	End
+	
+	Method OnMouseEvent( event:MouseEvent ) Override
+		
+		Select event.Type
+			Case EventType.MouseDown
+				If event.Button = 1
+					'if the clicked coordinate matches a cell then toggle it alive/dead.  
+					Local cell:Cell = gridRenderer.GetCell(event.Location.X - gridArea.TopLeft.X, event.Location.Y - gridArea.TopLeft.Y)
+					If cell Then cell.ToggleDead()
+				Endif
+				
+		End
+	
+	End
+	
+	Method OnRender(canvas:Canvas) Override
+	
+		If Not initialized
+			'This small If block only runs once at the start of the program.
+			'(Mojo must finish "constructing" before the Window's Width and Height properties
+			'return correct results - used in the Start method). 
+			Start()
+			initialized = True
+		Endif
+		
+		If Not suspended App.RequestRender()
+
+		canvas.Color = Color.White
+
+		gridRenderer.Render()
+
+		Local statusLine := "Iterations: " + iterations + "      FPS: " + Fps() + "      Speed: " + speed + "      "
+
+		canvas.DrawText(statusLine, 10, 10)
+		canvas.DrawText("[Space] - pause,    [Enter] - new,    [Up][Down] - speed,    [Tab] - toggle grid,    [c] - clear,    [Left-Click] - Toggle cell alive/dead" , 10, Height - fontHeight)
+
+		canvas.DrawImage(gridRenderer.Image, gridArea.TopLeft.X, gridArea.TopLeft.Y)
+
+		If paused
+			canvas.Color = Color.Red
+			canvas.DrawText("PAUSED - Press [space] to resume", 10 + canvas.Font.TextWidth(statusLine), 10)
+		endif
+
+		'---
+		
+		'Update the grid at the current speed (iterations per second). 
+		
+		If Not paused
+			
+			If Millisecs() >= (lastMS + (1000 / speed)) 
+				grid.Iterate()
+				iterations += 1
+				lastMS = Millisecs()
+			Endif
+		Endif
+
+		'---
+
+	End
+	
+	Method SpeedUp:Void()
+		If speed >= speedMax Then Return
+		speed += 1
+	End
+	
+	Method SpeedDown:Void()
+		If speed <= speedMin Then Return
+		speed -= 1
+	End
+	
+End
+
+
+'----------------------------------
+
+'This class renders a cell grid to an image. It can also return
+'a cell reference based on a given pixel coordinate.
+
+Class GridRenderer
+
+	Field _grid:CellGrid
+	
+	'Dimensions of the rectangle to render per cell.
+	Field _rw:UInt, _rh:UInt
+
+	'Image on which to render the grid. (And an associated canvas).
+	Field _image:Image
+	Field _iCanvas:Canvas
+	
+	Field _showGridOverlay:Bool
+	
+	Method New(grid:CellGrid, rw:UInt, rh:UInt) 
+		_grid = grid
+		_rw = rw
+		_rh = rh
+		_image = New Image(_grid.Cols * _rw + 1, _grid.Rows * _rh + 1)
+		_iCanvas = New Canvas(_image)
+		_showGridOverlay = True
+	End	
+
+	Property Image:Image()
+		Return _image
+	End
+
+	Method ToggleGridOverlay:Void()
+		_showGridOverlay = Not _showGridOverlay
+	End
+
+	Method GetCell:Cell(x:Float, y:Float)
+		
+		'Return a cell reference if a given pixel coordinate falls inside it. 		
+		Local col:UByte = Floor(x / _rw)
+		Local row:UByte = Floor(y / _rh)
+		
+		'Null will be returned if col or row are invalid. 
+		Return _grid.GetCell(col, row)
+
+	End
+	
+	Method Render:Void()
+		
+		'Render the grid (and overlay lines if necessary) onto the image canvas.
+		
+		_iCanvas.Clear(Color.Black)
+	
+		For Local c:Int = 0 until _grid.Cols
+			For Local r:Int = 0 Until _grid.Rows
+				Local curCell:Cell = _grid.GetCell(c, r)
+				_iCanvas.Color = Color.DarkGrey
+				If Not(curCell.Dead) Then _iCanvas.Color = Color.Green
+				_iCanvas.DrawRect((c * _rw), (r * _rh), _rw, _rh)	
+			Next
+		Next
+
+		If _showGridOverlay
+			_iCanvas.Color = Color.Grey
+			For Local x := 0 To _image.Width Step _rw
+				_iCanvas.DrawLine(x, 0, x, _image.Height) 
+			Next
+			For Local y := 0 to _image.Height Step _rh
+				_iCanvas.DrawLine(0, y, _image.Width, y) 
+			Next
+		Endif
+
+		_iCanvas.Flush()
+
+	End
+
+End
+
+
+'----------------------------------
+
+'A cell can either be dead or alive.
+'Pending dead = killed off in the second pass of the current iteration.
+
+Class Cell
+
+	Field _dead:Bool
+	Field _pendingDead:Bool
+	Field _col:UInt, _row:UInt
+	
+	Method New()
+		Dead = True
+		PendingDead = False
+	End
+	
+	Method ToggleDead:Void()
+		_dead = Not _dead
+		_pendingDead = _dead
+	End
+	
+	Method ApplyPending:Void()
+		Dead = PendingDead
+	End
+	
+	Property Dead:Bool()
+		Return _dead
+	Setter (value:Bool)
+		_dead = value
+	End
+		
+	Property PendingDead:Bool()
+		Return _pendingDead
+	Setter (value:Bool)
+		_pendingDead = value
+	End
+	
+	Property Col:UInt()
+		Return _col
+	Setter (value:UInt)
+		_col = value
+	End
+	
+	Property Row:UInt()
+		Return _row
+	Setter (value:UInt)
+		_row = value
+	End
+	
+End
+
+
+'----------------------------------
+
+
+Class CellGrid
+
+	Field cols:UInt
+	Field rows:UInt
+	Field data:Cell[,]
+
+	Method New(cols:UInt, rows:UInt)
+
+		Self.cols = cols
+		Self.rows = rows
+
+		data = New Cell[cols, rows]
+		For Local c:UInt = 0 Until cols
+			For Local r:UInt = 0 Until rows
+				data[c, r] = New Cell()
+				data[c, r].Col = c
+				data[c, r].Row = r
+			Next
+		Next
+
+		Init()
+
+	End
+
+	Property Cols:UInt()
+		Return cols
+	End
+	
+	Property Rows:UInt()
+		Return rows
+	End
+
+	Method GetCell:Cell(col:UInt, row:UInt)
+		If (col < cols) And (col >= 0) And (row < rows) And (row >= 0)
+			Return data[col, row]
+		Endif
+		
+		Return Null
+	End
+
+	Method Clear:Void()		
+		For Local c:UInt = 0 Until cols
+			For Local r:UInt = 0 Until rows
+				data[c, r].Dead = True
+			Next
+		Next
+	End
+
+	Method Init:Void()
+		For Local c:UInt = 0 Until cols
+			For Local r:UInt = 0 Until rows
+			
+				'Approx 25% of the cells will start alive
+				
+				If Floor(Rnd(0, 100)) <= 25 
+					data[c, r].Dead = False
+				Else
+					data[c, r].Dead = True
+				Endif
+				
+			Next
+		Next
+	End
+
+	Method Iterate:Void()
+	
+		'First pass - determine what cells will live and die
+		'Make the results 'pending'.
+		For Local c:UInt = 0 Until cols
+			For Local r:UInt = 0 Until rows
+				
+				Local curCell:Cell = data[c, r]
+				
+				curCell.PendingDead = True
+				
+				Local liveCount:UInt = CountLiveNeighbours(curCell.Col, curCell.Row)
+						
+				If curCell.Dead
+					If (liveCount = 3) Then curCell.PendingDead = False
+				Else
+					curCell.PendingDead = False
+					If (liveCount < 2) Or (liveCount > 3)
+						curCell.PendingDead = True
+					Endif
+				Endif
+				
+			Next		
+		Next
+
+		'Second pass - modify the grid by applying the pending changes.
+		For Local c:UInt = 0 Until cols
+			For Local r:UInt = 0 Until rows
+				data[c, r].ApplyPending()
+			Next
+		Next
+		
+	End
+
+	Method CountLiveNeighbours:UInt(cc:Int, cr:Int)
+	
+		Local count:UInt = 0
+		
+		' --- Boundary checking
+		
+		Local startc:Int = cc - 1
+		If startc < 0 Then startc = 0
+		
+		Local endc:Int = cc + 1
+		If endc >= cols Then endc = cols - 1
+		
+		Local startr:Int = cr - 1
+		If startr < 0 Then startr = 0
+		
+		Local endr:Int = cr + 1
+		If endr >= rows Then endr = rows - 1
+
+		' ---
+
+		'Count the live neighbours of the given cell.
+		For Local c:Int = startc To endc
+			For Local r:Int = startr To endr
+				If Not(data[c, r].Dead) Then count += 1
+			End
+		End
+		
+		'Adjust according to the given cell's status.
+		If Not(data[cc, cr].Dead) Then count -= 1
+		
+		Return count
+		
+	End
+
+End
+
+
+'----------------------------------
+
+
+'Frames-per-second function taken from the MX2 "Commanche" sample.
+Function Fps:Float()
+    
+    Global FPStime:Float, frameCounter:Float, frameTimer:Float, totalFrames:Float
+    
+    frameCounter+= 1
+    
+    totalFrames+= 1
+    
+    If frameTimer < Millisecs()
+		FPStime = frameCounter
+		frameTimer = 1000 + Millisecs()
+		frameCounter = 0  
+    Endif
+    
+    Return FPStime
+    
+End Function