Jump to content

  • Log In with Google      Sign In   
  • Create Account

frob

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

#5263905 C++11 template question

Posted by on 27 November 2015 - 10:37 PM

It is information the compiler has on hand because the type is a reference to an array.  As the book points out, this is one of those interesting little quirks of the language.
 
 
Remember that template code is not actual c++, it is a template.  The compiler effectively turns the template into a custom invisible cpp file with all the elements filled in, then that invisible cpp file gets compiled in.
 
Under the old C rules, passing an array is equivalent to passing a pointer to the first element. So as the book points out, the compiler's invisible custom cpp file would have a pointer to the item.  If the type were an array (like: int [10]) it would still be converted to a pointer to the first element (like: int*).  That is why the template needs to use a reference (T&) rather than a plain type (T) or type pointer (T*). 
 
Since it is a reference to the array, and because the C++ rules on references are slightly different than the old C rules for passing arrays, the compiler has the data to figure out the exact type of the array.  This is information the compiler knows at the time of compilation. 
 
 
 
 
So when the compiler generates the custom invisible cpp file from the template, the magic happens as the full type information is used to substitute T and N in the template.
 
The compiler takes the definition of the type that it knows:  int foo[10];
 
and applies it when it sees: arraySize(foo);
 
then it generates the invisible file with this function, filling in the blanks T and N in the template with the information it already knows:
 
constexpr std::size_t arraySize( int (&)[10]) noexcept { return 10; }
 
Again, this only works if you've got a reference (the & in the middle) because references have the full information. If it was not a reference, the type would be deduced as a pointer to int, (int *) so for this code the compiler could not properly substitute out the array parameter, so the substitution would fail and the compiler would not consider it as a valid template instantiation.


#5263854 Buying a game for private server

Posted by on 27 November 2015 - 11:55 AM

So Im trying to understand as much as I can from their perspective, before going back. ... I understood it like there was no problem putting the game back online

 
Imagine yourself as the business owner.
 
~~~~~
 
I'm running a big software company.  I have several business deals going on, each valued in tens, twenties, fifty million dollars or more.
 
Someone comes along asking for an old product to be revived.  A project we dumped because it did not look profitable.
 
The product is old, dating back to 2002-2003 era.  
 
The person wants me to bid on a project to:
 
* Go through the archives and find the software. It was 13 years ago. Does this software even still exist in our backups and archives?
* Figure out the settings and software dependencies for this 13 year old software.  It probably will not run without engineering work.
* The software probably ran on Windows 2000 servers, which is long dead. We cannot find the same hardware or operating system.
* The compiler and build tools were probably VS2002 or maybe VS6, both long dead. The build tools are out of date and may not work on modern systems.
* It probably relied on several other systems that have vanished over the past decade, or that have changed so much they are likely incompatible. We cannot find the 3rd party dependencies for the product.
* Get the system up and running.  This will likely take many weeks to make all the changes for that 13-year-old software.   Which developer do I assign, removing them from existing projects?  
* If anyone remains from the development team 13 years ago they are going to be senior level employees today. Do I need to remove my technical leads or managers from our current multi-million dollar projects for this? 
* These people already have other roles. Will this make my existing projects late, or put me at risks of missing dates?
 
~~~~~
 
This is not like going to a library and checking out a dusty old tome from the back room.  
 
If all you wanted was a license to use the software, and their only involvement was to give you a copy of the source, then it may be different.

 

Selling you a dump of the source files, the assets, and a license to use them, I can see that costing $50K.  

 

Getting the entire system up and running for you, maintaining the servers, taking workers off current projects and re-assigning them to a dead end, there is no way they are charging $50K.




#5263839 Algorithm for automatic ships production

Posted by on 27 November 2015 - 10:09 AM

 I'd go a direct approach.

 

For larger systems I might go with a statistical approach, but this is small.
 
You already a number of each item to build, and priorities associated with them.  
 
Now you need a queue of one item, or a "next item to build" slot.  This lets the player know what the AI is planning to do, making them happier.  You might want a longer queue, in that case just continue with this routine removing the items from the list as they get added to the queue.  Adding some complexity, you could let them cancel items or move items in the queue, pushing queued items forward in line and then filling the back again.  
 
