Jump to content
  • Advertisement
  • entries
  • comments
  • views

Text Animation by Event System

Sign in to follow this  
Jason Z


Text Animation by Event System

I've been out of town camping for the past week, and so I haven't had much quiet time with my compiler lately. However, right before I left I managed to finish up a small text animation system for my text entity classes. The way that my engine handles text is to create a 'TextEntity2D' which allows for setting all of the normal properties (size, color, position, font, etc...) and can be integrated into my scene graph implementation. This allows for easy control over objects that have both 3D representations as well as text associated with them.

To allow for things like fading colors in and out, or having the text scroll to somewhere else, or manipulating any of the other properties mentioned above, I turned to the standard 'Controller' system that I adopted from the Wild Magic engine long ago. The controller attaches to an entity and modifies it's parameters in some time oriented fashion. In general, you create a new type of controller when you want to implement special or new functionality. However, I wanted to have the animation states to be dynamically requested, and not key framed or something like that - basically I don't want to have to load animations from file, but rather control then through my scripting interface instead.

The solution was to have the controller receive events which are sent by the scripting functions that request a state. The state contains information about how long to interpolate between the current state and the next state, as well as any new property values that are desired. So regardless of the current state of the text entity, I can call a scripting function with the desired new state information and the time to get to it, and then it will send a message to the controller and take the appropriate action to get to the new state.

The best part about this system is that it utilized all completely existing functionality - namely the scripting manager (indirectly by running a script, and directly by registering function interfaces for sending events), the event manager (for sending the events themselves), and the controller system (to implement the requests). It's nice to add functionality without adding tons of new code to work through and test [grin]!

Another nice feature is that I use a queue in the controller to allow a 'burst' of states to be requested. So if you want the text to move in a circular fashion you could send eight messages, each one 1/8 of the way around a circle, and then controller would process each request in turn - giving the rotation effect that I wanted. Overall, the system works quite well - although there isn't much of a chance for screenshots of an animations system like this [sad]. Even so, it works well and I can move on to adding similar functionality to the 3D entities as well.
Sign in to follow this  


Recommended Comments

Hi, I have a question.

How do you handle the interaction between a controller and an entity?

I think you have a base entity exposing "standard" parameters via Set/Get methods (or publicly accessible members), then a stub base controller and real controllers accessing the entity parameters.

From my POV the problem is handling a new entity. If a new entity exposes a new parameter, then in theory you should derive a new controller to take advantage of it, thus completely destroying the advantage of having pluggable controllers. Of course decoupling responsibilities is always good, but you understand my point.

I'm currently facing a similar problem on two different projects. One is an *huge* engine and another one is a small framework I'm writing for fun in my spare time. Sometimes I put new ideas in my personal framework, then transfer the good ones in the engine if possible.

Thus far I've thought about two possible solutons.

One is to use an advanced parameter system so that I can send an event targeting a specific parameter and let my controller do the job for me. Of course the node/entity/object will expose a SetXXX(string i_sName, XXXi_Val) method.
I can see two problems with this approach:
1- the more parameters describe an object, the more time is spent parsing the parameter list
2- since the event includes the parameter name, I always need to write specific code everytime I have to ask for a new parameter (i.e. "Position" and "MyPosition" are different parameters, so I need different code to create the two events).

The other idea is to base the communication on channels. You have a controller which supports N output channels and an entity with M input channels. A communication channel maps an output to an input (this process should also include the channel type validation), so that only the setup code (creating the communication channels) is entity/controller type specific. An interesting side effect is a pending event could be discarded if the channel doesn't exist or isn't properly connected. Of course it is mandatory for a controller event to include the channel number. What I like about channels is in theory there's no need for the input/output channels to be sequentially numbered, and this allows you to associate each entity input channel number with a unique semantic (position, rotation, scale, etc), then if you decide to write a new application a new map can be in use. Another side effect I like is the ability to attach multiple controllers to the same entity, each one connecting at least one of its outputs to an entity input. The downside is you probably need multiple instances of a controller to allow multiple entities to be controlled by the same controller type.

It's just an idea, but I'll probably try to implement it soon. I'd like to know more about your implementation. Comments on mine are welcome!

Share this comment

Link to comment
That is a very valid argument if you add new entity types, which I used to do in my older engine. However, now I typically only use an Entity3D, Node3D, and TextEntity2D for building blocks of objects. If I need additional functionality for a new application, the new style game objects use one or more of those basic entities connected together with various controllers attached to each entity. It is explicitly forbidden to change the basic entities because they are used in so many different types of objects that I can't imagine the retesting I would have to do...

