Jump to content

  • Log In with Google      Sign In   
  • Create Account

Banner advertising on our site currently available from just $5!


1. Learn about the promo. 2. Sign up for GDNet+. 3. Set up your advert!


Bacterius

Member Since 28 Feb 2011
Offline Last Active Today, 03:50 AM

#5225672 Why Does Everyone Tell Newbies To Make Games?

Posted by Bacterius on Yesterday, 11:24 AM

In some ways many game engines/frameworks available today are simply too high-level to write games like Pong or Tetris in their most basic form, with their 3D-oriented abstractions (cameras, projections, models), interactive physics systems, node-based programming and whatnot, and they are most likely to confuse and discourage you than teach you anything.

If you are starting out just moving up from text-based games, all you really want is an event loop and a canvas, so that's what I'd recommend.


#5224857 C++ Ternary operator ?: surprising conversion rules.

Posted by Bacterius on 22 April 2015 - 09:05 AM


Well, if I didn't assign it to anything, or return it, there would be no need to convert it at all, would it?

 

The expression still has to evaluate to some typed value because of the way the grammar is defined (and parsed). That the expression eventually ends up unused doesn't free the compiler from the obligation to reject invalid code. Also consider:

(cond ? new B() : new C())->foo(...);

If both B and C had a member function foo inherited from A, which of the three would you expect to be called? What if B has a member function foo but not C? What if only A does? It seems like a pretty big source of confusion to give meaning to such expressions IMHO. But I think I agree with BitMaster above in that the operator was primarily not designed with polymorphism in mind.




#5224853 C++ Ternary operator ?: surprising conversion rules.

Posted by Bacterius on 22 April 2015 - 08:41 AM

Probably the most logical explanation is that the ternary operator simply isn't defined by the standard to infer the strictest common base type of its arguments, so, well, it doesn't. And I also think it would be kind of weird if the ternary operator had an unspecified return type completely dependent on the various types visible from the ternary operator's site (I guess in your case the only reason you would "expect" it to return a value of type A* would be because that's what your example function returns, if not it would genuinely be an unexpected "feature" for the compiler to resolve the ternary's return type to some random base type in my opinion).

 

But I'm sure someone later in the thread will post some C++ template madness that does just that, for kicks biggrin.png




#5224408 is it possible to program one app with different languages?

Posted by Bacterius on 19 April 2015 - 09:25 PM

Of course, directly calling a function in a program (or library) in another language is not the only way to communicate with it. You can very well make any two programs communicate via network or IPC, this is how DB queries and remote procedure calls generally work. That's also an example of programming an "app" with different languages: write the backend in one language, the client in another language, yet they can still communicate. This is probably not what you meant (you probably mean within the same process, e.g. Lua and C/C++) but thought I'd point it out.




#5222834 Limited lifetime of returned objects issue

Posted by Bacterius on 12 April 2015 - 06:48 PM

I don't think monitor names are unique - for instance my two monitors have the same name except one has 21" at the end and the other has 22" - and in my experience this kind of reverse lookup stuff tends to be brittle and unreliable. In the docs I see that you can register a callback to be notified of monitor connection/disconnection, I think I would personally use this to display to the user the *available* monitors and use it to make sure you never hold onto a pointer to a disconnected monitor.




#5222612 Is this C code using pointers valid?

Posted by Bacterius on 11 April 2015 - 10:23 AM

 

			current = (serverInfo*)realloc((*pServers), sizeof(serverInfo) * (serverCount+1));
			if (current)
			{
				pServers = &current;
			}
			else
			{
				return -1;
			}
This part is broken.... I think (the logic is confusing).
You reallocate the input data, so it seems that you want to pass that new allocation back out to the caller. If so, it should be:
(*pServers) = (serverInfo*)realloc((*pServers), sizeof(serverInfo) * (serverCount+1));
Anywhere where you're taking the address of a local variable should be cause for great inspection of the logic smile.png

 

 

Careful with this though, if realloc fails and returns a nil pointer you've lost your original pointer and you're screwed! biggrin.png Unless the caller knows that it has to make a copy of the input pointer, which can get complicated fast with more complex situations.




#5222610 Is this C code using pointers valid?

Posted by Bacterius on 11 April 2015 - 10:08 AM

