Jump to content

  • Log In with Google      Sign In   
  • Create Account

FREE SOFTWARE GIVEAWAY

We have 4 x Pro Licences (valued at $59 each) for 2d modular animation software Spriter to give away in this Thursday's GDNet Direct email newsletter.


Read more in this forum topic or make sure you're signed up (from the right-hand sidebar on the homepage) and read Thursday's newsletter to get in the running!


frob

Member Since 12 Mar 2005
Offline Last Active Dec 24 2014 10:26 PM

#5199899 Is Java a good Language for Games?

Posted by frob on 24 December 2014 - 03:53 PM

I know not a thing about Java, but I know that if you create a game, everyone has access to the source code because you can open .jar files with Winrar (or any other program that opens rar files) and you would be able to see and edit the source code. I do not think that happens with C# or other languages.

 

That is the case with many languages and with nearly all modern languages.

 

In modern languages that compile to an intermediate format, and languages that support reflection, including Java, C#, Python, Ruby, JavaScript, Go, etc., the nature of the language is that you need to be able to reconstruct the complete details of the original object's implementation. Some portions of it may be lost, such as comments or dead code, but everything that is accessible programmatically can be reversed to make something closely resembling the original code.

 

Under the very old C and C++ compilation model, which has its roots in the 1950s and 1960s, the design was to eliminate everything that could be eliminated which makes decompiling and reverse engineering much harder.

 

If you need to make things harder for someone decode, you can use tools to compile to a final optimized executable while stripping reflection information, or you can look to obfuscators that rename everything to less-understandable names.




#5199862 Visual studio 2013 (exe release) runs slower compare to VS2010

Posted by frob on 24 December 2014 - 10:48 AM

There are tons of options, plus there are code generation differences between the compilers. Could be lots of things.

 

For anything performance related, your profiler is your best friend.




#5199771 IAP promo codes to give to Kickstarter backers

Posted by frob on 23 December 2014 - 05:06 PM

Apple is pretty strict about that requirement, especially since it is how they get their money:  Apps that unlock or enable additional features or functionality with mechanisms other than the App Store will be rejected. Apps utilizing a system other than the In-App Purchase API (IAP) to purchase content, functionality, or services in an App will be rejected.

While other systems are more amenable to outside purchases, Apple maintains fairly tight control.


#5199770 html & opengl ( what should i use or should i recreate html render engine )

Posted by frob on 23 December 2014 - 04:54 PM

Just wondered if fetching data from Internet and using "common controls" instead of parsing a web page is possible (if will just be used for launcher and so) and feasible.

 

It is an option. In fact, that is exactly what REST systems are. You make a web request, you get back a response, and you interpret the response based on your own rules. 

 

There are no real technical reasons why you or the original poster couldn't do that. You could even use different HTML headers like the (Accept header) to specially indicate that your application is requesting the slightly different presentation. 

 

As was pointed out, a web browser is an amazing architectural infrastructure.  If all you need is to interpret ten or twenty markup symbols and you control both ends of the infrastructure, you might be able to handle that much easier than including an entire web browser. 




#5199130 C++ how to declare something that isn't declared?!?

Posted by frob on 19 December 2014 - 12:26 PM

Can any one explain the difference between these two lines?

  TSubparticle::Ptr p1, p2;
 
  TSubparticle* p3, p4;

 

In the first line the type is a pointer type, so both p1 and p2 are pointers.

 

In the second line the type is TSubparticle and only the first one is a pointer. p4 is actually an instance of type TSubparticle, not a pointer.

 

This and a few similar small 'gotachas' are a common reason coding standards often require only a single declaration per statement.




#5198886 Item Discontinuity Problem

Posted by frob on 17 December 2014 - 10:36 PM

In some games for some items that makes sense. In some games for certain patterns, there can be far more than that to a game object.

While sometimes it does make sense to reduce the object down to a minimal piece of data or a single integer count, other times it can make sense to keep a full object around, especially in games where a game object has a large number of ancillary behaviors and data points.

