Boss-based RTS games.

Started by
18 comments, last by popsoftheyear 14 years, 11 months ago
The performance goes down a bit as I keep playing the game (sort of "lags" a bit when I play the game for X amount of time).

Nice work so far though!

Quote:Original post by Thatotherguy
We quickly discovered that the reason bosses aren't included in most RTS games is because bosses traditionally are maintained in genres that require fine control by the player to defeat, and which have a recognizable pattern that the player must figure out and counter. RTS games don't generally offer fine levels of control, so any boss battle would usually reduce to "order these units to attack the boss until its dead". We tried to counter this tendency by giving the monsters "bodyguards" that would defeat player armies trying to swarm the monster, and by giving each monster a totally unique attack strategy.

What if you have an RTS boss that consists of an enemy base with enemy units? Sure it would be just like what you have done before, but a bit bigger (larger territory, etc), with more sections (tactical areas you must capture, etc), and a lot tougher than the usual (more units, etc). That could be considered a form of Boss for the RTS genre.

[Edited by - Tangireon on May 5, 2009 9:26:44 AM]
[url="http://groupgame.50.forumer.com/index.php"][/url]
Advertisement
Quote:Original post by Thatotherguy
You CAN select multiple units. Click and drag with the mouse from the top left to the bottom right. This is is box-select. You can also double-click on a unit to select all of that type of unit.


Well, I've been trying that so far, but when I do box-select it doesn't select any unit at all. Maybe it's a Linux-specific input issue? Double clicking does work as you describe.

Edit: After experimenting some more with the box-select, I found that I can use it if I drag right-down from a top left corner, but not if I drag from any other corner.


Quote:Original post by Thatotherguy
I'll see what I can do to reproduce your bug with the loading screen. Also, I have never seen that exception before.


I can't reliably reproduce that exception, but I can reliably reproduce the infinite loop when losing the game. Dunno what will happen if I win, I haven't managed to do that so far! :D


Quote:Original post by Thatotherguy
The idea behind the crab's laser was that it was supposed to force you to micro-manage all of your units. It used to be that the laser did about half its current damage, and had no splash damage. When playtesting we discovered that the player could easily defeat the crab just by building a bunch of GIs or jeeps and throwing them at it.

I should probably have it give you the funds back when you cancel...

What specs are you running at? Turning off the frame manager, I can easily get 300+ FPS running on a Q6600 and high-end Nvidia card. Running on my laptop, which has a T9300 dual core, I get about 150 FPS. With the frame limiter I get 60FPS with little jumps every now and then. I haven't done much testing on other hardware.


My specs are: Pentium 4 at 3.0 Ghz, 3 GB ram, geforce 8600 GT with 1 GB ram, running Ubuntu 8.10. and sun-java-6u10 (1.6.0_10-b33). LWJGL programs usually run just fine though.

I've also dropped the frame-rate to 1 fps by spamming GI's. Even though it says 1, nothing is actually moving anymore, so it's more like zero ^_^;;; At the very start of the game, I get about 50-65 fps. After doing nothing except producing 30 GIs, fps drops to single digits. At 40 GIs it's already unplayable.

Another thing I noticed, there are black horizontal lines appearing when I zoom in or out. Maybe due to vsync.

[Edited by - lightbringer on May 5, 2009 10:01:23 AM]
Quote:Original post by MortusMaximus
For some reason, it keeps telling me the download stalled.


The server is slow. It will stall for a few minutes and then continue.
Here's some output of the built-in profiling, doing nothing but building 40 GI's and then leaving it for a couple of minutes. I'm not an expert at this but it looks like the collision detection could be bogging down the game. Most of the time is spent on StrictMath.atan2() and Shape.intersects()

