Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

Work in Progress / Et Sulium Sao Eterniae

Author
Message
Ortu
DBPro Master
16
Years of Service
User Offline
Joined: 21st Nov 2007
Location: Austin, TX
Posted: 28th Sep 2014 04:38
Yep, that link is the version I am using

Ortu
DBPro Master
16
Years of Service
User Offline
Joined: 21st Nov 2007
Location: Austin, TX
Posted: 3rd Oct 2014 15:33 Edited at: 3rd Oct 2014 15:35
Hello again!

As mentioned in last week's update, I have been working on implementing interactable entities within the game world. These are things which the player can Examine, Use, Take, or Converse with.

It has been a hard fought and stressful pair of weeks, let me tell you. Aside from some tough to locate compile errors, some of the new functionality uncovered bugs, conflicts and potential conflicts with older system designs and required some refactoring of code and implementation across several modules. Chiefly, the animation and character handlers.

Three out of the four interactions are now complete however! It doesn't sound or look like much perhaps, and the video is short, but these are significant mechanics, providing some of the basic foundations which can begin to contribute towards actual game play, instead of just to the underlying engine as much of the previous work has been so far.



EXAMINE Interactables:

This was fairly simple and straightforward to implement, it took about an hour and I had actually recorded the entire development session for an update as it was a great showcase of working with the UI system. Unfortunately, the video was missing the first three quarters of the session. The recording software has a ‘pause' button, but apparently it drops anything recorded before the pause, and essentially just works as a ‘restart recording' button without giving a chance to save out what had been captured so far.

Still, the work itself was done and I am now able to detect an intereactable object within the world, execute an examine action, and return a description to a new gui panel on screen. Nice!

USE Interactables:
As more animated objects were added into the scene, it became increasingly difficult for each object to maintain a reference to its own current animation ID within the handler. In hindsight, it was a poor design choice that worked fine when the only object being animated was the player's own character, but as the system grows…

So, things have now been altered such that animated objects no longer attempt to track their own handlers. For one thing, they really don't need to know specifically which index contains their animation data. They already were making blind setter requests to the handler to set a new animation state, but I foolishly had them accessing current animation data through their specific handler ID. Of course, the problems started when handlers were removed and/or reordered. Now, when an object needs to know something about its current animation state, they can request it through new getter functions which do not require them to know anything about the exact data structure handling their animation data.

Next up in the list of hurdles came dynamically updated collision. Effing collision… this took two days alone to get working right, and after bad assumptions, much testing, several failed approaches, and lots of hair pulling, I've settled on a work around which isn't perhaps the best approach, but works well enough to proceed. This is an issue of anything which transitions through multiple states, requiring different collision data while in different states. Most obviously this applies to things like doors which can transition between open / closed.

The root problem? sc_updateObject – I had assumed this command would update including bone transformations. It does not. Well at first, I figured the problem was with Blender's export of the model, I have had to resolve issues between the exporter and Sparky's in the past so it seemed a likely culprit. I spent half a day testing various settings, files, and exporter versions before eliminating this as the cause.

Yes, Sparky's help file clearly states that it updates object location, rotation, and scale, and mentions nothing about animation deformation… I should have read the documentation more closely I know, but I did not. Anyway, ok so my bone animation based states did not update correctly, and I still could not walk through a door that had swung opened after using it. >> read the help files loc/rot/scale >> ok. So let's try old school object limb based animation: animate an object as a limb instead of transforming the mesh with a bone, like back in the DB Classic days. Same problem, the child limb is animating, but updateObject does not seem to be updating with the altered keyframe animated limb position. I still could not walk through the door.

At this point, I realize I will probably have to animate directly in the code via rotate object and the like, but while that would work fine for something like a door which animates only along a single fixed axis, it would quickly grow complicated for things which can have arbitrary rotations and animations: the lid of a chest opening and closing for instance which has itself already been rotated within the scene. Secondly, this sort of animation would require a completely different and separate animation handler from the keyframe based system already in use. This whole approach just seemed very problematic and I was not thrilled to attempt it. Another time perhaps.

Instead, I have chosen to implement a workaround using multiple collision meshes. I am already using simplified, non-rendered collision meshes for much of the static environment, the boardwalk / pier for example: the visible rendered object uses a separate box for each plank (as floating geometry all contained within a single object), but collision is calculated against a single larger box encompassing all of the planks together. This simplified geometry helps keep the collision system performing well, the objects can also be deleted or excluded once they have been added, and it allows the character to walk smoothly over the planks, despite gaps and minor uneven surfaces in the visible render of more detailed geometry.

Thus, most collidable entities are composed of 2 files: a detailed renderable mesh and an optimized collision mesh. So now, for useable multi-state objects such as a door, I have a collision mesh for each distinct state. A door has 2 states, ‘open' and ‘closed', and so it has 3 files: a detailed renderable mesh, a static collision mesh for open, and a static collision mesh for closed. The system is fully extensible and can handle useable objects with any arbitrary number of states with no need for additional code to manage them. On use, the visible detailed mesh is animated through the standard keyframe animation handler, and on animation completion, the active collision mesh is toggled from one state to the next through the use of a new function callback parameter added and passed to the handler when a sequence directed to start playing. This can be any function name you wish to execute once the animation is complete.

Now, this does mean that you are prevented from walking through a doorway as the door swings open, and you can walk through the door as it swings shut as the active collision is only updated when the animation reaches the next distinct state, but for now, this is a minor and acceptable concession to get the overall system to a working state. I will most likely need to revisit this later.

TAKE Interactables:

Next up comes things which can be taken from the world and put into the character's inventory. An actual inventory system is not yet in place, so for now I am just moving such items directly to an equipped state. The mechanics of removing the item from the world, associating ownership with a character, and binding it visually to the character / character animation is separate from the mechanics of managing inventory so this is not an issue, nor wasted effort. The inventory system will ultimately sit between the steps of removing the object from the world, and binding it to the character object, but will not interfere with either. Again pretty straight forward to implement, with just a few typical compile errors/issues to get through before getting it working.

CONVERSE Interactables:

I have not yet begun to work on this one, and likely will not for some time. The core interaction system which handles detection and interaction triggers will handle this action as well, but the actual execution of the action will require considerable work on a complex npc system that is still mostly in the design and planning phase. Basically, it is too early with none of the foundational data and AI required to do much on this action yet.

So, the last two weeks were spent mostly on code, next week I will turn back to the art and modeling side of things for a bit and flesh out the world a bit more.

-

wattywatts
14
Years of Service
User Offline
Joined: 25th May 2009
Location: Michigan
Posted: 3rd Oct 2014 19:41
That seems odd that you had problems with Sparky's and the door, I've had rotating platforms in some projects that worked great without any effort whatsoever.
Ortu
DBPro Master
16
Years of Service
User Offline
Joined: 21st Nov 2007
Location: Austin, TX
Posted: 3rd Oct 2014 21:04
Interesting.

How were your platforms being animated/rotated?

Keyframed bones via play/loop object / set object frame
Keyframed objects / limbs via play/loop/set
Code managed objects via position object / rotate object

?

Chris Tate
DBPro Master
15
Years of Service
User Offline
Joined: 29th Aug 2008
Location: London, England
Posted: 3rd Oct 2014 21:54 Edited at: 3rd Oct 2014 21:58
Quote: "Effing collision… this took two days alone to get working right, and after bad assumptions, much testing, several failed approaches, and lots of hair pulling, I've settled on a work around"


As fast as two days lol. Things like that would take me two weeks; and even then it would not be final.

Quote: "
I had assumed this command would update including bone transformations. It does not"


It would have been cool if it did.

Quote: "
walk through a door that had swung opened after using it...So let's try old school object limb based animation: animate an object as a limb instead of transforming the mesh with a bone"


This is why I like reading this devblog, so many techniques I would not have thought of using.

I would tend to not consider adding collision data to a door, since it is either opened or closed as far as the player is concerned; unless a half open door defines a different context; but it will be interesting to see what you come up with.

Quote: "
multiple collision meshes...allows the character to walk smoothly over the planks, despite gaps and minor uneven surfaces in the visible render of more detailed geometry."


A solid benefit indeed

Quote: "
An actual inventory system is not yet in place, so for now I am just moving such items directly to an equipped state"


Interesting challenge. I could not justify creating an inventory system in DBP alone because I would prefer to use a purpose built DBP plugin; it will be interesting to see what path you chooise.

If my life depended on it and I were not permitted to create plugins, I would use BBB GUI to take care of the inventory.

Ortu
DBPro Master
16
Years of Service
User Offline
Joined: 21st Nov 2007
Location: Austin, TX
Posted: 4th Oct 2014 07:07 Edited at: 4th Oct 2014 07:11
Quote: "This is why I like reading this devblog, so many techniques I would not have thought of using."


Yeah, give a problem to 100 different programmers, you will come up with at least 50+ different solutions. It's always interesting to see how different minds will approach something.

Quote: "I would tend to not consider adding collision data to a door, since it is either opened or closed as far as the player is concerned; unless a half open door defines a different context"


Well, I ended up with just collision as an open state, or collision as a closed state and toggle between them, I wanted full sliding collision while it was in mid swing, so you would not have to wait for the animation to finish before proceeding, and would not clip through the visible object if you tried to run through too soon. Running through a swinging door or waiting for it to finish isn't a huge deal, you can see both of these things happening in many games, and I don't think any project ever really gets completed without some compromises along the way. I may come back and revisit the issue, but this works well enough for now.

Quote: "Interesting challenge. I could not justify creating an inventory system in DBP alone because I would prefer to use a purpose built DBP plugin; it will be interesting to see what path you chooise.

If my life depended on it and I were not permitted to create plugins, I would use BBB GUI to take care of the inventory."


Inventory systems are primarily extensions of the GUI system. The actual data behind linking an item to a character isn't overly complex, particularly when it is all managed by a good database, what trips people up I think is interfacing with that data, and trying to build it without a good, robust GUI foundation. As you mention, a good GUI plugin like BBB should make short work of implementing an inventory.

My GUI system is native dbp code (+matrix1), but it is pretty decent I think, performance is quite reasonable, the biggest hits come when switching font properties like color, size, font-family etc and so I try to limit text styling to one or two standards, like a heading style and a body style. Performance on this would likely be improved by using say, cloggy's d3d plugin. It's been a long time since I last worked with that one and I need to go back and look over it again.

The thing I like best about the system though, is its nature and flexibility. It is inspired by the web, using html specifications for element layout, css specifications for styling, employs MVC design principles separating components into .xml views and .dba controllers, it implements events and event callbacks and so on.

With this system already in place to build on, I do not expect the inventory system to give me too much trouble... /knock on wood

