Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Lank
Sep 16, 2002

WHERE IS THE CHANCELLOR?!

HauntedRobot posted:


But I'm thinking of swapping out the tile engine for something a bit more 3d, going for the oldschool isometric perspective, or something equivalent. Maybe. I think I can get better puzzles going with the addition of a bit of 3d.

You may not need to go fully into 3d if you restrict the isometric view to a certain angle. Think Final Fantasy Tactics but without the 3d rotation or camera elevation levels. As long as you draw tiles starting at the back, and doing an entire Z-level (height level) at once before moving up, the view would turn out correctly using overlapping sprites instead of 3d objects.

It just sounds like you have a good setup to be able to easily implement tile layering already. It might be worth a shot unless camera movement would be really important or you just have an itch to try a 3d world.

Sounds good though. :)

Adbot
ADBOT LOVES YOU

Lank
Sep 16, 2002

WHERE IS THE CHANCELLOR?!

Hi guys,

I've been trying to get my feet wet with hobbyist game programming for years starting back in like 95 working with QBasic. I would always get stuck on the graphics portion of anything I did because it was always so complex even to just get a graphics device up and running properly. I just started working with XNA a few months ago and I love it. I finally found something I can wrap my head around when it comes to graphics.

Anyway, what I'm currently puzzled over is this. I'm creating a game that's a sandbox type game....but more of a "Set a bunch of settings and then watch what happens...repeat" using Dungeon Crawler-esque needs based AI. Think the Sims but with no user control. The problem I'm having is that I end up having to have each player's character check every other player and object in the game to see if it's close enough to influence its decisions.

I know this is bad. I've already cut down the math by using Vector2.distanceSquared instead of distance but when I get up to 50-60 total players and objects, all checking each other every frame my game slows to a halt. What I'd like to do is some sort of kd-tree or just some simple grid system to only have each character check the objects that could conceivably be within it's area of awareness. Dumb characters can't see / be aware of things at a very far distance, smarter characters can.

Here's my idea, but I wanted to know if this is done more easily some other way.

Split the map into squares with length equal to the maximum distance of awareness for all active characters and have each character only check against characters in adjacent squares on the grid (8 directions). THEN do the distance checking to see if they actually are close enough to be affected by them (attack, run away etc).

I think that will work well enough to make the game not come to a halt but if characters bunch up for any reason, I'm back at square one with n^2 distance checks per frame where n is the number of players and objects.

I've thought of possibly doing only one character update per frame but I think I'd get a faster frame rate at the expense of dumber characters who follow their old target for X frames till it's their turn to be updated again.

Any suggestions?

Lank
Sep 16, 2002

WHERE IS THE CHANCELLOR?!

Scaevolus posted:

It's not the best article, but you're describing Nearest neighbor search.

The better algorithms can reduce the complexity of what you're doing from O(n2) to O(n log n).

Looking at that article helped a lot. I think I might skip the distance checking and replace it with letting the k closest objects affect the person's actions where k is higher or lower depending on their intelligence / awareness. Then I can impose a hard cap at a value that is just lower than the point I see slow down. So max intelligence = 10 nearest objects / characters processed if I see slowdown at 11 or something like that.

That makes more sense too. Dumber characters would only be able to think about maybe 3-4 of the 20 enemies around them and make judgements based on them where smarter characters could analyze more at once. Just because things are near the person doesn't mean they could handle thinking about all of them. Thanks a ton, that helped a lot. :)

Lank
Sep 16, 2002

WHERE IS THE CHANCELLOR?!

Pfhreak posted:

There have been some good suggestions thus far. (Check out Oct-trees, and other space partitioning.)

But also think about time partitioning. Do you really need to update your AI 60 times a second? If your AI only updated 30, 15, 10, or even 6 times a second, would you really be able to tell? (My guess is no.)

You probably have either a factory or a manager class that is creating or handling these AIs. Basically what you want to do is create a counter in the factory or manager so that you only update each AI every n frames. Try to keep the AIs spread out so that you aren't doing all the updates in one frame.

It's simple, but it will net you a nice boost in frames. It's no substitute for a proper space partitioning algorithm, but it'll buy you a little improvement.

Another way to improve this is to build a system that doesn't rely on the Ai agents to perceive everything, but rather have the sensory inputs tell the AI agents about themselves. Food then tells the agents, "I am food!" and the agents can do what it will with that information. (I'd build a bit field of the possible stimuli, that way you can prevent a lot of lengthy distance calculations by eliminating things the agent can't even respond to.)

