Jump to content

  • Log In with Google      Sign In   
  • Create Account

Calling all IT Pros from Canada and Australia.. we need your help! Support our site by taking a quick sponsored surveyand win a chance at a $50 Amazon gift card. Click here to get started!


Ravyne

Member Since 26 Feb 2007
Offline Last Active Today, 07:52 PM

#5249394 What do you guys use as a key in RPG data structures?

Posted by Ravyne on Today, 12:15 PM

Just to be clear -- decorator is not a good choice to use for making permanent (even semi-permanent) changes to the decorated object -- decorator is a decent pattern when you want to temporarily change something about an object who's original form you want to retain. In the context of an RPG, decorator is a reasonable pattern for, say, status effects like curses or time-limited spell effects -- its a reasonable choice because in both cases you want to restore the original object when the curse is removed or when the effect of the spell wears off. In the context of an RPG, decorator is not a reasonable choice for leveling up a character or item, or for affecting any permanent/semi-permanent change to the affected object itself (for example, decorator is a poor choice for modeling a weapon's decreasing durability as its used.)




#5249387 AI for NPC

Posted by Ravyne on Today, 11:51 AM

Unless you plan on doing something very novel, I'm not really aware of any game-style AI that would be even slightly interesting as a master's thesis. Game AIs and classical AIs are different beasts. AIs that learn to play games are a different matter, but doesn't sound like what you're doing.

 

Have you met with your adviser yet to discuss your thesis proposal?




#5249376 Advice on weak_ptr usage

Posted by Ravyne on Today, 10:19 AM

I tend to agree that this is something of a design smell, but your functional use of weak_ptr is more or less correct -- weak pointers can be used when you need to share an object among observers who do not need to keep the observed object alive; that is, they can deal with it if the object dies (for example, they can then reacquire a new instance of what was observed). Again, design-wise this seems less than great, but functionally you're using weak_ptr in one of the ways it can be used.

 

A more typical use of weak_ptr is for breaking referential cycles (two objects have a shared pointer to one another that prevents either from ever being destructed) -- by using weak_ptr, destruction is not prevented and the cycle is broken.

 

A better pattern for what you're doing might be to pass in a network instance to a per-object network handling function inside each object (or the inverse, pass objects per-frame into a network object).




#5248837 What do you guys use as a key in RPG data structures?

Posted by Ravyne on 25 August 2015 - 01:26 PM


- There are "attack" objects, which all inherit from a base attack class (and may be composed of some other things in the future)—they do all the calculations given a character's stats and some damage multiplier. This will make it easier to give specific characters specific abilities. When performing an attack, one of these objects is created, passed to an attack-event, and an attack-handler applies all the appropriate damage. 

 

Sounds reasonable -- just beware the urge to derive a new object for each kind of attack. As a rule of thumb, strive to keep the number (and especially the depth) of derivations small. The basic approach in this case would be to only make a new kind of attack object when the attack formula is different -- by this I mean the actual shape of the formula, not just having different constant factors ("weights" or "multipliers") -- those can be passed into the constructor of the Attack.

 


- Items have the same attribute-map as characters. When items are equipped, an iterator just adds the appropriate item stats to the character stats by key (equipping, picking up items, etc. is actually handled by a handler, too, since it requires things like removing an item from a room and putting it in the character's inventory.)

 

Again, the idea is reasonable. There are a couple ways to approach this that immediately jump to mind. If most equipment/status-effects effect only one stat, then it might be better to have a list of such things (e.g. built up by looking at currently-equiped items and active status effects) and playing their effect on a copy of the player status object. This is fairly simple (its something like the Command Pattern). If many equipable items/status-effects effect multiple stats, then it might be better to have a list of 'filters' which derive from the stat object and "wrap" another stat object (the player stats at the root, or another stat filter) to present a filtered view -- in that way they can be chained together to apply stacking status modifiers (its something like the Decorator Pattern). In either case, an attacker might be allowed to have their own modifiers (say, a certain enemy type removes or reduces magic resistance, even that due to equipped items).

 

I still say that a map of strings-to-integers is both overkill (provides dynamism of stat names and number of stats you're not using and don't seem to need), and too limiting (all stats can only be integers), but you might have reasons that aren't clear, or might just be more comfortable with what you have. If it were me, I'd have a struct/class representing stats (or stat-packs, if different entity types or characters might have different sets of stats). You might be aiming for the flexibility to add unknown stats at a later time, but unless you want to be able to invent new stats at runtime (e.g. your 'game' itself is just configuration/data) the unused flexibility probably imposes more headache than you gain back in utility.




#5248784 What do you guys use as a key in RPG data structures?

Posted by Ravyne on 25 August 2015 - 09:56 AM

Performance wise, its unlikely you'll be accessing these stats often enough for the key type to make any real difference; the bigger issue is probably that the 'fuzziness' of using strings (or, say, integers, for that matter) can allow unintended mistakes to happen silently. Probably you will catch most of these errors quickly but its often better to have the compiler help you, as it could with an enumeration. But like all things this is a trade-off and your needs/perspective counts for the biggest part, maybe you need the flexibility that a set of string-int key-values provides, in which case this is a fine solution -- the task of an engineer, though, is generally to meet requirements with the simplest and safest machinery that does the job.

 

So, if you're not being dynamic at all (that is, neither the names of the stats, nor the number of overall stats is decided at runtime), then what you really want is a structure or class with a member for each stat. That does away with the need for an enum/key entirely (though you'll still might need to map between the members and an ID--that might be string-based--in, say, loading code.) Not only is this more concrete, but you can also choose, for instance, to have stats of different fundamental types. For instance, perhaps its more natural to express an all-up combat bonus as a float, or to express immunity to magic-based attacks as a hard yes/no using a bool. The fact that most RPG systems are integer-based is because they stem from pen-and-paper games that used dice and simple math (not even D&D nerds want to math harder than they have to), but there's no reason you have to with a computer simulation.




