[PloobsEngine] Tutorial 1 – Components and Input System


This second tutorial will teach you about the PloobsEngine Components and introduce the  Input handler System. (tutorials series here)

The idea is to make a little introduction describing the Components design, after show how the Input handler works and finish with a code sample.

What the hell are the PloobsEngine Components ?

Components are an abstraction to funcionalities that should be global to all screens everywhere. Its was designed to be completely independent and pluggable. To accomplish this task we used a slightly modified version of the Design Pattern Command Processor.

Every component extends the abstract class IComponent. You only communicate with components sending Commands objects through the CommandProcessor to them. The components contact our objects using specifics callbacks. Every Component used must be registered before, the PloobsEngine automatically register the Input and the DebugRender Components others are user responsability to register.

Remember, this is very important: Components are global, they are not binded to screen.

The CommandProcessor is a static class that is responsible to deliver Commands to the right component. It can send a command syncronous (the command is send exactely when the function is called) or assyncronous (the engine will send  the command as soon as possible, ALWAYS PREFFER THIS METHOD OF SENDING COMMANDS, IF YOU CAN — this method does not use threads)

As said, before using a component you need to add them, when you dont need it anymore you can remove

To add a Component just use this (we normally add components in the Initialize method of the IScreen, it has a parameter called EngineStuff that you use to add/remove and check if a component exists):

COMPONENT COMP = new COMPONENT();
engine.addcomponent(COMP);

Where COMPONENT is the actual component. After this we can send commands.

To send a Commmand, just use:

CommandProcessor.getCommandProcessor().SendCommandAssyncronous(COMMAND);

or

CommandProcessor.getCommandProcessor().SendCommandSyncronous(COMMAND);

 

The input advanced Component

This component is reponsible for handling Keyboard and Mouse. You send a command to this component describing an event (like Key B being pressed or Key O released) and the component will call a callback when the event happens (the process of associating a key event to a callback is called binding in the engine).

The input advanced component recieves the following commands:

  • ClearInputsCommand -> CLEAR ALL THE BINDINGS
  • BindMouseCommand -> BIND A MOUSE HANDLER
  • BindKeyCommand -> BIND A KEYBOARD HANDLER
  • TurnOffInputMaskCommand -> TURN OF AN INPUT MASK
  • TurnOnInputMaskCommand -> TURN OF AN INPUT MASK

The BindKeyCommand for example recieve two parameters, the first is an object called SimpleConcreteKeyboardInputPlayable that describes teh key event and the callback to call when the event is fired. The second is the action (add or remove the event). BindMouseCommand works in a similar way.

We can separate the inputs events (key and mouse handlers) in groups and enable and disable them when needed. A simple example is when we want to disable all character inputs when we enter in a in game menu (just put the inputs in diferrent groups and enable/disable them when needed).

To define the groups we use an InputMask (whe can pass it as a parameter in the SimpleConcreteKeyboardInputPlayable for example). It is a bit field. The engine has a active InputMask, if it input mask matchs with your event InputMask.

One example make everything clear:

Suppose that the engine has the 101 inputmask active.

And suppose that we bind 2 key events, the first has the input mask 100 and the second has 010.

Every frame The engine will check its Inputmask againt the key handlers input mask.

This is done by bit. The 101 in the engine InputMask means that the group 100 and the goup 001 are on and the 010 is off.

So, only the first handler will have the chance to be activated (the engine first check the InputMask of the registered event handler, if successful, it checks if the event really needs to be fired)

Internaly (if you are curious to know =P) the engine does this calculation: 101 ^ 100 = 100 Activate (100 = 100) for the first event handler and 101 ^ 010 != 101 (010 != 101) Not Activate for the second.

You can change the engine InputMask using TurnOffInputMaskCommand and TurnOnInputMaskCommand (you can use bit field operation to set the mask)

There are some special InputMasks like GALL that is 11111111111 (default in engine — means that all groups are enabled)

GSYSTEM is a very special inputmaks, cause it CANT be turned off (even if you try), if you bind a key handler to it, it will have the chance to be fired always.

The ClearInputsCommand, as the name said, clears ALL the event handlers =P.