Run this:

If nothing on queue (or empty spots in a multi-item queue):
  For each priority in priority order:
    If items needed at this priority:
      Build collection of all needed items in that priority
      Shuffle collection (or just pick a random item number within the collection)
      Queue first item in shuffled collection (and subsequent items if multiple slots)

If you've got a longer queue with room at the end, use that to fill up slots at the end until all slots are filled.

That method won't work too well if you are queuing up many thousand items, but from your description you're in single digits and double digits. A simple shuffle will mean slots with more items get built more often by virtue of it appearing more often. No fancy weighting required.
 

 

 

You'll need to decide what to do when the player adjusts the sliders.  You might do nothing (the easiest option) allowing the current queue items to build.  You might validate that the first item in the queue is still the highest priority and then insert items at their desired spot. You might remove items if they dropped the needed count to zero. 




#5263747 Buying a game for private server

Posted by on 26 November 2015 - 07:26 PM

That size development team costs about $3M per year. Note that isn't just salaries, it is all the other business costs too.

 

Usually development is around 1/3 of total costs. Marketing is typically as much money or more money than the software development.

 

So they could turn out an online game with about 3000 players (which is definitely not an MMO, just a regular old online game) 

 

The product has been archived for a decade.  It needs to be updated to work on modern systems.  And there was a reason they cancelled it, that reason likely still applies.

 

 

So what will that cost you?

 

If you are looking to just buy it directly, talk to them.  They might let the property go cheap.   My estimate of cheap and your estimate of cheap are probably different.

 

 

Once you've purchased it, based on your description, I'd expect at least 2 months of serious effort to get it out of storage and functioning on a modern environment.  Given the team size, that's about a half million dollars.

 

Then you probably want to advertise the game. That's another half million dollars at least if you want it to be well known.  Without the marketing budget, your game -- great as it may be -- will die in obscurity.  Safer to plan a full million, but it doesn't sound like you realistically would.

 

Then you'll need to pay for your servers and bandwidth, either through a system like Amazon or your own colocation system. For a minimalist setup you're probably looking around $500/month, more realistically $1000/month for what you described since there is a lot of bandwidth needed.  That's relatively small compared to the cost of the people maintaining it, probably about $50,000 per month. 

 

It will take a few months at least with heavy marketing to attempt to reach a sustainable level.

 

So I'd peg the whole thing around $2M for your costs.




#5263664 Buying a game for private server

Posted by on 25 November 2015 - 10:14 PM

mass produced MMOs in 2000-2005

 

Mass produced online games maybe, but not MMO.  The "MM" of MMO means "massively multiplayer" and very high capacity, on the order of 100,000 concurrent users or more.

 

Building a game that supports tens or even hundreds of concurrent users is not too difficult, lots of people have done that. With today's tools that is something you can pull off developing in your basement on no money.

 

Building a game that supports thousands of concurrent users is a much larger effort, when you approach tens of thousands of users you are talking about maintaining larger data centers and paying a thousands of dollars every month for those machines.

 

Building a Massively Multiplayer system, MMO, is fantastically more work. Even a small MMO has a budget measured in the hundred million dollars, with data centers costing tens of thousands of dollars every month.
 

Im sure it could cost $500-$1M to develope. (wild guess)

 

Are you sure about that?
 
Most of the "shovelware" style games today cost in the $5M - $10M range to develop in the US and other western nations.
 
Most of the mainstream games today cost in the $20M-75M range.  Games that are big budget are easily $100M.  
 
And true MMO launches are easily $100M for main development plus about twice that much again for marketing and deployment and initial launch.

 

 

 

It may be that a company is willing to sell you a ten-year-old engine on the cheap.  They may hook you up with an existing game for $50K.  But if they do, don't expect much from that engine.




#5263606 Depth buffer really confuse

Posted by on 25 November 2015 - 12:48 PM


Isnt this on eye space? I must have confuse on how depth buffer works on depth precision. All in all my real confusion was on the depth precision it self. Which happens first? is the the test or the equation for depth precision?

 

Normally it is a value between 0 and 1, mostly this stems from the nature of floating point.  

 