Flat profile of 398.43 secs (25962 total ticks): Thread-21  Thread-local ticks:100.0% 25962             Blocked (of total)Flat profile of 404.71 secs (26443 total ticks): Thread-20  Thread-local ticks:100.0% 26443             Blocked (of total)Flat profile of 412.87 secs (26562 total ticks): Thread-18  Thread-local ticks:100.0% 26562             Blocked (of total)Flat profile of 414.22 secs (26659 total ticks): javawsApplicationMain  Interpreted + native   Method                          0.6%   167  +     0    java.util.ArrayList.size  0.3%    74  +     0    java.util.LinkedList.size  0.1%    26  +     1    sun.misc.Unsafe.defineClass  0.1%     0  +    24    org.lwjgl.opengl.LinuxContextImplementation.nSwapBuffers  0.1%     0  +    23    org.lwjgl.openal.ALC10.nalcCloseDevice  0.1%     0  +    19    java.lang.Class.getDeclaredConstructors0  0.0%    10  +     1    java.lang.ClassLoader.defineClass1  0.0%     0  +    10    sun.font.FileFont.getGlyphImage  0.0%    10  +     0    java.nio.HeapByteBuffer.<init>  0.0%    10  +     0    com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.<init>  0.0%     0  +     9    org.lwjgl.opengl.GL11.nglPopAttrib  0.0%     0  +     9    java.util.zip.Inflater.inflateBytes  0.0%     0  +     9    org.lwjgl.opengl.LinuxMouse.nGetWindowHeight  0.0%     0  +     9    org.lwjgl.opengl.GL11.nglTexImage2D  0.0%     9  +     0    com.sun.org.apache.xerces.internal.parsers.XML11Configuration.<init>  0.0%     0  +     8    java.lang.SecurityManager.getClassContext  0.0%     0  +     8    org.lwjgl.opengl.LinuxDisplay.nCreateBlankCursor  0.0%     8  +     0    sun.reflect.MethodAccessorGenerator.emitInvoke  0.0%     0  +     7    java.util.zip.Inflater.init  0.0%     0  +     7    org.lwjgl.opengl.LinuxKeyboard.openIM  0.0%     2  +     5    java.io.UnixFileSystem.getLastModifiedTime  0.0%     0  +     7    org.lwjgl.opengl.GL11.nglPushAttrib  0.0%     7  +     0    com.sun.org.apache.xerces.internal.dom.ParentNode.ownerDocument  0.0%     7  +     0    com.thoughtworks.xstream.io.path.PathTracker.<init>  0.0%     0  +     6    org.lwjgl.opengl.GL11.nglClear  3.3%   575  +   294    Total interpreted (including elided)     Compiled + native   Method                         23.8%  6221  +     0    org.newdawn.slick.geom.Shape.intersects  9.7%  2480  +    48    org.newdawn.slick.geom.Line.<init>  2.6%   686  +     0    org.newdawn.slick.geom.Shape.checkPoints  2.5%   658  +     1    org.newdawn.slick.particles.ParticleSystem.update  2.3%   496  +    92    AI.avoidotherUnits  1.5%   390  +     0    RTSMap.blocked  1.2%   320  +     0    java.util.LinkedList.entry  1.2%   298  +     3    org.newdawn.slick.geom.Ellipse.createPoints  1.0%   270  +     1    AStar$PriorityList.add  0.7%   186  +     0    java.lang.String.indexOf  0.7%   184  +     1    Game.update  0.5%   138  +     0    AStar.findPath  0.5%   120  +     0    java.util.ArrayList.get  0.4%   110  +     5    org.newdawn.slick.geom.Shape.findCenter  0.4%   112  +     0    org.newdawn.slick.geom.NeatTriangulator.snip  0.4%   110  +     0    org.newdawn.slick.geom.Shape.calculateRadius  0.4%    93  +     7    Movable.move  0.4%    94  +     0    org.newdawn.slick.geom.NeatTriangulator.findEdge  0.3%    76  +     0    java.util.LinkedList.indexOf  0.3%    71  +     0    AI.targetEnemies  0.3%    66  +     0    org.newdawn.slick.particles.ConfigurableEmitter.updateParticle  0.2%    65  +     0    java.util.AbstractList$Itr.next  0.2%    58  +     3    Ent.act  0.2%    58  +     0    AStar.isValidLocation  0.2%    56  +     0    java.lang.String.indexOf 55.8% 14333  +   227    Total compiled (including elided)         Stub + native   Method                         31.8%     0  +  8294    java.lang.StrictMath.atan2  1.5%     0  +   384    org.lwjgl.opengl.GL11.nglVertex3f  1.4%     0  +   365    org.lwjgl.opengl.GL11.nglTexCoord2f  1.0%     0  +   253    org.lwjgl.opengl.GL11.nglColor4f  0.8%     0  +   221    org.lwjgl.opengl.GL11.nglDisable  0.4%     0  +   111    java.util.zip.Inflater.inflateBytes  0.3%     0  +    87    java.lang.Class.isPrimitive  0.3%     0  +    80    org.lwjgl.opengl.GL11.nglBegin  0.3%     0  +    74    org.lwjgl.opengl.GL11.nglEnd  0.3%    23  +    48    java.security.AccessController.doPrivileged  0.3%     0  +    67    java.security.AccessController.getStackAccessControlContext  0.3%     0  +    67    java.lang.Class.getSuperclass  0.2%     0  +    58    org.lwjgl.opengl.GL11.nglVertex2f  0.2%     0  +    57    java.nio.Bits.copyFromByteArray  0.2%     0  +    56    java.lang.String.intern  0.2%     0  +    54    java.util.zip.ZipFile.getEntry  0.1%     0  +    34    java.lang.System.arraycopy  0.1%     0  +    30    org.lwjgl.opengl.GL11.nglTranslatef  0.1%     0  +    28    sun.reflect.Reflection.getCallerClass  0.1%     0  +    26    java.lang.Object.clone  0.1%     0  +    22    java.lang.Class.getClassLoader0  0.1%     0  +    22    java.lang.ClassLoader.findLoadedClass0  0.1%     0  +    17    java.lang.Object.hashCode  0.1%     0  +    17    java.lang.Throwable.fillInStackTrace  0.1%     0  +    15    org.lwjgl.opengl.GL11.nglCallList 40.8%    34  + 10619    Total stub (including elided)  Thread-local ticks:  2.2%   574             Blocked (of total)  0.0%     3             Class loaderFlat profile of 418.74 secs (27045 total ticks): TimerQueue  Thread-local ticks:100.0% 27045             Blocked (of total)Flat profile of 418.84 secs (27053 total ticks): CacheCleanUpThread  Thread-local ticks:100.0% 27053             Blocked (of total)Flat profile of 418.85 secs (27053 total ticks): CacheMemoryCleanUpThread     Compiled + native   Method                         50.0%     0  +     1    java.lang.ref.ReferenceQueue.remove 50.0%     0  +     1    Total compiled         Stub + native   Method                         50.0%     0  +     1    java.lang.Object.hashCode 50.0%     0  +     1    Total stub  Thread-local ticks:100.0% 27051             Blocked (of total)Flat profile of 418.86 secs (27053 total ticks): ConsoleWriterThread  Interpreted + native   Method                        100.0%     1  +     0    java.awt.EventQueue.postEventPrivate100.0%     1  +     0    Total interpreted  Thread-local ticks:100.0% 27052             Blocked (of total)Flat profile of 418.87 secs (27054 total ticks): AWT-EventQueue-1  Interpreted + native   Method                         31.8%     0  +    88    com.sun.java.swing.plaf.gtk.GTKNativeEngine.nativeFinishPainting 19.5%     0  +    54    sun.java2d.loops.DrawGlyphListAA.DrawGlyphListAA 10.8%     2  +    28    sun.java2d.loops.MaskBlit.MaskBlit  7.2%     0  +    20    sun.java2d.loops.Blit.Blit  6.1%     0  +    17    sun.awt.X11.XInputMethod.openXIMNative  4.0%     0  +    11    sun.misc.Unsafe.unpark  3.6%     0  +    10    com.sun.java.swing.plaf.gtk.GTKNativeEngine.native_paint_box  1.1%     0  +     3    java.lang.System.identityHashCode  1.1%     0  +     3    sun.java2d.x11.X11CachingSurfaceManager.updateBitmask  0.7%     0  +     2    sun.misc.Unsafe.allocateMemory  0.7%     0  +     2    com.sun.java.swing.plaf.gtk.GTKNativeEngine.nativeStartPainting  0.7%     2  +     0    sun.font.GlyphList.getInstance  0.7%     2  +     0    com.sun.java.swing.plaf.gtk.GTKNativeEngine.finishPainting  0.7%     2  +     0    javax.swing.plaf.synth.SynthGraphicsUtils.paintText  0.4%     0  +     1    java.security.AccessController.doPrivileged  0.4%     0  +     1    sun.font.FontManager.getFont2D  0.4%     0  +     1    sun.awt.X11.XlibWrapper.XFlush  0.4%     0  +     1    sun.font.FileFont.getGlyphImage  0.4%     1  +     0    javax.swing.text.SegmentCache.getSharedInstance  0.4%     0  +     1    sun.awt.image.BufImgSurfaceData.initRaster  0.4%     1  +     0    sun.java2d.SunGraphics2D.clipRect  0.4%     1  +     0    java.util.IdentityHashMap.clear  0.4%     1  +     0    java.awt.Window.postWindowEvent  0.4%     1  +     0    java.util.concurrent.locks.AbstractQueuedSynchronizer.addWaiter  0.4%     1  +     0    java.util.concurrent.locks.AbstractQueuedSynchronizer.unparkSuccessor 94.6%    19  +   243    Total interpreted (including elided)     Compiled + native   Method                          0.4%     0  +     1    sun.swing.ImageCache.getEntry  0.4%     0  +     1    java.awt.Container.findComponentAtImpl  0.7%     0  +     2    Total compiled         Stub + native   Method                          1.4%     0  +     4    java.lang.Object.getClass  0.7%     0  +     2    java.lang.Object.hashCode  0.7%     0  +     2    java.lang.System.identityHashCode  0.7%     0  +     2    java.lang.Object.clone  0.4%     0  +     1    java.lang.Thread.currentThread  0.4%     0  +     1    java.security.AccessController.getStackAccessControlContext  4.3%     0  +    12    Total stub  Thread-local ticks: 99.0% 26777             Blocked (of total)  0.4%     1             InterpreterFlat profile of 419.08 secs (27074 total ticks): AWT-EventQueue-0  Thread-local ticks:100.0% 27074             Blocked (of total)Flat profile of 419.08 secs (27074 total ticks): AWT-Shutdown  Interpreted + native   Method                        100.0%     0  +     1    java.lang.Object.wait100.0%     0  +     1    Total interpreted  Thread-local ticks:100.0% 27073             Blocked (of total)Flat profile of 419.14 secs (27079 total ticks): traceMsgQueueThread  Interpreted + native   Method                         50.0%     1  +     0    java.lang.StringBuffer.length 50.0%     1  +     0    com.sun.deploy.util.ConsoleTraceListener.print100.0%     2  +     0    Total interpreted  Thread-local ticks:100.0% 27077             Blocked (of total)Flat profile of 419.15 secs (27079 total ticks): DestroyJavaVM  Thread-local ticks:100.0% 27079             Blocked (of total)Flat profile of 419.16 secs (27080 total ticks): Javaws Secure Thread  Thread-local ticks:100.0% 27080             Blocked (of total)Flat profile of 419.16 secs (27080 total ticks): AWT-XAWT  Interpreted + native   Method                         99.7%     1  + 26863    sun.awt.X11.XToolkit.waitForEvents  0.1%     0  +    20    sun.awt.X11.XlibWrapper.XQueryTree  0.0%     0  +    11    sun.awt.X11.XlibWrapper.XFilterEvent  0.0%     0  +     7    java.lang.Thread.yield  0.0%     0  +     7    sun.awt.X11.XlibWrapper.XSync  0.0%     5  +     0    java.awt.EventQueue.wakeup  0.0%     0  +     4    sun.awt.X11.XlibWrapper.XTranslateCoordinates  0.0%     0  +     2    sun.misc.Unsafe.unpark  0.0%     0  +     2    sun.awt.X11.XlibWrapper.XGetWindowProperty  0.0%     2  +     0    java.util.concurrent.locks.AbstractQueuedSynchronizer.addWaiter  0.0%     0  +     1    sun.awt.X11.XlibWrapper.XEventsQueued  0.0%     0  +     1    sun.awt.X11.XlibWrapper.InternAtom  0.0%     0  +     1    sun.misc.Unsafe.compareAndSwapObject  0.0%     1  +     0    sun.awt.X11.XWindowPeer.handlePropertyNotify100.0%     9  + 26919    Total interpreted         Stub + native   Method                          0.0%     0  +     3    java.lang.Object.getClass  0.0%     0  +     2    sun.awt.X11.XlibWrapper.XEventsQueued  0.0%     0  +     1    java.lang.Object.clone  0.0%     0  +     6    Total stub  Thread-local ticks:  0.5%   146             Blocked (of total)Flat profile of 419.35 secs (27093 total ticks): Java2D Disposer  Thread-local ticks:100.0% 27093             Blocked (of total)Global summary of 419.48 seconds:100.0% 28462             Received ticks  4.3%  1234             Received GC ticks  0.5%   129             Compilation  0.4%   111             Other VM operations  0.0%     6             Class loader  0.0%     1             Interpreter  0.0%     3             Unknown code
Quote:Original post by lightbringer