Chris Tate
DBPro Master
15
Years of Service
User Offline
Joined: 29th Aug 2008
Location: London, England
Posted: 4th Oct 2014 18:01
The inventory system seems to be well underway.

Ortu
DBPro Master
16
Years of Service
User Offline
Joined: 21st Nov 2007
Location: Austin, TX
Posted: 10th Oct 2014 15:59 Edited at: 11th Nov 2014 05:26
Today's update will be short and sweet folks.

I was planning to turn back to modelling this week, and did end up blocking out some of the interior furnishings for the house, but the discussion on the inventory system wouldn't get out of my head.

The video recording issues also continued to bother me, so I tracked down the lost content issue and have found that it wasn't due to the pause, it was due to exceeding a 2gb limit for the avi codec used to record with. Anything more than 2gb was unplayable in windows media player, although sometimes they could still play and compress ok in Blender, but there seems to be a hard cap at 4gb and most of those are scrambled too badly to be viewable.

So, for large videos, I have to record in smaller chunks < 2gb each, which depending on framerate and quality settings can run from about 90 seconds to 3 minutes per clip, then stitch them all back together again and compress.

Now, put this all together and you get today's update!

You will want to watch this in full screen for text readability, and it looks like Youtube serves up a fuzzy low res version while it continues to buffer in the background, the text gets to full crispness at about 24 seconds in when I watch it back :/ Have patience, you don't miss much at the start and the full session is about 10 minutes, which is compressed down from about 45 minutes in real time.


Making an Inventory - Part 1



- Edit -

After thinking about it for a while, I'm not sure I like video as a platform for demonstrating code. Static text is easier to follow and easier to put a presentation together. On that note, here is a quick text based overview of the video above. Part 2 later this week will likely be a similar text based update unless people just really want a video or something.

-----------

Adding new gui elements and classes is done entirely in xml, this lets me add, remove, and modify the way the UI looks without any need for a recompile. You can even alter how an element behaves by changing the event callback references with no need to recompile, however, to add or modify the callback function itself which is being referenced, you will need to make those changes in the controller and this does require a new compile.

For this part 1, we will be working solely with the view, to get the basic layout and appearance set up in game. Part 2 will hook this up to the controller to get the system actually doing stuff.

For elements like buttons and drop slots, in which we will have many instances of each, we will want to set up a style class which can be used to apply common style settings in bulk.

For the inventory system, I will be using two different sizes of item slots, one for bag space, and one for the things actively equipped. Thus, we will set up a class for each of these:



Which is the equivalent of this in css:



You will see that a large portion of the css 2 properties are supported, with more being added here and there as I get to them.

Next, we need to add a new element which will serve as the main inventory panel and which will contain all of the sub-elements like bag slots, paperdoll, control buttons etc. As gui elements are heirarchal, children inherit things like positioning and visibility (among others) from their parent. This means that if we want to toggle showing the inventory panel, we only need to toggle the display of the top level panel element, if this is hidden, the children will simply be excluded from the update process much like "exclude object on"

I'll write the element attributes in long form, as they are easier to read down as a vertical list I think, but I'll show the final result in the condensensed horizontal form which more closely matches html. Both forms are valid XML and can be parsed and loaded either way.



Which is roughly the equivalent of this in html:



Elements support "inline" styling which will be applied on top of inherited and class properties, just as html elements do, and while in line styling is generally a no no in html/css, dbpro works differently and it doesn't matter as much in my system, particularly on single one time elements.

You may notice here the property 'position-alignH="right" left="-8%"'. This is similar to using 'position:absolute;right:8%;' though the align also supports automatic centering. (as does position-alignV:top/bottom/center).

Some caveats to the system as it currently stands: It can offset by left and top only, and positions default to 'absolute', this is because it has no implementation of content wrapping or line breaks, and elements have no awareness of sibling elements to position themselves around. Elements are only really aware of their direct parent. This is not ideal, nor how it will remain so, but it is complete enough for current needs. So what this means is that position-align H/V will force the element in the specified direction towards its parent's boundary, taking into account margin and padding of itself and its parent, but ignoring any other content it may pass through or overlap.

Ok, now we will add 10 slots as empty storage space to put items into. These will be arranged as a grid, and instead of trying to position each one individually with exact x,y coordinates, we can make an invisible wrapper element and let the slots inherit this parent container's location and dimensions for alignment and positioning. This also lets us move and modify all of the slots together as a group just by modifying the wrapper element.

To add the wrapper as a child of the main panel, stick in after the panel's style block and before its closing block:



So how does opacity="0" differ from display="none" ? display:none completely excludes an element and its children from the update process, opacity:0 will still resolve the element's properties and continue to process its children, it just won't itself be rendered.

Next up, we need to fill our container with the actual slot elements. A bunch of nearly identicle elements like this could be (and usually are) created proceedurally in code. In the web, and following a strict MVC design, this should be done by a templating engine, jade and angular come to mind, though often these view elements get tangled up in the controller and are inserted with jQuery. Now, my little dbpro gui system is not nearly so robust as to support templating, but I'd still rather keep the view elements separate from the control code layer, so I am going to go ahead and define them manually here. If there were more than just 10, I'd probably go ahead and have the code do it. This is sort of the arbitrary grey area where things can be done in any number of ways and places and it is not a huge issue either way.

Anyway, we will make 2 columns of 5 slots each. Elements are left/top aligned and position:absolute by default. This means that we need to apply a right alignment to second column elements and an offset from top for each row. These alignments and offsets are based on the inventorySlots-wrap element so top:0, left:0 will be the top left corner of inventorySlots-wrap not literal 0, 0 in screen coords.



Next, there will be 6 slots for actively equipped items covering weapons, armor, and accessories. These will be arranged around the paperdoll image in the main panel background, and so these will not lend themselves to aligning against a container. These will just be explicitly positioned children of the main panel.

And so here is our full inventory panel view definition:



And it's equivalent in html/css:



Now of course on the web, we would move all the main panel inline styles into a #gameHUD-inventoryPanel selector and things like position:absolute could get moved into the css classes, In fact you would want to leave these as a default static and let the layout engine wrap/line break these down into rows for you spaced with margins, but I am mainly trying to show as close to a 1:1 translation between html/css and my gui as is currently possible rather than to show the best way to write html :p



Attachments

Login to view attachments
Ortu
DBPro Master
16
Years of Service
User Offline
Joined: 21st Nov 2007
Location: Austin, TX
Posted: 18th Oct 2014 00:23 Edited at: 11th Nov 2014 05:27
Making an Inventory - Part 2: Controller

For those that haven't seen it yet, I have edited my previous Part 1 post to include a shorter text based version of the original video session, if you haven't seen it, and haven't watched the video, you may want to look it over. I think I generally prefer the text as a platform for sharing code and the coding process, and so this update will follow suit.

So, now it is time to link up our visual elements with code so that it becomes a usable game system. The first thing we need to do is to be able to toggle its display. To control this, we want to bind the panel to a keyboard key which will callback to our toggling function when pressed.

First, let's make the function which will do the work so we have its name to reference against:



We don't need this to do anything fancy, just show it if the panel is hidden, or hide it if it is showing. Any GUI element event callback will take the calling element's id as a parameter, this way, we can work directly with the element without a need to find a reference to it. Handling of timing to prevent a keypress from sending hundreds of 'presses' per second while held down is done in the core UI framework module itself and is not needed here in a sub-module controller.

Next, we need to enable events on this element, bind it to the 'I' key, and reference our new function in the element's definition. These are element properties rather than style properties, and we will place them just below the holdMouseFocus flag:



Let's go ahead and compile + run to verify that it is working. We should be able to open and close it smoothly by pressing the 'I' key...

...Looks good, next we need to be able to fill it with items that we take from the world. If you remember from the world interactables update, I am currently moving an item directly from the world to an equipped state, now we will modify the Take action to move the item to inventory instead of to active equipment. A Take action is triggered by a player control, rather than a user interface event, and so reference to an onEvent callback function is stored with the item/entity in the database. Different items / interactable entities may need to perform different actions for the same type of event, and so while most items will just go to inventory, we don't necessarily want to hard code that into the take action itself. It should be more abstracted and let the specific item being taken direct the event process as to what more specific function should be called to carry out the details of the action. That being said, all take actions will involve both an entity being taken and an entity doing the taking (the character under the player's control referenced with the global identifier MY_CHAR). Any callback function we use for this action should take these as parameters.

So, the specific action we are interested in right now, is to put an item into inventory. Inventory and equipped items data is essentially character data, particularly as each character will have its own inventory and equipment set. This makes the character module a pretty good choice for our callback funtion. While the gui inventory panel is the best way for the player to manage the inventory data, the data itself is only used by the gui, it is not really part of the gui iteself, and there could be times where we want the system to place something in inventory directly, outside of any user action.



Now in characters, we need to add a new typed array to hold our active inventory data, and make a function to add items to this array which we will use as our onTake callback for an interactable dagger entity. Once we eventually add character persistance, this array will be imported/exported from the database on load/save games.



One of the more useful bits of data being handled here is the base portion of an entity's file string. we will be using this quite a bit and dont need to query it again and again, better to just store it in a UDT for future use. This base string is used to build references to related assests like a .x model file or a .png texture, or a .anim animation keyset for that model, a collision mesh etc.

From the fileBase of say "media/equipment/dagger" you can get access to the following related files by concatenating expected chunks to the base:

fileBase + ".x" = "media/equipment/dagger.x"
fileBase + "_diff.png" = "media/equipment/dagger_diff.png"
fileBase + "_spec.png" = "media/equipment/dagger_spec.png"
fileBase + "_norm.png" = "media/equipment/dagger_norm.png"

and so on. We can then clip out an itemBase of "dagger" with a bit of string handling, which can then give access to the item's gui icon representations:

"media/ui/icon-" + itemBase + "-lg.png"
"media/ui/icon-" + itemBase + "-sm.png"

Note the TODO: in the code above, I like leaving a standardized tag like this anywhere I need to go back and work on further at a later date because it is easy to just run a search on that tag to jump around the code. For adding an item to inventory, we will probably want to create and drop an actual icon element on the slot, for now to test that everything is working so far, we will just change the slot's background to the icon image directly. I don't know, maybe we will just leave this as is and create temporary elements as needed on pick up for drag and drop.

Next a quick change to the item's database entry to point it's take action from chars_equipItem() to our new chars_addToInventory() function.

Time to compile... we should be able to open an inventory panel to see all empty slots, close it, navigate over to the dagger object, pick it up, then open the inventory and see the first slot filled with the dagger's icon.

Let's give the user some feedback on mouseover, we can make use of the same control code that our menu buttons use for this same sort of push/pop feedback.

