From edeef06e143fbb5f6d60b8d0e90f9b4c47e96f55 Mon Sep 17 00:00:00 2001 From: Christophe Tes Date: Tue, 5 Jul 2022 22:14:59 +0200 Subject: [PATCH 1/5] Update languages.yml Added Wonkey extension to Monkey language --- lib/linguist/languages.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/linguist/languages.yml b/lib/linguist/languages.yml index fed3f5be9b..69bc4b83aa 100644 --- a/lib/linguist/languages.yml +++ b/lib/linguist/languages.yml @@ -4010,6 +4010,7 @@ Monkey: extensions: - ".monkey" - ".monkey2" + - ".wx" ace_mode: text tm_scope: source.monkey language_id: 236 From 41e1e812f2dee9d9278af05d61c24cd132299d79 Mon Sep 17 00:00:00 2001 From: Christophe Tes Date: Tue, 26 Jul 2022 11:02:49 +0200 Subject: [PATCH 2/5] Added Wonkey samples --- samples/Monkey/vec2.wx | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 samples/Monkey/vec2.wx diff --git a/samples/Monkey/vec2.wx b/samples/Monkey/vec2.wx new file mode 100644 index 0000000000..915fa846e9 --- /dev/null +++ b/samples/Monkey/vec2.wx @@ -0,0 +1,26 @@ +struct Vec2 + field x:T + field y:T + + method new( x:T, y:T ) + self.x = x + self.y = y + end + + operator+:Vec2( v:Vec2 ) + return new Vec2( x + v.x, y + v.y ) + end + + operator to:string() + return "Vec2(" + x + ", " + y + ")" + end +end + +alias Vec2 Vec2f + +'main entry +function main() + local v0:= new Vec2f( 10,20 ) + local v1:= new Vec2f( 30,40 ) + print v0 + v1 +end From bd0b3629c27974703a29d52ffd1daa421196abc5 Mon Sep 17 00:00:00 2001 From: Christophe Tes Date: Fri, 28 Oct 2022 13:56:36 +0200 Subject: [PATCH 3/5] Add more Wonkey samples --- samples/Monkey/effects.wx | 107 +++++++ samples/Monkey/life.wx | 524 ++++++++++++++++++++++++++++++++++ samples/Monkey/mojotest.wx | 96 +++++++ samples/Monkey/monkeyroids.wx | 461 ++++++++++++++++++++++++++++++ samples/Monkey/particles.wx | 100 +++++++ samples/Monkey/pbrspheres.wx | 87 ++++++ samples/Monkey/sdl2test.wx | 105 +++++++ samples/Monkey/terrain.wx | 118 ++++++++ samples/Monkey/viewlayout.wx | 178 ++++++++++++ samples/Monkey/water.wx | 83 ++++++ 10 files changed, 1859 insertions(+) create mode 100644 samples/Monkey/effects.wx create mode 100644 samples/Monkey/life.wx create mode 100644 samples/Monkey/mojotest.wx create mode 100644 samples/Monkey/monkeyroids.wx create mode 100644 samples/Monkey/particles.wx create mode 100644 samples/Monkey/pbrspheres.wx create mode 100644 samples/Monkey/sdl2test.wx create mode 100644 samples/Monkey/terrain.wx create mode 100644 samples/Monkey/viewlayout.wx create mode 100644 samples/Monkey/water.wx diff --git a/samples/Monkey/effects.wx b/samples/Monkey/effects.wx new file mode 100644 index 0000000000..810583d923 --- /dev/null +++ b/samples/Monkey/effects.wx @@ -0,0 +1,107 @@ +Namespace myapp + +#Import "" +#Import "" +#Import "" + +#Import "assets/" + +Using std.. +Using mojo.. +Using mojo3d.. + +Class MyWindow Extends Window + + Field _scene:Scene + + Field _camera:Camera + + Field _light:Light + + Field _donut:Model + + Field _bloom:BloomEffect + + Field _mono:MonochromeEffect + + Field _godrays:GodraysEffect + + Field _fxaa:FXAAEffect + + Method New( title:String="Simple mojo app",width:Int=640,height:Int=480,flags:WindowFlags=WindowFlags.Resizable|WindowFlags.HighDPI ) + + Super.New( title,width,height,flags ) + + _scene=Scene.GetCurrent() + _scene.ClearColor=Color.Sky + + 'create camera + ' + _camera=New Camera( self ) + _camera.Move( 0,10,-10 ) + New FlyBehaviour( _camera ) + + 'create light + ' + _light=New Light + _light.Rotate( 120,0,0 ) + + 'create effects + ' + _godrays=New GodraysEffect + _godrays.Enabled=false + _godrays.Light=_light + + _bloom=New BloomEffect + _bloom.Enabled=False + + _mono=New MonochromeEffect + _mono.Enabled=False + + _fxaa=New FXAAEffect + _fxaa.Enabled=False + + _scene.AddPostEffect( _bloom ) + _scene.AddPostEffect( _mono ) + _scene.AddPostEffect( _godrays ) + _scene.AddPostEffect( _fxaa ) + + Local material:=New PbrMaterial( New Color( 2,.5,0,1 ),0,1 ) + + _donut=Model.CreateTorus( 2,.5,48,24,material ) + _donut.AddComponent().Speed=New Vec3f( .1,.2,.3 ) + + _donut.Move( 0,10,0 ) + End + + Method OnRender( canvas:Canvas ) Override + + RequestRender() + + If Keyboard.KeyHit( Key.Key1 ) _godrays.Enabled=Not _godrays.Enabled + If Keyboard.KeyHit( Key.Key2 ) _bloom.Enabled=Not _bloom.Enabled + If Keyboard.KeyHit( Key.Key3 ) _mono.Enabled=Not _mono.Enabled + If Keyboard.KeyHit( Key.Key4 ) _fxaa.Enabled=Not _fxaa.Enabled + + _scene.Update() + + _scene.Render( canvas ) + + canvas.DrawText( "(1) Godrays="+_godrays.Enabled,0,0 ) + canvas.DrawText( "(2) Bloom="+_bloom.Enabled,0,16 ) + canvas.DrawText( "(3) Monochrome="+_mono.Enabled,0,32 ) + canvas.DrawText( "(4) FXAA="+_fxaa.Enabled,0,48 ) + End + +End + +Function Main() + +' SetConfig( "MOJO_OPENGL_PROFILE","es" ) + + New AppInstance + + New MyWindow + + App.Run() +End diff --git a/samples/Monkey/life.wx b/samples/Monkey/life.wx new file mode 100644 index 0000000000..2cce999b5a --- /dev/null +++ b/samples/Monkey/life.wx @@ -0,0 +1,524 @@ + +'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 "" +#Import "" + +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) + + 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 diff --git a/samples/Monkey/mojotest.wx b/samples/Monkey/mojotest.wx new file mode 100644 index 0000000000..cb5a4cf032 --- /dev/null +++ b/samples/Monkey/mojotest.wx @@ -0,0 +1,96 @@ + +#Import "" +#Import "" + +#Import "assets/RedbrushAlpha.png" + +Namespace mojotest + +Using std.. +Using mojo.. + +Class MojoTest Extends Window + + Field image:Image + + Field tx:Float,ty:Float + Field r:Float=1,g:Float=1,b:Float=1 + + Method New() + + ClearColor=New Color( 0,0,.5 ) + + image=Image.Load( "asset::RedbrushAlpha.png" ) + image.Handle=New Vec2f( .5,.5 ) + End + + Method OnRender( canvas:Canvas ) Override + + App.RequestRender() + + Local sz:=Sin( Millisecs()*.0007 ) * 32 + Local sx:=32+sz,sy:=32,sw:=Width-(64+sz*2),sh:=Height-(64+sz) + + canvas.Scissor=New Recti( sx,sy,sx+sw,sy+sh ) + canvas.Clear( New Color( 1,32.0/255.0,0,1 ) ) + + canvas.PushMatrix() + + canvas.Translate( tx,ty ) + canvas.Scale( Width/640.0,Height/480.0 ) + canvas.Translate( 320,240 ) + canvas.Rotate( Millisecs()*.0003 ) + canvas.Translate( -320,-240 ) + + canvas.Color=New Color( .5,1,0 ) + canvas.DrawRect( 32,32,640-64,480-64 ) + + canvas.Color=Color.Yellow + For Local y:=0 Until 480 + For Local x:=16 Until 640 Step 32 + canvas.Alpha=Min( Abs( y-240.0 )/120.0,1.0 ) + canvas.DrawPoint( x,y ) + Next + Next + canvas.Alpha=1 + + canvas.Color=New Color( 0,.5,1 ) + canvas.DrawOval( 320,240,320-64,240-64 ) + + canvas.Color=New Color( 1,0,.5 ) + canvas.DrawLine( 32,32,640-32,480-32 ) + canvas.DrawLine( 640-32,32,32,480-32 ) + + canvas.Color=New Color( r,g,b,Sin( Millisecs()*.003 ) *.5 +.5 ) + canvas.DrawImage( image,320,240 ) + + canvas.Color=New Color( 1,0,.5 ) + canvas.DrawPoly( New Float[]( 140.0,232.0, 320.0,224.0, 500.0,232.0, 500.0,248.0, 320.0,256.0, 140.0,248.0 ) ) + + canvas.Color=New Color( 1,.5,0 ) + canvas.DrawText( "The Quick Brown Fox Jumps Over The Lazy Dog",320,240,.5,.5 ) + + canvas.PopMatrix() + + canvas.Scissor=Rect + canvas.Color=Color.Red + canvas.DrawRect( 0,0,Width,1 ) + canvas.DrawRect( Width-1,0,1,Height ) + canvas.DrawRect( 0,Height-1,Width,1 ) + canvas.DrawRect( 0,0,1,Height-1 ) + + canvas.Color=Color.Blue + + End + +End + +Function Main() + + New AppInstance + + New MojoTest + + App.Run() + +End diff --git a/samples/Monkey/monkeyroids.wx b/samples/Monkey/monkeyroids.wx new file mode 100644 index 0000000000..ffd9abafc5 --- /dev/null +++ b/samples/Monkey/monkeyroids.wx @@ -0,0 +1,461 @@ + +Namespace asteroids + +#Import "" +#Import "" + +Using std.. +Using mojo.. + +Const SCREEN_WIDTH:Int = 640 +Const SCREEN_HEIGHT:Int = 480 +Const PI:Float = 3.14159265358979323846 + +Class MyWindow Extends Window + Const STATE_TITLE:Int= 1 + Const STATE_GAME:Int = 2 + Const STATE_GAME_OVER:Int = 3 + Global GameState:Int = STATE_TITLE + + Field player:Player + Field score:Int + Field level:Int + Field bestScore:Int + Field asteroidsNum:Int + Field asteroidsSize:Int + + Method New(title:String, width:Int, height:Int) + Super.New(title, width, height) + ClearColor = Color.Black + SwapInterval = 1 + SeedRnd(Millisecs()) + Reset() + 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 OnRender(canvas:Canvas) Override + App.RequestRender() + + Select GameState + Case STATE_TITLE + Asteroid.UpdateAll() + If Keyboard.KeyHit(Key.Space) + SetState(STATE_GAME) + End + Case STATE_GAME + player.Update() + Bullet.UpdateAll() + Asteroid.UpdateAll() + CheckCollisions() + Case STATE_GAME_OVER + Asteroid.UpdateAll() + If Keyboard.KeyHit(Key.Space) + SetState(STATE_TITLE) + Reset() + End + End + + Select GameState + Case STATE_TITLE + DrawTitleScreen(canvas) + Case STATE_GAME + DrawGame(canvas) + Case STATE_GAME_OVER + DrawGameOver(canvas) + End + End + + Method SetState(state:Int) + GameState = state + End + + Method DrawTitleScreen(canvas:Canvas) + Asteroid.RenderAll(canvas) + canvas.DrawText("MONKEYROIDS: RETURN OF THE CHIMP!", SCREEN_WIDTH / 2, (SCREEN_HEIGHT / 2) - 20, 0.5, 0.5) + canvas.DrawText("BEST SCORE: " + bestScore, (SCREEN_WIDTH / 2), (SCREEN_HEIGHT / 2), 0.5, 0.5) + canvas.DrawText("PRESS TO PLAY", SCREEN_WIDTH / 2, (SCREEN_HEIGHT / 2) + 20, 0.5, 0.5) + End + + Method DrawHUD:Void(canvas:Canvas) + canvas.DrawText("LEVEL: " + level, 0, 0) + canvas.DrawText("SCORE: " + score, SCREEN_WIDTH, 0, 1, 0) + canvas.DrawText("BULLETS#: " + Bullet.list.Count(), SCREEN_WIDTH/2, 0, 0.5, 0) + canvas.DrawText("ASTEROIDS#: " + Asteroid.list.Count(), SCREEN_WIDTH/2, 20, 0.5, 0) + End + + Method DrawGame(canvas:Canvas) + player.Render(canvas) + Bullet.RenderAll(canvas) + Asteroid.RenderAll(canvas) + DrawHUD(canvas) + End + + Method DrawGameOver(canvas:Canvas) + Asteroid.RenderAll(canvas) + canvas.DrawText("GAME OVER!", SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 - 20, 0.5, 0.5) + canvas.DrawText("SCORE: " + score, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, 0.5, 0.5) + canvas.DrawText("BEST SCORE: " + Self.bestScore, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 + 20, 0.5, 0.5) + canvas.DrawText("PRESS TO RETURN TO THE TITLE SCREEN", SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 + 40, 0.5, 0.5) + End + + Method CheckCollisions() + Local asteroidToRemove:Asteroid + + Local ait := Asteroid.list.All() + While Not ait.AtEnd + Local a:Asteroid = ait.Current + If Not a.dead And Dist(player.x, player.y, a.x, a.y) <= a.avgrad + player.shield -= 10 + a.dead = True + End + For Local b:Bullet = Eachin Bullet.list + If a <> Null And Not a.dead + If Dist(b.x, b.y, a.x, a.y) <= a.avgrad + a.life -= 1 + b.life = 0 + End + If a.life <= 0 + a.dead = True + End + End + Next + If a.dead + ait.Erase() + asteroidToRemove = a + Else + ait.Bump() + End + + End + + If asteroidToRemove <> Null + If asteroidToRemove.size > 1 + score += 5 + For Local t:Int = 1 To 2 + New Asteroid(asteroidToRemove.x, asteroidToRemove.y, Rnd(-5, 5), Rnd(-5, 5), asteroidToRemove.size - 1) + Next + End + End + + If Asteroid.list.Count() = 0 + level += 1 + asteroidsNum += 1 + asteroidsSize += 1 + CreateAsteroids(asteroidsNum, asteroidsSize) + End + End + + Method Reset() + Bullet.list.Clear() + Asteroid.list.Clear() + level = 1 + asteroidsNum = 2 + asteroidsSize = 3 + score = 0 + player = New Player(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2) + CreateAsteroids(asteroidsNum, asteroidsSize) + End + + Method CreateAsteroids:Void(num:Int, size:Int) + Asteroid.list.Clear() + Bullet.list.Clear() + Local tx:Float + Local ty:Float + For Local t:Int = 1 To num + Repeat + tx = Rnd(640) + ty = Rnd(480) + Until (tx < 280 Or tx > 360) And (ty < 200 Or ty > 280) + New Asteroid(tx, ty, Rnd(-2, 2), Rnd(-2, 2), size + Rnd(1)) + Next + End +End + +Class Sprite + Field dead:Bool + Field xv:Float, yv:Float + Field x:Float, y:Float + Field rotation:Float + Field canvas:Canvas +End + +Class Asteroid Extends Sprite + Global list:List = New List + Field ang:Float, angvel:Float + Field rad:Float[] = New Float[9] + Field avgrad:Float + Field size:Int + Field life:Int + Field cr:Float, cg:Float, cb:Float + + Method New(x:Float, y:Float, xv:Float, yv:Float ,size:Int) + Self.x = x + Self.y = y + Self.xv = xv + Self.yv = yv + Self.ang = Rnd(360) + Self.angvel = Rnd(-6, 6) + Self.size = size + Self.life = size + Self.cr = 1 + Self.cg = 1 + Self.cb = 1 + ' Create "Rockiness" + Self.avgrad = 0 + For Local t:Int = 0 To 7 + Self.rad[t] = size * 8.0 + Rnd(-size * 4.0, size * 4.0) + Self.avgrad = Self.avgrad + Self.rad[t] + Next + Self.avgrad = Self.avgrad /6.0 + Self.rad[8] = Self.rad[0] + Self.dead = False + + list.AddLast(self) + End + + Function RenderAll:Void(canvas:Canvas) + If Not list Return + For Local a:Asteroid = Eachin list + a.Render(canvas) + Next + End + + Function UpdateAll:Void() + If Not list Return + For Local a:Asteroid = Eachin list + a.Update() + Next + End + + Method Update:Void() + 'If dead Return + Self.x += Self.xv * Delta.delta + Self.y += Self.yv * Delta.delta + Self.rotation += Self.angvel * Delta.delta + + If Self.x < -Self.avgrad Then Self.x = Self.x + SCREEN_WIDTH + Self.avgrad *2 + If Self.x > SCREEN_WIDTH + Self.avgrad Then Self.x = Self.x - SCREEN_WIDTH - Self.avgrad *2 + If Self.y < -Self.avgrad Then Self.y = Self.y + SCREEN_HEIGHT + Self.avgrad *2 + If Self.y > SCREEN_HEIGHT + Self.avgrad Then Self.y = Self.y - SCREEN_HEIGHT - Self.avgrad *2 + End + + Method Render:Void(canvas:Canvas) + 'If dead Return + Local tmul:Float = 360.0 / 8.0 + canvas.Color = New Color( cr, cg, cb) + For Local t:Int = 0 To 7 + local x1:Float = x - (Sin(ToRadians(rotation + (t) * tmul)) * rad[t]) + Local y1:Float = y - (Cos(ToRadians(rotation + (t) * tmul)) * rad[t]) + Local x2:Float = x - (Sin(ToRadians(rotation + (t + 1) * tmul))* rad[t + 1]) + Local y2:Float = y - (Cos(ToRadians(rotation + (t + 1) * tmul)) * rad[t + 1]) + canvas.DrawLine(x1, y1, x2, y2) + Next + End +End + +Class Bullet Extends Sprite + Global list:List = New List + Field life:Float + Field cr:Float, cg:Float, cb:Float + + Method New(x:Float, y:Float, xv:Float, yv:Float, life:Float, cr:Float, cg:Float, cb:Float) + Self.x = x + Self.y = y + Self.xv = xv + Self.yv = yv + Self.life = life + Self.cr = cr + Self.cg = cg + Self.cb = cb + + list.AddLast(Self) + End + + Function UpdateAll:Void() + If Not list Return + + Local it := list.All() + While Not it.AtEnd + Local b:Bullet = it.Current + b.Update() + If b.life <= 0 + it.Erase() + Else + it.Bump() + End + End + End + + Method Update:Void() + If dead Return + x += xv * Delta.delta + y += yv * Delta.delta + + life -= Delta.delta + If x < 0 x = SCREEN_WIDTH + If x > SCREEN_WIDTH x = 0 + If y < 0 y = SCREEN_HEIGHT + If y > SCREEN_HEIGHT y = 0 + End + + Function RenderAll:Void(canvas:Canvas) + If Not list Return + For Local b:Bullet = Eachin list + b.Render(canvas) + Next + End + + Method Render:Void(canvas:Canvas) + If dead Return + Local tmul:Float + If life <= 25.0 + tmul = life / 25.0 + Else + tmul = 1.0 + End + canvas.Color = New Color( cr * tmul, cg * tmul, cb * tmul ) + canvas.DrawLine(x, y, x + xv, y + yv) + End +End + + +Class Player Extends Sprite + Field angVel:Float + Field velmul:Float + Field vel:Float + Field acc:Float + Field drag:Float + Field xv:Float, yv:Float + Field xa:Float, ya:Float + Field firedel:Float + + Field shipAngvel:Float + Field shipAcc:Float + Field shipVelmul:Float + Field shipFiredel:Float + + Field shield:Float + + Method New(x:Float, y:Float) + Self.x = x + Self.y = y + Self.shipAngvel = 6 + Self.shipAcc = 0.16 + Self.shipVelmul = -0.0005 + Self.shipFiredel = 5 + Self.shield = 100 + End + + Method Controls() + If Keyboard.KeyDown(Key.Up) Or Keyboard.KeyDown(Key.W) + acc = shipAcc + drag = vel * shipVelmul + Elseif Keyboard.KeyDown(Key.Down) Or Keyboard.KeyDown(Key.S) + drag = vel * shipVelmul * 50 + Else + acc = 0 + drag = 0 + End + + If Keyboard.KeyDown(Key.Left) Or Keyboard.KeyDown(Key.A) + rotation += shipAngvel * Delta.delta + Elseif Keyboard.KeyDown(Key.Right) Or Keyboard.KeyDown(Key.D) + rotation -= shipAngvel * Delta.delta + End + + If Keyboard.KeyDown(Key.Space) And Self.firedel <= 0 + Local tang:Float = Rnd(-.01, .01) + Local x1:Float = x - (Sin(ToRadians(rotation)) * 8) + Local y1:Float = y - (Cos(ToRadians(rotation)) * 8) + Local xv1:Float = xv - (Sin(ToRadians(rotation) + tang ) * 12) + Local yv1:Float = yv - (Cos(ToRadians(rotation) + tang ) * 12) + Local life:Int = 45 + New Bullet(x1, y1, xv1, yv1, life, 1, 1, 0) + firedel = shipFiredel + End + firedel -= Delta.delta + + End + + Method Update() + Controls() + xa = (drag * xv) - (Sin(ToRadians(rotation)) * acc) + ya = (drag * yv) - (Cos(ToRadians(rotation)) * acc) + xv += xa * Delta.delta + yv += ya * Delta.delta + x += xv * Delta.delta + y += yv * Delta.delta + vel = Dist(0, 0, xv, yv) + + If x < 0 x = SCREEN_WIDTH + If x > SCREEN_WIDTH x = 0 + If y < 0 y = SCREEN_HEIGHT + If y > SCREEN_HEIGHT y = 0 + + If shield <= 0 + If Game.score > Game.bestScore + Game.bestScore = Game.score + End + Game.SetState(Game.STATE_GAME_OVER) + End + End + + Method Render(canvas:Canvas) + + Local x1:Float = x - (Sin(ToRadians(rotation)) * 10) + Local y1:Float = y - (Cos(ToRadians(rotation)) * 10) + + Local x2:Float = x - (Sin(ToRadians(rotation + 140)) * 8) + Local y2:Float = y - (Cos(ToRadians(rotation + 140)) * 8) + + Local x3:Float = x - (Sin(ToRadians(rotation - 140)) * 8) + Local y3:Float = y - (Cos(ToRadians(rotation - 140)) * 8) + + canvas.Color = Color.White + canvas.DrawLine(x1, y1, x2, y2) + canvas.DrawLine(x2, y2, x3, y3) + canvas.DrawLine(x3, y3, x1, y1) + + canvas.Alpha = .5 + If shield < 50 Then canvas.Color = New Color(1, 0, 0) + canvas.DrawRect(10, SCREEN_HEIGHT - 15, Self.shield, 10) + canvas.Alpha = 1 + + End +End + +'TODO: Delta timing class +Class Delta + Global delta:Float = 0.5 +End + +Global Game:MyWindow + +Function Main() + New AppInstance + Game = New MyWindow("Monkeyroids: Return of the Chimp!", SCREEN_WIDTH, SCREEN_HEIGHT) + App.Run() +End + +Function Dist:Float(x1:Float, y1:Float, x2:Float, y2:Float) + Return Sqrt(Pow((x1 - x2), 2) + Pow((y1 - y2), 2)) +End + +Function ToDegrees:Float(rad:Float) + Return rad * 180.0 / PI +End + +Function ToRadians:Float(degree:Float) + Return degree * PI / 180.0 +End diff --git a/samples/Monkey/particles.wx b/samples/Monkey/particles.wx new file mode 100644 index 0000000000..ada48a5b88 --- /dev/null +++ b/samples/Monkey/particles.wx @@ -0,0 +1,100 @@ +Namespace myapp + +#Import "" +#Import "" +#Import "" + +Using std.. +Using mojo.. +Using mojo3d.. + +Class MyWindow Extends Window + + Field _scene:Scene + + Field _camera:Camera + + Field _light:Light + + Field _ground:Model + + Field _particles:ParticleSystem + + Method New( title:String="Simple mojo app",width:Int=640,height:Int=480,flags:WindowFlags=WindowFlags.Resizable|WindowFlags.HighDPI ) + + Super.New( title,width,height,flags ) + + _scene=Scene.GetCurrent() + +' _scene.SkyTexture=Texture.Load( "asset::miramar-skybox.jpg",TextureFlags.FilterMipmap|TextureFlags.Cubemap ) + + _scene.FogColor=Color.Sky + _scene.FogNear=20 + _scene.FogFar=1000 + + 'create camera + ' + _camera=New Camera( Self ) + _camera.Near=.01 + _camera.Move( 0,1,-1 ) + New FlyBehaviour( _camera ) + + 'create light + ' + _light=New Light + _light.Rotate( 60,45,0 ) 'aim directional light 'down' - Pi/2=90 degrees. + + 'create ground + ' + _ground=Model.CreateBox( New Boxf( -50,-1,-50,50,0,50 ),1,1,1,New PbrMaterial( Color.Green * .5 ) ) + + _particles=New ParticleSystem( 15000 ) + _particles.RotateX( -90 ) 'point upwards! + + Local pmaterial:=_particles.Material +' pmaterial.ColorTexture=Texture.Load( "asset::bluspark.png",TextureFlags.FilterMipmap ) + + Local pbuffer:=_particles.ParticleBuffer + pbuffer.Gravity=New Vec3f( 0,-9.81,0 ) 'gravity in world space in m/s^2. + pbuffer.Duration=2.5 'how long a single particle lasts in seconds. + pbuffer.Fade=0.0 'how long before paticle starts fading out in seconds. + pbuffer.Colors=New Color[]( Color.White,Color.Yellow,Color.Orange,Color.Red ) + pbuffer.ConeAngle=30 'angle of particle emission cone. + pbuffer.MinVelocity=15.0 'min particle velocity. + pbuffer.MaxVelocity=20.0 'max particle velocity. + pbuffer.MinSize=8.0 'min particle size. + pbuffer.MaxSize=12.0 'max particle size. + + For Local an:=0 Until 360 Step 45 + + Local pivot:=New Pivot + pivot.RotateY( an ) + pivot.MoveZ( 20 ) + pivot.Visible=True + + _particles.Copy( pivot ) + Next + + End + + Method OnRender( canvas:Canvas ) Override + + RequestRender() + + _scene.Update() + + _scene.Render( canvas ) + + canvas.DrawText( "Width="+Width+", Height="+Height+", FPS="+App.FPS,0,0 ) + End + +End + +Function Main() + + New AppInstance + + New MyWindow + + App.Run() +End diff --git a/samples/Monkey/pbrspheres.wx b/samples/Monkey/pbrspheres.wx new file mode 100644 index 0000000000..37bb2aea7a --- /dev/null +++ b/samples/Monkey/pbrspheres.wx @@ -0,0 +1,87 @@ + +Namespace myapp + +#Import "" +#Import "" +#Import "" + +#Import "assets/miramar-skybox.jpg" +#Import "assets/spheres.gltf" + +Using std.. +Using mojo.. +Using mojo3d.. + +Class MyWindow Extends Window + + Field _scene:Scene + + Field _camera:Camera + + Field _light:Light + + Field _ground:Model + + Field _spheres:Model + + Method New( title:String="Simple mojo app",width:Int=640,height:Int=480,flags:WindowFlags=WindowFlags.Resizable|WindowFlags.HighDPI ) + + Super.New( title,width,height,flags ) + + _scene=New Scene + + _scene.SkyTexture=Texture.Load( "asset::miramar-skybox.jpg",TextureFlags.FilterMipmap|TextureFlags.Cubemap|TextureFlags.Envmap ) + + 'create camera + ' + _camera=New Camera( Self ) + _camera.Near=.01 + _camera.Move( 0,10,-10 ) + + New FlyBehaviour( _camera ) + + 'create light + ' + _light=New Light + _light.Rotate( 54,144,0 ) 'calibrated so specular highlight matches sun on sky texture! + + Local godrays:=New GodraysEffect( _light ) + _scene.AddPostEffect( godrays ) + + 'create ground + ' + Local mesh:=Mesh.CreateBox( New Boxf( -50,-1,-50,50,0,50 ),1,1,1 ) + + Local material:=New PbrMaterial( Color.Green,0,.5 ) + + _ground=New Model( mesh,material ) + + 'create spheres + + _spheres=Model.Load( "asset::MetalRoughSpheres.gltf" ) + + _spheres.Move( 0,10,0 ) + + End + + Method OnRender( canvas:Canvas ) Override + + RequestRender() + + _scene.Update() + + _scene.Render( canvas ) + + canvas.DrawText( "FPS="+App.FPS,Width,0,1,0 ) + End + +End + +Function Main() + + New AppInstance + + New MyWindow + + App.Run() +End diff --git a/samples/Monkey/sdl2test.wx b/samples/Monkey/sdl2test.wx new file mode 100644 index 0000000000..6b825917de --- /dev/null +++ b/samples/Monkey/sdl2test.wx @@ -0,0 +1,105 @@ + +#import "" +#Import "" + +Namespace sdl2test + +Using sdl2.. +Using opengl.. + +Class SdlWindow + + Field sdlWindow:SDL_Window Ptr + + Field sdlGLContext:SDL_GLContext + + Method New() + + SDL_Init( SDL_INIT_VIDEO ) + + libc.atexit( SDL_Quit ) + + #If __DESKTOP_TARGET__ + SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK,SDL_GL_CONTEXT_PROFILE_COMPATIBILITY ) + #Else + SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK,SDL_GL_CONTEXT_PROFILE_ES ) + #Endif + + SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION,2 ) + SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION,1 ) + SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER,1 ) + SDL_GL_SetAttribute( SDL_GL_RED_SIZE,8 ) + SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE,8 ) + SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE,8 ) + + sdlWindow=SDL_CreateWindow( "SDL2 OpenGL Window",SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,640,480,SDL_WINDOW_OPENGL ) + + sdlGLContext=SDL_GL_CreateContext( sdlWindow ) + + SDL_GL_MakeCurrent( sdlWindow,sdlGLContext ) + + wxglInit() + End + + Method Run() + + Repeat + + Local event:SDL_Event + + While( SDL_PollEvent( Varptr event ) ) + + Select event.type + + Case SDL_WINDOWEVENT + + Local wevent:=Cast( Varptr event ) + + Select wevent->event + + Case SDL_WINDOWEVENT_CLOSE + + libc.exit_(0) + + End + + End + + Wend + + OnRender() + + SDL_GL_SwapWindow( sdlWindow ) + + Forever + + End + + Method OnRender() + + glClearColor( 1,1,0,1 ) + + glClear( GL_COLOR_BUFFER_BIT ) + + glEnable( GL_SCISSOR_TEST ) + + For Local y:=0 Until 256 + + glScissor( 0,y,640,1 ) + glClearColor( y/256.0,0,0,1 ) + glClear( GL_COLOR_BUFFER_BIT ) + + Next + + glDisable( GL_SCISSOR_TEST ) + End + +End + + +Function Main() + + Local window:=New SdlWindow + + window.Run() +End diff --git a/samples/Monkey/terrain.wx b/samples/Monkey/terrain.wx new file mode 100644 index 0000000000..20d9924927 --- /dev/null +++ b/samples/Monkey/terrain.wx @@ -0,0 +1,118 @@ + +Namespace myapp + +#Import "" +#Import "" +#Import "" + +#Import "assets/miramar-skybox.jpg" +#Import "assets/terrain_256.png" +#Import "assets/mossy.pbr/@/mossy.pbr" + +Using std.. +Using mojo.. +Using mojo3d.. + +Class MyWindow Extends Window + + Field _scene:Scene + + Method New( title:String="Simple mojo app",width:Int=640,height:Int=480,flags:WindowFlags=WindowFlags.Resizable|WindowFlags.HighDPI ) + + Super.New( title,width,height,flags ) + + CreateScene() + End + + Method CreateTerrain:Model() + + Local box:=New Boxf( -256,0,-256,256,32,256 ) + + Local hmap:=Pixmap.Load( "asset::terrain_256.png",PixelFormat.I8 ) + + Local material:=PbrMaterial.Load( "asset::mossy.pbr" ) + material.ScaleTextureMatrix( 64,64 ) + + 'model+mesh + Local terrain:=Model.CreateTerrain( hmap,box,material ) + terrain.CastsShadow=False + + Local collider:=New TerrainCollider( terrain ) + collider.Heightmap=hmap + collider.Bounds=box + + Local body:=New RigidBody( terrain ) + body.Mass=0 + + Return terrain + End + + Method CreateBodies() + + Local material:=New PbrMaterial( Color.Brown,1,.5 ) + + Local box:=New Boxf( -.5,.5 ) + + Local model:=Model.CreateBox( box,1,1,1,material ) + + Local collider:=model.AddComponent() + collider.Box=box + + Local body:=model.AddComponent() + + For Local i:=0 Until 360 Step 6 + + Local copy:=model.Copy() + + copy.Rotate( 0,i,0 ) + + copy.Move( 0,40+i*.1,Rnd( 5,10 ) ) + Next + + model.Destroy() + End + + Method CreateScene() + + _scene=New Scene + _scene.SkyTexture=Texture.Load( "asset::miramar-skybox.jpg",TextureFlags.FilterMipmap|TextureFlags.Cubemap ) + _scene.FogColor=New Color( .75,1,0 )*.25 + _scene.FogNear=75 + _scene.FogFar=100 + + Local camera:=New Camera( Self ) + camera.Near=.1 + camera.Far=100 + camera.Move( 0,40,0 ) + New FlyBehaviour( camera ) + + Local light:=New Light + light.CastsShadow=True + light.RotateX( 45 ) + + CreateTerrain() + + CreateBodies() + End + + Method OnRender( canvas:Canvas ) Override + + RequestRender() + + _scene.Update() + + _scene.Render( canvas ) + + canvas.DrawText( "FPS="+App.FPS,Width,0,1,0 ) + End + +End + +Function Main() + + New AppInstance + + New MyWindow + + App.Run() +End diff --git a/samples/Monkey/viewlayout.wx b/samples/Monkey/viewlayout.wx new file mode 100644 index 0000000000..e9887c1375 --- /dev/null +++ b/samples/Monkey/viewlayout.wx @@ -0,0 +1,178 @@ +#rem + +A slightly more complicated window example. + +The example implements a resizable window with virtual resolution support via the "letterbox" and "stretch" layout modes, and shows +some simple keyboard/mouse event handling. + +#end + +Namespace test + +#Import "" +#Import "" + +Using std.. +Using mojo.. + +Class MyWindow Extends Window + + Field virtualRes:=New Vec2i( 320,240 ) + + Method New( title:String,width:Int,height:Int,flags:WindowFlags=WindowFlags.Resizable ) + + 'Call super class constructor + ' + Super.New( title,width,height,flags ) + + 'Set initial layout (this is the default for Windows). + ' + Layout="fill" + + 'Window clear color - for "letterbox" and "float" layouts, this is effectively the border color. + ' + ClearColor=Color.Black + + 'Set minimum view size + ' + MinSize=New Vec2i( 200,140 ) + + 'Set view background color. + ' + Style.BackgroundColor=Color.DarkGrey + + End + + Method OnRender( canvas:Canvas ) Override + + 'This is necessary for 'continuous' rendering. + ' + 'Without it, OnRender will only be called when necessary, eg: when window is resized. + ' + App.RequestRender() + + 'Gets mouse location in 'view' coordinates. + ' + Local mouse:=Mouse.Location + + 'Render! + ' + Local h:=canvas.Font.Height + + canvas.DrawText( "Size="+Rect.Size,0,0 ) + canvas.DrawText( "Mouse="+mouse,0,h ) + canvas.DrawText( "Layout=~q"+Layout+"~q ('L' to cycle)",0,h*2 ) + + If Layout="float" + canvas.DrawText( "Resolution="+virtualRes+" ('R' to cycle)",0,h*3 ) + canvas.DrawText( "Gravity="+Gravity+" ('G' to cycle)",0,h*4 ) + Else If Layout="letterbox" + canvas.DrawText( "Resolution="+virtualRes+" ('R' to cycle)",0,h*3 ) + canvas.DrawText( "Gravity="+Gravity+" ('G' to cycle)",0,h*4 ) + Else If Layout="stretch" + canvas.DrawText( "Resolution="+virtualRes+" ('R' to cycle)",0,h*3 ) + Endif + + canvas.DrawText( "Hello World!",Width/2,Height/2,.5,.5 ) + End + + 'Measured out view. + ' + 'This is used by the "float", "letterbox" and "stretch" layouts. + ' + Method OnMeasure:Vec2i() Override + + Return virtualRes + End + + 'Process a KeyEvent. + ' + 'Needed because there's no App.KeyHit yet! + ' + Method OnKeyEvent( event:KeyEvent ) Override + + Select event.Type + Case EventType.KeyDown + Select event.Key + Case Key.L + CycleLayout() + Case Key.G + CycleGravity() + Case Key.R + CycleVirtualRes() + End + End + + End + + 'Process a MouseEvent. + ' + 'Note: event.Location property is in 'view space' coordinates. + ' + Method OnMouseEvent( event:MouseEvent ) Override + End + + Method OnWindowEvent( event:WindowEvent ) Override + Select event.Type + Case EventType.WindowClose + Print "Window close" + App.Terminate() + Case EventType.WindowMoved + Print "Window moved to:"+Frame.Origin + Case EventType.WindowResized + Print "Window resized to:"+Frame.Size + App.RequestRender() 'note: we do this to trigger a render when window is being 'modally resized'. + End + End + + Method CycleLayout() + Select Layout + Case "fill" + Layout="letterbox" + Case "letterbox" + Layout="stretch" + Case "stretch" + Layout="float" + Case "float" + Layout="fill" + End + virtualRes=New Vec2i( 320,240 ) + Gravity=New Vec2f( .5,.5 ) + End + + Method CycleGravity() + Local gravity:=Gravity + gravity.x+=.5 + If gravity.x>1 + gravity.x=0 + gravity.y+=.5 + If gravity.y>1 gravity.y=0 + Endif + Gravity=gravity + End + + Method CycleVirtualRes() + Select virtualRes.x + Case 320 + virtualRes=New Vec2i( 640,480 ) '4:3 + Case 640 + virtualRes=New Vec2i( 1024,768 ) '4:3 + Case 1024 + virtualRes=New Vec2i( 1280,720 ) '16:9 + Case 1280 + virtualRes=New Vec2i( 1920,1080 ) '16:9 + Case 1920 + virtualRes=New Vec2i( 320,240 ) '4:3 + End + End + +End + +Function Main() + + New AppInstance + + New MyWindow( "Simple Window Demo!",640,512 ) + + App.Run() +End diff --git a/samples/Monkey/water.wx b/samples/Monkey/water.wx new file mode 100644 index 0000000000..b494a8610f --- /dev/null +++ b/samples/Monkey/water.wx @@ -0,0 +1,83 @@ +Namespace myapp + +#Import "" +#Import "" +#Import "" + +#Import "assets/miramar-skybox.jpg" +#Import "assets/water_normal0.png" +#Import "assets/water_normal1.png" + +Using std.. +Using mojo.. +Using mojo3d.. + +Class MyWindow Extends Window + + Field _scene:Scene + + Field _camera:Camera + + Field _light:Light + + Field _water:Model + + Method New( title:String="Simple mojo app",width:Int=640,height:Int=480,flags:WindowFlags=WindowFlags.Resizable|WindowFlags.HighDPI ) + + Super.New( title,width,height,flags ) + + _scene=New Scene + + _scene.SkyTexture=Texture.Load( "asset::miramar-skybox.jpg",TextureFlags.FilterMipmap|TextureFlags.Cubemap|TextureFlags.Envmap ) + + 'create camera + ' + _camera=New Camera( self ) + _camera.Move( 0,10,-10 ) + _camera.AddComponent() + + 'create light + ' + _light=New Light + _light.Rotate( 54,144,0 ) 'calibrated so specular highlight matches sun on sky texture! + + 'create water material + ' + Local waterMaterial:=New WaterMaterial + + waterMaterial.ScaleTextureMatrix( 10,10 ) + + waterMaterial.ColorFactor=Color.SeaGreen + + waterMaterial.NormalTextures=New Texture[]( + Texture.Load( "asset::water_normal0.png",TextureFlags.WrapST|TextureFlags.FilterMipmap ), + Texture.Load( "asset::water_normal1.png",TextureFlags.WrapST|TextureFlags.FilterMipmap ) ) + + waterMaterial.Velocities=New Vec2f[]( + New Vec2f( .01,.03 ), + New Vec2f( .02,.05 ) ) + + 'create water + ' + _water=Model.CreateBox( New Boxf( -50,-1,-50,50,0,50 ),1,1,1,waterMaterial ) + End + + Method OnRender( canvas:Canvas ) Override + + RequestRender() + + _scene.Update() + + _scene.Render( canvas ) + End + +End + +Function Main() + + New AppInstance + + New MyWindow + + App.Run() +End From 1a2649950e9d44fa151c7faf18a665eb8113a8fe Mon Sep 17 00:00:00 2001 From: Christophe Tes Date: Fri, 18 Nov 2022 19:26:00 +0100 Subject: [PATCH 4/5] Remove large sample `life.wx` --- samples/Monkey/life.wx | 524 ----------------------------------------- 1 file changed, 524 deletions(-) delete mode 100644 samples/Monkey/life.wx diff --git a/samples/Monkey/life.wx b/samples/Monkey/life.wx deleted file mode 100644 index 2cce999b5a..0000000000 --- a/samples/Monkey/life.wx +++ /dev/null @@ -1,524 +0,0 @@ - -'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 "" -#Import "" - -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) - - 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 From d0979eee9991de6e2b463bce26d8616c8f7cf6d2 Mon Sep 17 00:00:00 2001 From: Christophe Tes Date: Fri, 18 Nov 2022 19:26:23 +0100 Subject: [PATCH 5/5] Remove large sample `monkeyroidswx` --- samples/Monkey/monkeyroids.wx | 461 ---------------------------------- 1 file changed, 461 deletions(-) delete mode 100644 samples/Monkey/monkeyroids.wx diff --git a/samples/Monkey/monkeyroids.wx b/samples/Monkey/monkeyroids.wx deleted file mode 100644 index ffd9abafc5..0000000000 --- a/samples/Monkey/monkeyroids.wx +++ /dev/null @@ -1,461 +0,0 @@ - -Namespace asteroids - -#Import "" -#Import "" - -Using std.. -Using mojo.. - -Const SCREEN_WIDTH:Int = 640 -Const SCREEN_HEIGHT:Int = 480 -Const PI:Float = 3.14159265358979323846 - -Class MyWindow Extends Window - Const STATE_TITLE:Int= 1 - Const STATE_GAME:Int = 2 - Const STATE_GAME_OVER:Int = 3 - Global GameState:Int = STATE_TITLE - - Field player:Player - Field score:Int - Field level:Int - Field bestScore:Int - Field asteroidsNum:Int - Field asteroidsSize:Int - - Method New(title:String, width:Int, height:Int) - Super.New(title, width, height) - ClearColor = Color.Black - SwapInterval = 1 - SeedRnd(Millisecs()) - Reset() - 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 OnRender(canvas:Canvas) Override - App.RequestRender() - - Select GameState - Case STATE_TITLE - Asteroid.UpdateAll() - If Keyboard.KeyHit(Key.Space) - SetState(STATE_GAME) - End - Case STATE_GAME - player.Update() - Bullet.UpdateAll() - Asteroid.UpdateAll() - CheckCollisions() - Case STATE_GAME_OVER - Asteroid.UpdateAll() - If Keyboard.KeyHit(Key.Space) - SetState(STATE_TITLE) - Reset() - End - End - - Select GameState - Case STATE_TITLE - DrawTitleScreen(canvas) - Case STATE_GAME - DrawGame(canvas) - Case STATE_GAME_OVER - DrawGameOver(canvas) - End - End - - Method SetState(state:Int) - GameState = state - End - - Method DrawTitleScreen(canvas:Canvas) - Asteroid.RenderAll(canvas) - canvas.DrawText("MONKEYROIDS: RETURN OF THE CHIMP!", SCREEN_WIDTH / 2, (SCREEN_HEIGHT / 2) - 20, 0.5, 0.5) - canvas.DrawText("BEST SCORE: " + bestScore, (SCREEN_WIDTH / 2), (SCREEN_HEIGHT / 2), 0.5, 0.5) - canvas.DrawText("PRESS TO PLAY", SCREEN_WIDTH / 2, (SCREEN_HEIGHT / 2) + 20, 0.5, 0.5) - End - - Method DrawHUD:Void(canvas:Canvas) - canvas.DrawText("LEVEL: " + level, 0, 0) - canvas.DrawText("SCORE: " + score, SCREEN_WIDTH, 0, 1, 0) - canvas.DrawText("BULLETS#: " + Bullet.list.Count(), SCREEN_WIDTH/2, 0, 0.5, 0) - canvas.DrawText("ASTEROIDS#: " + Asteroid.list.Count(), SCREEN_WIDTH/2, 20, 0.5, 0) - End - - Method DrawGame(canvas:Canvas) - player.Render(canvas) - Bullet.RenderAll(canvas) - Asteroid.RenderAll(canvas) - DrawHUD(canvas) - End - - Method DrawGameOver(canvas:Canvas) - Asteroid.RenderAll(canvas) - canvas.DrawText("GAME OVER!", SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 - 20, 0.5, 0.5) - canvas.DrawText("SCORE: " + score, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, 0.5, 0.5) - canvas.DrawText("BEST SCORE: " + Self.bestScore, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 + 20, 0.5, 0.5) - canvas.DrawText("PRESS TO RETURN TO THE TITLE SCREEN", SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 + 40, 0.5, 0.5) - End - - Method CheckCollisions() - Local asteroidToRemove:Asteroid - - Local ait := Asteroid.list.All() - While Not ait.AtEnd - Local a:Asteroid = ait.Current - If Not a.dead And Dist(player.x, player.y, a.x, a.y) <= a.avgrad - player.shield -= 10 - a.dead = True - End - For Local b:Bullet = Eachin Bullet.list - If a <> Null And Not a.dead - If Dist(b.x, b.y, a.x, a.y) <= a.avgrad - a.life -= 1 - b.life = 0 - End - If a.life <= 0 - a.dead = True - End - End - Next - If a.dead - ait.Erase() - asteroidToRemove = a - Else - ait.Bump() - End - - End - - If asteroidToRemove <> Null - If asteroidToRemove.size > 1 - score += 5 - For Local t:Int = 1 To 2 - New Asteroid(asteroidToRemove.x, asteroidToRemove.y, Rnd(-5, 5), Rnd(-5, 5), asteroidToRemove.size - 1) - Next - End - End - - If Asteroid.list.Count() = 0 - level += 1 - asteroidsNum += 1 - asteroidsSize += 1 - CreateAsteroids(asteroidsNum, asteroidsSize) - End - End - - Method Reset() - Bullet.list.Clear() - Asteroid.list.Clear() - level = 1 - asteroidsNum = 2 - asteroidsSize = 3 - score = 0 - player = New Player(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2) - CreateAsteroids(asteroidsNum, asteroidsSize) - End - - Method CreateAsteroids:Void(num:Int, size:Int) - Asteroid.list.Clear() - Bullet.list.Clear() - Local tx:Float - Local ty:Float - For Local t:Int = 1 To num - Repeat - tx = Rnd(640) - ty = Rnd(480) - Until (tx < 280 Or tx > 360) And (ty < 200 Or ty > 280) - New Asteroid(tx, ty, Rnd(-2, 2), Rnd(-2, 2), size + Rnd(1)) - Next - End -End - -Class Sprite - Field dead:Bool - Field xv:Float, yv:Float - Field x:Float, y:Float - Field rotation:Float - Field canvas:Canvas -End - -Class Asteroid Extends Sprite - Global list:List = New List - Field ang:Float, angvel:Float - Field rad:Float[] = New Float[9] - Field avgrad:Float - Field size:Int - Field life:Int - Field cr:Float, cg:Float, cb:Float - - Method New(x:Float, y:Float, xv:Float, yv:Float ,size:Int) - Self.x = x - Self.y = y - Self.xv = xv - Self.yv = yv - Self.ang = Rnd(360) - Self.angvel = Rnd(-6, 6) - Self.size = size - Self.life = size - Self.cr = 1 - Self.cg = 1 - Self.cb = 1 - ' Create "Rockiness" - Self.avgrad = 0 - For Local t:Int = 0 To 7 - Self.rad[t] = size * 8.0 + Rnd(-size * 4.0, size * 4.0) - Self.avgrad = Self.avgrad + Self.rad[t] - Next - Self.avgrad = Self.avgrad /6.0 - Self.rad[8] = Self.rad[0] - Self.dead = False - - list.AddLast(self) - End - - Function RenderAll:Void(canvas:Canvas) - If Not list Return - For Local a:Asteroid = Eachin list - a.Render(canvas) - Next - End - - Function UpdateAll:Void() - If Not list Return - For Local a:Asteroid = Eachin list - a.Update() - Next - End - - Method Update:Void() - 'If dead Return - Self.x += Self.xv * Delta.delta - Self.y += Self.yv * Delta.delta - Self.rotation += Self.angvel * Delta.delta - - If Self.x < -Self.avgrad Then Self.x = Self.x + SCREEN_WIDTH + Self.avgrad *2 - If Self.x > SCREEN_WIDTH + Self.avgrad Then Self.x = Self.x - SCREEN_WIDTH - Self.avgrad *2 - If Self.y < -Self.avgrad Then Self.y = Self.y + SCREEN_HEIGHT + Self.avgrad *2 - If Self.y > SCREEN_HEIGHT + Self.avgrad Then Self.y = Self.y - SCREEN_HEIGHT - Self.avgrad *2 - End - - Method Render:Void(canvas:Canvas) - 'If dead Return - Local tmul:Float = 360.0 / 8.0 - canvas.Color = New Color( cr, cg, cb) - For Local t:Int = 0 To 7 - local x1:Float = x - (Sin(ToRadians(rotation + (t) * tmul)) * rad[t]) - Local y1:Float = y - (Cos(ToRadians(rotation + (t) * tmul)) * rad[t]) - Local x2:Float = x - (Sin(ToRadians(rotation + (t + 1) * tmul))* rad[t + 1]) - Local y2:Float = y - (Cos(ToRadians(rotation + (t + 1) * tmul)) * rad[t + 1]) - canvas.DrawLine(x1, y1, x2, y2) - Next - End -End - -Class Bullet Extends Sprite - Global list:List = New List - Field life:Float - Field cr:Float, cg:Float, cb:Float - - Method New(x:Float, y:Float, xv:Float, yv:Float, life:Float, cr:Float, cg:Float, cb:Float) - Self.x = x - Self.y = y - Self.xv = xv - Self.yv = yv - Self.life = life - Self.cr = cr - Self.cg = cg - Self.cb = cb - - list.AddLast(Self) - End - - Function UpdateAll:Void() - If Not list Return - - Local it := list.All() - While Not it.AtEnd - Local b:Bullet = it.Current - b.Update() - If b.life <= 0 - it.Erase() - Else - it.Bump() - End - End - End - - Method Update:Void() - If dead Return - x += xv * Delta.delta - y += yv * Delta.delta - - life -= Delta.delta - If x < 0 x = SCREEN_WIDTH - If x > SCREEN_WIDTH x = 0 - If y < 0 y = SCREEN_HEIGHT - If y > SCREEN_HEIGHT y = 0 - End - - Function RenderAll:Void(canvas:Canvas) - If Not list Return - For Local b:Bullet = Eachin list - b.Render(canvas) - Next - End - - Method Render:Void(canvas:Canvas) - If dead Return - Local tmul:Float - If life <= 25.0 - tmul = life / 25.0 - Else - tmul = 1.0 - End - canvas.Color = New Color( cr * tmul, cg * tmul, cb * tmul ) - canvas.DrawLine(x, y, x + xv, y + yv) - End -End - - -Class Player Extends Sprite - Field angVel:Float - Field velmul:Float - Field vel:Float - Field acc:Float - Field drag:Float - Field xv:Float, yv:Float - Field xa:Float, ya:Float - Field firedel:Float - - Field shipAngvel:Float - Field shipAcc:Float - Field shipVelmul:Float - Field shipFiredel:Float - - Field shield:Float - - Method New(x:Float, y:Float) - Self.x = x - Self.y = y - Self.shipAngvel = 6 - Self.shipAcc = 0.16 - Self.shipVelmul = -0.0005 - Self.shipFiredel = 5 - Self.shield = 100 - End - - Method Controls() - If Keyboard.KeyDown(Key.Up) Or Keyboard.KeyDown(Key.W) - acc = shipAcc - drag = vel * shipVelmul - Elseif Keyboard.KeyDown(Key.Down) Or Keyboard.KeyDown(Key.S) - drag = vel * shipVelmul * 50 - Else - acc = 0 - drag = 0 - End - - If Keyboard.KeyDown(Key.Left) Or Keyboard.KeyDown(Key.A) - rotation += shipAngvel * Delta.delta - Elseif Keyboard.KeyDown(Key.Right) Or Keyboard.KeyDown(Key.D) - rotation -= shipAngvel * Delta.delta - End - - If Keyboard.KeyDown(Key.Space) And Self.firedel <= 0 - Local tang:Float = Rnd(-.01, .01) - Local x1:Float = x - (Sin(ToRadians(rotation)) * 8) - Local y1:Float = y - (Cos(ToRadians(rotation)) * 8) - Local xv1:Float = xv - (Sin(ToRadians(rotation) + tang ) * 12) - Local yv1:Float = yv - (Cos(ToRadians(rotation) + tang ) * 12) - Local life:Int = 45 - New Bullet(x1, y1, xv1, yv1, life, 1, 1, 0) - firedel = shipFiredel - End - firedel -= Delta.delta - - End - - Method Update() - Controls() - xa = (drag * xv) - (Sin(ToRadians(rotation)) * acc) - ya = (drag * yv) - (Cos(ToRadians(rotation)) * acc) - xv += xa * Delta.delta - yv += ya * Delta.delta - x += xv * Delta.delta - y += yv * Delta.delta - vel = Dist(0, 0, xv, yv) - - If x < 0 x = SCREEN_WIDTH - If x > SCREEN_WIDTH x = 0 - If y < 0 y = SCREEN_HEIGHT - If y > SCREEN_HEIGHT y = 0 - - If shield <= 0 - If Game.score > Game.bestScore - Game.bestScore = Game.score - End - Game.SetState(Game.STATE_GAME_OVER) - End - End - - Method Render(canvas:Canvas) - - Local x1:Float = x - (Sin(ToRadians(rotation)) * 10) - Local y1:Float = y - (Cos(ToRadians(rotation)) * 10) - - Local x2:Float = x - (Sin(ToRadians(rotation + 140)) * 8) - Local y2:Float = y - (Cos(ToRadians(rotation + 140)) * 8) - - Local x3:Float = x - (Sin(ToRadians(rotation - 140)) * 8) - Local y3:Float = y - (Cos(ToRadians(rotation - 140)) * 8) - - canvas.Color = Color.White - canvas.DrawLine(x1, y1, x2, y2) - canvas.DrawLine(x2, y2, x3, y3) - canvas.DrawLine(x3, y3, x1, y1) - - canvas.Alpha = .5 - If shield < 50 Then canvas.Color = New Color(1, 0, 0) - canvas.DrawRect(10, SCREEN_HEIGHT - 15, Self.shield, 10) - canvas.Alpha = 1 - - End -End - -'TODO: Delta timing class -Class Delta - Global delta:Float = 0.5 -End - -Global Game:MyWindow - -Function Main() - New AppInstance - Game = New MyWindow("Monkeyroids: Return of the Chimp!", SCREEN_WIDTH, SCREEN_HEIGHT) - App.Run() -End - -Function Dist:Float(x1:Float, y1:Float, x2:Float, y2:Float) - Return Sqrt(Pow((x1 - x2), 2) + Pow((y1 - y2), 2)) -End - -Function ToDegrees:Float(rad:Float) - Return rad * 180.0 / PI -End - -Function ToRadians:Float(degree:Float) - Return degree * PI / 180.0 -End