Edit: After experimenting some more with the box-select, I found that I can use it if I drag right-down from a top left corner, but not if I drag from any other corner.


That's correct. I guess I just never tested selecting from other corners. I think I may be mis-representing the box (ie, it has a negative width).


Quote:Original post by lightbringer
I can't reliably reproduce that exception, but I can reliably reproduce the infinite loop when losing the game. Dunno what will happen if I win, I haven't managed to do that so far! :D


I cannot reproduce this. I will try again.


Quote:Original post by lightbringer
My specs are: Pentium 4 at 3.0 Ghz, 3 GB ram, geforce 8600 GT with 1 GB ram, running Ubuntu 8.10. and sun-java-6u10 (1.6.0_10-b33). LWJGL programs usually run just fine though.

I've also dropped the frame-rate to 1 fps by spamming GI's. Even though it says 1, nothing is actually moving anymore, so it's more like zero ^_^;;; At the very start of the game, I get about 50-65 fps. After doing nothing except producing 30 GIs, fps drops to single digits. At 40 GIs it's already unplayable.

Another thing I noticed, there are black horizontal lines appearing when I zoom in or out. Maybe due to vsync.


Okay,sounds like CPU, probably related to pathfinding. GIs tend to rape the framerate because you can build so many of them and they collide often.

