Game AI: How to implement a basic deathmatch shooter

We from the Yuka team have finally developed a more complex showcase to demonstrate the features of the library. The following example demonstrates an implementation of a basic shooter-AI in a very simple deathmatch scenario. You can watch the game flow from an aerial perspective or click on “enable FPS controls” on the control panel in order to participate in the game.

Start Demo

The reasoning and decision-making processes of the AI are based on a so called “goal-driven agent design”. The weapon selection is implemented with fuzzy logic and the path-finding with a navigation mesh. All these features are provided by Yuka, so we were able to focus on the actual app-related logic.

If you play the game by yourself, you start with a blaster but you can collect a shotgun and assault rifle as well as health packs. The controls are quite basic:

  • Movement: WASD
  • Reload: R
  • Shot: Left Mouse
  • Weapon Selection: 1 (Blaster), 2 (Shotgun), 3 (Assault Rifle)

Please keep in mind that it’s not a rendering showcase^^. We’ve focused on AI programming and just provided a simple but (hopefully) clean visual appearance. Rendering is of course done with three.js. All models are glTF assets and we use an unlit MeshBasicMaterial with a light map for the actual level. Most of the models are from Mixamo and Sketchfab, the level was designed by Abdou Bouam.

The project is open-source and MIT licensed, see https://github.com/Mugen87/dive. Of course many features you would normally expect from a modern AAA shooter are missing. It is still a technical demo and not a real product/app. We hope to enhance it with additional iterations and also provide in-depth documentation and tutorials. However, it is matter of time and money if this is doable in the future. In any event, the project should be already a useful resource for everyone how wants to implement more advanced game logic. Contributions and feedback are welcome!

17 Likes

That is awesome.

2 Likes

Well, it’s not like the new Rage but at least Open-Source and rendered with three.js:grin:

4 Likes

I could see right off of the top of my head (Since you put it out there…) :slight_smile:

1.) Hit detection (maybe raycaster modified as a particle that could be fired at an object and report back on hit? )
2.) Geometries that have varying damage modifiers when hit.
3.) Any sort of buildup of energy the more you do something.
4.) Cool particle/volumetric effect (otherwise known as an “Alt” or a “Super” ability) takes place after stats reach a certain level/death/respawn.
5.) Make it playable with a controller slight_smile:
Although I know this is targeted at mostly laptop/PC GPU’s, even if this were made into a game API for larger GPU’s (aka Console type GPU’s) this would be huge.

Of course, if you make these changes to the Demo you will be hounded to keep adding things to it for everyone’s game development. You will have no time for general questions on Three JS :worried:

There is always time for community support^^

Just wow. You guys rocks!

1 Like

Looks great. A couple of small points from my side:

  • health bars. It would help understand what’s going on a bit more.
  • color-code weapons projectiles. I can’t tell the difference between blaster and AR
  • enable drawing of back faces on the level mesh, it looks sad without that
  • more aggressive blending of strafe animation. looks quite floaty right now

a few more that might be low-hanging fruits:

  • particle effects for pickups
  • on-hit particle effects, like sparks from level hit or blood spatter on body-hit
  • a couple more bots, the demo feels a bit anemic on action
  • view cone. It’s not obvious who can see whom at a glance. I think it’s super cool that bots physically turn, but it’s easy to miss I feel without seeing view cones/facing direction.

Many thanks for your feedback! I will put your points on a to-do list for further consideration.

If we would ever develop a real product, many things like your suggestions would be important additions. In this particular case however, we wanted to focus on the AI part and verify the features of Yuka with a more complex showcase. If you only develop very simple stuff, certain restrictions of a library won’t be visible. This project provided valuable input to make Yuka more stable.

Besides, it was important for us to demonstrate that you can implement something like this with good performance even for low-end devices. The app is single threaded and we have done no modifications to three.js. One of our most important task for the next months is to further improve the performance by implementing more software optimizations in Yuka.

BTW: The demo just draws the front faces so it’s easier to inspect what’s going on from the spectator view. In FPS mode, it is not an issue at all. Unfortunately, it’s hard for us to optimize the animations of the bots since we have no designer in our team. We are using the assets 1:1 from Mixamo.

3 Likes

Looks great. Studying it now.

I initially tried it on a MacBook using Safari and got a black screen. Console shows this error ReferenceError: Can’t find variable: requestIdleCallback.

Looks great in Chrome.

So Yuka is a Game Engine using THREE.js as the main render component. Is that correct?

Do you generate NavMeshes by hand or do you use a program to generate them?

1 Like

