Jump to content

Cybearg

Recommended Posts

Prelude:

 

Hello to all! I've recently had an epiphany of how wonderful game design can be, so I'm doing a little exercise to try to build my programming and artistic skills. Specifically, I'm starting with the Atari 2600 and then trying to work my way up with some other older consoles before settling again on modern engines. It seems like a good, fun exercise in rapid game development, since Atari 2600 games are relatively small. Keep in mind that I'm a novice programmer and this is meant to be a learning exercise to get me used to "thinking like a programmer."

 

Problems:

 

I sat down last night to crank out a simplified version of a game that I recently designed for GameJam and it's been going fairly well so far, thanks to visual bB and the manual that came with bataribasic. However, there are a number of problems and questions I have, so I hope that you good folks with all the knowledge can help me out:

 

1. First of all, I know that there are serious limitations on what can be done, but why are they THIS limiting? Maximum of two sprites? Any more requires significant slow-down and flicker as you teleport them from place to place? What about, for instance,

(which is very similar to the game I'm trying to make)? You've got a ball that does not share the same color as the playfield (and, for that matter, a playfield that is not one solid color) and a series of "blocks" that I assume are sprites, yet there is no noticeable flicker. Or, for another example, Pitfall, which not only seems to have multiple different sprites on screen, but also sprites with multiple colors (the man) and a playfield consisting of much greater pixel quantity/density than is available to me in Visual bB. What gives?

 

2. It seems like most loops and functions don't really work. For instance, I wrote this:

rem randomize color values
10 for temp = 0 to 15 step 1
temptwo=colorfun(f)
goto storecolors
next

function colorfun
if rand < 81 then return 1
if rand > 80 && rand < 161 then return 2
if rand > 160 && rand < 251 then return 3
if rand > 251 then return 4
rem get and assign numbers for variables - red, yellow, blue, white
end


storecolors
if temp = 0 then one = temptwo
if temp = 1 then two = temptwo
if temp = 2 then three = temptwo
if temp = 3 then four = temptwo
if temp = 4 then five = temptwo
if temp = 5 then six = temptwo
if temp = 6 then seven = temptwo
if temp = 7 then eight = temptwo
if temp = 8 then nine = temptwo
if temp = 9 then ten = temptwo
if temp = 10 then eleven = temptwo
if temp = 11 then twelve = temptwo
if temp = 12 then thirteen = temptwo
if temp = 13 then fourteen = temptwo
if temp = 14 then fifteen = temptwo
if temp = 15 then sixteen = temptwo
return

The intention is for-loop to count from 0 to 15, each time calling the function colorfun[ction] to generate one of four numbers (which will be used to determine the colors of things later on) and saving the value in a temporary variable, then sending it into an appropriate holding variable for later. The problem is, when I don't get a ROM out of space error on this (even though I have ~ 1.2K of ROM left), the screen is simply black, like the program is having trouble crunching the numbers in this fairly simple set-up. It's like batariBASIC can't handle nested functions/loops. Is there some way to get this kind of stuff working? The required workarounds--that is, using goto commands, is very wasteful of preciously scarce programming space.

 

3. Is there some way to name variables in ways that I can access easily through loops? Taking the above example, I have sixteen variables that hold a number from 1 to 4 denoting the color to be assigned to sixteen pfpixels (I would use sprites, but in my experience so far, the processing requirements to have sixteen sprites on screen at once makes the game such a flickering mess, it's unplayable), with an additional two variables used as bit operations to determine whether a given block should be "on" or "off" (that is, whether it's alive or has been destroyed). I would LOVE to be able to somehow count through the variables with a loop without specifying specifically, one by one, what to do, as if it were an array along the lines of:

array[temp] = temptwo

That would be so much simpler and more efficient. On a similar note, I wish I could do:

for temp = 0 to 7 step 1
bit_op{temp} = 1
next

... Or something along those lines. That is, use variables to denote other variable names so I can quickly and efficiently count through them and determine/set a number of variables without wasting the space with dozens of if-then statements for every possible iteration.

 

This is especially important for later on, since, after I've established which pfpixels get which colors and whether they are on or off, I'll need to program in collision (or some semblance thereof) so that getting hit by a ball (or missile) kills a pfpixel (a la Breakout). That would be difficult enough, BUT it gets harder:

 

Basic Game Explanation:

 

The pfpixels need to rotate their values, since the primary gameplay mechanic is the player moving the blocks to meet the ball, rather than the other way around. I'll need for loops to store the current and next color value of the blocks, swap the new value in while preserving the old, check to see whether that block is on or off, affect the collision appropriately, etc.

 

Maybe that explanation is confusing, so I'll try to represent it visually. The one-sixteen variables hold a color value from 1 to 4, which will possibly end up being 1 to 7, if I have my way. This is important, because only balls of a certain color can cake out blocks of a certain color, so there will need to be if-then statements comparing the stored value of the color of the ball with the stored value of the color of the brick to see if they are a match or not, then flip the appropriate bit operator. This can be represented with sixteen bit operations (between two variables) and sixteen actual variables (though it could possibly be done with bit operations, though it would be complicated):

 

1 1 0 1 1 1 1 1 1 0 1 0 1 1 1 1 0 - Bit Operation (on/off = alive/dead)

1 2 3 2 4 3 1 3 4 1 2 3 4 1 3 4 3 - Variables (number = color)

---------------------------------------> - Direction that the values must be shifted for each joystick right

<--------------------------------------- - Direction that the values must be shifted for each joystick left

 

Meanwhile, balls of three colors are being created on a loop, rather than randomly:


pulse = pulse +1
if pulse = 15 then color = color + 1:pulse = 0:beat = 0
if color = 3 then color = 0
if color = 0 then COLUPF=64
if color = 1 then COLUPF=28
if color = 2 then COLUPF=146

 

Which, when joystick trigger is hit, creates a ball with a color value based on the color variable and stores it for that ball so that it doesn't change.

 

When collision happens between a pfpixel and a ball (perhaps manually determined by a range of values that denote the pfpixel's location?), the ball's stored color value is checked in an if-then statement against the values in the brick being collided with:

 

if ballcolor = [variable containing block color value] then [set block bit operation to 0 to "kill" it and give the player points]
if [variable containing block color value] = 4 then [set block bit operation to 0 to "kill" it and give the player points, since these blocks can be killed regardless of the color of the ball hitting them]
else life = life - 1: goto [somewhere]

 

If need be, I could try using six variables as bit operations (instead of sixteen) to denote red, yellow, and blue colors and a function to generate the color number when needed , for instance:

 

for count = 0 to 7 step 1
if red{count} = 1 && yellow{count} = 1 && blue{count} = 1 then color = 4
if red{count} = 1 && yellow{count} = 0 && blue{count} = 0 then color = 1
if red{count} = 0 && yellow{count} = 1 && blue{count} = 0 then color = 2
if red{count} = 0 && yellow{count} = 0 && blue{count} = 1 then color = 3

Though I'd need two versions of it, since there are two bit operation groups at play, since there are sixteen blocks, so I'd have to run it again for the second half.

 

This would be nice because it's scaleable if I want to expand the number of possible colors:

 

if red{count} = 1 && yellow{count} = 1 && blue{count} = 0 then color = 5
if red{count} = 0 && yellow{count} = 1 && blue{count} = 1 then color = 6
if red{count} = 1 && yellow{count} = 0 && blue{count} = 1 then color = 7

 

As is probably apparent, I haven't gotten to these latter parts yet due to the difficulties I'm having getting loops and functions to work correctly.

 

So, after all that, if anyone can offer me some advice as to what's going wrong or how I can make my dreams come true in an efficient way, it would be very much appreciated!

 

TL;DR: Help me!

Link to comment
Share on other sites

I like your game idea. Sounds interesting! 8)

 

All I can offer (as I have been learning myself) is that you have to "think backwards" when it comes to the Atari 2600.

 

What I mean is, as great as it would be to take a modern game idea and scale it down to the limitations of the 2600, sometimes you have to start very basic and get a few objects moving on the screen first and then add more and more of your game until you run out of ROM space.

 

Keep in mind a few things about the 2600. It is one of the more difficult platforms to program for.. and you may find it easier to start with a more forgiving system with more sprites and memory available. Remember the 2600 only gives you 128 bytes of RAM and redraws the entire screen 60 times per second. You have to build the program kernel from scratch for each new game you code.

 

Also keep in mind that batari Basic makes the process much easier( and gives novice programmers like myself a chance to actually get simple games working :) ), but it also has the limitations of a "canned" kernel- thus, the hardest part of the game is already programmed but it only allows a certain set of parameters for your game. That is where adding assembly routines comes in to workaround the limitations (or you can change the batari Basic code itself, if you know what you are doing, to add unique features).

 

