Jump to content

  • Log In with Google      Sign In   
  • Create Account

Banner advertising on our site currently available from just $5!


1. Learn about the promo. 2. Sign up for GDNet+. 3. Set up your advert!


Norman Barrows

Member Since 04 Apr 2012
Offline Last Active Yesterday, 08:03 AM

#5232666 Moving beyond Arcade Style Games

Posted by Norman Barrows on 03 June 2015 - 04:02 PM


Or do you have fixed numbers of each type of game object?

 

bingo.

 

but no reason it couldn't be variable.

 

an example:

 

lets start with a character struct with just a name, x, and y. and we load and save a variable number of these. no problem, write the number of character structs, followed by the name, x, and y for each struct. very standard stuff, right? when you read, you read how many there are, then do a loop of that number of iterations reading in the values for each struct.

 

ok, now - add something else - how about z?   it should work for this example.

 

so you leave the existing code alone, and add new code at the end:

 

// you've already written num_structs, so no need to do it twice. just write the (new) struct data.

for each struct, write z

 

so you're saving all the version 1 format data first (name, x and y), followed by all the version 2 data (z).

 

and load just reverses the process:

 

read num_structs

for i=0 i<num_structs i++

    {

    read name

    read x

    read y

    }

// you could be clever and realize you probably don't need to write num_structs twice, so for new format 2 data just do:

for i=0 i<num_structs

    {

    read z

    }




#5232659 Need some tips and tricks to hunt down a bug

Posted by Norman Barrows on 03 June 2015 - 03:40 PM


Nah... I love arrays

 

sounds that like me, you like to use memory pools implemented using arrays.

 

i've found that with a bit of careful api design for array access, you can preclude the need for almost all range checks.

 

i honestly can't even remember the last time i had a range check error. its been that many years. and i've been doing this full time (for the forth time in my life) for the last 3 years now.




#5232614 Moving beyond Arcade Style Games

Posted by Norman Barrows on 03 June 2015 - 01:09 PM

It doesnt realy matters for small stuff, big stuff you Always write blocks if you can anyways.

I think you dont notice the difference with 1 write to disk, or more writes to disk.

 i used to think that way too. write out each member of each struct individually? instead of blockwriting the whole array of structs? naw! it would never work! too slow!

but once you get down to the bare bones fwrite_nolock routines, its actually doable. i'm saving 72 meg in about 5 seconds flat.

 

the whole problem with writing blocks is that if the definition of a block changes in the code, you can't read existing savegames without converting them first.

 

by writing out blocks one variable at a time, you can change the definition of a block, and still read existing savegames. by only adding new variables at the end of the file format, and initializing new variables to default values before loading, you can convert old format savegames to new format just by loading and saving them.




#5232564 I find it hard to find new games

Posted by Norman Barrows on 03 June 2015 - 09:05 AM

as a hard core gamer (as well as a game developer), i struggle with the same problem. day after day, year after year, i find myself playing the same titles over and over, because i cant find anything better.  

 

for me, those games are a RPG, a sub sim, and a wargame: elder scrolls, silent hunter, and total war.  there are things about each i dont like, but cant find anything better.

 

i also used to play city simulators, but simcity3 was a letdown, and the Caesar series is no more.

 

flight sims are another one i cant find anything good (and current).

 

carribean (a pirate rpg) has caught my eye, but looks like it ended up being shovelware (they didnt finish it, just shoveled it out the door). i was hoping i wouldn't have to make a pirate rpg, and could just buy and play one. i was hoping carribean would let me do that. but thats ok, last night i got my 100 animated skinned meshes onscreen at once test going, and got skinned mesh LOD going too. so that pirate rpg idea of mine with 100+ combatants in real time boarding action combat is no longer a dream. i could build it today.

 

mech sims is another one. i was a big fan of the metaltech battledrome series by dynamix (not mechwarrior, the other guys.  mechwarrior was the action game, battledrome was the hard core sim).

 

or anything to replace red barrron II. or x wing, or tie fighter, or falcon 4.0 gold edition.  the list goes on and on.  

 

some games i have taken a hard look at:  mount and blade: warband - i'll probably give this a try.  GTA4 - something different, never actually played GTA myself, though all my friends do. but DRM for PC version from steam is an issue, so i passed on that.

 

sometimes i'll spend a whole evening looking for a new game , instead of playing skyrim yet again. 

 