#5247726 default install folder for windows game

Posted by Ravyne on 19 August 2015 - 01:38 PM

well, everything in one directory does have some advantages during development. i can run the game straight from the release folder - don't have to install or update first. i can test install the demo to \program files(x86)\caveman3 without interfering with the version in the release folder - IE two completely separate installs with their own settings. also, everything in one folder makes it easy to find stuff - no chasing through folders to the right subfolder for some particular file type, etc. i can get away with it due to the relatively low number of assets in the game due to heavy reuse. example: all humans are implemented with just 10 skinned meshes and about 10 hair meshes.

 

but for end users, none of this "all in one folder" stuff is really necessary.

 

As irksome as jumping through those hoops are, you would probably be best jumping through them. The primary reason for this is that you ideally want to mimic how your users will be using the game as much as possible -- that means without elevated privileges (preferably, not sure if debugging makes this impossible) and with a filesystem layout that's identical to the final form. You'll find bugs that way that you're otherwise leaving your users to find, and when you do find one, you'll actually be able to trace through it on your own 'install' rather than trying to guess at it based on a bug report.

 

If you have regular, formal testing of your app through other mechanisms that do mimic an installed environment then you can lean on those, but I still think its a good idea for a serious project. You don't have to go through a whole uninstall/install every time (though, its worth mentioning that more games should more rigorously test their installer and especially their *uninstaller*) -- you can write a shell script to copy your game from its project build folder structure into its final structure and just call that script as a post-built step. (Using a script is a good idea anyways, since it makes the process repeatable and also serves as a kind of documentation that will be helpful when you do create the installer proper.)




#5247592 Pointer Clarification

Posted by Ravyne on 19 August 2015 - 02:06 AM

The benefit of using pointers is that they give you a level of indirection -- its often handy to know where to find a thing without having to have the actual thing with you, carrying it around all the time. To you as a programmer, a variable that's a pointer is basically an address with a name, and in most programming languages, having a name for something grants you the power (potentially) to change it.

 

So, for example, a pointer can be null or it can be a valid address -- that's a crude but useful mechanism for saying "Either I have no information (pointer is null) or I have information and its located here". A pointer (an address with a name) can also be changed -- that means it might point to one thing at one point in your program, or to a different thing at a later time -- by dereferencing a pointer (dereferencing collapses a pointer into what it points to), you essentially have a single name for different objects at different times in your program -- for example, say that your protagonist character can target single enemies and track their movement; a pointer can point to Goblin A now, and Goblin B later.

 

Another thing you can do with a pointer is increment and decrement it to look at an adjacent object of the pointer's type -- this means, for example, that you can start at the beginning of an array and walk towards the end looking at each element, and you can do that without an indexing for-loop (maybe you want to use a do or while loop.

 