As counter example to the "store just a count", there are games like The Sims where a simple game object comes with a high degree of custom information; custom textures and colors, custom date and location of of purchase, custom damage/repair history, custom usage count, custom purchase cost, custom depreciation cost. When placed in an inventory the relatively small data asset is moved into an inventory. The rendering and the UI thumbnail are both handled separately from the blob of data describing the game object, so they fall off into the cache and eventually vanish even though the game object is alive and well inside an inventory.

So while sometimes it is good to just store an index and a number, other times you will want to have a long-lived blob of data. It really depends on the game.


#5198580 html & opengl ( what should i use or should i recreate html render engine )

Posted by frob on 16 December 2014 - 01:45 PM

There are tools like webkitavailable.  It is/was the core for a bunch of modern browsers and is also used in many games. 

 

Know that HTML is a surprisingly complex language when it comes to rendering. Some parts of it are easy, but trying to cover all the stuff in the W3C standards is an enormous undertaking.




#5198561 Mobile Arcade

Posted by frob on 16 December 2014 - 12:08 PM

For a $0.99 game you'll have a hard time beating that with PayPal.

 

The fee they charge is 2.9% + $0.30 per sale.  For $0.99 that would be 33 cents, slightly more than what you pay for Google Play.

 

If you are charging more or have a high volume the story will be different, but you'll have a much harder time selling on your own without leveraging a marketplace.




#5198366 Byte and double byte numerals

Posted by frob on 15 December 2014 - 12:11 PM

When asking questions like that, it is often better to go directly to the standard rather than to people's interpretation of the standard.  You can reference the draft version of the standard that was approved. There are only minor differences between it and the final approved version, like the page headings and the front page. 

 

Take a look at the language grammar that handles integer constants (6.4.4.1).

 

The only allowed suffix in C are:

u or U - meaning unsigned

l or L - meaning "long", typically a 32-bit number

ll or LL - meaning "long long", typically a 64-bit number.

 

If you don't have a suffix and the number is small enough to fit inside an int, the numeric constant is an int. If you assign it to a char (which the uint8_t type is under the hood), the value is automatically and silently truncated.

 

The conversion and promotion rules can lead to lots of fun conditions, several of them are documented in the standard itself.

 

 

 

If you are using uint8_t you can get several interesting effects. Consider:

uint8_t a, b;
/* ... */
uint8_t c = a + b;

According to the arithmetic rules, the values for a and b are both promoted to unsigned integers before the addition takes place, then the result is silently truncated back to an 8-bit value.  This can be important for large values of a and b since it may not overflow as you expected.

 

 

Not understanding the conversion rules can lead to all kinds of subtle and potentially unexpected (e.g. buggy) behavior.

 

 

Edit: Note that C++ has similar but slightly different conversion rules.  Any time you play fast-and-loose with types and conversions the rules for automatic conversions and promotions can cause unexpected bugs. As another prime example, mixing 32-bit enum values with 32-bit numeric constants can lead to some unexpected trips into 64-bit land that will silently have radically different results on different compilers.




#5198086 Bullet hell projectiles as separate objects? Or as one whole particle system?

Posted by frob on 14 December 2014 - 02:25 AM

How many bullets do you have in your game?  Is everyone armed with machine guns or something?

 

Does your game seriously have bullets colliding with other bullets? 

 

In your image it looks like you have around 800 or so bullets just in that screen.  That is not a typical number. 

 
 
 

 

In older games and games where shooting is not central mechanic a bullet is often a simple ray test with either an instant reaction or a delayed reaction. I'm assuming that isn't the case.

 

In the bulk of games, a bullet is a cast ray.  Bullet starts at the origin. Over a single time step it moves along the ray as a line segment A to B, the intersection test is fast and easy. Also there are not a lot of bullets in the air at once, usually under five, possibly 20-30 if several machine guns happen to be active at once.

 

 

 

Since your screen capture does not look like either scenario, you'll need a different solution.  Treating each bullet as a swept line segment over a single step is normally fine with a smaller number of objects. With around 800 or so I can see on your screen, 800 line segment tests over a narrow area is going to be a real chore even with a robust spatial tree. 




#5198084 Need advice on C++ reflection system

Posted by frob on 14 December 2014 - 02:03 AM


I think we're agreeing with each other here, but just to beat a dead horse... don't reflect stuff like that. There's no reason to automatically reflect every hash table. I'm not even sure how'd you do that in C++ without using an external tool that intentionally scans for template instantiations which would be insanely difficult if you're not plugging into Clang or the like.

 

 