An example of registering a event handler is:

SimpleConcreteKeyboardInputPlayable ik4 = new SimpleConcreteKeyboardInputPlayable(StateKey.DOWN, new Keys[] { Keys.LeftControl, Keys.U }, Multiple);
BindKeyCommand bk = new BindKeyCommand(ik4, BindAction.ADD);
CommandProcessor.getCommandProcessor().SendCommandAssyncronous(bk);

We created the SimpleConcretekeyboardInputPlayable passing the state of the key, the Keys (for Combo, you can use a single key if you want) and the Callback. After we create the command and send it using the Command Processor (we used the default InputMask GSYSTEM).

The callback is a function with the following signature:

public void Multiple(InputPlayableKeyBoard ipk)
{
/// Handle the event =P
}

There lots of ways to create the SimpleConcretekeyboardInputPlayable (dont set the event on the construtore, use the property to do this, it is easier =P)

REMEMBER, COMPONENTS ARE GLOBAL, the binding will remains until you delete it.

BUT, sometimes, we want to bind the inputs for just one screen, when the screen goes away, we want to remove the bindings (it is boring to override the clean up method of the screen to done this …). So the engine provides an alternate solution, instead of sending the commands directely to the input component, you can use the method BindInput of the IScreen to does the job.

SimpleConcreteKeyboardInputPlayable ik2 = new SimpleConcreteKeyboardInputPlayable(StateKey.PRESS, Keys.Y, g2,InputMask.G2);
this.BindInput(ik2);

In this case we “atached” the SimpleConcretekeyboardInputPlayable to the screen, that will take care of makind the binding and removing it when the screen goes away. (look, in this case we used the G2 InputMask — this is not a special mask, can be used for anything). The binding made this way can be removed before the screen goes away, just call the method RemoveInputBinding()

 

Code Example

The following code sample show how to use the InputAvanced. The event key T Pressed is binded to the InputMask G1, the event key Y Pressed is binded to the InputMaks G2 and the Key Space is binded to the GSystem (always active).

When you press Space you change the engine active InputMask to G1 and G2 (and you see that Key T Pressed does not work when G1 is active)

There is also a binding showing how to use the Combos.

The code is:

using PloobsEngine.SceneControl;
using PloobsEngine.Physics;
using PloobsEngine;
using PloobsEngine.Cameras;
using PloobsEngine.Input;
using Microsoft.Xna.Framework;
using PloobsEngine.Physics.Bepu;
using PloobsEngine.Modelo;
using PloobsEngine.Material;
using PloobsEngine.Commands;
using PloobsEngine.Light;
using Microsoft.Xna.Framework.Input;

namespace IntroductionDemo4._0
{
    ///
    /// InputScreen
    ///
    public class KeyboardInputScreen: IScene
    {
        ICamera cam;        