Consider using array notation whenever appropriate, it's often a good idea to distinguish pointers to objects from pointers as arrays in your code and as a bonus it helps reason about the different levels of indirection involved. In fact non-temporary arrays should probably eventually be wrapped into a struct and given proper access patterns and ownership if they are used regularly.

 

Just because it's written in C doesn't mean it has to be hemorrhaging asterisks and ampersands, giving higher-level structure to your code beyond what the syntax offers is part of what differentiates high quality, readable/maintainable code from procedural, spaghetti code with plenty of side effects smile.png

 

 

I voted your answer down FRex because without any concrete examples it is unnecessarily negative.

Saying that it's "obfuscated on purpose" and that "it's not even proper C" is net helpful. Unless you demonstrate how to do it 'properly'.

Just my thoughts.

I am not really an expert in C so I can't offer any advice on how sound/unsound the code is.

However, the code doesn't look awful at all. ;)

 

FRex may be a bit blunt, however he does raise some good points, the code has a serious flaw, although I think besides the main problem of the reallocated array not being returned outside the function (you want *pServers = current) the rest mostly has to do with structuring the code, architectural concerns, avoiding redundant variables and better variable scoping, maybe using snprintf to build the server name from the server index without going through itoa and a temporary buffer, ... although those aren't the pointer problems the OP requested comments on.




#5222599 preventing system crash or power outage from wiping savegame: best methods

Posted by Bacterius on 11 April 2015 - 08:20 AM

 


But really, that's overkill.

 

yeah, probably, but what can i say? i'm a one percent-er. just because the engineering products we develop are for entertainment purposes doesn't mean we should become complacent and not try to deliver as solid a product as possible to the consumer. loading and saving files in a manner that can handle power outages and other crashes is not that difficult.

 

 

I think the point people are making here is that the environment of a typical PC gamer's computer is not controlled enough to be able to 100% guarantee that data will not be lost anyway. You may be able to get something incredibly reliable by using the atomic swap idiom on certified hard drive hardware/firmware/drivers with code that's been shown to be bug-free by a theorem prover, the whole thing being backed up by a triple redundant storage system inside a shielded, radiation-hardened nuclear bunker with its own power source.

 

But the average gamer has a basic hard drive with generic drivers and consumer firmware (which is probably lying to you anyway when asked whether it has actually flushed data to disk) and a power supply that can go out at any instant, not to mention the possibility for your program to simply be killed by a bluescreen or a hard freeze of the system, or the hard drive failing just as you finish writing to it, or a cosmic ray to flip a critical bit in memory that causes your program to malfunction and write corrupted data to disk without even being aware of it.

 

This is a bit reminiscent of Amdahl's law; you seem to be under the impression that you can achieve 100% reliability by simply writing "good code" when writing savefiles to disk, that there exists some sequence of statements that essentially guarantees that no player progress will ever be lost. But it turns out that you don't control all the variables, many environmental factors are independent of your program and will still find a way to screw up the process *no matter* how good your code is. In other words there is an upper limit to how reliable you can get the process given those factors, this is effectively what you have to "work with". It might be 95%, 99%, or even 99.9% for the everyday user (this depends on what your program does, the assumptions it makes and what it ultimately runs on) but it's not going to be 100% because there are way more bizarre things that can happen than conveniently timed power outages (with increasingly low probability, thankfully).

 

In short, don't spend too much time trying to solve issues which have underlying causes that you have no control over, instead work with what you have to produce something that works almost all of the time under normal circumstances and, should failure occur, gives the user a chance to recover in most cases, again under normal circumstances. In this particular instance the usual trick of writing the savefile to a dummy temporary file and "atomically" moving it to the right place when everything has been written works pretty reliably on today's systems, and in the unlikely event that something does go wrong (something well-defined at the level of your program that your program can detect and respond to in some way such as "execution halts while writing to temporary file, garbage was written but temporary file was not renamed to a proper savefile") the player will hopefully still have his before-last savefile to continue on, and maybe a notification that something has gone wrong with the last save, instead of being presented with a corrupted save. So this is a good, cheap and easy solution that seems to work well, and indeed it has been used for many years with very few problems.

 