To the best of my knowledge, batari Basic's standard kernel only allows one color per width of the screen(going from top to bottom). The playfield (left to right) is 20 pixels wide, then repeats/is reflected for 20 more pixels. So you will have 40 pixels across that make one line of the same color. Depending on vertical resolution, you can have a different color each line from top to bottom and that's it:

 

playfield:

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

and so forth..

Others here may know some of the programming tricks you can use to change the color mid-scanline but you have to have enough cycles to do so.

 

The multipsrite kernel only allows one color for the entire playfield(reflected).

 

The above may sound very limited but there are still many fun games that can, and have been, designed using the above-- and a few that expanded on the above limitations by adding assembly routines and bankswitching, etc.

 

To have complete control of your game mechanics and design, you may have to program it from scratch in assembly. However, another option may be to try and use the standard kernel with the SARA chip, which gives you an extra set of variables and another 128 bytes of RAM to work with. Also, the latest version of batari Basic is the DPC+ kernel that gives you multicolored sprites and more options.

 

Not sure if that helps, but wanted to suggest that your game idea is not impossible on the 2600, but could be very ambitious! Others will probably have better suggestions to give than I have. Good luck! 8)

  • Like 1
Link to comment
Share on other sites

Thanks much for the response!

 

I don't know much about the kernels and such. From what I've just read, they seem to take an awful lot of space. Not sure if that's worth it for bitmaps and the like.

 

