Jump to content

  • Log In with Google      Sign In   
  • Create Account


Member Since 12 Mar 2005
Offline Last Active Today, 01:41 PM

#5290463 Is it C# Territory?

Posted by frob on Today, 01:16 PM

Hoping not to derail too much, I'll make the comments then go back to the original topic.

Majority of specialized 3rd party libraries such as graphics APIs and geometry processing are built using C/C++. Writing a wrapper is another project especially if the library is big and complex.

Interop in C# does have a tiny cost, typically a single-digit number of nanoseconds, but it is not as difficult as you suggest. Generally C# can access a C++ library with either no additional work as a compiled library with exposed calls, or a tiny amount of work using tools to extract the calls to invoke the functions.

Managed languages don't give you control of memory allocation de-allocation policies; cannot build your own memory manager for most frequently allocated objects.

They are no different from C++ in this regard. You can choose to use the system's standard allocators or build your own. This was a popular debate point many years ago and arguing it is a fool's errand. There are many custom tools out there. The standard library provides general functionality, it was never meant to be all that everybody could ever ask for memory allocation. Replace it with one of the many existing libraries or your own home-built library if it doesn't fit your needs.

Memory usage can explode very quickly if the application is heavy on objects and data structures.

True of all languages. It is possible to write bad code in any language. When you follow the idioms of a language the results tend to be quite good.

Lack of on stack frame allocation/deallocation of local objects, or at least not guaranteed.

I'm guessing you haven't read the C++ standard. Guarantees in C++ are surprisingly rare.

C# GUI is still behind something like Qt or even MFC, even if it looks easier to use.

Again, built-in functionality is for general purpose use. Games are generally not a general purpose use. CAD software (what this discussion is about) is not necessarily a general purpose use.

Now what reason I would go with C# other than it makes average and entry level programmers life easier???!!!

There are many reasons to choose a specific language. A wide range of business decisions and technical decisions can go in to language choice. Ease of development for a certain group of developers is only one consideration of many.

And that brings us back again to the original topic.

What good reasons are there for it?


Generally C++ is well suited for systems-level work, and a big part of very large systems like games and CAD programs includes systems-level work.


Generally there is a large pool of developers who are comfortable with the language, although in C#'s 15 year history more and more people are getting comfortable with it and the C++ pool of developers is shrinking.


As mentioned about making developer's lives easier, that can mean cost reductions. Being able to hire less-senior developers and rely on more people with lower skills means saving money.  Everybody likes lower costs.


A large body of existing code is an important consideration.  For established companies it can mean hundreds of thousands or even millions of lines of C++ code that needs to be maintained. Since the business needs to have C++ programmers anyway, they might as well spend time on new development.



Many systems are open to extensions through plug-in style architecture.  The implementation details don't matter as long as the plug-in architecture is followed.  Many such systems provide a general interface following a few registration calls and a calling convention, but the plug-in can be written in any language as long as those few calls are compatible. Use C#, compiled python, Java, Swift, or whatever else you want as long as you meet the interface requirements.

#5290462 Is it C# Territory?

Posted by frob on Today, 01:14 PM

Removing a personal attack and a reply to the attack.  Please remember to keep it civil and stay on topic.

#5290410 I doubt I understand RAII just yet

Posted by frob on Today, 08:19 AM

It might be easier to explain with simpler "resources".

For RAII, they need to be set to an expected initialized values, and cleaned up when done.

Let's start with a simple case.

Consider a Vec2 type class, a 2 dimensional vector. It contains 2 floating point values.

An initialized value is likely setting both to 0. You might be able to leave them uninitialized, the values may point in any direction, but for consistency it is often best to initialize it to somewhere.

When you clean it up, the float types are released automatically so you don't need to do anything. Same is true with ints, chars, and the rest. No cleanup necessary.

Now let's advance to a small container.

Assume you make your own specialized container class. It has an array of pointers it maintains, and an integer storing how many are in use.

An initialized value is an empty container. You will probably set the integer storing how many are used to zero. There is no point in zeroing out the array since any value you add is going to overwrite that cell, so it can be ignored.

As you add items to your collections, let's assume this collection internally calls new to allocate each item and increments the count. When objects are removed the collection internally calls delete and decrements the count.