        protected override void SetWorldAndRenderTechnich(out IRenderTechnic renderTech, out IWorld world)
        {
            world = new IWorld(new BepuPhysicWorld(-0.097f,true), new SimpleCuller());
            DeferredRenderTechnicInitDescription desc = DeferredRenderTechnicInitDescription.Default();
            desc.DefferedDebug = false;
            desc.UseFloatingBufferForLightMap = false;
            renderTech = new DeferredRenderTechnic(desc) ;
        }
        protected override void  LoadContent(PloobsEngine.Engine.GraphicInfo GraphicInfo, PloobsEngine.Engine.GraphicFactory factory, IContentManager contentManager)
        {
            base.LoadContent(GraphicInfo, factory, contentManager);

            #region Models

            {
                SimpleModel sm = new SimpleModel(factory,"..\\Content\\Model\\cenario");
                IPhysicObject pi = new TriangleMeshObject(sm,Vector3.Zero, Matrix.Identity,Vector3.One,MaterialDescription.DefaultBepuMaterial());
                DeferredNormalShader shader = new DeferredNormalShader();
                shader.SpecularIntensity = 0;
                shader.SpecularPower = 0;
                IMaterial mat = new DeferredMaterial(shader);
                IObject obj3 = new IObject(mat, sm, pi);
                this.World.AddObject(obj3);
            }

            #endregion

            cam = new CameraFirstPerson(GraphicInfo.Viewport);
            cam.FarPlane = 3000;

            #region NormalLight
            DirectionalLightPE ld1 = new DirectionalLightPE(Vector3.Left, Color.White);
            DirectionalLightPE ld2 = new DirectionalLightPE(Vector3.Right, Color.White);
            DirectionalLightPE ld3 = new DirectionalLightPE(Vector3.Backward, Color.White);
            DirectionalLightPE ld4 = new DirectionalLightPE(Vector3.Forward, Color.White);
            DirectionalLightPE ld5 = new DirectionalLightPE(Vector3.Down, Color.White);
            float li = 0.4f;
            ld1.LightIntensity = li;
            ld2.LightIntensity = li;
            ld3.LightIntensity = li;
            ld4.LightIntensity = li;
            ld5.LightIntensity = li;
            this.World.AddLight(ld1);
            this.World.AddLight(ld2);
            this.World.AddLight(ld3);
            this.World.AddLight(ld4);
            this.World.AddLight(ld5);
            #endregion

            this.World.CameraManager.AddCamera(cam);            

            ///Bind a Key event (combination of Key + state(pressed, Released ...) + inputMask ) to a function
            SimpleConcreteKeyboardInputPlayable ik1 = new SimpleConcreteKeyboardInputPlayable(StateKey.PRESS, Keys.T, g1, InputMask.G1);
            ///When you use the method Bind of a IScreen, The key event will be sent by the engine while this screen remains added in the ScreenManager.
            ///TO create a Gloal Input (Keep working even if the screen goes away), see the DemosHomeScreen.cs
            this.BindInput(ik1);            

            SimpleConcreteKeyboardInputPlayable ik2 = new SimpleConcreteKeyboardInputPlayable(StateKey.PRESS, Keys.Y, g2,InputMask.G2);
            this.BindInput(ik2);            

            ///The SYSTEM Mask is Always On (cant be turned off)
            SimpleConcreteKeyboardInputPlayable ik3 = new SimpleConcreteKeyboardInputPlayable(StateKey.PRESS, Keys.Space, ChangeGroup,InputMask.GSYSTEM);
            this.BindInput(ik3);            

            ///StateKey.DOWN mean when the key is down the event will be fired --looooots of times(samae as UP)
            ///StateKey.PRESS is fired ONCE when the key is pressed (same as RELEASE)
            ///WHEN USING COMBOS, use DOWN AND UP (better for precision)
            ///The parameter EntityType is not used internaly
            SimpleConcreteKeyboardInputPlayable ik4 = new SimpleConcreteKeyboardInputPlayable(StateKey.DOWN, new Keys[] { Keys.LeftControl, Keys.U }, Multiple);
            this.BindInput(ik4);

            ///Send a command (design pattern) to the InputSystem to change the InputMask
            TurnOnInputMaskCommand tom = new TurnOnInputMaskCommand(InputMask.GALL);
            CommandProcessor.getCommandProcessor().SendCommandAssyncronous(tom);

            isAllActive = true;

            this.RenderTechnic.AddPostEffect(new AntiAliasingPostEffect());
        }

        bool isAllActive;
        bool isGroup1;
        bool isGroup2;
        bool isChangeGroup;
        bool isComboPressed;

