Forum Replies Created
-
AuthorPosts
-
I’ve only used the form defining opposite corners of a cube/box:
Monkey1New Boxf (x0, y0, z0, x1, y1, z1)In real-world use, this might look like:
Monkey12Local cube:Model = Model.CreateBox (New Boxf (-0.5, -0.5, -0.5, 0.5, 0.5, 0.5), 1, 1, 1, New PbrMaterial (Color.White))… where x0, y0, z0 define one extreme corner — in this case being left 0.5, down 0.5, towards camera 0.5 — and x1, y1, z1 define the opposite corner; in this case right 0.5 (forming total width of 1.0), up 0.5 and forward 0.5.
For further clarity, you might store the box as a Boxf and pass it to CreateBox:
Monkey123Local cube_box:Boxf = New Boxf (-0.5, -0.5, -0.5, 0.5, 0.5, 0.5)Local cube:Model = Model.CreateBox (cube_box, 1, 1, 1, New PbrMaterial (Color.White))As far as I can tell, you only really need 1, 1, 1 for the x, y, z segments — you might pass in more if you want to manipulate the cube’s vertices into another shape.
So the box is:
- -0.5 to 0.5 horizontally – New Boxf (x0, -0.5, -0.5, x1, 0.5, 0.5);
- -0.5 to 0.5 vertically – New Boxf (-0.5, y0, -0.5, 0.5, y1, 0.5);
- -0.5 to 0.5 depth-wise – New Boxf (-0.5, -0.5, z0, 0.5, 0.5, z1).
… meaning it measures 1.0 in all directions.
Another way to define it, if you want to specify a particular size:
Monkey12Local size:Float = 10.0Local box:Boxf = New Boxf (-size * 0.5, -size * 0.5, -size * 0.5, size * 0.5, size * 0.5, size * 0.5)Or…
Monkey12Local box:Boxf = New Boxf (-width * 0.5, -height * 0.5, -depth * 0.5, width * 0.5, height * 0.5, depth * 0.5)The parameters define opposite corners of the cube:
Monkey1New Boxf (-, -, -, +, +, +)… and if you find you still struggle, just wrap Model.CreateBox into a CreateCube function (like Blitz3D!), passing in the width, height, depth and a PbrMaterial (plus potentially the optional parent entity), and returning the Model.
Just updated this, along with a binary release for Windows 64-bit.
Done quite a lot since last post, chunky explosions with rocket parts being possibly the coolest. Some basic pixel shaders, too.
The release doesn’t really mean anything in particular, still tons to be done/tweaked, just testing out GitHub’s release option.
Try the shaders! (Contrary to notes below, use F-keys per the HUD.)
NB. Undocumented Pause feature (key P) currently broken due to recent addition of delta-timing for non-physics stuff. Use R to reset!
Recent-ish updates:
Monkey1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950Date: Sun Oct 21 21:32:13 2018 +0100Misc fixes, HUD and RocketParticle changes.Fixes public Behaviour stuff that should have been private.Orb is easier to collect now that IT HAS A NON-ZERO COLLISION RADIUS!HUD is now a proper object with methods, rather than a collection of public functions.HUD death-skull is finally a sprite! Should (SHOULD) now appear in VR, yet to test...Smoke is now more dynamic; clears up quicker and rises. May need to be changed to an option for performance, dunno yet.Date: Sat Oct 20 20:36:22 2018 +0100Adds monochrome (B&W stippled) shaderReverts to sprites for rocket particles -- thanks to Mark for fix!Date: Fri Oct 19 16:25:22 2018 +0100Many changes, slightly hesitant commit!WIP rocket particles (sprite and quad) changed back to cubes temporarily, due to problems with sprites and quads, as noted here:https://github.com/blitz-research/monkey2/issues/434https://github.com/blitz-research/monkey2/issues/436Removes redundant properties from Level.Attempts to make lots of non-physics stuff framerate-independent via delta timing... possibly. (Not overly sure what I'm doing here.)Disables Xbox pad if keyboard used. (Per-frame.)Adds explosion particles.Date: Wed Oct 10 03:46:14 2018 +0100Chunkier crashes! Definite WIP, may crash (seems OK so far but only tested on supplied rocket and in-game orb). TODO: Explosions...Date: Sat Oct 6 23:33:20 2018 +0100Adds pixel shaders -- greyscale and ZX Spectrum palette (TODO: attribute clash)Adds gem map (TODO: add orb and portal)SmokeParticles are now spritesDate: Sun Sep 30 14:57:35 2018 +0100Starts conversion of SmokeParticle to sprites, but [mojo3d sprite alpha appears to be broken at present] (https://github.com/blitz-research/monkey2/issues/410#issuecomment-425720114)Adds simple greyscale shader (press G to cycle through modes), just to provide a base for experimentation.Darkened sky to allow for better greyscale contrast.Godot 3 is actually pretty nice (I recommend this tutorial), but I found that when I wanted to build physics stuff via code — walls to knock down and the like — the whole point-and-click thing fell apart, as you have to implement it all in code anyway, so you have no 3D placeholder to help visualise objects’ positions.
I’m sure you could work around it, but I lost interest (some of the 3D coding was impractical or difficult to figure out) and have been doing mojo3d ever since.
That said, we know you’re not interested in monkey2 anyway.
Godot was definitely fun to play with, so go for it.
Please post your progress.
Huh? Mark said only two days ago that he’s looking into this.
Thanks for having a look… the camera definitely struggles in close-up, but it’s surprisingly tricky to resolve.
Yeah, I’ll be adding a gem map at some point, should be really easy.
I’m only using the default timing setup, so the truth is… I don’t really know! As far as I’m aware, mojo would default to running the display at the monitor’s refresh rate while running physics at the default Bullet rate of 60 fps, but I could well be wrong about that. (Maybe mojo/mojo3d sets physics to also match the monitor rate?) Don’t know why it would be running at exactly half the monitor’s rate either… :/
The halve-fuel thing was for testing of the low-fuel alarm, just forgot it’s still there. (Even when I could have made use of it earlier today, gah!)
I’ve been adding a simple sound channel mixing system today but got myself all tangled up with some subtle errors and need to start again, so haven’t committed it…
Hard-going for me, but this is probably the longest I’ve stuck at a single project! It’ll never be a great game, but I’m learning a lot and once it’s at least working fully I intend to document it to explain its workings, how it uses the language/engine features, etc.
Thanks again.
For what it’s worth, lots of updates!
Monkey1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374Date: Wed Sep 19 02:58:17 2018 +0100Preloads all audioDate: Wed Sep 19 01:14:40 2018 +0100Preloads sounds (few more to-do)Cleans up SpaceGem spawning, which was stupidTurns remaining physics objects to full Behaviours (todo: Rocket)Removes redundant refs to Model/RigidBody in Behaviours (may be some remaining!), can just return Entity/GetComponent <RigidBody> insteadRemoves misc redundant fields, properties, etc and makes more stuff PrivateFixes level naming for randomly-generated levelsRearranges some level init stuff and fixes removal of gems/pads post-conversion to BehavioursDate: Sat Sep 15 02:38:12 2018 +0100Converted PhysicsTri to Behaviour; auto-fades/removes each triangle nowDate: Sat Sep 15 00:34:44 2018 +0100Converts Portal to Behaviour-based objectDate: Thu Sep 13 04:43:53 2018 +0100Converts Orb, SpaceGem and SmokeParticle to pure BehavioursFixes to DummyOrbDate: Wed Sep 12 02:36:04 2018 +0100Adds dummy orb light (late TODO: Add portal ground light?)Date: Wed Sep 12 01:23:13 2018 +0100Updates to readme againDate: Wed Sep 12 01:21:21 2018 +0100Updates readme.Date: Wed Sep 12 01:15:24 2018 +0100Added screenshotsDate: Wed Sep 12 00:53:36 2018 +0100Fixed remaining orb channel error (played boom on level exit)Date: Wed Sep 12 00:45:49 2018 +0100FFS! Disabled temp portal collision visibilityDate: Wed Sep 12 00:44:56 2018 +0100Forgot to reset temp orb spawningDate: Wed Sep 12 00:42:33 2018 +0100Fixes orb and portal respawningFixes orb audio silence after first explosionDate: Tue Sep 11 02:24:39 2018 +0100Portal fixes WIP -- currently semi-broken!Date: Fri Sep 7 01:08:17 2018 +0100Dummy orb now basically spawns above player start point. WIP.Date: Thu Sep 6 05:07:16 2018 +0100Adds terrain smoothing via Gaussian blur.WIP DummyOrb for spawning physics Orb.A lot less ashamed of the code right now, at least… for the most part…
Main plan is to a) implement PAUSE (scared of this because I’m not sure how the physics engine will handle it!), and b) allow clicking of in-game objects to spawn text about where they’re implemented and how.
Current Windows 64-bit build here…
I actually like and use ‘ to comment blocks of code, it’s great!
There’s BlitzMax code here, ported from Monkey (1)…
Should be very easy to translate to MX2.
Looks like it originally came from here, but the stripped-down all-in-one BlitzMax code is ironically probably easier to work with.
Updated to fix jagged edges — threaded demo source and binary updated too. (Non-threaded ‘should’ just run from Ted2Go in recent releases, without needing GitHub develop branch.)
Experimental
Multi-threaded the terrain generation (for 3D demo)!
Model.CreateTerrain is the slowest part in generating the terrain, so this does the heightmap generation/mesh creation in a background thread, meaning there’s only a small jerk while the new terrain swaps in. Not sure what causes the jerk — uploading to graphics card, maybe? Still much nicer than the previous demo.
Hit G to generate new terrain while running.
Threading is probably only in the GitHub develop branch, and is experimental. Anyway, just quickly hacked it in out of curiosity!
Note the ground? checks for ease of use here, avoiding complex flags while the thread does its thing. I can simply turn the ground using ground?.Rotate (0.0, 0.125, 0.0) and if ground:Model is still loading/Null then it has no effect. Mark recommends against over-use of ? checks!
(I realised GenerateTerrain also hard-codes the height for now (256), easy enough to modify, of course.)
Monkey123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419#Import "<std>"#Import "<mojo>"#Import "<mojo3d>"#Import "<thread>"Using std..Using mojo..Using mojo3d..#RemBasic usage to generate 2D PNG heightmap (size must be power of 2):Local terrain:PlayfulJSTerrain = New PlayfulJSTerrain (seed, pixmap_size, roughness) ' eg. 1, 1024, 0.5Local heightmap:Pixmap = terrain.RenderPixmap ()heightmap.Save (DesktopDir () + "\mx2__rendered__heightmap.png")#End' -----------------------------------------------------------------------------' Start of PlayfulJSTerrain' -----------------------------------------------------------------------------Class PlayfulJSTerrain' Hunter Loftis' http://www.playfuljs.com/realistic-terrain-in-130-lines/' https://github.com/hunterloftis/playfuljs-demos/blob/gh-pages/terrain/index.htmlField size:IntField max:IntField map:Float[]Field roughness:FloatField upper:FloatField lower:FloatMethod New (seed:ULong, pixmap_size:Int = 1024, in_roughness:Float = 0.5)Assert (IsPow2 (pixmap_size), "PlayfulJSTerrain.New (pixmap_size) must be power of 2!")SeedRnd (seed)roughness = in_roughnesssize = pixmap_size + 1max = size - 1map = New Float[size * size]Generate ()EndMethod GetHeight:Float (x:Int, y:Int)If (x < 0 Or x > max Or y < 0 Or y > max) Then Return -1Return map[x + size * y]EndMethod SetHeight (x:Int, y:Int, val:Float)map[x + size * y] = valIf val < lower Then lower = valIf val > upper Then upper = valEndMethod Generate ()lower = 0upper = 0SetHeight (0, 0, max)SetHeight (max, 0, max * 0.5)SetHeight (max, max, 0)SetHeight (0, max, max * 0.5)Divide (max)EndMethod Divide (size:Int)Local half:Int = size / 2 ' Weird failed optimisation: "If size < 2 Then Return" at start is slower than this with half < 1 check!If half < 1 Then ReturnLocal scale:Float = roughness * sizeLocal scale2:Float = scale * 2 ' Quick pre-calc for the two loops below...Local x:IntLocal y:IntFor y = half To max Step sizeFor x = half To max Step sizeSquare (x, y, half, Rnd () * scale2 - scale)NextNextFor y = 0 To max Step halfFor x = (y + half) Mod size To max Step sizeDiamond (x, y, half, Rnd () * scale2 - scale)NextNext' Recursive call until too small (see "If half < 1")...Divide (size / 2)EndMethod Square (x:Int, y:Int, in_size:Int, offset:Float)Local total:FloatLocal count:IntLocal xms:Int = x - in_sizeLocal yms:Int = y - in_sizeLocal xps:Int = x + in_sizeLocal yps:Int = y + in_sizeLocal h0:Float = GetHeight (xms, yms)Local h1:Float = GetHeight (xps, yms)Local h2:Float = GetHeight (xps, yps)Local h3:Float = GetHeight (xms, yps)If h0 <> -1 Then total = total + h0; count = count + 1If h1 <> -1 Then total = total + h1; count = count + 1If h2 <> -1 Then total = total + h2; count = count + 1If h3 <> -1 Then total = total + h3; count = count + 1If Not count Then Return ' Don't divide by zero!SetHeight (x, y, total / count + offset)EndMethod Diamond (x:Int, y:Int, in_size:Int, offset:Float)Local total:FloatLocal count:IntLocal h0:Float = GetHeight (x, y - in_size)Local h1:Float = GetHeight (x + in_size, y)Local h2:Float = GetHeight (x, y + in_size)Local h3:Float = GetHeight (x - in_size, y)If h0 <> -1 Then total = total + h0; count = count + 1If h1 <> -1 Then total = total + h1; count = count + 1If h2 <> -1 Then total = total + h2; count = count + 1If h3 <> -1 Then total = total + h3; count = count + 1If Not count Then Return ' Don't divide by zero!SetHeight (x, y, total / count + offset)EndMethod RenderPixmap:Pixmap ()Local pix:Pixmap = New Pixmap (max, max, PixelFormat.I8)Local rgb:FloatLocal color:Color = New Color (0.0, 0.0, 0.0)For Local y:Int = 0 Until maxFor Local x:Int = 0 Until maxIf (upper - lower) = 0 ' Make sure range is valid for TransformRange!rgb = 0.0Elsergb = TransformRange (GetHeight (x, y), lower, upper, 0.0, 1.0)Endifcolor.R = rgbcolor.G = rgbcolor.B = rgbpix.SetPixel (x, y, color)NextNextReturn pixEndMethod TransformRange:Float (input_value:Float, from_min:Float, from_max:Float, to_min:Float, to_max:Float)' Algorithm via jerryjvl at https://stackoverflow.com/questions/929103/convert-a-number-range-to-another-range-maintaining-ratioLocal from_delta:Float = from_max - from_min ' Input range, eg. 0.0 - 1.0Local to_delta:Float = to_max - to_min ' Output range, eg. 5.0 - 10.0Assert (from_delta <> 0.0, "TransformRange: Invalid input range!")Return (((input_value - from_min) * to_delta) / from_delta) + to_minEndMethod IsPow2:Long (value:Long)Return Not (value & (value - 1))EndEnd' -----------------------------------------------------------------------------' End of PlayfulJSTerrain' -----------------------------------------------------------------------------' Helper function to generate checkerboard Pixmap...Function CheckerPixmap:Pixmap (color0:Color, color1:Color)Local pixels:Pixmap = New Pixmap (256, 256, PixelFormat.RGBA8)pixels.Clear (color0)Local pixel_toggle:Bool = FalseFor Local gp_y:Int = 0 Until pixels.HeightFor Local gp_x:Int = 0 Until pixels.WidthIf pixel_toggle Then pixels.SetPixel (gp_x, gp_y, color1)pixel_toggle = Not pixel_toggleNextpixel_toggle = Not pixel_toggleNextReturn pixelsEnd' Demo...Class MyWindow Extends WindowField scene:SceneField camera:CameraField light:LightField seed:Int = 0Field turn:Bool = TrueField ground:ModelField ground_thread:ThreadField render_timer:IntMethod New( title:String="PlayfulJSTerrain to Monkey2!",width:Int=1024,height:Int=768,flags:WindowFlags=WindowFlags.Center )' Method New( title:String="PlayfulJSTerrain to Monkey2!",width:Int=App.DesktopSize.X,height:Int=App.DesktopSize.Y,flags:WindowFlags=WindowFlags.Fullscreen )Super.New( title,width,height,flags )EndMethod GenerateTerrain_Threaded ()' Local ticks:Int = Millisecs ()Local tg:Model = GenerateTerrain (seed, 1024)ground?.Destroy ()ground = tg' Print "Terrain rendering thread took " + (Millisecs () - ticks) + " ms"' About a second...EndMethod OnCreateWindow() Overridescene=New Scenescene.ClearColor = Color.Skyscene.FogColor = Color.Skyscene.FogNear = 256scene.FogFar = 1024camera=New Camera( Self )camera.Move( 0,300,0 )camera.Far = 1024.0camera.Rotate (45, 0, 0)light=New Lightlight.CastsShadow=Truelight.Move (-512, 256, 0)' GenerateTerrain returns a mojo3d Model...'ground = GenerateTerrain (seed, 1024)ground_thread = New Thread (GenerateTerrain_Threaded)Mouse.PointerVisible = False' render_timer = Millisecs ()EndMethod OnRender( canvas:Canvas ) Override' Local render_time:Int = Millisecs () - render_timer' render_timer = Millisecs ()' If render_time > 17' Print "Rendering exceeded 17 ms, taking " + render_time + " ms"' EndifIf turn Then ground?.Rotate (0.0, 0.125, 0.0)If Keyboard.KeyHit (Key.Escape) Then App.Terminate ()If Keyboard.KeyHit (Key.T) Then turn = Not turn ' Toggle turn variable on/off...If Keyboard.KeyHit (Key.G)' One at a time, please...If Not ground_thread.Runningseed = seed + 1ground_thread = New Thread (GenerateTerrain_Threaded)EndifEndif' Hitting S demonstrates simple non-3D usage to generate a heightmap...If Keyboard.KeyHit (Key.S)' Create a terrain with same details as 3D one...Local terrain:PlayfulJSTerrain = New PlayfulJSTerrain (seed) ' Defaults to size = 1024 x 1024, roughness = 0.5' Render to Pixmap and save to desktop...Local heightmap:Pixmap = terrain.RenderPixmap ()heightmap.Save (DesktopDir () + "\mx2__rendered__heightmap.png")EndifIf Keyboard.KeyDown (Key.A)camera.Move (0.0, 0.0, 1.0)ElseIf Keyboard.KeyDown (Key.Z)camera.Move (0.0, 0.0, -1.0)EndifEndifIf Keyboard.KeyDown (Key.Left)camera.Rotate (0.0, 1.0, 0.0)ElseIf Keyboard.KeyDown (Key.Right)camera.Rotate (0.0, -1.0, 0.0)EndifEndifIf Keyboard.KeyDown (Key.Up)camera.Rotate (1.0, 0.0, 0.0, True)ElseIf Keyboard.KeyDown (Key.Down)camera.Rotate (-1.0, 0.0, 0.0, True)EndifEndifRequestRender()scene.Update()camera.Render( canvas )canvas.DrawText( "Seed=" + seed + ", FPS="+App.FPS,20,20 )canvas.DrawText( "G to generate new terrain",20,40 )canvas.DrawText( "S to save heightmap to desktop",20,60 )canvas.DrawText( "T to toggle rotation",20,80 )canvas.DrawText( "Cursors + A/Z to move (slowly!)",20,100 )canvas.DrawText( "Esc to exit",20,140 )If ground_thread.Runningcanvas.DrawText( "Generating new terrain...",20,180 )EndifEndEnd' For demo only...Function GenerateTerrain:Model (seed:ULong, size:Int = 1024, roughness:Float = 0.5, color0:Color = New Color (0.8, 0.5, 0.1), color1:Color = New Color (0.75, 0.35, 0.05))Local terrain:PlayfulJSTerrain = New PlayfulJSTerrain (seed, size, roughness)Local heightmap:Pixmap = terrain.RenderPixmap ()If Not heightmap Then RuntimeError ("Failed to generate heightmap!")heightmap.FlipY () ' 2D Y (increases downwards) translates to 3D Z (increases upwards)Local terrain_material:PbrMaterial = New PbrMaterial ()terrain_material.ColorTexture = New Texture (CheckerPixmap (color0, color1), TextureFlags.None)Local terrain_height:Float = 256.0 ' TODO!Local height_box:Boxf = New Boxf (-heightmap.Width * 0.5, 0.0, -heightmap.Height * 0.5, heightmap.Width * 0.5, terrain_height, heightmap.Height * 0.5)Return Model.CreateTerrain (heightmap, height_box, New PbrMaterial (terrain_material))EndFunction Main()New AppInstanceNew MyWindowApp.Run()EndI somehow suspect Discord is irrelevant to Monsieur B’s intentions anyway…
I can’t help but imagine that 3 rather uninterested replies over a period of more than 24 hours was somewhat disappointing to him too.
Cool, thanks, was trying to do this the other day and gave up!
In a hurry, but I recommend using a free program like Agent Ransack (just search for it), where you can search the module or main mx2 directory, input *.monkey2 as file name and whatever you’re looking for (eg. OnRender) under “Containing text”. That’s how I get around!
Yay!
Have you checked if fs = Null?
Doubting “asset:: slash data/etc” is valid, I would normally expect “asset::data/etc”. (Could be wrong though… )
-
AuthorPosts