When you clean it up, you need to clean up all the objects you own. This means looking at the counter for how many are in use and deleting all the things that are still in use.

Now lets look at a wrapper for an OS system object.

Initialization here might mean one of two things, and often both way are provided. Often acquiring a system resource is relatively slow and has a chance of failure. Default constructors should be fast and never fail, so generally the default constructor, the one with no parameters, initializes the resource to 0 or NULL or empty or some other marker. It also implements a function to actually acquire the system resource that I'll describe in a moment. Then there may be a second constructor that takes a parameter. That second constructor needs to first initialize values to blank to allow the acquisition function to run, then calls the function to acquire a resource which may take time and may fail.

The function to acquire a system resource needs to look to see if it already has a resource. If it already has one, it needs to do something appropriate, either return that it already has one, or release the current one and acquire a new one, depending on the design of the system.

Finally when it comes time to clean up, the wrapper needs to release the resource if it has one.

In each case when an object is created it is placed in a known-good state. This is something most young programmers expect by default having never worked in older systems where memory allocation meant getting a raw block of data that is filled with previous contents and never cleaned up. These days operating systems wipe all memory as a security precaution. The object needs to be initialized to the point that it is useful. For containers that means being marked as empty. For wrappers that means being marked as ready for use. For proxy objects that means pointing to empty. You can provide additional slow constructors that fill containers, wrap actual object and proxy real things, but those should not be the default constructors.

In each case when clean up happens anything that needs to be cleaned up is cleaned up. Objects that are owned are destroyed. Resources that are owned are released. Since those other items also implement a RAII pattern everything the child objects own gets destroyed when they do. Anything the grandchild objects own gets destroyed. Anything the great-grandchild objects own get destroyed, etc. All the resources get cleaned up and the system can continue.

#5290361 Call a procedure with pointer as argument

Posted by frob on Yesterday, 09:23 PM

You can add it to the built-in if the string option doesn't exist thanks to the design of the assert macro.

assert( foo==bar && "message goes here" );

The contents of the assert macro are tested and if it stops it also dumps the contents inside the parenthesis. The second half of && "message" does not effect the overall truth of the statement, if false it remains false because the first half fails, if it is true it remains true because && string is true.

So when it crashes you get something like:

Assertion failed! somefile.cpp:37: foo==bar && "message goes here"

Which is very useful for the error message.

More advanced systems will want to build a custom skippable assert, something that doesn't crash when an assert happens, write code that attempts to provide a sane default after an assertion, have assertion systems record to log files with the severity of the error condition and what triggered it and hopefully how to correct it, etc. But those are more advanced. When you've got a simple solution, the basic assertion && message is a good pattern to use.

#5290313 Deciding on a Masters - Carnegie Mellon's Masters Entertainment Technology

Posted by frob on Yesterday, 02:36 PM

For that, I prefer programmers generally with a CS degree, in this case master of computer science.


"Masters of Entertainment Technology" looks odd when I consider it with my resume-reading eyes, but because of the school's name it is less bad than it could be. The links in the forum FAQ page cover this topic fairly well. They tend not to transfer well, and most people in the industry do not remain for their entire career.


Looking over their program, it looks like they are trying to provide a "trade school" experience of job training rather than what is traditionally considered a master's program.

#5290186 How can I share a .exe game?

Posted by frob on 04 May 2016 - 09:05 PM

While obfuscators and other tools can make it more difficult, if someone truly wants to dig through the executable they can do it.  Even if you use the best DRM and game-locking technology out there today it can still be defeated if someone wants to see inside.  Ultimately the player needs to access what is inside the binary.


If you want something not released, the only reliable answer is to not include it.


That can mean conditionally compiling the code so it is not included, or it can mean removing the source files so they are not included in the build.  Either way, that means making sure whatever it is won't be there to be found in the first place no matter how hard they search.

#5290155 Is it C# Territory?

Posted by frob on 04 May 2016 - 05:03 PM

Yes, it could be used.


If you want to develop a brand new CAD application, feel free to use it.

#5290121 how good is rand() ?

Posted by frob on 04 May 2016 - 01:55 PM

Seems that way, yes. I wrote an edit to my earlier post.


When I started writing the edit there were no replies to that on my screen, I just took a long time to review it carefully so I missed the addition.