We need to add a couple of property definitions to our element: name, enableEvents, onMouseIn, and onMouseOut. We will do this in the controlling code, instead of in the element's base view definition, once an item is added to a slot. We don't need empty slots to do anything. For now we will stick this just below where we set the new background image in the chars_addToInventory function.



The name property is being used here much like fileBase and itemBase previously. From this, we can derive a 'pop' state and a 'push' state image file. Compile and run, and we can see that the item reacts to the mouse:



*side note: you may notice the new and improved hair The texture was completely redone, and the geometry was cleaned up a bit to remove some of the more awkward bits. This also reduced the poly count slightly so win-win. I'm faking the anisotropic specular highlights in the diffuse and spec maps. This is a poor substitute for a true comb map shader, but it's still a huge improvement over the previous hair I think.

Alright, we're a bit more than halfway there! We can now use a Take action on an interactable object, remove it from the world and add it to our inventory. I'm short on time today, so I will stop here for now.

Part 3 will implement drag and drop functionality, moving the private gui stuff back into the gui code behind public drag&drop interface functions.

This will then allow us to move the item from general inventory bag space to equip it as active equipment through our existing chars_equipItem() function which was previously being used directly by the Take action.
We will also add in the ability to move items around in inventory space, all with appropriate checks against a particular item being allowable to drop in a particular slot.

Attachments

Login to view attachments
Chris Tate
DBPro Master
15
Years of Service
User Offline
Joined: 29th Aug 2008
Location: London, England
Posted: 18th Oct 2014 02:36
That looks neat; looking forward to seeing it animate.

So, when playing will we need to look at the attributes of the items in the inventory, shown by the mouse cursor, inside of another window/panel or will the item attributes be hidden?

Ortu
DBPro Master
16
Years of Service
User Offline
Joined: 21st Nov 2007
Location: Austin, TX
Posted: 18th Oct 2014 05:13
Oh right sorry, current plan is to show relevant info like name, description, and stats as a popup tool tip on mouse over.

There are a couple of ways to handle this: I could modify the current button push/pop/unpop functions to check the elements type, and change the type from general div to more specific button / icon, an icon can then handle the update and display of tool tip in addition to the element styling feedback, or I could separate icons to use new push/pop/unpop functions. The first option has the least redundant code so I'll probably go with that.

Ortu
DBPro Master
16
Years of Service
User Offline
Joined: 21st Nov 2007
Location: Austin, TX
Posted: 22nd Oct 2014 00:50 Edited at: 11th Nov 2014 05:27
Making an Inventory - Part 3

Ok folks, time to wrap this up. The plan for today is to implement drag and drop capabilities, allowing us to move an item from pack space to equipped space. We will also want to display a tool tip panel on item hover to show details about the item.

The first thing I need to do is a bit of clean up. The popButton function needs to be made more flexible to support handling of different types of elements. We need to move these out of the menu document and into the common elements doc, which is a collection of general things which are commonly used by many other documents.

and so this:



becomes this:



Change callback references to these functions as appropriate. Would not hurt to go ahead and compile + run to verify that nothing is still trying to call the old non-existant functions.

Next, remember that private gui stuff that was sort of hacked into the character module to get things working in part 2? Let's move that back into the gui module and access it through a proper public function.



becomes:



Yes, we still need to rename gui_Elements to _gui_Elements, but that is a fairly sweeping change throughout many files and is not something I will tackle today. I've also left a stub for Ability icons, obviously items won't be the only type of icon we may want to create in the future. By setting the function up as a switch statement, it becomes easily extensible for future needs. What other sorts of things may need an interactable icon? Effects perhaps. Party member selection? Who knows! Whatever we may come across can now just slide right in.

So, let's do a quick compile and check that nothing was broken in the restructuring. We should basically see that everything still works just as it did at the end of part 2: open inventory with blank slots, pickup the dagger, see slot 1 filled with the dagger's icon. dagger icon should give visual feedback on mouse hover.

Good, good. Next, let's turn our attention to the onPress event. When we click and hold an icon, we will want to pick it up and bind it's position to the mouse position. Now getting the position to continually update with the mouse position isn't tricky in and of itself, but getting it to do so within the context of the framework's gui update is a bit more so. There is currently no handling for this sort of positioning and we will need to expand the core ui module for this. As with many thing, there are any number of ways to do this, from assigning a specialized class or converting the element's type, to adding a new element property, or a new UDT, to modifying an existing property with new functionality.

I think I am going to go with a combination of a new UDT and modifying the existing enableEvents property, there are a couple of reasons for this. This property is already of type byte giving us allowable values 0-255 of which I am currently using only 0-2. Additionally, an icon's enableEvent value is currently 1 which means that it will react to an assigned hotkey press/release and to mouse events such as onMouseIn, onMouseOut, onPress, onRelease and the like. Inventory slots are currently event type 0 which means, not enabled. Under the current types, we would need to make slots type 1, the same as the icons, and which is always active. Left as is, this could cause problems for drag and drop as in order to pickup or drop an icon, the mouse will have to be over 2 event enabled elements at the same time: the icon and the drop socket. We are already going to have to add some sort of event ordering or layering to handle this.

So, to start off with, let's set socket elements which are capable of receiving a dropped element as enableEvents type 3. These sockets should only become active while an element is being dragged. Further, lets bind the actively dragging element to a new global and type as we will need some specialized data handling for this action.



Next, we need to go back to our onPress callback and capture some data on icon pickup.



Now, when resolving the element's final position, we need to use the mouse position instead of the style position if the current update element matches the dragElement while drag isActive = TRUE



Ok, I realize that a lot of code is getting snipped out when dealing with user_interface.dba, I suppose this may cause things to seem a little disjointed perhaps, but really it is not needed to know the exact manner in which final screen coordinate values are being resolved, only that they have been, as far as adding this drag and drop functionality is concerned. The core UI code is quite long for one thing, and is not cleaned up or polished for presentation. It is a bit beyond the scope of these Inventory sessions. Hopefully, the overall concept of what is being done is clear enough. If not, I'm happy to answer questions or give more specific details.

Anyway, we are now at a point where we should be able to click and drag an icon around the screen, if we drop it, it should revert back to its original location.

Next, as we drag over droppable sockets, we need to check if the icon is allowed to drop on this socket, and give some feed back to the user about this. This will be done in the onMouseIn event for the socket in question, which specifically is a callback to the function _gui_hoverElement(e)

For this, we are going to need to know a bit more about the type of socket the mouse is over. We can get this by parsing the element's id which is already in the form "inventory-slot0", "inventory-equipped-body" and so on. So our hoverElement function will now look like this:



We also need to know more about the type of item the icon represents. This is a good time to go ahead and query up all the info we need for the tool tip display since we are going to be querying the database anyways. We already have a primary key reference stored as chars_Inventories().itemID for fast querying.

So, continue to expand the hoverElement function, but this time we will work with icons instead of sockets:



ah ha! we've got a problem here don't we. As our inventory array currently stands, all characters' inventories are mixed together. we can't easily iterate through it to retrieve our itemID as our hover function doesnt really know anything about the item that the icon is representing. As usual, Matrix1 provides a helpful method. Free lists! So we need to take a quick detour and rework a bit of the character module.

First, setup a new free list to handle our bag slots, and store a reference to it. We can stick it in to our handles data which stores references to various resource data. Next, block out the slots that the free list will handle, then modify the chars_addToInventory() function.



Another nice thing about this refactoring, is that we will now be able to move items around in bag space with gaps in between. You could now put something in slots 2, 7, and 9 where before this would cause problems when adding a new item.

Next, let's define our tool tip panel, this can be used to store and display our item details. For now, nothing fancy, we will just dump everything into a basic list. We can style it and art it up later.



Now we can try the hoverElement modification again. Let's also take this opportunity to move the more game-specific code back into guiDoc_gameHUD and leave this function as a more general and abstract helper, as this 'common' elements controller is meant to be non-specific and usable with little to no modification from project to project.



quick note on 'gui_Elements(ttPanel).selectedIndex = tWeaponID': selectedIndex was intended for use with drop down select boxes, I am re-purposing it here because it is both a suitable data type and a suitable name for the data I am storing, and this lets me keep the data I need without having to add any additional properties or handling. In a loose and flexible system like this, context is key, but you can get yourself in trouble if you lose track of that context...

Wow, so I'll admit this has grown more complex than I had initially *hoped*, but really no surprise there. We are in the home stretch now though. We can pick up an item, see it in inventory, mouse over it to get selection feedback and a tool tip with info about the item. We can click and hold to begin dragging and see the icon and tooltip follow the cursor around the screen. If we release our hold, the icon will revert back to its initial socket location, and when dragging it over other sockets, we determine and give visual feedback as to whether the icon is allowed to drop on this location. whew!

Just a few things left to do: drop the icon, move the item around within invnetory and equipped backend data, and update/hide the gui elements as needed. Lastly, if the item was equipped, we need to restore the 3d object to world space and bind it to the character object. Most of this will get triggered during the onRelease event of the dragging icon.

I will leave you for today with one little addition to unhoverElement to clear the tooltip for non-dragging mouse over icons. Yes, I can see that there will be a problem with the tool tip when dragging one icon over another, and each icon tries to use the tooltip panel to display info. That's why I set up 2 tooltip panels: 'active' and 'compare' in the xml. I'll add handling for this later, it's a pretty straightforward check against the active drag data and it's a non-issue until we have more than one icon in inventory anyway.





Attachments

Login to view attachments
Ortu
DBPro Master
16
Years of Service
User Offline
Joined: 21st Nov 2007
Location: Austin, TX
Posted: 29th Oct 2014 04:40 Edited at: 29th Oct 2014 04:46
Making an Inventory - Part 4

Hmm... where were we? Right, time to finish up the drop. So we are going to trigger a drop during the dragging icon's onRelease event. One problem with this is that we don't have any reference available to the socket that the icon is over when released. We could trigger on a socket's release event, but then we run into problems when releasing the icon when it is not over a socket. I'm going to add a 'target' property to the UI.dragElement object which can be updated on a socket's onMouseIn/Out events. Lets go ahead and verify that we have the data we need by popping an alert on the icon's release, basically where we will end up putting the drop code.



Ok, we get both of the needed IDs. Next, I noticed that we get a socket not valid against the original socket the icon is drug from. This should display as valid. Of course this is caused by simply checking if the slot is empty, which the home slot is not. We just need to add an additional check to see if the socket is the icon's current socket via its parent element id



Now we can check that the target is valid and execute the actual drop.



