More on Generic RPG
Advertisement
After spending much of my time off completing Roger Zelazny's works, trapped in the wikipedia time sink whirlpool, gamedev and watching TV Shows and generally not doing anything I got back into the game, so to speak yesterday, just when my little vacation is over.
Some thing I have noticed is that OOP is better for creating abstracted and decoupled easily extensible code. That is I have so far found OOP methods are better for arranging the overarching design than Functional programming which excels in detailing the execution. Using Functional Programming as glue and the real meat has allowed me to progress in a more descriptive manner and have the level of data driven code I wish. Also, although I have used objects with mutable fields, I have designed the objects to interact with functions which are mathematical in the sense that although they will run sequenced computations within, they will with a few exceptions return the same output given the same input. Nonetheless I have taken advantage of reference semantics for a few fields with regards to updating although this is leveraged in only 2 places in the code last i counted.
The code layout is based around interfaces and to a minor extent composition. GameObject mostly represents the part of the object that is used by the computer. When the map is created GameObject contains a set of values which will control what files are loaded, where they are drawn etc. Each object is associated with an SDL surface via a Map for rendering purposes. The class which renders is separate from the concept of World which itself collects objects which act or do not act. All GameObjects contain a field called AbstractPart. Which Is a field which accepts any objects that implements the AbstractObject Interface (requiring a .Act() method).
To render the Narrator tells the World to build a VisibleObjects Tree. This is done by partitioning the map into visible and none visible objects. The visible objects are then partitioned into those that act and those that do not. All the objects that act (e.g. move) are run through and then placed back into the NonActors Tree. This tree is sent to the narrator.
I enjoy being able to refactor sections of the code and not have to change any other bits and have it work. For example to update the system to use animations which have multiple differing I simply changed what I had left as a place holder - a string field to a list of tuples of type (string * string). Where the left string is the Animation name and the right is a filter expression that all animations which match it will be loaded. I suspect I will have to make significant changes to how I handle 'AbstractObjects' so I am glad of this ability to easily change sections without affecting other functionality.
The golden comet ball thing moves about like a fly while the tail animates. The blue flame does not move but animates
Source Snippet: Source
Another place where the focus on functional programming has paid off is in getting the AI up. The simple AI I rustled up uses Algebraic Types and Matching to create what I later found to be a Hierichal Finite State Machine. Within a functional paradigm it seemed pretty obvious and not worthy of a paper.. This is currently the stage where I am at. I wish the units to have fairly robust AI and am thinking of using Monads to implement something more robust than Behaviour Trees - that is if I understand it correctly, I am new to AI. My main texts on it are the book Mathematical Methods in Artificial Intelligence and AI Gamedev. My next post will detail my approach to this.
Some thing I have noticed is that OOP is better for creating abstracted and decoupled easily extensible code. That is I have so far found OOP methods are better for arranging the overarching design than Functional programming which excels in detailing the execution. Using Functional Programming as glue and the real meat has allowed me to progress in a more descriptive manner and have the level of data driven code I wish. Also, although I have used objects with mutable fields, I have designed the objects to interact with functions which are mathematical in the sense that although they will run sequenced computations within, they will with a few exceptions return the same output given the same input. Nonetheless I have taken advantage of reference semantics for a few fields with regards to updating although this is leveraged in only 2 places in the code last i counted.
The code layout is based around interfaces and to a minor extent composition. GameObject mostly represents the part of the object that is used by the computer. When the map is created GameObject contains a set of values which will control what files are loaded, where they are drawn etc. Each object is associated with an SDL surface via a Map for rendering purposes. The class which renders is separate from the concept of World which itself collects objects which act or do not act. All GameObjects contain a field called AbstractPart. Which Is a field which accepts any objects that implements the AbstractObject Interface (requiring a .Act() method).
To render the Narrator tells the World to build a VisibleObjects Tree. This is done by partitioning the map into visible and none visible objects. The visible objects are then partitioned into those that act and those that do not. All the objects that act (e.g. move) are run through and then placed back into the NonActors Tree. This tree is sent to the narrator.
def CheckFits( o, c, s, s2){ if ( (o + s2 - c > 0) && (o - c < s)) true else false } def partitioned_tree = Tree.Partition( visualization_tree , fun(o){ if ( CheckFits(o.Position.X, camera.Location.X,Nsdl.ScreenRes.Width, o.Size.Width ) && CheckFits(o.Position.Y, camera.Location.Y,Nsdl.ScreenRes.Height, o.Size.Height )) true else false }); def (visibleObjects, _) = partitioned_tree; def (actors, nonActors) = Tree.Partition (visibleObjects, fun(o) { match(o.VisualType ) { | VisualType.AnimatedAndActs => true | _ => false } }); seq [ (obj.Position, obj.CurrentAnimation) = (pos, dir.ToString ()) , obj in actors, obj.AbstractPart.Act(obj.Position, obj.Size) -> (pos, dir) ]; mutable FinalTree = nonActors; seq [ FinalTree = Tree.Insert(FinalTree, actor, false), actor in actors]; FinalTree;I enjoy being able to refactor sections of the code and not have to change any other bits and have it work. For example to update the system to use animations which have multiple differing I simply changed what I had left as a place holder - a string field to a list of tuples of type (string * string). Where the left string is the Animation name and the right is a filter expression that all animations which match it will be loaded. I suspect I will have to make significant changes to how I handle 'AbstractObjects' so I am glad of this ability to easily change sections without affecting other functionality.
The golden comet ball thing moves about like a fly while the tail animates. The blue flame does not move but animates
Source Snippet: Source
def objs = [GameObject(@".\Art\014.bmp", Drawing.Point(480,250), Drawing.Color.FromArgb (255,255,255), VisualType.Static() ), GameObject(@".\Art\stand2.png", Drawing.Point(920,300),Drawing.Color.FromArgb (200,140,208), VisualType.Static(), 1.0f ), GameObject(@".\Art\tavernx.bmp", Drawing.Point(420,260),Drawing.Color.FromArgb (200,140,208), VisualType.Static(), 1.0f )] ; def o1 = GameObject(@".\Art\017.bmp",Drawing.Color.FromArgb (255,255,255), VisualType.Static() ); def ao = GameObject(@".\Art\Animations\BlueJet", Color.FromArgb (2, 9,124), VisualType.Animated(), 2.0f); def ao2 = GameObject(@".\Art\Animations\earthmagic muni", Color.FromArgb (204, 173,97), VisualType.AnimatedAndActs(), 3.0f); ao2.FilterAnims = [("North","earthmagic muni n "),("South","earthmagic muni s"),("East","earthmagic muni e"), ("West","earthmagic muni w"),("NorthEast","earthmagic muni ne"),("SouthEast","earthmagic muni se"), ("NorthWest","earthmagic muni nw"),("SouthWest","earthmagic muni sw") ]; ao2.AbstractPart = MovingAnimatedObject(); def w = World(@".\Art\012.bmp"); seq [ w.AddObject (o) , o in objs]; w.AddObject(ao); w.AddObject(ao2); w.AddObjectManyTimes(o1, World.RandomDistribution(95, 500)); _ = Narrator(w);Another place where the focus on functional programming has paid off is in getting the AI up. The simple AI I rustled up uses Algebraic Types and Matching to create what I later found to be a Hierichal Finite State Machine. Within a functional paradigm it seemed pretty obvious and not worthy of a paper.. This is currently the stage where I am at. I wish the units to have fairly robust AI and am thinking of using Monads to implement something more robust than Behaviour Trees - that is if I understand it correctly, I am new to AI. My main texts on it are the book Mathematical Methods in Artificial Intelligence and AI Gamedev. My next post will detail my approach to this.
Advertisement
Advertisement
Advertisement
Discussion