My biggest problem is getting loops, functions, and variables to work correctly, so that's my primary concern. For instance, I know that bit operations work almost like arrays, with a{0} being a binary variable, a{1} being another, on up to a{7}. However, can I somehow reference them using a variable as an index, such as the following:

 

for temp = 0 to 7
bitop{temp} = 1
next

 

Which, in theory, should count up through the 8 bits and set each of them to 1, but it returns an error instead.

 

Secondary is any better way of rendering a series of boxes on-screen with minimal flicker. I know that there may be some answer in this, though I admit that I don't understand the concept there.

 

The idea I have is fairly simple, I think. The complication is in making those updates without a flickering mess.

Link to comment
Share on other sites

Memory is addressable

 

dim one = a
dim two = b
dim three = c
dim four = d
dim five = e
dim six = f
dim seven = h
dim eight = i
dim nine = j
dim ten = k
dim eleven = l
dim twelve = m
dim thirteen = n
dim fourteen = o
dim fifteen = p
dim sixteen = q

rem random ranges 0-255
rem scale rand to a range of 0-3
rem by dividing by 64
rem division by 2, 4 or 8
rem is optimized to shifts

rem the variables are in order in memory

for temp = 0 to 15
one[temp] = rand / 8 / 8 + 1
next

 

bit ops can't use variables for indexing

 

I think you'll have to do something like this

 

rem set a bit

var = var | setbits[index]

rem clear a bit

var = var & clearbits[index]

data setbits
%00000001, %00000010, %00000100, %00001000
%00010000, %00100000, %01000000, %10000000
end

data clearbits
%11111110, %11111101, %11111011, %11110111
%11101111, %11011111, %10111111, %01111111
end

 

That could be built into a subroutine or a macro

 

And it should be possible to def a substitution

for eg the callmacro statement so you could just

invoke it like "setb var index" but I can seldom get

that to work.

 

Also the kernel already contains the setbits and

clearbits data but I think where it is depends on

the kernel options.

 

edit goofed the random color (now fixed)

I guess there's no easy way to build the bit ops

into a macro

Edited by bogax
Link to comment
Share on other sites

I very much appreciate the help on the variables and such. Thanks!

 

Now, there's one major remaining hurdle: I need either multiple colored sprites or multiple colored pfpixels or something else on-screen at once. I've tried going through loops like so:

 


dim temp = a


for temp1 = 0 to 15

temp2 = rand

if temp2 < 41 then a[temp1] = 64

if temp2 > 40 then a[temp1] = 28

if temp2 > 80 then a[temp1] = 148

if temp2 > 120 then a[temp1] = 46

if temp2 > 160 then a[temp1] = 214

if temp2 > 200 then a[temp1] = 100

if temp2 > 240 then a[temp1] = 14

if temp2 > 247 then a[temp1] = 0

next

rem didn't use a for-loop because it just wouldn't work right

100 temp = 0

125 if temp < 16 goto 150 else goto 175

rem starting at the top, going clockwise, define each pfpixel

150 if temp = 0 then pfclear: pfpixel 16 0: COLUPF = a[temp]: drawscreen

if temp = 1 then pfclear: pfpixel 20 0: COLUPF = a[temp]: drawscreen


if temp = 2 then pfclear: pfpixel 24 1: COLUPF = a[temp]: drawscreen

if temp = 3 then pfclear: pfpixel 27 3: COLUPF = a[temp]: drawscreen

if temp = 4 then pfclear: pfpixel 28 5: COLUPF = a[temp]: drawscreen

if temp = 5 then pfclear: pfpixel 27 7: COLUPF = a[temp]: drawscreen

if temp = 6 then pfclear: pfpixel 24 9: COLUPF = a[temp]: drawscreen

if temp = 7 then pfclear: pfpixel 20 10: COLUPF = a[temp]: drawscreen

if temp = 8 then pfclear: pfpixel 16 10: COLUPF = a[temp]: drawscreen

if temp = 9 then pfclear: pfpixel 12 10: COLUPF = a[temp]: drawscreen

if temp = 10 then pfclear: pfpixel 8 9: COLUPF = a[temp]: drawscreen

if temp = 11 then pfclear: pfpixel 5 7: COLUPF = a[temp]: drawscreen

if temp = 12 then pfclear: pfpixel 4 5: COLUPF = a[temp]: drawscreen

if temp = 13 then pfclear: pfpixel 5 3: COLUPF = a[temp]: drawscreen

