Jump to content

Davaris

Members
  • Posts

    285
  • Joined

  • Last visited

Posts posted by Davaris

  1. Right click on the folder in which you would like to checkout your SVN working-folder and choose this URL as checkout URL:

    http://leadwerks-csharp.googlecode.com/svn/trunk

     

    The solution and projects have Visual C# 2010 format. To succesfully build the solution you should set NO BUILD for the "Test" project in the build configuration or manually copy the engine DLLs and shaders.pak in the "Test" project, else you will have errors during its build.

     

    svn1.png

    svn2.png

     

    I've followed all the instructions and can't get past one last error. It is asking for a file called app.config. Any ideas?

  2. I downloaded it and ran the zone and it worked fine using the executable, but after I ran the 2.3 updater on it (it downloaded a lot of files), I found the Zone crashes out when it is loading the MilitaryBarracks folder. It does not make any changes to the Engine.log file.

     

    EDIT:

    False alarm. I was using the old updater.

  3. I'm testing the LUA editor with the latest release and I am getting the above message when I press the play button on one of the sample scripts. The LUA script I am running, is in the directory:

     

    C:\Leadwerks Engine SDK

     

    Both Engine.exe and ScriptEditor.exe, are set to WinXP SP3 compatibility.

     

    I also set the paths in the ScriptEditor to:

     

    Exe, Debugger, Compiler

    C:\Leadwerks Engine SDK\Engine.exe

    C:\Leadwerks Engine SDK\Engine.debug.exe

    C:\Leadwerks Engine SDK\luac.exe

     

    Is there anything I have missed?

     

     

    EDIT:

    I got it working!

     

    I tried a right click and open with, but that didn't fix the problem either.

     

    However if I open the ScriptEditor.exe first and then use it to open a LUA file, it works.

  4. I thought I'd post this here, because we are writing C# code and I don't want to keep bugging the C++ people with what we are doing.

     

    This is the original thread, if you want to see what we were talking about:

    http://leadwerks.com/werkspace/index.php?/topic/2150-component-propertyattribute-design/

     

    What I am working on is similar to Rick's component idea but is also very different, in that you no longer have objects containing private data and the functions that operate on them.

     

    You have data as a separate entity and functions as separate entities. When the functions want to do something, they access the data pool.

     

    The other big idea, is you can stack data on top of each other, in a hierarchy to build up complexity and if you write a wrapper class (AKA Decorator) as described below, you can share a common pool of data with all your game entities.

     

    I took the idea from this excellent article. Read it to get an idea of what my code does:

    http://steve-yegge.blogspot.com/2008/10/universal-design-pattern.html

     

    You can write a wrapper class for it that provides a second parent pointer, so you can share all the parent data among your game entities base data. All it has to do is change StateCore's parent pointer to its own, before it performs an operation and then restore it when it is complete.

     

    As for permission, you are free to use this code in commercial or free projects, as long as you take full responsibility if it causes any damage. Also if you see a way to improve it, let me know as I am a C# newbie.

     

    TBH, it is probably safer to get the general idea and write your own. :)

     

    namespace Game
    {
       public class StateCore
       {
           // OrderedDictionary sorts as it inserts (bah!)
           // LinkedHashMap maintains insertion order, but you have to buy a decent one
           // and I don't know if it works on anything other than PC
           private OrderedDictionary<string, object> mList;
    
           private string mName;
           private StateCore mParent;
           public const string cBlank = "$_Blank_$";
           private bool mIsReadOnly;
    
           public string Name { get { return mName; } set { mName = value; } }
           public OrderedDictionary<string, object> List { get { return mList; } }
           public StateCore Parent { get { return mParent; } set { mParent = value; } }
           public bool IsReadOnly { get { return mIsReadOnly; } set { mIsReadOnly = value; } }
    
           public StateCore(string name)
           {
               mName = name;
               mList = new OrderedDictionary<string, object>();
               mParent = null;
               mIsReadOnly = false;
           }
    
           public bool Put<T>(string key, T val)
           {
               AssertIsReadOnly();
               AssertTypeCompatibiltyAll<T>(key);
    
               if (PutPrivate<T>(key, val))
               {
                   DebugPrintKeyVal("Put", key);
                   return true;
               }
               return false;
           }
           public bool Get<T>(string key, ref T ret_val)
           {
               object val;
    
               for (StateCore p = this; p != null; p = p.mParent)
               {
                   if (p.mList.TryGetValue(key, out val))
                   {
                       if (p.IsBlank(val)) return false;// not present
                       p.AssertTypeCompatibiltyVal<T>(val);
                       p.DebugPrintKeyVal("Get", key);
                       ret_val = (T)val;
                       return true;
                   }
               }
               return false; // not present
           }
           public bool Has<T>(string key)
           {
               object val;
    
               for (StateCore p = this; p != null; p = p.mParent)
               {
                   if (p.mList.TryGetValue(key, out val))
                   {
                       if (p.IsBlank(val)) return false;// not present
                       p.AssertTypeCompatibiltyVal<T>(val);
                       p.DebugPrintKeyVal("Has", key);
                       return true;
                   }
               }
               return false;// not present
           }
           public bool Remove<T>(string key)
           {
               object val;
    
               AssertIsReadOnly();
    
               if (mList.TryGetValue(key, out val))
               {
                   if (!IsBlank(val))
                       AssertTypeCompatibiltyAll<T>(key);
    
                   DebugPrintKeyVal("Remove", key);
                   mList.Remove(key);
                   return true;
               }
               return true;
           }
           public bool SetIsBlank<T>(string key)
           {
               AssertIsReadOnly();
               AssertTypeCompatibiltyAll<T>(key);
               if (PutPrivate(key, cBlank))
               {
                   DebugPrintKeyVal("SetIsBlank", key);
                   return true;
               }
               return false;
           }
    
           public void PrintContents()
           {
    
               Console.WriteLine("****************************");
               Console.WriteLine("PrintContents");
               Console.WriteLine("****************************");
    
               for (StateCore p = this; p != null; p = p.Parent)
               {
                   Console.WriteLine("");
                   Console.WriteLine("CONT = {0}", p.Name);
                   Console.WriteLine("");
    
                   foreach (KeyValuePair<string, object> entry in p.List)
                   {
                       if (entry.Value == null)
                           Console.WriteLine("({0}, null) TYPE: null", entry.Key);
                       else
                           Console.WriteLine("({0}, {1}) TYPE: {2}", entry.Key, entry.Value, entry.Value.GetType());
                       Console.WriteLine("");
                   }
               }
               Console.WriteLine("");
           }
    
           // *****************
    
           private bool PutPrivate<T>(string key, T val)
           {
               object ret_val;
    
               // Cannot put null values
               if (val == null)
                   throw new Exception("null values are not allowed");
    
               // assert key type is allowed
               GameState.AssertObjectType(val.GetType());
    
               if (mList.TryGetValue(key, out ret_val))
               {
                   if (!((T)val).Equals(ret_val)) // val will be changed
                   {
                       mList[key] = val;
                       return true;
                   }
               }
               else // new key
               {
                   mList.Add(key, val);
                   return true;
               }
               return false; // no change
           }
    
           private bool IsBlank(object val)
           {
               return val.GetType() == cBlank.GetType() && ((string)val) == cBlank;
           }
           private void AssertTypeCompatibiltyVal<T>(object val)
           {
               if (val.GetType() != typeof(T))
                   throw new Exception("Type is incompatible");
           }
           private void AssertTypeCompatibiltyAll<T>(string key)
           {
               object val;
    
               for (StateCore p = this; p != null; p = p.mParent)
               {
                   if (p.mList.TryGetValue(key, out val))
                   {
                       p.AssertTypeCompatibiltyVal<T>(val);
                       break;
                   }
               }
           }
           private void DebugPrintKeyVal(string function, string key)
           {
               /*
               if (mList[key] == null)
                   Console.WriteLine("{0}: ({1},null) TYPE: null, CONT: {2}", function, key, Name);
               else
                   Console.WriteLine("{0}: ({1},{2}) TYPE: {3}, CONT: {4}", function, key, mList[key], mList[key].GetType(), Name);
    
               Console.WriteLine("");
               */
           }
           private void AssertIsReadOnly()
           {
               if (mIsReadOnly)
                   throw new Exception(string.Format("{0} is read only and cannot be altered", Name));
           }
       }
    }
    
    

  5. Nice, but.. I cannot see C# in the "Programming" section and I think there should be since we have a C# community which seems to be active (at least me and few others Q_Q).

     

    C# and C++ are very similar except for the pointers and destructors. Just replace the '->' with '.', the '*' with nothing, and anything with a '~' in front of it with nothing and you are set. :unsure:

  6. Oh no, don't get me wrong. I just wanted to see a real world example so I could understand it better.

     

    I think what I've posted above explains it pretty well. At least I hope it does. :P As soon as I get it working in LWs I'll post it. It shouldn't be more than a week or so, if I stick with it.

     

    Anyway, what I love about this system, is you can use it to write glorious spaghetti code! :)

  7. I'm much closer to finishing now. I've wrapped my property class in a decorator class that stores a second parent pointer, so I can have different hierarchies of property bags that share the same property bags (if that makes any sense :) ).

     

    I've also written some messy classes (they won't win any beauty contests) that watch and interact with the property bags, using the Observer Pattern.

     

    Pointers are shared between these classes, however if one or the other is deleted, they tell each other to Detach immediately (this area needs more testing). After that, it is just XML and dlls and I'll be ready to start trying to do things in LWs.

     

    Have you tried to get an real world example working yet?

     

     

    If you are worried that this will run slow, I don't think it will. In fact, I think it will be super fast, if used correctly because it is event driven.

     

     

    This is where the bulk of work is done in my Action class. There will be one Action class for any action I invent for my games. As you can see, nothing happens until a variable it is listening for, changes in one of the property bags it is linked to.

     

       // The property bags send you messages when the
       // variables in them you are watching change.
       // You can also read or change the bags contents. 
       // You can create new actions from here as well.
    
       public override void OnNotify<T>(string owner_name, string opcode, string key, object val)
       {
           if (opcode != "Put") return;
    
           Console.WriteLine("{0} {1} has changed to {2}", owner_name, key, val);
    
           if (key == "uintKey2") // a message from bag1
           {
               float float_val = 0;
               // Get Speed from bag 2
               if (mSubject2.Get<float>("Speed", ref float_val))
               {
                   Console.WriteLine("{0} Speed is {1}", mSubject2.Name, float_val);
    
                   // Change Speed in bag 2
                   mSubject2.Put<float>("Speed", float_val + 100);
               }
           }
           if (key == "Strength")
           {
           }
           if (key == "Speed")
           {
           }
           if (key == "JUNK")
           {
           }
           if (key == "JUNK2")
           {
           }
           if (key == "JUNK3")
           {
           }
       }
    

     

     

     

    My action class also has an Update member, so if you need to you can keep a copy of the variable changes from OnNotify, so there is no need for costly lookups every tick or frame, or whatever they call it.

     

        
    public void OnUpdate()
    {
    }
    

     

    Output:

     

    child1 unitKey2 has changed to 123

    child1 Speed is 101

    child2 Speed has changed to 201

     

     

    Explanation:

     

    child1, child2 are the names of the property bags mSubject1, mSubject2.

     

    1) I changed the value of 'unitKey2' in 'mSubject1' (bag1) in my main loop and my action object was notified and received the changed variable in OnNotify<T>.

     

    2) My Action object then reads the value of 'Speed' from 'mSubject2' (bag2) and adds 100 to it.

     

    3) My action class is notified of the change it just made to 'Speed' in 'mSubject2', as are any other Action objects that are also watching it.

     

     

     

    EDIT:

    It just occurred to me that I may need to stop the action class, from being notified of the changes it makes to any property bags it is watching.

  8. Nice Flexman, those are the things I'm looking for. Thanks for the link too.

     

     

    Reload Weapon, Quaff potion.

     

    Another one you may not have though of is Effects. Say you are given a short term boost, you don't want to alter your main stats, you want to keep the boost in a separate object and add it to your main stat when you check it.

     

    When the effect wears off, it is deleted from your system. These kinds of effects can be used for many things from spells, potions, magic weapons and injuries that can be healed or can wear off by themselves.

  9. >Looking good Davaris. Have you tried to get an real world example working yet?

     

    Thanks. Its still early days yet. I have to add a few features (XML, a variable watcher and event sender, a way to share the parent's data with the whole system), before I'll be ready to start on the action objects that use it.

     

    I am also thinking of making it accessible from LUA, so I can use LUA scripts for my actions instead of C#, but I don't know if that is possible in Leadwerks.

     

    I have a question, do you think we should make these property bags thread safe?

     

     

     

    BTW you can get the source for the LinkedHashMap here:

     

    http://gforge.opensource-sw.net/gf/project/flexsdk/scmsvn/?action=browse&path=%2Ftrunk%2Fswfutils%2FJavaCompatibleClasses%2FLinkedHashMap.cs&revision=2&view=markup&pathrev=34

     

    It is a C# port taken from part of Adobe's FlexSDK, however I think there is a bug in it which can be fixed by doing the following:

     

    // (search for) m_Tail.m_Next = node;

    // (add this line underneath) node.m_Previous = m_Tail;

     

     

    The reason LinkedHashMap is so useful for our purposes, is everything is maintained in its original insertion order.

  10. This is what I have so far with my C# property container. I'm copying Steve Yegge's Universal Design pattern, so it will work differently to Rick's and may be too slow in the end (I hope not).

     

    I haven't posted the code yet, because it might have a minor bug or two that I can't see. So if anyone thinks of some good tests that might break something like this, please post them.

     

    public class StateData
    {
       private string mName;
       private LinkedHashMap List;
       private bool mIsReadOnly;
       private StateData mParent;
       private const string cBlank = "$_Blank_$";
    
    
       public StateData(string name)
       public void SetParent(StateData parent)
    
       // If the key in your parent exists, create a new key here
       public void Put<T>(string key, T val)
       public bool Get<T>(string key, ref T ret_val)
       public bool Has<T>(string key)
       public void Remove<T>(string key)
       public void SetIsBlank<T>(string key)
       public void PrintContents()
    }
    

     

    Sample usage:

     

           StateData state_parent = new StateData("parent");
    
           // ****************************
           // state_parent
           // ****************************
    
           state_parent.Put<float>("floatKey1", 6.0f);
           state_parent.Put<string>("stringKey1", "this is a string");
           state_parent.Put<int>("intKey1", 1);
           state_parent.Put<uint>("uintKey1", 1);
    
           // ****************************
           // state_child
           // ****************************
    
           StateData state_child = new StateData("child");
           state_child.SetParent(state_parent);
    
           state_child.Put<uint>("uintKey2", 122);
           state_child.Put<uint>("uintKey1", 7);
           state_child.Put<uint>("uintKey1", 99);
    
           state_child.SetIsBlank<int>("intKey1");
           //state_child.Remove<int>("intKey1");
    
           int int_val = 0;
           if (state_child.Get<int>("intKey1", ref int_val))
           {
               Console.WriteLine("intKey1 = " + int_val);
               Console.WriteLine("");
           }
           else
           {
               Console.WriteLine("Get intKey1 failed ");
               Console.WriteLine("");
           }
    
    
           state_child.PrintContents();
    
    

     

    Once you give the child a parent, the parent's data becomes read only. If the child wants to Put a variable (create or set) that already exists in the parent, it creates a copy in itself and henceforth accesses it instead of the one in the parent.

     

    Setting a variable as blank, forces the child class to read it (as null) instead of an identically named variable that may exist in the parent. That way you can get a 'variable does not exist' message back, even if an identically named one exists in the parent.

     

    If you Remove a variable, it will be removed from the child list completely and from then on a call to Get will search for the same named variable in the parent.

     

    Yes I know its a very odd way of doing things. You would have to read Steve Yegge's article to understand the reasons for it.

  11. Storing only one component per type is not so flexible... i.e. how could I create a chain of actions (cast abilities or also more animation sequences) to my toon? Or group more meshes? I would consider into turning to component's name as key for the Components.

     

    I'm not sure how Rick's code works, but you are supposed to be able to have more than one component of a type, as long as you think up a unique name for each one.

     

    The container class stores a list of components, each of which is addressed by a string label that you give it.

  12. The only downside to components that I have heard of, is some people say they can run a little slower due to the searching to get components. However I have also read there are ways to solve the speed issues. Also the major dev houses have been successfully using them for 5-10 years, so they must have overcome these problems.

     

    The speed issue will be something I'll have to deal with as there are a lot of variables per entity in my game, so there will be a lot of searching.

  13.  

    Good luck to all of you looking to implement this type of design though, I'll watch with interest!

     

     

    Thanks!

     

    I'll be using the techniques from the last two articles I linked on Object-Oriented Game Design, to refactor my huge inheritance based RPG engine, to the action-entity-data model, which really is a data driven Object Component model.

     

    My first goal will be to get it outputting its commands and results entirely in text and then I'll use the other techniques discussed in the articles to rapidly swap in Leadwerks, a 2D engine or almost any other 3D engine, if I wanted to do so.

     

    I also expect this structure to make it trivial, to add networking.

     

    So yeah, this will probably take a while... :)

     

    I'll post again on this subject, when I get the text version working.

  14. while this is an interesting topic... i find it has little practical value... sorta like theoretical metaphysics... :)

     

     

    http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy

     

    EXPECT RESISTANCE

     

    The first problem I encountered was in trying to explain the system to other programmers. If you are not particularly familiar with the idea of object composition and aggregation, then it can strike you as pointless, needlessly complex, and unnecessary extra work. Programmers who have worked with the traditional system of object hierarchies for many years become very used to working that way. They even become very good at working that way, and manage to work around the problems as they arise.

     

    Selling the idea to management is also a difficult. You need to be able to explain in plain words exactly how this is going to help get the game done faster. Something along the lines of:

     

    "Whenever we add new stuff to the game now, it takes a long time to do, and there are lots of bugs. If we do this new component object thing, it will let us add new stuff a lot quicker, and have fewer bugs."

     

    My approach was to introduce it in a stealth manner. I first discussed the idea with a couple of programmers individually, and eventually convinced them it was a good idea. I then implemented the basic framework for generic components, and implemented one small aspect of game object functionality as a component.

     

    I then presented this to the rest of the programmers. There was some confusion and resistance, but since it was implemented and working there was not much argument.

     

    :)

  15. Hey Guys,

    I found a few more articles with source that relate to this topic. If you are new to this kind of coding, they will increase your understanding.

     

     

     

    This is really long, but explains how actions, states and entities can work together to make an engine that can be used again and again for different types of games. It ties in with the code Rick wrote.

     

    Object-Oriented Game Design

    A modular and logical method of designing games

    http://www.devmaster.net/articles/oo-game-design/

     

     

     

    This blog entry explains the actions, states and entity relationship the above article introduces in simpler terms and once you understand it, you will see how powerful this kind of system is.

     

    Object-Oriented Game Design

    http://gbgames.com/blog/2006/03/object-oriented-game-design/

     

     

    Both articles have source, one is in C# and one C++. The monopoly example in C++ is more clear IMO, but both are worth a look.

     

     

     

    This guy wrote the code for the article "Game Object Component System" - Chris Stoy, from Game Programming Gems 6. It is mislabeled in the link below, as being from GPG 5. This is a C++ implementation.

    http://www.unseen-academy.de/componentSystem.html

     

     

     

    And finally a GameDev page of links:

    component-based design resources

    http://www.gamedev.net/community/forums/mod/journal/journal.asp?jn=443615&cmonth=9&cyear=2008

  16. Small variance to make it glow bluish. Also added a soft blue material to the cog for a smooth glow effect.

     

    This one reminds me of Metropolis for some reason. I'd make it simpler with just the hex and the cog.

     

    metropolis.jpg

     

    As for the logo, bring back the Steampunk! :P

     

    But seriously, I thought the old logo and coloring made the engine look neato and expensive, like a European sports car. :)

  17. Have a look at the article I linked to in comment #10. It makes Object Components go from cool, to very cool. :)

     

    Dynamic Game Object Component System for Mutable behavior Characters

     

    Also there are some behaviors you may want to turn on and off. For instance: sparkly effects, a twitch or a limp, a sound playing, a skill or ability earned or lost, a weapon equipped, armor that affects your stats and so on.

  18. If components can be added and removed during run time, then you would have to send a message to a component manager class, which in turn will tell all of its components what was removed.

     

    Then for the components that are missing a dependency, we have two options:

     

    1 A component that is a missing a dependency, tells the component manager to remove itself from the component list.

     

    2 If components are not deleted when removed (they are still in the list, but are not updated, or rendered anymore) you can let the component continue to access its "missing" dependency, as if nothing happened.

     

    As I don't know what should be the standard, perhaps it should be offered as a user selectable option for each component?

×
×
  • Create New...