Jump to content

Cybearg

Members
  • Content Count

    951
  • Joined

  • Last visited

Posts posted by Cybearg


  1. In the first paragraph above it'd be clearer if i said there are separate ram registers for colors and the playfield blocks, and those shouldn't change so the assembly kernel can pick them out. Gotta go now!

    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.


  2. 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?


  3. could you just use collision([whateverobjectyouareusingfortheshot], playfield) and detect WHICH block simply by the direction it was shot in? In other words, when you fire the shot record which of the angles the shot was fired from. When it eventually hits a target (using the traditional collision command) you know it came from that last angle - and thus which block it hit.

    That's brilliant! Let me fiddle with it and see what I can come up with. Great idea!


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


  5. what I posted was just meant to be an example of

    what would need to be done, the collision routine

    would need to be fixed, I just did't show it.

    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 don't think there's anything wrong. Try it with just one color

    (don't change flicker) and then with two (let flicker cycle 0-1)

    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.

     

    the asm I posted for the rotation was bugged, fixed now

    If it makes you feel any better, I have zero clue about ASM, so it was all Greek to me, anyway.

     

    I'd suggest you keep a count of the remaining blocks that

    gets updated when you have a good hit rather than counting

    through the blocks to check if there's any left

    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.

     

    in the flicker code you could pull the color look up out of

    the loop

    you could also up date flicker in one place

     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

    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 *[email protected]                 *
    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


  6. 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 *[email protected]                 *
    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


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


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


  9. 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 *[email protected]                 *
    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.


  10. 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?


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


  12. 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?

     

    No idea. My bB was able to compile that just fine. Here's the version output:

     

    batari Basic Compiler date (7/16/2003 1:03:48 AM)

    Current bB compiler version does not support -O option. Peephole optimizer option disabled.

    Current bB compiler version does not support DPC+ kernel. Those options will be disabled.

     

    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.


  13. 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?


  14. 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?


  15. Right now you are using GRP0 for the heart, and GRP1 for the projectile, correct? M1 shares the same color as GRP1 so you have the choice of using either object.

    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.


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


  17. 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).


  18. I watched the video of the original game and of the Atari 2600 WIP. How many rows (concentric circles) are you going for? The video of the original game started with 1 circle and went up to 2 circles, but I got the impression it would have added more as the game progresses?

    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.


  19. I usually try to write for the lowest common denominator

    Oh, ouch.

     

    Anyway, I thought that Visual bB was just an IDE that one could update bB as required for, but apparently they're tied together in ways that they can't be separated?

     

    Maybe I should invest in bB. I mean, what does Visual bB offer above just bB? The ability to work within an environment that organizes files for you? One could just have Visual bB running for the nice visual interfaces for setting up playfields, sprites, etc., then copy it on over to normal bB, right?


  20. temp1 = frame & 3

    if temp1 = 0 then colorindex = colorindex+1

    Oh, yeah. That fixed it for me, too. Thanks!

    Also, holy crap, SeaGt! That's awesome! I've been having some issues with

    . It's all working pretty well except that I seriously need a way to have multiple colors in the same row on-screen at once. Do you think this would work for that? I don't know Assembly at all, so if so, how could/would it be implemented?
×
×
  • Create New...