Jump to content

bogax

Members
  • Content Count

    902
  • Joined

  • Last visited

Posts posted by bogax



  1. As has been pointed out masking is not going to effect the randomness


    My guess would be that if you have unsatisfactory results with your

    scheme it will be because the 6 bit numbers you mask off are too

    correlated, they share too many bits.

    eg if two share the least significant bit then they'll both either

    be odd or even you wont get one odd and one even.

    except it's worse (or may be worse) than that 'cause you have them

    sharing more than one bit.

    The simplest way to fix that would be to use a bigger RNG maybe 24

    bits instead of 16, but that needs another byte of RAM


    You might try stirring things up by some simple hashing

    maybe choose 4 bits and use that to pick a number from ROM

    at some random looking place in the program and XOR it with

    your 6 bits probably using a different 4 bits a different 6 bits

    and a different place in ROM for each of your 6 bit numbers

    (they'ld still be correlated but it may be easier to make

    them less correlated and it may not be as obvious)



  2. Mountain King's version of mutisprite


    Added rand16

    _COLUP1 instead of COLUP1

    player1x<9

    player1y = (rand&63)+16

    moved JUMP2



    bytes are 8 bits


    bits 0..7 (right to left) are powers of 2

    2^0 = 1

    2^1 = 2

    2^2 = 4

    2^3 = 8

    etc


    AND is (bits)


    0 AND 0 = 0

    0 AND 1 = 0

    1 AND 0 = 0

    1 AND 1 = 1


    & is a bitwise AND (bytes a & b = c, bits a0 AND b0 = c0, a1 AND b1 = c1, etc)


    63 = 00111111 = 32 + 16 + 8 + 4 + 2 + 1

    76 = 01001100 = 64 + 8 + 4


    you'll only get a bit where you've got two ones

    so ANDing something with 76 will only give you numbers

    that are the sum of three of 64, 8, 4, 0, 0, 0 (the corresponding power of 2 or 0, for each bit)

    that's 8 different possibilities (3 bits set, 2^3 = 8 possibilities)




    Example_MK.bas


  3.  

    As I am writing this, I'm wondering if it isn't possible somehow to "buffer" the surrounding screens of the current screen the player might be inhabiting. Calculating the left and right screen only requires one iteration of the feedback register. I wonder if there's a mathematical trick to reduce the amount of cycles required to go through in order to calculate a new Y-index of the overworld, instead of a new X-index. Perhaps a lookup table? A lookup table could perhaps be used to do multiple loops through the feedback register, just a row up and a row down. It might be possible to do some algebra and find out what XOR $D4 to XOR $D4 to XOR $D4 to an unknown number is...

     

    Otherwise every movement up or down a Y-index is a full-row's worth of screens' calculations...

     

    There has got to be a faster way... Feel free to jump in and give your two cents!

     

    ==

     

     

    This is what you want jumpf2.pdf (warning: the math is kind of dense ;) )

     

    This one deals with LCGs anl-rn-arb-stride.pdf

     

    This one also deals with LCGs but it has a couple of paragraphs (mostly I'm just throwing it in 'cause it's a good read :) ) hmc-cs-2014-0905.pdf

     

     

    edit: not sure I understand what you're doing Why not just run two polynomial counters, one for X and one for Y?

    better yet if you've got the ROM just run two counters and look up the room configuration ie a mapping from

    a straight counter to (something like) your polynomial counter's state except it could be completely arbitrary

    and taylored more to what you want the rooms to be instead of what you'ld get from the polynomial counters



  4. A couple more things.


    First I didn't really mention it 'cause it doesn't really pertain

    to tables

    If eg you take the room 2 branch and fall through you go on and

    spend another 150 cycles or so testing a bunch of rooms you already

    know you're not in.


    Second the 180 cycles v 77 + 50 is worst case and only if you change rooms

    If you ran through that code every frame and changed rooms three times

    a second that would still only be 5% of the time

    If you fall through after, say, the two x position tests then break even

    is at about 5 room tests.


    The table code always (potentially) does four tests (not counting the room test)

    Only a few of the string of if tests do that many.


  5. Here I've done some code with tables


    First is 22 of your if statements (put in to a more tabular form)

    then the same thing with tables.


    Each if statement takes a minimum of 7 cycles so if you fall through

    all 22 that by it self takes 154 cycles.

    If the if statements represent 1/3 of the possible rooms and the

    rooms come up at random (they probably don't) 2/3 of the time you'll

    spend 154 cycles just to decide you don't want to do anything.

    If you do take the if statement then on average you'll do half of them

    or about 77 cycles (again if the rooms are random which they probably aren't)

    plus the 50 cycles or so that it takes for the rest it.


    In the case of the tables it does a look up to decide if it needs to do

    anything, that takes about nine cycles (versus 154).

    The rest of the table code takes 180 cycles or so (versus the 77 + 50)


    But that's all sort of worst case. It might be faster it might not.

    I don't think it would be much worse.


    It takes about 1/3 the ROM


    Of course, it's not tested but it does compile.





    set romsize 32k
    set optimization noinlinedata

    dim _Room = r
    dim _Bit5_Frozen = f

    bank 2

    dispatch2



    bank 3

    dispatch3
    DS7

    mk1

    if _Room = 2 && player1x > 72 && player1x < 85 && player1y < 55 then _Room = 46 : player1y = 85 : _Bit5_Frozen{5} = 0 : goto DS46 bank5 ; 01 1
    if _Room = 4 && player1x > 66 && player1x < 86 && player1y > 45 && player1y < 55 then _Room = 42 : player1x = 117 : player1y = 85 : _Bit5_Frozen{5} = 0 : goto DS42 bank5 ; 02 0
    if _Room = 5 && player1x > 108 && player1x < 118 && player1y < 65 then _Room = 39 : player1y = 84 : _Bit5_Frozen{5} = 0 : goto DS39 bank4 ; 03 10
    if _Room = 6 && player1x > 44 && player1x < 56 && player1y < 71 then _Room = 27 : player1x = 78 : player1y = 85 : _Bit5_Frozen{5} = 0 : goto DS27 bank4 ; 04 3
    if _Room = 7 && player1x > 114 && player1x < 134 && player1y < 25 then _Room = 37 : player1y = 18 : _Bit5_Frozen{5} = 0 : goto DS37 bank4 ; 05 8
    if _Room = 8 && player1x > 62 && player1x < 77 && player1y > 52 && player1y < 62 then _Room = 40 : player1x = 21 : player1y = 85 : _Bit5_Frozen{5} = 0 : goto DS40 bank4 ; 06 11
    if _Room = 9 && player1x > 49 && player1x < 70 && player1y < 24 then _Room = 66 : player1y = 84 : _Bit5_Frozen{5} = 0 : goto DS66 bank5 ; 07 7
    if _Room = 10 && player1x > 80 && player1x < 91 && player1y > 55 && player1y < 63 then _Room = 31 : player1x = 77 : player1y = 77 : _Bit5_Frozen{5} = 0 : goto DS31 bank4 ; 08 4
    if _Room = 13 && player1x > 46 && player1x < 66 && player1y > 40 && player1y < 46 then _Room = 37 : player1y = 84 : _Bit5_Frozen{5} = 0 : goto DS37 bank4 ; 09 8
    if _Room = 15 && player1x > 87 && player1x < 96 && player1y > 60 && player1y < 77 then _Room = 25 : player1x = 78 : _Bit5_Frozen{5} = 0 : goto DS25 bank4 ; 10 1
    if _Room = 18 && player1x > 99 && player1x < 113 && player1y > 40 && player1y < 47 then _Room = 38 : player1y = 84 : _Bit5_Frozen{5} = 0 : goto DS38 bank4 ; 11 9
    if _Room = 19 && player1x > 51 && player1x < 64 && player1y < 63 then _Room = 26 : player1x = 78 : player1y = 85 : _Bit5_Frozen{5} = 0 : goto DS26 bank4 ; 12 2
    if _Room = 24 && player1x > 58 && player1x < 78 && player1y < 62 then _Room = 32 : player1x = 46 : player1y = 85 : _Bit5_Frozen{5} = 0 : goto DS32 bank4 ; 13 5
    if _Room = 32 && player1x > 88 && player1x < 104 && player1y < 31 then _Room = 34 : player1y = 85 : _Bit5_Frozen{5} = 0 : goto DS34 bank4 ; 14 6
    if _Room = 35 && player1x > 96 && player1x < 106 && player1y < 62 then _Room = 36 : player1y = 85 : _Bit5_Frozen{5} = 0 : goto DS36 bank4 ; 15 7
    if _Room = 37 && player1x > 124 && player1x < 134 && player1y > 28 then _Room = 7 : player1y = 34 : _Bit5_Frozen{5} = 0 : goto DS7 bank3 ; 16
    if _Room = 41 && player1y < 55 then _Room = 56 : player1x = 25 : player1y = 84 : _Bit5_Frozen{5} = 0 : goto DS56 bank5 ; 17 5
    if _Room = 47 && player1x > 32 && player1x < 52 && player1y < 47 then _Room = 48 : player1y = 75 : _Bit5_Frozen{5} = 0 : goto DS48 bank5 ; 18 2
    if _Room = 51 && player1x > 114 && player1x < 134 && player1y < 47 then _Room = 50 : player1y = 75 : _Bit5_Frozen{5} = 0 : goto DS50 bank5 ; 19 3
    if _Room = 52 && player1x > 71 && player1x < 90 && player1y < 47 then _Room = 51 : player1y = 84 : _Bit5_Frozen{5} = 0 : goto DS51 bank5 ; 20 4
    if _Room = 54 && player1x > 77 && player1x < 90 && player1y < 40 then _Room = 64 : player1y = 84 : _Bit5_Frozen{5} = 0 : goto DS64 bank5 ; 21 6
    if _Room = 59 && player1x > 84 && player1x < 101 && player1y > 59 && player1y < 76 then _Room = 23 : player1y = 84 : _Bit5_Frozen{5} = 0 : goto DS23 bank4 ; 22 0



    mk2

    dim room_index = temp1
    dim target_bank = temp2
    dim DS_target = temp3

    if !ridat[_Room] then skip
    room_index = ridat[_Room]-1

    if player1x < P1xlo[room_index] || player1x > P1xhi[room_index] then skip
    if player1y < P1ylo[room_index] || player1y > P1yhi[room_index] then skip

    _Bit5_Frozen{5} = 0
    if newxdat[room_index] then player1x = newxdat[room_index]
    if newydat[room_index] then player1y = newydat[room_index]
    _Room = new_room[room_index]
    DS_target = DStdat[room_index]
    target_bank = tbnkdat[room_index]

    on target_bank goto bnk3 bnk4 bnk5 bnk6

    skip


    bnk3 goto dispatch3
    bnk4 goto dispatch4 bank4
    bnk5 goto dispatch5 bank5
    bnk6 goto dispatch6 bank6


    ; 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21

    data newydat
    85, 85, 84, 85, 18, 85, 84, 77, 84, 0, 84, 85, 85, 85, 85, 34, 84, 75, 75, 84, 84, 84
    end

    data newxdat
    0, 117, 0, 78, 0, 21, 0, 77, 0, 78, 0, 78, 46, 0, 0, 0, 25, 0, 0, 0, 0, 0
    end

    data P1xlo
    73, 67, 109, 45, 115, 63, 50, 81, 47, 88, 100, 52, 59, 89, 97, 125, 0, 33, 115, 72, 78, 85
    end

    data P1xhi
    84, 85, 117, 55, 133, 76, 69, 90, 65, 95, 112, 63, 77, 103, 105, 133, 255, 51, 133, 89, 89, 100
    end

    data P1ylo
    255, 46, 255, 255, 255, 53, 255, 56, 41, 61, 41, 255, 255, 255, 255, 29, 255, 255, 255, 255, 255, 60
    end

    data P1yhi
    54, 54, 64, 70, 24, 61, 23, 62, 45, 76, 46, 62, 61, 30, 61, 0, 54, 46, 46, 46, 39, 75
    end

    data new_room
    46, 42, 39, 27, 37, 40, 66, 31, 37, 25, 38, 26, 32, 34, 36, 7, 56, 48, 50, 51, 64, 23
    end

    data DStdat
    1, 0, 10, 3, 8, 11, 7, 4, 8, 1, 9, 2, 5, 6, 7, 0, 5, 2, 3, 4, 6, 0
    end

    data tbnkdat
    3, 3, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 3, 3, 3, 3, 2
    end

    data ridat
    0, 0, 1, 0, 2, 3, 4, 5, 6, 7, 8, 0, 0, 9, 0, 10
    0, 0, 11, 12, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0
    14, 0, 0, 15, 0, 16, 0, 0, 0, 17, 0, 0, 0, 0, 0, 18
    0, 0, 0, 19, 20, 0, 21, 0, 0, 0, 0, 22, 0, 0, 0, 0
    end

    mk3



    bank 4

    dispatch4 on DS_target goto DS23 DS25 DS26 DS27 DS31 DS32 DS34 DS36 DS37 DS38 DS39 DS40 DS37

    DS23
    DS25
    DS26
    DS27
    DS31
    DS32
    DS34
    DS36
    DS37
    DS38
    DS39
    DS40


    bank 5

    dispatch5 on DS_target goto DS42 DS46 DS48 DS50 DS51 DS56 DS64 DS66

    DS42
    DS46
    DS48
    DS50
    DS51
    DS56
    DS64
    DS66



    bank 6

    dispatch6


    asm
    echo (.mk2 - .mk1)d
    echo (.mk3 - .mk2)d
    end




  6. excerpts from two bB.asm files




    .L00 ; if a < b then if a < b then if a < b then c = c
    LDA a
    CMP b
    BCS .skipL00
    .condpart0
    LDA a
    CMP b
    BCS .skip0then
    .condpart1
    LDA a
    CMP b
    BCS .skip1then
    .condpart2
    LDA c
    STA c
    .skip1then
    .skip0then
    .skipL00



    .L00 ; if a < b && a < b && a < b then c = c

    LDA a
    CMP b
    BCS .skipL00
    .condpart0
    LDA a
    CMP b
    BCS .skip0then
    .condpart1
    LDA a
    CMP b
    BCS .skip1then
    .condpart2
    LDA c
    STA c
    .skip1then
    .skip0then
    .skipL00
    .


    ie they produce the same code


  7.  

    It's doing what it should do :) I was just wondering how you're using the same variable in your 8.8 type x & y variables

     

    dim p1x = player1x.w
    dim p1y = player1y.w
    Just w while I have to use both v & w
    dim _P1_L_R = player1x.v
    dim _P1_U_D = player1y.w
    So I'm wondering if I could also use just one variable in some way? Just making shure I'm not currently wasting nine variables if I don't have to?

     

     

    it only uses the fractional part in one direction at a time

     

    if the angle is less than 45 or greater than 135 the x direction is whole integer and the y is fractional

    other wise y is integers and x is fractional


  8. I'm still not clear on what your trying to do that it's not doing


    if you're trying to get it to wrap around from 0 to 93 then maybe something like this




    _P1_U_D = _P1_U_D - _robotspeed
    if player1y > 93 then player1y = player1y + 93


  9. what kernel?

    what are you trying to do?

     

    if your speed was, say, l = 5

    then player1y would have to be >= 99 for player1y to not be set to 93 and then player1y would be >=94


  10. I don't think I'd call this a work in progress, more like exploring some ideas

     

    The code is buggy there aren't many comments and it's full of kruft

     

    the stuff in the bottom left corner is the upper byte of a 9 bit counter which

    is supposed to be keeping track of the number of playfield blocks but it doesn't quite

     

    edit: forgot to mention I had to adjust some stuff in the 2600basic.h file

    but I don't know how it comports with RevEng's latest and greatest

    I moved playfieldpos = $F0 and commented out the calculations

    for playfield from pfres

    falling_sky_03_5_1.bas

    falling_sky_03_5_1.bas.bin

    • Like 4

  11. from the DPCplus.h file

     

    ;----------------------------------------
    ; Random Number Initialization
    ;----------------------------------------
    ; The random number generate defaults to a value that spells out DPC+.
    ; Store any value to RRESET to set the random number back to DPC+, or you
    ; can use RWRITE0-3 to change the 32 bit value to anything you desire.
    ;
    ; reset random number
    ; LDA #0
    ; STA RRESET
    ;
    ; set a specific random number (spells out 2600)
    ; LDA #$32
    ; STA RWRITE0
    ; LDA #$36
    ; STA RWRITE1
    ; LDA #$30
    ; STA RWRITE2
    ; STA RWRITE3
    ;
    ; NOTE: do not set all 4 bytes to 0, as that will disable the generator.
    ;----------------------------------------
    RRESET DS 1 ; $70
    RWRITE0 DS 1 ; $71
    RWRITE1 DS 1 ; $72
    RWRITE2 DS 1 ; $73
    RWRITE3 DS 1 ; $74


  12. I did that, like, five years ago or so and I don't remember what I did.

    I'm sure I didn't use a spread sheet. It was just by inspection.

    ie what needs to go where. (but by all means use a spread sheet

    if it helps)


    It was just something I banged together to see how it would work.


    In retrospect, I was too conservative with my tables.

    Looking at it now, I prefer more comprehensive table

    (ie more like ZackAttack's suggestion)


    So here's the new, improved version.



    There will always be a sprite copy in the left position. (I have decreed it thus)


    So There are only four possible configurations for the sprite.

    a single sprite, a near copy, a far copy, or both copies.

    (the original table is somewhat redundant in that regard)


    If there is a collision it can only happen in one of three possible places


    If there is a collision you may have to adjust the sprite x position and

    change the configuration.


    You only have to change the sprite's x position if there's a collision

    with the left most sprite/copy


    So you need a 3 x 4 table to look up NUSIZ0 and a table with 4 elements

    for the adjustment to the x position.

    (But that requires an if statement to restrict x position adjusments

    to the 0 sprite position. It could be done with a twelve element table

    but you'd be adjusting the sprite x position by 0 most of the time)

    (the NUSIZ0 table will have four positions for situations that can't

    happen, but that's about 2/3 of an if statement so well worth a little

    redundancy)



    The limit for rightward movement of the sprite will also depend on the

    sprite configuration.

    You could probably calculate that from the tabel for the x position adjustment,

    but there's only four possibilities so its probably faster and easier

    and maybe smaller to just do another table.



    If there's a collision it can only happen in an interval of 40 pixels to the

    right of the sprite's x position,


    The copies are spaced on 16 pixel intervals so we take


    (missile1x - player0x)/16


    and that will give us a number 0..2 for which copy had the collision.


    I use that as the row address and since there's four values per row

    its divide by 16 multiply by 4 ie divide by 4 with an AND mask to get rid

    of the fractional part.


    ((missile1x - player0x)/16) & %00001100


    I save the sprite configuration in bits 0..1 of jf and changed missile fired

    flag to jf{7} (0 if the missile's fired) (there's also a direction flag, jf{6})


    So the table address for the new sprite configuration is


    (((missile1x - player0x)/16) & %00001100) | (jf & %00000011)



    The playfield junk in the lower right is jf with some pixels below it to

    indicate the bit positions (var40 = $55, var36 = jf)



    edit: I swapped missile1x and player0x above (not in the code) (now fixed)


    I left out the bit reference in the if predicate so you can (re)fire the missile

    some times when you shouldn't be able to

    line 69 in the code should be


    if joy0fire && jf{7} then missile1x = player1x + 3 : missile1y = 80 : jf{7} = 0

    x3_2.bas

    x3_2.bas.bin

    • Like 1

  13. Lolkiu64,

     

    Thanks to Bogax code I was able to adjust some of my stuff. I did add the feature of speed control (based upon RT's Code) if that helps. That way your sprite speed is adjustable.

     

    ;***************************************************************

    ;

    ; Don't move right if pfpixel is in the way.

    ;

    if joy0right then _P0_L_R = _P0_L_R + .5 : then left

    temp3 = (player0x - 14)/4 : temp4 = (player0y - 6)/8

    if pfread(temp3, temp4) then _P0_L_R = _P0_L_R - .5 : then down

    temp3 = (player0x - 14)/4 : temp4 = (player0y - 1)/8

    if pfread(temp3, temp4) then _P0_L_R = _P0_L_R - .5 : then down

     

    (Just adjust all the .5 to what ever you need. 1.5; 1.8; .9 etc.) I did try to add another section, but got an error to detect the middle of the sprite. My thought there was if you can detect the middle of the sprite. Why not code it for the entire sprite. I know it will eat up space but then I think you have 100% collision. What I tried and it didn't compile. temp4 = (player0y - 3)/8 should detect the middle of the sprite, i think.

     

    ;***************************************************************

    ;

    ; Don't move right if pfpixel is in the way.

    ;

    if joy0right then _P0_L_R = _P0_L_R + .5 : then left

     

    temp3 = (player0x - 14)/4 : temp4 = (player0y - 6)/8

    if pfread(temp3, temp4) then _P0_L_R = _P0_L_R - .5 : then down

     

    temp3 = (player0x - 14)/4 : temp4 = (player0y - 3)/8

    if pfread(temp3, temp4) then _P0_L_R = _P0_L_R - .5 : then down

     

    temp3 = (player0x - 14)/4 : temp4 = (player0y - 1)/8

    if pfread(temp3, temp4) then _P0_L_R = _P0_L_R - .5 : then down

     

    I am working on the Multisprite version which is attached. Hopefully Bogax or someone can adjust the code around to work. The left and right detection works. I'm having trouble with the up and down portions.

     

    The issue I see even in the above program is that they both use only one pixel for detection which is great, but at times the sprite will cut corners and not have the 100% true detection. This is still better that the bouncy detection that I first learned how to use. Hope these help in your game development, thanks.

     

     

    you could have a look at this

     

     

     

    collision_prevention_13.bas

    collision_prevention_13.bas.bin

    • Like 1

  14. here I've inserted different collision code and changed the height of player0

     

    the code is basically similar

    it tests two corners of the player0 for each direction

    to see if there's a playfield pixel in the way

     

    so for example if you're moving right it tests the top right

    corner of player0 against the bottom left of the PFpixel

    and the bottom right of player0 against the top left of the PFpixel

     

     

    Max_Maze_mod_01.bas

    Max_Maze_mod_01.bas.bin


  15.  

    It kind of worked. The flicker is gone. But it still doesn't look right.

    dim ptr = a
    mainloop
     temp1=golemShape[ptr]
     temp2=golemShape[0]
     temp3=golemShape[1]
     temp4=golemShape[2]
     
      COLUBK=$00
    
      COLUPF=$08
      pfpixel 20 5 on
    
      pfpixel 21 5 on
    
      pfpixel 22 5 on
    
     
    
      pfpixel temp2 7 on
    
      pfpixel temp3 7 on
    
      pfpixel temp4 7 on
    
     
    
      ptr = 0
       
      pfpixel temp1 9 on
    
      ptr = ptr + 1
    
      pfpixel temp1 9 on
    
    
      ptr = ptr + 1
    
      pfpixel temp1 9 on
      drawscreen
      goto mainloop
    
    
      data golemShape
    
      20, 21, 22
    
    end
    

     

    pfpixel uses temp1 and temp2

×
×
  • Create New...