The flexibility of the system is having multiple controller types available - I don't have any problem with deriving a new controller and having the application add the controller to an entity for a specific purpose. Your suggestion sounds like a monolithic controller to get/set all potential properties, which is a little different than what I am going for. I allow multiple controllers to be attached to each entity, and the person writing the code to add the controllers to that entity has to ensure that the controllers are mutually exclusive with respect to the properties that they modify.

For example, if I wanted to change the system from this post to have two controllers instead of one (say one for color control and one for position control) then I would just define separate controller derived classes that would get attached to the TextEntity2D. The application would write a 'glue' function that would add the controllers to the entity upon creation, which helps hide the integration issues.

Overall, it works for me. What do you think?

Share this comment

Link to comment
The idea seems good, as limiting the number of controllable classes allows you to focus on writing many reusable controllers. I'm sure this perfectly works 99% of the times you attach a controller.


Share this comment

Link to comment
Can you think of a scenario (the other 1% of the time) that it would not be a good solution? I may be wrong, but it sounds like you have something specific in mind that you are trying to overcome... Thanks for your questions by the way - I appreciate you reading my posts :)

Share this comment

Link to comment
It's a pleasure to read your journal, it's often inspiring. :)

You say this:

"the new style game objects use one or more of those basic entities connected together with various controllers attached to each entity"

An object IS NOT an entity but USES entities, so an entity can be thought as an attribute (actually a set of attributes), whose value(s) is (are) handled by the controller.

Since there's a strong coupling between a controller and an entity, because the controller needs to know the type of the entity it is attached to, you should pick up entities carefully. In the worst case scenario a new entity cannot be controlled by any of the controllers you already implemented.

While "entity3d" and "node3d" are generic sets of attributes, the same doesn't always apply to textentity2d.

Suppose you need 3d text inside your scene. You can implement a textentity3d class, but you can't use the controllers you already have available because its a brand new type. If you're going to use inheritance, you should decide if the base class is entity3d or textentity2d. Maybe you could have two base entities, a 3d entity and a 2d one. Textentity3d is derived from entity3d and textentity2d is derived from entity2d.
Of course the problem is the "text" part which needs to be written twice. Furthermore the controllers handling size and font should be written twice, even if they do exactly the same thing. You could probably allow a controller to be attached to different kind of entities, but this is a patch, not a good design practice. Maybe you can write an object taking some attributes from entity3d and some others from textentity2d, by using two entities. I wouldn't call such an object "clean", as some of the attributes in textentity2d (the entity2d part) are ignored. Without proper documentation the way the game object works isn't immediately understandable.

Multiple inheritance isn't an option, as things can get nasty. Think about a textentity3d derived from textentity and entity3d then all of a sudden you need an extra position, so you derive your new entity from textentity3d AND entity3d.
Multiple inheritance alone is a nightmare, I believe your list of entities used by an object is the way to go.

If we forget about the code, the problem looks simple: we have an object whose attributes must be controlled by external classes.

An OOP guru would come here and say: "hey, build small attribute sets as classes and use multiple inheritance to make an object support complex behaviour", but we know multiple inheritance is often evil.

Since I'm not an OOP guru, my POV is: if an object HAS A LIST OF other objects I consider them attributes, if an object IS ALSO another object then this is a behaviour.

IMHO the problem is we have a design based on behaviours (a design based on dependencies between class types) instead of a one based on attributes. (Actually it's a mix of the two: the relationship object-entities is attribute-like while the relationship entities-controllers is based on behaviours.)

I think implementing behaviours is not the way to go, as the problem is we don't know in advance which attributes will be needed in the future, but for sure we would like our existing controllers to work on any new object the programmer wants to create.

Since your design is partly based on attributes (an object uses entities aka sets of attributes), the idea is just to make a step further and have a finer control over attributes, so that you are not forced to use a set of N attributes if you need only one. This should allow reusable controllers/interpolators.

Sorry for the long post :)

Share this comment

Link to comment
I agree with your general discussion - we're on the same page. It is actually quite liberating to use the entities as attributes, after trying the inheritance route in my previous engine. All together I had approximately 40 classes based on the entity, and it pretty much sucked.

Life is better with more componentized designes, which this controller system helps with. Thanks again for the comments - I'll look forward to hearing more later on!

Share this comment

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!