and the saddest part of all...   look at what you find when you go look for a game. 90% of it is all the same crap.

 


So, if you are a gamer then how do you find out about cool indie games? Any favorite sites you use, or just word of mouth? What cool games have you discovered’?

 

search the web, and the usual online outlets. perhaps a little word or mouth, i've hard good things about witcher3, and the battlefield and uncharted series on consoles. i didn't have the heart to tell my console buddies that battlefield started out as a hard core mission based WW2 FPS. they just think its yet another cool cops and robbers title like GTA or Juarez.

 

as for what i've discovered, not much. first: cool is subjective - opinion, not fact. so one person's "cool" game might be next person's "stupid", "boring", "childish", "too easy" or "too hard" game.

 

right now, we're in a very "me too" time in the game market. low cost development tools and a plethora of devices to develop for leads to a lot of new entries into the field. unfortunately, most are just building yet-another-tower-defense game. someone made money on angry birds? me too! i want to do that too! let's make yet-another-angry-birds clone!

 

eventually, the uninspired copycats will realize they can't reproduce the fad success of angry birds (or tetris back in the day), and will stop flooding the market with clones.  at the same time, original works with true merit will start to slowly rise to the top - stuff like minecraft, kerbal space program, etc. so its not all bad news. but like anything, you have to sift through 99.9% junk to get the 0.1% good stuff. and yes, i'd say its close a 1000 to 1 ratio of crap to quality titles out there right now.

 


If you are a developer then how and where do you promote your game?

 

in the past: free playable demos on bbs's and AOL. posting demo links to every game site you can. i've also gotten free tv coverage on the evening news and a top 10 DL on AOL, both of which are the type of PR you simply cannot buy.

 

this time around, i'll probably use the same basic marketing strategy. but the number of game sites (such as gamespot, ign, etc) has gone down, and the number of online game stores has gone up.  not quite sure why, but i get a bad vibe from GOG and Steam and such.  they will require serious thought before i decide to use them as marketing tool / channel.

 


and if it Is easy to increase your fanbase before launching or after release?

 

the idea is to create demand for the product that pulls it through the channel, not spend cubic dollars trying to push it though the channel. fanbase is at most perhaps an indirect indicator of how successful you are at this. probably its greatest value is as a source of info as to how well your design works in the field, and what changes need to be made in the next design-implement-deploy-fieldtest cycle.




#5232421 skinned mesh triangle count

Posted by Norman Barrows on 02 June 2015 - 12:12 PM


I would suggest you first get a working process running. Then, if needed, profile the process to determine where improvements could be made.

 

i've got all the code up and running.

 

its just a test routine off the tools menu in Caveman 3.0, but it does the following:

 

loads and draws skinned meshes with multiple animations, and can change between animations. no animation blending yet.

supports all 5 or 6 skinning methods from tiny.cpp.

can set the texture for each mesh in a skinned mesh on the fly before drawing. textures can be pooled. materials can be pooled if desired.

can draw an object in relation to a bone (IE attach wpn to hand bone type stuff).

drawing multiple instances of a skinned mesh, each with its own animation controller, using a single shared skinned mesh and skeleton.

there's different versions of the code so you can load non-pooled textures and materials with the mesh and use them for drawing subsets, like a regular dx mesh,

or you can draw using the current texture and material for all meshes and subsets in the skinned mesh, or you can set textures for each mesh in the skinned mesh individually, then draw it using the current material.

 

the last thing i tested was using the in-game realtime 10 channel matrix editor to scale, rotate, and translate eyeballs to their correct position with respect to the head bone, while playing an animation where they don't move. this allows me to read off the srt values for use in a pre-defined "offset" matrix used to draw each eye. since the eyes are drawn as an attachment to a bone, i can change their texture, or make them look in any direction desired. to support visual tracking, the xr and yr angles from the lookat (or camera's forward) vector to the target's direction vector from the camera should be the rotations that need to be applied before the offset matrix, follwed then by the combinedtransform matrix - i think. haven't tested it yet, but i think its right, might need to negate the angles or something.

 

about the only code left is a skinned mesh pool class, and a controller pool class. i've pseudo coded them, but was too lazy at 1am last night to lookup syntax and var names, so it still needs about and hour's worth of work perhaps, at most.

 

