Sign in to follow this  
  • entries
    45
  • comments
    115
  • views
    54479

About this blog

Successfully avoiding completing game development projects since 1988...

Entries in this blog

Kylotan
As much as I like GameDev.net, I find the journal system here to be underpowered - no tags, no categories, posts disappear from the front page if they're too old, poor support for inline formatting, etc. This has made me hesitate to spend time putting entries here, and the last one was eight months ago.

So in future, I will be posting on my own blog at http://www.ebonyfortress.com/blog/. It's using Wordpress, which is your typical example of crap-code-good-functionality, but it's functionality that counts here. Hopefully I'll see some of you over there, as well as through my continued presence on the forums here of course.
Kylotan

AI in games

Hello GD Journal, it's been a while. Mostly because the journals are still exceedingly well separated from the rest of the site. I have no idea whose journals are worth reading - any suggestions?

At work, our development cycle is coming to a close and I have lots of reflections on the development process to share; but that will wait until after release.

At home, I am very slowly working on a web-based game, but have changed direction with it quite significantly after not only did I hit a problem, but I stumbled upon a solution at about the same time. Unfortunately it left me questioning a fundamental approach to my game, which I'll come to shortly.

Earlier this year I started a couple of threads on an algorithm for grouping a set of actors together so that they could perform tasks, the idea being that they'd gather as many actors as necessary, but not too many (as the reward would be diluted), and that certain actors were better suited to some tasks than others.

As you might see from the threads, should you be bored enough to read them, finding a good algorithm for this is quite difficult, especially since my original specifications are not exactly fixed in stone. I just wanted something that looked right, and defining it was surprisingly tricky. It was easier to list situations that I didn't want to happen, than to specify precisely what I did want. Such is the nature of all AI problems really - the trick is in finding the correct representation of your problem. In the end, I got the feeling that this system was unworkable; I found ways of having the characters group up for tasks, but it was usually quite predictable, and trying to influence them through the size of the reward was too coarse a tool.

That was when I found the solution, in the form of the football (ie. soccer to North America) management game, Championship Manager. The problem you face there is much the same as my problem, in that you have tasks to perform (in this case, football matches), and you have a pool of characters of differing abilities which must be combined to achieve this goal. Instead of the AI grouping the characters for you, you pick the team yourself.

This removes my initial aim of the characters being largely autonomous entities that work together to achieve a goal. But it arguably makes for better gameplay, by moving more interesting choices into the human player's hands. And so I can now move the game design and prototype forward with some solid principles that have been tested in the field and have done well with players (over 85% on Metacritic for recent instalments in the series, ie. the Football Manager games). But now the AI component is no longer part of the game.

This leads me to think, just how useful is AI in games? Quite a few of us rue the fact that so many computer opponents are stupid, but that tends to be a feature of faster paced games where foes run into walls, or aim like Imperial stormtroopers instead of like real soldiers, or where monsters would rather stand still and be hacked to death than run away or call for help. When we ask for better AI, we could have all of these with virtually no code time at all. Is that really what we're asking for? Or is there something more? I have the first 3 AI Wisdom books, and although every single article in them impresses me in some way, virtually none of the games I play or consider making would make use of any of these. For example, listing 101 ways to generate pathfinding nodes is all well and good, but not terribly interesting unless reducing CPU usage for AI from 5% to 2% is of interest.

I'd like to hear what AI you'd like to see in games, and perhaps why you think it isn't there yet (eg. deliberate design decision, lack of raw computing power, difficult to represent well as an algorithm, etc).
Kylotan

Here's an idea

For so long we've seen newbies come on these forums, and say something like "I have a great idea for a game - how do I get it made?" The slightly more optimistic, or dare I say mercenary, may actually ask how they sell it, but the underlying concept is the same, in that someone with no knowledge of how the industry works comes on here thinking that a vision is valuable. Not only that, but they believe that their vision is valuable.

Board and industry veterans, myself included, chuckle inwardly and decide how best to deflate this newbie's hopes. A couple of people will mention that ideas are a dime a dozen, and that games companies don't buy ideas because their employees have loads already. Some may mention that games are expensive products, that those who make them are highly paid professionals, and that therefore the value comes in what you can bring to that process, because implementation is the hard part. Some will point out that companies won't look at idea submissions for legal reasons. Tom Sloper will post a link to his wonderfully detailed Sloperama advice site. The newcomer eventually experiences one of three emotions, disappointment (and often a loss of interest), resolve (to learn the tools to get their game made), or bitterness (that nobody can understand just how great their idea is).

All the while, the industry churns out crap. Yes, it's polished, enjoyable crap, but it's crap nonetheless. What sold well last year?

On the PC: World of Warcraft (sequel, admittedly in new genre), The Sims 2: Open for Business (expansion/sequel), The Sims 2 (sequel), The Elder Scrolls IV: Oblivion (sequel), Star Wars: Empire at War (license), Age of Empires III (sequel), Civilization IV (sequel), The Sims 2: Nightlife (expansion/sequel), Guild Wars: Factions (sequel), Zoo Tycoon 2 (sequel).

How about the PS2: Madden NFL 07 (the mother of all sequels/license), Kingdom Hearts II (sequel), Guitar Hero, Final Fantasy XII (the father of all sequels), NCAA Football 07 (sequel/license), Guitar Hero II (sequel), MLB 06: The Show (license/sequel), Scarface: The World is Yours (license), LEGO Star Wars II: The Original Trilogy (double license/sequel), Fight Night Round 3 (sequel).

XBox 360: Tom Clancy's Ghost Recon Advanced Warfighter (license/sequel), Madden NFL 07 (sequel/license), Gears of War, The Elder Scrolls IV: Oblivion (sequel), Fight Night Round 3 (sequel), Saints Row, Dead Rising, NCAA Football 07 (sequel/license), Call of Duty 3 (sequel), Tom Clancy's Splinter Cell: Double Agent (sequel/license).

Come on guys... this isn't just unfortunate, it's embarrassing.

