Jump to content

  • Log In with Google      Sign In   
  • Create Account

We're offering banner ads on our site from just $5!

1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


Trienco

Member Since 22 Aug 2001
Offline Last Active Yesterday, 10:55 PM

#5005961 Is C++ too complex?

Posted by Trienco on 01 December 2012 - 01:10 AM

I am still of the opinion that exceptions are too costly to use for anything but exceptional situations.


To be fair, that's why they are called "exceptions" and not "common stuff happening" or "code flow control construct". As such you could easily argue that someone using exceptions for situations that aren't actually "exceptional" errors is probably using them wrong.

vector::at throwing at an invalid index is fine (it IS kind of a big screw up), std::find throwing if an element isn't found would be silly (as it's a perfectly expected case). Which leads to a nice anti-pattern called "expectation handling".

c++ is not too complex, just you need some dedication and you can easily learn the c++...
first try to learn c it will help you in learning c++ easily and in efficient manner..

dynamicmounting.com


Strangely enough, everytime I hear someone claim "C++ is easy" it is accompanied by "C with classes" and the person in question not even knowing enough about C++ and its countless dark corners to realize just how little he/she actually knows.


#5004115 Code::Blocks "warning: deprecated conversion from string constant to ‘ch...

Posted by Trienco on 25 November 2012 - 11:24 PM

I use tolua++ to generate Lua bindings and unfortunately, as it currently stands, the generated binding code is filled to the brim with these warnings.


Maybe I'm confused by the name, but ++ suggests that it creates bindings for C++. Everything producing "char*" instead of "const char*" (unless the function might actually modify the string) should be considered flat out broken and worthy of a bug report. Mostly because I'm extremely sick of having to add hacks and workarounds when using C++ strings and c_str. Casting away the const feels like slapping a time bomb and copying the string to a vector<char> is just irritating.


#5003384 [C++] Delayed action of srand() - coordinates for object

Posted by Trienco on 22 November 2012 - 11:27 PM

Well, L.Spiro has a version that will at least trigger at all (when one coordinate is getting close enough), while the other version looks like in the end the ball will reach one coordinate first, then start jittering around on one axis, move only along the other axis and finally find a new destination. It also means that if one coordinate is reached, the balls will effectively move at only half the speed.

So obviously I second the approach of using vectors, simply because the other code only allows for 45° steps in motion and I doubt that sudden changes of direction while heading towards a destination are intended.


#5001444 Completed Tic Tac Toe - Critical Critiques and Advice

Posted by Trienco on 15 November 2012 - 11:18 PM

I think you will get the most in terms of learning experience and better design by not assuming a fixed board size and hard coding every possible win condition. After all, the real core of programming isn't knowing language X or memorizing whole libraries, but about problem solving.

How would you write it, if the board size can be configured to 4 or 5? Ironically, you should find that your code will get a lot shorter, cleaner and contain way fewer messy if-else and switch-case constructs.

Once that is working, how would you handle the win condition not being n in a row (where n equals the board size), but a value that can be configured independently? You should find this to be a very small adjustment to your existing code (okay, I'm lying, unless you didn't realize that only two diagonals need to be checked for n = board size).

What if the board doesn't have to be square? Again, this should end up being only a minor change.


#5000465 Switch vs if else

Posted by Trienco on 12 November 2012 - 10:59 PM

That's a bit too general, don't you think? Without using switch or a bunch if-else statements, what does an event dispatcher look like? How do you implement a factory function?


Event dispatchers can use runtime type information or simply strings and just forward events to all handlers that registered themselves for certain message types. I'd actually be a bit sceptical if my event dispatcher starts switch/casing over event types. Same for a factory. A factory using a big switch/case is usually considered the "naive" approach and while typically good enough, it's probably the least desirable implementation. Generally you do not want to touch your factory (or event dispatcher) every single time a new class/message is added.


#4997877 C++ pointer strangeness

Posted by Trienco on 05 November 2012 - 11:31 PM

Of course reversing a string in C++ is kind of boring:

string original("some text");
string reversed(original.rbegin(), original.rend());


