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!


Trienco

Member Since 22 Aug 2001
Online Last Active Today, 02:23 AM

#4975026 Design verification, (UML class diagram attached)

Posted by Trienco on 30 August 2012 - 09:56 PM

I really don't think you should make your game objects meshes. They might HAVE a mesh used for rendering, but it's not what they ARE.

The design doesn't really seem to try and separate game logic from display.

I'd also question if it makes any sense to have specific classes for stuff like a Warehouse or a HandTrolley. That would seem like the kind of stuff that is defined by data, not by class.


#4970823 Lighting in caves

Posted by Trienco on 18 August 2012 - 07:04 AM

Minecraft in particular is having a very specific lighting where each cell has two lighting values ranging from 0-15 (one for sunlight and one for artificial light). Sunlight is propagated downwards at full intensity, but loses intensity "sideways" (reduced by 1 per cell). Artificial light is always reduced by 1 per cell. Also, the lighting value of a call is not the brightness of the cell (or geometry in that cell), but the brightness used for adjacent faces. In fact, all cells filled with a solid have lighting values of 0.

Daytime doesn't matter (sunlight doesn't change direction and is always straight down). Darkness (at night) isn't applied by updating and recalculating all sunlight values, but by simply deducting a darkness value from the existing sunlight value.

There is no easy way to recreate that system with basic 3D API functions and it only makes sense for a grid/block based world like Minecraft.


#4939512 Cleaning up a vector of pointers?

Posted by Trienco on 12 May 2012 - 12:34 AM

Not to mention that you better make sure that there is absolutely no location in your code that creates a copy of the map or calls a function where you pass it by value. It at any point you create a temporary copy of that map, all your pointers will be invalid and your walls deleted.

If that is the case, it might be time to google for the Rule of Three.

Did you place a breakpoint in the destructor and make sure it only gets called once? Debug output might actually work better, as some debuggers are notoriously bad with breakpoints in destructors.

If in doubt, place a breakpoint in the destructor of your Wall class and check the call stack when you hit it to see where it's getting called.

Things don't get magically deleted on their own. A more far fetched explanation would be writing out of bounds and screwing up the internal pointer of the vector.


#4937282 Bullets Not Updating

Posted by Trienco on 03 May 2012 - 10:27 PM

Also your initBullet function is going to do exactly nothing right now.


#4936663 Confused as to why this wont compile

Posted by Trienco on 01 May 2012 - 10:28 PM

Isnt it the job of #pragma once to stop multiple inclusions anyway (using VC2008)?


I strongly suggest to read Antheus post, because I really wish more people would actually care about how compiling and linking works.

#include doesn't mean "use this as a source to look up stuff". It means "recursively copy/paste the whole frigging thing and everything it includes". If in this whole mess of headers including headers including headers the same header appears twice, then and ONLY then pragma once or inclusion guards come into play.

Header files on their own are never compiled, so you can't have a project that is "header only". Nothing will really happen when compiling this.

Every .cpp file is compiled completely in isolation. It doesn't matter what might be in other files. Some compilers might make special exceptions for inline and template code, but you might notice that those are exactly the two things that should be entirely defined in header files, if you expect them to work.

After every .cpp file in your project has been compiled to an .obj file, the linker will try to piece them together and make the final binary (.dll, .exe). In THIS stage, you got your error about multiple definitions, long after anybody cares about headers or inclusions guards. All that matters is having the same definition in two different .obj files.


#4935172 Programmer already, just new to gaming

Posted by Trienco on 26 April 2012 - 01:14 PM

I'd actually advice against thinking of a game as "moving images around". Images aren't the game. A sprite is not the player or a monster. It is just the method used to _visualize_ them. The game state shouldn't care about images or 3d models. Games are a perfect example for model-view-controller and short circuiting view and controller by treating the view as the model often results in a mess.

Ideally, you can replace your view of the game world without major rewrites (ie. replace 2d sprites with 3d models, a top-down view with a freely moveable camera, etc.). That means NOT saying "left moves the image" but saying "left changes the player position" and "when displaying the game state, place the image according to the players position".


#4933705 Measuring performance - overdraw

Posted by Trienco on 21 April 2012 - 10:53 PM

And finally, one more thing that bothers me most. In the very first scenario I described in this thread, with the plane mesh filling the whole screen and taking 190ns to render, I noticed that depending on how close the camera was to the plane, the render time varied, despite the fact that the plane was the only geometry entity filling the whole screen. I noticed that the closer the camera was to the plane, the less time it took to render it. My times varied from 180ns (as close to the plane as possible without frustum near plane clipping) to 220 ns (as far as possible to still fit the entire plane on the screen).


Why is that a surprise? You sound like you somehow moved from thinking that only the number of polygons matters to thinking that only the number of pixels matters. You get closer to the plane, more geometry gets clipped, fewer triangles get rasterized -> less overhead. You are measuring ns. There are about a gazillion factors that come into play, many of them hidden from you by things the driver might be doing or just the way stuff happens in the hardware.

