Here comes the "how to do..." list of the most common things useful to know if you wanna make games. They are lots of silly things, but they make the differece between a good game and a good-idea-but-badly-implemented game. How to ... ------------------------------------------------------------------------------ * ... choose the "perfect" animation frequency/frame rate Humans have a "feedback" (the time it takes to react) frequency of about 10Hz (nothing strange, it is close to the frequency of brain waves). But the visual system is a lot complex, so even if the "frame rate" of a common eye is about 10..15 Hz the visual system can perceive "flashes" up to 50Hz (you don't see the "flash" but you perceive the image is not rock solid) (that's why televisions use long persistance phosphors to "smooth" the electronic beam flashing the dots). Do you feel worried? Worry not! This has nothing to do with us. If the screen image is "steady" (read: the monitor has 60Hz refresh frequency, better if 72hz or more) your eye performs interpolarion of frames with about a 10hz frequency (usually 12Hz) and gets a "steady" image. Just going at 12 FPS (Frames Per Second) produces smoothly ANIMATED sequences (by the way 12 FPS was the frame rate of animations in Disney's cartoons). Notice i said ANIMATED SEQUENCES, NOT MOTION. At 12 FPS a "static" animation (i.e a face changing from angry to smiling) is good enough to not be "jumpy" (but looks a little "slow"). But if it is a sprite in motion (i.e. a walking man) you need a higher frame rate. Why? Because our motion detection system works at about 10..12Hz, you need twice the "feedback" frequency to fool it. So "change sprite image" 12 times in a second, but move 'em at least 24 times in a second. Usually on arcade games 12 FPS are good enough (the feedback time does not need to be realistic). BUT for flight simulators or other things like that, 24 FPS are the minimum to get realistic animation and 50 FPS are the minimum for "total feedback" (when you "feel" that eye and hand motion are coordinated) So always include some options to speed up animation with a little and/or a big loss of detail. Well, NOW you know the lower "good animation" limits: "Image update" can go as low as 12 FPS and look very realistic depending on what you do, you can go even lower (i.e. combining motion with image changes) and still look realistic. "Image motion" must be at least 20..24 FPS to look realistic on simulators and 50 FPS to give "perfect" feedback to commands. NOW COMES THE HIGHER LIMITS: Moving things too fast makes just "flashes and streakes", use a timer to get always the same motion speed indipendently of the frame rate ( notice the 386TIMER module , you don't need a timer interrupt for everything just calculate the time elapsed and then calculate the "motion to show" on next frame). ------------------------------------------------------------------------------- * ... perform smooth scrolling with no hardware support Quite easy, if you want to have a screen (_DispX,_DispY) wide and want to perform animations on a virtual screen (_VirtX,_VirtY) wide simply set a screen buffer (_ScrX,_ScrY) wide where _ScrX = _DispX + _WidestSpriteX and _ScrY = _DispY + _TallestSpriteY +1 Then set the "display start" (_VDispX,_VDispY) at (_WidestSpriteX,_TallestStriteY) to get "out of screen" borders using the "row wrap" to simulate two lateral borders even if there is only one. Then keep a pair of variables to memorize what is the actual position corrispondent to screen buffer coordinates (0,0). At every frame regenerate the "visible image" on the screen buffer, then blit it to the actual screen. This was the hard part, now you have to decide when to scroll and how much. Usually you want to scroll to follow the "player's character" on screen but you have to remember to sincronize scrolling with animation or you'll get "jumpy" scroll, this depends on how much action there is in the game and where the plyer's eye look at. Another thing to keep in mind how to avoid those strange "streaks" you see if a sprite moves too fast, they are the result of interpolation between the current image and the previous, to reduce this effect use sprites with a "dark" border (better if black), or don't scroll/move more than 1..2 pixels at a time if you cannot sinchronize "scrolling steps" with the frame rate. ------------------------------------------------------------------------------ * ... play multiple sounds with a single DAC Usually, with a DMA channel and an IRQ line you can tell the sound board "take this chunk of memory and send it to the DAC" without having to send it one byte at a time. [ you program a DMA transfert, then when the transfert ends, the sound board raises and IRQ signal, so if after the first "feed" you place the "dma restart for next block of data" on the ISR (Interrupt Service Routine) serving that IRQ, you get continous sound with minimal cpu overhead] But if you want MULTIPLE VOICES and you have a single DAC you have to perform SOFTWARE SOUND MIXING, you take the various sound samples you want to play and add them together (to mix the signals) and then send the result to the sound output DAC. The easiest approach is disabling DMA, chaining to a timer interrupt running at the playback frequency you want and every time the interrupt "ticks" you add the current values to send and then write the result to the DAC. This method uses the cpu a lot (and the more your cpu spends time executing irq routines, the less time it will work on your main program) going beyound a 8Khz playback frequency can cause serious processing problems. Forget to make it work under Windows (too much irq response overhead) and forget to have CD frequency playback (Sheesh! An ISR for timer interrupts ticking at 44Khz eats nearly all cpu time on a plain 486 !!!). There is a better method, you still use a DMA channel and an IRQ line to send the data to the DAC, but every time the current sound data has been sent, you call a "software mixing" routine to mix a block of N samples adding together the next N samples of the various voices you want to play. This way you reduce a lot the interrupt overhead (i.e. if with a "timer interrupt mixing" at 8Khz you had 8000 irqs in a second using "block mixing" with 100 samples per block you only have 80 irqs in a second). Of course, this has problems too, you have to "compose the block of data" BEFORE the IRQ requests another block (or you'll get "pauses") That is, the block you compose "now" will have to be sent AFTER the current block is played. The mixing process works at a frequency that depends on how many samples you put in a block of sound data and depends on what is the playback frequency. For example: With a playback frequency of 8000 Hertz and mixing sound in blocks of 100 samples each the mixing routines gets called 80 times in a second (80 Hertz) [ mix_frequency = playback_frequency/block_size_in_samples ] The less interrupts happens the better so, maybe you want a lower "mixing frequency", but you have to remember that you cannot go lower than 30Hz. The reason for this is that animation (not motion) happens at 12 FPS and you "play late the sound" (the "time fidelity" of sounds is half the mixing frequency). If you try to use lower mixing frequencies you will get "decoupled" sound and animation. On the other side, sending big chunks of mixed sound data takes processing power. IF you process too big chunks YOU MAY GET "stop-go animations". IF you process too little chunks with an high playback frequency YOU MAY GET lots of cpu overhead caused by too many interrupts. So include an option to change the playback frequency and/or the number of voices you mix on the flight. ------------------------------------------------------------------------------- * ... experience the effect of a Non-lethal Disabling Technology (URK!!!!) Ever heard of the Bucha effect? When you are exposed to strong flashing lights and they flash with a frequency close to that of brain waves (brain waves are usually in the 10..20 Hz range) you get vertigo and feel quite unhealty (you feel like you are gonna puke). So avoid to put "big flashing light" effects "blinking" at a fixed frequency. A classic for this effect is Doom 1 level 2 (the nuclear plant) one of the secret zones simulates broken flourescent lights perfectly and gives a good example of nearly-Bucha effect on videogames. Another is Jazz Jackrabbits's Tubelectric level. The same thing applies to sound, if you use "block mixing" remember to always put in at least a soft "background music", the low frequency hiss caused by the constant frequency of mixing you get on some sound boards is disturbing to say the least. (Yeah! block mixing can add noise to the actual sound, if the gap between the time a block finishes and the next starts playing is too wide) (the "silence" between blocks sometimes is real, but in some boards is a "fall to zero" that causes noise). ----------------------------------------------------------------------------- * ... avoid sonic booms Remember to always include volume settings into the game because not everyone has speakers with sound volume control. Months ago, when i had two high-wattage stereo speakers connected to the soundcard, i uploaded a game called Riptide. It had no sound volume controls after five minutes i erased it, it was too darned loud. Now i have a pair of little speakers with volume control [ 4watt speakers are good enough and you dont' have to steal the speakers from your brother's stereo rack :) ] Another thing to remember is to "fade sounds" ("fade in" when it starts and "fade out" when it ends)(do it preprocessing the sound data) because "brutal" changes of DAC output levels causes "dings!" "tings!" and other noises. Guess what happens if you mix together 4 or more sounds starting/ending at the same time. Thats' all.... Well, i think these are the basic advices you may need to avoid problems and reduce your "game programming" learning curve. Remember these are generic advices, with good programming skills you can "cut corners" without losing too much playability, i'm not a big time game programmer, i'm just an electronic engineering student with a strong background in assembler coding.