It also avoids all the other bugs and issues in the C-style implementation above (loop too short, calling strlen on every single iteration, passing pointer by value, the dreadful "function internally allocating memory" thing).


#4997443 Error accessing vector member

Posted by Trienco on 04 November 2012 - 11:21 PM

Of course now you have to ask yourself who is responsible for cleaning it up and when should that happen. Rule of thumb: for every "new" that isn't assigned to a smart pointer, there must be one (and only one) "delete".


#4996096 Manual construction and destruction

Posted by Trienco on 31 October 2012 - 11:55 PM

//Delete old location (without destructing).
delete memoryA; //How's it know how much memory to delete? Do I need to cast back to void* before calling delete?


If you want to know that in detail, try showing the memory right before your allocated chunk. Chances are your compiler placed all the memory management info right there.

An easier answer: in the same way free knows how much memory to free when pointed at malloc'd memory.


#4988956 A strange issue with the scope of the << operator

Posted by Trienco on 10 October 2012 - 10:40 PM

If in doubt, never rely on expressions to be evaluated in any particular order (this behavior can change even between debug and release builds).

Notable exceptions: logical operators (&&, ||) and the comma operator (the operator, not just any comma like in parameter lists)


#4985281 tictactoe

Posted by Trienco on 30 September 2012 - 01:24 AM

This piece of code: "rand() % 9 + 1"generates a number between 1 and 10. In C++, arrays begin at 0, so you may not want the +1 there.
(An array with 10 elements, goes from 0 to 9)


Nitpick: the number will be between 1 and 9.

About the implementation of the second option. You actually fooled me, as my first impression was you determine a number between 0 and emptySpaces, then make as many steps from the start (skipping filled spots). In that case you should never have to wrap around. But with your approach of starting at the selected spot and then skipping ahead until the first free cell, is the first part even necessary (as in: does it produce better randomized results)?

My impression would be that it might make it less random. If the first 4 spots are filled, you would ways end up with the 5th spot: 5 spots are empty, so spot = rand() % 5 = 0-4. In each case you get spot = 4.

So I think you should either always create numbers 0-8 and skip empty spots as above, or if you do create a number using only the free spots, it would probably be something like this:

int steps = rand() % numberOfEmptySpaces;
int spot = -1;

while (steps >= 0)
{
	//If free, decrease step count
	if (board[spot] != 'O' && board[spot] != 'X')
	{
		 --steps;
	}
	++spot;
}

place_marker(spot);

I believe that should create an equal probability for each spot.

Alternatively (and somewhat more cumbersome) you could add an extra layer of indirection by keeping a list of empty spots and randomly picking an index from that list.

   //Declared somewhere and initialized with the board
   vector<int> freeSpots; //Fill with 0 - sizeOfBoard


   const int idx = rand() % freeSpots.size();
   place_marker(freeSpots[idx]);

   freeSpots.erase(freeSpots.begin() + idx);

Since erasing from anywhere but the end of a vector requires moving stuff in memory, a common method is to not remove a value, but swap it with the end and reducing the size of the vector.

swap(freeSpots[idx], freeSpots[freeSpots.size()-1]);
freeSpots.pop_back();

By not removing the last element and instead keeping track of the size yourself, you can keep reusing the same vector and just need to reset the size

vector<int> freeSpots(SIZE_OF_BOARD); //Initialize once when starting up


//When placing a marker
swap(freeSpots[idx], freeSpots[--numberOfFreeSpots]);

//When resetting the game
numberOfFreeSpots = SIZE_OF_BOARD;

Since all random numbers should be equally likely, it doesn't matter in which order the numbers are stored in freeSpots.

Personally I like this approach for simulating a deck of cards, as you don't need to do any initial "shuffling".


#4984589 A conversion prgram

Posted by Trienco on 27 September 2012 - 10:07 PM