        protected override void  Draw(GameTime gameTime, RenderHelper render)
        {
 	        base.Draw(gameTime, render);

            render.RenderBegin(Matrix.Identity);
            render.RenderText("Demo: Keyboard Input", new Vector2(GraphicInfo.Viewport.Width - 515, 15),Vector2.One ,Color.White);
            render.RenderText("Press Space to change the Active Input Mask (G1 or G2)", new Vector2(GraphicInfo.Viewport.Width - 515, 40), Vector2.One, Color.White);
            render.RenderText("Press T to use a G1 InputMask Input", new Vector2(GraphicInfo.Viewport.Width - 515, 60), Vector2.One, Color.White);
            render.RenderText("Press Y to use a G2 InputMask Input", new Vector2(GraphicInfo.Viewport.Width - 515, 80), Vector2.One, Color.White);
            render.RenderText("Press Ctrl + U TO use a Combo (Registered in all Masks)", new Vector2(GraphicInfo.Viewport.Width - 515, 100), Vector2.One, Color.White);
            if(isAllActive)
                render.RenderText("Group ALL Active", new Vector2(20, 40),Vector2.One, Color.White);
            if (isGroup1)
                render.RenderText("Group1", new Vector2(20, 20), Vector2.One, Color.White);
            if(isGroup2)
                render.RenderText("Group2", new Vector2(100, 20),Vector2.One, Color.White);
            if(isChangeGroup)
                render.RenderText("Active InputMask " + Groups[index], new Vector2(20, 40),Vector2.One, Color.White);
            if(isComboPressed)
                render.RenderText("Combo Pressed", new Vector2(20, 60),Vector2.One, Color.White);
            render.RenderEnd();

        }

        public void g1(InputPlayableKeyBoard ipk)
        {
            isGroup2 = false;
            isComboPressed = false;
            isGroup1 = true;
        }
        public void g2(InputPlayableKeyBoard ipk)
        {
            isGroup1 = false;
            isComboPressed = false;
            isGroup2 = true;
        }

        InputMask[] Im = new InputMask[] { InputMask.G1, InputMask.G2, InputMask.GALL };
        string[] Groups = new string[] { "G1", "G2", "GALL" };
        int index = 2;
        public void ChangeGroup(InputPlayableKeyBoard ipk)
        {
            index = (index + 1) % 3;

            ///Turn Off all Masks (we cant turn the GSYSTEM MASK, even if we try ....)
            TurnOffInputMaskCommand tof = new TurnOffInputMaskCommand(InputMask.GALL);
            CommandProcessor.getCommandProcessor().SendCommandAssyncronous(tof);

            ///Turn only the right mask
            ///Masks are Bit Field, You can turn more than one using InputMask.GALL | InputMask.G1 for example
            ///The TurnOnInputMaskCommand Just combine its actual mask with the mask provided, It does not TURN OFFthe active masks (this is the reason why i sent a turn off mask before)
            TurnOnInputMaskCommand tom = new TurnOnInputMaskCommand(Im[index] | InputMask.GNONE);
            CommandProcessor.getCommandProcessor().SendCommandAssyncronous(tom);

            isAllActive = false;
            isGroup1 = false;
            isGroup2 = false;
            isComboPressed = false;
            isChangeGroup = true;
        }

        public void Multiple(InputPlayableKeyBoard ipk)
        {
            isGroup1 = false;
            isGroup2 = false;
            isComboPressed = true;
        }

    }
}

The code for this demo can be found in our Introduction Demos package, you can download it here. (there are lots of others demos in this package, we will explain each of them in the next tutorials)

Any doubts, critics, suggestions, pls go to our forum or leave a comment here.

See you guys =P

Links

 

 