The language standard as written is ambiguous, at least to me. Given the nature of the standard it is possible there is another note elsewhere about the range, but I didn't see it.

#5290117 Is it real?

Posted by frob on 04 May 2016 - 01:36 PM

Well, that's discouraging to say the least lol.
5-10 years is still a hell of a lot of time. Might die in that time period.



Yes, you might.  You might also die before you complete your next shopping trip, but you probably still plan menus and shopping lists.

The major AAA games coming out today frequently have budgets measured in hundreds of millions of dollars.  
A single hobby game should not expect to compete directly, attempting to produce a feature-rich enormous world filled with unique content and highly interactive environments that appeal to the masses with little risk.
Instead, hobby games should focus on what they do best, small experimental ideas that are high risk but potentially (relatively) high reward.

#5290099 Is it real?

Posted by frob on 04 May 2016 - 11:46 AM

 make something at the scale of Dragon Age Origins, if i already have all the assets (models, audio, arts etc.) and i'm using unreal engine?


Considering the game credits, subtracting out the artists I'd estimate about 400-600 work years.


Looking over the public information, November 2002-mid 2004 was a small concept team, mid 2004-spring 2007 was a moderate team, spring 2007-fall 2009 (final release) was full-on development, with work continuing on expansion packs and DLC for about a year after launch where the teams shrink considerably.


You don't win awards like Best Game of the Year from a huge number of awards shows and magazines and news outlets without enormous investments.




Now if you change your requirements, do not make something anywhere near that scale but make something of the same spirit of the game, with a much smaller feature set and much smaller story line and a less rich collection of features, and if you had an awesome original collection of assets, you could probably reduce it to something on the order of 5-10 work years.  It would require serious feature-cutting to reach that, but it is something an individual or small team could conceivably implement.

#5290093 how good is rand() ?

Posted by frob on 04 May 2016 - 11:16 AM

"The rand function returns a pseudorandom integer in the range 0 to RAND_MAX (32767). "  so it returns 0 thru 32766, but not 32767, right?




Correct.  In modern math notation this type of function works with [0,x)  meaning it includes zero but stops just short of x.  This is also common in many other systems.  Graphics, for example, typically draw segments in the [A,B) form, starting exactly at A and ending the instant before B.


Something troubled me about this, so I spent some time over lunch looking it up.


Turns out this is more complicated.   The wording in the standard is unusually bad but they get away with it because of history and because of the footnote in the standard.


The C++ standard references the C standard.  C++ 11 has a whole bunch of random number engines and adapters which are mostly all better than std::rand(), the C implementation.  I went back to the C11 standard and C99 standard, neither specifies the case. In C11 we get:



The rand function computes a sequence of pseudo-random integers in the range 0 to RAND_MAX. (See footnote)


The rand function is not required to avoid data races with other calls to pseudo-random sequence generation functions. The implementation shall behave as if no library function calls the rand function.



The rand function returns a pseudo-random integer


Footnote: There are no guarantees as to the quality of the random sequence produced and some implementations are known to produce sequences with distressingly non-random low-order bits. Applications with particular requirements should use a generator that is known to be sufficient for their needs.


The odd part is that generally in the language standard it is called out for inclusive or exclusive ranges.  For example, the conversion family around strto* (string to long, string to unsigned long, etc) specify a number base as "between 2 and 36 inclusive", meaning it includes both numbers.  For rand() the final number is never explicitly called out as being inclusive or exclusive.


Most of the time, but not always, ranges are exclusive of the final element.  They start at the beginning and go to one before the end of the range, excluding the final element. As a common C++ idiom iterators have iter::begin() that starts at the first item and iter::end() that is one past the end, the end element is excluded. Most but not all parts of the library follow that pattern for anything range related. This is true for most but not all ranges in C as well.


From further digging, it seems different library implementations have their own interpretation if the range is INCLUSIVE or EXCLUSIVE of the RAND_MAX value. It may or may not include that number as a potential number source. The POSIX reference version uses inclusive, including RAND_MAX.  


Either way there are better options as mentioned.

/end edit.


how good is rand()?


It depends entirely on your needs.


The key features were hit above.  No particular implementation is guaranteed, no particular distribution is guaranteed. LCG implementations are commonplace.


If you need something with cryptographic-style random guarantees you will need a specialized library for that.