if temp = 14 then pfclear: pfpixel 8 1: COLUPF = a[temp]: drawscreen

if temp = 15 then pfclear: pfpixel 12 0: COLUPF = a[temp]: drawscreen

temp = temp + 1

goto 125

175

 

The problem is that, with the pfpixels arranged in a circle on the playfield, it just creates a very noticeable loop of the colors spinning around, since it's not fast enough to draw them without being noticed.

 

Is there any way to have multiple (in this case, 16) objects of different colors on-screen at once without it being a flickering mess?

Link to comment
Share on other sites

I'm no expert

 

I'm not really sure what you're trying to do

and it may not be possible to do it fast enough

in bB. It may not be possible in ASM.

 

But I'm guessing that its absolutely impossible

the way you're doing it.

 

I think drawscreen waits for the next time the

screen needs to be drawn (60 times a second)

and draws it. Since you clear the playfield then

set one pixel and call drawscreen you're only going

to get one (playfield) pixel each time the playfield

is drawn and since you immediately do it again,

it will only last a 1/60 second (except for the last

pixel).

 

You never say what exactly the problem is you are

having with for-next loops. For-next loops have to be

short. However you can jump out (goto) and come back

(or you could gosub, takes longer).

If that's a problem you're having and since you

probably ought to replace those long strings of

if statements with on..goto statements you could jump

out and back without it costing much (since you'd be

jumping any way).

 

But there's nothing magic about for-next loops.

It may even be possible to do a faster loop with an if

statement (if you're careful how you structure it, but

I'm not sure about that, and a for-next loop is probably

faster generally).

 

As I said I'm no expert, but I think the closest you can

get to what (I think) you want in bB is one color per line.

Setting pixels on the fly won't get you more colors with out

the flicker so you should probably give up doing the individual

pixels on the fly and just change the colors.

 

However if you're only doing two colors per line, perhaps

you could alternate colors every other drawscreen without

the flicker being too bad. It might be tricky getting it

fast enough. Since your pfpixels are fixed you might

do a playfield statement, change the colors as fast as

possible (and drawscreen) then do a different playfield

statement etc.

 

if you:

 

dim temp = a

 

then temp, a, and a[0] (and temp[0]) are all ways

of refering to the same location.

 

You randomize a (a[temp1] while temp1 = 0) in the

for loop then set it to 0 (temp = 0)

 

To speed things up you could use on..goto statements, compute

instead of select (as in scaling rand), use look up tables

where appropriate (which may not be faster in and of itself

but could allow you to use faster code)

 

I don't quite get your randomization of the colors

this time.

They're not equally spaced nor is the spacing a power

of two, so this is not the same as yours.

 

for temp = 0 to 15

temp2 = rand / 4 / 8
a[temp1] = color_tbl[temp2]

next

data color_tbl
64, 128, 148, 46, 214, 100, 14, 0
end

 

It may be possible to speed things up by manipulating

things directly from bB instead of calling the routines

to do it but that would require digging into the kernel

and figuring out what to manipulate.

 

None of that code is tested but it compiles

Edited by bogax
Link to comment
Share on other sites

However if you're only doing two colors per line, perhaps

you could alternate colors every other drawscreen without

the flicker being too bad. It might be tricky getting it

fast enough. Since your pfpixels are fixed you might

do a playfield statement, change the colors as fast as

possible (and drawscreen) then do a different playfield

statement etc.

 

I tried it.

It looks like crap, in stella at least.

 set kernel_options pfcolors


LOOP
 pfcolors:
 $90
 $90
 $90
 $90
 $90
 $40
 $40
 $40
 $40
 $40
 $40
 $40
end

playfield:
...X............X........X.....
...X............X........X.....
...X............X........X.....
...X............X........X.....
...X............X........X.....
...X............X........X.....
...X............X........X.....
...X............X........X.....
...X............X........X.....
...X............X........X.....
...X............X........X.....
end 

drawscreen

 pfcolors:
 $40
 $40
 $40
 $40
 $40
 $90
 $90
 $90
 $90
 $90
 $90
 $90
end

playfield:
....X............X........X....
....X............X........X....
....X............X........X....
....X............X........X....
....X............X........X....
....X............X........X....
....X............X........X....
....X............X........X....
....X............X........X....
....X............X........X....
....X............X........X....
end 

drawscreen

goto LOOP

Link to comment
Share on other sites

Well, I was kind of hesitant to post the full code of what I was working on, but this has so many problems, unless folks have some novel fixes that I wouldn't have considered, it won't be going much further, anyway.

 

[redacted]

 

Sorry for the mess in the code.

 

You can see the basics in place. There are multiple colored squares that are rotated by left/right joystick movements. In the center is a pulsing heart sprite that serves as a life bar as well as an indicator for "ball" color. When the trigger is pressed, a ball of the same color as the heart at the moment of the trigger is created and sent off in a random direction. The object of the game would be to match the color of the ball to the color of the block it hits, scoring points. The wrong ball to the wrong block loses a life.

 