How are you even measuring the exact timing for vertex and pixel processing when these things should be processed in a pipeline on the hardware? If you have more than one triangle, it's not first going to process all vertices and then do all the pixels. One triangle is done and gets rasterized/shaded while at the same time the next triangle gets prepared. There are caches, the second time around a vertex might not even be processed anymore. Hardware today has unified shaders that can be dynamically used for either vertex or pixel processing, completely changing how long vertex and pixel processing will take.

There is little to no point to make ns measurements and expect any obvious and linear relationship between numbers. Not on modern hardware.


#4932367 Are Pack Files (PAK, ZIP, WAD, etc) Worth It?

Posted by Trienco on 17 April 2012 - 10:26 PM

I feel the need to add a good example of the media understanding enough about to screw you over.

Over here, we pay a small fee on every blank medium (from printer paper to DVDs) than can be used to copy stuff. At a time they even tried introducing it for RAM, arguing that there are "temporary copies" created in RAM. In return we have the right to create "private copies" and distribute small numbers to friends (rule of thumb says around 7 and you must be familiar with the people you give them to).

Then the lobbying began to change copyright laws and just as Hodgman said, it was now illegal to copy anything with a copy protection (there was a wording about "effective copy protection" which I bet has been removed by now, because obviously if you can copy it anyway, it wasn't that "effective"). As a result, everything is copy protected, we still pay that fee for everything, but the "private copy" thing has become purely hypothetical.

In short: don't underestimate the amount of legal stuff companies and lawyers can throw at things. Even if they don't have a clue about the technology they will still try to drown in licenses, just to legally be on the safe side. Particularly if you use licensed art, expect them to enforce some way make it non-trivial to just extract and distribute it.


#4932015 Help fix pong enemy paddle please?

Posted by Trienco on 16 April 2012 - 09:47 PM

Of course it is. Put a breakpoint in there when it does that and you might notice that the ball is above the paddle, then the paddle moves and is above the ball, so the next frame it will move down again and on and on and on.

A concept you might want to look up is called Hysteresis (IF you really want to keep that approach).

Even if you add an area where the paddle doesn't move it won't look very natural to constantly stop-move-stop, because a real player estimates where the ball WILL be when it reaches him. AI can easily calculate that, add a random error and simply move to that position. To look more like a human player, the calculated position can be adjusted every once in a while as the ball gets closer and the random error gets smaller.


#4931628 I include a .h and my project expodes with errors :(

Posted by Trienco on 15 April 2012 - 10:23 PM

Maybe it's just me, but I would really get into the habit of NOT using #include in header files except when you really need them. Using forward declarations wherever possible means not ending up with including includes that include includes that end up with every single source file including almost every header in your entire project.

If your class is only showing up as a pointer or reference in some other header, do NOT include the entire class header and just forward declare. After a while it will be as natural as not putting 'using namespace' in header files and just type out the entire names.


#4931348 Beginning c++ through game programming third edition, solutions to exercise a...

Posted by Trienco on 14 April 2012 - 10:57 PM

There is no point in creating a variable for every single enum value (and get into the habit of declaring them const, when they aren't supposed to change)

The location of declaring choice is plain weird, declare them right before they are used for the first time and in their own line (and initialize... always). What if you fail to read because the user entered "slkjsfg"? Choice will still have some random value.

Don't use if/else chains when a switch is perfectly fine.

Put success _inside_ the loop, inizialize to true and avoid setting it in every single if block (removing the need to do something in a million places removes the possibility to forget it half the time).


#4931137 Importance of structs?

Posted by Trienco on 14 April 2012 - 01:58 AM

While technically there is no real difference, you might sometimes find code where structs are used for plain data and classes are used when it also contains functions to operate on that data. So if you do want to make a difference, make it the distinction between data vs. behavior. Or in other words, if your thingy is supposed to "do" something, call it a class, if it's merely a dumb container for data, call it struct.


#4931116 Importance of structs?

Posted by Trienco on 13 April 2012 - 10:45 PM

You put data in structs. Especially if you need that data "as a whole". Imagine you have a bunch of things that can have an address (persons, shops, ...). You do NOT want to spam street/zip code/city/country as separate members into every single one of them. Most likely you will have functions that operate on addresses (printing them on labels, doing a sanity check). And again you wouldn't want each of these functions to take each value as a separate parameter. Even more so you may have a function that should create and RETURN an address. Functions simply can't return more than a single thing (unless you go with ugly workarounds like having half a dozen output parameters, which are an ugly concept that should be avoided whenever possible).

In short: whenever something belongs together (and will be used more than once), put it in a struct.


I guess this needs some example to demonstrate how utterly messy and unmanagable things would be without structs.

Start simple, you want to manage people. Let's say they have a name, age and gender. Let's also use a simple array instead of lists to store them. Also, have a function that can print a persion.

Without structs
string name[50];
int age[50];
int gender[50];

void printPerson(string name, int age, int gender)
{
   cout << name << age << gender;
}

or even some really bad style, that requires all your above arrays to be (semi)-global
void printPerson(int index)
{
  ///
   cout << name[index] << age[index] << gender[index];
}


With structs:
struct Person
{
   string name;
   int age;
   int gender;
};

Person people[50];

//I deliberately ignore the option to pass by reference
void printPerson(Person someone)
{
    cout << someone.name << someone.age << someone.gender;
}

//There is now no good reason to pass an index to the function.

Let's say you need a function to create a person or read one from a file


Without struct
void readPerson(File file, string* name, int* age, int* gender)
{
    *name = ...;
    *age = ...;
    *gender = ...;
}

using it would require this:

string name;
int age;
int gender;

readPerson(file, &name, &age, &gender);

If you had a struct, it could be easier

Person readPerson(File file)
{
    Person person;
    person.name = ...;
    person.age = ...;
    person.gender = ...;

    return person;
}

and using it would just be

Person person = readPerson(file);


Now let's add Addresses and Shops without using a struct for the address.

struct Person
{
   string name;
   string street;
   string zip;
   string city;
};

//Yes, this is easy to write AT FIRST by just copy/pasting stuff... and you will hate yourself for every single Ctrl+V when you need to add the country to the address EVERYWHERE

struct Shop
{
   Person owner;
   string name;
   string street;
   string zip;
   string city;
};

compare that to
struct Person
{
   string name;
   Address address;
};

struct Shop
{
   Person owner;
   string name;
   Address address;
};

In short, structs let you structure your code and avoid redundancy,usually resulting in lots of copy/paste. If you find yourself copy/pasting whole blocks of code, stop it and ask yourself why you even NEED to do that in the first place.

Structured code means less work, easy to maintain, extend and use. Also a lot less bugs, which is what happens when code becomes a huge mess where it gets increasingly hard to figure out what is happening when, where and how.


#4928117 how to force global variable which define in a static library to initialize?

Posted by Trienco on 04 April 2012 - 12:05 AM

One of my "favorite" issues that caused a lot of pain.

With VC++ you usually get away with actually referencing the variable somewhere (a dummy read in a destructor or whatever). GCC will actually delay it until the very first time the variable is actually accessed. So you can not rely on any side effects caused by the initialization to actually happen before main.

In short, trying something like this will usually not work:
bool classXisRegistered = registerClassX();

For VC++, you might get away with a simple reference somewhere
SomeClass::~SomeClass
{
	bool dummy = classXisRegistered;
}

For GCC we actually had to create static global objects that would have the desired side effect in the constructor. And based on all the weird rules about how a compiler may optimize, I wouldn't rely on even this to work for absolutely every compiler.

template
class Registrator
{
public:
   Registrator() { registerClass(); }
};

static const Registrator registerClassX;

By the way, this method still failed on another project, where this code was in a static lib that was used to build a dll. Somewhere along the way the linker still decided to drop it. They moved the entire code to be a direct part of the dll.

I played around and tested a few methods, which ended up in a somewhat convoluted test:
http://festini.devic...factorytest.zip

But I guess the easiest solution is to simply not rely on any side effects of global static variable initialization.


#4927498 Newbie here, I wish to start.

Posted by Trienco on 02 April 2012 - 08:03 AM

Though it would technically be possible to create a "turn based" Pong on the console with nothing but the standard library.

Text-based Pong ftw!
>>> you move your bat:
>>> 4
>>> units
>>> you miss the ball!
>>> **** YOU LOSE ****


Well, I was thinking more along the lines of an o for the ball and a couple |s for the bats. The reason I said "turn based" is because I don't know any non-standard way in C or C++ to get keyboard input without blocking.

TL;DR: try and be more open-minded. Nobody's forcing you to anything but it doesn't hurt to look beyond what one already knows and actually try it out long enough to get comfortable with it - who knows, you may actually like it!


To emphasize this point: I had co-workers with up to 40 years of experience in C that unfortunately spent at least 30 of them stubbornly refusing to learn anything new. Their code tended to be messy, not because you can't write clean code in C (you can), but because all the extra work resulted in taking shortcuts and just be sloppy to finish in time. So you had code with plenty of bugs that were also a pain to find in all that mess.

Of course I might simply be biased because I spent many years being the guy that had to find and fix bugs in other peoples code whenever the bug reports came in.

Nobody expects anyone to instantly transition to C++ and write what is so nicely called "modern C++". But flat out refusing even the option to make use of some extremely useful and time saving features out of a feeling of being "overwhelmed" by all the new possibilites? Really?




PARTNERS