We need a way to translate the target socket gui element into the backend target inventory data location. We are already parsing this out in the call to _gui_gameHUD_getDropAllowed() so it doesn't make much sense to do it all over again immediately on a valid return, plus we want to keep this sort of game specific stuff out of common.dba so we can either create a near duplicate function such as _gui_gameHUD_dropIcon(target) or we can convert _gui_gameHUD_getDropAllowed(target) into a multipurpose _gui_gameHUD_tryDropIcon(target, mode) where mode can specify if we want to check validity only or check and execute. I try to avoid duplicating repetitive blocks of code when possible, so modifying the existing function sounds like a plan.



And boom we can now move the item from pack space to the right hand, equipping the model back into the world. This can be used as a template to fill in the move code for the other equip slot locations. One last bit to cover for today and this series will be wrapped up. There is certainly a lot of clean up and in depth testing / bug hunting to do, but the broader process is fully covered I think.

Now that we can equip an item, we need to be able to unequip it, and as a bonus, this bit will also let us move items around in packspace, as an unequip involves moving an item into a new packslot similar to moving from one packslot to another.

I realize that I've sort of used the terms 'slot' and 'socket' somewhat interchangeably, the intention for these is that a slot refers to a location within the inventory data as managed by the freelist, while a socket is a gui element which accepts a droppable element, typically an icon. I probably need to do some clean up in the code to maintain consistency in usage. You can also see that it is a constant struggle and effort to keep components specific to a given game out of the more general framework components, and to arbitrarily assign components to a specific module when it touches on several. The are no hard and fast rules when the structure is entirely by convention in a non-OOP language environment, but the more consistent you can be with yourself, the easier the code will be to manage. It's worth the effort.

Anyway, here is the last bit:



Lookin', lookin', lookin' good. We can pick an item up, move it around in inventory, equip it, unequip it, get tooltip info on it, it will react to the mouse with visual feedback and performs some determination of drop allowed by item type. One 'last' thing (there's always some -other- last thing that inevitably pops up) that has been bothering me though, is that dragging the larger sized icon around feels clunky. particularly over the smaller equip slots. Let's make it so that it changes the icon to the small form on pick up for usability. UX is just as important as functionality when it comes to UI.

Now when we pick an item up, we are storing the mouse offset coordinates from the icon's base position. This lets us keep the mouse at the same position within the element while dragging so that it doesnt snap to the corner or center or wherever. We will need to modify these offsets to account for the smaller size, fortunately, the small icon is exactly half the size of the large so we can just reduce the offsets by half as well and everything should stay proportionate.



And so, I will leave you with a quick video of the results in action:



Ortu
DBPro Master
16
Years of Service
User Offline
Joined: 21st Nov 2007
Location: Austin, TX
Posted: 30th Oct 2014 04:32 Edited at: 30th Oct 2014 04:35
Something a little different today folks, time for some lore.

In earlier days, there was a growing nation called Pharos. From among the people of this nation, there lived a philosopher who, with great wisdom and insight, discovered a method for gathering and manipulating the hidden energies of the world.

He called this method Alchemy.

From this discovery, he determined the following four principles upon which all further alchemical study within Pharos was based:

Manifestation – The creation of a new physical thing from raw unformed energy.

Dissolution – The destruction of a physical thing, returning the energy which shaped it back into an unformed state.

Transmutation – The alteration of the energy which shapes and defines a thing in such a way that it transforms into a different thing.

Augmentation – The transference of energy from one thing to another thing, combining the two into one.

Many pharosians sought this man, Erastaces, to learn the ways of Alchemy and he freely taught anyone with the ability to learn. While Erastaces believed that his techniques should be available for the betterment of all, most alchemists jealously guarded their secrets, masters sharing knowledge only with trusted students. As larger cabals began to form and take control over the usage and teaching of alchemy, Erastaces quickly found himself, and those of his students whom shared his views, ostracized and later imprisoned to prevent their unauthorized sharing of 'secrets' with the uninitiated, particularly foreigners. Pharosians were very nationalistic people to start with and jealously guarded anything considered to be within their realm, material or otherwise.

For decades, alchemy remained a secretive thing, its practitioners working alone or with a few others, each of them aligned loosely with one or another of the larger ruling cabals, which themselves were little more than distrustful collections of masters which would occasionally meet to settle various issues.

Then much like the discovery of alchemy itself, things suddenly changed when an ambitious young alchemist name Diacles developed a tool which could assist with and enhance the act of alchemy, empowering virtually anyone to use its power with little need for talent or training. Though Erastaces had died in prison long before, Diacles named this tool a "Philosopher's Stone" after the father of alchemy, and in honor of Erastaces' belief that the benefits of alchemy should be widespread and freely available.

This tool was a smooth, crystalline orb, of a material that even Diacles himself could not determine. The size varied from orb to orb, but was generally no smaller than two inches diameter and no larger than four. The larger the orb, the more powerful it was, and the more power it could contain. Having learned from the history of Erastaces, Diacles quietly gathered support from many corners before revealing and distributing his orbs. By the time they learned of them, the cabals could do little against the unified interests of the influential merchant guilds and privileged nobility, both of which could taste the wealth and power to be attained through Diacles' orbs.

As the use of alchemy via orbs became widespread across Pharos, the nation quickly advanced well beyond its neighboring peoples. Civilization, wealth, and power flourished within its borders, while the western barbarians and southern nomads could only look upon Pharos with equal measures of envy and fear. The power of the cabals was undermined, and their controlling grip upon alchemy was broken.

A Golden Age had begun.

Ortu
DBPro Master
16
Years of Service
User Offline
Joined: 21st Nov 2007
Location: Austin, TX
Posted: 4th Nov 2014 22:35
OK, I know everyone is probably bored and sick of user interface for a while, I'm getting tired of talking about it, so I will make this Design Discussion brief and then we can all move on to something new. This is more of a broad overview of UI in general rather than my or any other specific implementation of them.

Part 7 – User Interface

My thoughts:

I feel that some input controls are better suited to the user interface module rather than to the player controls module, but things can get a bit blurry here. Why not have all user controls in the same place? At first it may seem simpler and more logical, however I think it's important to make a distinction between a 'game control' and a 'game-play control'. The key difference being that game-play controls are highly specialized to a specific game and directly affect the character and its actions or directly affects the user's interaction with the character such as with the camera.

A game control is more general, and includes things like menu commands and hotkeys, which are completely reliant upon and integrated with the GUI. To me, these controls more logically fit with that which they directly affect: the state of the GUI, just as player controls more logically fit with a module that directly affects the character state.

While both modules take input from the mouse and keyboard, they are very different systems, which do very different things with those inputs, and so warrant separation into different modules.

When under the scope of the GUI, you often will want to exclude character control events from even being processed. You don't want to make an attack if you are just clicking a button in a menu, or a slot on an inventory panel. You don't want to move every time you type something that includes a letter 'w, a, s, or d' and so on.

Much of the time, you will want a clear distinction between controls being under the scope of the GUI or under the scope of game-play, or under some shared blend of the two, (say giving the keyboard game-play scope while the mouse has GUI scope in the case of allowing a player to move with wasd while clicking around in an inventory or skills panel) and pass the captured user input to each module accordingly.

Granted, this could still be done in a single module, and it really comes down to how each individual tends to associate and group things, and the line of distinction between the two can be pretty arbitrary. This is just where I've chosen to set it, and of course this should all be transparent to the user. When they go to the options and settings menu to set up their controls and key assignments, they get a single unified list grouped by categories regardless of the specific module that controls actually get mapped to and handled by.

So, all of that aside, the biggest issue facing the module is how to go about implementing and handling the GUI elements themselves along with their content. Coming from a strong background in web development, I immediately turned my attention in that direction.

The results:

Well, you've seen it yourself in action across the 4 part making of the inventory, found above.

Progress:

As the complexity of this system grew, it quickly became apparent that this could be an entire project unto itself. It is not fully complete, but it is functional with the core features in place.

Available styling generally includes most of the CSS2 specifications with a few omissions and additions.

Element positioning, sizing and layout is mostly complete, but still to do is the handling of overflow, stretching, wrapping, and scrolling based on inner content.

Currently, elements can only support a single class assignment at any given time. I will likely expand support for multiple classes eventually but it is low priority for now.

The biggest costs to performance are frequent text styling changes (switching between fonts, sizes, and colors) and special image handling (clipping, scaling, and tiling). Both of these could likely be optimized through plugins, but for now, I simply keep their use to a minimum.

Ortu
DBPro Master
16
Years of Service
User Offline
Joined: 21st Nov 2007
Location: Austin, TX
Posted: 14th Nov 2014 23:28 Edited at: 3rd Dec 2014 07:55
Ah ha, didn't think there would be an update this week? I thought about skipping it, but keeping to at least one per week keeps me on target and productive. So what is new since the last update? Code wise, I've been filling in some of the stubs left behind during the inventory sessions, and I also tracked down and fixed a bug which has been annoying me for some time: accessories bound to the character were visually out of sync with the character, this was more noticeable as the framerates got lower and can be seen in previous videos where the hair would lift up off the head or sink down into it. It turns out accessories were one update loop behind the character in terms of the animation keyframe being set. These accessories were being updated after the character data (location, rotation, animation sequence etc) update, but before the animation handler updated the character's current frame, so it was effectively matching against the character's previous frame. So timing has been fixed and everything remains in sync with no wierd clipping issues even down at ~14 fps on my 'worst case scenario' test machine, an old laptop running windows XP and crappy integrated graphics.

I also spent some time working on another bug that has been frustrating me for a while in which Advanced Lighting renders with a vertical band of graphical error on the right side of the window when running in various resolutions. This band appears at different resolutions on different displays, can appear on both supported display resolutions and un-supported resolutions, some un-supported resolutions display just fine. The issue is likely to do with my integration of AL into my project, as running a clean version of Evolved's demos seem to work ok at the same resolutions that show errors in the project, and I'm pretty sure that I remember earlier versions of my project were also able to run at some of the resolutions that now have errors. The problem is that I'm not really sure when it started, nor what change exactly may have caused it. I've been going back through the revisions looking to pin it down, but it's pretty much as tedious as it sounds, so I am only poking at it here and there... Not too worried, I'll work it out sooner or later.

Next up, I've started working on some of the interior furnishings for the house. I've decided to close off the first two rooms behind locked doors and window shutters to keep the amount of required art assets to something manageable. I will focus on Carliet's bedroom, the main living quarters, and the exterior. So, in the bedroom, the bed will be the 'hero' piece, featuring the most detail in terms of geometry and polycount. Basic furniture like wardrobe, chest, and chair will be lower detail with a writing table and a bookshelf in mid-range details to help transition between them. This serves a couple of purposes: first, cutting detail where you can obviously cuts polycounts and helps performance, but it also speeds production of the assets themselves. The lower the detail, the faster and easier it is to make. But it's not all about making things easier for myself, when there is variation in the 'value' of detail, it helps make the enviroment less 'noisy' and provides the eyes both places of interest and places of rest. This is really just a scaling up of the same concepts applied to the design of individual models. Texture detail and quality should remain fairly consistent regardless of physical detail to help tie everything together. Difference in detail, texture, or style should never be so great that anything feels out of place or that it doesn't belong in the scene.