I can reproduce this too on my machine. Buildling too many GIs will almost certainly cause the frame rate to die. I'm not exactly sure what to do to make this better. It would probably require serious changes to my engine.

Black lines occur on all Nvidia cards. This is an issue with the tile map format I am using, and I'm not sure how to fix it. It is probably related to scaling of images messing up the tiling on the background.

What you can do, if you aren't doing it already, is reduce the number of collision tests by only testing for nearby collision targets (you can split them up using any scheme that makes sense, whether it's a regular grid or quadtrees. I would also investigate the viability of alternatives to StrictMath if I were you.

Pathfinding in general could be smoother - I often see things such as a tank stuck oscillating when trying to pass in a narrow space, such as between a house and a nearby turret.

I also noticed that the uranium bar at the top keeps changing shape when it's depleting (horizontally expanding/contracting or jumping up and down). This only seems to happen when zoomed in all the way, or when many units are produced (or maybe both, I'm not certain about it).

About the loop after endgame, here's what happens:
Tue May 05 18:39:57 CEST 2009 ERROR:Resource not found: /res/tiletemplate.pngjava.lang.RuntimeException: Resource not found: /res/tiletemplate.png	at org.newdawn.slick.util.ResourceLoader.getResourceAsStream(ResourceLoader.java:69)	at org.newdawn.slick.opengl.InternalTextureLoader.getTexture(InternalTextureLoader.java:159)	at org.newdawn.slick.Image.<init>(Image.java:152)	at org.newdawn.slick.tiled.TiledMap$TileSet.<init>(TiledMap.java:540)	at org.newdawn.slick.tiled.TiledMap.load(TiledMap.java:419)	at org.newdawn.slick.tiled.TiledMap.<init>(TiledMap.java:94)	at Game.checkGameStatus(Game.java:1302)	at Game.update(Game.java:424)	at org.newdawn.slick.state.StateBasedGame.update(StateBasedGame.java:252)	at org.newdawn.slick.GameContainer.updateAndRender(GameContainer.java:541)	at org.newdawn.slick.AppGameContainer.start(AppGameContainer.java:371)	at RTSDemo.main(RTSDemo.java:58)	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)	at java.lang.reflect.Method.invoke(Method.java:597)	at com.sun.javaws.Launcher.executeApplication(Launcher.java:1171)	at com.sun.javaws.Launcher.executeMainClass(Launcher.java:1117)	at com.sun.javaws.Launcher.doLaunchApp(Launcher.java:966)	at com.sun.javaws.Launcher.run(Launcher.java:121)	at java.lang.Thread.run(Thread.java:619)org.newdawn.slick.SlickException: Failed to parse tilemap	at org.newdawn.slick.tiled.TiledMap.load(TiledMap.java:440)	at org.newdawn.slick.tiled.TiledMap.<init>(TiledMap.java:94)	at Game.checkGameStatus(Game.java:1302)	at Game.update(Game.java:424)	at org.newdawn.slick.state.StateBasedGame.update(StateBasedGame.java:252)	at org.newdawn.slick.GameContainer.updateAndRender(GameContainer.java:541)	at org.newdawn.slick.AppGameContainer.start(AppGameContainer.java:371)	at RTSDemo.main(RTSDemo.java:58)	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)	at java.lang.reflect.Method.invoke(Method.java:597)	at com.sun.javaws.Launcher.executeApplication(Launcher.java:1171)	at com.sun.javaws.Launcher.executeMainClass(Launcher.java:1117)	at com.sun.javaws.Launcher.doLaunchApp(Launcher.java:966)	at com.sun.javaws.Launcher.run(Launcher.java:121)	at java.lang.Thread.run(Thread.java:619)Caused by: java.lang.RuntimeException: Resource not found: /res/tiletemplate.png	at org.newdawn.slick.util.ResourceLoader.getResourceAsStream(ResourceLoader.java:69)	at org.newdawn.slick.opengl.InternalTextureLoader.getTexture(InternalTextureLoader.java:159)	at org.newdawn.slick.Image.<init>(Image.java:152)	at org.newdawn.slick.tiled.TiledMap$TileSet.<init>(TiledMap.java:540)	at org.newdawn.slick.tiled.TiledMap.load(TiledMap.java:419)	... 16 more
Yep, collisions look like the big bottleneck.