, , , , , ,

  1. #1 by youtube.com on 30 de abril de 2017 - 9:05 pm

    Howdy I am so excited I found your webpage, I really found you by accident, while
    I was browsing on Askjeeve for something else, Nonetheless I am here now and would just like to say
    cheers for a incredible post and a all round entertaining blog
    (I also love the theme/design), I don’t have time to read through it all at the moment
    but I have saved it and also included your RSS feeds, so when I
    have time I will be back to read much more, Please do keep up the
    great job.

  2. #2 by Pre-Owned and Used Luxury Cars in Atlanta Georgia on 30 de abril de 2017 - 9:27 pm

    hello there and thank you for your information – I have definitely picked up something new from right here.
    I did however expertise several technical
    issues using this site, since I experienced to reload the web site lots of times
    previous to I could get it to load properly.
    I had been wondering if your web host is OK? Not
    that I am complaining, but slow loading instances times will
    very frequently affect your placement in google and can damage your high-quality score
    if advertising and marketing with Adwords. Well I’m adding this RSS to my email
    and can look out for much more of your respective fascinating content.
    Ensure that you update this again very soon.

  3. #3 by ariel princess party on 30 de abril de 2017 - 9:29 pm

    It is in reality a nice and helpful piece of information. I’m happy that you just shared this useful information with us. Please stay us up to date like this. Thank you for sharing.

  4. #4 by Claudia on 30 de abril de 2017 - 9:31 pm

    I think the armin ⲟf tһis web site іs genuuinely
    woгking hɑгd for hhis web site, for thee reason thɑt here egery stuff is quality based data.

  5. #5 by purchase viagra on 30 de abril de 2017 - 9:32 pm

    What a joy to find someone else who thinks this way.

  6. #6 by Pre-Owned and Used Luxury Cars in Atlanta on 30 de abril de 2017 - 9:32 pm

    What’s up to every one, because I am in fact keen of
    reading this webpage’s post to be updated daily. It includes nice stuff.

  7. #7 by sarratumirkalli on 30 de abril de 2017 - 9:39 pm

    I have read so many posts about the blogger lovers but this piece
    of writing is genuinely a good paragraph, keep it up.

  8. #8 by pre-owned exotic cars in Atlanta GA on 30 de abril de 2017 - 10:08 pm

    Just desire to say your article is as astounding. The clarity for your put up is simply
    nice and that i could suppose you’re knowledgeable
    in this subject. Well with your permission allow me to seize your RSS feed to
    keep updated with forthcoming post. Thanks a million and please keep
    up the enjoyable work.

  9. #9 by RN Travel Assignments in California on 30 de abril de 2017 - 10:09 pm

    Amazing issues here. I am very satisfied to look your post.
    Thank you so much and I’m having a look ahead to contact you.
    Will you please drop me a mail?

  10. #10 by Cecil on 30 de abril de 2017 - 10:14 pm

    Thiss web site гeally hаs ɑll the infoгmation Ι
    neᥱded concerning thios subject and dіdn’t noѡ who to ask.

  11. #11 by sildenafil on 30 de abril de 2017 - 10:15 pm

    That’s a mold-breaker. Great thinking!

  12. #12 by silver mlm on 30 de abril de 2017 - 10:21 pm

    Wonderful blog you have here but I was curious if you knew of any user discussion forums that cover the same topics discussed in this article?
    I’d really like to be a part of community where I can get suggestions from other knowledgeable individuals that share the same interest.
    If you have any recommendations, please let me know. Kudos!

  13. #13 by http://www.kingpin-international.com/userfiles/media/421.html on 30 de abril de 2017 - 10:25 pm

    It headset was like spectacular just as within the image. That it appeared promptly. I would suggest utilizing a towel done every one coating as you click information technology over w / any vapor iron. It doesn’t vapor out alongside merely a steamer. Ones iron had been important. It is very fine, when you cannot trust personally with all the towel additionally vapor iron, after that bring they up to a pro. Awesome noise.

  14. #14 by http://www.dhaninvestment.com/power/7.html on 30 de abril de 2017 - 10:26 pm

    It headset had been because breathtaking because in visualize. This came promptly. I’d suggest using a towel through each and every coating as you push this outside w / letter steam iron. It doesn’t vapor away among merely a steamer. The actual iron is required. It can be sensitive, so if you cannot trust your self using the towel plus steam iron, subsequently accept things to a certified. Stunning noise.

  15. #15 by travelnursejobs.zohosites.com on 30 de abril de 2017 - 10:34 pm

    Thanks for finally talking about >[PloobsEngine] Tutorial 1 – Components and Input System | Ploobs <Liked it!

  16. #16 by http://news.saveindex.xyz/saveindexxyz/302.asp on 30 de abril de 2017 - 10:47 pm

    It product is in such a awesome price I by no means thought the particular top quality would be hence exceptional. Its breathtaking. Your mama is going to like it regarding Christmas early morning when she starts gift therefore appearances like I invested more, then again rates is really ideal!!

  17. #17 by http://news.hermesreplica.win/hermesreplicawin/440.asp on 30 de abril de 2017 - 10:48 pm

    I’ve purchased our brand regarding bracelet a number of circumstances. Every a person is super attractive, made well, does not tarnish to significant based on what an you purchase as well as which we give it at.

  18. #18 by http://www.musirc.com/ on 30 de abril de 2017 - 10:48 pm

    Your goods had been at such a great amount I by no means idea the actual good is and so exceptional. It’s pretty. Our mother will likely prefer that regarding Christmas time morning once she opens up present therefore styles like I invested even more, still pricing had been just awesome!!

  19. #19 by cars for sale in Atlanta on 30 de abril de 2017 - 10:55 pm

    You can certainly see your skills within the article you write.
    The world hopes for even more passionate writers like you
    who are not afraid to mention how they believe.
    Always go after your heart.

  20. #20 by Nurse Jobs in California on 30 de abril de 2017 - 10:55 pm

    First off I would like to say terrific blog!
    I had a quick question that I’d like to ask if you don’t mind.
    I was curious to find out how you center yourself and clear your head prior to writing.
    I’ve had difficulty clearing my mind in getting my thoughts out
    there. I do take pleasure in writing but it just seems like the first 10 to 15 minutes are usually wasted just trying to figure out how to begin. Any suggestions or hints?
    Many thanks!

  21. #21 by pre-owned luxury cars Atlanta on 30 de abril de 2017 - 10:55 pm

    I know this if off topic but I’m looking into starting my own weblog and was curious what all is required to get set up?
    I’m assuming having a blog like yours would cost
    a pretty penny? I’m not very internet savvy so I’m not
    100% positive. Any tips or advice would be greatly appreciated.
    Appreciate it

  22. #22 by milowrkf333322.bloguetechno.com on 30 de abril de 2017 - 10:56 pm

    Yesterԁay, whiⅼe I waas at worк, mу cousin stole my apple ipad аnd tested to ѕee if іt сan survive
    ɑ 25 foot drop, јust so she cаn bee a youtube
    sensation. Ӎy apple iad іs noᴡ broken аnd sɦe has 83 views.
    I know thiѕ iѕ totally off topic buut I
    had tߋ share іt with someone!

  23. #23 by Layne on 30 de abril de 2017 - 10:57 pm

    Right now it looks ⅼike WordPress iss tҺe tօp bllogging platform avаilable right now.
    (fгom ᴡhat I’vе гead) Is that what you are using on yohr blog?

  24. #24 by California Travel Positions for Registered Nurse on 30 de abril de 2017 - 10:58 pm

    Hello! Do you know if they make any plugins to help with
    SEO? I’m trying to get my blog to rank for some targeted keywords but I’m
    not seeing very good results. If you know
    of any please share. Appreciate it!

  25. #25 by Travel Jobs in California on 30 de abril de 2017 - 11:11 pm

    Thank you for sharing your thoughts. I truly appreciate your efforts and I will be waiting for your next write ups thanks
    once again.

  26. #26 by find on 30 de abril de 2017 - 11:15 pm

    Great write-up, I’m a frequent visitor of your blog. I like reading your articles.

  27. #27 by http://tysonpdqe470258.isblog.net/a-simple-key-for-ac-repair-in-miami-unveiled-2965997 on 30 de abril de 2017 - 11:15 pm

    Great post, I’m going to spend more time learning about this topic.

  28. #28 by Charles on 30 de abril de 2017 - 11:16 pm

    Hi, just wɑnted to tell you, I lіked this post. It
    was practical. Keep on posting!

  29. #29 by lukasumex998887.amoblog.com on 30 de abril de 2017 - 11:25 pm

    Thіs desig іs incredible! You obvioujsly know how tߋ ҝeep a reader entertained.
    Ⲃetween уour wit and yoᥙr videos, I wɑs aⅼmօst
    moved to start mʏ own blog (wеll, almost…HaHa!) Wonderful job.

    Ι rreally looved what you had too say, and moгe than that, hⲟw yoᥙ рresented іt.

    Toօ cool!

  30. #30 by California Travel Assignments for Registered Nurse on 30 de abril de 2017 - 11:26 pm

    It’s going to be end of mine day, however before ending I am reading this impressive article
    to increase my know-how.

1 1.987 1.988 1.989
(não será publicado)