Jump to content

Cybearg

Members
  • Posts

    951
  • Joined

  • Last visited

Everything posted by Cybearg

  1. No, decimal is clearer because it can be quickly read by anyone who glances at the code. Why would base 2 or base 16 be clearer than base 10, unless maybe you grew up with 2 or 16 fingers, respectively? ;P Anyway, thanks much for your fix! Adding 4 seems pretty obvious, so I'm embarrassed that I didn't think of it right away. Why would everything be offset by 4, I wonder? As for your code, why does bxtbl have a single value in it all by itself? Is there some advantage to doing that and going back to software checks rather than relying on the hardware collision detection?
  2. yHow are they different? I know that anglevar is a range of 0 to 7 and the colors are a range of 0 to 15, but since each value of anglevar corresponds to every other value of the colors, a[0] to a[15] step 2 = a[anglevar], right? So then a[0] to a[15] step 1 = a[anglevar*2] I just don't see why it's getting mirrored over the x axis. anglevar = (rand/32) Let's say that anglevar = 0 rem x motion table data xmtbl 50, 51, 51, 51, 50, 49, 49, 49 end rem y motion table data ymtbl 51, 51, 50, 49, 49, 49, 50, 51 end rem separate out cardinal from diagonal directions if anglevar <> 0 && anglevar <> 2 && anglevar <> 4 && anglevar <> 6 then goto 670 else goto 680 Since angle = 0, we goto 680 680 rem movement values for cardinal (0, 90, 180, 270 degrees) directions -- applies a cooldown to ensure that cardinal directions do not move too fast if cooldown <> 3 && cooldown <> 7 then player1x = player1x + xmtbl[anglevar] - 50 if cooldown <> 3 && cooldown <> 7 then player1y = player1y + ymtbl[anglevar] - 50 From this and the tables established above, we find that xmtbl[anglevar] = 50 and ymtbl[anglevar] = 51 So player1x = player1x + 50 - 50 : player1x = player1x player1y = player1y + 51 - 50 : player1y = player1y + 1 This moves the ball straight up, towards 12 o'clock mark. Then... rem check for collision -- if not, bypass everything else as we wait for a collision if !collision(playfield,player1) then goto 800 Let's say that there is a collision with the 12 o'clock block. This is then true and the code continues... rem double anglevar in order to determine how the number relates to a 0-15 range rather than a 0-7 range temp4 = (anglevar + anglevar + base) & 15 Since anglevar = 0 and we haven't rotated left or right, temp4 = (0 + 0 + 0) & 15 : temp4 = 0 rem checks for various hit-types, currently only consists of a single possibility, but there will be more for secondary colors, white, and black if a[temp4] = ballcolor then goto good_hit Let's say that both are red, so a[temp4] = ballcolor or a[0] = ballcolor : 64 = 64 good_hit rem set current block to dead a[temp4] = 0: blkcount = blkcount - 1 So this should set a[0] to 0, which will mean that it won't be drawn. Instead, it sets a[8] to 0. Where in the code is that made to happen? ------------------------------- Your code: rem check for collision type 710 temp4 = temp4 + base & $0F rem check if the block is already dead if a[temp4] = 0 then goto 800 rem check ball color against block color if a[temp4]<>ballcolor then goto bad_hit rem if the hit is good... This doesn't really apply anymore because, using hardware collision and comparing to the angle of the ball, there is no need to loop through and check each block anymore. Instead, I need to offset an equal amount as the color's movement is being offset, then cross-reference the color value by the angle of the ball. Hence my stuff above. Also, why do you like using $0F when 15 is functionally equivalent and much less confusing to read?
  3. Alright. The following implements the hardware-based collision detection and the simpler color rotation. There is one problem remaining: With the implementation of the hardware collision detection comes the same problem I described in the first post on this page. That is, collisions are mirrored on the x axis for some reason. If someone can suggest a fix for this problem, things will be working very well. rem ==================== rem COLLISION DETECTION rem ==================== 700 rem check to see if player 1 is out of bounds if player1x = 25 || player1y = 0 then goto 750 if player1x=133 || player1y = 140 then goto 750 rem check for collision -- if not, bypass everything else as we wait for a collision if !collision(playfield,player1) then goto 800 705 rem double anglevar in order to determine how the number relates to a 0-15 range rather than a 0-7 range temp4 = (anglevar + anglevar + base) & 15 rem checks for various hit-types, currently only consists of a single possibility, but there will be more for secondary colors, white, and black if a[temp4] = ballcolor then goto good_hit rem if the hit is bad... bad_hit Aside from that, everything seems to be working. I understand the way that the base thing works now--I think that I was confused by the odd choice by bogax to use HEX $0F instead of the much simpler and more readable 15 and I didn't grasp how the & actually works in that context, but now I think I understand it better. Can anyone offer a suggestion why the above would cause collisions to be mirrored on the x axis? Note: it has nothing to do with the implementation of the better color movement style, as I was having the same problem even at the top of this thread's page. heartbreak.bas.bin heartbreak.bas
  4. As you say, for the kernel to have non-fickering colors, it will eventually have to have all pfpixels on-screen at once and will segment the color drawing in some way (what way, I don't know, since I'm not sure how it would work). For the time being, each pfpixel color is on-screen every third frame (if there are 3 colors being rotated). Hardware collisions shouldn't be a problem, because the ball isn't moving every frame--it's moving every other frame. Even if it hit a pfpixel horizontally (where the pfpixel is only 4 pixels wide), the hardware should detect a collision because, at least, the ball would be within the range of the pfpixel while it is on-screen for a couple of frames where a pfpixel is being drawn, which would register a collision. Maybe that's not perfect, but it's scaleable and, for the time being, it's sufficient. I'd like to nail things down as being as close to perfect so, when/if someone generously creates the magical kernel I'm waiting for, it can be just dropped in and most everything will be set up to already utilize it.
  5. Thanks for all the help, folks, especially bogax. I kind of worry, though, that after getting so much help, I can hardly claim the game as my own creation anymore. Well, I took theloon's suggestion to tweak the collision detection to this: rem ==================== rem COLLISION DETECTION rem ==================== 700 rem check to see if player 1 is out of bounds if player1x = 25 || player1y = 0 then goto 750 if player1x=133 || player1y = 140 then goto 750 rem check for collision -- if not, bypass everything else as we wait for a collision if !collision(playfield,player1) then goto 800 705 rem double anglevar in order to determine how the number relates to a 0-15 range rather than a 0-7 range temp4 = anglevar + anglevar rem checks for various hit-types, currently only consists of a single possibility, but there will be more for secondary colors, white, and black if a[temp4] = ballcolor then goto good_hit rem if the hit is bad... bad_hit This seems like a great simplification from what was before, but it doesn't quite work right, though I don't understand why. Collisions are correct at 3 o'clock and 9 o'clock, but 12 o'clock takes out the block at 6 o'clock and other angles tend to wander. I don't see how the game can take 0 + 0 and get 8 from that. EDIT: It seems that all values are inverted across the x-axis. It's possible I'm just being stupid, but how does that work?
  6. That's brilliant! Let me fiddle with it and see what I can come up with. Great idea!
  7. So far as I am aware, BASIC, at least bB, can't do pointers, and even if it could, I've only just started learning about pointers in my C class at college, so I don't truly grasp how they work, yet. Anyway, that bug was already accounted for in my original code, as around page 2 I posted that I noticed that colors 15 and 0 always shared the same color, and after a bit of visualizing on paper, I figured the solution of plucking out a[0] and then placing it in a[15] after the loop had completed. I've got so many versions of this game all over the place and I've not really saved it in a long time because none of them are fully functional. While I see the advantage of the new way of doing the color movement, it breaks the hit detection big-time and I'm not sure how to fix it (or maybe just too exhausted with fiddling around with the code to see a solution). And then there's still the constant issue of "this game will not be made if there is not a fix for the flickering." Unless multiple pfpixel colors can be displayed on-screen at once (or some other flicker-free equivalent for the 16 blocks), it hurts the eyes too much to play.
  8. I've spent all day wracking by brain over how it can be done. After much frustration and swearing, I give up. If only I knew what "base" was at any given moment, but score = base gives me nothing; score refuses to provide me any hints as to what any value is that I've ever tried. I have no clue why, but it just doesn't work for me. If only I knew what base was, I could see what was going on and figure out a way to compensate for it, but I can't and I'm out of ideas and extremely annoyed. I did, but it doesn't work. If I lower it to just two possible values, there is still far more flicker than there should be. On the first level, where all the blocks are red, there should be no flicker at all because there is no other color to flicker TO. The code SHOULD be recognizing through the loop that there aren't any blocks of any color besides red and thus skipping drawing any colors besides red, but it just doesn't. I don't know why. I've gone over the code dozens of times and spent between six to eight hours among this and the hit detection stuff, all to no avail whatsoever. If it makes you feel any better, I have zero clue about ASM, so it was all Greek to me, anyway. But unless I know which color of block is remaining, which, unless I have another 16 variables to spend, I have no way to keep a running memory of, then just knowing how many blocks are left doesn't help me. The point of running through the blocks each time is to count how many of each color remains so that the flicker can reduce to only displaying the colors that are actually on the playfield, but it doesn't work. It still flickers through all the other colors, anyway, and I have no clue why. This is probably all a phenomenal waste of time, anyway, because it is highly unlikely that, when/if/hopefully someone writes that new kernel that I've been begging for over the past week or so, it will rely on the current flickering system. So trying to improve that code is pointless until I have some modicum of an idea of how a new kernel could work or what it would require me to do. I tried this suggestion. It really doesn't change anything; it just splits apart what's already being done, more or less. I still get a recurring flicker even on level 0, where each of the blocks is red and the code should recognize that is the case and refrain from any flickering. rem Generated 1/28/2013 1:50:36 PM by Visual bB Version 1.0.0.548 rem ********************************** rem *heartbreak.bin * rem *A re-imagning of breakout with a lonely heart trapped in a void... * rem *Cybearg (aka Nic) * rem *cybearg.plays@gmail.com * rem ********************************** rem ============== rem INITIALIZATION rem ============== rem set up settings/optimization set optimization speed rem set up my variables dim level = s dim cooldown=t dim anglevar=u dim pulse=v dim flicker=w dim offset=x dim ballcolor=y dim heartcolor=z rem set offset to a number greater than 0 to allow for "negative" values offset = 50 rem set heartcolor to begin at red heartcolor = 64 rem set player 0's location player0x=80:player0y=48 rem ========== rem MAIN LOOP rem ========== draw_loop rem clear the playfield pfclear rem increment the multi-purpose cooldown variable cooldown = cooldown + 1 rem mute sound at 7 cooldown cycles or after 20 cycles if there's been a titlescreen restart if cooldown = 7 || cooldown = 70 then AUDV0 = 0 : AUDV1 = 0 rem =============== rem BEATING HEART rem =============== rem increment pulse counter pulse = pulse +1 rem cooldown to make sure that player doesn't leave the title screen by firing a ball if pulse = 45 && cooldown >= 50 then cooldown = 0 rem after 45 cycles, increment color if pulse = 45 then pulse = 0 rem special occasion for first level if level = 0 then heartcolor = 64: goto 10 rem special occasion for second level if level = 1 && heartcolor = 64 && pulse = 0 then heartcolor = 28: goto 10 if level = 1 && heartcolor = 28 && pulse = 0 then heartcolor = 64: goto 10 rem increment the colors if heartcolor = 28 && pulse = 0 then heartcolor = 148: goto 10 if heartcolor = 64 && pulse = 0 then heartcolor = 28: goto 10 if heartcolor = 148 && pulse = 0 then heartcolor = 64 10 rem set the playfield colors COLUP0 = heartcolor rem turn the score red if player is on the last life if lives = 1 then scorecolor = 64 else scorecolor = 10 rem swap the heart sprite for 5 cycles to create illusion of beating if pulse < 40 then goto 40 else goto 44 rem values for the up-beat (40 out of 45 cycles) 40 if lives = 0 then goto 80 41 if lives = 1 then goto 70 42 if lives = 2 then goto 60 43 if lives = 3 then goto 50 rem values for the down-beat (5 out of 45 cycles) 44 if lives = 0 then goto 80 45 if lives = 1 then goto 90 46 if lives = 2 then goto 70 47 if lives = 3 then goto 60 rem the various player 0 heart sprites 50 player0: %00010000 %00111000 %01111100 %11111110 %11111110 %11111110 %01101100 %00000000 end 55 goto 100 60 player0: %00000000 %00010000 %00111000 %01111100 %01111100 %00101000 %00000000 %00000000 end 65 goto 100 70 player0: %00000000 %00000000 %00010000 %00111000 %00101000 %00000000 %00000000 %00000000 end 75 goto 100 80 90 player0: %00000000 %00000000 %00000000 %00000000 %00000000 %00000000 %00000000 %00000000 end rem ============== rem COLOR FLICKER rem ============== 100 rem if the player has zero lives, skip this part if lives = 0 then goto 410 rem set up possible colors data blkc 64, 28, 154, 44, 202, 122, 14, 0 end rem set up possible pfpixel locations data ctbl 16, 20, 24, 27, 28, 27, 24, 20, 16, 12, 8, 5, 4, 5, 8, 12 end data rtbl 0, 0, 1, 3, 5, 7, 9, 10, 10, 10, 9, 7, 5, 3, 1, 0 end 110 rem cycle through pfpixels, turning them on if they are equal to the color being drawn temp3 = blkc[flicker] for temp5 = 0 to 15 if a[temp5] = temp3 then pfpixel ctbl[temp5] rtbl[temp5] on: temp4 = 1 next flicker = flicker + 1 & 7 rem determines if a color shows up; if not, don't bother drawing that color and return for the next if temp4 then COLUPF = temp3 else goto 110 rem ================== rem MAIN DRAWSCREEN rem ================== rem main drawscreen drawscreen rem skip to COLOR MOVEMENT goto 415 rem ============= rem TITLE SCREEN rem ============= 410 rem set the beat of the title screen heart to the ongoing pulse if pulse < 40 then goto 413 else goto 412 rem the two possible title screen frames 412 playfield: ................................ ...X.X.XXX..X..XX.XXX........... ...X.X.X...X.X.X.X.X............ ...XXX.XX..XXX.XX..X............ ...X.X.XXX.X.X.X.X.X............ .............................. ...........XX..XX..XXX..X..X.X.. ....X.X....X.X.X.X.X...X.X.X.X.. ....XXX....XX..XX..XX..XXX.XX... .....X.....X.X.X.X.XXX.X.X.X.X.. ...........XXX.................. end rem skip to color goto 414 413 playfield: ................................ ...X.X.XXX..X..XX.XXX........... ...X.X.X...X.X.X.X.X............ ...XXX.XX..XXX.XX..X............ ...X.X.XXX.X.X.X.X.X............ ................................ ...XX.XX...XX..XX..XXX..X..X.X.. ..XXXXXXX..X.X.X.X.X...X.X.X.X.. ...XXXXX...XX..XX..XX..XXX.XX... ....XXX....X.X.X.X.XXX.X.X.X.X.. .....X.....XXX.................. end 414 rem color the title screen playfield COLUPF = 64 rem drawscreen for titlescreen only drawscreen rem skip everything else and wait for a trigger goto 760 rem ================= rem COLOR MOVEMENT rem ================= 415 rem NOTE: offset base is 50, so the numbers below determine how sensitive the controls are rem determine block offset if joy0left && offset < 56 then offset = offset + 1 if joy0right && offset > 44 then offset = offset - 1 rem adjust block offset 420 if offset > 55 goto 435 if offset < 45 goto 445 rem if no adjustments are necessary, skip this part goto 500 rem move all block values to the left (counter clockwise) 435 temp2 = a for temp1 = 0 to 14 a[temp1] = b[temp1] next p = temp2 goto 450 rem move all blocks to the right (clockwise) 445 temp2 = p for temp1 = 15 to 0 step -1 b[temp1] = a[temp1] next a = temp2 rem reset the offset 450 offset = 50 rem ============ rem PLAYER FIRE rem ============ 500 rem checks to see that a few cool-down measures are a go, then moves the ball (player 1) to the center of the heart (player 0) rem cooldown ensures that the player cannot fire while a ball is at play rem cooldown also ensures the player doesn't exit a title screen by firing a ball prematurely if joy0fire && lives > 0 && player1x = 0 && player1y = 0 && cooldown < 50 then player1x=80:player1y=48 else goto 600 rem moves the ball's current color from heartcolor (set in the BEATING HEART section) to ballcolor for safe-keeping ballcolor = heartcolor rem set player 1's sprite player1: %00000000 %00000000 %00000000 %00011000 %00011000 %00000000 %00000000 %00000000 end rem generate random number to determine ball movement rem variables ensure that ball speed/angle does not vary once ball has been generated anglevar = (rand/32) rem ========= rem THE BALL rem ========= 600 rem skip everything dealing with the ball if it is at its resting position (0,0) if player1x = 0 && player1y = 0 then goto 800 rem maintain the color of the ball at the moment of firing COLUP1 = ballcolor rem all ball movement possibilities rem allows for ball movement in a direction every 45 degrees 650 rem cooldown is used to manage the speed of the ball if cooldown > 8 then cooldown = 0 rem x motion table data xmtbl 50, 51, 51, 51, 50, 49, 49, 49 end rem y motion table data ymtbl 51, 51, 50, 49, 49, 49, 50, 51 end rem separate out cardinal from diagonal directions if anglevar <> 0 && anglevar <> 2 && anglevar <> 4 && anglevar <> 6 then goto 670 else goto 680 670 rem movements for diagonal directions (45, 125, 225, 315) -- applies a cooldown to ensure that diagonals do not move too fast if cooldown <> 1 && cooldown <> 3 && cooldown <> 5 && cooldown <> 7 then player1x = player1x + xmtbl[anglevar] - 50: player1y = player1y + ymtbl[anglevar] - 50: goto 700 else goto 700 680 rem movement values for cardinal (0, 90, 180, 270 degrees) directions -- applies a cooldown to ensure that cardinal directions do not move too fast if cooldown <> 3 && cooldown <> 7 then player1x = player1x + xmtbl[anglevar] - 50 if cooldown <> 3 && cooldown <> 7 then player1y = player1y + ymtbl[anglevar] - 50 rem ==================== rem COLLISION DETECTION rem === thanks to bogax === rem ==================== 700 rem check to see if player 1 is out of bounds if player1x = 25 || player1y = 0 then goto 750 if player1x=133 || player1y = 140 then goto 750 rem minimum collision data locations (x, y) data btbl 78, 4, 109, 12, 125, 44, 109, 76, 77, 84, 45, 76, 29, 44, 45, 12 end rem check each of the 8 possible collision locations for temp4 = 0 to 14 step 2 temp3 = temp4 + 1 rem set up temporary variables to contain the full range of the x and y potentials temp5 = btbl[temp4] + 4 temp6 = btbl[temp3] + 8 rem if player1x is within the range for the current block and player1y is within the range for the current block, there is a collision if player1x > btbl[temp4] && player1x < temp5 && player1y > btbl[temp3] && player1y < temp6 then goto 710 rem otherwise, check the next block next rem if no collision is detected, skip to the end of the main loop goto 800 rem check for collision type 710 rem check if the block is already dead if a[temp4] = 2 then goto 800 rem check ball color against block color if a[temp4]<>ballcolor then goto bad_hit rem if the hit is good... good_hit rem set current block to dead a[temp4] = 2 rem increment score score = score + 25 rem play good hit sound AUDV1 = 6 AUDC1 = 12 AUDF1 = 19 goto 725 rem if the hit is bad... bad_hit rem lose a life lives = lives - 1 rem play bad hit sound AUDV1 = 6 AUDC1 = 6 AUDF1 = 16 rem reset sound cooldown counter 725 if lives > 0 then cooldown = 0 else cooldown = 50: pulse = 0 750 rem reset player 1 location, unlocking player 0 fire player1x = 0: player1y = 0 rem ================== rem STAGE GENERATION rem ================== 760 rem exits title screen and generates a new stage if joy0fire && lives = 0 && cooldown < 50 then score = 0: pulse = 0: cooldown = 50: level = 0: goto 775 rem cycles through blocks to check if all have been destroyed temp2 = 0 for temp1 = 0 to 15 if a[temp1] = 2 && lives > 0 then temp2 = temp2 + 1 next rem if not, then end cycle if temp2 <> 16 then goto 800 rem if so, then score bonus points for completing stage and continue if lives = 3 then score = score + 600 if lives = 2 then score = score + 400 if lives = 1 then score = score + 200 rem increment the level counter, but make sure it doesn't go too high if level < 10 then level = level + 1 rem generates new stage by looping through and inserting new colors taken from data set under COLOR FLICKER 775 rem different values for different levels if level = 0 then goto 776 if level = 1 then goto 777 else goto 780 776 rem first level has only red blocks, to teach basic mechanics of firing a ball and rotating blocks for temp1 = 0 to 15 a[temp1] = blkc[0] next goto 799 777 rem second level teaches the differences between the colors and how the right color must go to the right ball for temp1 = 0 to 15 temp2 = (rand/64) if temp2 < 2 then a[temp1] = blkc[1] else a[temp1] = blkc[0] next goto 799 780 rem third level introduces all three primary colors for temp1 = 0 to 15 temp2 = rand if temp2 < 86 then a[temp1] = blkc[0] if temp2 > 85 then a[temp1] = blkc[1] if temp2 > 170 then a[temp1] = blkc[2] next 799 rem complete reset by giving full lives lives = 3 rem end loop 800 set debug cyclescore goto draw_loop I'd show you a video, but FRAPS can't capture it right. It's just too messed up. P.S. Sorry if I have a bit of attitude in the above. I'm very, very frustrated by this, particularly since I feel like I'm just spinning my wheels as I wait for someone to make an improved kernel. I don't know how that improved kernel would work, what sort of system flow it would require, or if anyone is even working on it. heartbreak.bas heartbreak.bas.bin
  9. Egh. Tried fiddling with what you offered there, bogax, and while it does make the movement work just fine, the hit detection is completely buggered by the change. Anyone have any further suggestions about my primary kernel problem? EDIT: And I still can't figure out what's going wrong here: rem set up possible colors data blkc 64, 28, 154, 44, 202, 122, 14, 0 end rem set up possible pfpixel locations data ctbl 16, 20, 24, 27, 28, 27, 24, 20, 16, 12, 8, 5, 4, 5, 8, 12 end data rtbl 0, 0, 1, 3, 5, 7, 9, 10, 10, 10, 9, 7, 5, 3, 1, 0 end 110 rem cycle through pfpixels, turning them on if they are equal to the color being drawn if flicker = 8 then flicker = 0 for temp5 = 0 to 15 if a[temp5] = blkc[flicker] then pfpixel ctbl[temp5] rtbl[temp5] on: temp4 = 1 next rem determines if a color shows up; if not, don't bother drawing that color and return for the next if temp4 = 0 then flicker = flicker + 1: goto 110 else COLUPF = blkc[flicker]: flicker = flicker + 1 rem ================== rem MAIN DRAWSCREEN rem ================== rem main drawscreen drawscreen Here's what I think it should be doing (let's assume it's a level with only red, 64, and yellow, 28): 1. Since all variables initialize at 0, flicker begins at 0 2. Since flicker is != 8, flicker is not affected by the first if statement 3. A temporary variable (temp5) starts a loop, initializing itself at 0 4. The first block in the ring (a[0]) is checked to see if it conforms with the first color in the data set (blkc[0]) -- let's say that it does match 5. A pfpixel corresponding to location 0 is drawn for the block and temp4 is set to 1 6. The loop continues, finding some yellow blocks that aren't drawn and some red blocks that are drawn 7. Since temp4 != 0, COLUPF is set to blkc[0] (64, red) and flicker is incremented 8. The cycle repeats for yellow (in the next main_loop cycle, after a drawscreen and pfclear), where temp4 gets set to 1 again because a[something] = blkc[1] (28, yellow), so pfpixels are drawn, the "if temp4 = 0" check is passed, and COLUPF = blkc[flicker] and flicker is incremented. 9. This time through the main loop, flicker = 2, and since there are no blue blocks in this particular theoretical randomization, temp4 should remain 1, which triggers the "if temp4 = 0" check, which increments flicker and sends back for another loop through, this time checking for flicker = 3, and so it continues until flicker = 8, whereupon flicker = 0 and the cycle continues at red. In theory, this should only flicker between colors that are actually represented in the playfield. A field with all red blocks should be completely solid because there should never be a cycle where a playfield is rendered with fewer than all of the blocks being red. Similarly, if the playfield consists of half red and half blue, then all the blue blocks are killed by the player, the playfield should become solid red because the above loop would not have any other colors to trip the temp4 = 1 check and get drawn. Instead, it continues to flicker as always, even when all playfield blocks are red. I cannot understand why. rem Generated 1/28/2013 1:50:36 PM by Visual bB Version 1.0.0.548 rem ********************************** rem *heartbreak.bin * rem *A re-imagning of breakout with a lonely heart trapped in a void... * rem *Cybearg (aka Nic) * rem *cybearg.plays@gmail.com * rem ********************************** rem ============== rem INITIALIZATION rem ============== rem set up settings/optimization set optimization speed rem set up my variables dim level = s dim cooldown=t dim anglevar=u dim pulse=v dim flicker=w dim offset=x dim ballcolor=y dim heartcolor=z rem set offset to a number greater than 0 to allow for "negative" values offset = 50 rem set heartcolor to begin at red heartcolor = 64 rem set player 0's location player0x=80:player0y=48 rem ========== rem MAIN LOOP rem ========== draw_loop rem clear the playfield pfclear rem increment the multi-purpose cooldown variable cooldown = cooldown + 1 rem mute sound at 7 cooldown cycles or after 20 cycles if there's been a titlescreen restart if cooldown = 7 || cooldown = 70 then AUDV0 = 0 : AUDV1 = 0 rem =============== rem BEATING HEART rem =============== rem increment pulse counter pulse = pulse +1 rem cooldown to make sure that player doesn't leave the title screen by firing a ball if pulse = 45 && cooldown >= 50 then cooldown = 0 rem after 45 cycles, increment color if pulse = 45 then pulse = 0 rem special occasion for first level if level = 0 then heartcolor = 64: goto 10 rem special occasion for second level if level = 1 && heartcolor = 64 && pulse = 0 then heartcolor = 28: goto 10 if level = 1 && heartcolor = 28 && pulse = 0 then heartcolor = 64: goto 10 rem increment the colors if heartcolor = 28 && pulse = 0 then heartcolor = 148: goto 10 if heartcolor = 64 && pulse = 0 then heartcolor = 28: goto 10 if heartcolor = 148 && pulse = 0 then heartcolor = 64 10 rem set the playfield colors COLUP0 = heartcolor rem turn the score red if player is on the last life if lives = 1 then scorecolor = 64 else scorecolor = 10 rem swap the heart sprite for 5 cycles to create illusion of beating if pulse < 40 then goto 40 else goto 44 rem values for the up-beat (40 out of 45 cycles) 40 if lives = 0 then goto 80 41 if lives = 1 then goto 70 42 if lives = 2 then goto 60 43 if lives = 3 then goto 50 rem values for the down-beat (5 out of 45 cycles) 44 if lives = 0 then goto 80 45 if lives = 1 then goto 90 46 if lives = 2 then goto 70 47 if lives = 3 then goto 60 rem the various player 0 heart sprites 50 player0: %00010000 %00111000 %01111100 %11111110 %11111110 %11111110 %01101100 %00000000 end 55 goto 100 60 player0: %00000000 %00010000 %00111000 %01111100 %01111100 %00101000 %00000000 %00000000 end 65 goto 100 70 player0: %00000000 %00000000 %00010000 %00111000 %00101000 %00000000 %00000000 %00000000 end 75 goto 100 80 90 player0: %00000000 %00000000 %00000000 %00000000 %00000000 %00000000 %00000000 %00000000 end rem ============== rem COLOR FLICKER rem ============== 100 rem if the player has zero lives, skip this part if lives = 0 then goto 410 rem set up possible colors data blkc 64, 28, 154, 44, 202, 122, 14, 0 end rem set up possible pfpixel locations data ctbl 16, 20, 24, 27, 28, 27, 24, 20, 16, 12, 8, 5, 4, 5, 8, 12 end data rtbl 0, 0, 1, 3, 5, 7, 9, 10, 10, 10, 9, 7, 5, 3, 1, 0 end 110 rem cycle through pfpixels, turning them on if they are equal to the color being drawn if flicker = 8 then flicker = 0 for temp5 = 0 to 15 if a[temp5] = blkc[flicker] then pfpixel ctbl[temp5] rtbl[temp5] on: temp4 = 1 next rem determines if a color shows up; if not, don't bother drawing that color and return for the next if temp4 = 0 then flicker = flicker + 1: goto 110 else COLUPF = blkc[flicker]: flicker = flicker + 1 rem ================== rem MAIN DRAWSCREEN rem ================== rem main drawscreen drawscreen rem skip to COLOR MOVEMENT goto 415 rem ============= rem TITLE SCREEN rem ============= 410 rem set the beat of the title screen heart to the ongoing pulse if pulse < 40 then goto 413 else goto 412 rem the two possible title screen frames 412 playfield: ................................ ...X.X.XXX..X..XX.XXX........... ...X.X.X...X.X.X.X.X............ ...XXX.XX..XXX.XX..X............ ...X.X.XXX.X.X.X.X.X............ .............................. ...........XX..XX..XXX..X..X.X.. ....X.X....X.X.X.X.X...X.X.X.X.. ....XXX....XX..XX..XX..XXX.XX... .....X.....X.X.X.X.XXX.X.X.X.X.. ...........XXX.................. end rem skip to color goto 414 413 playfield: ................................ ...X.X.XXX..X..XX.XXX........... ...X.X.X...X.X.X.X.X............ ...XXX.XX..XXX.XX..X............ ...X.X.XXX.X.X.X.X.X............ ................................ ...XX.XX...XX..XX..XXX..X..X.X.. ..XXXXXXX..X.X.X.X.X...X.X.X.X.. ...XXXXX...XX..XX..XX..XXX.XX... ....XXX....X.X.X.X.XXX.X.X.X.X.. .....X.....XXX.................. end 414 rem color the title screen playfield COLUPF = 64 rem drawscreen for titlescreen only drawscreen rem skip everything else and wait for a trigger goto 760 rem ================= rem COLOR MOVEMENT rem ================= 415 rem NOTE: offset base is 50, so the numbers below determine how sensitive the controls are rem determine block offset if joy0left && offset < 56 then offset = offset + 1 if joy0right && offset > 44 then offset = offset - 1 rem adjust block offset 420 if offset > 55 goto 435 if offset < 45 goto 445 rem if no adjustments are necessary, skip this part goto 500 rem move all block values to the left (counter clockwise) 435 temp2 = a for temp1 = 0 to 14 a[temp1] = b[temp1] next p = temp2 goto 450 rem move all blocks to the right (clockwise) 445 temp2 = p for temp1 = 15 to 0 step -1 b[temp1] = a[temp1] next a = temp2 rem reset the offset 450 offset = 50 rem ============ rem PLAYER FIRE rem ============ 500 rem checks to see that a few cool-down measures are a go, then moves the ball (player 1) to the center of the heart (player 0) rem cooldown ensures that the player cannot fire while a ball is at play rem cooldown also ensures the player doesn't exit a title screen by firing a ball prematurely if joy0fire && lives > 0 && player1x = 0 && player1y = 0 && cooldown < 50 then player1x=80:player1y=48 else goto 600 rem moves the ball's current color from heartcolor (set in the BEATING HEART section) to ballcolor for safe-keeping ballcolor = heartcolor rem set player 1's sprite player1: %00000000 %00000000 %00000000 %00011000 %00011000 %00000000 %00000000 %00000000 end rem generate random number to determine ball movement rem variables ensure that ball speed/angle does not vary once ball has been generated anglevar = (rand/32) rem ========= rem THE BALL rem ========= 600 rem skip everything dealing with the ball if it is at its resting position (0,0) if player1x = 0 && player1y = 0 then goto 800 rem maintain the color of the ball at the moment of firing COLUP1 = ballcolor rem all ball movement possibilities rem allows for ball movement in a direction every 45 degrees 650 rem cooldown is used to manage the speed of the ball if cooldown > 8 then cooldown = 0 rem x motion table data xmtbl 50, 51, 51, 51, 50, 49, 49, 49 end rem y motion table data ymtbl 51, 51, 50, 49, 49, 49, 50, 51 end rem separate out cardinal from diagonal directions if anglevar <> 0 && anglevar <> 2 && anglevar <> 4 && anglevar <> 6 then goto 670 else goto 680 670 rem movements for diagonal directions (45, 125, 225, 315) -- applies a cooldown to ensure that diagonals do not move too fast if cooldown <> 1 && cooldown <> 3 && cooldown <> 5 && cooldown <> 7 then player1x = player1x + xmtbl[anglevar] - 50: player1y = player1y + ymtbl[anglevar] - 50: goto 700 else goto 700 680 rem movement values for cardinal (0, 90, 180, 270 degrees) directions -- applies a cooldown to ensure that cardinal directions do not move too fast if cooldown <> 3 && cooldown <> 7 then player1x = player1x + xmtbl[anglevar] - 50 if cooldown <> 3 && cooldown <> 7 then player1y = player1y + ymtbl[anglevar] - 50 rem ==================== rem COLLISION DETECTION rem === thanks to bogax === rem ==================== 700 rem check to see if player 1 is out of bounds if player1x = 25 || player1y = 0 then goto 750 if player1x=133 || player1y = 140 then goto 750 rem minimum collision data locations (x, y) data btbl 78, 4, 109, 12, 125, 44, 109, 76, 77, 84, 45, 76, 29, 44, 45, 12 end rem check each of the 8 possible collision locations for temp4 = 0 to 14 step 2 temp3 = temp4 + 1 rem set up temporary variables to contain the full range of the x and y potentials temp5 = btbl[temp4] + 4 temp6 = btbl[temp3] + 8 rem if player1x is within the range for the current block and player1y is within the range for the current block, there is a collision if player1x > btbl[temp4] && player1x < temp5 && player1y > btbl[temp3] && player1y < temp6 then goto 710 rem otherwise, check the next block next rem if no collision is detected, skip to the end of the main loop goto 800 rem check for collision type 710 rem check if the block is already dead if a[temp4] = 2 then goto 800 rem check ball color against block color if a[temp4]<>ballcolor then goto bad_hit rem if the hit is good... good_hit rem set current block to dead a[temp4] = 2 rem increment score score = score + 25 rem play good hit sound AUDV1 = 6 AUDC1 = 12 AUDF1 = 19 goto 725 rem if the hit is bad... bad_hit rem lose a life lives = lives - 1 rem play bad hit sound AUDV1 = 6 AUDC1 = 6 AUDF1 = 16 rem reset sound cooldown counter 725 if lives > 0 then cooldown = 0 else cooldown = 50: pulse = 0 750 rem reset player 1 location, unlocking player 0 fire player1x = 0: player1y = 0 rem ================== rem STAGE GENERATION rem ================== 760 rem exits title screen and generates a new stage if joy0fire && lives = 0 && cooldown < 50 then score = 0: pulse = 0: cooldown = 50: level = 0: goto 775 rem cycles through blocks to check if all have been destroyed temp2 = 0 for temp1 = 0 to 15 if a[temp1] = 2 && lives > 0 then temp2 = temp2 + 1 next rem if not, then end cycle if temp2 <> 16 then goto 800 rem if so, then score bonus points for completing stage and continue if lives = 3 then score = score + 600 if lives = 2 then score = score + 400 if lives = 1 then score = score + 200 rem increment the level counter, but make sure it doesn't go too high if level < 10 then level = level + 1 rem generates new stage by looping through and inserting new colors taken from data set under COLOR FLICKER 775 rem different values for different levels if level = 0 then goto 776 if level = 1 then goto 777 else goto 780 776 rem first level has only red blocks, to teach basic mechanics of firing a ball and rotating blocks for temp1 = 0 to 15 a[temp1] = blkc[0] next goto 799 777 rem second level teaches the differences between the colors and how the right color must go to the right ball for temp1 = 0 to 15 temp2 = (rand/64) if temp2 < 2 then a[temp1] = blkc[1] else a[temp1] = blkc[0] next goto 799 780 rem third level introduces all three primary colors for temp1 = 0 to 15 temp2 = rand if temp2 < 86 then a[temp1] = blkc[0] if temp2 > 85 then a[temp1] = blkc[1] if temp2 > 170 then a[temp1] = blkc[2] next 799 rem complete reset by giving full lives lives = 3 rem end loop 800 set debug cyclescore goto draw_loop heartbreak.bas heartbreak.bas.bin
  10. I tried kind of what you suggested, Andrew, but I can't get it to work. What you wrote precisely just causes the program to do nothing, and since I don't really understand what a[temp1] = a[(temp1+1)&15] does, I can't do much to fix it. I did try keeping the spirit of the suggestion with something like this: rem cycle through pfpixels, turning them on if they are equal to the color being drawn for temp5 = 0 to 15 rem adjust block offset if offset > 55 then temp6 = (temp5 + 1) if offset < 45 then temp6 = (temp5 - 1) else temp6 = temp5 if a[temp6] = blkc[flicker] then pfpixel ctbl[temp6] rtbl[temp6] on next I see your point, though I don't think that it will work with the way the code is currently set up. More than just the visual colors are dependent on the location in the array: the coordinates of each pfpixel is tied to a location in the array which I depend on when determining which color each pfpixel is, so a[0] needs to correspond to ctbl[0] and rtbl[0]. I'm not sure that a single variable is sufficient for carrying that offset in addition to performing the cooldown function (to ensure that the ring rotation isn't per-pixel sensitive), and I'm really not quite sure how it would work at all without the ability for variable values to go into the negatives.
  11. Yeah, it's an honor! Thanks, Andrew! I feel foolish for not having thought of it. It's still certainly relevant, so I'm going to try implementing that now. It'll surely save a number of cycles. What I'm trying to crunch at the moment is a way for the flickering set-up to dynamically adjust to serve however many colors are in the array at a time, but it just isn't working. rem set up possible colors data blkc 64, 28, 154, 44, 202, 122, 14, 0 end rem set up possible pfpixel locations data ctbl 16, 20, 24, 27, 28, 27, 24, 20, 16, 12, 8, 5, 4, 5, 8, 12 end data rtbl 0, 0, 1, 3, 5, 7, 9, 10, 10, 10, 9, 7, 5, 3, 1, 0 end 110 rem cycle through pfpixels, turning them on if they are equal to the color being drawn if flicker = 8 then flicker = 0 for temp5 = 0 to 15 if a[temp5] = blkc[flicker] then pfpixel ctbl[temp5] rtbl[temp5] on: temp4 = 1 next rem determines if a color shows up; if not, don't bother drawing that color and return for the next if temp4 = 0 then flicker = flicker + 1: goto 110 else COLUPF = blkc[flicker] rem ================== rem MAIN DRAWSCREEN rem ================== rem main drawscreen drawscreen Even though this makes sense to me in my head, it doesn't seem to work correctly. I'm probably just overlooking something painfully obvious.
  12. Thanks much for all the advice! I hadn't thought to combine the data sets (though it only saved me about 10 bytes, but still!) and I didn't know that you could do a[temp1+1] with b[temp1]. though it makes sense in hindsight. That's pretty awesome. It occurs to me that I haven't posted the code in a while. I'm always open to input to make things more efficient, and maybe it will help in developing that kernel (hope that everyone hasn't forgotten ). rem Generated 1/28/2013 1:50:36 PM by Visual bB Version 1.0.0.548 rem ********************************** rem *heartbreak.bin * rem *A re-imagning of breakout with a lonely heart trapped in a void... * rem *Cybearg (aka Nic) * rem *cybearg.plays@gmail.com * rem ********************************** rem ============== rem INITIALIZATION rem ============== rem set up settings/optimization set optimization speed rem set up my variables dim level = s dim cooldown=t dim anglevar=u dim pulse=v dim flicker=w dim offset=x dim ballcolor=y dim heartcolor=z rem set offset to a number greater than 0 to allow for "negative" values offset = 50 rem set heartcolor to begin at red heartcolor = 64 rem set player 0's location player0x=80:player0y=48 rem ========== rem MAIN LOOP rem ========== draw_loop rem clear the playfield pfclear rem increment the multi-purpose cooldown variable cooldown = cooldown + 1 rem mute sound at 7 cooldown cycles or after 20 cycles if there's been a titlescreen restart if cooldown = 7 || cooldown = 70 then AUDV0 = 0 : AUDV1 = 0 rem =============== rem BEATING HEART rem =============== rem increment pulse counter pulse = pulse +1 rem cooldown to make sure that player doesn't leave the title screen by firing a ball if pulse = 45 && cooldown >= 50 then cooldown = 0 rem after 45 cycles, increment color if pulse = 45 then pulse = 0 rem special occasion for first level if level = 0 then heartcolor = 64: goto 10 rem special occasion for second level if level = 1 && heartcolor = 64 && pulse = 0 then heartcolor = 28: goto 10 if level = 1 && heartcolor = 28 && pulse = 0 then heartcolor = 64: goto 10 rem increment the colors if heartcolor = 28 && pulse = 0 then heartcolor = 148: goto 10 if heartcolor = 64 && pulse = 0 then heartcolor = 28: goto 10 if heartcolor = 148 && pulse = 0 then heartcolor = 64 10 rem set the playfield colors COLUP0 = heartcolor rem turn the score red if player is on the last life if lives = 1 then scorecolor = 64 else scorecolor = 10 rem swap the heart sprite for 5 cycles to create illusion of beating if pulse < 40 then goto 40 else goto 44 rem values for the up-beat (40 out of 45 cycles) 40 if lives = 0 then goto 80 41 if lives = 1 then goto 70 42 if lives = 2 then goto 60 43 if lives = 3 then goto 50 rem values for the down-beat (5 out of 45 cycles) 44 if lives = 0 then goto 80 45 if lives = 1 then goto 90 46 if lives = 2 then goto 70 47 if lives = 3 then goto 60 rem the various player 0 heart sprites 50 player0: %00010000 %00111000 %01111100 %11111110 %11111110 %11111110 %01101100 %00000000 end 55 goto 100 60 player0: %00000000 %00010000 %00111000 %01111100 %01111100 %00101000 %00000000 %00000000 end 65 goto 100 70 player0: %00000000 %00000000 %00010000 %00111000 %00101000 %00000000 %00000000 %00000000 end 75 goto 100 80 90 player0: %00000000 %00000000 %00000000 %00000000 %00000000 %00000000 %00000000 %00000000 end rem ============== rem COLOR FLICKER rem ============== 100 rem if the player has zero lives, skip this part if lives = 0 then goto 410 rem set up possible colors data blkc 64, 28, 148 end rem set up possible pfpixel locations data ctbl 16, 20, 24, 27, 28, 27, 24, 20, 16, 12, 8, 5, 4, 5, 8, 12 end data rtbl 0, 0, 1, 3, 5, 7, 9, 10, 10, 10, 9, 7, 5, 3, 1, 0 end rem cycle through pfpixels, turning them on if they are equal to the color being drawn for temp5 = 0 to 15 if a[temp5] = blkc[flicker] then pfpixel ctbl[temp5] rtbl[temp5] on next rem set playfield to current color COLUPF = blkc[flicker] rem increment flicker temp1 = blkc_length + 1 if flicker = temp1 then flicker = 0 else flicker = flicker + 1 rem ================== rem MAIN DRAWSCREEN rem ================== rem main drawscreen drawscreen rem skip to COLOR MOVEMENT goto 415 rem ============= rem TITLE SCREEN rem ============= 410 rem set the beat of the title screen heart to the ongoing pulse if pulse < 40 then goto 413 else goto 412 rem the two possible title screen frames 412 playfield: ................................ ...X.X.XXX..X..XX.XXX........... ...X.X.X...X.X.X.X.X............ ...XXX.XX..XXX.XX..X............ ...X.X.XXX.X.X.X.X.X............ .............................. ...........XX..XX..XXX..X..X.X.. ....X.X....X.X.X.X.X...X.X.X.X.. ....XXX....XX..XX..XX..XXX.XX... .....X.....X.X.X.X.XXX.X.X.X.X.. ...........XXX.................. end rem skip to color goto 414 413 playfield: ................................ ...X.X.XXX..X..XX.XXX........... ...X.X.X...X.X.X.X.X............ ...XXX.XX..XXX.XX..X............ ...X.X.XXX.X.X.X.X.X............ ................................ ...XX.XX...XX..XX..XXX..X..X.X.. ..XXXXXXX..X.X.X.X.X...X.X.X.X.. ...XXXXX...XX..XX..XX..XXX.XX... ....XXX....X.X.X.X.XXX.X.X.X.X.. .....X.....XXX.................. end 414 rem color the title screen playfield COLUPF = 64 rem drawscreen for titlescreen only drawscreen rem skip everything else and wait for a trigger goto 760 rem ================= rem COLOR MOVEMENT rem ================= 415 rem NOTE: offset base is 50, so the numbers below determine how sensitive the controls are rem determine block offset if joy0left && offset < 56 then offset = offset + 1 if joy0right && offset > 44 then offset = offset - 1 rem adjust block offset 420 if offset > 55 goto 435 if offset < 45 goto 445 rem if no adjustments are necessary, skip this part goto 500 rem move all block values to the left (counter clockwise) 435 temp2 = a for temp1 = 0 to 14 a[temp1] = b[temp1] next p = temp2 goto 450 rem move all blocks to the right (clockwise) 445 temp2 = p for temp1 = 15 to 0 step -1 b[temp1] = a[temp1] next a = temp2 rem reset the offset 450 offset = 50 rem ============ rem PLAYER FIRE rem ============ 500 rem checks to see that a few cool-down measures are a go, then moves the ball (player 1) to the center of the heart (player 0) rem cooldown ensures that the player cannot fire while a ball is at play rem cooldown also ensures the player doesn't exit a title screen by firing a ball prematurely if joy0fire && lives > 0 && player1x = 0 && player1y = 0 && cooldown < 50 then player1x=80:player1y=48 else goto 600 rem moves the ball's current color from heartcolor (set in the BEATING HEART section) to ballcolor for safe-keeping ballcolor = heartcolor rem set player 1's sprite player1: %00000000 %00000000 %00000000 %00011000 %00011000 %00000000 %00000000 %00000000 end rem generate random number to determine ball movement rem variables ensure that ball speed/angle does not vary once ball has been generated anglevar = (rand/32) rem ========= rem THE BALL rem ========= 600 rem skip everything dealing with the ball if it is at its resting position (0,0) if player1x = 0 && player1y = 0 then goto 800 rem maintain the color of the ball at the moment of firing COLUP1 = ballcolor rem all ball movement possibilities rem allows for ball movement in a direction every 45 degrees 650 rem cooldown is used to manage the speed of the ball if cooldown > 8 then cooldown = 0 rem x motion table data xmtbl 50, 51, 51, 51, 50, 49, 49, 49 end rem y motion table data ymtbl 51, 51, 50, 49, 49, 49, 50, 51 end rem separate out cardinal from diagonal directions if anglevar <> 0 && anglevar <> 2 && anglevar <> 4 && anglevar <> 6 then goto 670 else goto 680 670 rem movements for diagonal directions (45, 125, 225, 315) -- applies a cooldown to ensure that diagonals do not move too fast if cooldown <> 1 && cooldown <> 3 && cooldown <> 5 && cooldown <> 7 then player1x = player1x + xmtbl[anglevar] - 50: player1y = player1y + ymtbl[anglevar] - 50: goto 700 else goto 700 680 rem movement values for cardinal (0, 90, 180, 270 degrees) directions -- applies a cooldown to ensure that cardinal directions do not move too fast if cooldown <> 3 && cooldown <> 7 then player1x = player1x + xmtbl[anglevar] - 50 if cooldown <> 3 && cooldown <> 7 then player1y = player1y + ymtbl[anglevar] - 50 rem ==================== rem COLLISION DETECTION rem === thanks to bogax === rem ==================== 700 rem check to see if player 1 is out of bounds if player1x = 25 || player1y = 0 then goto 750 if player1x=133 || player1y = 140 then goto 750 rem minimum collision data locations (x, y) data btbl 78, 4, 109, 12, 125, 44, 109, 76, 77, 84, 45, 76, 29, 44, 45, 12 end rem check each of the 8 possible collision locations for temp4 = 0 to 14 step 2 temp3 = temp4 + 1 rem set up temporary variables to contain the full range of the x and y potentials temp5 = btbl[temp4] + 4 temp6 = btbl[temp3] + 8 rem if player1x is within the range for the current block and player1y is within the range for the current block, there is a collision if player1x > btbl[temp4] && player1x < temp5 && player1y > btbl[temp3] && player1y < temp6 then goto 710 rem otherwise, check the next block next rem if no collision is detected, skip to the end of the main loop goto 800 rem check for collision type 710 rem check if the block is already dead if a[temp4] = 0 then goto 800 rem check ball color against block color if a[temp4]<>ballcolor then goto bad_hit rem if the hit is good... good_hit rem set current block to dead a[temp4] = 0 rem increment score score = score + 25 rem play good hit sound AUDV1 = 6 AUDC1 = 12 AUDF1 = 19 goto 725 rem if the hit is bad... bad_hit rem lose a life lives = lives - 1 rem play bad hit sound AUDV1 = 6 AUDC1 = 6 AUDF1 = 16 rem reset sound cooldown counter 725 if lives > 0 then cooldown = 0 else cooldown = 50: pulse = 0 750 rem reset player 1 location, unlocking player 0 fire player1x = 0: player1y = 0 rem ================== rem STAGE GENERATION rem ================== 760 rem exits title screen and generates a new stage if joy0fire && lives = 0 && cooldown < 50 then score = 0: pulse = 0: cooldown = 50: level = 0: goto 775 rem cycles through blocks to check if all have been destroyed temp2 = 0 for temp1 = 0 to 15 if a[temp1] = 0 && lives > 0 then temp2 = temp2 + 1 next rem if not, then end cycle if temp2 <> 16 then goto 800 rem if so, then score bonus points for completing stage and continue if lives = 3 then score = score + 600 if lives = 2 then score = score + 400 if lives = 1 then score = score + 200 rem increment the level counter, but make sure it doesn't go too high if level < 10 then level = level + 1 rem generates new stage by looping through and inserting new colors taken from data set under COLOR FLICKER 775 rem different values for different levels if level = 0 then goto 776 if level = 1 then goto 777 else goto 780 776 rem first level has only red blocks, to teach basic mechanics of firing a ball and rotating blocks for temp1 = 0 to 15 a[temp1] = blkc[0] next goto 799 777 rem second level teaches the differences between the colors and how the right color must go to the right ball for temp1 = 0 to 15 temp2 = (rand/64) if temp2 < 2 then a[temp1] = blkc[1] else a[temp1] = blkc[0] next goto 799 780 rem third level introduces all three primary colors for temp1 = 0 to 15 temp2 = rand if temp2 < 86 then a[temp1] = blkc[0] if temp2 > 85 then a[temp1] = blkc[1] if temp2 > 170 then a[temp1] = blkc[2] next 799 rem complete reset by giving full lives lives = 3 rem end loop 800 goto draw_loop heartbreak.bas Current remaining resources: 1234 bytes and 2 variables Note that the way that the colors flicker will likely have to be changed for whatever the kernel ends up being and I intend to have a number of extra pre-set level types to introduce new colors, but I haven't programmed them in because everything relies on the flickering.
  13. Has anyone had any luck devising (or does anyone know of) a kernel that will allow what I want to happen to happen? How will the code have to change once this is in place? I assume I won't continue to drawscreen every three cycles to change colors and will instead have a color per drawscreen, right? Any idea how that would need to look, so I can work on setting up the code to work for it in the meanwhile?
  14. Okay, everything seems to work now. I installed the latest version of Visual bB (with updates) from here, the latest version of bB from here, the latest version of DASM from here, sed.exe from here (it's included in the 1.0 bB package), and the 64-bit fix from here. All seems fine on all fronts now!
  15. Okay, I went through and got rid of all my old stuff. The new VisualbB and bB DO work for the above issues, except that my current game won't compile due to "complexity." I'll send you a PM with the code if you have a chance to look it over and let me know what's up, Random.
  16. It's really confusing. To some degree, I must be doing it wrong, but there also seems to be some problems afoot. For instance, the bankswitching demo works with my bB 1.0, which means that it must work, but if I set romsize 8k on my game and set up a bank 2 area at the bottom of the code, compiling causes postprocess.exe to crash and I get a bunch of errors spit out at me: DASM V2.20.07, Macro Assembler ©1988-2003 --- Unresolved Symbol List pfcenter 0000 ???? (R ) drawscreen 0000 ???? (R ) pfpixel 0000 ???? (R ) 0.800 0000 ???? (R ) player50_0 0000 ???? (R ) player70_0 0000 ???? (R ) player60_0 0000 ???? (R ) player90_0 0000 ???? (R ) pfhalfwidth 0000 ???? (R ) playerL0139_1 0000 ???? (R ) randomize 0000 ???? (R ) pfclear 0000 ???? (R ) BS_jsr 0000 ???? (R ) Fatal assembly error: Source is not resolvable. Errors were encountered during assembly. Can someone suggest a test I could do to see if pfheights is working or not? Could you please point me to all the files for your version of Visual bB/bB/DASM/etc.? Maybe I've got mismatched versions or something.
  17. True, though having added some more, it didn't seem to help a great deal. rem generated 2/3/2013 10:20:19 PM by Visualdb Project Wizard Version 1.0.0.3 rem ********************************** rem *<filename> * rem *<description> * rem *<author> * rem *<contact info> * rem *<license> * rem ********************************** set kernel_options playercolors player1colors pfcolors pfheights set tv ntsc set romsize 8k player0color: $f5 $f5 $f5 $43 $f5 end player1color: $f5 $f5 $f5 $43 $f5 end pfheights: 8 8 15 1 8 8 8 8 8 8 8 end player0: %00100010 %00010100 %00011000 %01011000 %00111100 %00011010 %00000000 %00011000 end main_loop playfield: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX X..............................X X...XXXXX.XXX.XXXXX.X....XXXX..X X.....X....X....X...X....X.....X X.....X....X....X...X....X.....X X.....X....X....X...X....XXX...X X.....X....X....X...X....X.....X X.....X....X....X...X....X.....X X.....X...XXX...X...XXXX.XXXX..X X..............................X XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX end pfcolors: $f5 $f5 $f5 $43 $f5 $f5 $f5 $f5 $f5 $f5 $f5 end drawscreen goto main_loop I reverted my stuff to bB 1.0 and then to the Win 64 release of it. Let's start there, I suppose. Trying the set romsize 8k doesn't work, which is worrying because it severely limits what games can be made. Any idea what's wrong?
  18. Alright, so while that other game I'm working on is stewing, I'm thinking about what to do next. I had planned to at least experiment with ROM sizes above 4K and some broader kernel options, but I've hit kind of a snag. If I use the old version of bB (by "old" I mean the one suggested for Win 64-bit systems on the Visual bB thead), kernel_options like playercolors, pfheights, etc. or things like set romsize 8k cause the compiler to crash. The following causes postprocess.exe to crash: set kernel_options playercolors player1colors pfcolors pfheights set tv ntsc set romsize 8k main_loop drawscreen goto main_loop Which, in my mind anyway, has no good reason to crash. If I upgrade to the latest bB version, my other game gets the crashes due to some error about complexity. Is there kind of a middle ground that will allow me to do both, or do I have to either not use romsizes over 4k/kernel options or be able to continue working on my introduction project? EDIT: Well, I just tried upgrading again to recall what the exact error was with my current project and it seems the new one isn't any better--even with the latest bB, it crashes if the romsize or kernel options are set. Anyone have a suggestion as to what the problem is? Keep in mind that, with the latest versions, my current project also gets a "could not recompile" error with the message being: 2600 Basic compilation failed! LINE --> complex condition detected ... But with no specific mention of which line is causing the error. The error message claims a syntax error at line 0, column 66, but that's just a lie since that's a simple rem statement that's been there the whole time and has nothing wrong with it. So my questions are twofold: 1. Why can't I set kernel options or a higher rom size without compiling errors? 2. Why does the new bB have problems with my existing code that worked perfectly on build 554?
  19. True, but if I was using player 1 and player 0 together to create a megasprite, that would require them to share the same colors in order to make it work, which in turn wouldn't work when missile1 swapped colors to match.
  20. The problem with using missile 1 or missile 0 is that they take on the colors of their sprites. I need the "projectile" to take on the color of player0 (the heart) at the moment of joy0fire and retain that color (and have it stored somewhere that can be read, since it's important for collision detection), which is what currently happens. If I have to trim out some of the intricacies of the original gameplay design, that's alright so long as what remains works well.
  21. Ahh, right. I guess that those links I saw in red didn't register as being relevant, for whatever reason. I'll have to stick with the old since the new one gets some kind of complexity error when compiling. Ah, well.
  22. I don't see why my version didn't work, then. Somewhere (not on that page that was linked), I found a bB 1.01 which was build 566 or something, while the VisualbB post only mentions a 1.0 up to build 554. What's up with that?
  23. My biggest worry is getting this to work without flicker. Adding more rings would be neat, but my biggest worry is getting it to not give people seizures. I don't know anything close to the know-how to create a new kernel or whatever must be done, so I'm pretty much sitting on my hands until someone pops out a genie of a solution. Additionally, a variable is set aside to remember the color in each of the current 16 positions, so adding more is essentially out of the question unless I use a superchip RAM, which I hesitate to do because I'd love the game to all be perfectly packed in your average 4K 6400 cartridge. Doesn't increasing the player size just widen the sprite, though? It doesn't make it any taller, so it would just look like someone stomped on the sprite, rather than like the whole heart was larger, no? Also, I can't draw using player 0 and player 1 because the player 1 is the ball (necessary because the ball takes on the color of the playfield, if I'm not mistaken).
  24. There are some gameplay aspects of the original game that I don't think will be able to be replicated. For instance: 1. In the original game, yes, there are up to 3 circles, which increases stage complexity as well as difficulty, since you have less time to move a color on the circle to the correct color of ball. 2. In the original game, the heart at the center, in addition to serving as a life meter and to indicate which color of ball will be spawned if the player hits the trigger, also serves as a means of increasing difficulty. With more life, the heart gets larger, which in turn, like the added rings, gives the player less time to react to the random location of the spawned ball, so the game requires more strategic thinking about which colors are most wanted at a particular time. 3. In the original game, the player gets 3 strikes for each heart, so the player technically has 9 lives. I haven't decided yet whether or not to be that generous with the 2600 version, seeing as there will never be more than 16 blocks on-screen at once, while the original could get about 30 with the three rings and at increasing difficulty. 4. The original game was intended to be music-based, so the heartbeat is synchronized to the BPM of the song that's playing (though it may not have been done quite perfectly). For faster songs, this means that the player will need to react faster to the colors that are being swapped with the heartbeat, but the rhythm could also assist the player and improve response. Obviously, this isn't really an option with the 2600 version. Both of these things will likely have to be dropped for the 2600 version. Unlike the original game (which was somewhat clumsily thrown together in Unity over a 27-hour period), the speed of the ball cannot be precisely regulated, the angles of the ball are limited, the locations of the blocks are limited, etc. I think that the game can still be enjoyable and challenging with just a single ring, so long as there's a degree of randomization. Ideally, someone will offer a kernel that will allow me to have multiple colors on screen at once without the flicker so I can add more possible colors to the blocks, including: 1. Secondary colors - any of the two primary colors that make up a secondary color can be used to break a secondary color block 2. White - Any color can break a white block, plus, at least in the original game, it gives the player +1 heart. They do not spawn nearly as often as the other colors, and it will probably only be a 1/20 or 1/30 chance in the 2600 version, particularly since, unlike the original, there is not really any added difficulty from having a larger heart. 3. Black - We didn't get around to doing this in the original, but I'd like to add a chance for black blocks (which would spawn about the same as white blocks). They cannot be broken by any color and must be avoided entirely. The challenge, then, is that the level will seem to spawn with some blank spaces. The player must remember where those blank spaces are in relation to other blocks around it, since once all other blocks are removed, one won't be able to see the black blocks against the black background. If I can implement all these things, I'll set up a series of randomized levels that follow a basic pattern to introduce the player to new concepts, as is done in the original game, but eventually the game will enter a randomized loop where the player gets about a 15 percent chance for each of the primary or secondary colors and a 5 percent chance for white and black blocks. I hope that this degree of complexity is sufficient for an enjoyable 2600 game, as that about reaches the extent of how how complex I intended the gameplay to get.
×
×
  • Create New...