You should though follow the rule of reflecting only what you need.

 

You write there is no reason to do it. 

 

You write that you should only reflect what you need.

 

So that means we are still in disagreement.  I feel both these statements are incorrect.

 

 

 

Reflection is heavily used in nearly all modern languages. Not just C# and Java. Objective-C, JavaScript, Python, ActionScript, Ruby, PHP, Go, and many more. The type of thing you are talking about is a far cry from what reflection is or what it enables.

 

For lack of another authoritative definition, I'll use the one from Wikipedia: Reflection allows inspection of classes, interfaces, fields and methods at runtime without knowing the names of the interfaces, fields, methods at compile time. It also allows instantiation of new objects and invocation of methods.

 

Reflection does not mean partial metadata, knowing only a part of the interfaces, a few of the fields, a subset of the methods, or invocation of the methods the linker happened to leave in place.  Reflection means you can programatically access another system and completely reuse the entire functionality of classes and other parts..

 

 

In modern languages there is a very strong, compelling, and language-mandated reason to export every part of the public interface.  Modern reflection mechanisms provide the complete functionality to any program that is allowed to observe or modify the system. 

 

In C++ there is a language-preferred reason not to expose anything. The overhead and additional costs involved are exactly the reason the language does not want it.

 

This is one of the radical differences between what modern languages use for reflection and what older languages do.

 

 

 

 


More realistic systems would reflect only...

 

That is where I strongly disagree.  Your "more realistic" means "a tiny piece of support compared to others".

 

Reflection in modern languages is very different from, and incompatible with, the old compilation model used by C and C++.  Microsoft has invested a fortune into it building C++/CLI. Even after spending untold millions on the system across more than a decade, it still only partially works and they cannot get it to the same level of quality found in any modern language.  

 

Large ecosystems have developed around reflection, with plugin architectures and external modifications being some of the biggest benefactors.  

 

This is one of the big pieces of functionality that helps other languages advance far beyond C++ outside of systems-level work, and is a painful hole when doing systems work when your system must integrate with other systems. Back in the mid to late 1990s COM objects and DCOM objects became popular and profitable, as businesses could get components, drop them into their programs, and gain programmatic access and interoperability. There was (and still is) some overhead in figuring out exactly what should be exposed and how to expose it.   Then there was an explosion of other languages with reflection. That is available for free with modern languages. Now in these modern languages you can pull down just about any functionality you want from any of a large number of public repositories, download only the final executable/library build, and have full access to everything you would have without need source, without needing to rebuild with different compiler options, without needing to account for ST/MT versions, without needing to account for dependencies.

 

C++ is a wonderful language for systems-level work and HPC because of the level it works at.  But with an ever-expanding collection existing engines and tools, the lack of reflection continues to grow as one of C++'s serious flaws and missing features. The cost and effort of making a C++ program that plays well with others is painfully high. Every time there is a new library or new engine, or even an update to an existing component you've integrated into your library, the flaw becomes that much more apparent. In reflection-supporting languages you download a new final build and verify in the documentation that the public interface has not changed in breaking ways. In C++ such a change can require several days of integration efforts.  

 

Like you, I've worked with many enormous code bases. I've maintained build systems, run the integration of many working parts, and even for one game cycle had the horrible job of keeping a large collection of C++ libraries updated with EA's massive corporate collection of systems for all the libraries used by the game, the tools, the build chain, and everything else. I currently work for a different company doing similar things but with a mostly Java codebase. The ability to simply point to nexus and pull down the latest final build, and having programs designed to automatically bind with any build I specify... Well, that is me and our codebase relying on the modern reflection mechanisms. The build chain automatically notifies the team when updates are available, and if we chose to take the updates we can usually integrate them by typing in a new version number and telling the build server to run the test suite. Having seen what reflection enables, I hope to never again need to manage dependency trees as is still done in C++. 

 

 

TL:DR: About the closest C++ can get to reflection is with COM objects or DLL exports or similar extracted or programmer-maintained systems. While these are useful alternative interfaces, they are worlds away from reflection as it is used everywhere.




#5198058 Mobile Arcade