If you do want to do even better than that (should "better" exist on at least some system/hardware that you are targeting), then, like people said before, instead of rolling your own you may want to look into how high-reliability software like databases have solved the problem, and do not be surprised if you find that the way they do it is actually not that much better than yours practically speaking when you have little to no control over the environment your program runs in; in general it might address a few more corner cases, have special code for various hardware combinations, and be more conservative overall in how it handles data, for correspondingly rarer failure cases (this is not to say that databases are unreliable, this is just to point out that the less control you have, the less guarantees you can make, the less you can do).




#5221294 What C# Library/Framework to make games

Posted by Bacterius on 04 April 2015 - 05:07 AM

I believe that MonoGame has everything that SlimDX has (is it maintained still?) and then a bucketload more smile.png

 

SharpDX may be a more up to date version of SlimDX, I believe. Note the two projects are not related as far as I know, but the API they expose is basically identical since they are both plain D3D wrappers.




#5221059 GCC -malign-double

Posted by Bacterius on 02 April 2015 - 10:00 PM

As I understand it this flag doesn't really do much on most x86_64 ABI's since long longs and doubles are already aligned on a two-word boundary. However if that is not the case then you must be very careful what you apply that flag to, because if any non-PhysX structure declarations (in library/system headers and so on) get affected by that flag and their layout suddenly differs from the layout expected by their implementation, which does not expect malign-double, there's no telling what might happen, but it will almost certainly end with stack corruption, an eventual segmentation fault of your program, and lots of tears.

 

I would recommend controlling the usage of this compiler flag as strictly as possible, in other words limiting it to the PhysX headers (or wherever they are needed) and nothing else.




#5220334 The Gamination Company

Posted by Bacterius on 30 March 2015 - 05:53 PM

Why'd this topic get moved to beginners? This is not a beginner topic, even though I am a beginner, it doesn't correlate...
 
This belongs in the Indie Projects, because it IS an official indie project


It's not, it's a recruitment thread, and as such belongs in the Classifieds as Hodgman said.


#5220155 Increase power of light in a Pathtracer

Posted by Bacterius on 30 March 2015 - 04:29 AM

The RGB color of my light is already at 255 and it is still too dark.


Sorry, I meant 50/100 as in floating-point values, that would translate to 12750 and 25500 in "integer" RGB values. Basically color is not really limited from 0 to 255, that's an artificial limitation of your display hardware. Most raytracers work in floating-point colors that can range from 0 to infinity (in principle) and then apply tonemapping to the final render to bring them back to a range where they can fit in an RGB color to be displayed.


#5220153 Increase power of light in a Pathtracer

Posted by Bacterius on 30 March 2015 - 04:22 AM

I have a recoursive Trace function which checks on intersection if the hitObject is a light source, if so it returns the object color.


So the object color in this case (for light sources) is essentially its intensity for R, G and B channels. Increase the value of those channels, and your light will become brighter. It's not unusual to have values for the "color" of a light source that are greater than 50 or even 100. And then tonemap when your renders start to become oversaturated (= washed out).


#5219649 Global Consts

Posted by Bacterius on 27 March 2015 - 10:20 AM


The thing is, there's no "magic" in this number.  If you're drawing quads you expect to see the number 4, or a multiple of 4, and by having it in-place you immediately get to do a visual/mental sanity-check on the code rather than having to go scoot off to a header file somewhere else.  In this case 4 is not a magic number.

 

There's a related discussion over at http://programmers.stackexchange.com/questions/266717/are-all-magic-numbers-created-the-same which I'm sure many of you will have already read... and personally I agree. Normally only a small part of your program needs to know that a quad has four vertices, and I'm pretty sure that number isn't going to change without the "quad" part changing as well. But if naming it VERTICES_PER_QUAD or whatever the case may be gives you warm fuzzies...




#5218211 Tiny .ini parser

Posted by Bacterius on 22 March 2015 - 02:23 AM


"Assuming you're on Windows.." does not imply that it is cross platform.

 

I was saying that because Acharis asked for a cross-platform solution in this post... these things can be easy to miss, and it seems gratuitous to lock yourself to the Windows API when (a) there are plenty of drop-in libraries that are already cross-platform and (b) you can write your own basic parser anyway in under ten minutes if you really wanted to. Also, ini files aren't Windows specific, they just happen to be found more on Windows, you can certainly store your settings in any format you like on any system you like (let's face it, key-value stores aren't exactly an uncommon format).

 

Having a library that abstracts the actual configuration data from its storage sounds like a useful thing to have though.






PARTNERS