The Perpetuated

Continuing on from previous posts about components, I attempted to build a component to group objects together, basically nominating an object as a Parent Object and then attaching a separate component for the Child Objects; attempt is currently the status of this component. There are a number of learning’s for me along this journey and as such I want to wrap up a few misconceptions I may have perpetuated.

Trigger Components

Many times I’ve found myself thinking that there has to be a better way and yet still have a solution that works and allows me to continue moving; the sense of motivation is important and so is being able to learn from my past indiscretions. In a previous post I suggested that to make use of triggers, we would subscribe to the event once during an update loop and then setup a method to handle the trigger event – that’s all good, except that SunBurn can save you from doing this if you just use the actual Trigger support as such:

[Serializable]
public class Component_PropperTrigger_HideObject : BaseComponentManualSerialization<ISceneEntity> // BaseComponentAutoSerialization<ISceneEntity> {
    public override void OnCollisionTrigger(IMovableObject collider, IMovableObject trigger)
    {
        // handle trigger response here... SceneObject sceneobject = (SceneObject)ParentObject;

        // Hide the object, except when the editor is running sceneobject.Visibility = ObjectVisibility.RenderedInEditor;

        // Stop reciving updates for this object (Don't trigger any more events & ensure that this is only called once). sceneobject.CollisionType = SynapseGaming.LightingSystem.Collision.CollisionType.None;
    }

}

 

That’s easy isn’t it? Keep all the editor settings the same & you can just drop this component in.

Editor Variables

Previously I suggested a way of adding an editor updatable variable by creating a custom Scene Entity and then using a static class to marshal the updates to the other component – well that’s not needed either. In fact you can add the same directions to the components and enable variable editing through the editor just like a custom scene entity. Here’s an example of how to do it – using the Weapon component introduced previously with a variable to support the distance that the object will come in to existence (based on a distance from the origin of the object that the component is attached to). Also note that I’m using Manual Serialisation in this example just to demo how this combination can be used.

[Serializable]
[EditorCreatedObject]
public class Component_Trigger_FireWepon :  BaseComponentManualSerialization<ISceneEntity>
{
    bool xDown = false;

    private int _OriginDistance = 8;

    [EditorProperty(true, Description = "Origin Distance", ToolTipText = "The distance that the weapon fire will generate away from the origin")]
    public int DistanceFromOrigin
    {
        get { return _OriginDistance; }
        set { _OriginDistance = value;}
    }

    public override void SetObjectData(SerializationInfo info, StreamingContext c)
    {
        base.SetObjectData(info, c);
        SerializationHelper.DeserializeField(ref _OriginDistance, info, "OriginDistance", true);
    }

    public override void GetObjectData(SerializationInfo info, StreamingContext c)
    {
        base.GetObjectData(info, c);
        info.AddValue("OriginDistance", _OriginDistance);
    }

    public override void OnUpdate(GameTime gameTime)
    {
        KeyboardState keyboard = Keyboard.GetState();

        // Cast the Object the component is attached to, to a scene object SceneObject sceneobject = (SceneObject)ParentObject;

        // Move Forward if (keyboard.IsKeyDown(Keys.X) && !xDown)
        {
            xDown = true;

            SceneObject fire = new SceneObject();
            SceneObject copyBase;
            SceneInterface.ActiveSceneInterface.ObjectManager.Find("Fire", out copyBase);
            fire = (SceneObject)copyBase.Clone();
            fire.CollisionMove.RemoveForces();

            //Scale-Rotation-Translation Quaternion fireQ = new Quaternion();
            Vector3 fireSpot = new Vector3();
            Vector3 fireScale = new Vector3();
            fire.World.Decompose(out fireScale, out fireQ, out fireSpot);

            Quaternion rotationQ = new Quaternion();
            Vector3 spot = new Vector3();
            Vector3 scale = new Vector3();
            sceneobject.World.Decompose(out scale, out rotationQ, out spot);

            Matrix rotation = Matrix.CreateFromQuaternion(rotationQ);
            Matrix location = Matrix.CreateTranslation(sceneobject.World.Translation.X, sceneobject.World.Translation.Y, sceneobject.World.Translation.Z);
            //works fire.World = rotation * location;

            // Puts the bullet in front of the player (fire.World.Forward * 8) is the distance in front of the player Vector3 testTranslation = fire.World.Translation + (fire.World.Forward * _OriginDistance);

            // Multiple by scale first to get the right size Matrix scaleM = Matrix.CreateScale(fireScale);
            // Define the offsetHight for the Bullet to start from Matrix offsetHeight = Matrix.CreateTranslation(0f, 2f, 0f);

            // Set the direction for the bullet (rotation) // Multiply by the result of // The multiplicatino of the offset from the world translation after the rotation has been set and the location of the player // By the offset height fire.World = scaleM * (rotation * (Matrix.CreateTranslation(testTranslation) * offsetHeight));
            // & hey presto we have a bullet traveling from the direction the player is looking in with a small offset in front of the player Vector3 directionOfFire = new Vector3(0f, 0f, -0.7f);
            fire.CollisionMove.ApplyObjectForce(directionOfFire);

            fire.UpdateType = UpdateType.Automatic;
            fire.Visibility = ObjectVisibility.RenderedAndCastShadows;

            fire.Name = "shot";

            SceneInterface.ActiveSceneInterface.ObjectManager.Submit(fire);

        }
        else {
            if (keyboard.IsKeyUp(Keys.X))
            {
                xDown = false;
            }
        }

    }
}

 

Try it out and see how it goes & if you do, attach the component to two objects and then set the distance to different amounts and notice that everything is serialized separately – awesome!

If you don’t want to persist the variable data yourself, use the [SerializeMember] directive in front of the [EditorProperty] directive then it serializes and persists as expected.

Hopefully this ensures no further perpetuation because of my past gaffes’, if you do identify any, feel free to drop me a note and help me get it redacted.

Leave a Reply

Your email address will not be published. Required fields are marked *