Jump to content

Flexman

Members
  • Posts

    916
  • Joined

  • Last visited

Blog Entries posted by Flexman

  1. Flexman
    About: This is a short series for the Leadwerks community on the process of creating a simple game using procedural content.
     
    A short while ago I was approached to write a book on terrain generation using dedicated tools for a variety of game engines. There's a lot more to game content than just terrains. Josh's recent blogs on CSG got me thinking about one of my favourite games and had me itching to re-visit the genre.
     
     
     
    This series is an exploration of topics I don't normally exercise but are fun to do. Leadwerks is a fun engine that's ideal for prototyping ideas. So throw out your terrain system, we're going to make a game all about claustrophobia. We're going DOWN into the tunnels to blow stuff up Leadwerks style using a mix of old-school gaming know how and modern day 3D.
     
    Our goal: create a simple six degrees of freedom shooter set in a procedurally generated network of rooms and corridors. You can use this as the basis for a number of different games but as I'm a fan of the old classic shooter "Descent" and it's easy to create a physics controller to fly around in Leadwerks. Also it can be re-worked using Leadwerks3Ds CSG functions when it's available.
     
     
    Procedural Map Generation
     
    Dungeoneering is back in gaming news with Legend of Grimrock, a take on Dungeon Master grid based geometry. Many games are based on grids, they are easy to work with and often form the basis of AI routines. They are also easy to generate geometry for. There have already been numerous articles and blogs on creating such levels, you'll find links at the bottom of this article.
     

    True Story: The Survival horror Amiga game Xenomorph copied the same gridded dungeon mechanics in a blatant rip-off of the Alien universe where stone walls were replaced by ship corridors. Coded by an ex-Microprose employee I visited his house somewhere in Devon many years ago. He revealed that many of the game objects I clung onto for dear life had no function whatsoever. Lesson learned: Don't explain everything, keep the mystery, it's dishonest but more fun for the player.  
    But before we look at some LUA code to create geometry we'll first have a taster of different techniques used in creating random level geometry. After that we'll kick things up by adding more vertical elements for our demo game. I warn you in advance, I'm not a LUA expert and nor am I a big fan but I'm sure you good folks can make it better and LUA brings the examples to the widest possible audience.
     
     
     
    Node based grid
     
    Our goal is to create a collection of rooms connected by corridors through which we can explore. A simple approach is to seed a random number of nodes (rooms) and connect them up. There are other methods, such as a corridor based approach which adds rooms in a second pass, such a method is used in the classic DOS game HACK (aka NETHACK).
     
    For our examples we'll stick to a 40 x 40 grid to keep it simple. Each grid square could equate 100 world units or 10 in Leadwerks, it doesn't matter as long as we use a consistent scale. We'll stick to 100 units (1 unit = 1 meter) per grid square for this example meaning our potential map is 400x400 units.
     

     
    Here each node represents a room of random size. We can restrict the size of the room to fit within its parent grid to make it easier to deal with problem of overlapping rooms as illustrated in the figure below. Eventually we'll construct the geometry to build these irregular shaped rooms so they merge as a single entity.
     
    You can see that choosing the size of rooms will impact on how much corridor space you're going to end up with per map. This is something you can set in code easily giving control over how open or closed your level will feel.
     

     
    If we stick to the grid arrangement connecting them by corridors becomes an easy process. The difficult part is constructing the vertices and triangles to fit together nicely but we'll get to that. By far the easiest way of joining rooms together is by joining them at the cardinal points of the room. While this makes logic easy it also makes for a pretty boring layout. What's more, there's no reason why a corridor has to be of fixed width...or height.
     
    A room typically connects to a room in a neighbouring grid using the straightest link possible and we'll dog leg corridors as required. To add some interest we'll create a 'route' through the grid and randomly connect to neighbours.
     
    Again there are many ways you can do this and I encourage you to try your own variations. Our rule-set will have a random chance of connecting to a neighbour if that room. That chance will degrade if that room overlaps and on the number of existing corridor links. Hopefully our final 2D layout will approximate the figure below.
     

     
    Then each room can add its own flavour by adding columns, point lights, props, whatever fits your game.
     
    Once we've got a class to generate the map we can then move on to generating the required geometry (surfaces) so we end up with something looking like...

     
    Things get even more exciting when we'll extend these maps into 3D, with vertically offset rooms and corridors. Eventually we'll have a complete base generated by a single random seed you can fly, shoot, leap, run through with a basic controller.
     
    Once we make the logic for generating rooms 'furniture' props can be parented to the room mesh to take advantage of culling. I'm not going to add much in the way of occlusion, instead Leadwerks can take the stain and should do a good job with no effort on our part.
     
    In part 2 we'll start with some code to generate the above with geometry directly in the Leadwerks editor and we'll be using Vertex and Surface commands to create rooms which look like the screen-shot below.

     
    Random room generation in LUA, corridors coming shortly for part 2

     
     
    Everyone is welcome to contribute.
     
     
    External Links
     

    Procedural Content Wiki http://pcg.wikidot.c...geon-generation
    Generating Random Dungeons http://dirkkok.wordp...article-series/
  2. Flexman
    About: This is a short series for the Leadwerks community on the process of creating a simple game using procedural content.
     
    This week we implement the map creation process discussed in part 02 then add the mesh generation and a controller to fly around our level. Then we'll have the first iteration of our procedurally generated map.
     
    Part 01
    Part 02
     
     
     
    Starting with the Map class.
     
    Map:Create Function...first iteration, no corridors.
     
    Simple nested for-loop to generate a room for each cell. Each room is stored in the table Map.Room[] with dimensions, a counter for reference and a cell offset in world units.
     
    For our example a cell is a virtual 40x40 space, our example map is made of 4 x 4 cells.
     
    We call the function like this...

    Map:Create (407, 4 , 4 , 40 )
     
    And our function definition is...
     

    function Map:Create( seed , xsize , ysize , cellscale , roomscale ) self.xsize = xsize self.ysize = ysize self.seed = seed self.roomscale = roomscale math.randomseed( seed ) if roomscale == nil then roomscale = 1.0 end Map.roomscale = roomscale if cellscale == nil then cellscale = 40.0 end Map.cellscale = cellscale Map.roomheight = 2.0 Print("Creating map, dimensions " .. xsize .. " x " .. ysize) -- table to store our rooms Map.Room = {} -- room counter rcount = 1 for x=1,xsize do for y=1,ysize do if math.random() > 0.2 then self.Room[rcount] = {} local r = self.Room[rcount] r.roomID = rcount r.cellx = x r.celly = y r.x = math.random(cellscale) r.y = math.random(cellscale) r.width = math.ceil( math.random(3 , cellscale ) ) r.length = math.ceil( math.random(3 , cellscale ) ) r.info = string.format("id %.2d cellx %.2d celly %.2d x:%.3d y:%.3d w:%d h:%d", r.roomID , r.cellx , r.celly , r.x , r.y , r.width , r.length ) print(r.info) rcount = rcount+1 end end end self:MakeGeometry() end
     
    In the above code to reduce rooms arranged in a solid 'grid' there's a random chance that a cell skips room creation. The cell offset ( r.x and r.y ) serves to add more irregularity to the layout.
     
    Map.roomscale and Map.cellscale: bigger number = bigger space. One scales distance between rooms, the other scales the room mesh.
     
     
    After generating the geometry from such an arrangement we get this...

     
    I've added a head-up display to show an overhead map and annotations to the screenshot to show how the distribution of rooms work. So far so good.
     
    Perhaps worth mentioning the CELLS are ordered top to bottom then left to right. That gives you some idea that the random offset works to radically shift rooms around to avoid being too attached to the grid arrangement.
     

    Info: CELL is a term I use to describe a container in virtual space.  
    Before we generate any geometry for our rooms we have all the data we need to display a map (like the one above). Debug overlays or HUDs are handy during early development and can be migrated to a finished game HUD later. All we need right now is some way to check room volumes and positioning, some info and the players position. Later we can use a second camera to draw a top-down view if required.
     
    Another feature we want in our HUD is some flag to draw it, a position to move it about the screen and a scale so we can fit the map to the whole screen or just squeeze it into a corner. The following code does all this. X and Y is typically used as a screen-coordinate position to draw an element and s is the size in pixels to fit the map into.
     
    If you need to re-size text as well then you need to start rendering these to a buffer but we'll avoid the extra complexity. This is often made easier with OpenGL commands but they are not exposed to Leadwerks LUA scripts (as of 2.5).
     
    Drawing the HUD and overhead map
     

    function DrawHUD() if App.showhud ~= true then return end SetBlend(2) SetColorf(0.1,0.3,0.1,0.3) DrawText("ROOM DATA",22,22) local c = string.format("RoomCount %d", #Map.Room) DrawText(c,22,60) local x = 40 local y = 80 for n,r in pairs(Map.Room) do DrawText( r.info , x , y ) y = y + 16 end x = 400 y = 80 s = 512 sx = s / (Map.cellscale * Map.xsize) sy = s / (Map.cellscale * Map.ysize) DrawText("OVERHEAD MAP",x,y-20) --DrawLine(x,y,x+s,y) DrawLine(x+s,y,x+s,y+s) DrawLine(x+s,y+s,x,y+s) DrawLine(x,y+s,x,y) for n=0,Map.xsize do DrawLine(x + (n*Map.cellscale*sx) , y , x + (n*Map.cellscale*sx) , y + s) end for n=0,Map.ysize do DrawLine(x , y + (n*Map.cellscale*sy) , x + s , y + (n*Map.cellscale*sy)) end -- sorry for the fiddly math here -- its needed to match the map scale with the HUD display scale for n,r in pairs(Map.Room) do local roomx = x + (( r.x + (r.cellx-1)*Map.cellscale) *sx ) local roomy = y + (( r.y + (r.celly-1)*Map.cellscale) *sy ) DrawRect( roomx , roomy , r.width * sx, r.length * sy ) DrawText(string.format("%.2d",r.roomID), roomx + ((r.width*sx)*0.5)-8 , roomy + ((r.length*sx)*0.5)-9 ) end DrawText(string.format("view co-ords x:%d y:%d", camera.position.x , camera.position.z) , 40, GraphicsHeight() - 20 ) -- player marker cross in yellow SetColorf(0.3,0.3,0.1,0.3) DrawText("X", x + (camera.position.x * sx)-4 , y - (camera.position.z * sy) -8 ) SetBlend(0) end
     
    The map size is adjusted by changing "s = 512" to however many pixels across. Objects are scaled and drawn accordingly. Once we start merging rooms this will need some alteration, the overhead camera might be a viable alternative and one we can have some fun with.
     

    randomly flagged tile data, looks like a "BallBlazer" level.
     
     
    Tiles and Geometry
     
    Rather than write up how it works you can look through the code and tinker with it. The next and penultimate part will cover generating corridors and using "tile" data to merge overlapping rooms and add props like doors. You'll see already there are random light sources assigned to each room, random assortments of props such as columns, crates, particles etc. can be done in a similar fashion.
     
     
     
    The Code for this article
     
    I've attached the full code which creates the room data and geometry (sans no corridors and intelligent tile merging - we'll deal with that in part 04).
     
    Don't forget to execute this script using ScriptEditor.exe (or run it with ENGINE.EXE) you will need to make sure the path at the top of START.LUA (MediaDir) points to your Leadwerks SDK location and the default scripts are present (as "required" at the top of the script).
     
    You'll find a few bits of code commented out and older functions I used to create meshes. I've left them in for curiosity (learning and laughter).
     
    Until part 04, have a good weekend.
  3. Flexman
    Particle engines are commonly used for fire and smoke effects adding a lot of eye-candy for little effort. Every frame an emitter creates a number of billboard sprites along a vector. Normally this is not an issue when movement along this vector between frames is quite small.
     
    But what if you're talking about something that moves really fast between frames? Such as a rocket launcher or space-ship? Fellow Brit and indy developer Cliff Harris of Gratuitous Space Battles fame ran into the same problem. Here's a screenshot from his blog of a rocket.
     

     
    The rocket moves too far between frames to space out the particles in a pleasing manner. By adding a line of particles between each frame update a more pleasing effect is achieved.
     

     
     
    In Combat-Helo the hero-ship is typically loaded with several 70mm rockets that accelerate to 700 meters per second in approx 1.5 seconds. Even maintaining a short smoke trail of 10 meters can't be maintained as the rocket distance between two frames might be 50 meters or more.
     
    A linked list of billboards (TMesh CreatePlane()) is being trialled. UsingMacklebees billboard shader tweak and changing...

    ... gl_Vertex.x,gl_Vertex.y to ... gl_Vertex.x,gl_Vertex.z
    ...to work for Planes a 2D billboard function was implemented which handled colour and timing properties with a deviation (waver) offsets.
     
    This creates a ribbon of 50-150 quads (TPlanes) aligned to the camera using the billboard shader. Scale of each quad is roughly double the space between them to ensure some overlap and consistency. The smoke texture has baked lighting with a normal map however a normal map is redundant since the quad is camera aligned and rendered in the transparency layer.
     
    The spacing produces a good fill between two positions each frame. In the example image below the length of the trail is 75 meters, each particle doesn't require much updating since this was written for a specific purpose. As the shader takes care of orientation only timer tests, waver and alpha-colour needs updating although some extra instruction for management could be implemented (see footnote).
     
    Don't attempt to use ScaleMesh() as that slows the whole pipeline down. If you need to change the size of a particle you'll either have to do it in the shader or delete the particle and replace it with a larger one.
     

     
    Same again showing the AABB of each TMesh/Plane.
     

     
    That's about as fast I can can come up with using LE commands. The next stage is to replace the TPlane billboards with a single entity built using a TMesh and adding triangles as needed.
     
    Other optimisations might include changing the number of particles depending on the 2D length between the head and tail. We need more 'filler' if seen from the side than head on.
     
    Worst case would be a full salvo from 4 pods (each pod carries 9 rockets), in this event the particle manager could limit them. With the Leadwerks emitter function, once created you can't change the number of particles so having this level of control is handy for all manner of effects that need adjustment over time. This is of course slower than the LE particle system.
  4. Flexman
    About: This is a short series for the Leadwerks community on the process of creating a simple game using procedural content.
     
    In part 01 we looked at one theory of generating random maps in the style of old school dungeon crawlers. This week we'll put that into practice to generate map data, room geometry and mesh colliders. The easy part was adding a flying physics based camera to act as our first-person flown "spaceship".
     
     
    Again I want to flag I'm not a LUA expert, this is not a LUA tutorial but like most languages they are a syntax away from common functionality. It includes examples and explanations of some LUA code to relate why I did something a certain way. What you see is what you get. All code is freely available for use and modification however you see fit.
     
     

    How to use the code and run any examples in this series
     
    After working on the code a short time I found using the Leadwerks ScriptEditor.exe better for the process rather than attempting to run and debug it as an editor script. And one last note before we get on with it, 99% of the assets are included the Leadwerks SDK media folder so please edit the "MediaDir" in the LUA source. Any other required media will be included as a download.
     
    Pre-amble over with. Lets get to it.  
     
    Map Data to 3D Geometry - first experiment
     
    The focus for this tutorial is generating map data then creating 3D geometry from it. The latter raised several questions about what would work for a tutorial and flexibility for use in different kinds of games. So I've focused more on this side for part 02. (Also I had to re-write it meaning less time to work on the map data code).
     
    My first room generator working prototype created "shoe boxes" as pictured below. With lighting, ambient sounds and the physics on a controller to fly your 'ship' around in first-person view it was a passable bit of code.
     
     


    figure 2.2 - "ShoeBox" room and corridor structure  
    "ShoeBox" was efficient in that it was a collection of flipped volumes with light sources, individually painted surfaces (6 materials) and would be good for a simple iPhone adventure.
     
    When it came to merging volumes for more complex rooms I realised there would be a lot of code needed to split up geometry and re-build it. Rather than turn it into an exploration of CSG, triangulation and mesh simplification (which is not trivial) I ditched it for another simpler approach.
     
    Going back to how 2D games work, room geometry became a collection of grids (figure 2.2) that can be thought of in terms of traditional 'tiles'.
     


    figure 2.2 - tiled room (aka a regular mesh)  
    Looking more like a terrain mesh with walls and roof, the grid structure makes it easier to merge volumes, add doors, corridors and holes traps or vertical shafts. And by increasing the mesh density and adding vertex noise you can turn rooms into caves with bumpy walls. I felt justified in presenting this method as it allows more possibilities and simplifies geometry construction.
     
    In appearance it's quite like old-school cells and tiles, similar to existing 2D dungeon map generators. In my working prototype you can't individually paint a tile but it might be possible to modify the code to allow for UV painting and save out this data. Each room can have it's own unique set of materials.
     
     
    LUA code-time. Geometry Construction
     
    Leadwerks like other engines provides tools to create solid shapes entirely in code. First you need to create a Mesh object then a Surface object attached to that Mesh.
     

    local room = {} room.mesh = CreateMesh() room.surface = CreateSurface(room.mesh)
     
    Note: For clarity this is using ONE surface, this will be expanded to use a six surfaces for each side of the room. The important part is that you add geometry to surfaces, you paint surfaces with materials, you create colliders with surfaces. It's all about the surfaces baby.
     
    All room elements such as walls, floor, lights, props etc. are parented to the room.mesh which is positioned in world space. Moving the room is as simple as calling Map:Room[id].SetPosition(x,y,z)
     
    Really evil dungeon masters might want to re-position a room with players inside. Well you can do that, even rotate it. Parent the room to the whole map (which has a pivot) and you can roll the entire map around for a marble game. All walls are solid but as they are one sided you can see right through them when viewing from outside.
     
     
    Patch Maker
     
    Let's look at a LUA code snippet for creating the roof and floor mesh, I want to draw attention to one of the cute things LUA can do and if you've not come across it before it can be confusing. So I draw your attention to it now. The assignment of (nameless) functions to a table and indexing them by string.
     
    Depending on what part of the room we are building we take care vertices are wound the correct way and the vertex normals are perpendicular. So I put the AddVertex() and AddTriangle() calls into a table and for ease of identification indexed them by string such as "roof", "floor", "north_wall" (walls not included here for clarity).
     

    addvert["floor"] = function (s,x,y,height,xsize,ysize) return s:AddVertex ( Vec3( x-(xsize * 0.5), height , y-(ysize *0.5) ) , Vec3( 0 , 1 , 0 ) , Vec2(x / (ysize*0.1), 1.0- y/(xsize*0.1)) ) end addvert["roof"] = function (s,x,y,height,xsize,ysize) return s:AddVertex ( Vec3( x-(xsize * 0.5), height , y-(ysize *0.5) ) , Vec3( 0 , -1 , 0 ) , Vec2(x / (ysize*0.1), 1.0- y/(xsize*0.1)) ) end addtris["floor"] = function (s,v,ysize) s:AddTriangle ( v-ysize-1, v , v-1 ) s:AddTriangle ( v-ysize-2 , v-ysize-1 , v-1 ) end addtris["roof"] = function (s,v,ysize) s:AddTriangle ( v-1, v , v-ysize-1 ) s:AddTriangle ( v-1 , v-ysize-1 , v-ysize-2 ) end function Map:CreatePatch( surface , width , length , height , mode ) for x=0,width do for y=0,length do vcount = addvert[mode](surface,x,y,height,length,width) -- we degenerate first row and column when making a grid if ((y>0) and (x>0)) then addtris[mode](surface, vcount , length) end end end end
     
    Our room geometry code needs to call the patch builder with dimensions and the name of the component like thus...
     

    -- example useage from the room builder Map:CreatePatch(room.surface, 8 , 8 , 0 , "floor") Map:CreatePatch(room.surface, 8 , 8 , 2 , "roof")
     
    That's the easy part. We will need to extend Map:CreatePatch to take our merged room data and generate an appropriate mesh to fit the irregular shape of our rooms and corridors as supplied by our dungeon creator.
     
    Now we have a method to generate basic rooms which is easy to modify we can look at the other problem; creating our random map.
     
    Remember the map structure we're looking for, a grid of cells into which we position at random offsets a regular set of rooms (see figure below). Each room being of variable size and can overlap. For this part of the tutorial we're going to keep the rooms small enough to prevent overlap to keep the source size down and reduce the complexity. We'll cover triangulation for a more advanced geometry function in a later part. In other words I couldn't get it to work properly in the time allotted.
     


    figure 2.3 - room and corridor structure  
     
    We'll begin with a creator function...
     

    -- function to build entire map -- params: random seed value, xsize and ysize (dimensions of map in cells) -- roomscale (is multiplier of room size in world units) function Map:Create( seed , xsize , ysize , roomscale ) math.randomseed( seed ) if roomscale == nil then roomscale = 1.0 end Map.roomscale = roomscale Map.roomheight = 2.0 Print("Creating map, dimensions " .. xsize .. " x " .. ysize) -- table to store our rooms Map.Rooms = {} ... ... end
     
    For our dynamically generated game level, we need to know a couple of things;
    How big in game cells (how many rooms across and down)
    The seed from which the random nature of all springs forth (how poetic)
    How big we want the rooms to be relative to each game cell (room scale).

    A tile is simply a value stored in a 2D array e.g. tile[x,y]
     
    Our data would benefit from being organised into a grid. A 2D tile structure which represents an overhead view of our 3D world. This makes tile arrangement makes it simple to merge rooms and corridors, flag as walls, doors, traps and anything else we might want to generate. However...(c'mon you knew that was coming)...
     
    If we want to make really HUGE levels then array mapping will be inefficient, the 400x400 grid in our example will be fine but anything larger will become resource hungry as we increase the world size. Much of it becomes empty space.
     
    To avoid unnecessary memory usage and run-time costs we will virtualise the space a little. We've done it already with our room nodes (figure 2.4)
     
     


    figure 2.4 - room nodes are virtualised rooms  
    Note: A room object simply exists at world_x, world_y and is this >< big. This is for boundary test and positioning.
     
    We will use a 2D array of tiles for each room. Each tile maps to a room_x, room_y. This way the data is available to game logic for locating objects, spawn points.
     
    After room generation is complete we run a post processing function to merge rooms, this is where the tile array comes in handy.
     
    The room merge steps through all rooms, a boundary check is performed on neighbours and merging into a new room as needed. Corridors are considered rooms (just thin), where they bend they are in fact two overlapping rooms and should be merged during the same process.
     
    After rooms have been merged, the geometry builder works on the new set of room tiles to spit out all the required meshes, lights and props.
     
    Infinite Power!
     
    In theory we can make an infinite dungeon if we move the rooms around us at the origin and use world space as a random seed for new rooms. An order of magnitude more advanced than Very Big Cave Adventure.

    10 PRINT "You are in a cave (N,S,E,W)?" 20 INPUT a$ 30 GOTO 10
     
    Out of time!
     
    Yes I've run out of time for part 02 due to code re-writes. I'll write up the room generator code as part 03 and post the example code with it. Then we'll start to see the two halves coming together and creating our procedural maps.
     
    Preview: HUD Overhead Map

    First pass on HUD to show location of rooms (with ID) within the randomly generated map complex.
  5. Flexman
    Now available.
     
    *edit* A few additional notes...
     
    The controller setup page shown in this video has a number of devices listed. These are just the ones I had plugged in at the time of recording. All DirectInput controllers should be available, some will have ready to fly config files (most Saitek sticks, Logitech).
     
     
     
    I forgot to turn on the post processing effects since I work without them (generates more heat). There is a LOT of changes going on to various sensors and the IHADSS won't be updated to reflect these changes until I've done the MPDs. So please no accuracy police, I'm aware of the various bits and bobs. It's all in hand.
     
     
    YouTube Link: http://youtu.be/L8AHX8uXHpQ?hd=1
    Vimeo Link: http://vimeo.com/29957378
     
     
     
    Screenshot of the day
     
    Cleanup in lanes 1,2,3,4,5 and 6 please.
     
    Padlock, shoot, padlock shoot, HMD mode
    cleans house at close range , almost too easy

     
    Source
  6. Flexman
    Had a quick play with Saitek's DirectOutput SDK, results are mixed but not bad. The MFD resolution in Combat-Helo is a native 512x512 and the Saitek Flight Instrument Panel is VGA 320x240, there's a bit of difference.
     

    Sampling the buffer down to a smaller surface and then adding a suitable BMP header to send over to the device. Remarkably easy. I'll have three more please Saitek
     
    BUT please can you make an FIP version two with a 512x512 square ratio display? Or at least increase the vertical resolution to 256?
     

    Text is near impossible to read, but the general layout is recognisable. I don't know if we're going to support these devices in game, it's just one more thing to go wrong and support, and the default button locations don't match up so it would need code to move functions over to the left side, there are only 6 six buttons. But it's interesting to play around with.
     

     
    Source
  7. Flexman
    I know it's a little late for Valentines Day. Excessive flapping, bumping and separation is discussed in this priceless US Army video from 1980. If only they had "RotorCam ™". The Apache has a fixed rotor, mast bumping isn't an issue but it's all part of helicopter theory.
     

     
     
    I've been forced to continue hunting for other employment to deal with a mounting debt crisis. As a result work was put on hold the past two weeks (hence the lack of updates). I apologise for letting my post slide, the project really is taking a toll. I've been ordered to get back to Combat-Helo ASAP (taxes and all that business stuff needed to be done too), I'll be updating as well as I can. There's an engine update to finish rolling into the project (I started on that earlier in the week, this fixes a problem with terrain and I hope the EntityUserData and hierarchy problem).
     
    A Twitter follower suggested I post some Gun Cam footage, I had a look at that and found vegetation range/LOD issues in the MTADS camera need dynamic adjusting (not sure what the most efficient method will be yet).
     
    I'll just round this entry off by stating that raising funds in the UK for technical entertainment projects is very difficult if not near impossible. Bank staff/accountants take one look at video of Apache cockpits and give you funny looks like you're some kind of gun nut (that actually happened).
     
    In the meantime, enjoy the technical detail of the above video.
  8. Flexman
    Swimming was one.
     
    Setting up controllers in XPlane is another.
     
    Yes the things you thought were going to take a few days which turned into a week and a bit (you could almost say 'two weeks'). Josh at Leadwerks gave me a leg-up on how to put an MMO style launcher together and I've almost done wrapping up all the security for the necessary database, key code generation, CVS style updates and all the stuff we need to match individual content to clients. We'll make available downloadable content (DLC) such as new maps and the occasional helicopter (the planned CH-47D), not to mention the odd mission pack.
     
    No, this key won't work, it's a fakeSo there was a lot to do to make a simple one shot MMO style launcher. The back-end server stuff had to be built from scratch. The launch .EXE calls home, applies on-demand updates and preps game settings for launch. For simple security sakes I layered server-side scripts for handling the updates, admin and audit. Auditing is handled by triggers, SQL injection is futile since only one procedure is exposed to clients.
     
    Any DBA will tell you Auditing is an important part of any security. If you build any kind of database exposed to the internet and you don't build your own layer on top of any default transaction logging then you're kind of asking for trouble. The database engine used here is not known for keeping detailed logs so it was necessary to build one anyway. Things you might want to think about if you ever need to create systems like these are making log indexes suitable for frequency analysis (this one method Twitter uses to spot spamming), fake open doors and keys and silent alarms. My favourite trick in the past was a fake database that gives the intruder a high and makes them believe they have walked away with the crown jewels while evidence is collected. That sort of none-sense is not required here, I kept this one functional with a tiny footprint.
     
    The Pilot ID we'll be sending out is the key to your content; install once, play as you like. If you share copies around on your network you can launch 'offline' no worries, no need to be connected to the internet until you want to update. It's nice if you want to buy multiple copies for your network and support the effort put into this project but I'm poor too so I know how it is.
     
    Little bit of script consolidation and testing to do before we let this loose in the real world.

     
    Source
  9. Flexman
    Just a short post since I'm busy being pulled in a dozen different directions; I got roped into helping someone create a short health and safety film, drafting a project proposal, raising finances and even managed to fix a long standing bug in Combat-Helo. Now the sensors, line of sight and all that guff is now WORKING again, Hooray. A quick background on that, an engine update needed to fix some occlusion issues slightly changed the Model hierarchy in a subtle way that changed how actual filenames of models were retrieved, long story short, they no longer matched the ones in the vehicle database as they had "lod1" suffixed to everything . But hey it was a quick fix once traced, I digress as usual.
     
    Talented Paolo, creator of many a fine mascot has been working on some fictional nose-art and patches for the squad mascot in Combat-Helo. We knew we wanted it to feature a mosquito, the mosquito is the nickname allegedly given to the AH-64D by Taliban forces. Incidentally it was also the aircraft my father was attached to during World War II so I felt it had a double meaning.
     
    The character will be visible on squad patches and eventually be available as nose-art.
     
    "Mossie" copyright 2012 Paolo Pomes
    Below is an earlier draft of "Mossie" to help decide on nose style, the nose later became the Apache's signature Bushmaster cannon.
     
     



    Please post your thoughts and comments on "mossie", suggestions for what he can hold in his left hand are invited.

     
    Source
  10. Flexman
    I think these have been on the SimHQ forums for a couple of days but I've been too busy to post any updates. Here AD has been adding some gardens to the Friday Mosque and adding it to the city.
    To overcome scale/zbuffer issues of having a large scene, AD has buried the the tiled gardens into the terrain, just like the river sections. The gardens sit on a large slab that is quite deep, this also accommodates uneven terrain.

     

     
    No paved road surface currently. While Leadwerks supports roads that are baked into terrain geometry they are not efficient for our large scale map. One of the reasons we're looking to build our own terrain streaming system after Combat-Helo is released. We might be able to squeeze in another texture layer to splat a paved surface in.
     

     

    A high altitude view of the city shows the west side is still waiting to be populated. This was the area most damaged during a previous regional conflict.
     
    Source
  11. Flexman
    Another update of map progress on the SimHQ Combat Helo forums. Showing how the City of Herat as a sprawl of densely packed compounds and commerce is being built. Using blocks of prefabs and arranged on a grid. This is a selection of my favourite.
     

    Meant to be viewed from a low altitude, the prefabs do a good job of keeping the eye busy. Here is half a city already with parks and minarets to add. All built to be frame-rate friendly.
     

    And a mini-game for your base, the "Hello World" of physics engine programming, shooting hoops. Camp Stone has it's very own half-court.
     

     
    Source
  12. Flexman
    Another disaster strikes, PC wont boot at all. Strange thing happens on the BIOS screen, the moment any attempt to detect any drives (and I tried a few different drives that I know were fine), a bright underscore character appears under the circled comma (picture above).
     
    So apart from my laptop I'm now without a working PC and no means to fix it atm :/
     
    Source
  13. Flexman
    I've been using this for testing and making profiles for Combat-Helo since the weekend. This is a really odd stick. It's perhaps the best built joystick out of the box I've ever had the privilege of using. And quite a looker too. The textured metal feel, the metal triggers and even a couple of the HATs. Oddly this level of build isn't consistent with several hats made from what feels like a poor quality plastic. But it wasn't broken or badly assembled, and nothing has broken yet.
     
    If you didn't know, the X65 is a force sensing stick. It doesn't move and is really sensitive to tiny amounts of hand pressure along the x/y and rotation axis. The amount of pressure you apply is translated into a direction. It makes fine control a joy since there are no springs or rubber boots to interfere with your intent. Apart from the plastic hats I don't have anything to say about the stick. Just really nice to hold, use, and with no moving parts it should be reliable. Guiding the Apache in Combat-Helo around for landing can be tricky made easier by the X65.
     
    Then there's the throttle. *sigh*
     
    Again beautifully made except for the dual throttle tension adjuster, a tiny hex screw on the underside made from the softest metal on the planet designed to dissolve on contact with anything heavier than neutrinos. The dual-throttle operation set to the weakest tension setting requires quite a lot of force. More force than is comfortable or practical for a helicopter collective that might require a good percentage of travel quickly. The perfect combo would be a separate collective controller and then just use the dual throttle for the engine levers. Also it has a rather unpleasant sounding 'gloop' noise when operated, like there's a lot of grease inside being moved around. The noises are almost pornographicly sticky.
     

     
    So we have a super sensitive joystick perfect for fine control. And a near impossible-to-move dual throttle controller that needs to be nailed down (which is why it comes with a heavy steel plate).
     
    All in one neat package. A tale of two joysticks.
     
    Source
  14. Flexman
    Today we looked at a neat little program called SMAK which is a neat little program for generating normal maps for low poly models by using high poly models. It also can bake ambient occlusion shadows onto your diffuse textures.
     
    This is also a feature of 3DMAX so Dave tried a little experiment.
     
    Before, no baked AO
     
    After, with baked AO
    You might want to click on those images to see the full sized renders. Certainly the cockpit area could benefit, and the buildings we have with ground proximity shading for compounds and city blocks. Best of all, no fps impact. There's still work to do to improve normal maps.
     
    We started an audit of game textures and will extend this to include QA for each texture layer, ensuring it's as good as we can make it and optimise memory usage into the bargain.
     
    There are subtle things, such as the DXT5 compression that results in acne. Using a different DDS format and reducing the resolution can result in a better image and smaller memory footprint. See pic below.
     

     
    We made some material changes to the cockpit, specular, glow maps. I'm not sure the grips should be backlit but it makes them easier to read in the dark.
     

     
    Source
  15. Flexman
    The art-gnome at Combat-Helo has been playing with bloom and glow shader materials for the cockpit and came up with instrument night lighting. I thought it was a cool use of extra texture stages and materials with Leadwerks engine, it's an easy effect to add. With additional green point lights around the pit it should look pretty close to the real deal.
     


     
    Here's a real shot with night lighting. Panel back-lighting and small point lights.
     

     
    Source
  16. Flexman
    It's not going to win any awards for realism but we have a rudimentary ENV environment class that handles time-of-day ticking and updating scene elements accordingly. Lighting, colouring, fog, sun position. Currently it's using computed light values which renders lovely post apocalyptic scenes, the colours are terrible IMO, looks like a nuke's gone off. A lookup table will be better and an exercise I'll leave for later. Also I added some data structures for moving weather zones around the map. These are trigger zones for adjusting fog density as you penetrate. To be used for any spot environmental effects we want to add, dust-storms, rain.
     
    Not clear how best to add the gradient data, the old Combat Helo code used a tiny 64x64 bmp. Can't seem to find the graphic I used.
     
    In the remote chance I get to implement "Megaparticles" (looks around for Shader X book) the skies would benefit from 3D looking clouds. Value vs. performance. Helicopters on our battlefield won't be spending much time at altitude and we're not a fighter sim. We can manage some rudimentary clouds but I'd avoid using particles. Fill rate costs are not worth it. Which leaves billboarding and textured planes which are cheap to render.
     
    iPhone development picked up a pace. With access to my big box of assets, Dormouse (lead dev on that project) was showing me how to fly a Sophwith Camel around with nice springy 3D person camera moves and the base skybox I just made for CombatHelo. Nice little exercise to explore what we can do with Unity iPhone. Some rudimentary shaders, OpenGL and javascript. From what I've been seeing, it's not that far removed from LUA scripting in Leadwerks although I find the way Leadwerks interacts with entities more intuitive.
     
    Dave, part man-part frame-buffer, tackled craters and we had the problem of blending them with the terrain, especially when we have massive z-buffer artifacts with co-planer polys near the outer-regions of the map. Leadwerks nice built-in library of shaders proivded the answer. Using a terrain hugging vertex shader, the crater morphs to fit, and the frag shader does a reasonable job of blending in the base texture to the terrain.
     
    And we have a new concrete bridge for Herat. The region map has been a work in progress for close to three months now. All the compounds, village buildings, structures number approx 502 with the airbase and the city of Herat yet to complete.
     
    It's a massive region on foot, and takes a while to fly across. Navigation is a bit of a problem, I hope to fix that with a pop-up map if I can work out how to blend the different map layers from the terrain buffers to make something readable. Otherwise it's going to have to be another pre-loaded DDS texture with enough resolution to zoom in.
     
    Here's more of my least favourite colour in games. Brown.
     

     
    Source
  17. Flexman
    I'm putting together specifications on the mission side of the game. To me, the bit that you 'play' is every bit as important as the simulation side, and while it's taken a back seat for now, things are getting to the point where it's time to get on and make it all work. Going through some of my older material on this, it needs to play like Longbow 2, have the crew management elements from Gunship 2000 and strategy elements from tactical board games on guerilla warfare and a bit of a story element that wouldn't be out of place in a Chris Roberts game.
    So where do we start? Units, missions, events and triggers.
    Units perform missions, missions contain waypoints, events and triggers. So lets start at the top and work our way down.
    Missioneering
    Not many will remember the last iteration of my mission planning tool and generator, Missioneer Delta pictured below, circa 2000, seems like almost 10 years ago :/

    The plan is to put in something similar onto the command tent terminal you can operate to change waypoints and assign untasked airCREW to helos to carry out listed missions. In some ways this is not unlike Enemy Engaged. Missions are not necessarily assigned to aircraft (they can be), but we'll assign them to the player, AI pilot or crew. Like the arming system, it will be possible for a player to take the role of a commander and assign missions to aircraft that pilots execute.
    You can walk around and choose an aircraft that's not already assigned (see it's info plate when on foot for status). In future we hope to have a selection of helicopters/vehicles (CH-47) but we're focused on the Apache.
    When the player boards the aircraft, this is like loading a data cartridge with your mission detailed into the aircraft's avionics. The TSD will be updated with waypoints, times and mission page populated accordingly. First man in sets the mission.
    The mission ID# key is set in the vehicle entity. This is reset on one of two conditions, the player has exited the aircraft for 5 minutes or the master zeroise guarded switch in the cockpit is operated. In the case of the latter, a new mission profile can not be loaded until all crewmembers have exited the aircraft.
    Mission ID# is just a key reference to the hosts list of active missions which can be viewed on the command tent terminal (connected to the projector).
    But we're getting ahead of ourselves. Missions and units need a detailed specification which is the point of this blog entry and my current task.
    Running under the surface of the simulation will be the all important campaign engine which iterates through units. We'll take the term UNIT to mean a collection of vehicles, a "group entity". Lets look at an old user editable unit form, take from Missioneer. Nothing really remarkable about it, just happens to be handy.

     
    So we can see some of the basic parameters of a unit. There's a list of entities than make up the unit, a 'formation' which is a list of relative positions that each member of the group will attempt to follow (we'll have some behavioural exceptions to this). An orientation, direction to face when at rest. A name, something fancy and military. Skill level, agression and some factional information.
    There are also some timers, our game runs in a real-time 24 hour clock cycle (with time advancement). So unit timers might be relative to an absolute time (world time) or mission time (from dust-off). Timers have an enabled/active status too in case they need to be activated by triggers.
    For example, if we want a group of insurgents for player assigned patrol mission to spawn when a player has taken off, the mission engine will assign a MT (mission time) of "00:00:00mt Active", but we might want them 5 minutes into the mission, or not spawn at all except by some trigger, such as a player entering the engagement area.
    Or we can set the unit destruction time (just means the de-spawn time). For example, a rescue against the clock, get to them before they are discovered by encroaching insurgent forces. Once depawned, that would trigger a unit removal message which another event trigger can listen for, signalling a mission fail.
    So timers are simple unit level events that require no special handling by an event system. But for our game to handle recognition of a "win" or a "fail" situation we'll need to add a basic "cause and effect", a "cause" being destruction of unit "x" with the "effect" being "mission complete".
     
    Mission Events
    SpawnUnit (unitID) DestroyUnit (unitID) SetUnitWaypoint (unitID, waypointID) SetUnitFlag (unitID, active|weapons_free|godlike|formation|state, param) SetUnitFaction SetMissionResult SetWorldFaction( factionID, delta) SpawnObject (objectID, parameters) CreateWaypoint (unitID, waypointID, location, speed, altitude) Play Audioscript (script or audio filename)
    Mission Triggers (in any active combination)
    MissionRating (percent, win|loose|draw) MissionTime (+ - secs, MT|LT) UnitDistanceFrom (unitID, targetUnitID, distance_meters) UnitDamage (unitID, damage_percent) UnitWaypoint (unitID,at|before|after, waypointID) UnitStatus (not_in_combat|combat|flee|panic|landing|takeoff) UnitInZone (unitID, zoneID) FactionDelta (factionID1, factionID2, + -value) DiceRoll (percent)
    These are enough for the campaign and mission system to generate pretty much most situations.
    Now the tricky part is to build the logic to generate seemingly intelligent behavior and entertain missions using this small command set. And here is where we can have a lot of fun.
    We could extend the complexity of the logic further by adding a LUA Get/Set interface for the event system. Then user made missions can apply some complex logic. Even creating whole missions from a LUA script. This is not something we want to do at this time. But for the future, it could be done.
     

     
    Source
  18. Flexman
    Quick update. Busy working on a lot of small things. We have a cockpit update coming to update MPDs, internal and external night lighting. MPDs taking to the TStores class and working towards having a number of cockpit functions up and ready for the start-up. Dave added the CP/G throttle panel too (which removes the power switch and engine startup).
     
    Experiencing a problem with fps slowdown over time again. Mostly down to repeatedly running combat-helo, stop, edit, re-run. FPS drops to single figures. I'm not seeing main memory leaks and it doesn't effect other games. I'm not clear what is happening, a reboot fixes it.
     
    I wanted to see what the TEDAC would look like later so I was cheeky and borrowed a still from another game as temp background.
     


     
    Source
  19. Flexman
    Finally a video showing the free flight mode we really wanted to show at Summer Sim 2010. Thanks AD for doing an amazing job of making it all look good.
     
     

    http://www.youtube.com/watch?v=Y6ILqIQDaio
     
     
    Sorry about the lack of blade-cam, LUA object reference problem. Will get it sorted.
  20. Flexman
    Updates to the green-zones, incremental improvements to the billboards, painting 'shadow' under vegetation.
    Dev-diary update at SimHQ
     


    It's looking great considering how much detail we can't use. Currently we can't use the 2.32 engine due to lack of LOD distance control, and loading the levels with all the vegetation takes three times as long in the new version due to the extra processing required for veg culling. The detail in our production level map shows little performance difference between versions. Upgrading to a new version of the engine is becoming less attractive from a performance viewpoint. Which seems a bit silly but there you go.
     
    In the background we have started preliminary design work on an all new rendering system, not for Combat-Helo but for a later project (again simulator related). This will incorporating object streaming and allow for very large terrains. This work isn't interfering with Combat-Helo, there will be no unnecessary delays in production.
     
    I'm currently working on aircraft data import, the part that takes a data-file (profile) of an aircraft (helicopter, fixed wing, hot-air balloon etc) and builds an instance of a class that tells it how it flies. Our FFD (Free Flight Dynamics, or Freds Fantastic DLL) class is pretty flexible, a specialist physics engine of it's own.
     
    One of the more interesting features are the virtual helicopter controls. Your control inputs are sent to "virtual controls" which then have any necessary trim by AI/AFCS or other input shaping applied. The virtual cyclic can be set to match throw of your actual joystick, you set the ratio of your joystick to that of a full size 70cm cyclic. So if you're using a 20 cm tall stick, setting the joystick length to a value of 20 will correct the input as if you have a 70cm floor standing cyclic. It uses a non-linear function to still give you 100% cyclic throw (shaped after 20% so you can still apply fine control inputs).
     
    We'll be discussing the Auto Trim feature at a later date. It's so simple most pilots will never know it's there.
     
    Source
  21. Flexman
    Airbase preview at our SimHQ forum.
     
    Gluing the airfield into place has been an interesting job, using terrain 'visibility' to cut out terrain chunks and fit it into place. Shindand airfield is used for medical and humanitarian flights, it's currently VFR only and no lighting system. We might modernise it a little for our scenario.
     
    Most NATO flights will come and go from here. A node system for AI aircraft to follow the taxiways and tank-off/land will be added.
     
    Multiplayer options starting to appear. The base sat-dish serving as network startup/shutdown. I'm using a red light on the dish to indicate offline and blueish-green to indicate connected status. We're using the tried and tested Raknet library, it's the only one I have experience with and quite reliable.
     
    These screens are from my forest test area and for testing purposes only.
     
    Command tent (that hanging light, I stole from an underground bunker). This is a spacious area where you'll find the mission terminal, chalkboard (scores/stats) and overhead projector display.
     
    Reality check. These command and briefing tents are normally enclosed/air conditioned and inflated. But in homage to older 90s sims we're using this. It's roomy and allows quick access. MMOs typically have overscale interiors/doorways to ease player mobility.
    This week allowed me to finish off the missing elements of the arming procedure. Loading rockets into zones and building the weapons page inventory. I did run into a slight discrepancy. As I allow each pod to be loaded with 3 different kinds of ammo, in the Apache you can only select 5 zones. I was torn between giving more flexibility to the player and keeping it simple or hardwiring 5 zones and cross-linking zones. For now I'm going to let the players have the extra zone and bump the additional level of realism to a post release update.
     
    Source
  22. Flexman
    We're not trying to re-create Armed Assault, or even build some form of Helicopter MMO. Our plan is to take the old school 2D interfaces of military bases and create 3D analogues. Mission assignment and planning is done in the command tent. This is still exploritory, we have a number of office furniture elements planned, some of which we have tried in the editor to get a feel.
     
    There's more furniture to come. A mil-spec laptop/terminal, interactive map on a board (that's a copy of your personal map - will use the same buffer).
     
    And eventually we hope to have various AI pilots sitting in on briefings that you might want to converse with Wing Commander style. Romeo 1 from the intro mission will be hanging around. Along with WO J Petersan and others from time to time.
     
    I don't have much time to decorate, just placing these objects around my test-map to check how they look and function but it should give you an idea.
     
    With a couple of AI guys and a co-op friend there should be enough room to keep it looking busy. It's possible we might make AI crewman choices ala Gunship 2000 available in this manner if it works.
     
    We need some flooring I think. Hexmesh or some other plastic matting.
     
    Using a projected texture for mission briefings on the OHP. Interacting with a screen set 5 meters away is problematic, once at the projector you'll get to interface which will allow you to view available missions and annotated map, with a "close up" option (position a 3rd person cam up close to the screen).
     
    Like with other parts of the game, such as arming, the player interfacing with the projector will have their data shown to everyone else. Allowing you to give briefings. If there's time we might add a laser pointer for mouse control.
     
    We're using a 1024x1024 buffer for the projector which is a material assigned to a special spot_light entity parented to the OHP model. Objects/avatars walking in front of the projector have the image mapped over them in a realistic manner. So you too can act like a right tit in front of the C/O making shadow puppets with your head.
     
     
    Additional objects in the command tent will operate on a private level, mission planning and editing will work on a laptop type screen and a wall map will be copy of your pop-up map. There may also be a Sierra Hotel score board, I think that's required by tradition.
     
    So this the the start of the important ground office in Combat-Helo. We tend to have about three different project elements on the go at any one time, rather like making a series like Star Trek, planning, filming and pre-production.
     
     
    Finally a recent ETADS screen-shot, taking a peek at a sign through the trees some distance away (it's way off to the left out of sight so don't bother trying to spot it). Some folks will be well pleased with the corners. This coming week I'll be working on the event system (delayed due to PC technical problems, see earlier blog posts) and more of the TADS elements.
     

     
    Source
  23. Flexman
    These are placement tests for the Apache model in the editor, getting a feel for colour, levels, position, range and angle. The left nav light (red) on the Apache model needs to have the fullbright material applied to be visible in dark conditions. One pilot was telling me that the ground on the left side on the helicopter appears brighter than the right with night vision. Interestingly our night vision shader amplifies lighting levels based on final pixel colour and gives a boost to red values so you should also experience the same effect.
     

     
    Same again but with the nav strobe blinking, ever so short flash that should be visible 2km away in game terms. It uses a corona and not a real light source for performance reasons. It's highly visible and does it's job. Although it will probably flare-out or clip in NV mode. I experimented adding two point lights in the cockpit area, these lights currently exist in the internal cockpit mode but I'll see about adding them to the external model if it can be easily done. On the whole, performance would be better just baking that light onto the texture but the exterior cockpit is really simple, the canopy doesn't cast shadows and the light range is short.
     

    Final shot is the retractable spot-light, which we were going to model, maybe we did already but can't remember...(check notes). It's supposed to be steerable and there's a toggle switch for it somewhere. I think using a 3D cone mesh to add a bit of fake 'haze' around it might be an idea.
     

    I shall get these coded up into the game model now. Pretty pleased with the overall layout.
     

     
    Source
  24. Flexman
    [NTS] Left Upper button. Next To Shoot is the ubiquitous video game cycle through targets. Or TAB target if you play MMOs.
     
    I've touched upon how radar works in this blog entry from August - Radar - A Discussion
     
    The Apache can automatically selecting priority targets based on some sort of criteria. This short blog post touches on how I've elected to do this. Again if you're familiar with the 1996 classic, Janes Longbow 2 there's nothing unfamiliar here.
     
    The TSD (tactical situation display) collects data from visual cues (look at object), radar and TADS (again look at and store). A linked-list of 3D entities is stored and sorted by range. The list is re-sorted by what type of object it is.
     
     



    Target object sorting as follows:
     

    Fast Movers
    Helicopters
    Air Defence with Radar
    Air Defence
    Armour
    Wheeled
    Aircraft normally only show up in air targeting modes. The image above has one on the GTM Radar which is a BUG but that helicopter (another Apache) is on the ground.
     
    Then these are sorted by range.
     
    The [Cycle Target] key (default: TAB) steps through the list. This is different to the [Padlock Cycle] key (default: LCTRL F4) which applies to your head view and steps outward through visual targets sorted by range only. Sometimes the nearest isn't closest to the centre of view.
     
    I'll touch on how I've programmed the game internally. A linked list of objects that are picked up in the FCR footprint are added to a TSDcontact list if the entity pointer (an entity is a vehicle) is not already present.
     
     
    The game maintains separate lists from sensors and a Tactical(Situation Display) list which is used for referencing entities on the TSD. It also allows for messages received by the THelicopter message handler to add entities to the TSD when the player presses the 'ABCC download' button to download shared targets from a shared digital battlespace (fancy name for a simple array). To upload your TSD list you press the 'ABCC upload' function. I will think about expanding this to work on several channels in later versions.
     
    Tactical Sensor Lists
     
    The TSD used in our Apache vehicle is simply an instance of the TacticalSensor class which is used for all AI but the inputs are wired up differently.
     
     



    These inputs are updated when in use, typically triggered by a player pushing keys. I've colour coded the inpus accoring to type. FCR is radar type area scan, high volume, Orange (HMD) is using the Mk1 eyeball, TADS in blue is an optical sensor (longer range eyeball) and Red is known data from external source, which you can imagine as a radio or some data modem.
     
    As potentially there might be a hundred active AI vehicles in close proximity having all of these using all kinds of sensors, doing lots of volume searches and entity queries is woefully inefficient. Fortunately the natural hierarchical structure of unit can be simply used to make things much more efficient.
     
    Since entities are grouped into Formations which share waypoints and mission targets, they share a common awareness. The same TacticalSensor class we use in our Apache. Only this time the inputs come from the different entities in the formation. Some will have an active sensor system, some are unable to supply input.
     
     



    They periodically perform a sensor scan (interleaved to spread the load) to refresh their group TacticalSensor list.
     
     
    Oh NO! The MIG! Target Priority
     
    I'm sorting the linked list when updated based on criteria that I want based on experience from other games of this type. Worked for them, works for me.
     
    In LB2 a Mig was triggered at random if flying over 250 ft. If not spotted quickly it was almost certain virtual death. To give these a high priority I added a Priority field to the SensorClass and arranged the icon IDs (1,2,3,4 etc) so by default the Priority value can be taken from the icon ID then modified later. Now the most dangerous entities can be simply sorted on this field but we could for example assign an entity as a "Primary Target" and add +10 to the Priority to have it automatically sit at the top of the TAB target list.
     
    Very handy for scripting tutorials and the like. For example we can now spawn a virtual waypoint marker on a target range and command the avionics to give top priority.
     
    So whatever the first entry on the linked list is, that's the NTS object, the second in the list would be the ANTS.
     
     
    PFZs
     
    Another often asked about feature in Combat-Helo is the ability to create PFZs. Which is something that only applies to the Hellfire missile system which is coming in a later update as we've not yet implemented it. However our Tactical list makes this a trivial matter to implement. We have a static list of entities, mouse input on the TSD map and mouse driven events. Everything needed to add PFZs and NFZs.
     
     



     



    Correct weapon symbology coming soon
    Whole HMD needs a going over.
     

     
    Source
×
×
  • Create New...