Cybearg Posted January 29, 2013 Share Posted January 29, 2013 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! Quote Link to comment Share on other sites More sharing options...
Gateway Posted January 30, 2013 Share Posted January 30, 2013 I like your game idea. Sounds interesting! 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! 1 Quote Link to comment Share on other sites More sharing options...
Cybearg Posted January 30, 2013 Author Share Posted January 30, 2013 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. Quote Link to comment Share on other sites More sharing options...
bogax Posted January 30, 2013 Share Posted January 30, 2013 (edited) 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 January 30, 2013 by bogax Quote Link to comment Share on other sites More sharing options...
Cybearg Posted January 30, 2013 Author Share Posted January 30, 2013 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? Quote Link to comment Share on other sites More sharing options...
bogax Posted January 30, 2013 Share Posted January 30, 2013 (edited) 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 January 30, 2013 by bogax Quote Link to comment Share on other sites More sharing options...
bogax Posted January 31, 2013 Share Posted January 31, 2013 However if you're only doing two colors per line, perhapsyou 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 Quote Link to comment Share on other sites More sharing options...
Cybearg Posted January 31, 2013 Author Share Posted January 31, 2013 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. Quote Link to comment Share on other sites More sharing options...
bogax Posted January 31, 2013 Share Posted January 31, 2013 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. Quote Link to comment Share on other sites More sharing options...
Cybearg Posted January 31, 2013 Author Share Posted January 31, 2013 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? Quote Link to comment Share on other sites More sharing options...
+Random Terrain Posted January 31, 2013 Share Posted January 31, 2013 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 Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted February 1, 2013 Share Posted February 1, 2013 (edited) 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 ). 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: 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. 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. 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. 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 February 1, 2013 by SpiceWare 2 Quote Link to comment Share on other sites More sharing options...
Cybearg Posted February 1, 2013 Author Share Posted February 1, 2013 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? Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted February 1, 2013 Share Posted February 1, 2013 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. 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. 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. Atari Video Cube changes the playfield color mid-scanline by updating the playfield color register: 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. 1 Quote Link to comment Share on other sites More sharing options...
Omegamatrix Posted February 1, 2013 Share Posted February 1, 2013 I watched your video and it looks fun! It could be done flickerless in assembly. You just have to update the playfield color midline. Approach it as a few mini kernels. Quote Link to comment Share on other sites More sharing options...
Cybearg Posted February 1, 2013 Author Share Posted February 1, 2013 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! Quote Link to comment Share on other sites More sharing options...
Cybearg Posted February 1, 2013 Author Share Posted February 1, 2013 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. Again, if someone can explain how sounds work, that would be a great boon as well. Quote Link to comment Share on other sites More sharing options...
+Random Terrain Posted February 1, 2013 Share Posted February 1, 2013 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. Quote Link to comment Share on other sites More sharing options...
Cybearg Posted February 1, 2013 Author Share Posted February 1, 2013 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. Quote Link to comment Share on other sites More sharing options...
+Random Terrain Posted February 1, 2013 Share Posted February 1, 2013 If you use Superchip RAM, you'll get 48 extra variables (from the old playfield) and more variables that can only be read and written to in a special way. Quote Link to comment Share on other sites More sharing options...
Cybearg Posted February 1, 2013 Author Share Posted February 1, 2013 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. Quote Link to comment Share on other sites More sharing options...
bogax Posted February 2, 2013 Share Posted February 2, 2013 (edited) 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 February 3, 2013 by bogax Quote Link to comment Share on other sites More sharing options...
Omegamatrix Posted February 2, 2013 Share Posted February 2, 2013 (edited) 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 February 2, 2013 by Omegamatrix Quote Link to comment Share on other sites More sharing options...
Omegamatrix Posted February 2, 2013 Share Posted February 2, 2013 (edited) Actually, I just had the thought that you are probably in asynchronous mode. That is okay, it is easy to deal with too. Edit: It would also be nice to know what you are drawing the heart and shot with. Is GRP0 the heart, and GRP1 or M1 the shot? Edited February 2, 2013 by Omegamatrix Quote Link to comment Share on other sites More sharing options...
+Gemintronic Posted February 2, 2013 Share Posted February 2, 2013 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. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.