If you need something with gambling regulation quality randomness you will need specialized libraries (and possibly specialized hardware) for that.



Even if you use a library that guarantees a specific distribution it is very easy for programmers to screw it up and ruin the distribution.  Say the original algorithm satisfied all statistical tests for an even random distribution for a 32-bit number, 0-4294967295. But you only have 45 items in your list so you use rand%45. That screws up the distribution since it isn't evenly divisible, the first 30 items are slightly more likely to be hit than the last 15.   Same thing with shuffling algorithms, the random number generator may be perfect but the algorithm itself does not yield a random shuffle even with a statistically random generator.


There are many excellent number generators out there with a wide range of purposes.  You can find (or implement) generators that follow specific statistical models, such as producing numbers on specific probability curves or formulas or biases.  In games it is fairly common to use sigmoid distributions, Gaussian (aka normal or bell curve) distributions, Poisson distributions, piece-wise weighted value distributions, and dice roll distributions (eg: 3d6+2d12), in addition to even distributions, all depending on the background of the game's designers. Sometimes they take time to learn the names but the designers still typically understand the distribution curves they want.


Figure out your needs, then pick a generator that satisfies those needs.  If your needs are "I need a number that is in this range but I don't care about statistics" then rand() can work well.  

#5289912 A question for how game engines build their game code for game logic -_-?

Posted by frob on 03 May 2016 - 12:27 PM

Most game engines these days are made in C++.  Some are made in other languages, but they are few in number.  Game engines and other systems-level work has more complex needs for explicit memory management and object lifetimes, for explicit control of many hardware features, for direct access to a linked library rather than going through a marshalling process from an abstract memory format to a specific one. C++ provides better control of those features than most other modern languages.  


Games use a wide range of languages for script code. C#, Lua, AngelScript, and C++, and more as well.  Scripting languages can (but do not need to) provide a way to modify the game without stopping to rebuild the source code, can make it easier for large teams to collaborate, can make it easier for designers and artists to make changes with less fear of breaking the game.  


You can choose to use whatever languages you want.  HTML and Javascript, Python, C, Java, Go, Rust, Scheme, or any other language you feel like using to write your game.


Know that those "popular engines" are typically built and maintained by teams of 100+ people. A hobby project with one person has different needs.

#5289911 Graphics Format for IOS and Android Versions

Posted by frob on 03 May 2016 - 12:18 PM

Games do not typically use those formats on any platform.  Photoshop and Illustrator documents are not typically supported directly, neither are jpeg or png formats typically directly supported.  The images are usually exported to a hardware-friendly format by a tool or by artists.


Unity has some support for extracting the data from those formats and creating textures out of them, but it is generally more common to export out exactly the content you need. 


You can use the PSD files in your project, and Unity's automatic extraction tools will probably extract out what you are looking for. But they might not, they might incorrectly combine layers or mess up advanced Photoshop data. You can use the automatic extraction in Unity, it just isn't the typically preferred method.

#5289769 Use which kind of generic string?

Posted by frob on 02 May 2016 - 12:48 PM

Most systems I've worked with have std::string markers in the code, the localization system generates a different type of immutable localized string that is accepted for the UI.

#5289761 Procedural Universe: The illusion of infinity

Posted by frob on 02 May 2016 - 11:46 AM

That is an awful lot of space. 


Your scales are a good start but will need tuning based on actual scales.  If you are operating on a meter scale for the 'planet scale', an Earth-sized planet is about 6.4 million meters which blows your scale.


You mention building new galaxies procedurally and drawing a quick rendering of the brightest stars. How many stars do you have in a galaxy?  100 billion?  500 billion? Or something game-like?   Then you repeat for each galaxy, we've got over 100 billion galaxies in our observable universe.  


Obviously rendering something lifelike on the order 10^22 stars for your background sky box is out of the question. 



On the matter of quadtrees, when you are talking about such immense areas of sparsely-populated space you will be better off starting with hashes or similar for the enormous areas, probably hashing them again multiple times until you get down to clusters of interesting objects, then using an octree once you've got it pruned down small enough to no longer be sparse. 



But still, having an illusion of infinity means both high repetition and sparse specific content. Few designs handle such things well.  An Earth-sized world is difficult enough to fill with interesting stuff.