At the point in the pipeline it is happening the pixel fragment is generally relative to the view frustum, a value from 0 to 1. 

 

The task for comparing against the z-buffer is simple enough. The pixel fragment's depth value is compared against the z-buffer using the selected operation (any one of <, <=, ==, !=, >=, >, true, false).  If the result is false the pixel fragment is discarded and processing stops. if the result is true the z-value is written to the z-buffer, and processing continues.

 

As for what happens first, that gets a little tricky.

 

 

 

From a high level perspective, the test against the z-buffer happens toward the end of the graphics pipeline:  Everything is sent to the card to be rendered.  The vertex shader is run, which can do tasks like skinning and transformation, basically moving stuff around. The hull shader is run that can break down line segments into smoother curve segments. The tesselator runs to connect all the tiny line pieces. The domain shader is run, and it can calculate the final position of each vertex point. The geometry shader runs next and can further modify what vertices are actually drawn. The pixel shader runs and can modify color and depth information.  Conceptually the z-test runs here, as described above. Assuming the z-buffer test passes, the pixel fragment is passed along to be merged with other values. Finally, output of all the rendered pixels are merged together and generate a full final image.

 

 

In practice, there are several tricks and optimizations that hardware can do to make the test happen much earlier. The hardware can peek ahead at the shaders being used. 

 

If the hardware can see that the pixel shader does not modify the z-value, it can run the test before the vertex shader eliminating what is normally the most expensive shader.

 

If the hardware can also see that the geometry shader does not modify z-value, it can run the test that much earlier and avoid the work if the test fails.  If the hardware can also see the domain shader doesn't affect the z value, it can be bumped again.  Repeat for each shader.

 

That part happens automatically.

 

 

There are methods (I am not fully read up on them) to run an early depth-only processing pass. Basically it runs to transform all the geometry but does not do any of the more expensive lighting or coloring operations.   That information is used to perform earlier or more reliable depth tests in the second pass.




#5263512 execute constructor of derived class

Posted by on 25 November 2015 - 12:17 AM

TObjectPropertyEditor something;


In that case, get and study a GOOD book about the language.

Based on your comments over the past few months, I recommend current editions of either of these:

# "C++ Primer" by Lippman, Lajoie, and Moo. (NOT "C++ Primer Plus")
# "Accelerated C++" by Andrew Koenig and Barabara Moo

Don't bother with both since they mostly overlap. The first one has a gentler learning curve than the second.


#5263436 execute constructor of derived class

Posted by on 24 November 2015 - 12:06 PM


TObjectPropertyEditor() //TForm constructor will be executed right?

Yes.

 

 

 


~TObjectPropertyEditor() {} //TForm desctructor will be executed right?

 

Yes with a caveat.

 

If the function is not marked as virtual, it is possible for the TForm destructor to be called but the TObjectPropertyEditor not get called.

 

So that works only if the TForm destructor is virtual, which it should be.  Virtual gets inherited, so if TForm derived from something and it was marked virtual, that would also make it happen.

 

If it is not virtual, than this won't work:

base* b;
b=new derived;
delete b;

In that case if the destructor is not virtual than the derived destructor won't be called, only the base constructor is called.

If the base class destructor is virtual then both the base destructor and derived destructor will be called.

 

 

Or more specific to your example:

TForm* form;
form=BuildSomePropertyEditor();
...
delete form;

In that case if the destructor is not virtual only the TForm destructor would be called, which is a bug.

 

If the destructor is virtual then when the object is deleted the TObjectPropertyEditor destructor gets called, then TForm destructor gets called, which is what you want.

 

So make sure the base class destructor is virtual, otherwise there can be serious problems.




#5263418 execute constructor of derived class

Posted by on 24 November 2015 - 11:00 AM

Your code and your words don't quite match up.

 

 

TObjectPropertyEditor is derived from TForm.  That means TForm is the parent class, and TObjectPropertyEditor is the derived class.

 

When the objects are created, the TForm constructor is executed and run completely before TObjectPropertyEditor constructor is run.  Base class constructors are called first, in the order they are listed in the class definition, then the constructors of sub objects are called in order, then the current class constructor is called.

 

 