Posted by frob on 13 December 2014 - 07:27 PM

Here is my question. Does anyone know the Paypal API and how I could interface with it to allow the user to make a payment from my site and then trigger IP address addition to the database?

 

It is well documented on the PayPal web site, developer.paypal.com.

 

It is not too hard to use. You provide formulaic URLs to your users for them to use.

 

When the payment is completed the system includes both an automatic ping-back from the servers that you can handle, and you can also query into their system.




#5197931 C++: Easiest way to implement an in-game Time/Date system?...

Posted by frob on 13 December 2014 - 01:30 AM


I've tried a few different things using QPC()/QPF() and come to a point where the seconds seem to be progressing quite smoothly in general, but there's still a definite, though probably significantly rarer than before, occasional time when a second visibly hangs for a moment before the next second shows up and goes by more quickly to compensate.

 

Scrolling back up to my earlier wall of text, use the results of QPC as a stopwatch. Tiny error in individual frames will work itself out over a larger time frame. Don't try to convert it back to milliseconds or do fancy division or averaging, just leave it at the high performance clock values. 

 

The only time you really need to stop that clock is when the elapsed time is obviously out of bounds.  Usually that happens when you stop the game in the debugger or the system otherwise has stalled.  That is easy enough to handle as a special case, along the lines of

elapsedTime = GetTimeSinceLastUpdateWithQPC();
if(elapsedTime > WAY_TOO_LONG) {
    elapsedTime = DEFAULT_TIMESTEP;
    Logger::Log( Simulator, Logger::Info, "Excessive time between updates exceeded, possibly from an OS stall or a debugger. Resuming with a sane time step.");
}
accumulatedTime += elapsedTime;
while(accumlatedTime >= SIMULATOR_FREQUENCY)
{
  simulator.runOneStep();
  accumlatedTime -= SIMULATOR_FREQUENCY;
}

Without that kind of protection you quickly fall into an update death spiral. One update takes more time than you allow, and when you come through the next time two updates need to run to catch up. Then because you spent more time it needs to run three, then four, then soon the game is doing nothing but trying to catch up.

 

Since I'm sure you have followed the route mentioned above to decouple your rendering loop from your simulation loop happy.png it doesn't matter if the renderer has problems since you can simulate multiple times in a row, and if your simulator is running slow your renderer can interpolate between the two values. Fixing your time step is an important part of having a reliable simulation.




#5197930 Need advice on C++ reflection system

Posted by frob on 13 December 2014 - 01:00 AM


I don't see how that follows. The translation mechanism of C++ works just perfectly fine with reflection, optimizations and all. I have a few multi-million line codebases and more than a few bases of much smaller size floating around as testament to that.

You should though follow the rule of reflecting only what you need. For instance, with a class, there's little good reason to automatically reflect every member variable or function. Reflecting the ones that you need to serialize to disk or expose to GUI editors or bind to the scripting language, however, will by its very nature never be able to keep dead code or data alive (the non-reflection approach would've linked in the class and any of the bound function symbols as well, and member variables can't be elided by the compiler anyway).

You may be right or not about "little good reason", but the reasoning is not what I was referring to.

 

Reflection in languages like C# and Java is very different from, and incompatible with, the old compilation model used by C and C++.

 

 

Reflection in modern languages embeds every potential function, every data member, every generated item. Even if you never reference it in your code the items are generated.  If you use generic/template elements every variant is generated and enumerable. You can open the executable and see every generated function, every private function, anything that was coded. It will all be there by default.  You can take steps to disable it but most people don't. Many games that use the languages know full well that others will use it, and they serve as a launching pad for the modding community.

 

The object and library/archive model eliminates everything that is not used in the final program. Uncalled functions are eliminated. Template methods that are not used are never expanded, and sometimes those that are used are completely expanded inline and never generate a signature. Archives and libraries do not bring over the full contents, instead only bringing over the bare minimum the linker deems necessary. You can take steps to ensure items are generated but that is rarely done. If you want to allow others to poke into your game you need to expressly provide that functionality yourself.

 

Going for a concrete example.

 