The wardrobe just needs to be unwrapped and textured, the bed is just blocked in and still needs considerably more work on the high-poly, then retopo, bake, and the works.



Lastly, I read back over some of the earlier design discussions, and I realized that I skimped on Part 3 – Character Control. While everything in that part is true, I did not go into the details behind the implementation of those controls as I should have. You can probably consider this Part 3b, but I like increasing the list of roman numerals in the OP, so I’m just going to call it 8.


Part 8 – Character State

When starting out with character coding, or when you just want to get something up and running without much planning, the easiest and fastest way to get a character to do something is to have it respond directly to user input. Press the upkey, and the character moves forward, something like:

if upkey()
move object forward 1, 10
endif

if keystate(30) = 1
yrotate object 1, 5
endif

This is fine for a short demo of something, or a simple single player game, but as the game grows more complex, or if it plans to implement online or networked multiplayer it quickly runs into a few problems. Chiefly, it lacks any representation of state. None of the code which comes after the action has any real awareness of what action was taken unless you build a lot of repetitive code within deeply nested if blocks.

In multiplayer, this means that you have no way to reproduce the same action on the other players’ machines: you have no way to tell them what action to reproduce! You can send them the final result of a new position/rotation etc, but this makes it hard to account for ping time, lag, and packet processing times. It also provides an easy way to cheat if users send an altered result value. It implies trust in the data being sent and received, and history shows us to never implicitly trust a client.

Even in single player, it can cause complications for controlling animations, determining if an action is allowed in combination with other actions, and probably other things besides. The biggest issue here is that anything which relies upon an action being taken, has to be nested within the detection of that action.

If upkey()
Do all upkey stuff here
endif

regardless of whether the actions being taken should belong to an animation handler, a combat module, a physics handler, collision handler and so on. Because after this block passes, nothing is remembering that it happened. So there needs to be a means of remembering state for later use, which will enable us to break the results of an action down into more appropriate modules.

We could do something like:

`control module:
If upkey()
Do all upkey stuff here
movedForward = 1
endif

`multiplayer module:
If movedForward
Send update to other players
endif

But really, this is only part of the way towards modularization and separation of concerns. Updates to character data (location, rotation, speed etc) should be handled by the character module, updates to the animation frame should be handled by the animation module, physics and collision checks and updates should be handled by the physics module and so on. Each component in a complex system should have its own specific set of responsibilities, and should be left to perform those responsibilities internally, within the component, with limited reliance on external modules. The more any given module becomes tangled with other modules, the less it is able to be used without those other dependant modules and the less abstract and re-usable the codebase becomes.

Thus, the player input and controls component should simply be responsible for detecting an input and then notifying the other relevant components about that input, and should not really be taking action on the input directly.

`control module:
If upkey()
movedForward = 1
endif

`physics module
If movedForward = 1
If get collision -> move allowed? <> 1
movedForward = 0
endif
endif

`character module:
If movedForward = 1
Update position and rotation etc
Endif

`multiplayer module
If movedForward = 1
Send update to other players
endif

Is this a more complicated way to get the same result? Sure is! But it is also the difference between manageable module files of a couple hundred lines vs a giant controller file of thousands of lines, it also lets us abstract the controller away from the specific game and makes it largely reusable across multiple projects. Every project just about will need to detect directional movement, what any given game actually does with that movement (and how) can vary greatly from game to game.

Attachments

Login to view attachments
Dimis
12
Years of Service
User Offline
Joined: 12th Jun 2011
Location: Athens, Hellas
Posted: 15th Nov 2014 19:49
maybe post a screenshot of that AL problem? perhaps someone else had the same issue before. i remember having some strange white outlines around me models, some kind of resolution mismatch between the application window the AL system, it was nothing but i guess this is a different problem.

Ortu
DBPro Master
16
Years of Service
User Offline
Joined: 21st Nov 2007
Location: Austin, TX
Posted: 17th Nov 2014 05:49 Edited at: 17th Nov 2014 06:07
Quote: "maybe post a screenshot of that AL problem? perhaps someone else had the same issue before. i remember having some strange white outlines around me models, some kind of resolution mismatch between the application window the AL system, it was nothing but i guess this is a different problem."


Fair enough, here's some more detail:

Testing results from the following hardware:

AMD Radeon HD6870 on display with max 1920 x 1080 (desktop)
AMD FirePro ? on display with max 1366 x 768 (laptop, integrated)
AMD FirePro ? on display with max 1920 x 1200 (same laptop + external monitor)

The following resolutions appear to work cleanly on any setup which supports the resolution:

800 x 600 (4:3)
1024 x 768 (4:3)
1280 x 1024 (5:4)
1680 x 1050 (8:5)
1920 x 1080 (16:9)
1920 x 1200 (8:5)

The following resolutions which are supported by a given display, render the 3d scene with either a black bar on the desktop PC or a scrambled mess of colored pixels bar of the same size and location as the black one on the laptop.

1152 x 648 (16:9)
1152 x 864 (4:3)
1280 x 720 (16:9)
1280 x 800 (8:5)
1366 x 768 (16:9)

1440 x 1080 which is not supported by any of the displays actually works fine on the 1920 x 1200 monitor.

So, when taking some screenshots for this post, I realized something interesting, the graphical error starts at the same pixel x on any resolution within a given aspect ratio, and this is always just over 1000 pixels. resolution width seems to be the only factor, height seems to have no effect.



This only affects the 3d render, 2d UI elements paste over this without issue, and these resolutions work without issue on the AL demos, there has to be something somewhere that I've changed or missed, but I haven't found it yet.

Attachments

Login to view attachments
Dimis
12
Years of Service
User Offline
Joined: 12th Jun 2011
Location: Athens, Hellas
Posted: 17th Nov 2014 14:42
strange problem, i have not come across something like that. but again i have not tested AL in so many resolutions.

Chris Tate
DBPro Master
15
Years of Service
User Offline
Joined: 29th Aug 2008
Location: London, England
Posted: 23rd Nov 2014 20:40
Have you managed to rectify the problem with the display per resolution?

Ortu
DBPro Master
16
Years of Service
User Offline
Joined: 21st Nov 2007
Location: Austin, TX
Posted: 24th Nov 2014 18:38 Edited at: 3rd Dec 2014 08:00
@Chris Tate: no, I've set that problem on the back burner for now. I dislike getting bogged down on any one thing for long and prefer to maintain forward progress as long as the issue isn't an absolute show stopper.

Things have been quite busy with work and family and so I have not had a lot of time this past week for game dev. The pace of updates in general will likely slow down as we approach and get through the coming holidays as December is always a very busy time for me.

That is not to say that progress has stopped! I have begun working on implementing the combat system. As with any RPG / Adventure game, combat is one of the key, defining, systems and it is important to get it right. This will be a major milestone once it is up and running. I have been working on the concept for quite a while, revising and adapting it, and while it seems fun and engaging in my head, the design is far from final until it can be experienced and tested in game.

The first component of combat which I will be talking about is the application of damage resulting from an un-defended attack. This encompasses a complex interaction between weapon, armor, and character stats.


Part 9 – Melee Combat Damage

My Thoughts:

Forever and a day now, weapons in RPGs have been given an arbitrary and mostly level based "damage" rating which often combined with an equally arbitrary "speed" rating give a dps value, and this is used as the primary component to calculate damage dealt. The problem with this is that weapons don't actually have physical properties of level, damage or speed.

Realistically, damage is a result of applied force. Force is a result of mass and velocity. A weapon is an inert thing and has no inherent speed in and of itself; speed is given to it by the user. Damage also is a result, not a component factor, and it's kind of silly to have two swords, the exact same physically in size, shape, weight, etc but one of them does ten times more damage because it is a higher "level" or more "rare". While material and quality should be factors, most of the advancement in a weapon's effectiveness should really be on the side of the user. A master swordsman should be nearly as deadly with bronze as with steel, and a raw recruit will be equally poor with either.

Now the typical system works well enough to simulate combat damage for games, but why stop there when we can make it more interesting than just picking numbers to make this weapon do more damage than that weapon simply because it "should". Armor can also be made more interesting than "plate x prevents y damage of type z". Some games don't even really bother to distinguish between damage types, and often when they do, it is through character based resistance stats rather than armor based resistance properties.

If attacking shifts its focus from damage and instead looks at force, armor can now take on properties of resistance as well as absorption. If a piece of armor is able to withstand the force of a blow, less damage would be done than if it is breached. A cutting slash that would cause flesh to bleed would be converted to less dire impact damage. Now that armor has resistance properties, weapons which were historically designed to penetrate armor, can gain such properties to set them apart from other weapons designed for use on flesh. The whole interaction between weapons, armor, and damage types gains depth and interest.

The Results:

So how do we go about calculating force? I can't even count the number of formulas, algorithms, and methods I've tried and discarded. Using actual physics math required too many component variables and calculations. It quickly got bogged down into lengthy and unnecessary details.

So I began iterating the process, simplifying and trimming out factors and components until what we are left with is again rather arbitrary but now has its roots and essence in physical properties rather than levels.

Weapons are given comparative ratings (think of the Mohs hardness scale) on mass, length, and balance, which together will result in an applied force value. Heavier weapons are modified further by the user's strength, while lighter weapons are modified by the user's agility. The manner in which a weapon is used will give further modification. Is it swung or is it thrust? Using one hand or both? Is the weapon's mass too great to be used effectively with only one hand? Is the weapon designed for puncturing armor? Is it designed to break down and destroy armor/shield condition? Many of these factors also get applied to calculating parry success as well as readiness and recovery time after an attack.

Armor is rated for absorption, resistance, and durability against each physical damage type (slashing, piercing, bludgeoning) individually. How much force can it resist of the weapon's damage type before being penetrated? How much force will it absorb? These base factors are then modified by the armor's current condition, which wears down when damaged until it is first breached, and then eventually destroyed. Padded leathers may have good absorption, but poor resistance and durability. Chainmail has much better durability, but poor absorption. It will certainly last and remain effective longer but may not always provide "better" protection.

The important thing to understand is that this is mostly intended to be an active, player-skill based combat, rather than a character-skill level progression based combat with a bunch of passive chance-based defense systems. Active blocking, parry, and evasions will form the core of your survivability, with armor being the last line of defense meant mostly to turn minor, stray blows and hopefully keep a lethal blow or two from crippling you outright.