Your constructor initializer lists should be in the same order the members appear.  If you have five or ten members getting initialized, put the base constructor first and the member variables in order, the same order they appear top to bottom in the class file.

 

If you need to pass parameters or initialize variables, you can do it using a constructor initializer list, something like this:

struct TObjectPropertyEditor : public TForm
{
TEntity * apply_to;
TObjectPropertyEditor() : TForm(), apply_to(NULL)
{
}

//Adding this one as an example
//If you want to pass a parameter to a base class, you can do it like this
TObjectPropertyEditor(TController *controller) : TForm(controller), apply_to(NULL)
{
}

// Double check that your base class destructor is virtual and public.
~TObjectPropertyEditor() {}
};

When you create a TObjectPropertyEditor it will first call TForm's constructor, and after the TForm is created the above code will initialize apply_to with the value NULL, then it will run the TObjectPropertyEditor constructor body.

 

In the second constructor I wrote as an example, it will pass the parameter on to the TForm constructor and run the constructor, then initialize the variable to NULL, then run the constructor body.

 

 

 

 

 

Base class destructors -- which should usually be virtual and public, are automatically called.   A class that is free standing can have a regular function for a destructor, but base classes have some special rules. Nearly always, and always when you intend to use polymorphic behavior for the class, a base class destructor needs to be public and virtual.  

 

These destructors are an exception to the normal rule because they automatically call their base class variant, you don't need to call them.

 

Without that special rule you would need to write:

~TObjectPropertyEditor() {}
 // My own destruction
 ...

 TForm::~TForm();   // DON'T DO THIS, Don't chain virtual destructors, the compiler does it for you.
};

In any other case if you need to call the behavior of a virtual class you would need to chain it manually.  Destructors are a special case, just make sure the base class destructor is virtual and they will all get destroyed in the correct order, ~TObjectPropertyEditor gets called first, then ~TForm is called next.




#5263364 Getting Started With Game Development?

Posted by on 23 November 2015 - 08:53 PM

Moving to For Beginners.

 

You question is listed right at the top of the For Beginners Faq, where it answers the question "where do I start?" with several options.




#5263330 Communicating with Modelers

Posted by on 23 November 2015 - 03:47 PM

This type of communication often falls on the shoulders of the designer.  

 

Designers need to document and explain the design to all the groups; the programmers, modelers, animators, audio, effects, and QA groups all need to understand what the thing is supposed to do.

 

Part of that understanding includes knowing why a thing needs to be that way.  In this case, perhaps a single line would have prevented the problem:  Doorway needs to be at least 4 units wide to accommodate pathfinding.  

 

For doorways on other projects we've tended to ignore pathfinding and use a portal system. Doorway elements (bridges, doors, teleporters) include marked locations (like a named joint) to allow animations to hook up cleanly. The object needs to walk to the marked location with the correct orientation, play the animation set associated with the object's motion, then resume from the exit location.  This allows for things like gates that need to be opened and closed, one-way portals, and other object properties.




#5263327 Depth buffer really confuse

Posted by on 23 November 2015 - 03:33 PM


Are you sure this is still the truth?  With all modern GPU having Hi-Z, I know at least ATI(AMD) has fast Z clear IIRC using Hi-Z buffer.  I would think drawing the skybox last will potentially save alot of fill depending on how much of the sky is visible.

Ah, the joys of constantly-changing graphics hardware.

 

Looks like yet another change, where an older best practice is replaced.  

 

I'm glad I'm not a graphics-centric engineer because it seems every few years it flips itself on its head; the old best practices are discouraged, the old practices to avoid become recommendations.

 

From some of that reading you linked, if your graphics card has a compressed z-buffer, use a clear operation since it will drop the compressed blocks.  if you are using an older card without compressed Z-buffer, overwrite rather than clear since a clear resets the value to a specific depth and then you'll immediately overwrite it with new depth data.

 

And if you're targeting cards in between, implement both.

 

If you implement only one or the other, you're doing it wrong on the opposite era's cards.  blink.png




#5263306 Survival Mmo

Posted by on 23 November 2015 - 01:14 PM

The "massively multiplayer" part of MMO was created to show the difference between regular online games.  

 

