• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
  • entries
    432
  • comments
    1166
  • views
    759189

Crafting Skills, and Ranting About UI Programming

Sign in to follow this  
Followers 0
JTippetts

968 views

a57K21u.jpg

Did some more coding on the spellbooks and crafting units UI today. I can see a significant refactor coming pretty soon, now that I have gotten both a better handle on how the UI system works, and have gotten some refinements done on the code I am using to instance UI elements.

Made a few tweaks to the spellcasting system to incorporate crafting skills. The spellcasting system defaulted to a target selection mode when any spell was cast, since most combat skills require a target or target location. However, crafting skills don't take a target and should happen immediately, so I had to make that change.

A crafting skill is essentially just an instant-cast spell. It consumes certain specified resources, and triggers an effect that adds other resources to the caster. In the current tests, both the Basic Workbench and Basic Spell Tome share the same crafting list, with but two elements: Create Wood Planks (consumes 2 Wood, creates 1 Plank) and Create Tinder (Consumes 2 Leaves, creates 1 Tinder). Tinder is now the resource of choice for TestFireball. In order to cast any fireballs, you have to chop down a "tree" (in the caves, mushrooms are trees) in order to obtain a few leaves, then convert those leaves to tinder at a workbench. This is a basic template for most of the gameplay I have in mind: you scavenge around, obtaining materials with which you can cast spells or do other things.

As part of the impending refactor of some of the spellbook UI stuff, I'm going to need to incorporate hover text for skills. Given my small set of icons, it's getting hard to remember which buttons do what since they are all drawn from the same 4 icons.

I've always found UI systems to be awkward. It's just the nature of the beast. You have a hierarchy of elements, all of which require a fairly decent chunk of data to describe, requiring a deeply nested structure of descriptions to be instanced as elements. Either you write a bunch of boilerplate to do it, feeding it a table of data and obtaining an instance hierarchy at the other end, or you build them all by hand, laboriously and with much proneness to error. However, the act of instancing it through boilerplate includes its own gotchas.

For example, UI elements in Urho3D UI generate events that pass through the core event management system, which can be received by any Object-derived class that subscribes to them. You can subscribe to events globally, such as the main-loop Update event. Any object signing up for Update gets the game tick. Or you can subscribe to events originating only from a given object. This is how the nuts and bolts of inter-component communication works. A TakeDamage event sent by a specific Node is listened for in some of the various internal components, to do things like modify life, generate floating combat text, log the hit to the combat log, etc... If these components couldn't sign up to hear Takedamage only from their owning node, then they would receive all TakeDamage events generated anywhere in the game, and the result would be madness.

So in order to get events from a particular UI element, you need to subscribe to events from that specific element. In order to do so, you need a reference to the element. The problem with this approach is that UI hierarchies can get deep. For example, I have a top-level player UI element that contains all of the child elements for a particular player unit, including a container for any spellbooks opened by workbenches, the quick bar, the quick bar spell library, the action bar, and so forth. A spellbook itself is a hierarchy consisting of a background, a scroll view, a close button, a UI element panel holding the buttons/icons representing the spells, etc... It can get deep, and unfortunately these icons/buttons inside the panel are the ones we need to obtain in order to sign up for their events for Pressed, Released, etc...

The problem with instancing a UI through a chunk of boilerplate that consumes a hierarchical description and returns the instanced element, is that all of the child elements are hidden away in a UIElement's children list; and all of their children are hidden away in their own lists. And so on. So to get to the action buttons of a spellbook, I need to descend down through the hierarchy, from the player root window, through the spellbook container, into a particular specified spellbook, into the spellbook's background element, into it's scroll view, into it's button panel and container, and finally to the buttons. Given the clumsiness of the interfaces for delving down through hierarchies, this quickly becomes quite a large pain in the ass.

A solution, of course, is to build all the elements by hand, stashing away references to elements we are interested in using later to sign up for events. This, of course, leads to the even bigger pain in the ass of instancing elements by hand, with all the wordiness and crushing tedium that entails. A compromise is to instance hierarchies for some bits using the boilerplate, and instance the interesting bits by hand, using hierarchical descriptions for those elements in turn and stashing away the references. This is the method I am currently using.

The problem with this method is that it leads to spaghetti code, functions or methods that have to do a lot of by-hand wiring up and munging around. I've already gotten some leaks doing it this way, and I am currently using code that I find to be highly suspicious, and not trustworthy at all. I haven't done any kind of long-duration stress testing on it, and I'm afraid that if/when I do it'll all kind of unravel on me, slowly and messily.

I've always hated UI code, specifically for this hairy mess of getting all the doohickeys wired up to the thingamabobs in anything even approaching an elegant fashion. This tedium is why I find UI programming to be the most onerous part of game development.

5
Sign in to follow this  
Followers 0


4 Comments


The problem I run into alot with my GUI code is that GUIs, by their very nature, use multiple fundamentally different paradigms than the rest of the game logic, and where the two paradigms meet I feel like I always resort to sloppy duck-taping the code together to get them to play nice.

 

If you're hard-coding connections anyway, how about some kind of "reference directory", which your event subscriber objects can query for GUI elements by name to get the reference they need to subscribe to events.

On UIElement creation: ReferenceDirectory["Custom name"] = this_handle;
GameObjectThatNeedsHandle: SubscribeToEventsFrom( ReferenceDirectory["Custom name"] );

Random thought 4 minutes to midnight, so take it with a grain of salt.

0

Share this comment


Link to comment

Note that if your Urho3D UI elements are uniquely named, you can do a recursive search for arbitrarily deep children from the root of your UI element. GetChild("ElementName", true)

0

Share this comment


Link to comment

Man, I hear you. I hate, hate, hate UI programming. It's always ugly. Unfortunately, I've never seen any good solutions to the complexity. If you have a complex UI, you're going to have to write a lot of ugly code to get things hooked up. Like Servant said, duck-taping two paradigms together gets messy.

 

Looking pretty awesome, though. If you need any volunteers for your stress-testing, let me know. I'm not a huge fan of turn-based, but maybe a complete turn-based noob is what you need to find the weak spots. :D

0

Share this comment


Link to comment

Huh, somehow I missed GetChild(). That does make it easier. I did do a little refactoring, and the new result is much nicer.

0

Share this comment


Link to comment

Create an account or sign in to comment

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

Create an account

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


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now