Currently I am using the "stupid method" for collisions (ie, I use an n^2 loop to check and see if GI i intersects GI j, and then apply a force)

A quad tree would probably be a better idea. I just never learned how to do quad tree collision detection. I should probably read up on this now.

EDIT: To make a quad tree, I'd have to come up with some kind of hashed data structure and then remove and add units constantly as their positions change. Is this really efficient?

As for the exception; it really doesn't make much sense. I call the exact line it is complaining about when you start the game, and it didn't crash for you then, did it?

Also, I updated the game to fix the selection rectangle bug.

Thanks for testing, guys.

[Edited by - Thatotherguy on May 5, 2009 12:05:54 PM]
Quote:Original post by Thatotherguy
EDIT: To make a quad tree, I'd have to come up with some kind of hashed data structure and then remove and add units constantly as their positions change. Is this really efficient?

Collision testing against every object in the scene obviously doesn't scale - many games use at least spatial partitioning to get around this. You can also eliminate double tests by remembering which pairs were already tested. You don't have to update the partitions every frame, either.

Quote:Original post by Thatotherguy
As for the exception; it really doesn't make much sense. I call the exact line it is complaining about when you start the game, and it didn't crash for you then, did it?

Nope, only when it goes into this loop after losing. The exception keeps looping, too.
I partitioned the space into a giant hash map that uses seperate chaining, considering each tile on the map to be a bucket in which things can collide. If a unit intersects multiple tile maps, they get mapped to several buckets in the collision map. Then, when they want to see what they're colliding with, they poll the collision map and it returns a list of entities in the same grid square as they are.

I also removed the frame limiter.

I'm not sure if this is any faster, but I was able to spam about 20 more GIs than usual. The crux is, GIs are so small that maybe 10-20 of them can fit on a square. So, I'll have to further divide the space and do a real quad tree implementation to see real performance increases.
Quote:Original post by Thatotherguy
I partitioned the space into a giant hash map that uses seperate chaining, [...] in the same grid square as they are


Why not just use an array of some kind? What extra benefit does the hash map get you?
Then, when you encounter a "bucket" with entities, instead of testing 3 entities like this:
a -> b
a -> c
b -> a
b -> c
c -> a
c -> b
Test them like this:
a -> b
a -> c
b -> c
And mark the "bucket" as processed so (if you're iterating entities) you don't go and test them again. Just don't forget to reset the buckets to unprocessed at the end of the frame.

This topic is closed to new replies.

Advertisement