Back in the late '90s when it was coined, Massively Multiplayer meant servers with over 10,000 concurrent users. The normal notation is "C" for "concurrent" followed by the number, so in this case C10K.  

 

Today the number for MMO is usually much larger, C100K or so at a minimum.

 

Building an online game with a small number of concurrent players, maybe 4 or 8 or even 64 (C4, C8, C64) is relatively easy.  They can usually connect directly to each other, or go through a game hub you set up and control.  You can do this in your basement or through a cheap hosting account with pocket money for budget.

 

Controlling a larger online game (still not MMO) with many concurrent players, say C1K or C2K, that requires an investment of dedicated hardware and probably multiple data centers. This generally requires a multi-million dollar budget and commitment from a developer.  

 

Controlling a massive number of concurrent players, C10K or C100K, you are looking at price tags in the hundred million dollar range. 

 

 

Unless you happen to be a billionaire hiring a very large team for their dream game, building an MMO is not feasible for an individual.




#5263299 Put game data to files or using database tool

Posted by on 23 November 2015 - 12:56 PM

Usually parsing and loading files is a slow process.  Many file formats require decompression to be used. Other file formats like XML are memory-expensive and compute-expensive to parse and validate. 

 

 

In the AAA world, there are frequently multiple formats accepted:

 

First, there is a final packed format. These are designed to be loaded directly into memory without any processing.  Dump it in a big block of memory, fix up some pointers to point inside the memory, and use it immediately.

 

Second, there is support for development formats. These are the intermediate files, perhaps raw images or textures or model Collada files or wav files. Better engines will monitor the directory tree and swap out the files while the game is running when the files are changed.  These are not preferred because they take more time and effort to parse, but they save significant dev time by allowing artists, modelers, animators, designers, and audio to iterate quickly. They can make a change in their tools, save the file, watch it change in game, make another change, save, and iterate rapidly.

 

Third, there may be support for modding tools or development tool attachments. These may load and process their own file formats or build data dynamically on the fly.  

 

 

 

The exact details of your file formats are up to you. Use what works for your process.




#5263297 Depth buffer really confuse

Posted by on 23 November 2015 - 12:48 PM

Just re-iterating and re-wording:

 

 

The depth buffer usually works as a shortcut to see if something should be drawn or discarded. It has several options:  

* NEVER (don't draw)

* ALWAYS (always draw)

* EQUAL (draw if the values are exactly equal)

* NOTEQUAL (draw if the values are different and store this)

* LESS (draw if the value is smaller than what exists, and store this new smaller value)

* LEQUAL (draw if the value is smaller or equal to what exists, and store the new value)

* GREATER (you get it...)

* GEQUAL (Greater or equal)

 

Generally games will not explicitly clear the depth buffer.  Instead they set the flag to ALWAYS and draw their skybox or draw a distant plane, thus obliterating whatever was stored and setting a new maximum depth.

 

The depth buffer can be used for other tasks as well as depth.  You can use depth images, or pre-computed depth fields, to mix and match 3D worlds with pre-rendered 2D images by drawing a pre-rendered image and telling the depth buffer what pre-computed depths they represent. You can use depth buffers to help compute fog or atmospheric scattering or depth-of-field distortions.

 

 

 

As for how the depth number is determined, there are many methods.  You can change the values that get used inside your graphics shaders or compute shaders.

 

Because of the magic of floating point, smaller numbers are more precise than bigger numbers. The sliding scale of the decimal point (hence "floating" point) means the tiniest numbers have the greatest precision. Each time it floats bigger, the precision drops by half.  Floating point precision operates at logarithmic scales.

 

That means that the nearest items usually have high precision, but distant items can suffer from "z-fighting", where planes that are touching each other will shimmer and shift between the objects as the camera and models moves. 

 

To counter the sliding precision, people have come up with many different ways to compute the depth values.  

 

You can use the simple calculation of (object depth / view frustum depth). That is normally the default that happens if you didn't provide a custom value.  Some programs will store the inverse of that distance, termed a 'w-buffer". Some programs will use a logarithmic z value, basically reversing the logarithmic nature of floating point turning it back to a roughly linear scale. Some programs will use different algorithms that suit them better.

 

The value that you store and compare against is up to you. 






PARTNERS