top of page
Game Summary
Images and the Map
2D Collision
Amanatides Woo Raycasting
Entities and Basic AI
What Went Well
Challenges
What I Learned

Assault (2D top down tank game)

Turret shooting at player tank.

Technology

  • Visual Studio (2013/2015)

    • C++

    • GLSL (OpenGL)

  • Photoshop

  • Perforce

 

Genre Single Player, 2D, top down, tank

Platform PC (Windows)

Development Time 2 months

Resources Used

Table of Contents
Game Summary

   Assault is a 2D tank game, with the intended means of play being that of the xbox controller.  The game uses an image file to load up the game map, as well as place units onto the map.  There are three types of units outside of the player: enemy turrets, enemy tanks, and ally tanks.  Enemy turrets are locked to a single location, and will shoot at the player and ally tanks that get in their radius and it has direct line of sight with.  Enemy tanks, if it has line of sight with the player, and the player is within it's radius, will turn to chase the player and shoot at the player.  If the player or an ally tank is not within it's view radius, it will wander about the map randomly.  An ally tank is on the player's side, and acts much the same way as the enemy tank, except it has less health than the enemy tank.  The controls are described within the game on start up. So there is no need for a controls section on this one.

Images and the Map

Summarized Bullet Point:

  • Map is read in via an image file.

  • Particular colors mean that particular entities will spawn there or be a wall and so on.

  • There is a minimap; thats just regular map getting rendered a second time, but smaller.

  • Fog of war:

    • For game view fog, press F

    • For minimap view fog, press R.

   As previously stated, the engine used in this using GLSL for rendering. Every image has a set address that the program attempts to load from, and the images data is pushed up to the GPU, except for the map.  The map is a special case in that it does not have the image data get pushed up to the GPU, as it actually has to take that data and instead set the tile types it has, plus spawn in the correct entities at those tiles based on the colors per pixel of the image.  Creating a minimap can be pretty simple as well, since its basically just rerendering everything at a smaller size.  However, it is worth noting that if the player is given full view of the minimap at all times, then its very easy for the player to just be able to snipe every enemy on the map.  What can help with this is implementing a fog of war type of effect on the minimap.  By default there is no fog of war, but in game fog of war in the actual game view and the minimap views can be toggled by pressing the F and R keys respectively.

Map Generation code from Image.

Entities and Basic AI

Summarized Bullet Points:

  • AI is very basic:

    • Wander AI: Just picks a random direction; AI controlled tanks constantly move forward

    • Chase and Shoot AI: If valid target in range and have direct line of sight, AI picks that direction to try and turn towards; then starts shooting if within 2 or so degrees of it.

   There are three types of entities in the game.  They use a wander AI and a Chase and Shoot AI.  The wander AI occurs whenever it does not have line of sight towards a valid target.  Every few seconds, the entity will turn towards a target angle when wandering.  When a valid target is actually available, the AI controlled entity will turn towards it, and start shooting at it if the angle is close to what is needed to look at it.  A valid target is considered to be whenever there is another entity within a set range from our entity, our entity has a direct line of sight to it, and it is not on the same team as our entity.

    For more information about which AI controlled entities do what, please click the button below.

All Entity Class Declarations and Inheritance tree

EnemyTank, AllyTank, and EnemyTurret Updates along with common methods

2D Collision

Summarized Bullet Points:

  • Two sets of collision handled:

    • Circle versus Circle

    • Circle versus Box

    • Circle collision is on entities

    • Box is on tiles

   There are two types of collision occurs in this game. Circle versus Circle collision, and Circle versus Box Collision.  To determine that two circles are intersecting, get the distance between them by subtracting their center positions, then get the length of that distance.  If that length is less than the combination of the two circles radius-es, then the circles are intersecting.

   Circle versus box collision is a little trickier.  Firstly, we have to grab the tiles around the entity with circle collision (North, East, South, West should be done first, followed by the corner cases). In the non-corner cases, first check to see if the given tile is solid, then get the displacement between the entity plus the entity's radius in the direction of the tile on the access checking against, minus the edge of the tile testing against. If that displacement is less than 0, then the circle and tile are intersecting, and thus the entity will need to be moved.  In the corner cases, we again check to see if the tile is solid, then get the position of the nearest corner of the tile were testing to the entity we are testing against. We take the entity's position minus the corner's position, and check to see if the displacement's length is less than the circle collision radius. If it is, then the entity is colliding with the tile.

Map Update methods, and all Collision related methods.

Amanatides Woo Raycasting

Summarized Bullet Points:

  • Raycasting is done very quickly through Amanatides Woo version of Raycasting.

    • Basically idea is only check against tiles at the exact point cross into a new tile; thus only test a tile once.

   For the Turrets and Tanks to check line of sight between one another, it has to run a raycast.  In order to make those as fast as physically possible, it would be best to avoid repeatedly checking the same tiles over and over, which the simplest form of raycasting does.  Thus comes in Amentides Woo version of raycasting, where in the code would calculate the amount it takes to step into the next tile, then upon hitting that tile, checks to see if that tile is solid.  If the tile it hits is solid, then the raycast detects a hit.

   The raycast first takes in a start position, and end position.  With that, we calculate several bits of data mentioned in the image below before entering a loop, and testing if tiles are solid when we enter their borders.  We do not exit the loop until we hit something or find our end point.

The Amanatides Woo raycasting method in the Map class

What Went Well
  • Getting the basic AI working was really quick and easy, even with the team IDs.

  • Old GLSL code was really user friendly, thus easy to set up rendering, and easy to get textures set up.

  • Reading the map data from an image file was really user friendly, and made it easy to visualize the level layout.

Challenges
  • Having made the tile definitions hard coded only makes it a little too rigid for a lot of fun interesting level design.

    • Had not known how to read XML at the time.

  • Time was limited, and a fair number of things I was hammering my way through for the first time.

    • Did not get as many entity variants as would of liked.

    • Wanted to have a way to cycle through levels after killing all enemies.

  • Frequently let my methods and functions get overly bloated with code, leading to slow downs in debugging, and making it difficult to read.

What I Learned
  • Learned a fair number of algorithms and concepts that had not previously touched or worked through before.

  • Planning things out further before starting on a particular system or segment of code can go a long way in making the best of one's time.

  • If a function or method starts to get bigger than 40 or 50 lines, consider breaking it out, or at the least comment the hell out of it.

bottom of page