Armor cannot and should not turn you into an impervious tank rolling across the field hardly touched by even the heaviest of weapons. It cannot and should not hold up indefinitely against a direct and sustained assault. There is a reason why shields have historically been so vitally important, why fencing masters work endlessly to perfect the art of the parry. There is even something to be said for the theatrical "near miss" as you fling yourself out of the way of a crushing blow. If your armor is taking the majority of the hits against you, you're doing it wrong.

Now of course a dagger isn't going to breach and kill someone wearing plate mail in a couple of hits, in fact the way the system of force, resistance, and durability works naturally makes a dagger almost useless against plate, which it should be, however a spiked warhammer swung with both hands is a very different story. If you weaken the armor's condition with a hit or two of the hammer side, then flip it and penetrate with the spiked side, you can reasonably expect to take down a plate wearer rather quickly. This is what such a weapon was designed for and this system reflects and enables that.

Progress:

The calculation functions are fully implemented and return damage values against both health and equipment condition.

Property ratings have been defined, compared and tested for perhaps a dozen weapon types and half a dozen armor types. This list is of course extensible so new items and types of items can be added as needed, though I think it is fairly comprehensive as is and covers the majority of base equipment types. Additions will be mostly visual and cultural variations of the same general types.

You can get the source, detailed info, and a small sample project to play around with on github:

https://github.com/Ortu-/damage-calculator

Chris Tate
DBPro Master
15
Years of Service
User Offline
Joined: 29th Aug 2008
Location: London, England
Posted: 24th Nov 2014 20:25 Edited at: 24th Nov 2014 20:27
Interesting points.

It seems that the game will be based on more realistic combat systems; I look forward to seeing how the combat turns out. There are many mindless games out there, thus there is plenty of room for mindful gaming such for everyone. Most guys I have known over the years who play RPGs, play them for different reasons; it makes it quite a challenge to please them all.

Your screen rendering problem is a real bugger of a clipping disaster. I can only see that the character is not central in view on the first screenshot, the others are covered by it. I could only tell that it is a clipping problem because the character is not in the middle of the window. No doubt you have searched for the figure of '1000' in all of your text based files; that figure has to come from somewhere.

Ortu
DBPro Master
16
Years of Service
User Offline
Joined: 21st Nov 2007
Location: Austin, TX
Posted: 24th Nov 2014 20:44 Edited at: 24th Nov 2014 20:52
The character is centered in the window as it should be, which causes it to appear offset within the area that renders correctly. The position of the error varies between aspect ratios, something like 1007 on any 8:5 resolution, but say 1013 on any 16:9 resolution

Here is a shot from the laptop with center line and the scrambled graphics version of the error instead of the simple black that the desktop gives.

You can see that the scene is centered to the window and 2d graphics paste over it as they should. When running the AL debugging update, each of the component renders exhibit the same vertical bar



Attachments

Login to view attachments
Chris Tate
DBPro Master
15
Years of Service
User Offline
Joined: 29th Aug 2008
Location: London, England
Posted: 24th Nov 2014 21:55
I see.

Well, the cause will be narrowed down and found sooner or later; no doubt it is to do with one of the render targets or a render target based sub component of Evolved's rendering pipeline. Good luck with it when you get round to it.

Ortu
DBPro Master
16
Years of Service
User Offline
Joined: 21st Nov 2007
Location: Austin, TX
Posted: 25th Nov 2014 00:00 Edited at: 3rd Dec 2014 07:38
Hmm the plot thickens. I was getting the approx 1000 pixels measurement by estimating with a box selection in the screen shots. Now using the actual mouse coords provided in game it always starts at 1023 no matter the aspect ratio. Considering 0-1023 = 1024, a common ^2 number of significance, it does not feel to be some random coincidence that this is where it happens.

I would think it was some sort of memory issue, except that some larger resolutions work just fine like 1920 x 1080, which certainly uses more than 1280 x 720

edit: OKAY! I have found *what* is causing it though not exactly *why*

it is the shadow map size parameter of directional light create when set to 1024 I get the error of I drop it to 512 every thing works normally on all resolutions. now at least I have a starting point to go diving through the AL and shader code. to see why some can handle 1024 shadow maps and others can't, seemingly at random.

Chris Tate
DBPro Master
15
Years of Service
User Offline
Joined: 29th Aug 2008
Location: London, England
Posted: 25th Nov 2014 17:57
Nice! So that problem has been narrowed down quite a bit.

Ortu
DBPro Master
16
Years of Service
User Offline
Joined: 21st Nov 2007
Location: Austin, TX
Posted: 25th Nov 2014 20:31
Yeah, and i was able to reproduce the issue on a clean copy of the AL terrain demo, so it definitely seems to be an issue with AL code or the shaders, rather than an issue with their integration with my project.

If anyone else wants to try to reproduce, run the terrain demo with various display modes: 1280, 720, 32 is known to have the issue on both of my machines and DirLight_Create(1,1,2,1024)

Ortu
DBPro Master
16
Years of Service
User Offline
Joined: 21st Nov 2007
Location: Austin, TX
Posted: 3rd Dec 2014 07:39 Edited at: 3rd Dec 2014 08:24
This week has been a case of needing to take a step back in order to take two steps forward.

As I've gone deeper into working on the combat system, I have realized that changes are needed to the character controller and animation handler. This does not require any fundamental changes fortunately, they only need to be made more flexible and more capable. Combat is a complex beast of animations, states, and timing and while my existing controllers were able to handle basic movement well enough, they already required some hacky special handling for things with multiple states like jumping and falling. The complexity of combat exacerbates this further.

So, the character controller, which sorts through character states to dertermine what animation should be playing, has now become much more abstract, making it more flexible, more extensible, and better able to handle complexity without requiring me to manage that complexity with any sort of hard-coded values or logic.

The old controller was doing something like this, which is frankly a bit of a mess, overly rigid, and difficult to maintain:



This is a simplified example but you can already see what a mess of nested if's this thing was, growing deeper and deeper as more states are evaluated. Not good.

So how do we abstract this and simplify? To start, the controller doesn't need to know anything about what specific sequences to play for a given state. The *.anim configuration files can provide this along with the range of frames that a sequence is composed of. This controller only needs to match the current state against the state identifier provided by the configuration file. This further means that the controller doesn't need to do any real evaluation of the states, it only needs to retreive them and build the current state identifier to use for matching.

So now we can reconfigure our controller to do something like this:



This gives us a string along the lines of "0010" (not in combat, not guarding, moving, not crouching = basic passive walk sequence) which can be matched against the same identifier in the animation sequence definition data. What's notable here is that we are now accessing animation sequences by a 'built on the fly' character state key instead of a pre-defined sequence name; abstraction! We can still include sequence names or labels in the config file for readability though, and can build a template for .anim files with something like this:



and of course, states don't need to be limited to a binary on/off true/false value. There can be say a 'locomotion' state in which 1=crouching, 2=walking, 3=running, 4=sprinting. This compression of things into a single state is good for those things which are mutually exclusive. For the locomotion example, whenever any one of those states is true, the other three must always be false, and so there is no need to manage them as individual booleans.

OK great, so that takes care of the character controller, but we still run into some awkward limitations in the animation handler. When setting an animation to an object, we can pass an 'action' as a parameter. This is expected to be "play", "loop", or the sequence name of another sequence to begin looping after the initial sequence plays once. This allows sequences to be chained together in a limited fashion in order to transition between loops and ensure that a given sequence completes before starting a designated follow up sequence. This is nice and all, but it makes it difficult to say for example, play an 'out/finish' transition, follow with an 'in/start' transition, then follow that with a loop. Our follow up actions are also limited to just starting another sequence as a loop, but what if we need to execute some arbitrary code only after a sequence finishes playing? Updating jump, fall and combat states, or to trigger an effect or some type of event for example.

By modifying this follow-up "action" to take a function as a callback (yay matrix1), we can empower the handler to take much more complex "actions" as a result of the animation state, without it needing to know anything more about the action than a variable function name and a string of paramaters to pass to it.

To facilitate an arbitrary and extensible chain of sequences for any given object, I have modified the processing of the list of active animations to allow an object to have multiple animation entries acting as a queue in which the 'active' animation is the oldest/first entry which will be popped when complete (and triggering any callback), allowing the next entry to become the new active animation for that object.

anim3d_setActiveAnimation(object, sequence, action)

now becomes

anim3d_addObjectAnimation(object, sequence, mode, callback)

and I've added a new function which will flush the animation queue for a given object from the handler for when you need to break out of a looping animation or just start something new.

On the art front, I am knee deep in Blender making new combat animations. From poses and stances, to attacks and reactions. Fun stuff. I hope to have a new video up next week, which will at least show some of the new animation.

I am still a ways off from getting these animations linked up to actual combat mechanics, but they give me material to work with and I am getting closer.

Chris Tate
DBPro Master
15
Years of Service
User Offline
Joined: 29th Aug 2008
Location: London, England
Posted: 4th Dec 2014 12:16
The animation functions look well written; I hope the result turns out the way you want it.

Dimis
12
Years of Service
User Offline
Joined: 12th Jun 2011
Location: Athens, Hellas
Posted: 4th Dec 2014 13:02
Well written indeed. I hope we get to see some animations soon

Quote: "and of course, states don't need to be limited to a binary on/off true/false value. There can be say a 'locomotion' state in which 1=crouching, 2=walking, 3=running, 4=sprinting. This compression of things into a single state is good for those things which are mutually exclusive. For the locomotion example, whenever any one of those states is true, the other three must always be false, and so there is no need to manage them as individual booleans."


Fully agree, and i would advice you to do that. It will be less confusing, and produce less logical errors and possible bugs, from my experience.

Ortu
DBPro Master
16
Years of Service
User Offline
Joined: 21st Nov 2007
Location: Austin, TX
Posted: 4th Dec 2014 17:24
Thanks guys.

@Dimis, yeah in the actual code, I've condensed around a dozen Boolean states down to just four byte value states.

A neat side effect of procedurally producing the template .anim file is that it provides me with a to do list of animations which still need to be created.

It may also be important to note that while I've said in the past that each object will have an attached .anim config file, it is possible for multiple similar objects to share a single config file even if the exact animations differ as long as the range of key frames for a given state match. A male and female walk sequence will be animated differently, but they should both use the same range of frames and can both share the same configuration file.

Accessories bound to a character don't need a config, as they inherit from the parent object they are bound to.

Ortu
DBPro Master
16
Years of Service
User Offline
Joined: 21st Nov 2007
Location: Austin, TX
Posted: 18th Dec 2014 19:46
Phew, time for a quick update I guess.