Pointers are also lightweight (almost always a machine word, so 32 or 64 bits) compared to many classes or structures you might use or write. If you were to pass parameters of those heavy types by value (not using a pointer or a reference) then you copy the whole thing pessimistically (you pay the cost of copying even if you don't actually use it later) -- but if you pass those heavy types by pointer or by reference, then you only pay the small cost of copying the pointer instead -- later you can use the pointer to find the thing and you can look at it where it stands (no copying) if you don't need a unique copy of it; you can make a copy of it if you need, but you only pay the cost of doing so when you do.




#5247435 Windows 10 Game Programming

Posted by Ravyne on 18 August 2015 - 12:12 PM

Seems like a good place to share --

 

If you want to do WinRT (Windows 8 and 10, universal apps) using C++, a Microsoft MVP named Kenny Kerr has created a 'pure' C++ (that is, C++11/14, not C++/CX) library that provides a projection of the library surface. Basically, it performs the function of C++/CX (and then some) without you having to resort to using C++/CX and its funny 'hat' operators to do the reference counting, through careful use of move/copy semantics to manage lifetimes (though that description is a simplification I'm sure).

 

That library is called Modern and its available on Github. I highly recommend this option over C++/CX for those who prefer C++. Those who use C# or other .Net languages should use the standard projections for those languages.




#5246336 D3D12 atrocious performance

Posted by Ravyne on 13 August 2015 - 05:58 PM

In general, the rule of thumb consensus seems to be this:

 

In D3D11 and prior, *late decisions* were good because you had the most information with which to batch effectively to minimize state changes.

 

In D3D12 (and other new APIs) that's turned on its head -- you want to set down decisions as soon as you can practically make them, and re-use them as much as possible.

 

 

This especially means that naively porting D3D11-optimized patterns are a recipe for disaster on D3D12. Here's a presentation from Sigraph 2015 about Unity's experience bringing their engine forward from D3D11/Classic-GL style towards D3D12-style: http://aras-p.info/texts/files/201508-SIGGRAPH-PortingUnityToNewAPIs.pdf




#5246293 Is Javascript easy if you know basic C++

Posted by Ravyne on 13 August 2015 - 01:53 PM

 

Is Javascript easy if you know basic C++


Yes.

If the average Web programmer can use it then any quasi-sentient life form should be able to pick it up pretty quickly.

 

 

I know this is a snarky answer, but that may not be so apparent to OP or other less-experienced folks.

 

All non-trivial programming is hard. Sometimes because the problem is hard, sometimes because the solution is necessarily large or complex, but always because hundreds, thousands, or millions of things can go wrong. There's a lot of moving parts rubbing against one another, and they all have to move together. There are languages that make certain kinds of programming easier, but there is no language that makes programming easy. Javascript is not popular or widespread because its *easy*, its popular because it is *accessible and necessary*.

 

Aside from the differences of dynamic and static typing itself, the next biggest difference, IMO, is that because it is statically typed as a language, a C++ compiler can and will detect many errors before a program is run -- if the program compiles, you're reasonably sure that it does something legal and sensible, though the results may be incorrect and there are some problems (like integer overflow at runtime, for instance) that a compiler won't catch or warn you about. Javascript, on the other hand, is dynamically typed, and so all the error detection that flows from static typing is right out -- a javascript program will always run until it finds that the circumstances of its execution have become untenable. There are no warnings; there are no errors, except those that happen at runtime in the wilds. To make up for this, there are extra tools you can run to help catch errors by pre-validating javascript code to the degree that its possible in a dynamically-typed language (e.g. JSLint), but mostly javascript must be systematically and rigorously tested as a condition of each build pass-fail. This kind of tooling is the only thing that stands in the way of you pushing buggy javascript out to the world. Of course C++ should also be tested, but many of the most important tests are essentially built into the compiler, where they happen as a part of any nominal build.

 

Another big difference between C++ and Javascript is that, again due to a lack of static types, there is no such thing as a real "class" as you're used to from C++. To be clear, its the difference from what you're used to (and the sometimes oblique method of creating class-like objects in javascript) that is at issue -- its a perfectly serviceable way of doing things, and has its own merits, its just very different. An object in Javascript is essentially just a bag of stuff -- you might only put one thing in it at a time, and so it acts like that thing, but you might put more things in it. If you use array-index notation, it looks something like an array (but different indexes can hold different kinds of data because there is no strict typing). If you use the 'dot' notation it looks something like a structure, and those somethings can indeed be functions. That's how you build a class in JavaScript -- When you want to create lots of those 'classes' you write a function to perform the necessary steps, which is like a constructor in C++, but its not part of the 'class' itself and its not special. Also because of dynamic typing, an instance of such a 'class' is not sealed -- you can keep adding data and functions, delete, or replace them at any time. Again, this has its own merits, but its very, very different than C++ or C# or other statically-typed languages.

 

The final big difference I'll mention is scoping -- In C++ things like if/else, do/while, for-loops, etc. create new scoping blocks for named variables -- you can even create a scope any arbitrary place just by throwing down a pair of curly brackets. This is not true in Javascript, where there is only a global scope and function-level scope -- a named variable inside a for loop doesn't alias the same-named variable at function scope, but it does alias a same-named variable at global scope, as does any variable inside a function alias a same-named one at global scope. Again, this has its own merits, but its very different than what you are used to, and javascript gives you no warnings about it (JSLint will, though, which is why its important).

 

If you want the flexibility and portable ubiquity of javascript, but retaining the familiar structure of languages that you are used to, I recommend you to check out some languages that compile down to javascript. Typescript is my favorite, but there's Dart, CoffeeScript, and others.




#5246030 How to do sprites like this?

Posted by Ravyne on 12 August 2015 - 11:59 AM

Right -- its practice, practice, practice, as well learning about how the old masters did it, and often a good dose of color theory (either formal or intuitive). You can get the latter two from the internet if you care to look, but you'd have to deal with the first the old-fashioned way.

 

Having a pixel-art program helps, especially for artwork using a limited color palette. I like Cosmigo Promotion, but there are others like GraphicsGale, and you can configure programs like photoshop, the Gimp, or Paint.NET for that kind of workflow if you know how (google it). By default, most popular graphics packages today  that aren't explicitly pixel-oriented are set up for photo editing or larger-format, high-color, high-DPI digital painting, which isn't suited to pixel work; you'll have to reconfigure them before they're useful.




#5246026 Data oriented design and rendering

Posted by Ravyne on 12 August 2015 - 11:49 AM


This encourages the "AoS" pattern. Before issuing a draw call, it forces me to upload a buffer of "Vertex" on the CPU, which is the opposite of what I want. Would shader performance be the same if I split the buffer in the shader into 3 StructuredBuffers, one for each vertex attribute? Am I doing all this for nothing in the end?

 

What you're finding out is that the vertex -- whatever that means to your render code -- is the natural atomic unit you're dealing with. You wouldn't split its normal from its position and more than you would split X from Y in a position structure.

 

DOD isn't about blindly decomposing things to their basest elements, its about understanding what elements are used strictly (or almost-so) together. You probably could decompose it if you really wanted, but I'm not sure it'd be worthwhile.




#5244989 GCC auto vectorizer alignment issues

Posted by Ravyne on 07 August 2015 - 11:44 AM

If you're relying on this code to be performant, and you have the resources and skills, then you really want to look at vector intrinsics (or, linking a vector routine written with... I forget the name, but its a vector-aware C-like compiler, or perhaps an assembler, depending on which of those dependencies is more comfortable).

 

auto-vectorization is great when it works, but it should generally be viewed as a bonus -- its brittle against reasonable code changes (that is, innocent-seeming changes can break assumptions the compiler relies upon to be sure it can vectorize safely), and as you are seeing it often doesn't pick up on what we intend to be obvious (ie the straight-forward approach) without superfluous hints -- you end up adding this meta-code that only serves to inform the compiler, as the solution is already described, and this is in some way a violation of the DRY (don't repeat yourself) principle; for example, a change in the "working code" could disable vectorization without a corresponding change in the meta-code.

 

As my own personal rule of thumb, if auto-vectorization takes any more effort than marking things for alignment and with restrict and such (that is, if it requires the kind of meta-coding I've been talking about) then its probably better written using something other than the auto-vectorizer. If its something that pops on a profiler, then it definately gets written using something other than the auto-vectorizer. For myself, auto-vectorizer is acceptable when I either lack the capacity to use something else effectively (a lack of time or skill) or when, with minimal effort, I can gain from it but am not relying on it to make framerate (e.g. usually something off the critical path).




#5244862 default install folder for windows game

Posted by Ravyne on 06 August 2015 - 01:24 PM


yes, but then you lose the "everything under one folder" convenience.
 
guess that's the price you pay for doing it the microsoft way...

 

Its Microsoft's flavor of the same UAC rules all platforms have in one way or another. Its not about bending a knee to Bill Gate's whims, its about your program being a good citizen to the machine it shares with other programs, other users, other users of other programs, and to the OS itself. We don't live in a singe-user-assumed-to-be-admin world anymore. Windows through XP got UAC wrong -- Vista actually got it right, more or less, though it got a bum wrap for experiencing the growing pains of all those existing windows programs poor (but perfectly acceptable by previous versions of Windows) habits.




#5243316 What skills is more important for a Junior programmer to master

Posted by Ravyne on 28 July 2015 - 09:45 PM

Totally -- that example is a good showing for dealing with all the moving parts and overcoming the challenges in doing so. Your samples have to not just be 'done' to some arbitrary degree -- they really should be polished. They don't need to be dressed like a million bucks, but a sample needs to carry itself like a million bucks -- have terrible graphics and even worse sounds if needs be, but the sample needs to be put together in a way that's polished and complete.

That said, don't let perfect be the enemy of good, and don't be intimidated. This is something to always strive for, and its not unattainable, but neither is it something that should prevent you from pursuing opportunities for lack of living up 100% to this gold standard.




PARTNERS