I want to learn 3d programming

mikeblas said:
Like I said, the bitwise operators let you divide or multiply by powers of two. Certainly, you see the application of multiplcation and division, right? Maybe I'm not understanding what you're driving at.

I'm not explaining myself well, not your fault. A couple anecdotes and an example is about as close as I can get:

A few years ago I was messing around in Perl for fun, building a poker hand evaluator (Texas Hold 'Em, 7 cards, make the best 5 card hand and compare to another). My solution was tedious and slow. Then I saw a solution that someone else wrote, really fast and full of bitwise operators. I puzzled over it a few days and gave up. To this day I couldn't do the same thing.

More recently I was messing around with the GD graphics library (again in Perl) and wanted to make a circle. Not knowing much math I wound up calculating every point in a square, and if it was within the circle's radius (using the Pythagorean theorem to determine distance) it got colored in. I'm sure there's a faster way to do that.

The example would be AI. Say I have a hungry NPC in a roleplaying game (which is my ultimate goal) and that NPC doesn't have money, but does have a musical instrument and a weapon. Depending on the time of day, how hungry he is, where he is etc. he might choose to rob someone or play for coin. Rather than a ton of switch and if-else checks, along with scripting every behaviour of every NPC in the game, I think I can give NPCs a set of base attributes and let them go on their own. And I think bitwise operators are going to play a big part of that--but applying it is going to take a lot of plodding and planning on my part.

These are all just examples, not requests for specific help. What I'm trying to get to is a state of mind where I'll think "1011 & (0100 << 1)" is better to do than "if x > 7 && y >= 4 then"... See what I'm getting at? Sorry that I can't explain myself any more coherently than this.
 
I see. Thanks for the clarifications.

eggrock said:
The example would be AI. Say I have a hungry NPC in a roleplaying game (which is my ultimate goal) and that NPC doesn't have money, but does have a musical instrument and a weapon. Depending on the time of day, how hungry he is, where he is etc. he might choose to rob someone or play for coin. Rather than a ton of switch and if-else checks, along with scripting every behaviour of every NPC in the game, I think I can give NPCs a set of base attributes and let them go on their own. And I think bitwise operators are going to play a big part of that--but applying it is going to take a lot of plodding and planning on my part.

It'll take planning, sure. Do you mean "plotting" instead of "plodding"?

I don't think this is necessarily an application for bit masks. I'd expect that you'd have some generic character class. That class knows that characters need money and food, might say things, and might fight back when attacked, for example.

If the character notices it is hungry, it will look at a more derived class that implements a specific character (or class of character). That class can provide information about the character's skills. Does it know how to play an instrument? DOes it have one? Then it can include an action in a list of things it can do to get some food. Does it know how to steal? Does its alignment allow it to do so? Then that's added to the list, too.

Maybe deep in the implementation you end up finding a rack of things that can be held as a bitmask, but I'm not seeing it in going just this far in design.

eggrock said:
A few years ago I was messing around in Perl for fun, building a poker hand evaluator (Texas Hold 'Em, 7 cards, make the best 5 card hand and compare to another). My solution was tedious and slow. Then I saw a solution that someone else wrote, really fast and full of bitwise operators. I puzzled over it a few days and gave up. To this day I couldn't do the same thing.

This one is a little more appropriate. Say you have a list of cards. How can you represent it? A naieve progrmamer might do something like this:

Code:
struct card
{
   int nSuit; // 1 == hearts, 2 == clubs, etc
   int nFace; // 1 == ace, 11 == jack, and so on
};

Say you want to look for a straight. How do you do it? You need an array of these things, and sort them, then see if there's a contigious streak of 5 (or 7) of consecutive cars. That's a lot of code, isn't it?

What if we pick a different way to represent cards? Say we use an integer, which has more than enough bits for the thirteen different values a card could have. We'll set the n-1 th bit of the card for the n value of the card. An ace sets bit zero, a 2 sets bit one, and so on.

If I want to take an array of the card structures and convert them to a single integer with these flags, I can write a function called HandAsBitmask() like this:

Code:
int HandAsBitmask(struct card* pCards, int nHandSize)
{
   int nReturn = 0;

   for (int nCard = 0; nCard < nHandSize; nCard++)
   {
      nReturn |= 1 << (pCards[nCard].nFace - 1);
   }
}

Note that I loose the suit here. Maybe I just keep this approach and use something else to analyse suit hands, or maybe I have both data structures. For now, let's just focus on the bitmask.

If I have only two cards, a 2 and a 6, I get this word back:

000010 0010 == 0x22

for example. The cards are already sorted, so I can look for a sequence of ones. If I have all the cards, 2 through 6 inclusive, then I see this mask:

0000111110 == 0x3E

I don't want to compare against every possible straight though (like, 0000111110, and then 0001111100, and then 0011111000) so I want to write a neat loop. Here's how:

Code:
bool GotStraight(int nHand)
{
    for (int n = 0; n < 13; n++)
    {
        if (nHand & 0x001F)
        {
            return true;
        }
      nHand = nHand >> 1;
    }

    return flase;
}

which is a lot better than sorting and looking for a bunch of things in order. Right?

The above loop runs 13 times because I'm watching the Steelers right now. What's the minimum number of times it can run to correctly test?

The above loop also looks for a five-card straight. How can we make it take a parameter to tell us how many cards are in the hand? We'll have to get an integer with n bits set in the rightmost position if we want to check for straights of length n.

eggrock said:
More recently I was messing around with the GD graphics library (again in Perl) and wanted to make a circle. Not knowing much math I wound up calculating every point in a square, and if it was within the circle's radius (using the Pythagorean theorem to determine distance) it got colored in. I'm sure there's a faster way to do that.
There certainly is. But I don't think it has go to do with bitmasks.
 
If I have only two cards, a 2 and a 6, I get this word back:

000010 0010 == 0x22

for example. The cards are already sorted, so I can look for a sequence of ones. If I have all the cards, 2 through 6 inclusive, then I see this mask:

0000111110 == 0x3E

lightbulb.jpg


That did it, THANK YOU. When I said 'plodding' I meant plodding.

It's a coin sorting machine... I get it.. Finally...
 
What is an API? Is it just a bunch of standards or is it some sorp of library or what? It stands for Application Program Interface, but what does this mean in human terms? Thanks.
 
Shameless Liar said:
What is an API? Is it just a bunch of standards or is it some sorp of library or what? It stands for Application Program Interface, but what does this mean in human terms? Thanks.
You could think of it as similiar to a library. Basically it's a way for you to interface from your application to another. For example, the Win32 API is a way for your program to work with Windows. You can easily set different things like disabling the screensaver or creating a window.

I'm not too good at explaining things but that's the basics of it.
 
I always thought of it as almost a client/server approach, or I guess a class 'interface' now that I'm getting into those. You can use functions and data that the API allows you to but not mess around with anything else (not directly at least).

Like with FTP, (though I don't know if that's really an API). You can log in, send/receive files and a few other things, but you're limited to the available commands, get, put, rename and so on. You can send a file but not execute it (unless the FTP server has a function to let you do that). You can only get/put files from/to the area defined as your 'home' directory; you can't go outside of that and do anything at all.
 
An api is a set of functions that generally make something easy to do. =)

(My contribution to crappy definitions, btw eggrock, no.)
 
dammit.. I'm always wrong. :p

export Lord_of_Shadows=verbose

./Lord_of_Shadows
 
An application is something you write. A programming interface is an interface that allows programs to talk to whatever the API supports.

The Windows API is the set of functions, macros, type definitions, and classes that let applications interact with the services and features the target provides.

Perhaps the most important part of an API is documentation.
 
What's the gist of multithreading (in relation to C++)? I have absolutely no idea how it works, other than to make more than one thing (seem to) happen at once.

Eg, if I have a game and perform an action I *know* will take a few seconds to complete (like loading an entire level from disk, determining all the visuals and then displaying it... How do I keep the background sound playing? (Pretend for the sake of discussion that the background music is NOT on an accompanying CD.)
 
The answer to your question is a whole book. In my book, I spent a chapter or two on multithreading, and it was hardly enough.

I'm not sure why this question doesn't deserve its own thread, but here's a sketch of an answer:

First, nothing. C++ doesn't specify anything for multithreading. Everything you do with threads (and almost everything you do with processes) is done using an API for your specific operating system.

You'll note that functions which the langauge does specify, like fread() for the C runtime library, always block. That is, you call them, they work, and they don't return to you until they're either done or have failed.

Windows will offer APIs to do lower-level I/O, which isn't hard -- but they are capable of doing asynchronous calls. That is, you call the function to read asynchronously. It returns almost immediately, and meanwhile the operating system gets to work on doing the I/O. You can check to see if the operation completed (and was it successful?) or arrange to be notified via a callback if you want.

So, you might call SoundPlaySound() to play your sound on one thread, and fread() on another thread. When the read finishes, that thread continues gets to unpacking the level or playing the game (or whatever it needs to do).

Or, you might call ReadFileEx() to do an asynchronous read, and while you're waiting, call SoundPlaySound() to play the sound; waiting for a I/O completion notification.

Or, you might have any other number of designs based on your exact requirements.
 
mikeblas said:
I've only been here for about 18 months, but I wonder why HardForum users are so sensitive to what they call thread hijacking. Conversations go off in different directions very naturally; plus, there's no way to branch a new thread referring to the old notes in anothr thread.
Thread hijacking happens when user A starts a thread and user B posts another question right away, and B gets answered and A gets ignored. This is bad, because user A gets disillusioned about the whole process. There was an example of this (the hijacking, at least) in the Disk Storage forums recently. Thread crapping is a lesser offense - this post, for example, answers a question not asked.

In short, thread hijacking is only a problem when a user doesn't get their question fully or well explained. Once everyone's satisfied, there's no reason to lead the thread in a new direction. Thread crapping is just a nuisance.

 
mikeblas said:
The answer to your question is a whole book. In my book, I spent a chapter or two on multithreading, and it was hardly enough.

I'm not sure why this question doesn't deserve its own thread, but here's a sketch of an answer:

Probably a few books, a forum, newsgroup and standards committee. ;)

mikeblas said:
First, nothing. C++ doesn't specify anything for multithreading. Everything you do with threads (and almost everything you do with processes) is done using an API for your specific operating system.

You'll note that functions which the langauge does specify, like fread() for the C runtime library, always block. That is, you call them, they work, and they don't return to you until they're either done or have failed.

Windows will offer APIs to do lower-level I/O, which isn't hard -- but they are capable of doing asynchronous calls. That is, you call the function to read asynchronously. It returns almost immediately, and meanwhile the operating system gets to work on doing the I/O. You can check to see if the operation completed (and was it successful?) or arrange to be notified via a callback if you want.

So, you might call SoundPlaySound() to play your sound on one thread, and fread() on another thread. When the read finishes, that thread continues gets to unpacking the level or playing the game (or whatever it needs to do).

Or, you might call ReadFileEx() to do an asynchronous read, and while you're waiting, call SoundPlaySound() to play the sound; waiting for a I/O completion notification.

Or, you might have any other number of designs based on your exact requirements.

If I wanted part of my program to run asynchronously, what would I need to do? Would I have one or more separate programs called by the main program... Like a DLL maybe? And then the Windows API allows me to message back and forth between the two while both run in their own threads? This isn't getting into multicore (or multiple) processors, PPUs and such but I don't want to get too far off the beaten path.
 
eggrock said:
If I wanted part of my program to run asynchronously, what would I need to do? Would I have one or more separate programs called by the main program... Like a DLL maybe? And then the Windows API allows me to message back and forth between the two while both run in their own threads? This isn't getting into multicore (or multiple) processors, PPUs and such but I don't want to get too far off the beaten path.

DLLs aren't involved in parallelism.

Look up the CreateThread() API. If you're using VC++, then you should use the _beginthreadex() call. If you're using some other runtime, then you should read its rules about creating threads.

These functions end up creating a thread, getting it initialized, then calling a function that you supply to the API. That function executes in the newly created thread.

There's a variety of mechanism for synchronizing and communicating between threads. See the MSDN topic on Process and Thread functions for a list.
 
Thanks mb.

I'm jumping around enough that I'm just going to sit on the gamedev forums and read for a good long time. The books as well. And practice. And practice. And practice.

Thanks for your vast knowledge.
 
This thread is excellent. I love the poker example... as a professor of mine often says, "That's sexy code".
 
Back
Top