Things are progressing well. The overhaul to the character states and controller has been thoroughly debugged and basic movement, jumping, falling and the like is all working comparably to how they did previously but now with improvements to the transitions between states. For example, when moving while crouched the character will no longer pop back up to standing idle before sinking down into crouched idle. This is due to better detection and control between changing states as mentioned in the previous update.

Going in to these modifications, I the two goals of simplifying the state code, and expanding its control and flexibility.

It is certainly more flexible and provides me with much better control over animation, but I'm not sure if it is ultimately any simpler. It is certainly more compact though, the raw line count of the character module shrunk to about half the original size. This gain was quickly counterbalanced by the addition of new skill / ability handling code which is required for the development of combat and potentially for some non-combat abilities as well.

OK, so let's talk a bit more about combat itself. Previously, I talked about the damage result of un-defended melee attacks. So today, let's talk about ways to defend against attacks, and avoid taking that damage in the first place.



Part 10 - Combat Defense

There are three basic methods for defending against a physical attack, be it melee or projectile. You can block with a shield, you can (possibly) parry with a weapon(s), and you can evade with quick movement abilities.

(Note that all {{mouse/key}} controls are defaults and can be fully remapped/reassigned through user options)

While in a combat state, you may hold {{RightMouse}} to enter a defensive guard state. Attacks cannot be made while guarding, and you remain vulnerable during the transition in and out of guard state. The speed of the transition can be improved through stats and abilities, and can be penalized by performing certain attacks or while under certain statuses.

The type of guard state that you will enter depends on what you have equipped along the following priority level:

if a shield is equipped -> enter Shield Guard elseif a parry capable weapon is equipped -> enter Parry Guard else -> enter Evasion Guard

Shield Defense:

Shields provide the best defense. While ready in a shield guard state (holding {{RightMouse}}) they will automatically block physical attacks (melee and projectile) incoming within a 180 frontal arc.

As with all equipment, damage done will reduce the item's condition, and it will eventually break, thus you can't just turtle up and hide behind a shield forever.

Parry Defense:

Parry is a bit more complex. The coverage zone is smaller, (subject to testing and adjustment) something along the lines of 105 degrees.

Similar to shields, while ready in a parry guard state (holding {{RightMouse}}) a parry capable weapon will *attempt* to automatically block physical attacks (melee only) incoming within the weapon's coverage arc.

The exact location of the coverage arc depends on weapon usage. If using a weapon with both hands or with the main hand only, coverage may be directed to either the right side or the left side thus covering the range of either 0 - 105 degrees or 75 - 180 degrees, leaving you partially exposed.

Coverage side can be directed by moving the mouse right or left past a minimum threshold to allow for, and ignore, minor movements which should not be considered as a coverage switch command.

When dual wielding and using a parry capable weapon in each hand, one hand may be placed into a guard state and cover the 105 degree arc on that side (ex: left hand covers left side), while leaving the other hand in a combat state and able to continue making attacks. In this situation, when using the mouse to direct coverage, you are swapping which hand is in guard state and which is in combat state such that directing coverage to the right side will put the right hand into guard and left into combat, you cannot move coverage to the right and leave the left hand in guard/right hand in combat.

Dual wielding with two parry capable weapons additionally opens up a third coverage option in which both hands are put into a parry guard state and the coverage arc is extended to the full frontal 180 degrees. You can direct this full coverage by moving the mouse down beyond the minimum threshold. Just as with the non-dual wield guard states, no attacks can be made while in this full coverage.

Now for a succesful parry, in addition to needing the proper coverage, you must also pass a parry check which compares various character and equipment stats against the incoming force. If this check is failed, your parry is considered to be 'overpowered' and it will only reduce the incoming damage, not block it outright.

Evasion Defense:

Evasion doesn't stop an attack, it works by physically removing you from the attacker's range. Aside from simply moving your character out of the way with basic movement, there are evasive abilities which may be used to quickly move the character a short distance typically backwards or to the sides.

