Forum Replies Created
-
AuthorPosts
-
October 21, 2017 at 1:09 am in reply to: Is Mark pulling the plug on Monkey2? Worrying comments on Twitter #11242
And don’t block your followers on twitter – because it’s not a good marketing strategy
Sorry, but I can’t live my life based on a ‘good marketing strategy’. I will tone down the swearing (I’m not normally a swearer, well, I try not to be), but I should have blocked that guy on twitter from the get go as it would’ve saved me from telling him to f#^*k off. And twitter is very much part of my life, it’s actually probably the last bit of the internet I actually enjoy these days!
I am a bit sorry for what I said on twitter, but only a bit, as he made my life really unpleasant over the last 6 months of monkey-x. It’s no doubt partially my fault – I should have said something to him privately (he may not even know he was doing it) but instead I just avoided him altogether, to the point where I wouldn’t even read threads if I saw his name because, you know, you can’t offend the customer, and it just became easier to ignore him. Any other other ‘reluctant community managers’ out there? Any advice?
So for people who wonder why I have ‘pulled away’ from the community over the years, I suspect this desire to ‘not offend’ anyone is part of the reason. As I have discovered over the years, the easiest way to ‘please everyone’ is to just shut the hell up as much as possible and to offer as few opinions as possible. But I still seem to end up blowing-up now and then anyway, so it doesn’t really work! Also, it sucks having to remain so ‘reserved’ at all times when your job and you life intersect as much as mine do.
In terms of twitter, what I probably need to do is resurrect the @blitzresearch account, but I’ll save that for my fantasy marketing guy (must be a monkey lover). My priority right now is to get my real world s#*t together, ie: get a consistently paying job so I don’t have to worry about that side of things.
And wot secondgear said…
October 20, 2017 at 10:00 pm in reply to: Is Mark pulling the plug on Monkey2? Worrying comments on Twitter #11236Ok, will behave again!
Monkey, Monkey X, Monkey 2, Cerberus X…
Cerebus X is a 3rd party ‘fork’ of Monkey X (which was originally called Monkey). It is AFAIK completely compatible with Monkey X.
Monkey2 is the ‘sequel’ to Monkey X. It should be fairly familiar and easy to pick up for users of Monkey X but it is not compatible.
The only android project I know of that has been written in Monkey2 so far is revengestar: https://play.google.com/store/apps/details?id=com.playniax.revengestar
The point of fibers is really that they allow you to perform blocking operations, without causing the entire program to halt.
So yes, if a fiber executes ‘Accept’ and there’s nothing trying to connect, it will block. And blocking will allow other fibers to run etc.
In general, there’s no need to synchronize access to global lists etc with fibers, because fibers only ‘switch’ at known times, eg: blocking for an Accept etc, blocking for a Read, blocking while waiting for a Process to finish etc.
You do have to be a tiny bit careful here, as its possible to indirectly call code that may cause a fiber switch without your knowledge. But even then, the switch will never occur in the middle of adding a stack element or whatever so it’s perfectly safe to use lists, stacks etc, even global ones, from any fiber. Ted2 makes extensive use of fibers and I never once had to really think about synchronizatoion issues when using fibers. Which is what largely makes them so cool.
Never really used annotations, are they a bit like compiler warnings in c/c++? I have never been a huge fan of warnings in c/c++.
I have seen @override used in java I think. Why is it optional? Because it would break too much existing code? What does it actually do then?
And why not add @nulable as a language keyword?
As you may have guessed, I’m not really into just throwing every possible construct at the language (simple as possible, no simpler etc) ala c#, and it’d be nice to have some ‘examples’ of why this is useful too?
Ok, after a lot of positive feedback, I have decided to definitely keep working on monkey and to leave the patreon open.
My main concern was that people had tried it, decided they didn’t likely to had stopped using it – it just went really quiet for a while there. All I really care about is that people find it useful and are actually doing things with it!
I will not be changing the website right now. I know it sucks, but its honestly the best I can do without splashing out on something professsional, or rewriting another site from scratch which I will NOT be doing. I would definitely like a nicer site, but realistically it will cost money that I just don’t have.
I think skn3 has the right idea. I should team up with someone who actually gives a shit about all this marketing BS. I have actually had an offer to help with the website etc recently which I may eventually take up. But in the meantime, it will be business as usual as my priority right now is finding gainful employment in the real world.
And I will NOT be changing the name. If you don’t like the name, please kindly shut the f#*k up about it or f#*k off! Sorry, but I really can’t put it any nicer than that. If I WERE to change the name, it certainly wouldn’t be because a bunch of random users nagged me to death over it.
Locking this now, I think everyone’s said their bit.
First google result for ‘opengl FBO tutorial’ looks useful:
http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-14-render-to-texture/
I’d also recommend looking at mojo/graphics/rendertarget.monkey2.
…here’s a nice piece on component systems, mostly as it appies to ‘game logic’:
http://gameprogrammingpatterns.com/component.html
In fact, that whole ‘book’ is really nice:
http://gameprogrammingpatterns.com/
Can somebody dumb-down “components” for me?
Component systems provide a way to create new types of entities by ‘gluing together’ component pieces at runtime.
In some ways, both blitz3d and mojo3d are already crude component systems. Some of what an entity does is not coded into the actual entity, but coded via an optional object such as an Animator or RigidBody that is ‘attached’ to an entity when needed. This is done behind the scenes in blitz3d, but is more explicit in mojo3d, eg: New RigidBody( entity ) both creates a RigidBody ‘component’ and adds it to an entity in one step. Using a separate RigidBody object here as opposed to just hacking *everything* into Entity helps keep Entity much simpler and lighter.
But Animator and RigidBody in mojo3d are currently attached to bodies in ‘ad hoc’ ways. Entity has an ‘Animator’ field to hold an optional animator object, but RigidBody uses a wonky ‘dynamic property’ system. This is because I want to keep physics in an optional module, so Entity can’t ‘know’ about physics, so it can’t have a RigidBody field.
Adding a Component system sort of generalizes all this and provides a consistent way to create components like Animator and RigidBody that can be optionally added to an Entity. Instead of Entity having an ‘Animator’ field etc, it just has an internal Stack<Component> that stores *everything* attached to the entity. When the entity needs to Update, it calls an OnUpdate Method inside each component in this stack, when it wants to render, ditto etc (although currently component system is not used fo rendering).
There is some similarity here to adding ‘child’ entites to an entity. But a child entity cannot ‘drive’ a parent the way a parent can ‘drive’ a child (drive=move etc) so things like RigidBody and ‘update scripts’ cannot be done like this. And this is where the simple blitz 3d entity approach falls down really. If I were to stick with a ‘pure’ blitz3d system and make RigidBody just a new type of entity, users would have no choice but to make RigidBody the ‘root’ of any entity hierarchy they wanted to apply physics to. This is doable, but is very inconvenient compared to just being able to attach a rigidbody to any entity.
There are lots of cool things about all this. For me, it makes my life easier as I now have a consistent way to create things that can optionally be attached to entities. And of course, anyone can write their own components using the same system – which also makes them a cool way to share code. Components can be combined in different ways, eg: the KeyboardContooller component described above can be easily switch to a JoystickController, even at runtime if you want. There is nothing mind bindingly complicated about being able to do this – but it does at the very least you don’t need to ‘roll your own system’ to handle it.
Note that at the extreme case, it’s possible to create a component system where an Entity has pretty much NO ‘functionality’ (well, except for AddComponent!) and does everything via components – even storing entity matrix and parent in a component. I’m not going to go that far (mostly I suspect because I’m just not that good a programmer) but it can be done.
I also haven’t converted Camera, Light etc to compnents yet. I would like to do this eventually, but would still like to provide blitz3d stylee Camera, Light entities too so you don’t have to deal with any component stuff if you don’t want to.
Finally, yes, this *is* a little more complex than blitz3d’s approach, but IMO it’s worth it. I agree with KISS, but not all solutions *can* be simple, ie: ‘make it as simple as possible, but not simpler’. I don’t want be afraid of adding features that are more complex than I’m used to and that make take me outside my comfort zone a bit (and this definitely qualifies), although for sure I do want to come up with the nicest/simplest solutions I can.
And seriously Adam, aren’t you just gonna write your own 3d engine from scratch anyway no matter what I do?!?
Very nice!
Not sure how happy you’ll be about this (hopefully happy!) but I actually started on a component system for mojo3d based on what we were talking about in the extending mojo3d thread, and I was planning to release it in v1.1.08.
I only did the ‘update’ stuff – Animator, Collider, RigidBody – as I didn’t want to move *everything* to a component system just yet for fear of upsetting the massive throng of existing users. Plus, I really just wanted to play with the general idea first anyway, and Animator and co are still very much experimental.
The ComponentType and Component classes look like this:
Monkey1234567891011121314151617181920212223242526272829303132333435Namespace mojo3d.graphicsEnum ComponentTypeFlagsSingleton=1EndClass ComponentTypeMethod New( name:String,priority:int,flags:ComponentTypeFlags )Property Name:String()Property Priority:Int()Property Flags:ComponentTypeFlags()EndClass ComponentMethod New( entity:Entity,type:ComponentType ) 'protected really...Property Entity:Entity()Property Type:ComponentType()Method OnCopy:Component( entity:Entity ) VirtualMethod OnBeginUpdate() VirtualMethod OnUpdate( elapsed:Float ) VirtualMethod OnDestroy() VirtualEndA few notes:
- the ‘Singleton’ ComponentType enum flag is for components that an Entity can only have 1 of. If this is not set, you can add more than one of a particular component type. Maybe ‘Unique’ might be a better name for this to prevent confusion? or even ‘Multiple’ with opposite meaning?
- The ‘Priority’ property is used when adding a component and determines component order within an entity. This allows you to make sure certain component types are processed/updated before/after other component types.
- I only did a handful of ‘On’ virtual methods in Component. More can easily be added, although I think we should be careful about what we add here, as there’s a danger of overcomplicating things IMO. Currently, entities are visited in ‘tree order’. OnBeginUpdate happens first and is ‘bottom up’, then OnUpdate happens ‘top down’. IME it’s very convient to have both bottom up and top down passes, although having a bottom up pass does imply visiting ALL nodes, whereas a top down pass can potentially ‘early out’, say for culling or something.
- I didn’t want to use reflection just yet as it’s not clear just how much overhead that will eventually use. I don’t expect it to be massive, but I still like to keep things as lean as possible and I don’t think we need reflection in this case. Hence the ComponentType class.
Here’s an example of an actual Component, the new RigidBody:
Monkey1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162Class RigidBody Extends Component'Every component shoud declare a 'Type' const like this...Const Type:=New ComponentType( "RigidBody",0,ComponentTypeFlags.Singleton )Method New( entity:Entity )Super.New( entity,Type )EndProperty Kinematic:Bool()Return _kinematicSetter( kinematic:Bool )_kinematic=kinematicEndProperty Mass:Float()Return _massSetter( mass:Float )_mass=massEndProperty Friction:Float()Return _frictionSetter( friction:Float )_friction=frictionEnd...etc...Method OnCopy:RigidBody( entity:Entity ) Override'copies body...EndMethod OnBeginUpdate() Override'syncs entity->bullet body...EndMethod OnUpdate( elapsed:Float ) Override'syncs bullet body->entity...EndMethod OnDestroy() Override'destroys bullet body...EndEndThe const ComponentType ‘Type’ member is a convention – every component type should implement it so that entity methods with <T> params can easily get component type using ‘T.Type’. For example, here’s Entity.NumComponents<T>()
Monkey123456789Method NumComponents<T>:Int()Local n:=0For Local c:=Eachin _componentsIf c.Type=T.Type n+=1NextReturn nEndAnother, non-generic way to implement NumComponents could be:
Monkey123456789Method NumComponents:Int( type:ComponentType )Local n:=0For Local c:=Eachin _componentsIf c.Type=type n+=1NextReturn nEndI haven’t decided which way is the best/right way yet, but I just thought I’d throw in both ways for now.
Note that the actual component management mechanism in Entity is very simple – it’s just a Stack<Component> – and could theoretically be souped up with Maps or something. But it also could be that simpler is better in this case as the actual component insert/count/remove etc code is very simple and it may not be worth making it more complex. Would definitely want to test before changing it anyway.
I haven’t done anything to Camera, Light, Renderer, Sprite etc yet, but my plan right now is to implement a CameraComponent (as you have above) and rewrite the Camera entity so it just redirects to CameraComponent. Ditto with Light. This provides a backwards-ish compatiblity layer for blitz3d users and is just plain easier to use for lazy coders like myself.
Renderable will probably go, and something like MeshRenderer added. A Model subclass can also be added to blitz3d-ify MeshRenderer. Not quite sure what Model.Load will do any more yet though!
Note that I haven’t pulled out the matrix stuff into a Transform component yet. I may do this later, but can’t really see the point right now except for the fact it’s a bit cleaner conceptually. The downside of having a Transform component is it’s a bit slower as there’s an extra indirection for each matrix or parent access (OK, not a big deal) and a bit more fiddly code-wise.
There are probably gonna issues with all this, but so far I like it. I hacked together a quick GameController component that behaves like a virtual joystick, with ‘ButtonDown’ etc methods, and a simple KeyboardController subclass that implemented keyboard input. I then moved the FlyAround code in util.monkey2 to a component that used the current GameController component for input.
So creating a flyable camera ended up looking like:
Monkey123Local camera:=New CameraNew KeyboardController( camera ) 'GameController priority should be -1?New FlyComponent( camera )There is of course a cost to all this, but IMO it’s minimal and defintely bearable – probably just the cost of the Stack<Component> allocation (plus underlying array) per entitiy created.
I guess you’re not really meant to subclass components, but I have done in several cases such as this (also, Collider is subclassed by BoxCollider, SphereCollider) and don’t see it as a problem just yet – as long as all subclasses have the same ComponentType that is. Otherwise, GetComponent etc may get ugly to implemement.
Is everyone OK with mojo3d going in this direction? It’s a bit of a major change, but it *does* make mojo3d way more flexible and expandable. I also hope you’re not too bummed out that I’ve gone in this direction too, Ethernaut! I do think your reflection/serialization stuff will be an invaluable addition to this, and eventually a reflection based GUI ‘object editor’ system along with custom editors for certain classes/types that could be implemented as ted2go plugins. A sort of ‘open’ RAD system with no fixed functionality.
Hey everyone, just wanna say I’m here and reading the comments.
I haven’t quite decided what I’m gonna do yet, but it’s reassuring that at least some people seem to think monkey2 is worth continuing with so I’ll definitely keep that in mind. Things get so quiet around here it’s hard to tell sometimes.
I’m actually OK with how much money patreon is pulling in. Sure, it’d be nice if it was enough to be able to work on monkey2 fulltime (which I have been doing anyway, but is gonna have to end SOON!) but still, 400/month is nothing to be sniffed at!
At the end of the day, I will almost certainly keep hacking away at monkey2 no matter what happens. As I’ve said before, I really have no desire to do another language, so at the very least twiddling with monkey2 and fixing bugs etc gives me a little ‘fix’ of language-dev every now and then.
Will post more as it occurs to me…
Streaming music is very high on the todo list!
You need to use the version of GetDecl with the extra ‘type’ parameter – GetDecl with just the name param returns null if there are multiple decls with the same name.
Also, for ctors the function type you pass to GetDecl should have a Void return type. Something like this…
Monkey1234567891011121314151617181920212223242526272829303132333435363738#Import "<reflection>"Class CMethod New( x:Int )Print "x="+xEndMethod New( n:String,x:Int )Print "n="+n+", x="+xEndMethod Test:String( x:Int,y:Float )Return ""EndEndFunction Main()Local info:=TypeInfo.GetType( "default.C" )'Lists declarationsFor Local d := Eachin info.GetDecls()Print d.Name+":"+d.TypeNext'Try to invoke 'New()'Local v:VariantLocal ctor:=info.GetDecl( "New",Typeof<Void(String,Int)> )v = ctor.Invoke( Null,New Variant[]( "Yeah!",10 ) )'Checks variant's typePrint "--------------------------------------------------"Print v.DynamicTypePrint "--------------------------------------------------"EndLooks really cool! Is there a new download available yet?
On android, any reason you don’t use “internal:”, or if you have large-ish files, perhaps this:
…which apparently requires no special permissions on KitKat+, so I was thinking of making it the “external:” of choice for monkey2 (which currently doesn’t even support “external:”). Root dir of external can be made available differently. I’m guessing getExternalFilesDir it’s the one we’re supposed to use anyway.
It would definitely be useful to find out some of the needs people have for fileio, and what the best approaches are. For example, I take it people want acces to media dirs like pictures, music etc. Anything else?
Any suggestions for general filesystem (or other) module improvements would be greatly appreciated too – feel free to post any source code you have!
-
AuthorPosts