And every time we tell a newbie that ideas are currently worth nothing, we are helping to perpetuate that lack of worth. This in turn perpetuates the crap above, where gamers scramble over each other to get their hands on Halo 3, a sequel to a sequel set in a cliche setting and a highly derivative genre. (And it wouldn't be surprising if even the Bungie guys, although proud of their work, were quite aware of just how little they are giving to the world by delivering yet more of the same when they are capable of so much more, thus setting the stage for them parting ways with Microsoft.) This is surely part of why Nolan Bushnell, responsible for so much innovation in games during the 80s, considers modern games 'unadulterated trash'.

Is there a better way?

Well, I'm certainly not arguing that every newbie with a 'k3wl g4me 1dea' should be taken seriously and have their work published. But on the other hand, the highly trained human factories who churned out the cloned dross above are certainly not going to be producing much of real worth either. Perhaps someone needs to be going through these external ideas and looking for the diamond in the rough? If, as we often see on the forums, an idea is just another RPG with their own particular permutation of the typical elements, then sure, toss it out. But if their idea is the next Guitar Hero, or Tetris, or Civilization, or Donkey Kong, or Elite, or... hell, anything that doesn't have an ordinal number as a suffix and a pre-existing property as a prefix - then shouldn't there be someone who can step in and deliver that to us?

Let's be fair, game design is not about merely coming up with a cool idea and selling it to someone else - it's about systems, as designer Raph Koster points out in a recent blog entry. Games are active and the design must manage the flow of the players and the non-players through the game space. This is not usually something you can adequately predict before building any prototypes. But does that mean the original idea is worthless? A good script can be rewritten as a screenplay, often rewritten several times before it can be shot as a film. But it doesn't mean the original script was worthless. Sometimes the original writer might be retained for some duration while the script is worked into something usable, and other times it might just be purchased from them. There can be overlap and cooperation between the person who holds an overall vision, and the person or people who buy into that vision but who better understand the systems they're working with.

Sure, many people who write for films find themselves rejected time and time again, and 99% of the submissions are probably useless, but does that mean that we should discount the other 1% (or 0.1%, or 10%) out of hand, in favour of trying to produce the same old software, relying on branding and licenses to carry it in the market? Is it perhaps worth investing in trying to cultivate new ideas? Or do we continue to rely on the ideas grown in-house, which don't seem to be delivering the goods?

There have been plenty of great game ideas out in the independent sphere, things like Braid, Immortal Defense, Virtual Villagers, Democracy. Sure, as with most games, they owe much to their predecessors, but they do not just update the graphics, or add a couple of extra weapons, or add a replay feature, or tack on yet another multiplayer mode. They bring significant new twists to the gameplay and presentation, to give us a new way of seeing games. Some make us think, not just in the "work out this puzzle" sort of way, but in the "ponder the human condition" sort of way. Why can't we expect a typical game to do this? When will a mainstream game have the same emotional impact as a game like Photopia?

I'm pretty sure I don't have all the answers to the problem. But I refuse to believe that "the market" dictates that people only want sequels and licenses. As with film and books, something new and special quickly carves its own niche if it's good enough. All we have to do is give it a decent chance and not bury it under the sequels and licenses which should be the bottom layer of our industry, not the top layer. We need to encourage interesting ideas and interesting takes on old ideas, and much of that is not going to come from within.
Kylotan

Squirrel

Imagine you are a squirrel. You're at the foot of a large oak tree, contemplating climbing it to feast upon the acorny goodness that it offers. You start climbing up the trunk, and it provides a single obvious and reliable route up the tree. Eventually you reach branches, where you can choose the one that seems most appealing to you, perhaps holding the most acorns, or bigger acorns, or other squirrels to play with. If you end up choosing the wrong branch, you can back up and choose another one, and sometimes you can jump across from one branch to another one nearby. As you continue to climb, the branches get thinner and start to bend under your weight. The further up the tree you go, the more they move in response to your presence and that of the other squirrels. Sometimes this makes it easier to get to the other branches and liberate the acorns they hold, and other times you end up dangling in the middle of the air, needing to go back before you can proceed. But once you leave the branch, eventually it reverts back to its original position, ready for the next intrepid squirrel.

The tree is a persistent online game. The squirrels are players. The branches are courses of action that players or groups of players can take. Most games provide these branches, but they don't bend. You pick quests, carry them out in largely the same way that the last person did, and nothing changes as a result. You climb up the steel branch, get the acorn, then climb back down to the welded join to take the next branch.

A better system would involve a degree of flexibility. A player should have an impact on the game that influences their future choices and which is noticeable to the other players. There wouldn't be so much at early levels; this is the 'trunk' and the largest branches, which barely budge under your weight, and which are designed to be rigid introductions to the game, with little scope for error. Later on you get to have a real influence on the world, that gives better opportunities to make a difference. But when you withdraw from that area of the gameplay, it slowly bends back into place, giving other players the same opportunities that you had.

So, how do we build this flexibility in place, while keeping the 'springiness' that makes a branch snap back when a player leaves it? Perhaps players gradually accumulate more and more skills that allow them to alter the game world, but none of those alterations would be permanent - houses crumble, forests regrow, goblins migrate to different lairs. A better understanding of feedback systems might help here, allowing us to create sub-environments that can absorb a certain degree of player action before springing back in response. Better exploitation of the middle ground between 'repetitive grunt work' and 'high fantasy quests' when creating tasks for players might be lucrative; defending outposts or making diplomatic representations are the sort of activities that can both make a difference and yet legitimately be carried out by player after player without breaking the fiction. A Tale In The Desert shows one possible direction with many of the activities being social in nature, the fact that many players are doing the same quest becoming a benefit rather than a fiction-breaking distraction.

I'm not sure we have all the answers just yet, but I am sure that we can do better than the relatively rigid structures that we currently have in most such games.
Kylotan

Ivory Towers

It's funny when people appear to live in some parallel dimension where they don't have to contend with the details of real life. Take this quote from "Efficient C++ Programming" in 2002:

Quote:
The language extension never became part of the language, but the optimization itself has become nearly universal. It is called the name return value optimization.[...] (At the time of this writing, I am aware of only two compilers that do not provide the named return value optimization: the GNU compiler gcc and Visual C++.)


Just which universe did Stanley B. Lippman dwell in where you could exclude MSVC and gcc and still consider a C++ feature 'universal'?
Kylotan

Inefficiency

My short time in the games industry - 8 months or so - has been marked by inefficiency. I now have a good idea why games take so long and why so many projects are cancelled. Setting aside human error and egos, which are a major problem on the publisher side it seems, the development side is just plain inefficient, often because problems are solved in such a way that other things become harder.

Examples:

- source control systems: it keeps source backed up, it allows for revertions, and stops people trampling on each others work. All good. But it also leads to a fair bit of hassle - exclusive check-outs often make you wait for a file, shared check-outs make you waste time merging and checking automated merges. It also holds up bug fixes because a one-liner fix may now have to go through the update/merge/commit cycle.

- exotic architectures: it's often quite cool to write extensive systems that make a certain complex idea possible. eg. Call a function, and have it executed on multiple servers and clients automatically, with all passed in data members correctly serialised and reconstructed. Grrrreat idea. Now try wrestling with the lengthy code needed to create such functions and the data, and the 48-page long template errors you get at the slightest typo.

- data backed by SQL databases: these give you automatic persistence, standardised querying facilities, easy ability to locate your data on a different computer to the program doing the querying, etc. All good. Now try to write a common interface for such SQL-enabled objects, get it to work across inheritance, and guarantee that the code stays in sync with the SQL statements required to create the database. I never knew adding two integers to a C++ class could take 3 weeks before, but now I do.

- using complex template libraries like Boost: as seen in recent threads on the forums, many people swear that Boost makes their life easier - and it does - but Boost also makes your compile times longer - which it does. Longer compile times can't be shrugged off as irrelevant, as the compiler is a valuable tool in checking your code correctness at the low level, freeing you to think of the high level tasks. Faster builds also facilitate running tests, whether of an informal nature or of the Test Driven Development variety. Using complex template types inevitably means inserting them into headers, and that means bigger build times, and probably a reluctance to refactor code due to this. People talk about using the pImpl idiom to help here, but let's not kid ourselves - the pImpl idiom is a workaround to sidestep problems with the language. It's extra work, no two ways about it.

All these facilities do Great Things. There's no denying it. But you pay a price. And I fear that all we're doing is shuffling the burden around rather than eliminating it.

I think the answer to some of these problem will look something like a word that starts with 'P' and ends with 'ython', but I'll go into that another time.
Kylotan
Compiling...

\Dev\GameProjects\FSProjects\FSLibs\ServerLogic\Source\Actor_ServerLogic.cpp(1435) : error C2679: binary '=' : no operator found which takes a right-hand operand of type 'double' (or there is no acceptable conversion)
D:\Dev\CoreLibs\Reflection\ReferenceMetaProperty.h(75) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=bool
]
D:\Dev\CoreLibs\Reflection\ReferenceMetaProperty.h(75) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=bool
]
D:\Dev\CoreLibs\Reflection\ReferenceMetaProperty.h(75) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=bool
]
D:\Dev\CoreLibs\Reflection\ReferenceMetaProperty.h(75) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=int8
]
D:\Dev\CoreLibs\Reflection\ReferenceMetaProperty.h(75) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=int8
]
D:\Dev\CoreLibs\Reflection\ReferenceMetaProperty.h(75) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=int8
]
D:\Dev\CoreLibs\Reflection\ReferenceMetaProperty.h(75) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=uint8
]
D:\Dev\CoreLibs\Reflection\ReferenceMetaProperty.h(75) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=uint8
]
D:\Dev\CoreLibs\Reflection\ReferenceMetaProperty.h(75) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=uint8
]
D:\Dev\CoreLibs\Reflection\ReferenceMetaProperty.h(75) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=int16
]
D:\Dev\CoreLibs\Reflection\ReferenceMetaProperty.h(75) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=int16
]
D:\Dev\CoreLibs\Reflection\ReferenceMetaProperty.h(75) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=int16
]
D:\Dev\CoreLibs\Reflection\ReferenceMetaProperty.h(75) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=uint16
]
D:\Dev\CoreLibs\Reflection\ReferenceMetaProperty.h(75) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=uint16
]
D:\Dev\CoreLibs\Reflection\ReferenceMetaProperty.h(75) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=uint16
]
D:\Dev\CoreLibs\Reflection\ReferenceMetaProperty.h(75) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=int32
]
D:\Dev\CoreLibs\Reflection\ReferenceMetaProperty.h(75) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=int32
]
D:\Dev\CoreLibs\Reflection\ReferenceMetaProperty.h(75) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=int32
]
D:\Dev\CoreLibs\Reflection\ReferenceMetaProperty.h(75) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=uint32
]
D:\Dev\CoreLibs\Reflection\ReferenceMetaProperty.h(75) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=uint32
]
D:\Dev\CoreLibs\Reflection\ReferenceMetaProperty.h(75) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=uint32
]
D:\Dev\CoreLibs\Reflection\ReferenceMetaProperty.h(75) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=float
]
D:\Dev\CoreLibs\Reflection\ReferenceMetaProperty.h(75) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=float
]
D:\Dev\CoreLibs\Reflection\ReferenceMetaProperty.h(75) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=float
]
D:\Dev\CoreLibs\Reflection\ReferenceMetaProperty.h(75) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=double
]
D:\Dev\CoreLibs\Reflection\ReferenceMetaProperty.h(75) : see reference to class template instantiation 'Reflection::G
enericMetaProperty<TProperty>' being compiled
with
[
TProperty=double
]
D:\Dev\CoreLibs\Reflection\ReferenceMetaProperty.h(75) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=double
]
D:\Dev\CoreLibs\Reflection\ReferenceMetaProperty.h(75) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=std::string
]
D:\Dev\CoreLibs\Reflection\ReferenceMetaProperty.h(75) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=std::string
]
D:\Dev\CoreLibs\Reflection\ReferenceMetaProperty.h(75) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=std::string
]
d:\Dev\CoreLibs\Reflection\ObjectMetaProperty.h(70) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=bool
]
d:\Dev\CoreLibs\Reflection\ObjectMetaProperty.h(70) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=bool
]
d:\Dev\CoreLibs\Reflection\ObjectMetaProperty.h(70) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=bool
]
d:\Dev\CoreLibs\Reflection\ObjectMetaProperty.h(70) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=int8
]
d:\Dev\CoreLibs\Reflection\ObjectMetaProperty.h(70) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=int8
]
d:\Dev\CoreLibs\Reflection\ObjectMetaProperty.h(70) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=int8
]
d:\Dev\CoreLibs\Reflection\ObjectMetaProperty.h(70) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=uint8
]
d:\Dev\CoreLibs\Reflection\ObjectMetaProperty.h(70) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=uint8
]
d:\Dev\CoreLibs\Reflection\ObjectMetaProperty.h(70) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=uint8
]
d:\Dev\CoreLibs\Reflection\ObjectMetaProperty.h(70) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=int16
]
d:\Dev\CoreLibs\Reflection\ObjectMetaProperty.h(70) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=int16
]
d:\Dev\CoreLibs\Reflection\ObjectMetaProperty.h(70) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=int16
]
d:\Dev\CoreLibs\Reflection\ObjectMetaProperty.h(70) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=uint16
]
d:\Dev\CoreLibs\Reflection\ObjectMetaProperty.h(70) : see ref
erence to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=uint16
]
d:\Dev\CoreLibs\Reflection\ObjectMetaProperty.h(70) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=uint16
]
d:\Dev\CoreLibs\Reflection\ObjectMetaProperty.h(70) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=int32
]
d:\Dev\CoreLibs\Reflection\ObjectMetaProperty.h(70) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=int32
]
d:\Dev\CoreLibs\Reflection\ObjectMetaProperty.h(70) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=int32
]
d:\Dev\CoreLibs\Reflection\ObjectMetaProperty.h(70) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=uint32
]
d:\Dev\CoreLibs\Reflection\ObjectMetaProperty.h(70) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=uint32
]
d:\Dev\CoreLibs\Reflection\ObjectMetaProperty.h(70) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=uint32
]
d:\Dev\CoreLibs\Reflection\ObjectMetaProperty.h(70) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=float
]
d:\Dev\CoreLibs\Reflection\ObjectMetaProperty.h(70) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=float
]
d:\Dev\CoreLibs\Reflection\ObjectMetaProperty.h(70) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=float
]
d:\Dev\CoreLibs\Reflection\ObjectMetaProperty.h(70) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=double
]
d:\Dev\CoreLibs\Reflection\ObjectMetaProperty.h(70) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=double
]
d:\Dev\CoreLibs\Reflection\ObjectMetaProperty.h(70) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=double
]
d:\Dev\CoreLibs\Reflection\ObjectMetaProperty.h(70) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=std::string
]
d:\Dev\CoreLibs\Reflection\ObjectMetaProperty.h(70) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=std::string
]
d:\Dev\CoreLibs\Reflection\ObjectMetaProperty.h(70) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=std::string
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=bool
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=bool
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=bool
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=int8
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=int8
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=int8
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=uint8
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=uint8
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=uint8
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=int16
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=int16
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=int16
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=uint16
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=uint16
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=uint16
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=int32
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=int32
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=int32
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=uint32
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=uint32
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=uint32
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=float
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=float
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=float
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=double
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=double
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=double
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=std::string
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=std::string
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=std::string
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=bool
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=bool
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=bool
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=int8
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=int8
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=int8
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=uint8
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=uint8
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=uint8
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=int16
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=int16
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=int16
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=uint16
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=uint16
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=uint16
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=int32
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=int32
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=int32
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=uint32
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=uint32
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=uint32
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=float
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=float
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=float
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=double
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=double
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=double
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=std::string
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=std::string
]
D:\Dev\CoreLibs\Reflection\DecoratedObjectSequenceMetaProperty.h(56) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=std::string
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=bool
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=bool
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=bool
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=int8
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=int8
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=int8
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=uint8
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=uint8
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=uint8
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=int16
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=int16
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=int16
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=uint16
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=uint16
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=uint16
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=int32
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=int32
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=int32
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=uint32
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=uint32
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=uint32
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=float
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=float
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=float
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=double
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=double
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=double
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=std::string
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=std::string
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericMetaProperty<TProperty>' being compiled
with
[
TProperty=std::string
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=bool
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=bool
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=bool
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=int8
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=int8
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=int8
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=uint8
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=uint8
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=uint8
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=int16
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=int16
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=int16
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=uint16
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=uint16
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=uint16
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=int32
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=int32
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=int32
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=uint32
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=uint32
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=uint32
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class template instantiation 'Reflection::GenericDecoratedMetaProperty<TProperty>' being compiled
with
[
TProperty=float
]
d:\Dev\CoreLibs\Reflection\ObjectSequenceMetaProperty.h(51) : see reference to class Read more...
  • 1 comment
  • 217 views
  • Kylotan

    Magical traffic

    I've had 6 or 7 people view this journal today, yet I haven't updated in a couple of weeks. This is above the normal level of traffic when it's fallen off the Developer Journals front page, so I wonder why this is. Has someone linked to it or something? It seems doubtful. If you know, leave a comment please. :)

    Of course, this post will pop it right back at the top there, so I'd better add some content.

    Currently I'm working with Python. At work, I'm embedding it into the very large existing C++ code base, without using Boost or any other pre-made wrapper. Boost has been a source of problems in the past apparently, so I'm coding this to the C++ API and keeping it quite lean and mean. Sadly nobody on comp.lang.python or the Python/C++ Special Interest Group seem at all interested in answering my questions, so I've spent more time reading docs and searching Google Groups than actually coding. Still, it's working reasonably well, and it's been a good reminder of how C++'s templates and overloading can go some way towards sanitising an otherwise awkward C API.

    At home, I'm struggling on with the Turbogears web development framework, which takes various Python packages and loosely throws them together to mildly resemble Ruby On Rails. As with many open source projects and almost all Python projects, documentation is minimal, but it's still far better than it was almost a year ago when I started out with it. Powerful yet under-documented frameworks like this are interesting, because you typically find yourself perpetually replacing your old code as you discover new functionality. This means that the finished product, while you're learning the ropes at least, often takes just as much coding as an ASP/PHP style site, but you finish up with about 1/5 of the code. That's probably good for maintenance, if you can put up with the frustration of incomplete docs long enough to get that far.
    Kylotan
    I've been arguing about object-relational mappers recently. For those unfamiliar with the concept (and unwilling to check Wikipedia ;) ), it's basically a library or class framework that allows you to use an object in an object-oriented program language and have it automatically backed by a relational database as a persistent data store, as an alternative to explicit serialisation, simplifying your code.

    My gripes were twofold:

    - one, that adding in an intermediate layer like this needs to be documented absolutely fully, otherwise you're going to hit a corner case you're unable to solve. Making the mapping library open source mitigates this somewhat as you can dig around inside to see what the problem is, but then you start to lose the transparency of the system, which is the main benefit of having it in the first place. Is it worth having wrappers that you keep needing to unwrap? Debatable.

    - two, that often what you need from the database doesn't map directly to your objects very well, which is unfortunately what the mapper usually gives you. This is (rather pretentiously) referred to as the object-relational impedance mismatch. Usually it refers to the trouble trying to represent your OO hierarchy in database form, or vice versa. But I think there's another interesting distinction, and that is in how the data is used.

    On an abstract level (think 'whole procedure' rather than 'line of code'), when an application is modifying data, it's typically modifying one object at a time. Sometimes it writes out a few sub-objects, but predominantly I'd say that you write to one object. Examples: when your library management system notes a book has been borrowed, it creates a row in a Loan database. Or when you update your game characters, you typically adjust position and AI state of each character in turn with minimal or no writing done to other characters. Generally speaking, you write one thing. When you insert a MIDI note into your music package, you're typically altering a single track.

    However, staying on that same level, when you read data you're often reading several objects at once. When the library management system checks for late loans it typically cross-references them with the Users, to generate reminders. When you perform collision detection, you often want a data structure that can instantly give you the subset of characters that lie within a certain distance, to be tested against. When you're playing back your MIDI song, it's pulling events from several tracks and parameters from the instruments and effects simultaneously to generate the output that you hear.

    SQL itself recognises this - compare the complexity of typical SELECT statements, both in practice and in what the statement allows for, with the relative brevity of the typical UPDATE or DELETE statement. Whether you consider that deliberate or an artefact of the implementation is another matter, of course.

    But this leads me to thinking: is object-orientation fundamentally a data writing paradigm and relational data (and by extension, structural data such as C's structs) a data reading paradigm? Is object-oriented querying inherently cripped by design? And is a relational database generally much poorer for editing data than for storing it?
    Kylotan
    Apparently in Windows Vista, DirectSound will no longer be hardware accelerated under Windows Vista, going through the software mixer instead. ie. DirectSound just lost the 'Direct' aspect.

    One reason for this is increased system stability, gained by moving things out of kernel space. A laudable aim, but not really an important one given that I'd think most sound drivers are pretty stable, especially compared to their GPU counterparts. Also, with MS moving things like HTTP handling into the kernel, this reason rings less true.

    Another reason, and presumably the more important one, is that Microsoft are altering the audio stream to make DRM more effective, as referenced here.

    So, many of your existing games are going to run more slowly, sound worse, or perhaps not run at all, so that MS can work with people like the MPAA to protect their interests, not yours.

    Developers can opt for OpenAL which still goes direct to the hardware, bypassing this problem. I have no idea how well supported it is, or how awkward it is to program with it. It wouldn't surprise me if it ended up being software emulated on all non-Creative sound cards. Does anybody know any more on this?
    Kylotan

    Resistance

    The primary problems I face on a daily basis with game development are often down to the amount of trouble you have to go through in order to get certain things done. Some tasks seem to be far more resistant to implementation than they ever should be, and this tends to lead to those tasks either being done poorly, or not as often as they should be, or both. This should be pretty self-evident, of course, but it's interesting to see where the bottlenecks show up.

    One example in the current project is adding a new file. Refactoring old code and writing new code often involves adding new files. But when that involves doing a full update from the version control software, checking out the project, adding the files, checking that it all builds, checking in the new files, checking in the project, and re-applying any local amendments to the global project, you tend to be wary of doing it too often.

    Similarly, localisation can be an issue. You have to think twice about adding more text to the game when that means you have to think up a unique identifier, check out the localised strings data, add in your new identifier with the associated text, run the exporter tool to update the data files, test that it builds, test that it shows the correct text, and check the lot back in.

    (It's worth noting here that these methods are imposed upon us in order to interoperate with another company.)

    It's these problems that Big Upfront Design models like the waterfall method were designed to fix. After all, if you can plan all your classes before you start coding, you won't ever need to add files to the project later. And obviously your string database can be done first too, making localisation later easier. These are examples where software development is like traditional engineering - making changes is slow and costly, and therefore should be planned for meticulously.

    Unfortunately the vast majority of software development is not engineering, and never will be. If you could rebuild a car or a bridge to make a minor change in 2 minutes, you can bet that traditional engineering would be done vastly differently. We also have to react to market and design forces more rapidly than most engineers do - some of this is a problem with management, but much of it is inherent to the industry. You have to be able to adapt to shifting requirements. Computing power can double in the time it takes to complete a project and expectations can rise with it. Software development, and especially game development, needs to be agile.

    But how do you mix developmental agility with lumbering systems that require so much effort that they actively discourage their own use? Things like source control and localisation are necessary evils of course, and there are probably better ways to do them, but there are many smaller scale issues of a similar nature, such as generation of graphical assets, getting sounds into a game (anybody used the Sony tools? ouch.), etc. I'm sure many of our problems come from the tasks that turn out to be far more resistant than they should be.
    Kylotan

    schedules

    I am starting to learn how games fall behind schedule. An external producer comes in a week before the milestone and proceeds to request wide-ranging changes to functionality that has been in and working for well over a month, which could have been looked at and remarked upon long before. That is all...
    Kylotan
    Sometimes the way a game tells you it wants you to play, is not actually how the game encourages you to play. Recently I've come across two examples of this, quite different and yet equally frustrating.

    First, Oblivion. This RPG scales monster difficulty roughly in line with player level, to keep the game challenging. Player level rises to follow usage of the player's major skills, and is independent of usage of minor skills. For many players, this works ok, but for many others, rises in major non-combat skills result in the monsters growing stronger more quickly than the player does, making the game harder, even when travelling in areas that were previously safe. Ultimately, the player is forced to emphasise use of their minor skills, or to stop electing to level up, in order to stay competitive - surely not what the designers had in mind. Scaling monster difficulty according to player success as opposed to player level is one way they could have improved this. Or they could have stuck to the geographically-bounded difficulty levels that work well in most other RPGs.

    Secondly, Empire Earth. This RTS attempted to bring more tactics to the genre by adding explicity Rock-Paper-Scissors mechanics to the game. Spearmen beat shock troops (range advantage), shock troops beat archers (shock troops carry shields and can chase down archers), and archers beat spearmen (spearmen cannot block missiles). All well and good in theory. However in practise - at least in the single player scenarios - the opponents tend to come at you as one heaving mass of all three unit types, meaning you may as well do so as well, or just pick one type arbitrarily, and hope for the best in each case. This mechanic might well work a lot better in games like the Total War series, which give you more time to manoeuvre individual troop types. Maybe it works better in Empire Earth 2, as well?

    It's a shame when actual gameplay doesn't match the implied 'correct' gameplay as directed by the overall system. It implies a design element that wasn't fully thought out to the degree where it would be guaranteed to work.
    Kylotan

    Developer publicity

    I am very wary of comparing games to films, especially since the analogy is often used by (typically inexperienced) designers to argue that story is more important than gameplay, or used by clueless journalists to complain about the graphical quality of a computer game or the poor acting within one. But there is one key aspect of the film industry that the games industry really needs to address, and that is the way in which it publicises and promotes the creators of the work.

    Genre aside, I'm going to claim that films are usually sold and promoted on two 'features': the actors, and the director. For the average person, the actor is probably the main focus point. It often tells you quite a bit about the kind of film you'd be seeing - eg. Vin Diesel or Hugh Grant... which one is most likely to be in a romantic comedy and which one is most likely to be crushing heads with his pectorals alone? And obviously people have actors they think are better or who they like more for whatever reason.

    Then, arguably for the more discerning viewer, you have different directors, who again tell you a lot about the sort of film you'll be seeing, but also how you'll be seeing it, as each director has ideas about the amount of dialogue they use, the sort of cinematography they like to employ, the types of actors they will bring to a production, and more.

    For the average viewer, the combination of actors and director is the most part of the movie (arguably the screenplay is a close 3rd, though the director often has a big hand in that too). Hence their prominence in advertising, and in other
    promotion. You rarely go to see a film without knowing who is in it or who directed it.

    Yet with games... all you tend to hear about is the publisher. How often I've heard about the new game from Eidos, EA, Infogrames, Microsoft, or some other publisher, when they don't contribute anything of significant creative worth to the process. Sometimes admittedly they actually buy up the studios in question so you can argue that they have the right to call it 'their' game. But either way, what you still have is a marginalisation of the creative workers in favour of those who hold the purse strings.

    This in turn allows the industry to continue as if all that matters is intellectual property and the publishers that own it. How are we ever going to see more creativity when the people who come up with that creativity are never acknowledged? Worse still, what about when those people are sidelined and the publisher pushes the intellectual property onto someone else? How many people really think that Thief 3 played as well as Thief 1 and 2, after Eidos liquidated Looking Glass Studios and gave that property to Ion Storm Austin?

    A recent example here in the UK is that of football (soccer) management simulators. The first one, to my knowledge, was a simple game by a man called Kevin Toms, called simply "Football Manager", now 24 years old. Later on came similar games like Premier Manager, and Championship Manager, the latter developed by people who went on to form the Sports Interactive company. Championship Manager and various sequels was happily published by Eidos for quite some time. Eventually the relationship seems to have broken up, but because of the perverted nature of the industry, Eidos get to keep the brand name. Hence, we have Championship Manager 2007, developed by someone else entirely. Look at the website; can you see which creative people were behind it? Keep looking - there's some small print at the bottom, light grey on dark grey, listing a developer's name after the publishers. They don't even get their own logo displayed as a reward for all their hard work. Obviously Eidos are not keen to emphasise the developers because then people may realise that it's not the same people who made the previous Championship Manager games. As for Sports Interactive, their new endeavour is the Football Manager series. At least Sega let them keep their logo on the front of the package. But of course, this 'Football Manager' has nothing to do with the original 'Football Manager', not that any but a few oldies like me would remember the original.

    But can we keep going on, disregarding the unique and individual efforts of developers worldwide, treating them as if the intellectual property they devise and implement is worthless? Can we ever expect the industry to be anything but sequel and hype-led when we yield up our creations to publishers to be doled out to whichever interchangable developer best suits their bottom line? At the very least, consumers deserve to know who is actually making these games for them.

    EDIT: More games I thought of where the IP has been passed on to someone else apart from Thief and Championship Manager seem to include Fallout, and The Bard's Tale. Anybody got any others? I bet there are many around.

    2nd EDIT: Tomb Raider, Might and Magic, Myth...
    Kylotan

    Inspiration

    The more I work on 'real' games (and it's only been a little over a month so far, I admit), the more it makes me want to get back to working on my own stuff as well. Don't get me wrong, I love the work I'm doing. But like it or not, we all know The Industry is a slow moving monolith that doesn't offer immense scope for creativity, especially not for programmers. After all, even small houses like ours need to get funding somehow, and that tends to filter down from the bigger players.

    Besides, I'd love to put the new skills I've acquired into practice in some of my own projects which never got completed. When you see 'professional' code, you realise 2 things, seemingly opposed but yet perfectly intertwined:
    1) Some of it is really elegant. This educates you on how to achieve the same effect yourself.
    2) Some of it is really ugly, but works just fine. This gives people like me encouragement to stop worrying about perfect program structure and to get the game done, whatever it takes.

    Anyway, in the near future we're likely to find that independent games can really take off over digital distribution channels, and although the amount of money spent on such games is going to be smaller, the slice of that pie which goes to the developer is an order of magnitude higher. Working on smaller games with an emphasis on creativity and design rather than AAA polish would let you create several in the time it would take for a normal game, giving you more of an opportunity to hone your craft, refine your re-usable code and assets, and make a name for yourself with published works. This is definitely something I'd like to look at in the future.
    Kylotan

    Oh dear

    Myself and a co-worker are working on a contract for another company, so we have to work with their code and base a lot of our work on it. Today we had to examine one of their files in order to see how they're implementing a certain feature - all well and good.

    But during execution, the game froze in their code. We check the debugger - it claims it's still running - no crash, no assertion, no breakpoint. We pause it, then hit 'step out of function' to try and work up the call stack. We find a call that never exits. Hmm, infinite loop, we think.

    No, the truth is much worse. At the end of the function, a single statement stands alone:

    goto reloop;


    "I'm gonna need a beer before I debug this!", wails my colleague, who heads off to the kitchen.
    Kylotan

    Status update

    Ok, so, some of you may be interested to hear that I'm in the industry now. Developing games, that is. The 'real' stuff, too: not mobile phone downloads or Flash downloads, but PS2 and PSP games. I even have the 2 devkits on my desk to prove it. I have docs for cool middleware like Renderware, Havok, and SpeedTree, and they make for interesting reading.

    It's kind of weird finally being here after years of thinking it would never be possible, then a year or two of knowing it was possible and not being interested, and finally ending up 'here' anyway.

    I can't say what I'm working on, for the usual contractual reasons. But it certainly beats finance software, I'll say that much.

    (PS. Sony's documentation is Not Very Good.)
    Kylotan
    Here, another poster mistakes games for movies. Nothing against that poster: he's obviously new to things and it's an understandable mistake to make. This is something I used to see a lot of in the Game Design forum, where lots of wannabe film-makers see computer games as essentially being movies, with just a few tiny insignificant differences - such as managing a team of programmers, hardware specifications to meet, performance considerations, control methods and interface design, robustness, etc etc. They want to write a story for the players to enjoy, and the fiddly irrelevant technical stuff can be handled by the programmers. It's not important, anyway. Story is all!

    I've been reading a book by fantasy author Terry Brooks called 'Sometimes the Magic Works'. He relates a series of useful hints for authors based on his own experiences, which include writing the tie-in book of the film for 'Hook', and later 'The Phantom Menace'. His experience was that the writing of a book is absolutely nothing like the process of making a movie, and that his expectations as a writer were hopelessly wrong when applied to movie-making. Yet fundamentally, they are both forms of passive, linear, closed-ended entertainment, quite similar when looked at from the outside.

    So if those forms can be so different, how can anybody expect to equate movies to games - which are active, and often non-linear and open-ended - and expect to be taken seriously?
    Kylotan

    Disillusioned

    At the moment I am getting a bit fed up of the way some open-source projects are getting developed.

    First, Mozilla Firefox. I love the browser and couldn't use IE again. Opera is faster and less resource-hungry but lacks many of the nice extensions I've come to love in Firefox. But damn, the Firefox development process is abysmal. The latest idea is to merge in to the nightly builds what they're calling 'Places' functionality, which on the surface is a handy combination of bookmarking and history, working on the the Google (or Web 2.0 if you're up with your buzzwords) mantra of 'search, don't sort'. All well and good, except the interface and most of the functionality is horribly broken. This might be acceptable for many nightly builders, except it didn't need to be broken so badly before they removed the other functionality. Of course, they merged it into the more stable development branch when it is still throwing up about 10 new bugs a day due to the shoddy state that it is in. Someone needs to tell the Firefox developers that test driven development does not mean writing something that's half-finished, then giving it to your testers to see how badly you've broken it. When using development builds I expect bugs and I expect unrefined features, but there is no need to break things so spectacularly when changes can be done incrementally.

    The other subject of my ire is TurboGears, a Python web framework I mentioned before, which originally caught my eye because it brings together several other well-known libraries into one whole. Unfortunately, it spectacularly fails to document exactly how it does so, instead relying on the growingly-trendy Quicktime webcast video to convince you of how easy it is to use, and some very contrived examples that don't do anything interesting or useful (such as validate HTML form submissions). In response to the lack of documentation, the usual answer is "use the Google Group to ask for help", but unfortunately most of the people on there are bleeding-edge source readers who've all moved on to the alpha of the next version anyway, so you get little help. This is presumably due to the poor documentation weeding out anybody who was going to stick with official releases or who doesn't want to trawl through the code anyway. The end result is that although you can allegedly write a wiki in 20 minutes using Turbogears, doing something else like a simple login page can take hours while you wait for someone to point out which deeply-buried piece of the API you're supposed to use to achieve a certain goal. Grr!

    Documentation matters, people. I don't expect a full user manual with everything you write, but seriously, I'm sure that some people write these so-called 'tutorials' and don't even read through it afterwards. If they did, they'd spot the unreasonable assumptions they tend to make throughout, expecting you to know all sorts of things that you shouldn't need to know in a tutorial.
    Kylotan

    Article writing

    It's been years since I had that 'Organising Code Files in C and C++' article published, so I think it's time I wrote another. Out of the following choices that appeal to me at the moment, what would you think would be most interesting or useful to Gamedev readers?

    - "10 Reasons to write your next game in Python" - basically a language advocacy thing, although I intend making it factual rather than opinion-based. Cool snippets would be the major feature here, showing improvements relative to C++ and Java.
    - "Basics of Game Programming" - are there any articles explaining simple yet important things like what to put in a game loop, state handling, resource management, etc? I've not seen one, and maybe one needs to exist.
    - "Designing Combat Systems" - I am fed up of seeing posts asking about how to write combat/experience/statistics systems for an RPG or RPG-like game. I'd like to go over some examples from other games and throw in some probability/statistical theory for good measure, so that people can develop balanced games without either immense trial and error or ripping off someone else's rules.
    - Something else - any better ideas? My other area of interest is AI in the non-academic sense but I don't know what to write about there.
    Kylotan

    Documentation woes

    I use a lot of free and open source libraries, and the main problem I find with them is documentation. Strangely, it's rarely that there's a lack of documentation, but more commonly that the documentation provided is inadequate.

    The typical incarnation of this is where someone has processed their entire source code with Doxygen or something like that, in the almost completely misfounded belief that an unordered list of function names and objects is enough information to get started. It is much like giving someone 100 identical keys when they ask how to unlock a certain door. Why make them dig through the whole lot? Anyone with a decent IDE (or a reasonable command of their toolchain) can look up function names and parameters in seconds anyway. Providing an HTML interface to it all seems largely pointless unless you're going to add value with diagrams and so on.

    Today I came across something less common - the opposite extreme, where the authors have gone to lengths to ensure that you have an easy and well-worded tutorial, yet have seemingly forgotten to provide any sort of useful reference that doesn't involve reading a long block of prose. My culprit for today is the Lua documentation. The reference manual is okay, but feels disorganised. To find something within, you have to look at the table of contents, pick a likely-looking topic, and hope for the best. I wanted to put one table inside another using the C API, and had to chase around several sections before discovering that what I needed was elsewhere on the web. Lua also has a lot of very helpful functions in the auxiliary library, which aren't documented properly anyway. This is somewhat ridiculous as they make life so much easier, but I digress. There is not even an index where you can look up function names to see exactly what they do. So whereas other documentation drowns you in detail and leaves out the big picture, the Lua docs give you their big picture but don't tell you the details of how to draw your own picture.

    So, what do I think documentation needs? It's quite simple:

    1) Tutorial/Overview. I want to be told what the software does, and ideally be given some short sample code illustrating exactly how it does it. Talk me through it line by line, so I get a feel for the interface, and can see how I might modify it to suit my needs.

    2) Hierarchical description. Give me a table of contents where the functions and classes are described, arranged according to sensible groupings of functionality. This allows me to translate a task in my head to a relevant section of the documentation. No function or class should be omitted, least of all convenience functions. No function should be described without an example. Even if that example is just an uncompilable snippet, it's still better to see it in context. All functions and classes in a section should be summarised together at the start of that section with a one-line description for each. You should be able to drill down from the top level (seeing which module you want) to the sub-section (seeing which function you want) to the individual function (seeing which parameters you need). Feel free to generate this automatically from the code providing there is a clear and obvious hierarchy. Most automatic doc-generators do not do this at all. (Or perhaps I should say that nobody is using them in such a way.)

    3) Index. After a while I will vaguely know about the existence of functions or objects but will not know precisely what they do. I may have a rough idea that they might be useful to me, or I might just be interested in finding out for future reference. But if I don't know what they do, I cannot look them up in the table of contents. So an alphabetical index is vital. Don't make me wade through your tutorial again to find the one place where you used that function.
    Kylotan
    When it's just a fancy name for a bit of terminology, that's what. Somehow, especially in game design rather than game programming, people have seized upon the idea of design patterns and decided that a design pattern is a formalised name for a concept we see often. So we get articles like this one over at Gamasutra which just treats game design patterns as glorified ways to talk about vague elements of gameplay.

    Design patterns are not just formalised names. We already have terms for that: jargon, or more charitably, terminology. Standardised terminology is a good thing but we can do better than that. From fields of psychology, statistics, mathematics, drama, and literature, we can come up with theories of gameplay that not only describe a concept but explain how to model it, what it achieves, what the downsides are, and give abstract implementation hints. Let's not fool ourselves into thinking that game design is some mystical and indescribable quantity. Any other artist knows that there is some method behind the madness, so why don't we?
    Kylotan
    I posted on this about a year and a half ago, complaining that the state of Python web development wasn't moving forward in the correct way, and that the developers of various web frameworks were all resistant to change because they wanted to protect their work.

    Well, to an extent I've been proven right, and these products have largely been sidelined in favour of a new paradigm. The Ruby programming language is often compared to Python as the feature sets are incredibly similar. So when Ruby On Rails came out, leading Tim O'Reilly to claim that with it, 'Powerful web applications that formerly might have taken weeks or months to develop can be produced in a matter of days', Python users were left scratching their heads, wondering why the Python equivalent didn't exist yet, despite Python being the older language with the wider and more mature user base.

    My opinion on the matter is that too many Python developers have traditionally been convinced that Python is a better Java, merely because they seem to have come from a Java background - as perhaps most people do these days - rather than because of any compelling similarity between the languages. So all Python web frameworks have looked much like the overblown Java ones, meaning they miss out on the simplicity that Python can offer.

    Obviously Ruby had raised the bar, and then Python developers finally stepped up. As a result, we now have 3 serious contenders:

    There is rumour of 2 of the above combining, which could potentially create a de facto web development standard for Python, which has been a long time coming.

    Some of the functionality of these systems is built out of the best parts of the previous myriad of competing web systems, but the idea is to make frameworks that are clean and easy to use, yet potentially powerful, just like the language they're written in. Check them out.
    Kylotan

    CVS

    We're using CVS at work, which I always thought was a good idea, until I had to work with it for a while. Basically, in order to change a part of your project, you have to ask for the latest version from the server, make the changes, document what changes you made, and then resubmit it to the server. The idea is that the server can track your changes and undo them in the event of a mistake, and ensure that two people don't accidentally edit the same file in different ways at the same time.

    Unfortunately this tends to mean that you feel obligated to take a file, make the smallest change possible, and then check it back in quickly. You do this because the longer you keep files checked out, the more chance of finding that someone else wanted to change them while you were using them, and the more changes you make, the harder it will be to merge your changes with someone else's in the event of that happening. So instead of effective refactoring that makes the code much better to use in the future, you tend to get lots of isolated little hacks, fixing the symptoms but making the code less and less maintainable. The codebase ossifies into a fragile state.

    On the other hand, you're reluctant to make small changes such as fixing typos or renaming variables, as the update/commit/document overhead takes too much time. Call me lazy, but it gets tedious writing a 2 sentence summary for why I used a single search and replace.

    So what are the options? Here are my somewhat uninformed thoughts:

    1) Use more files - if your project uses lots of small files rather than a few big ones, you have fewer sharing conflicts and can feel safe in making larger changes. Downside - the project probably gets unmanageable quite quickly this way.

    2) Use CVS differently - for any large fix, you could reasonably create a branch for that fix, work exclusively on that, and then merge it back into the main trunk development. I expect this works well, but in my opinion still neglects a category of fix which is too big for a quick edit but too small to justify creating a temporary branch of your project.

    3) Use better tools - if your editor or IDE handles CVS checkins/checkouts automatically, I expect the overhead issue diminishes to nearly zero. I don't have this luxury unfortunately. And documenting the small changes may still be a hassle even with tools to manage the file handling processes. Does Subversion improve significantly over CVS in this area? I have no idea.

    4) Use fewer developers - this may sound strange but I think it has benefits for the wider process anyway. In this context, fewer developers mean fewer concurrency conflicts and less dependency on having the latest version of the code at each step. Obviously with fewer developers you then have to 'work smarter' to get the same amount of work done, but there are many ways I think you can do that (which I may go into one day).

    Sign in to follow this