Jump to content
  • entries
    39
  • comments
    0
  • views
    735

About this blog

Behind the scenes of "Oh Shoot!" 

Entries in this blog

Assembler

I used defines with IFCONST to optionally include code into the ROM.  I added a DEFINE_DEMO which results in reduced features and a different title screen in the output ROM.  If I comment out DEFINE_DEMO the output ROM is the full game.  This is very convenient for debugging and being able to easily enable and disable game features. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Define constants A ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Regions

I created PAL and SECAM builds of Oh Shoot for thos regions.   I couldn't change the number of lines per row to try to better fill the PAL screen so the result is the screen is a bit scrunched with a thick border on the bottom.  It plays well though.  Here you can see NTSC vs PAL:   Here are some SECAM screen shots:   I wonder how bad these would look on actual SECAM hardware and CRT... I guess I'll never know.   Here's the sources I used for t

Select Screen

One part of my game that folks don't seem to like too much or find confusing is the select screen.  I'll just go through the history of the Oh Shoot select screen.   On almost all of the original 2600 games in the select screen all you get is a number and you have to look this number up in the instruction manual's "game select matrix" to figure out what game settings correspond to the game select number.  This kinda sucks!  But it took very little rom space to implement.   Th

Polish

I wanted to highlight some refinements to polish the game up.  I had plenty of brainstorming sessions on how I could improve the game.   1.  Random initial weapon cooldown value at start of round for computer players. Without this the ships would be shooting perfectly in synch and would often die perfectly in synch... I didn't like that.   2.  Half width front scanner for moving human player. I mentioned this already, but worth mentioning again.  This makes it much

Piledriver

Piledriver in Design

Color

The 2600 has a large well organized color palette.   The colors are crystal clear on an emulator on my computer screen.   The problem is the colors may not look like you expect on a CRT TV.  Here's some bad examples:   The ghosting is so bad on some of these colors you can't even tell what you're looking at!  Here's some good color combos on my CRT (Sony Trinitron): There's still ghosting, but you can tell what you're looking at, a

Piledriver

Piledriver in Design

Exhibition Mode

I just love exhibition mode!  Not only was it extremely helpful for debugging the game, but it just looks cool.  It adds to the ambiance of a retro gaming room.  Sometimes I'm doing something on my computer and I just like to see the Oh Shootians out of the corner of my eye.  By the way exhibition mode is in the demo.    

Piledriver

Piledriver in Design

Cut Features

Let's look back on things that were cut or never implemented or abandoned for various reasons. -matching ships mode -blinking playfields -striped playfields and backgrounds -multiple ripple maps -complex controls of the Destroyer shots -variable range in helicopter shots -numerous screens including giant galactic toilet paper -kamikaze ship type -invisible ships unless firing -bomb drops when above enemy -Easter egg where human falls o

Sprite Positioning

Sprite positioning on the 2600 is a lot weirder than you'd expect.  For some reason my missiles were always off by a pixel.   I hacked in some missile offset code to compensate and make things look good.   The sprite positioning code in my book and other online sources all pretty much had the same issue.  Then I found this: https://bumbershootsoft.wordpress.com/2018/08/30/an-arbitrary-sprite-positioning-routine-for-the-atari-2600/   When I put in th

Debugging

I got frustrated debugging on 8bitworkshop.  With more complex bank switched code things would mess up and the program counter would just go to weird random places.  I switched to VS Code and Atari Dev Studio for this reason.   Despite the issue I had with the bad labels with bank switched code Stella is an amazing emulator and debugger!  You can step ahead by an instruction, a line, or a full screen.  You can even jump back in time, so if something weird happens you can rewind and not

Helpful Tools

Here's my primary tools for this project: Visual Studio/C#, 8bitworkshop, Visual Studio Code + Atari Dev Studio, Stella, MSPaint, PaintShop Pro 7, Winmerge   I'm curious what tools Atari programmers had to help them develop their games in the old days.  I had Visual Studio and C# which let me crunch out any helpful tools fast.  Here's the tools I made with a brief description.   6502Branching- help me generate assembly to handle <, >, <=, and >= logic.  I was

Loading Frame

I use one frame between matches to load up a screen, process it, initialize player and match settings, and initialize FX or AI variables.   I didn't want a frame of perceptible flicker during this so I had to make sure I had the correct screen colors set before I start the load screen and I draw the score and top barrier so those wont flicker.   I have a a debug option to change the background color after various loading steps so I could ensure I wasn't running out of time du

128 Bytes RAM

128 bytes is a crumb of RAM!   I made a RAM label visualizer to help me see what's going on.  The first blue section is the p0 data, the red section after that is p1 data.  The dark grey section is my screen in RAM.  The very dark section at the end is my function call stack.   I don't want to go off the deep end on what every bit is for.  But there's some interesting points.   The game has two basic modes - FX mode and AI mode.  I made the FX first (all the s

AI: Ranger

It was easy to design the original Ranger before there was any AI.  Things got complicated with the Ranger and MANUAL flight AI though.  The problem was the Ranger didn't know its enemy was out of firing range.  I had a big chunk of AI code that was on the chopping block.  This code was for an attack mode I thought I didn't need.  In this mode the attacker randomly picks one of 3 directions that will move the attacker towards the enemy.  In testing I found this mode annoying as it always lead to

AI: Missiles

A ship with missile dodge assistance has a top and bottom radar to detect missiles.  If an enemy missile is detected by the top radar the ship automatically moves down.  If a missile is detected by the bottom radar the ship will automatically move up.   Here you can see a missile dodge sequence.  Top radar detects a missile.  Ships avoids by dodging downwards.   With harder computer players their radars increase in size making them able to respond to missiles sooner.  T

AI: Optimization

Despite all the optimizations I already mentioned I needed MORE optimizations!   The AI ships don't need to perform a front scan every frame.  So I have two AI modes - "low power" and "high power" and the ships alternate between those every frame with only one ship in high power mode and the other in low power mode.  A ship must be in high power mode to perform the following tasks - a front scan, missile scan and missile dodge initiation, changing to a new state (attack vs meander).  A

AI: Avoidance

Let's talk about corridor escape implementation.  Here is a typical screen showing corridors in green.  Note that there are empty rows that are too small vertically for your ship to safely fit in and hence are not considered corridors and are not green in this image.   It is actually somewhat complicated to determine if a row is in fact part of a corridor because of the requirement that a corridor be at least two rows tall.  So I do the slower more time consuming corridor assessm

AI: Scanning

I explained how the AI interacted with the playfield.  To do this I need to scan rectangular regions of playfield for obstacles.  That's what I want to discuss today.   Lets simplify the problem to only determining if a given tile in a playfield row is empty or solid.  PF0 is not used so any tile in there is empty.  My first "solution" was something like this: 1.  Convert ship horizontal position to a tile column (There are 0-39 playfield tiles or playfield columns). 2.  if (

AI: Overview

All throughout this project I thought it would be cool to have an AI opponent.  I figured the game would be played 100x more if it contained a good 1 player mode.  I also thought that would be impossible to implement unless I only had computer opponents in an empty arena.  Today I want to talk about the long path to Oh Shoot AI! The game has 2 basic modes that affect AI - MANUAL flight (fly in any direction) and AUTO flight (horizontal speed is constant).  I figured it would be much easier

Missiles

I want to discuss how the ships changed over time.  They actually have names by the way.  This is how they appeared originally.   I had some interesting ideas for the Destroyer.  I wanted the shot trajectories to be different based on your input.  If you press up or down while firing your shot does a wide zig-zaggy path and doesn't cross the midpoint of the ship's position from the time it fired (first two paths below).  If you weren't pressing up or down the shot would do a half

Piledriver

Piledriver in Design

Rumble Effect

Let's get ready to rumble!     Rumble is similar to ripple but it's only applied to the top and bottom boundary rows.  The rumble data is a sin table with values that are dampened further into the table.   Rumble sort of breaks AI... but in a good way.  With rumble the playfield is drawn out of place vertically from where the AI playfield detection thinks it should be causing some surprise deaths.

Ripple Effect

One day I was brainstorming about how I could spice up the kernel a bit.  I explored striped foregrounds and backgrounds.  Even animated backgrounds that looked like waterfalls or lavafalls.  They looked kinda cool but somewhat distracting and I considered it a lower priority feature (which obviously didn't make it in in the end).  While I was poking around in the kernel code I looked at the code that always sets the playfield row thickness/countdown value to 4 giving each playfield row a unifor

Scrolling Effects 2

How do I get the chunk index from a screen row?   For all the scrolling functions I need to retrieve the playfield bytes of a specific row.  The screens are compressed on the ROM and are stored as indexes to chunks.  So to retrieve a row's playfield data I need to know which chunk it's in.  The problem I needed to solve is given a row number for a screen what chunk is the row in?   This may sound like a trivial problem, but I need to do it very fast since I need this during g

Scrolling Effects 1

Let's talk about the scrolling effects.   So I had a huge amount of screens for my game, but I didn't want to stop there.  I wanted some sort of animation or movement to my screens.  It would have been nice if I could store multiple frames of animation for the various screens, but it wasn't possible.  I came up with the idea of scrolling the screens in and out both horizontally and vertically!  Most scrolling on Atari games is just cycling the playfield bits in RAM of each row being sc

Piledriver

Piledriver in Design

1024 Screens!

Check it out!  1024 screens!  When I only had 64 screens I added a gimmick to flip screens upside down at random to give the illusion of extra content.  So all these screens in the gif also have flipped counterparts.   My initial barebones game only had run length encoding.  I could only make 16 screens with limited detail.   Then with a chunk palette I could make 64 screens (still in a 4KB rom).   And then with 32KB I had a lot more freedom.

Piledriver

Piledriver in Art

×
×
  • Create New...