While ready in an evasive guard state (holding {{RightMouse}} and while moving {{wasd}} you may {{LeftClick}} to execute a quick dodge in order to leap a short distance in the direction of movement.

Additionally, some combat skills / abilities will perform a quick dodge from a combat stance without requiring you to be in an evasive guard state. This means that depending on how you choose to build your combat style, you may have evasion abilities available even if your equipped weapons will put you into a shield or parry guard state while holding {{RightMouse}}

The notable difference between evasion and the other defensive skills is that there is nothing automatic about it, even while holding a guard state, you must actively trigger an evasion every time.

Progress:

Managing combat and guard states is complete and I am currently working on implementing the evasion abilities and their ability to reposition the character.

Ortu
DBPro Master
16
Years of Service
User Offline
Joined: 21st Nov 2007
Location: Austin, TX
Posted: 7th Jan 2015 05:54 Edited at: 7th Jan 2015 05:54
Hello my friends, hope you all had a great end of year, mine was. Things have been busy, for Sulium and otherwise.

The combat-mode character controller is nearly complete, though actual combat which will require npc AI among other things, is still a ways off. What does this mean exactly? You the player now have the ability to attack, defend, and use abilities to your hearts content, there just isn't anything to actually use these against quite yet.

The available abilities are also quite limited, only 3 or 4 have been implemented so far and I've not yet begun working on the interface for the character to train and manage them.

The technical foundation is there, but it has a long way yet to go before it is a fully fledged gameplay system. That being said, it's kind of, sort of, starting to feel like an actual game now. Exciting times!

I am working on finishing up a few more animations, and some art assets before getting a new video together to show where the game is at, but here is a quick preview, enjoy



Attachments

Login to view attachments
Dimis
12
Years of Service
User Offline
Joined: 12th Jun 2011
Location: Athens, Hellas
Posted: 7th Jan 2015 23:25
Just an idea, maybe you could have your character fight a clone of herself, somehow? Just to see how the combat feels against an actual opponent, even having the clone doing only basic attacks and defenses.

Ortu
DBPro Master
16
Years of Service
User Offline
Joined: 21st Nov 2007
Location: Austin, TX
Posted: 8th Jan 2015 00:39
That's exactly what i am planning to do for the next phase once I start getting to work on basic AI

Ortu
DBPro Master
16
Years of Service
User Offline
Joined: 21st Nov 2007
Location: Austin, TX
Posted: 12th Jan 2015 00:16
As promised, here is some video of ability use in action.

I'll be the first to admit that character animation is not one of my strong points some are quick placeholders, others need work to smooth them out, but it's enough for the engine to work with for now so that's a good thing! Interestingly enough, it currently takes longer to export the character to .x than it does to compile the game.

anyways, I'd like to move directly into some basic AI to get an opponent in the game, but I really need to spend some time modeling and texturing to flesh out the cottage and environment a bit, I haven't quite decided which way I'll go for the next week or two, but something will get done one way or another.



So, I suppose a little bit about what is going on is in order. You will notice the new vitals HUD in the bottom right corner, it shows Health, Stamina, and Armor Condition.

It also has a silhouette which shows the character's current stance. Each attack ability has a starting stance and an ending stance, you can create something of a 'soft-chain' by timing abilities so that the next ability start stance matches the previous ability's end stance, this creates a smooth and uninterrupted flow of attacks because there is no need to transition to the proper stance, the previous ability has provided the transition as part of the ability motion itself.

If you trigger an ability that starts in a stance different from your current stance, the ability will be queued up to begin after a transition into the start stance from the current stance, causing a short delay, and leaving you open to be attacked.

There are currently 2 non-combat stances: Passive and Sneaking

There are currently 5 combat stances: Shield Guard, Parry Guard, Evasion Guard, Balanced and Striking

I will eventually be adding a Firing stance for use with ranged weapons.

In addition to stances, melee combat abilities can belong to one of three 'modes' or 'types': Basic, Powerful, Skillful

And will also belong to one of three 'directions' or 'intents': Press, Hold, Fallback

In addition to dealing damage and applying effects to the target, abilities are able to control the user's speed and positioning. This enables defensive abilities like dodge to quickly move you backwards or sideways, allows an ability like Lunge to move you forward to close distance with your target, and abilities like Flank can move you around your target to land positional attacks against the back or side.

To wrap it up for today, aside from the soft-chaining of stances, abilities can also be hard-chained such that say ability Y has a requirement that it must be used immediately after using ability X. There are abilities with positional requirements: ability Z can only be used against a target's rear half; and lastly, there are reactionary abilities such that ability W can only be used after you block an incoming attack.

Now as to how many abilities can you take into combat, how do you manage them, how do you activate them, how do you chain them and so on and so on, I will leave that for a more detailed write up of Part 11 - Melee Combat and Abilities, coming soonish

Dimis
12
Years of Service
User Offline
Joined: 12th Jun 2011
Location: Athens, Hellas
Posted: 12th Jan 2015 13:43
Good work Ortu. The HUD is subtle but very clear. Are you using the native DBpro animation commands?

Ortu
DBPro Master
16
Years of Service
User Offline
Joined: 21st Nov 2007
Location: Austin, TX
Posted: 12th Jan 2015 21:07
I use only 'set object frame' I handle playing, wrapping, timing, etc in order to determine what frame should be current myself in my animation module.

This gives me better control over playback speed to keep it consistent regardless of frame rate, and allows me better detection and control over what happens when a sequence has reached the last frame. Does it loop? Does it end and remove itself from the queue? Does it execute a callback function? If it is a looping animation does it need to execute a callback function to validate whether it should continue looping?

For instance, a stance transition animation will play through once, call back to a character function to update the current stance data, then remove itself from the animation queue allowing the next sequence, say an attack In animation to begin.


When the attack In completes it calls back to a combat function to determine if anything was hit, was it defended, and to get a damage result, it then removes itself and let's the next item, an attack Out sequence Begin playing, which will callback another stance update on finish.

For something like a dodge, after the ability In finishes, it removed and begins a loop sequence for that ability which will callback each cycle to check if the abilities max move distance had been reached. It will continue to loop until it does so then remove itself and begin the ability Out sequence.

Ortu
DBPro Master
16
Years of Service
User Offline
Joined: 21st Nov 2007
Location: Austin, TX
Posted: 13th Jan 2015 19:51
Who wants more lore? It's been a little while since we had a look at the more creative side of this project instead of the technical, and what is an RPG without story right?

This bit of story will give you a first look at some of the more prominent characters in the game, including the primary player character / protagonist, Samir, and it sets the stage for what is happening when the game begins.

It is a bit lengthy, so I won't post the whole thing directly. Here is an excerpt and the full chapter as .doc is attached if it grabs your interest and want to read more.

... The first thing one invariably noticed upon entering the Chamber of the Sun was the device itself, the Eternal Sun. The entire room, in fact, the entire tower, was designed around this one thing of singular importance. When Sulium had been created, there was no Guardian; such a being did not yet exist. Caelios had been just another Pharosian, an inhabitant of the tower as any other. Sulium had not been built for the Guardian, nor for his Chosen, it had been built for the Eternal Sun, and this chamber made that very clear. It held the center of the room, as the beacon of a lighthouse, with grand, freestanding pillars ringing it about. Its brilliance could rival the natural sun above at times and it hurt to look at when it was actively in use.
Today it simply pulsed with a soft and pensive glow to match the Guardian's own. Caelios stood peering into its fiery depths and Samir could not begin to guess what his master might see there. To Samir, the Sun was a spherical mass that seemed to have substance, yet was certainly not solid. It was as if light had turned to liquid and been gathered in one spot. It hung suspended in the air, floating unsupported and held up by nothing apparent. Above it and below, lay a pair of platforms similar in many ways to the lifts throughout the tower. They were covered with the same golden tangle of lines, yet these had additional pipes and tubes and thick black ropes which disappeared into the ceiling and floor, presumably carrying its power throughout the tower.
The substance of the Guardian's body matched that of the device: liquid light that was both substantive yet un-solid and ever shifting. Samir knew that if he were to reach out and touch his form, his hand would meet resistance for all that it looked as if Caelios were nothing more than light gathered in a man-like shape. His form was the perfect sculpture of a man in his prime, tall and muscular, an embodiment of physical power. Caelios had no need to stand or walk, but simply floated over the ancient tiles as did the Eternal Sun itself. Samir often thought of the Guardian as an ember, a spark broken off and swirling about the larger star from which he came...

Attachments

Login to view attachments
Chris Ritchie
18
Years of Service
User Offline
Joined: 7th Jan 2006
Location: Norn Iron
Posted: 14th Jan 2015 23:46
I have been keeping an eye on this project from the start and just wanted to tag in and say what a fantastic job you are doing with it. I am always interested when a new rpg project is started because the work and scale of a project such as this is huge and sometimes daunting, but from the professional way that you have thought out and planned from the start I fully expect to be playing the game someday. Stick with it and keep up the good work.


Lead programmer ULIDIA
Ortu
DBPro Master
16
Years of Service
User Offline
Joined: 21st Nov 2007
Location: Austin, TX
Posted: 15th Jan 2015 00:13
Thanks man! That is really appreciated.

Big projects can indeed be intimidating, you are deep into one yourself and probably have had similar experiences in it. As you probably know, the keys in my experience are to go into it with a solid overarching plan, but don't get bogged down into details and lose momentum, let it be an iterative process of refinement, where something rough or temporary to start can become corrected and more polished over time. I also find it helpful to focus on only what is immediately before me, or is very soon to come, and try not to think much about the mountain of asset and content creation that still needs to be done.

I look forward to having you play the game someday, I'm also looking forward to seeing more updates on Ulidia, your visuals are impressive.

Chris Ritchie
18
Years of Service
User Offline
Joined: 7th Jan 2006
Location: Norn Iron
Posted: 15th Jan 2015 00:27
Indeed, what you mentioned is exactly the process that I am taking (although I wish I had taken it sooner), once all the core aspects are in you can go back and fine tune. Thanks for the compliment I am just putting the finishing touches to a new video at the minute, should be posted within the next week.


Lead programmer ULIDIA
Ortu
DBPro Master
16
Years of Service
User Offline
Joined: 21st Nov 2007
Location: Austin, TX
Posted: 20th Jan 2015 19:56 Edited at: 20th Jan 2015 19:59
This isn't really am update, but i was playing with lighting and this shot in particular stood out to me so i thought I'd share

Progress wise, i did indeed decide to spend some time on art assets and am working on getting the interior filled out a bit more. I've got a real ceiling now and some structural support elements. We will see how far i get this week and reevaluate what comes next.



Attachments

Login to view attachments
Chris Ritchie
18
Years of Service
User Offline
Joined: 7th Jan 2006
Location: Norn Iron
Posted: 21st Jan 2015 18:11
Looks great man, very nice lighting and I like the lens flare. Are your buildings going to be fully open, or will you have the interiors and exteriors as separate models?


Lead programmer ULIDIA
Ortu
DBPro Master
16
Years of Service
User Offline
Joined: 21st Nov 2007
Location: Austin, TX
Posted: 21st Jan 2015 18:35
They will be fully open as seen in the videos so far, though some rooms/areas will be blocked off through closed and locked doors and shutters. Interior objects not viewable through an opening can be toggled on/off during the door's Use interaction event much as it would with zoning to help performance. While i do want building access to be seamless, visibility in and out needs to remain restricted when possible. I can always switch to zoning later if it ends up unable to maintain my performance goals.

All credit for the lens flare and other shaders goes to Evolved and his Advanced Lighting system, thanks though!

Lens flare, bloom and the like can be controlled or disabled through user settings, for those that don't care for them.

Ortu
DBPro Master
16
Years of Service
User Offline
Joined: 21st Nov 2007
Location: Austin, TX
Posted: 6th Feb 2015 05:14 Edited at: 6th Feb 2015 05:16
Sorry for the slowing pace of updates folks, I'll admit that I was rather unmotivated last week, I tend to lose focus and drive when I start working on media. I enjoy modelling and sculpting, but it just isn't nearly as engaging as code development. I got back to work this week though and figured it was time to start getting some vegetation in.

I've been putting this off, it is almost always a massive performance killer to try to flesh out a landscape with trees, bushes, grass and the like. While I knew there would be performance issues to deal with, I didn't expect to have nearly as much trouble just getting the dang things in as I did. This was one of those things that *should* be fairly straight forward, it's just loading some models right? that ended up being more complicated than anticipated.

First off, I struggled to get the tree objects working with the AL tree and leaf shaders, the trunks didn't have much trouble but I never did manage to get the leaf shader to work with my Blender exports correctly. The best I could manage was black / unlit leaves with proper alpha and motion but of course that isn't good enough, gotta have light!

So I fell back to bone based animation with the same shader used for the character models. It's working well enough and looks good, so I proceeded to add in support to the world database and level loader for cloning and instancing obejcts. Cloning worked fine right off the bat, though it killed performance of course. Instancing was not so easy. Nothing was visible, debugging showed that the triangle count being rendered was correct, but I couldn't see the trees. My first assumption was that AL wasn't playing nice with instancing, despite it working fine in the palm tree demo, so again my time was tied up in trying to figure out what went wrong.

Just by chance I happened to get the camera view set in such a way that I noticed a spec against the skyline and realized that the instances were there, they were just scaled down ridiculously small. Scaling them up was an easy enough fix, so on to scattering these bad boys all over the landscape.

I pushed my tests up to 500 instances of a single tree, rending around 650k triangles on screen and performance is less than satisfactory. Keep in mind I haven't implemented any sort of LOD or culling optimizations yet, but framerates were fluctuating between 25-40 most of the time, down from around 120 before the trees. ouch.

It's well known that DBpro prefers fewer objects with more limbs than lots of objects even if it is the same amount of polies being rendered overall, so back to Blender to build some tree clumps using around 8 - 10 trees / object limbs per object. This lets me field roughly the same number of trees with 60 instances instead of 500. Performance did boost, hanging between 38-60 but this is still no where near acceptable. I'll need to continue to optimize going forward, but even then, I realize that I will probably need to cut back and have a somewhat sparser landscape than I was hoping for. /sigh To be honest, this was pretty much expected and the main reason I'd been putting this off.

Getting the limbs to adjust / fit themselves to the terrain was another adventure that took most of my time today to sort out. I don't know what it is but limbs have always given me trouble. These are fairly basic things and shouldn't be that big a deal, but I constantly have issues with positioning, offsets, and scaling of limbs.

If there is a GET limb position for world space coordinates, why is there no SET limb position in world space coordinates?? Instead you have to transform back and forth between world space position and internal offset, which apparently is not affected by scaling the limb, so if it is scaled, a change in offset value will not directly equate to the same value in position. Sure the math is simple once you are aware of the difference, but it took time just to figure out what was going on.

It also turns out that unless you recalculate the object bounds when changing a limb offset, you will not get updated world space position coordinates for the limb.

So, anyway it's been a good if long learning experience this week. I've got a long long way to go on the performance side of things, but I'm looking forward to adding more variety and tree types. Filling out the world does a lot to make Sulium feel more like a game and less like an engine test. This is progress.

Here are some lemon trees:



And just for giggles, here are some old trees from my first real project in DBClassic back in 2007:



Attachments

Login to view attachments
Chris Tate
DBPro Master
15
Years of Service
User Offline
Joined: 29th Aug 2008
Location: London, England
Posted: 6th Feb 2015 10:52
Very nice. How does the color management work in the last example?

Ortu
DBPro Master
16
Years of Service
User Offline
Joined: 21st Nov 2007
Location: Austin, TX
Posted: 6th Feb 2015 18:36
The old DBC shot? It was a fully dynamic day/night cycle using 4 layered sky spheres and changing the color and angle of light 0. It had 2 basic ghosted cloud layers, with scrolling texture for motion, a sky color layer which used color object / fade object, and the outermost layer was a night sky / star map.

Dimis
12
Years of Service
User Offline
Joined: 12th Jun 2011
Location: Athens, Hellas
Posted: 7th Feb 2015 14:02
Nice screenshot with the lemon trees.
The old one is not bad, seems to me like decent enough work, for DBpro Classic. Sometimes you have to look back to see how much you have progressed.

Did you try to add more than 50 bones to the main character?

Ortu
DBPro Master
16
Years of Service
User Offline
Joined: 21st Nov 2007
Location: Austin, TX
Posted: 17th Feb 2015 06:24 Edited at: 17th Feb 2015 06:44
@Dimis,

No, I haven't yet sorry. I'm pretty sure it will work fine though, as thinking back, I think the problem I had before was actually with some vertices being weighted to more than 4 bones, but this was only uncovered after I reduced the bone count so I kind of just assumed both were part of the problem.

Quick update, I've started work on some really basic AI. Pathfinding is something that I've always avoided and put off as it seemed very complicated. Turns out it's really not, at least the basic premise isn't. Fine tuning and optimizing can get much more complicated, but I was able to get a simple A* implementation up and running today.

It tries to avoid increasing elevations / steep hills and seems to work pretty well, if not terribly fast. As I said, it's very basic and needs a lot of optimization to really be usable but the foundations are there now.



And of course, the obligatory maze:



Attachments

Login to view attachments

Login to post a reply

Server time is: 2024-03-29 14:49:35
Your offset time is: 2024-03-29 14:49:35