Thanks for the great advice. I've got a few comments on it:

Fewer updates per frame: I had thought about this but didn't really know how to implement it. Would it be as simple as perhaps assigning a 1-10 to each player evenly distributed and then only updated those players labelled with # that frame....so 10 groups would mean each player would only update 6 times per second? Also, does this mean I still update the unit's location / animations / health etc but I don't have him "think" about changing what he's doing? I think I can handle that once I find what I need to about elapsed time in XNA.

Objects holding the info: I read about this style from the very start of this project and I think I'm executing it correctly. I have my objects store their value, their danger, what they can accomplish etc so the agent says "well there's gold to my left and a huge guy with a mace on my right....I'm running towards the gold." The issue I ran into was simply the distance calculations. I needed to know whether the object was allowed to tell the agent what it was and have the agent react or not. But I think I solved that....

It was stupid of me to think that a perfect radius of awareness was necessary. I just made a "cardboard box flattened out" shape around the player with the bounding boxes of the largest square that would fit inside the circle of awareness and the smallest square that would fit on the outside of it. No distance checking, just a few inequalities. I should have thought of it from the beginning but I thought I'd throw it up to show how to save a TON of time and still have an approximate circle of awareness. I'm sure I could add a few more squares to approximate the circle even more but this was a good place to start.

Sorry for rambling.

Only registered members can see post attachments!

Lank
Sep 16, 2002

WHERE IS THE CHANCELLOR?!

Pfhreak posted:

great stuff

Wow. That definitely gives me a lot to digest for a while now and tinker with. :) Thanks for taking the time to explain that stuff. I'll definitely check out flags (I've got the big old Oreilly C# bible at home) and play around with them.

Sounds like my slowdown was much more about me updating every frame as opposed to the distance checking I originally thought. I appreciate the help and I'm sure I'll be back when I hit the next road block.

Lank
Sep 16, 2002

WHERE IS THE CHANCELLOR?!

Maybe I can return the favor here.

http://www.policyalmanac.org/games/aStarTutorial.htm

That's the original link I used to get a solid understanding of how the path was actually created using an implementation of the A* algorithm. If that's way beneath what you need, sorry.

As for handling a huge terrain, is there any way you could scale the node size to make waypoints? Like, two passes of the algorithm, one to set direction at a high level to get a target, then at a small level to say actually how to get there. That would keep you from searching a gigantic grid at a very small scale but still have your character moving in the correct direction towards its final destination.


Also, so long as we're ping-ponging each other, is there a perference or best practice between setting up your character array as static vs passing the entire array as a reference to a function? Each character I have has an update / AI method, but it needs to access the other players in the same array. I can see both methods working, but I can also see someone saying OH MY GOD DON'T EVER SET A HUGE ARRAY OF GAME OBJECTS AS STATIC. Not a big deal, just curious.

Adbot
ADBOT LOVES YOU

Lank
Sep 16, 2002

WHERE IS THE CHANCELLOR?!

I guess query may have been the incorrect word.

I'll make it simple so we don't look like two lovers taking over this entire thread.

I've got my class gameObject. (To answer a later question, yes, I'll be making characters, items, etc off of this base class so I have a basic understanding of polymorphism)

I have an array of players in my main game loop.

For player[1] to use his think method, he needs to know who he should be targetting or where he should be fleeing to. To do that, he needs to know things like player[everything but 1].position, and be able to use things like player[everything but 1].perceivedStrength(). I've never set up a dictionary before but would it make life easier? I just need each player in the array to be able to access all the other players in the same array.

Wouldn't that still be the case if I used a dictionary? I mean, even if I use the dictionary to lookup a target player for the current player to do something to, wouldn't he have to call player[1].attack(player[target])? They need to have access to each other don't they?

Maybe I'm just really not setting up my access correctly. It sounds like I'm the definition of coupling.

Edit: Ok, I just read your first question again. I'm not iterating through an array just to find something, I need to know, for player A, his distance to player B, player B's perceived strength, player B's health, then the same for player C, then D etc for all the other players. The think() method for each player isn't just "Attack closest player" or anything. the whole point of the game is to experiment with a complex AI so each player needs to interact with the others a ton. So I don't understand how a dictionary could hold something like "distance to object X" when that distance is constantly changing for every player to player combination as they move. It's not grib based, it's pixel by pixel movement. Does that clean things up at all?

ps: my email is awmaas@gmail.com if you want to chat more

Lank fucked around with this message at 19:03 on May 9, 2008

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply