Jump to content

The Southsider

  • entries
    81
  • comments
    767
  • views
    138,549

Multi-tasking


Guest

626 views

I am not very good at multitasking. I find it difficult to switch from one project to another, and so I tend to give a single project my full attention for some time while ignoring the rest. My problem is that I have a lot of projects, including redecorating my house, writing a book, developing several websites, and learning to drive. I guess that my girlfriend should also be included in that list! As a result, my Atari projects tend to move along at a relatively slow pace, with occasional spurts when they have my full attention. post-4740-1101348357_thumb.jpgBy an unhappy coincidence, it turns out that the Atari 2600 is not very good at multitasking either. There are times when it becomes painfully clear how little time there is between screen updates to actually get any work done. For my PoP game, at least the following tasks will have to be done during this time period:

  1. Check which directions the player can move in.
  2. Check if the player has reached the screen edge.
  3. Check if the player is falling and/or dead.
  4. Check if any floor switches have been pressed.
  5. Check if any loose tiles have been stepped on.
  6. Read the joystick & console switches.
  7. Move the player.
  8. Update the player sprite animations.
  9. Animate the visible objects, e.g. flickering torches, bubbling potions, loose tiles.
  10. Open and close any moving doors.
  11. Move and animate any visible guards (enemy AI).

The PoP game currently does steps 1, 2, 6 and 7 and things are starting to get tight. I have optimised the collision detection routine that I posted last time and it still only leaves 7 scanlines free in the overscan region in the worst case. Fortunately it is not going to be necessary to perform all of these tasks on every frame, so I am still confident that the game will be possible. However, it might eventually be necessary to perform time-slicing, as described by Andrew Davie in his Boulderdash project.The task that I am currently wrestling with is how to implement the floor switches. It turns out to be a bit more complex than I had anticipated as the switches can open doors which are not visible on-screen. I think I now have a reasonable way to do this, but I haven't implemented it yet. The basic idea is as follows:

  • All of the switches and doors will be given a unique index, and there will be a maximum of 15 doors and switches on each level. The status of these doors and switches will be stored in a table in Supercharger RAM. If this is not enough, then to doors and switches could be separated into separate tables.
  • There are around 28 positions on a screen where a door or switch can appear. To avoid the need to store an ID for every possible position, I will restrict each screen column to a single door or switch. The alternative would be to restrict each row, but in examining the original game levels it appears that doors and switches often appear on the same row, but only rarely in the same column. The levels will have to be altered slightly, but I don't think this will be a big problem.
  • There are 4 columns on a screen (for the 4 PF registers), so this means that we need 4 IDs per screen to represent the doors and switches. Since each ID is in the range 0->15, each screen will require only 2 bytes extra storage.
  • When the player steps on or off a switch, the status table will be updated. It should be easy to determine which entry needs to be updated as the column can be trivially calculated from the players X position.
  • The status table will be checked regularly and updated, e.g. a closing door will be closed by 1 step per check.
  • The screen data needs to be updated to reflect the status of the doors and switches, so this will be done by directly modifying the level data. This is the only step which I am concerned about. A single door will usually appear on 2 screens, so we need to search through the level data to find these screens, then find the correct position, and then perform an update. Fortunately the doors move slowly, so this can probably be split between frames.

I hope this makes some sense? If anyone can think of a better way, then I will be happy to hear it. This appears to be the point at which the game will require the extra Supercharger RAM, and could not be done simply by using a large ROM. ChrisP.S. I appreciate that everyone has different music tastes. However, I think that the track "Twisted Logic" by Coldplay (X&Y Album) makes an excellent Atari programming anthem!

5 Comments


Recommended Comments

Hi there!

 

Could you possibly post your current collission detection code? You sound like it is your most time consuming part so far :)

 

Greetings,

Manuel

Link to comment
How big is PoP?  Are you planning to split it across multiple loads?  If you run into space constraints, you definitely should.

 

There are 13 maps in the original PC version. I am definitely planning to multi-load these levels as there will not be enough space in 6K for all of the screens.

 

Could you possibly post your current collission detection code? You sound like it is your most time consuming part so far :)

 

I have attached the latest code to the blog entry. The bulk of the collision detection is done by the MapCords subroutine which takes a row number and a Y coordinate and returns the screen data at this position. The screen is split into 7 rows which are 4 floor rows and 3 wall rows interleaved. If you can find a way to reduce the complexity of this code then I will be very grateful!

 

Chris

Link to comment

Hi there!

 

Well, my first suggestion would be adding two mapping tables for

 

x -> row

y -> col

(maybe even x -> shift)

 

For y that seems to require 90 bytes and for x 116 bytes of ROM.

 

For less than a page, you not only get zillions of cycles, but also render your code much more predictable, because instead of vague worst case situations like:

 

; Calculate Screen Row
; Entry (A = Y Coordinate) Exit (Y = Screen Row 0-6)
ScreenRow
ldy #6  ; [0] + 2
ScreenRowLoop	
cmp RowTable,Y	; [2] + 4
bcs EndScreenRowLoop; [6] + 2/3
dey  ; [8] + 2
bpl ScreenRowLoop; [10] + 2/3
EndScreenRowLoop	; WORST CASE = 7 Iterations (77 Cycles)
rts

 

(which, judging by the comment can eat up to a whole scanline :sad:)

 

You'd have a constant 8 cycle fetch like

 

TAY
LDA table,Y
TAY

:x

 

Greetings,

Manuel

Link to comment
Well, my first suggestion would be adding two mapping tables for

x -> row

y -> col

(maybe even x -> shift)

For y that seems to require 90 bytes and for x 116 bytes of ROM.

 

Thanks - that makes a lot of sense - I am always missing these memory/cycles tradeoffs!

 

Chris

Link to comment
Guest
Add a comment...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...