• Content count

  • Joined

  • Last visited

Community Reputation

155 Neutral

About Negs

  • Rank
  1.   Hi, the developer on Path of Exile who wrote the pathfinding we use.   We use A* for pathfinding, but we have an extra rule you might find helpful.   We restrict the A* search to be inside a bounding ellipse with the destination and the starting point as focuses. Because we keep the ellipse size constant, if the destination is far away it makes a long and thin ellipse so it will only find paths that are quite direct to the solution, but if the destination is close by then it creates a much wider ellipse and thus will search quite far perpendicularly to the direction of the destination. We always path to the closest point we found to the destination even if we fail to find a path.   We have found this scheme works quite well in gameplay. When the player clicks far away they tend to just want to move in that general direction, but when they click close by they are keen to find an exact path to the place they clicked even if it means moving around a blockage like a wall.   It also has fairly good properties that prevent the A* blowing up and searching really far away or in the wrong direction when it can't find a path, improving performance.
  2. At Grinding Gear Games we use a technique called Tile Based Texture Mapping in order to make good looking ground. There isn't much online about creating art using the technique so our lead artist thought he would create a tutorial for his process when creating ground textures. There might be a few other tips in there that apply more generally as well. Hope someone finds this useful.
  3. It sounds like I'm doing something that is somewhat different. In data file for each different entity type that can be created I have a GameObjectType definition that contains a list of components and for each one a bunch of things that set variables in the component. A small example: Monster { Physical { size = 4 } Moving { speed = 10 } } Any variables you don't set get default values. You can also derive from one of these classes FastMonster : Monster { Moving { speed = 30 } } For each component I have something deriving from ComponentStatic and Component. At load time when you parse these files for each type we create a list of ComponentStatic objects that belong to that type. A component static has functions for accepting variable definitions and a list of components that it requires services from. Moving for example requires Physical to be present (You need to be able to update the position of the object in order to move it). If you list a component and you don't include its dependency then the Type will fail to load and an error gets reported. For each dependency you store a ComponentRef which is really just the index of the component for easy look up later. A GameObjectType also remembers the sizeof for the non-static components corresponding to the static ones it contains and the sum of all of these. So now each type of object we want has a ComponentStatic that contains dependancy indices and all of the type specific data that each component needs. When we instantiate a GameObjectType as a GameObject we allocate all of the memory for all of the non static components in one call and use placement new to call of of the constructors for each game object. Each non static component has a reference to its static cousin so that it can easily access all of the object type specific data it needs. The GameObject has a function that takes a ComponentRef and returns a pointer to the game object that you want. It does this by using a lookup table in the GameObjectType that contains the offsets of each Component for this type. This may sound a little complex but it means that creating new objects is now pretty fast. You allocate all of the components in one go and this has the additional benefit that all of the components are located next to each other in memory to improve caching performance. We also have a quick way of getting references to other components. All of the dependencies the component needs are stored as ComponentRef's so getting a pointer is just a constant time array lookup. There is one other thing needed here though, and that is a way to publish messages to components that require info back from you. For example, you need a way of notifying any components that need to the fact that the object has stopped moving for example (required for animation). I considered some kind of callback system and implemented some of it but it was fairly complex. So I settled with a much simpler solution. Each component has a ReceiveMessage virtual function and when a ComponentStatic is instantiated all of the components that it requires get an entry added to say that it is interested in messages from those components. When a component wants to send a message it calls a function that will send messages to all of the other components that registered as listeners. So our animation controller lists the moving component as a dependancy and now it gets notified of any events that it needs to. There are a few other issues I have not discussed here. The first one that is not yet implemented fully the ability to be able to load GameObjectTypes faster using a binary game object type format that contains a blob of binary data that each component can memcpy directly into a little inline struct during loading. You can compile all of the game object type files down into this format, number all of the components and then very quickly load a game object type. This is for distribution as it requires a locking down of the available components and you can't really edit the type files after that. The other issue is network serialisation. I have a system that allows each component to be serialised and put into a network stream and come out whole on the other end, and a "dirty component" thing that allows components to say that they have changed and then only components that require changes to be serialised get sent (with a bitfield at the start to say which components the client needs to load. That mechanism has a whole other list of strange things to do with Components being marked as Client, Server or Shared. Only Shared components get state serialisation and Client / Server components only actually exist on the sides that they need to. All of the Shared components come first in the physical object to preserve that the component indices are always the same on both the client and server. (We don't send the indices in network traffic but its easier to get your head around sometimes) I'm not totally happy with the networking part of the system honestly. It can be hard to say sometimes what should be serialised as part of the object state and what should be sent as a standard message packet. I've been considering some kind of Object -> Object network message thing but haven't implemented it yet. That would be so that the server can notify the client of events without actually sending it as object state. Anyway, this ended up being a pretty long post. Any suggestions and comments welcome.
  4. Thank you jpetrie for telling me about the extra debug information. When I turned the debug information on I noticed that I had allocated a few D3D resources in another thread by mistake. I added the code to allocate resources a long time after I had written the code to create the thread and had forgotten that this loading code would have been done in another one. This explains why the error was common on the fast machine, it has a Duel Core CPU and my laptop doesn't. I guess there is some race condition in the resource allocator that causes this problem. I moved the allocation code back to the main thread and now it all works fine. Thanks Guys
  5. Quote:Original post by jpetrie The task manager is not necessarily useful for checking this kind of thing. What does the D3D debug output say? Can you clarify what you mean by "arbitrary" (one particular call always fails, or one call fails but its not always the same call, etc?) I'm not sure where to get any extra output. I'm using the V_RETURN macro around the call from the DXUT which triggers the trace popup box showing E_OUTOFMEMORY. Its not one particular call that fails, it could be any resource creating call. And a call does not always fail. On the machine with 2GB of ram a call will fail perhaps 1/3rd of the time. The rest of the time it is fine. On the laptop it almost never happens.
  6. Quote:Original post by Todo Quote:Original post by Negs Ironically the error comes up far less frequently on my laptop with only 512 MB of main memory and a 128 Meg graphics card. This sentence leads me to believe you are (somehow, probably unintentional) allocating resources out the wazoo. I can't really think of any other reason. Could there be a loop somewhere in your program causing it to allocate (but never release) resources? I don't see what about that sentence would make you think that. If anything the opposite is true. Presumably have less RAM would mean the OUTOFMEMORY errors would come up more frequently? Looking at the RAM usage in the task manager shows that there is more then 1GB of memory free when the error occurs.
  7. I was using PNG texture files so I tried switching to DDS files to see if there was some kind of buggy loader for PNGs, but it didn't work. I still get E_OUTOFMEMORY on arbitrary calls. It happens on Vertex buffers as well, so it seems to be on any kind of resource. I'm getting very frustrated here, so any help would be appreciated.
  8. Hi I have been finding that resource creation has been giving me the E_OUTOFMEMORY error sporadically. I assume that since there appears to be a different error for Video Memory (D3DERR_OUTOFVIDEOMEMORY) that this must mean System Memory. The problem is that there is clearly enough system memory available. I am allocating only a few textures and a couple of very small index and vertex buffers. I am allocating textures with D3DXCreateTextureFromFile. The textures allocated are three 256 * 64 textures, a 512 * 512 texture and a pair of 256 * 256 textures. There are perhaps 8 small vertex and index buffers of less then 20 vertices or indices each. All of these resources are being allocated in the Managed Pool. As you can see, this is hardly enough to expect to fill up system memory. The system in question has 2 GB of system memory and 512 MB of graphics memory. Ironically the error comes up far less frequently on my laptop with only 512 MB of main memory and a 128 Meg graphics card. Looking into various D3D creation options I noticed D3DCREATE_DISABLE_DRIVER_MANAGEMENT which says "Direct3D calls will not fail for resource errors such as insufficient video memory." but I do not think it had any effect. It kind of seemed like it happened less often, but its of hard to tell. Is there anything I need to know about why this kind of error would be happening? Thanks Jonathan Rogers [Edited by - Negs on March 23, 2007 3:43:35 PM]