There are lots of things wrong with the build at the moment. The most glaring is the awful flickering. Second, I can't seem to work out how to get the ball to shoot out in one of 8 set directions at random (every 45 degrees) without being too fast to react to. Third, I have no idea how to perform by-box collision that will allow the hit box's color to be compared to that of the ball to determine whether the hit is good or not. There's also a weird glitch in the first and last box values (the very top and the one just to the left of the top), causing those two to always share the same color for some reason.

 

And this is just a very simplified version of the game I intended to do. Ideally, the boxes would rotate fluidly, not just swap between a number of pre-determined spots and there would be more possible colors/effects on the boxes, but alas. I'm rather exhausted with the attempt unless someone can suggest novel ways of dealing with the aforementioned problems that I just didn't think of.

Link to comment
Share on other sites

I haven't looked at your game code yet.

 

Just to be clear, I'm not saying it's impossible.

I'm saying it's not possible the way you're trying to do

it because the flicker is built in. There's no way to

go fast enough if you have to wait on drawscreen.

And you have to wait on drawscreen to get a box on a

particular line drawn before you change the color for

a different box on the same line. Also since you're

identifying colors with objects you either have to have

the objects the same colors, or wait on drawscreen and

waiting will give you flicker.

If you use a multicolor playfield you're restricted to

11 colors and the colors are per line and since the

objects move in opposite directions relative to the lines

there's probably no practical way to make it work if you

need to have more than one object per line.

So with a limit of 11 colors, one per line and objects

identified with colors, and one object per line so the

colors/positions/objects don't interact in impossible to

implement ways, you're limited to 11 objects each on a

different line.

That may be possible although it might not look as pretty

as hoped. The problem is the pfcolors are normally taken

from tables in rom so you either have to have all

possibilities in rom (probably an impossibly large number)

or coax the kernel to get the playfield color data from

ram where you can manipulate it.

 

That sounds like an intersting possibility/problem and I

think I'll try and make it work.

 

But as I said before I'm no expert, I don't know what more

advanced options may be available and I have (almost) no idea

what you can do with DPC+

 

Don't give up. If you give up you'll never figure it out.

Link to comment
Share on other sites

Well, I've been told that the more advanced stuff, like this, isn't really possible with batariBasic but may be possible with Assembly, although I don't know Assembly. I'll try going through Andrew Davie's course and hopefully that will put me a bit further along.

 

Meanwhile,

of what the code does so far.

 

I could try the pflines thing if I space out the blocks differently, but then they certainly wouldn't be circular and it may be very limiting.

 

Could this be done if I use multisprite, giving each different colors, and moved them around the field instead of pfpixels?

Link to comment
Share on other sites

Well, I've been told that the more advanced stuff, like this, isn't really possible with batariBasic but may be possible with Assembly, although I don't know Assembly. I'll try going through Andrew Davie's course and hopefully that will put me a bit further along.

 

It's also here:

 

www.randomterrain.com/atari-2600-memories.html#assembly_language

Link to comment
Share on other sites

1. First of all, I know that there are serious limitations on what can be done, but why are they THIS limiting? Maximum of two sprites? Any more requires significant slow-down and flicker as you teleport them from place to place? What about, for instance,