Safari is not supported so far since it does not support window.requestIdleCallback. This could be polyfilled but Safari does also not support Ogg Vorbis. We decided to exclude Safari and invest our time in other stuff. Sometimes I have the feeling Safari becomes the new Internet Explorer :unamused:

Yuka is actually just an AI engine but it provides some game engine related logic so you can easier represent your game entities as renderable components (e.g. meshes). In any event our team is too small to develop a real game engine (we are only two guys right now^^) so we try to focus just on the AI part. It’s also important to note that there is no dependency to three.js. You could also use Yuka with any other 3D engine like Babylon.js.

We generated them in Blender. However, a long-term goal of the project is to implement an own nav-mesh generator. The general approach for doing this is well documented in code and scientific papers. It’s just a matter of time to start with a JavaScript implementation. In this way, you could generating nav meshes on-the-fly if necessary.

If you are interested in the general concepts, read Programming Game AI by Example. We extensively worked with this literature^^. The basic AI architecture of the project is based on the shooter “Raven” which is discussed in detail at the end of the book.

2 Likes

Thanks for advice. I’ve been playing with the Blender Navigation Mesh builder. Afraid it isn’t as tidy as the Unity one. Looking for ways to export the Unity one as a 3D Object. Might be easier to create one by hand.

If you can export it to glTF, you can load it with YUKA.NavMeshLoader since the library expects the data in glTF format. This project might be helpful in this context.

Thanks for the tip.

what is the best practice this days for a mini map?

what i have found is this approach http://stemkoski.github.io/Three.js/Viewports-Minimap.html

with two render

I would say that’s pretty bad. You want to render only what is needed, not the entire scene. It’s bad for performance otherwise. It might be a good teaching tool, but you would almost never do it this way in a real game.

Also, typically you want to render a symbolic representation, show enemies as red dots, ammo pick-ups as yellow bullets, and health pick ups as white crosses, for example.

I have a minimap module for meep, it’s pretty complex as a result of applying multiple optimizations but it does what I have described as its core.

2 Likes

Easily the best free and open-source WebGL FPS available, that I have found. Feels very professional. :+1::+1::+1:

I felt that the second weapond did no damage at all. Then I understood that it must be the “shotgun”. It did not look like a shotgun, so I expected something else. Also, I think a short-range weapon may be mostly useless in the particular context. The way to “win”, in my short experience, is to find a rifle before going willingly into a fight. (And probably camp near a health pickup. :stuck_out_tongue: )

Stats would be cool. Kills and deaths.

Enabling controllers (from the programming side) is actually not hard, using the HTML5 Gamepad API.

Agreed!

Nah, I think blood is irrelevant to the “sports” aspect of the game. And definitely to the AI aspect (unless the bots start following blood trails). Maybe I am a bit on the anemic side. :wink: At least I found the amount of enemies perfect. Most encounters are proper duels, which is not necessarily the case with more enemies on the board. And there are moments of hunting (or hiding) and expectation between the encounters. Maybe I would get bored after playing a while, though. Then a slider in the GUI would be great.

2 Likes

We added a shotgun in order to implement a weapon which fires multiple projectiles at once. That’s a bit different how the blaster and assault rifle works.

To be clear, the weapons and items are all from Sketchfab since we could not invest any money for assets. :sweat_smile:

The demo renders the same scene with a top view camera which is essentially the same approach like in this Unreal Engine 4 tutorial (https://www.youtube.com/watch?v=8AhY7CUbzwc).

However, you can also implement a minimap more simple by just mapping the most important objects like characters or items onto a 2D sprite representing the level. In this way, you do not render the scene twice which is definitely more performant.

3 Likes

The texture for such a 2D sprite may be generated from a single orthographic rendering of the map with no characters or powerups, optionally stylized with another shader.

3 Likes

That’s a matter of preference. Either way, particles can be teddy bears for all it matters - what’s important is to highlight the impact, to communicate to the player visually and audibly that a hit on a certain object has occurred.

I do like the idea of non-murdery games, but personally - I’m completely desensitized to blood in games at this point.

I do just that, but it’s an off-line step, I export a 2k rendering of the entire level as seen from above. In that rendering I remove certain objects from the level, as they have no relevance and would only confuse the player. At runtime I load the rendered texture. It seems like common sense mostly. There are some additional things that can/should be done if your level is very large, like tiling that image.

2 Likes

Super idea !!! )) I propose to add tanks and armored vehicles !!!

I once made an online shooter. You can kill yourself in different browser tabs. ))

And in this case, you can connect online players.