In C#, you can use something like HashSet<foo> myHash = new HashSet<foo>;  Then in your code you add items, iterate over the items, and nothing else. Build it, open it up in the right reflection tools, and you can see every method that would be available to HashSet<foo>.  You have access to functions you didn't call, functionality like Clear(), Contains(), SelectMany(), or whatever you want. The functions you used, like Add() and GetEnumerator() will also be there. If you want to attach with the right tools and call functions that were not used in your program like Count() or First(), those functions can easily be found by reflection. The whole class in its entirety all exist in the end product and can be called by an attached program unless you take rather extreme steps to remove them. You can repeat this with your own generic classes as well, build what you want and it will all be present in the final executable by default.

 

In C++, you can use roughly the equivalent unordered_set<foo> myHash; Then you code you also write stuff that adds items, iterates over the items, and does nothing else.  Build it, open it up in your favorite tools or just look over the map file ... and you will probably find zero addressable function calls for it, perhaps you may find a small number of internal utility functions.  The template items like clear(), find(), equal_range(), they do not exist. They were never generated. They cannot be addressed nor can they be called with a tool attempting to reflect in to the code. The functions you did use like add() and begin() also probably do not exist as functions with addresses, they were almost certainly moved inline. If you attach to the code by some unknown reflection method, the functions you didn't use like count() and find() were never generated and therefore cannot be called. Practically nothing from the class exists in the end product unless you take rather extreme steps to the signatures specifically and ensure they are all addressable. You can repeat this with your own classes and custom libraries as well, build what you want and only the absolute minimum required will be present in the final executable by default.

 

This is the hurdle you need to overcome if you want to have modern reflection in the old archive-based compilation model that C++ uses. 

 

It is something that can be overcome if you need to with sufficient compiler support.  Microsoft did it with C++/CLI and it took them nearly a decade to get it mostly working okay, but even so it is incomplete for a huge amount of code. If some specific functionality is missing you can special case it into the reflection mechanism.  There were some attempts in GCC to get reflection working but the code branch died roughly in 2005 due to lack of interest and demand.

 

 

That is why I wrote originally, "it is important to ask how you intend to use the system".  If your intention is to be able to call a limited number of functions and look up the names and offsets of specific variables, that is one thing and it can be accomplished. That is how C++ game engines open themselves up to modding communities. It takes effort but can be done.  If your goal is to make generic C++ do what Java and C# do with reflection, that will require rewriting large chunks of the compiler and linker.

 

So far only Microsoft has spent the time, effort, and money necessary to get it working, starting in to the project around 2001. It was pretty horrible until around 2008. They still tinker with it, and today in 2014 (over a decade since they started on it) the compiler's C++ reflection-generation system mostly works okay, but is far from perfect.




#5197883 Need advice on C++ reflection system

Posted by frob on 12 December 2014 - 04:50 PM

In Microsoft land, C++/CLI has some reflection built in, and if you are mixing your code with other .net stuff this can be easy and powerful.

 

 

Reflection is a great tool, but is contrary to the nearly sixty-year-old compilation model. The model used by C++, C, and even older Cobol and Fortran, favors eliminating unused stuff and minimizing data. Optimizations by the compilers will eliminate dead code, exclude things that the compiler doesn't see is useful, and eliminate intermediate elements whenever possible.

 

 

For C++ specifically, it is important to ask how you intend to use the system. Some features are limited to compile-time only, others are dynamic-only, some you could access differently for both.

 

For instance, at compile time and at link time you might be able to leverage SFINE to potentially implement some reflection-like features. Depending on your compiler choices you can provide weak symbols as alternatives to help you call functions that may or may not be present when the module is built, but are present at link time.

 

 

Beware about using self-registering code like you suggested.  I've seen that handled as a class that creates a single global instance, and as part of the constructor the registration takes place. Optimizing compilers frequently choose to not generate code if they don't have to. This can have a side effect that even though you wrote code for a template and created an instance, only a small number of the functions are actually available. Or if you rely on side effects that are difficult for the compiler to track, the compiler may not see them and decide to elide the code in a way that breaks your intention. 

 

Even if you require registration it can be possible for functions to be eliminated by the compiler or linker. I've been on projects where we used self-registration systems where the overly-smart compilers dumped the functions and globals at link time since it assumed they were unused, and we needed to resort to various linker options to force the system to mark them as used.






PARTNERS