so i'm more or less ready to go for it with a fully rigged and ready to rock model. the question is how many tris? i started with a beautiful mesh - excellent topology, easy to mod, looked great right out of the box. when i went to export with two animations, i thought blender had crashed. i tried exporting just the mesh. it took 10 minutes. turned out the mesh was over 100K tris. i decimated it to about 10K for testing, but the topology was ruined. about half way through testing, i switched to a nice topology mesh of about 30K tris. but this is probably still a bit big for 100 onscreen at once type of thing. a female will require 3 drawsubset calls - a male, two calls (no bra). i decided to implement bra and loincloth as separate meshes along with a head and body mesh, as the two or three meshes in a single skinned mesh. eyeballs and hair will add three more DIP calls per character, using static VBs and IBs. in my rigid body system, i'm using 14 (male) or 15 (female) static meshes to draw a character (if they're bald, subtract one hair mesh). some of them i know are perhaps unreasonably highpoly, 50K for a body, 20K for a head, that kind of thing. but they're all static.  i was somewhat surprised to find little difference in FPS between various skinning methods in tiny.cpp sample running on my pc. something like 169 vs 175.




#5231980 Help - getting input form windows

Posted by Norman Barrows on 31 May 2015 - 09:20 AM

ok, i'm checking into that wm_quit and wm_close question, here's what seems to be going on...

 

my code is only for fullscreen d3d apps, not windowed. so the only way to get a wm_close message is to alt-tab or ctrl-alt-del out of the app, then close it from the desktop toolbar or program manager. both of which seem to send wm_destroy messages. that's why i don't need to process wm_close.

 

but if the user does break out and kill the app, i do need to process wm_destroy, which should postquitmessage, and shutdown the app.

 

postquitmessage sends a wm_quit to windows, which unhooks the windows message proc. wm_quit is a message sent from an app to windows to unhook its message proc, its not a message sent from windows to an app.

 

wm_close:

https://msdn.microsoft.com/en-us/library/windows/desktop/ms632617(v=vs.85).aspx

 

wm_quit:

https://msdn.microsoft.com/en-us/library/windows/desktop/ms632641(v=vs.85).aspx

 

wm_destroy:

https://msdn.microsoft.com/en-us/library/windows/desktop/ms632620(v=vs.85).aspx

 

postquitmessage

https://msdn.microsoft.com/en-us/library/windows/desktop/ms644945(v=vs.85).aspx

 

 

a more typical implementation would probably be to set a "I_got_a_destroy_message" flag in the window proc, then process it when you process input. input can basically be processed two ways:

immediate processing - as soon as you get a wm_destroy or whatever, you process it.   my code above is an example of this.

deferred processing - you set a flag or post some sort of message to an internal message queue or something, indicating some sort of input has occurred, then process it later, perhaps when its more convenient or whatever.  but this requires extra flags, message (input) queues, variables , etc, and spreads the code over multiple areas of the program (received in one place, but processed elsewhere). 

 

for my input system, i've opted for immediate processing whenever possible. its just simpler and i don't need timestamps. so i just postquitmessage, shutdown the game library and exit. seesm to work fine. its similar to back in the day with a simple text based app - you get input to quit. well, you can exit out of all those subroutines back out to main, or just halt. there's no real difference. good idea to cleanup first (release stuff), but windows does a pretty good job cleaning up after you even if you don't - but you should not rely on that.

 

as for keyboard input, i'm only concerned with key states at the time of polling, and poll at a fixed rate. so i don't require input time stamps, and consuming input in ET sized chunks, a la L Spiro.

 

for a full-tilt implementation, use L Spiro's time stamped and "consume input in ET sized chunks" method. unfortunately i can't find the link at the moment. can't recall if it was an article or posting here or on lsprioengine.com.




#5231880 Moving beyond Arcade Style Games

Posted by Norman Barrows on 30 May 2015 - 03:22 PM


Are you saving one struct per file? Otherwise, I don't know how your system could work.

 

i'm saving every variable in the game pretty much - more or less the entire state - missiles in flight and all. in a single binary file.

 

think of it this way:

 

time to save the game, so you're going to write some data to disk. a bunch of variables. some might be members of objects, some might be members of structs, some might be stand alone variables. 

 

all i do is write them all out to a binary file, one at a time, in a fixed order, then read them in, in the same order.

 

the fixed read /write order means you know what variable to read next, and thus its type - and its size. no key:value parsing required.

 

now, time to add a new variable to a class declaration.  and we want to load and save this new variable as part of a savegame.

 

so first you do all the usual things, declare, init, change, and use it. then comes time to load and save.  this means your savegame file format is going to change. the old format won't have the new variable, the new format will.

 

now, how to change the format? well, you could just insert it into the existing load and save code right after the previous variable in that class, but that would change the existing load and save order, and any games saved with the old order could no longer be read. and you want to be able to read the old AND new formats, as well as save in the new format.

 

so what you do is this:

1. when loading a savegame, init all loaded vars to default values first, then read in saved values over them. if the savegame file ends before you read all the variables, any unread variables will retain their default values.

2. to add new variables to the savegame format, you always add the load and save code at the end of the routine, IE at the end of the list of variables to load/save. this preserves the loading order of existing variables. so now you can add code to the end of your load and save routines for the new vars, load in an old format file, and the new vars will take default values, and when you save, it'll save in the new format - automatic conversion with no special routine or utility.  and backward compatibility all the way back to the original format.

3. to remove existing variables, you just read and write junk values to maintain the read order (and size). if you add a new variable of that type later, you can use that "empty slot" for the new variable, instead of using a junk value. this can safely be done if both your junk and new default values are zero. this saves space, but then very old formats with the deprecated value in them will no longer be compatible with the new format.  i find it handy since i only really have the one in-house long term playtest savegame file to convert at the moment, and variables continue to be  added to and removed from the format as the game evolves. no sense reading and writing a bunch of junk values in the Caveman 3.0 release version. it doesn't have to be backward compatible with anything. but if i remove variables in the version 3.1 release, i'd need to use junk values, and not reuse them, for backward compatibility with v3.0.

 

rather surprising - or perhaps not - you don't get much of a performance hit writing individual variables one at a time using fwrite nolock (or whatever its called) - ie the good old fashioned bare bones down to the metal no error checks c-type runtime library code. i'm saving something like 73 meg in 4-5 seconds flat.

 

 

 

i find this method gives me a number of advantages:

1. no key-value pair parsing required

2. easy to mod: wi(intname) wf(floatname) ws(stringname) - write int, write float, write string.  ri(intname), rf(floatname), rs(stringname) - read int, read float, read string.

just add a line of code to the end of load and save for each new var - all cut and paste boilerplate stuff. you can also save chunks of vars/data with blockread and write, since its binary format. but that means the chunks can't change without automatically breaking the load and save code. the thing about writing out individual members vs a whole struct is you can change a struct definition without automatically breaking the existing load and save code.

3. automatic backward compatibility

4. automatic format conversion.

5. only have to save the members you want out of a struct.

 

i was looking for a savegame system and file format that was

1. easy to use

2. fast

3. backwardly compatible

 

my savegame format for Caveman has probably changed six times since i implemented the system. no more re-creating or converting long term playtest games from old to new formats. and i have a long term playtest game i started almost two years ago now.

 

over the long term, you end up with a save routine something like this:

init vars to default

open file

load original format vars

load file format 2 additional vars

load file format 3 additional vars
(...)
load file format N additional vars
close file
 
save is identical, with write instead of read calls.



#5231720 Equipment/modules for ships

Posted by Norman Barrows on 29 May 2015 - 01:21 PM

hull upgrades can go both ways. USAF operates airframes that are over 50 years old (transports and tankers).   but the f-111 vs the f-117 is a definite hull upgrade due to new materials. note that both are deep penetration ground strike aircraft. one pre-stealth, and the other post-stealth. this is somewhat similar to the tiger I vs tiger II, where the hull itself was one of the the major new technologies in the design. the t-34 is another example of a "new kind of hull" type design.

 

the US navy commonly will rip out the entire guts of a ship to refit it over course of many months. about the only thing they can't do is put intercontinental ballistic missiles on a ship not originally deigned for it, and they can probably do that too, given enough time. 

 

there's no reason to think that such behavior patterns would not occur in the future, any future, unless you have game universe rules that make it otherwise.

 

so you probably only need hull upgrades when you have changes in hull technology - which would most likely be the result of completing a node on the research tree.

 

by limiting or eliminating changes in hull technology you can limit or eliminate hull upgrades.




#5231711 Equipment/modules for ships

Posted by Norman Barrows on 29 May 2015 - 12:51 PM


There's more to consider than simple friction even in real non fictional science and it can be made very believable if you have a good writer and like all good lies base it partly in truth...

 

all of the people some of the time, some of the people all of the time, you know the rest.

 

remember its a 4x, not angry birds, your target demographic will tend to be a little smarter than the average bear.

 

its doesn't have to be "realistic", but it does have to be believable within the rules of the game universe.




#5231710 Equipment/modules for ships

Posted by Norman Barrows on 29 May 2015 - 12:42 PM


You just try strapping that brand new warp/wormhole drive into it and see how long it takes before you turn the crew inside out...

 

that's the inertial dampeners, not the hull. of course the hull does have to be able to take the internal stresses. hulls are what hold components together. inertial dampeners are what keep the crew from becoming a smear on the wall under high G forces.

 

you might say that hulls of a given size can only use engines of a certain size due to lack of structural integrity, even if they have enough "slots".




#5231701 Imposter Transitioning to Mesh

Posted by Norman Barrows on 29 May 2015 - 11:52 AM


4-5000 vertex objects

 

that would be the main difference. 

 

i'm using low poly trees. 100-250 tris each?

 

i have single meshes for the trunks, and single meshes that are ALL the branches for one tree. i draw all the trunks with the same texture, all the trunks with the next texture, etc, then all the leaves of all the trees with the 1st leaf  texture, all the leaves of all the trees with the second leaf texture, and so on. since all the branches of a tree are just one mesh, a non instanced tree is just two meshes and thus just two draw calls. 

 

trees are especially hard to get good LOD models for. you almost really have to make each LOD level model yourself by hand, and even then the change in LOD level can still be noticed. good LOD model matching combined with alpha blend in / blend out can minimize this. but at the end of the day, LOD and imposters are both workarounds / cheats / hacks for not being able to draw lots of hi-rez models at once. 

 

in the case of Caveman, paleolithic technology limits weapons range to about 50-100 feet. so the player will almost always be focused on the nearby environment, out to 50 feet, not 500 or 5000. so i opted to draw dense vegetation out as far as i could, and then just use a shorter fade distance and no LOD or imposters. but then again, from the beginning, i've known i'd need to draw lost of stuff - thousands of plants and perhaps a hundred people and animals at once.  so i've tried to keep triangle budgets for models down to an appropriate size in an attempt to achieve this. an example: just two crossed quads with their tops twisted in relation to their bottoms makes an excellent grass or plant mesh with just 4 triangles, and almost no edge-on disappearing.

 

if you'er starting with hi-rez trees of 4k-5k tris each, its going to be some work to get good looking LOD and or imposters going, since you're starting with such a good looking tree! <g>. 

 

you might want to attack the problem from all angles simultaneously, reduce the number of tri's in your trees some, reduce texture sizes a bit, reduce the number of instances slightly, implement 2 LOD's (normal and low-rez) and one level of imposters. 

 

btw, are you getting into double and triple pass drawing of leaves for those trees yet? <g>   yes there is no end to the insanity of how far you can go with graphics, given enough processing power.

 

to make your trees pipeline friendly (data oriented design), break them up into separate static meshes based on texture, or texture and material combination. make the meshes as large as possible, so one mesh for all branches, instead of one mesh for each branch, etc. draw them based on texture/material order, then near to far.

 

consider clumping two or three trees into two meshes - one of three trunks, and one of three tops - instead of drawing them as three trees (6 meshes).

 

you could even go for entire patterns of trees. all the tree trunks of a given texture in a "terrain chunk" are one mesh, all their tops are a second mesh. if you had 4 types of trees in a "terrain chunk", you could draw them all with just 8 meshes and 8 draw calls. get about four terrain chunk patterns of trees going (pre-sorted by texture) , and then tile them at random across the world.

 

even just doubling up your tree models will cut draw calls in half.  instead of one trunk per mesh, a mesh is two trunks, separated by some number of feet. and so on with branches and such. but the number of tri's rasterized doesn't go down. and that's got to be the bottleneck, unless you have 100 branches per tree and draw each one with a separate draw call. only lower LOD will fix long rasterization times. IE draw fewer tris.




#5231283 2D Platformer: Choosing a physics engine

Posted by Norman Barrows on 27 May 2015 - 11:14 AM


Specially since something being "easy" is a very subjective thing and it really depends on who you ask.

 

quite true. in my case, roll-your-own would probably be easier than trying to use a 3rd party package. then again, physics was always my best subject, and i've been doing this a LONG time.




#5230577 Imposter Transitioning to Mesh

Posted by Norman Barrows on 23 May 2015 - 09:44 AM

i too was displeased with transitions from impostors to meshes. in the end, i optimized my render queue to the point i could render 10K non-instanced mesh trees out to a range of 300 meters or so using fixed function dx9 pipeline, and got rid of impostors entirely.




#5230403 Making Indie game with advanced Animations or AI

Posted by Norman Barrows on 22 May 2015 - 06:48 AM


I want to know whether I should make my own game engine, or choose one of the
game engines

 

 use a game engine if possible to save time.

 

 

 


I've been told developing your own game engine will reduce lag in the final game, is this true?

 

not necessarily. full access to source code simply means you have the ability optimize anything required. but all the engines mentioned are designed to do what the do very well, and very fast.

 

 

 


I want obstacles, uneven ground and character tiredness to alter the characters' animations using some algorithms that can also be used to animate robots similar to Big Dog or Atlas (both made by Boston Dynamics). Where can I find or learn how to make such algorithms?

 

true procedural animations don't seem to be that common yet.  so instead of a single procedural stand/walk/run/sprint in any direction animation, you typically have separate walk, run, and sprint animations for each direction ( 3 speeds times 8 movement directions = 24 animations, plus stand = 25 animations) and then blend between the current and desired animations.

 

 

 


Should I choose C++, C# or some other language for this project.

 

that would depend on the engine you use. if you build your own engine, you can use any language, as long as the resulting code runs fast enough.

 

 

 


a randomly generated sandbox open world game with realistic physics (using real mathematical formulas, tables and charts in real physics books and chemistry books) that has very little content at first and where players create the environment, and if people buy it

 

there are already many sandbox games with decent physics, and more than "very little" content, and modding capabilities. so your game wouldn't be very competitive, and thus would not likely sell well.

 

 

 


How much time do you believe or know I will need to achieve this if i begin learning now?

 

for a small triple AAA type title, figure at least 5 coders, 25 artists/level designers, a foley artist, a musician, 10 voice actors, and 3 to 5 years. that's once you have learned all those skills. foley and music might be one man-year each. voice acting might be one man-year total. so you have 30 coders and artists working for 5 years, and a musician, foley artist, and voice actors doing one man-year each. that adds up to 38 man-years, once you've learned the skills. [EDIT] did my math wrong: 30 coders and artists x 5 years + 3 man-years of audio work = 153 man-years, not 38.  forgot that x5 years part.

 

i'm currently working solo on a project smaller than what you describe, and i already have 10,500 man-hours in it over the last 2.5 years (yes - i have no life! <g>). and i have 26 years experience as a gamedev.

 

 

 


and believe i can really make such a game because I was told Minecraft was made by 1 person, and Mount&blade was made by 2.

 

as stated above, those games were STARTED by small teams. To determine the rough man-hours in a game, multiply the number of coders and artists by the number of years in development. it would take one person AT LEAST that long to make that game - once they had the skills. longer actually, as this doesn't include any audio work.

 

take some time and check out the game engines. see which one you like the best. then implement a camera you can move around an empty scene. then add an animated skinned mesh to the scene. then make it play a sound effect when you hit a key. right there you'll have the basics. if you can draw an animated skinned mesh, simple meshes are easy to draw by comparison. if you can play a sound effect, you can do audio and music. then start making content, levels, and using additional capabilities of the engine (particles, physics, etc).  pretty soon you'll get a feel for how hard it is to do stuff and how long it will take. then you can begin to set realistic goals for what is achievable on your own.




#5229048 Can a lone indie dev do an open world like this?

Posted by Norman Barrows on 14 May 2015 - 06:13 PM


As long as you consider the time it will take, sure, it is possible. Just remember that in 10 years, technology will have advanced a great deal.

 

another excellent point. hardware is a moving target. anything over about 5 years dev time and odds are you'll be porting to the next gen game engine when you're already most of the way through the project.  Diakatana comes to mind with regard to this. thats why i try to develop as much as possible with placeholder graphics, then do the graphics last. 






PARTNERS