Maybe he forgot to mention something like "for 1 billion test runs". In either case it doesn't really matter, since it has little to nothing to do with the actual topic. It's not about converting string<->int, but essentially about subtracting one number from another (while skipping values outside a certain range and using a different offset depending on which range you're in).

At no point should stringstream, atoi, etc. have anything to do with it.


#4981915 C++ Relative Paths

Posted by Trienco on 19 September 2012 - 10:24 PM

Basically it doesn't matter where your binary ends up, as long as you start it from the debugger. The only thing that matters is what you configured as your working directory. Once you want to run it manually, you have to make sure the binary is located in that same directory.

Considering that your binary will most likely be in POOA when you're done, you may want to change the debugger settings to use that as your working directory (something like $(ProjectDir)/..) and stick with "data/tiles.png" as your path.


#4979580 View matrix forming

Posted by Trienco on 12 September 2012 - 10:37 PM

The way I consider safe to a persons sanity is to handle the "camera" like any other object. Since scaling the camera doesn't make much sense, all you got are rotation (in the top left 3x3 "sub matrix" and translation in the last column -corresponding to the last 4 floats in the memory layout used for OpenGL-).
This means the first three columns are basically the cameras x,y,z (typically "right", "up" and "forward") axes expressed in world coordinates with the last column being it's position. It's convenient and easy to read.

To use it as view matrix, you obviously need to move everything "the opposite way", so you need the inverse of your matrix. Since you didn't scale, your matrix can be inverted in a simple way. The rotation part is transposed (which explains why it's rows, not columns) and the translation is negated along the original axes (which is better explained by showing the result.

So if your camera matrix (using r,u,f,p as right, up, forward, position instead of uvn) is:

r.x u.x f.x p.x
r.y u.y f.y p.y
r.z u.z f.z p.z
0 0 0 1


Your view matrix will be (created from the camera matrix once per frame):

r.x r.y r.z -(p dot r)
u.x u.y u.z -(p dot u)
f.x f.y f.z -(p dot f)
0 0 0 1


So: keep your camera matrix around, don't recalculate from scratch every frame and for heavens sake, stay as far away from Euler angles as possible (ego shooter style camera is about the only thing they can handle without a lot of head ache).

I'm not sure why Kaptein makes rotating an object around itself so complicated. If you want the camera to rotate around itself, you use camera_matrix * rotation_matrix. If you want it to rotate around the origin you use rotation_matrix * camera_matrix (or the other way around). If you are in fact feeling lazy, you can abuse OpenGL to do the matrix math. Translation and rotation are always applied in object coordinates, so objects already rotate around themselves (using their current right/up/forward axes), no matter where they are and always translate along their local axes as well.

Point is: OpenGL is not doing anything "backwards" unless you insist on thinking in world coordinates instead of object coordinates.

Examples:

-Strafe right is always glTranslate(1,0,0)
What people often do: calculating some "right" vector (instead of 1:1 extracting it from the objects transformation matrix) and then going to the trouble of translating along that vector in global coordinates by forcing things to be done "backwards".

-"Pitch around self" is always glRotate(angle, 1,0,0)
What people often do: calculate some "right" vector (again), then do stuff backwards (including translating stuff to the origin and back)

If you want to mix things, like rotate around "global up" but around your current position, you still don't need to start translating. You just need to adjust your axis by multiplying the "global" axis with the transposed rotation part of the object (basically you cancel out the existing rotations, so your objects "up" is the same as the worlds "up"):

To rotate around global (0,1,0):

axis.x = 0*r.x + 1*r.y + 0*r.z
axis.y = 0*u.x + 1*u.y + 0*u.z
axis.z = 0*f.x + 1*f.y + 0*f.z

ie: glRotate(angle, r.y, u.y, f.y)

Bottom line: think forward and think local, it will make things much easier and more intuitive


#4976301 Checking my Progress in Game Programming

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

'and' is not a C++ keyword. If you have a macro named 'and' that is defined as '&&', get rid of it! Posted Image


Actually it is and it is the same as &&. However, absolutely nobody uses it to the point where I didn't even know about it after almost 10 years of C++. Maybe it's because && is easier to type or simply because it sticks out a lot better than 'and'. Basically, use && and || instead of 'and' and 'or', unless you are extremely paranoid of accidentally using & and | instead.


#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.




PARTNERS