(which is very similar to the game I'm trying to make)? You've got a ball that does not share the same color as the playfield (and, for that matter, a playfield that is not one solid color) and a series of "blocks" that I assume are sprites, yet there is no noticeable flicker. Or, for another example, Pitfall, which not only seems to have multiple different sprites on screen, but also sprites with multiple colors (the man) and a playfield consisting of much greater pixel quantity/density than is available to me in Visual bB. What gives?

 

It's THIS limiting because that's what affordable hardware in the 70s could support. As an example of how expensive technology was back then, when they started developing the Atari in 1973 1KB of RAM cost $390 (which is about $2000 in today's currency :-o ).

 

I'm not sure what you mean by significant slow-down on the 2600 as that does not occur with 2600 games. I know it's a problem with later systems due to how they were designed.

 

Have you used Stella? It has a built in feature called Fixed Debug Colors that can help you understand how the different TIA objects are used to generate the game display. (TIA's the video chip in the Atari). Toggle Fixed Debug Color mode by hitting Command-Comma on a Mac or ALT-Comma on Windows or Linux. These are the colors each object takes:

post-3056-0-26613500-1359682713_thumb.gif

By looking at the color table you can see that all the bricks are drawn by using the playfield. They appear to be different colors because you can change the colors of objects on different scanlines.

post-3056-0-49642600-1359682679_thumb.png post-3056-0-06444700-1359682685_thumb.png

 

And the ball does take on the color of the play field, in this screenshot you can see that the ball takes on 2 colors because of where it is onscreen.

post-3056-0-70784900-1359682965_thumb.png

 

While there's only 2 sprites, you can reuse them as the screen is being drawn. In this you can see that player 0 (sprite 0) is used to draw parts of the score, timer, tree branches, pitfall harry, and parts of the Activision logo. The other sprite, player 1, is used to draw parts of the score, timer, tree branches, log, brick wall and parts of the Activision logo.

post-3056-0-12911100-1359682692_thumb.png post-3056-0-68134500-1359682697_thumb.png

 

 

I don't know much about the kernels and such. From what I've just read, they seem to take an awful lot of space. Not sure if that's worth it for bitmaps and the like.
Unlike modern systems, the Atari does not have video RAM for the video chip to use to draw the display. Instead, the program must update TIA in real time (scanline by scanline) with the data to display. This part of the program is called the kernel.

 

 

I did a presentation at the Houston Arcade Expo that you may find enlightening.

Edited by SpiceWare
  • Like 2
Link to comment
Share on other sites

Thanks for the info, Spice. I read your presentation as well as about half of the assembly course, though I don't feel much closer to actually being able to do things differently, though it is interesting stuff that makes the meanings of things a bit clearer.

 

Okay, so we've established that the playfield either has to be a solid color or a solid horizontal line. Now, is there any way to put multiple colors in the background without being limited to a single color per line? There seems to be different colors per line in Pitfall, there. If I could color in specific colors to certain regions of the screen, I could use a mostly-black playfield as a mask to cover up the rest of the background so that the colors only would show through where I wanted them to. If not that, and not any way to do the playfield differently, is there maybe a way of interlacing the image to that each pfpixel is made up of half as many lines, but those lines, each of the appropriate color, could be swapped between fast enough to made the flicker negligible? Even if it results in a less-solid image, that'd be preferable to one that flickers.

 

If not any of that, is there ANY solution whatsoever, or is it entirely impossible to have multiple colors on screen like I'm trying to do?

Link to comment
Share on other sites

Any TIA register can be changed mid-scanline, that includes the registers for background color and playfield color. In practice it's quite complex to do because there's only 76 cycles of CPU time per scanline.

 

I changed the playfield color mid-scanline in Medieval Mayhem by using a feature called SCORE. I turned it on/off/on as the scanline is drawn. SCORE tells TIA to color the playfield using the colors of player 0 and player 1 for the left and right sides respectively. It worked well for this as the kings needed to be the same color as the shields.

post-3056-0-17062100-1359687853_thumb.png post-3056-0-88985300-1359687856_thumb.png

 

I documented the development of MM in my blog, most of the entries contain source code. Using the category filter you can see just the entries for MM. The second entry is where I started changing the playfield color. For the score line I changed the playfield color instead of using SCORE mode as I needed to show 4 colors.

post-3056-0-07912900-1359689536_thumb.png post-3056-0-36222900-1359689541_thumb.png

 

SCORE is how the games used to display scores before they figured out the 48 pixel trick. They'd draw the scores using the playfield and color them by setting SCORE.

 

post-3056-0-50185100-1359688282_thumb.png post-3056-0-21692000-1359688287_thumb.png

 

post-3056-0-23140100-1359688274_thumb.png post-3056-0-58816500-1359688278_thumb.png

 

 

Atari Video Cube changes the playfield color mid-scanline by updating the playfield color register:

post-3056-0-07127800-1359689029_thumb.png post-3056-0-17419700-1359689033_thumb.png

 

Do you have an iOS device? David Crane did a couple apps, 2600 Magic and Dragster Magic, that go over programming the 2600. They're quite well done.

  • Like 1
Link to comment
Share on other sites

Unfortunately, I do not have an iOS device, but I'll definitely go over that code, thanks! Too bad I don't know anything about Assembly, so I'll probably end up needing assistance.

 

In the meanwhile, I kept hammering away at the game and I think it's basically done, aside from two things:

 

1. The flicker problem

 

2. Collision detection issues

 

The collision detection code can be seen below:

 

rem collision detection
700
if a[0] = 0 then goto 701
if player1x > 80 && player1x < 85 && player1y >8 && player1y <17 && ballcolor = a[0] then a[0] = 0: goto good_hit
if player1x > 80 && player1x < 85 && player1y >8 && player1y <17 && ballcolor <> a[0] then goto bad_hit
701
if a[2] = 0 then goto 702
if player1x > 113 && player1x < 118 && player1y >16 && player1y <25 && ballcolor = a[2] then a[2] = 0: goto good_hit
if player1x > 113 && player1x < 118 && player1y >16 && player1y <25  && ballcolor <> a[2] then goto bad_hit
702
if a[4] = 0 then goto 703
if player1x > 129 && player1x < 134 && player1y >48 && player1y <57 && ballcolor = a[4] then a[4] = 0: goto good_hit
if player1x > 129 && player1x < 134 && player1y >48 && player1y <57 && ballcolor <> a[4] then goto bad_hit
703
if a[6] = 0 then goto 704
if player1x > 113 && player1x < 118 && player1y >80 && player1y <89 && ballcolor = a[6] then a[6] = 0: goto good_hit
if player1x > 113 && player1x < 118 && player1y >80 && player1y <89 && ballcolor <> a[6] then goto bad_hit
704
if a[8] = 0 then goto 705
if player1x > 81 && player1x < 86 && player1y >88 && player1y <97 && ballcolor = a[8] then a[8] = 0: goto good_hit
if player1x > 81 && player1x < 86 && player1y >88 && player1y <97 && ballcolor <> a[8] then goto bad_hit
705
if a[10] = 0 then goto 706
if player1x > 49 && player1x < 54 && player1y >80 && player1y <89 && ballcolor = a[10] then a[10] = 0: goto good_hit
if player1x > 49 && player1x < 54 && player1y >80 && player1y <89 && ballcolor <> a[10] then goto bad_hit
706
if a[12] = 0 then goto 707
if player1x > 33 && player1x < 38 && player1y >48 && player1y <57 && ballcolor = a[12] then a[12] = 0: goto good_hit
if player1x > 33 && player1x < 38 && player1y >48 && player1y <57 && ballcolor <> a[12] then goto bad_hit
707
if a[14] = 0 then goto 708
if player1x > 49 && player1x < 54 && player1y >16 && player1y <25 && ballcolor = a[14] then a[14] = 0: goto good_hit
if player1x > 49 && player1x < 54 && player1y >16 && player1y <25 && ballcolor <> a[14] then goto bad_hit
708
if player1x = 0 || player1y = 0 then goto 750
if player1x=156 || player1y = 140 then goto 750

 

I mapped out the top-left pixel location of all the pfpixels in the playfield seen below:

 

playfield:
............X...X...X...........
........X...............X.......
................................
......X...................X.....
................................
.....X..........X..........X....
................................
......X...................X.....
................................
........X...............X.......
............X...X...X...........
end

 

From there, I added a range of 4 width and 8 height to accommodate the full "hit box" of the pfpixel. For some reason, though, only #703 and #707 (the bottom-right corner and top-left corner) work correctly. All the other hitboxes register no detection and the "ball" passes straight through. I would say that it's a problem with the ranges I set, but I used the same sort of range values for all other pfpixels as those two. In all cases, the minimum ranges are derived from the top-left pixel in the pfpixel (determined by checking through spawning player1, with a sprite shaped like a pfpixel, at the location), though now that I say that, I may have an idea as to what is wrong -- I'm probably forgetting that player sprites are spawned in the center of their location, so all my values are incorrectly offset. Oh, well, I'll get 'em fixed!

 

Somewhat worryingly, I'm down to just 263 bytes left, though it's probable that there is room for optimization and the core of everything is there already. If there is a way for me to resolve this flicker problem as Omega and others have suggested, I may have to upgrade the game to an 8k rom file, because what you see is really a very simplified version of a game that I designed for GameJam. I'd like there to be room to add secondary colors (orange, for instance, can be 'killed' by a red ball or a yellow ball) and white (which can be killed by any ball, but takes to hits to do so) and black (which will hurt if it is hit, so the player will have to take note of the "blank space" relative to the other colors and make sure not to hit it) with levels that progress at more than an entirely random degree (a bit of planned progression to introduce the new blocks as they come, though still governed by randomness).

 

Also, is there a good, simple tutorial for what is necessary to add sounds? Music is out of the question, both because I am no composer and due to the size limit, but I'd at least like to have audio feedback for a good hit and a bad hit. The demos I've seen seem a bit complicated and don't make it clear how much of all the code is necessary for getting a sound to play.

 

I'll probably also get someone to playtest to give me some feedback on the controls--whether the balls move too quickly to respond and whether the controls on the block rotation are too fast or too slow.

 

So, thanks to everyone for the great feedback and help! Any more resources that can teach me more about how to get this flicker problem to go away, or anyone willing to write a kernel that I can just plug 'n play while still programming in bB, that'd be great!

Link to comment
Share on other sites

Alright, got that collision detection issue all sorted out. As I figured, I put in the wrong numbers, forgetting that sprites center to their coordinates.

.

 

There's a bug where block #15 and block #0 always share the same colors. #0 starts at the very top and the numbers go clockwise, so #15 is the one just to the left of it. I'm sure that I made a dumb mistake when writing the rotation routine, but every time I stare at the code for it and try to visualize the problem, my brain goes numb.

 

If anyone is willing to point out the glaringly obvious oversight, it would be appreciated. I'm sure that I just have to store one of the variables to be placed later or something like that.

 

rem move all block values to the right
435  for temp1 = 0 to 15
temp2 = temp1 + 1
if temp2 = 16 then temp2 = 0
a[temp1] = a[temp2]
next
offset = 50
goto 500
rem move all blocks to the left
445  for temp1 = 15 to 0 step -1
temp2 = temp1 - 1
if temp2 = 255 then temp2 = 15
a[temp1] = a[temp2]
next
offset = 50
450

 

Other than that, it mostly just comes down to flicker issues. If I can get the flicker issues fixed through everyone's suggestions and things look to be working well, I'll probably expand this to an 8k ROM and add some further functionality. :D

 

Again, if someone can explain how sounds work, that would be a great boon as well.

Link to comment
Share on other sites

Again, if someone can explain how sounds work, that would be a great boon as well.

 

Have you looked at the example programs here yet:

 

www.randomterrain.com/atari-2600-memories-batari-basic-commands.html#sound

 

 

I make sound effects by hunting down sounds with Tone Toy 2008 and shaping/altering those sounds using VbB's Music and Sound Editor.

Link to comment
Share on other sites

Have you looked at the example programs here yet:

 

www.randomterrain.com/atari-2600-memories-batari-basic-commands.html#sound

 

 

I make sound effects by hunting down sounds with Tone Toy 2008 and shaping/altering those sounds using VbB's Music and Sound Editor.

 

Yes, I did. There are a lot of variables at play and I don't see how many of them are absolutely necessary. You have temp variables for all sound values, loops, functions, etc. all over, but is that necessary? What is the absolute minimum code necessary to make a sound work? Because I've only got about 200 bytes and maybe 1 variable to spare.

Link to comment
Share on other sites

May do that, RT. I'd like to hold off unless absolutely necessary.

 

I managed to fix that silly bug with the duplication between a[0] and a[15], which is a huge relief. I've gone through and optimized the code as much as I can, squeezing out a total of 183 Bytes that have not yet been used. If this kernel thing works to handle the flicker, that can be upped to about 710 bytes, as a good chunk is spent in the flicker code.

 

I haven't looked into the kernel/etc. stuff yet, but I'm about to. If anyone has a genie-in-the-bottle solution to offer, though, I'm all ears.

 

It was suggested that some assembly code be used to update the colors mid-scanline. Does anyone have the code for this? Can I insert assembly code into bB so that it runs those things separately?

 

I can't read Assembly and I don't know what it means, so if it's coming to that, I'm probably going to need some strong advice/help.

Link to comment
Share on other sites

I've gone through and optimized the code as much as I can, squeezing out a total of 183 Bytes that have not yet been used. If this kernel thing works to handle the flicker, that can be upped to about 710 bytes, as a good chunk is spent in the flicker code.

 

obviously this is untested but it compiles.

I may well have goofed something up.

 

I rewrote the collision code you posted to get rid of those

redundant if-then statements (and then stuck a couple of

my own in)

 if playerx1<50 || playerx1 > 133 then goto skip_collision_test
if playery1<9 || playery1 > 94 then goto skip_collision_test

for i = 0 to 14 step 2
if a[i] then goto collision_test
nexti
next

skip_collision_test
if player1x = 0 || player1y = 0 then goto 750
if player1x=156 || player1y = 140 then goto 750


collision_test
temp1 = playerx1-xtbl[i]&127
if temp1>3 then goto nexti
temp1 = playery1-ytbl[i]&127
if temp1>5 then goto nexti
if a[i]<>ballcolor then goto bad_hit

rem good_hit
a[i]=0

bad_hit


750

data xtbl
81, 00, 114, 00, 130, 00, 114, 00, 82, 00, 50, 00, 34, 00, 50
end

data ytbl
9, 00, 17, 00, 49, 00, 81, 00, 89, 00, 81, 00, 49, 00, 17
end

 

edit: goofed the datastaments up (now fixed I hope)

should probably interleave the x and y values but

this is just ment as illustration so I didn't bother to

obfuscate

edit somemore

more goofs

Edited by bogax
Link to comment
Share on other sites

I don't know enough about BB to say whether or not you can replace most of the kernel with assembly. That would be the ideal solution, where you could insert some assembly inline and compile the whole thing from one source.

 

An alternative would be to compile the game as is, and patch in the assembly routine where the BB kernel normal lies (since you won't be using it anyhow).

 

As to draw it, I believe the routine right now is storing all the PF block bits in ram. You could instead just store the colors for the individual PF (you probably already are), and color the playfield blocks black as they get hit to hide them. Does that make sense? The reason in this case is it would make the assembly portion much easier to do. Essentially the playfield would be set up in reflected mode, and the circular pattern would be drawn each screen with each block its unique color (or black to be hidden).

 

I believe from your code the collisions are being handled through software, so that should still work.

Edited by Omegamatrix
Link to comment
Share on other sites

From the last video I dun get why there is flicker and soft collisions.

 

Can't you use traditional collision(missile0, playfield) when the players shot hits a block?

 

Also, you don't really need multiple colors per row. Stagger the playfield blocks between rows. This should work except for the topmost row and bottom.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   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...