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.
     
    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.
  2. 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.
  3. 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/
  4. Flexman
    While waiting on fixes for the flight-model and control inputs, putting some game into the game we talked about ranges and how performance measuring was going to work. In addition we wanted to add a little variety which required working mob AI.
     
     
    So nothing fancy but I managed to rustle up a simple finite state machine FSM to get some tanks and cars running around. Our design uses a group formation system (a group is a number of individual units that share common logic, e.g a tank platoon) and if you've ever used Missioneer you'll be familiar with the concept.
     
     
    Currently tanks are driving around a small test tool I'm using to test the module, switching formations, revving engines, exhaust smoke. Performance is king so updates are interlaced, no vehicle physics are required so animation suffices.
     
     
     



    Each group member has a goal pivot, when the formation changes the individual vehicles seek their pilot according to their driving behaviour. All the pivots are parented to a master pivot controlled by the group. This way you just need to update the group position (e.g movement orders to x/y) and the rest takes care of itself.
     
    We can look into expanding the states later when we want them to do more complicated things, and do that on a per unit basis. Tank gunners will want to turret to target when attacking, manpads will simply turn to face. Same state but slightly different logic per unit. And this can be done in LUA level by setting the models "fsm_mode" key. That makes less work for me and gives Dave the artist some nice toys to play with. At the end of the day I at least have a tile based tank engine to play with. I'll throw up a video.
     
    For the gunnery range we don't need anything demanding; some AI road following traffic, people in groups and the odd vehicle following a set of waypoints. Nothing spectacular or difficult there. That hardest part is turning the 3D geometry of the road network into a navigation grid. Then your mob groups need to know if they are supposed to be following the road or their own formation (switching as they move from one to the other).
     
     
    Roads
     
    The one problem I have in getting AI traffic running around is putting together a nav-grid I can work with. Our roads are large models (2 or 3 assorted) that are built in 3D Max using a height deformation modifier (the same height-map used to build terrain layers). And it mostly fits. I think we need to flatten it out so only the surface triangles can be read and turned into usable data.
     
    Speaking of art, "Mossie" has been given some love.
     
     



     
    Further reading:
    FSM gate scandal - Why they are old hat
     
     

     
    Source
  5. 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
  6. 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.
  7. 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
  8. Flexman
    It was over a year ago we were notified that some of the models we had purchased from Dexsoft might possibly have been stolen. After a period of investigation the probability was quite high this was the case and Dexsoft contacted customers to offer new packs. However months later I was unable to get a reply about these replacements and only in November when doing a review of outstanding assets and licensing we had to either press again or do a re-build.


     

    Dave elected to take it upon himself to do a rebuild and not wanting to have to reposition every building adopted the same dimensions with the exception of adding much needed 'basements' (a basement is just an extrusion of the exterior wall so that it will sink under terrain so no gaps are left if the centre of the model is positioned on uneven ground.


     

    Originally the models were made for use in first-person games and LOD0 had details such as railings and girders. Dave completely built (from scratch) versions complete with new textures and made them more efficient at the cost of some detail. An original building had 5213 polygons, after a rebuild only 728 polys (which is iPhone territory).


     



    Original stolen model on left, rebuilt from scratch on right
    Scratch build on left, original on rightAny small indie developer takes a leap of faith when purchasing models from 3rd parties, you don't know where they came from or their history. In this instance we got bitten as did the 3rd party which handled the situation well (but it would have been nice to have the replacements anyway). No harm was done, anyone using or releasing games with 3rd party content be aware.
     
    Thanks Dave for once again being on the ball.
     
     
    Update
    Started work on the updater again.This is based in part on the Leadwerks SDK downloader which is pretty much everything I needed given a little twist and a slice of lemon. Hopefully some of you will be seeing this in the near future. At some point we'll add user names and a regcode system prior to any content downloads (these will not be required to play).
     
    As much as you might want to click on it, you can't yet
    With any luck the 'one click' update system will let us add rolling improvements at the cost of occasionally annoying you with a download when an update is available. I just want to be able to push one button, get the latest changes to any content I own and go.
     
    Support for different builds (content)

     
    Source
  9. Flexman
    I apologise for lack of updates, long time since the last one (weeks it seems although I have two unpublished ones which are no longer relevant). I've been avoiding online spaces during this time, work has been bogged down with the multitude of tasks not just relating to the Combat Helo game.
     
    I'm working on the flight model again this week so don't expect any updates in a while. I did get started on an updated FAQ and will publish that ASAP. Lots of things happen around this time of year with concerts and church services, when you have a musical family there's a lot of evenings taken up with those.
     
    So I don't know when we'll have something to show for all this work. It'll happen when it happens, there's no budget to finish and I've got huge debts that require me to stop at some point and take time off to do other work.
     
    On the plus side I did get a nice pressie from one of my brothers which is going to buy a nice cheap car (sensible, used K car but importantly has a working HEATER, a nice to have feature for UK winters). Something to be said for being happy just by virtue of being in a car that's warm.
     
     
    "Do you know what’s killing Western democracy, George? Greed, and constipation. Moral, political, aesthetic. The economic repression of the masses institutionalized." - Bill Haydon from John le Carré's Tinker Tailor Soldier Spy 1974.

     
    Source
  10. Flexman
    Last week I identified one issue relating to UserEntityData introduced with the last engine update which prevents consistent update of Enity data due to some change in the hierarchy and no documentation on what was changed.
     
    So I'm faced with having to re-factor (meaning to changing code but same behaviour) core sensor code. It's the sort of thing that is utterly frustrating and makes one want to throw everything out of the window. It's not as if there aren't enough things to do.
     
    There's 4 major issues I'm not happy with:
     
     

    Flight Model bridge refinement
    Ground dynamics
    Horizon gapping and other asset problems (licences/legal, audio)
    Events / Triggers

    I know I can rush some of these things and end up with something I'm not happy with. And if I'm not happy with it I don't see why anyone else will be happy. The majority of potential customers don't follow this blog, they don't care about how much work or team sizes, finds and lack-of, how or why, and often they don't care about the word "beta". To do what's right in the long term means having to not cut corners and do what needs to be done.
     
     
    Sucks though.
     
     
    Who would have thought building a stand-alone study sim of the most advanced attach helicopter on the planet would be so difficult? What gives?

     
    Source
  11. Flexman
    US Army released video showcasing the new Block III Apache in a virtual training environment.


     
     
    The video covers in a nutshell...
     

    Weight reduction
    Improved software upgrade pipeline
    Increased engine power 701-D engines and improved drive system
    Better digital battlefield intergration
    UAV commanding
    IFR certified instruments
    Reliability and servicing improvements
    RFI range triangulation
    Maritime classification
    Awesome new logo

    Further reading

     
    Source
  12. Flexman
    While Dave is away hopefully keeping his head above water (all those Bear Grylls survival videos should come in handy) I've got not much else to do except worry and get on with my to-do list.
     
    C-SCOPE was something I remember saying wouldn't make it but turned out to be a freebie since everything was available to simply drop it in.
     
    [C-SCP] button on the FCR page overlays FCR target symbols on TADS video and HMD. Makes finding those hard to see vehicles a piece of cake.
     
     



     
    C-SCOPE FCR symbols presented on the HMD
    ref: http://www.fas.org/man/dod-101/sys/ac/docs/ah-64-mfp-1-33.htm
     
    The High Action Display is currently getting an update for the ACQ interaction (I've tried really hard to work through what this does and how I can gamify it to make something both usable and understandable by normal people).
     
    Also I'm overjoyed at getting news of our ATC audio recordings and looking forward to playing with that.

     
    Source
  13. Flexman
    Dave who is the artist on Combat-Helo is currently in the process of evacuating his home in Thailand as the floods in Bangkok have made living difficult. With no fresh drinking water for days, no supplies in the shops and place of work closed, services breaking down it's time to jump ship.
     
    Blue indicates server flooding (clearly) Red=flood defence
     
     



    BBC carries the story here
     
    Dave's last act before evacuating was uploading the latest Chinook work to our server alas there was no time to upload the PSDs. Good luck and fingers crossed we'll hear from you in a week or a month...

     
    Source
  14. Flexman
    Yes Panic.
     
    When you're rushing to get a reasonable build ready for hammering out problems I'm finding I'm making all new problems. Going over the HMD code I realise how badly it needs rebuilding, there are existing elements that need updating, a few new ones that require adding. There's no way to rebuild the HUD in time.
     
    Another problem. LUA in the Apache entity. Works in the first instance, but fails in subsequent entity spawns resulting in the inability to mount the aircraft. It's an issue relating to LUA accessing keys stored in the model. I want to rip out all the LUA code from models except for the model initialisation that puts on pylons and attaches the rotor models. Not much time to deal with that either.
     
    Dual Seat configuration.
     
     



    The interaction between front and rear seat was not well thought out early enough, instead I opted for a 'duality' where all features could be operated from either seat with just some interface differences. I should have opted for a strict seat A can do xxxx and seat B can only do yyyy. This was a mistake in my attempt to simplify control but ended up introducing more complex logic.
     
    It's not too late to undo this but a difficult process to start. If I have to design this game all over again I think I would probably nail down all of these problems from day one. Hindsight being wonderful.
     
    TrippleHead - lot more pixels to post process, looks great but a GPU strain
     
     



     



     
     

     
    Source
  15. Flexman
    Not a Combat-Helo post. I'm engaged in a spot of design and research but was looking for some old material online and found I had left a digital trail pre-dating commercial internet use.


     

    28 Years ago I drew this. I was in high school. Shocking really. I used Z80 machine code to generate the 'impressive' sound and visual effects in this game. *wince*


     



    A lifetime of programming and tinkering, stacks of hard drives of unpublished projects ranging from Spanish school time-table generators to a Black Shark snapshot campaign generator.
     
    Some material I doubt will ever be revived, the Memotech MTX 500 version of Next War was stored on cassette tape, probably oxidised beyond recovery. However the code lives on in other forms, the dynamic campaign system was enhanced and put to some use in a PC build. Some of which will form the backbone of the Combat-Helo campaign. One day I hope to merge the big war game with the Apache simulation and revisit the forgotten Fulda Gap scenario.
     
    More unreleased WWIII fun and games
    NATO vs Warsaw Pact at the Fulda Gap
     
    Even my own attempt at producing a self-indulgent comic based on our exploits in the Star Wars Galaxies MMO...(PDF dug out of the old SONY Online game forums).
     
     



     



     



     


    Even though the game will soon have the plug pulled the footprints we leave behind in the digital space will live on...for a bit.
     
    I've rescued the original PDF and made it available here... Orion Outpost Chronicles part 4 - PDF
     
    Anyway back to work.

     
    Source
  16. Flexman
    AD has started some great work on the armaments of the CH47 that will form the first major DLC pack for the full release of Combat-Helo. Each door position will offer a fun interactive activity, usually in the form of throwing out obscene amounts of virtual lead.


     

    For more pictures please see:
    ADs SimHQ CH-47 blog update thread

    Mini-gun, I don't get the mini part though.

     
    Source
  17. 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
  18. Flexman
    Starting to feel the pressure now. Both the financial and stress factors are weighing in. Doesn't stop me working but it's hard to switch off. On the business side there's a ton of things on the to-do list, it all eats time taken from production.
     
    Spooky, ok so the lip light isn't actually on his mic.
    If it was you wouldn't see this.
    Boeing sent me a poster back in 2002, this is a homage to that.
    This time with the rear seat.
    Taking out bad guys without damaging the good guys is a challenge.
    Experimenting with simple TSD display and labels.
     



     



     



     



     



     
    On top of this I'm studying some Unity material and shader programming. I could use a beer, a real one.

     
    Source
  19. Flexman
    Quadtree software has released the 3.1 update to Grome.
     
    Grome is a fantastic terrain editor I've been playing with for future enhancements and rolling out a larger terrain systems in the future. If you play flying games and RPGs on consoles chances are you've probably already seen a Grome edited terrain. It's used by nearly every major player in the simulation industry. Incorporating a plug-in system, OpenSceneGraph and now new improved Unity integration.
     
    What's new in 3.1
     
     
     



     
     



    I'm quite keen to see how it works in the up and coming Leadwerks 3(D) engine which is looking to sport threaded streaming of assets. If this could be incorporated alongside the vegetation system it would be perhaps the most powerful and complete 3D engine for less than 1,000 USD.

     
    Source
  20. Flexman
    Remember the spinny radar thingy in Longbow 2? Scan sectors sizes and off-axis settings for the Longbow FCR (Fire Control Radar)? No?
     
    If you look at the heading tape of the screen-shot you'll see in the heading tape the "butt-cheeks" (two Ds back to back) on a heading of 225, off axis by 45 degrees. This indicates the direction the radar is pointing, as the FCR display is 'always up' in GTM mode. This can be a little disorientating and the radar footprint is mirrored on the TSD, this paints a clearer picture of where it's pointing. Failing that you can see the radome outside the aircraft turning as it seeks out the designated offset.
     
     



    (And why are all our aircraft IDs Z666? We shall never know. If you have a TrackIR and explore the cockpit nooks there's even a Clint Eastwood reference in it).
     
    Radar offset angle is set by clicking on either of the two LEFT RIGHT arrow buttons on the MPD or your designated sensor left/right control input when the FCR is your selected sensor. (If TADS is selected the sensor control steers TADS instead). NOTE: The offset can not be moved while the FCR is active, although you can queue movement by hitting the offset control then quickly cycling the FCR burst key. Got it?
     
    It will be in the manual. Promise.
     
    Vectors - all vectors, no bitmaps
     
    In the front seat, TEDAC view of the FCR

     
    Source
  21. Flexman
    Dull day, so lets post about something most normal people find dull. Fuel flow controls. In the Apache D model this is administered on the FUEL MPD page.
     
    Not much to say about it, I'm bored already. It does what it does. Our Apache has two internal ballistically shielded self-sealing fuel tanks. Fuel can be drawn or transferred from one or the other to adjust weight distribution. Activating fuel boost engages the rear tank cross-feed valves as seen here. Fuel transfer between tanks should normally be left to auto unless you feel the need to play with it. HTR flight model should take account of the weight distribution.
     
    Marching antsFuel flow takes about 4 seconds to change, while changing, indicated fuel lines are drawn in high intensity white before returning to green.
     
    The most important button on this page is bottom right [CHECK]. This brings up the a sub version of the page where you set your bingo fuel status if you get an alert reminder in the UFD.
     
    Bingo TimeAward for dullest sim video goes to...."Fuel Crossfeed"..yeah. There it is. It's Friday.
     
     

     
    Source
×
×
  • Create New...