Jump to content

bogax

Members
  • Posts

    942
  • Joined

  • Last visited

Everything posted by bogax

  1. Can't say I've tryed it but if you're just toggling between two positions you should be able to use an exclusive or something like const toggle_x = M01X ^ M02X const toggle_y = M01Y ^ M02Y if collision(missile0, player0) then missile0y = missile0y ^ toggle_y : missile0x = missile0x ^ toggle_x
  2. you didn't say what the problem is the code looks like it's for 8x8 sprites playfield pixels are 4x8 player pixels and the playfield coordinates don't jibe with player coordinates the player movement code does collision detection by converting player coordinates to playfield pixels and checking to see if there's a playfield pixel in the way it does the conversion by adding an offset to the player position and dividing by 4 (for x) or 8 (for y) you probably want to adjust the offsets to compensate for the difference in the sprite dimensions
  3. a couple of previous Multiple Sprite Shots with NUSIZ1 (Standard Kernel) Questions about NUSIZ1
  4. The short answer is yes, but a little ASM helps a lot Here are some previous comments
  5. I was thinking something like this ; d3 = 100's, d2 = 10's, d1 = 1's d3 = 0 : d2 = 0 : d1 = temp1 if d1 >= 100 then d3 = d3 + 1 : d1 = d1 - 100 if d1 >= 100 then d3 = d3 + 1 : d1 = d1 - 100 if d1 >= 50 then d2 = d2 + 5 : d1 = d1 - 50 if d1 >= 30 then d2 = d2 + 3 : d1 = d1 - 30 if d1 >= 20 then d2 = d2 + 2 : d1 = d1 - 20 if d1 >= 10 then d2 = d2 + 1 : d1 = d1 - 10
  6. What you want to do is subtract the 10's frome temp1 and add them to temp2 so you end up with the 10's in temp2 and the 1's in temp1 so the if statements would be like if temp1 > 99 then temp2 = temp2 + 10 : temp1 = temp1 - 100 ; temp2 gets the 10's ie 100 = 10 10's
  7. the fractional part is still just a byte it can reperesent 256 values, 0..255 inclusive as a .8 fraction (8 is the number of bits in a byte) a byte is the integer number of 256ths (1/256) 1 = 256 256ths .25 = 256 * .25 = 64 for 0.25 you have two bytes 0 and 64 ie the fractional byte will equal 64 this will be relatively neat in your case because youre looking for multiples of a power of two so eg .25 (a power of 2, 2^-2) is an integer number of 256ths if you want to test for 1.5 it will be 1 and .5 * 256 = 128 if a = 1 && b = 128 then [do something] for non powers of two it gets messier 0.33 is 84.48 256ths ie .33 * 256 = 84.48 and bB rounds it to 84 personally I'd dim it as b.a because the variables are in order in memory and the processor is little endian and expects a 16 bit quantity to be in order in memory with the least byte first but that has nothing to do with what you're doing
  8. some things need to be page aligned its possible that adding a few bytes or rearranging things could cause bB to add a bunch of padding
  9. you don't have to avoid gosubs but you do have to be mindfull of how deep you're going I have sometimes wondered if it would be worth doing a bit of indirection in the returns so eg you'ld define 16 return labels and implement a stack of nibbles for 4 bit return tokens with the stacking and returns done in software it would be messy and slow but you could turn 1 stack position into 4 (and would 16 possible returns be enough? could be a different 16 for each bank)
  10. 1 if you're only using horizontal and vertical you wouldn't need the timer which is only to make the second tap diagnol recognizeable as such 2 I think it would be trivial to either coerce a diagnol to horizontal or vertical or just ignore diagnols 3 its moot if you don't want to adapt it any way 😜 really I just meant to show the behavior without timing the double tap, the use of SWCHA and the use of tables (I just threw all those defs and macros and verbose names in there to keep RT happy )
  11. here I added a delay it uses another variable half for saving the state of SWCHA and half for a timer when it sees a change on SWCHA it starts the timer then processes the joystick when it times out a 4 frame delay seems a reasonable compromise between too long and not long enough (for me anyway) set optimization noinlinedata dim counter = c dim move_flags = m dim move_direction = temp1 dim j0_direction = temp2 def joy_was_0 = m{6} def frame_parity = m{5} def speed_x_2 = m{4} def true = 1 def false = 0 def set_move_flag = callmacro smd_mac def get_move_flag = callmacro gmd_mac const noscore = 1 const delay = 4 macro smd_mac {1} move_flags = (move_flags & %11110000) | {1} end macro gmd_mac {1} {1} = move_flags & %00001111 end gosub init loop COLUP0 = $38 COLUPF = $86 drawscreen get_move_flag move_direction if !collision(playfield, player0) then check_counter player0x = player0x - x_move_table[move_direction] player0y = player0y - y_move_table[move_direction] move_flags = 0 : move_direction = 0 goto skip_move check_counter if counter & $0F then count_down if (counter ^ SWCHA) & $F0 = 0 then check_parity counter = (counter & $F0) | delay goto check_parity count_down counter = counter - 1 if counter & $0F then check_parity check_joy0 j0_direction = (SWCHA ^ %11111111)/16 j0_direction = direction_table[j0_direction] if j0_direction = 0 then check_parity if j0_direction <> move_direction then move_direction = j0_direction : speed_x_2 = false : goto check_parity if joy_was_0 then speed_x_2 = true check_parity if speed_x_2 then do_move if frame_parity then skip_move do_move player0x = player0x + x_move_table[move_direction] player0y = player0y + y_move_table[move_direction] skip_move if SWCHA & $F0 = $F0 then joy_was_0 = false else joy_was_0 = true if frame_parity then frame_parity = false else frame_parity = true set_move_flag move_direction counter = counter & $0F : counter = (SWCHA & $F0) | counter goto loop init player0x = 40 player0y = 30 player0: %00011000 %00111100 %00111100 %00011000 end playfield: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX X..............................X X..............................X X..............XX..............X X..............XX..............X X..............XX..............X X..............XX..............X X..............XX..............X X..............................X X..............................X XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX end return data x_move_table 0, 0, 1, 1, 1, 0, -1, -1, -1 end data y_move_table 0, -1, -1, 0, 1, 1, 1, 0, -1 end ; 1 ; 8 2 ; 7 * 3 ; 6 4 ; 5 ; 0 1 2 3 4 5 6 7 8 9 10 SWCHA ; ---u --d- --du -l-- -l-u -ld- -ldu r--- r--u r-d- right left down up joy switches data direction_table 0, 1, 5, 0, 7, 8, 6, 0, 3, 2, 4 ; direction end double_tap_2.bas double_tap_2.bas.bin
  12. I can't get it to hold a diagonal so you may need a timer, but not for the double tap I'm using a keyboard but I'd guess it would also be a problem with a real joy stick
  13. I did one movement is controlled by two flags there's also a frame parity flag the current move direction is the lower four bits of the move_flags variable if joy0 is not active nothing changes if joy0 is active but the joy0 direction is different from the move direction the move direction is set to the joy0 direction and the speed_x_2 flag is set to false if the joy0 direction is the same as the move direction and joy direction was 0 on the previous frame the speed_x_2 flag is set to true (no timer) if the speed_x_2 flag is true the frame parity check is skipped and the player is moved each frame other wise the the player is moved every other frame a collision backs off the player and clears the move_flags variable set optimization noinlinedata dim move_flags = m dim move_direction = temp1 dim j0_direction = temp2 def joy_was_0 = m{6} def frame_parity = m{5} def speed_x_2 = m{4} def true = 1 def false = 0 def set_move_flag = callmacro smd_mac def get_move_flag = callmacro gmd_mac const noscore = 1 macro smd_mac {1} move_flags = (move_flags & %11110000) | {1} end macro gmd_mac {1} {1} = move_flags & %00001111 end gosub init loop COLUP0 = $38 COLUPF = $86 drawscreen get_move_flag move_direction if !collision(playfield, player0) then check_joy0 player0x = player0x - x_move_table[move_direction] player0y = player0y - y_move_table[move_direction] move_flags = 0 : move_direction = 0 goto skip_move check_joy0 j0_direction = (SWCHA ^ %11111111)/16 j0_direction = direction_table[j0_direction] if j0_direction = 0 then check_parity if j0_direction <> move_direction then move_direction = j0_direction : speed_x_2 = false : goto check_parity if joy_was_0 then speed_x_2 = true check_parity if speed_x_2 then do_move if frame_parity then skip_move do_move player0x = player0x + x_move_table[move_direction] player0y = player0y + y_move_table[move_direction] skip_move if j0_direction then joy_was_0 = false else joy_was_0 = true if frame_parity then frame_parity = false else frame_parity = true set_move_flag move_direction goto loop init player0x = 40 player0y = 30 player0: %00011000 %00111100 %00111100 %00011000 end playfield: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX X..............................X X..............................X X..............XX..............X X..............XX..............X X..............XX..............X X..............XX..............X X..............XX..............X X..............................X X..............................X XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX end return data x_move_table 0, 0, 1, 1, 1, 0, -1, -1, -1 end data y_move_table 0, -1, -1, 0, 1, 1, 1, 0, -1 end ; 1 ; 8 2 ; 7 * 3 ; 6 4 ; 5 ; 0 1 2 3 4 5 6 7 8 9 10 SWCHA ; ---u --d- --du -l-- -l-u -ld- -ldu r--- r--u r-d- right left down up joy switches data direction_table 0, 1, 5, 0, 7, 8, 6, 0, 3, 2, 4 ; direction end double_tap.bas double_tap.bas.bin
  14. I think you are trying to convert you're direction to a number I find that a lot easier to deal with with this sort of stuff I'd suggest you go read about SWCHA and then do something like this direction = (SWCHA ^ %11111111)/16 direction = dirt[direction] ; 1 ; 8 2 ; 7 * 3 ; 6 4 ; 5 ; 0 1 2 3 4 5 6 7 8 9 10 SWCHA ; ---u --d- --du -l-- -l-u -ld- -ldu r--- r--u r-d- right left down up joy switches data dirt ; direction table 0 1, 5, 0, 7, 8, 6, 0 3, 2, 4 ; direction end do you really need to time it? could you just bump the speed up if you're already going in the same direction?
  15. you can reuse the variable. in this case variable e when you use the sdata statement bB makes the name you give it an alias for the variable lev1 becomes an alias for the variable e like you'd dimmed it dim lev1 = e bB also declares a lable derived from the sdata name by appending _begin so here the lable would be lev1_begin if you use the same sdata name twice bB will try to declare the same lable twice with different values so yes similar to two subroutines with the same lable
  16. the sdata statement sets the pointer it doesn't matter if two sdata statements use the same variables for the pointer it will be whatever the last sdata statement executed set it to (unless you change it and of course sread increments it)
  17. lo and hi are just abbreviations for low and high in the names to remind me what they are and help me keep things straight all these values are binary and bytes and stuff and we write them as hexadecimal suppose it was decimal I define a byte as two decimal digits normal bB variables are one byte and can only hold values 0..99 but memory be it RAM or ROM is numbered 0..9999 suppose I have a data table that starts at location 1234 12 is the hi byte of location 1234 34 is the lo byte of location 1234 suppose I have a table at location 1234 data data_table [some data] end data_table is the name for (location) 1234 <data_table is 34 >data_table is 12 I have a pointer named a it's a bB variable and it only holds values 0..99 it's a pointer because it holds a number which is the location in memory of some data, it points at the data suppose a contains 51 v = data_table[a] takes 1234 (the value of data_table) adds 51 (the contents of a) gets the data that's at location 1285 and sticks it in v since the pointer a can only hold values up to 99 you can only get to 99 values in the table that way an sdata statement makes the pointer 4 digits so you can get at 9999 values in a table four digits needs 2 bytes you specify a variable and the sdata statement assumes that the location after it is the second byte (that's the way the processor works) and the name you specify is not the name of the location of the table it's the name of the variable that contains the location of the data (the 4 digit 2 byte pointer) if you specify variable a then the 4 digit 2 byte pointer will be variables b,a (the variables are in order in memory b comes after a, f comes after e that's just the way bB does things) b contains 12, a contains 34 sread takes what ever variable you pass to it assumes that that is the low byte of a 2 byte pointer gets whatever is at the location pointed to by the pointer and increments the pointer if the pointer is the variables b,a and contains 1234 it will get what ever is at location 1234 and increment the pointer to point at 1235 for the next sread b will contain 12 a will contain 35 the 2 byte pointer is just a couple of variables you can point them at anything you want if you want the pointer to point at a paticular table you just set the pointer to the location of that table with sdata you don't know the location. the name is the name of the pointer that contains the location. with a data statement the name is for the location of the table/data and that is 4 digits, 2 bytes in a const declaration or in specifying of table data you can choose which byte by prepending < for the low byte or > for the high byte so if data_table is the name for 1234 <data_table = 34 >data_table = 12 so you can create a couple of tables containing the hi bytes and the lo bytes of the locations of your level data tables and use variable a, your level number, to pick the corresponding location out of the levplo and levphi tables which contain the locations of you level data tables (lev1, lev2, etc) and copy the level data table location to your chosen sread pointer which in this case are variables f,e I used abbreviations levplo and levphi for level pointer lo, level pointer hi for the names of the tables conaining the lo and hi bytes of the locations of the level data tables e = levplo[a] f = levphi[a] t = sread(e) data levplo <lev1, <lev2, <lev3, etc end data levphi >lev1, >lev2, >lev3, etc end data lev1 14,4,15,4,17,4,18,4,11,6,12,6,14,6,15,6,17,6,18,6,20,6,21,6,8,8,9,8,23,8,24,8,23,10,24,10,23,12,24,12,23,14,24,14,11,16,12,16,14,16,15,16,17,16,18,16,20,16,21,16 end data lev2 14,4,15,4,17,4,18,4,11,6,12,6,14,6,15,6,17,6,18,6,20,6,21,6,8,8,9,8,23,8,24,8,23,10,24,10,23,12,24,12,23,14,24,14,11,16,12,16,14,16,15,16,17,16,18,16,20,16,21,16 end etc
  18. normal bB variables are one byte, 8 bits and can have values 0..255 data addresses go upto 65535 and need two bytes sread needs a two byte pointer sdata lev1 = e defines e as the 16 bit pointer and since e only holds 8 bits the next byte, f holds the other 8 bits its kind of like dim lev1 = e except its 16 bits so maybe it's more like dim lev1 = f.e sdata also loads the 16 bit address of the data in to the lev1/f.e pointer data lev1 makes lev1 the name for the 16 bit address where the data is <lev1 is the lower 8 bits of lev1 >lev1 is the high 8 bits of lev1 data levplo <lev1, <lev2, <lev3, etc end creates a table of the lower 8 bits of the locations of the level data e = levplo[a] f = levphi[a] assign the lower 8 bits to e and the high 8 bits to f sread doesn't need you to assign a name for the pointer it just needs the the name of the variable that is the low byte of the pointer t = sread(e)
  19. if you just need to change the pointer to point to the level data you could do something like this e = levplo[a] f = levphi[a] t = sread(e) data levplo <lev1, <lev2, <lev3, etc end data levphi >lev1, >lev2, >lev3, etc end data lev1 14,4,15,4,17,4,18,4,11,6,12,6,14,6,15,6,17,6,18,6,20,6,21,6,8,8,9,8,23,8,24,8,23,10,24,10,23,12,24,12,23,14,24,14,11,16,12,16,14,16,15,16,17,16,18,16,20,16,21,16 end data lev2 14,4,15,4,17,4,18,4,11,6,12,6,14,6,15,6,17,6,18,6,20,6,21,6,8,8,9,8,23,8,24,8,23,10,24,10,23,12,24,12,23,14,24,14,11,16,12,16,14,16,15,16,17,16,18,16,20,16,21,16 end etc
  20. at the risk of being more confusing than helpfull... v = sread(dat) the sread is sort of like this v = dat[pointer] pointer = pointer + 1 data dat [data] end except that with the normal data statement pointer is 8 bits so you can only address 256 bytes of data with the normal data statement dat is the name of the location of the data and with sdata the name is the name of a pointer which points to the data sdata dat = p [data] end is sort of like dim dat = q.p const datlo = <dat_ ; the lo byte of dat_ const dathi = >dat_ ; the hi byte of dat_ p = datlo q = dathi data dat_ [data] end with the data statement dat is the name for the location of the data with the sdata statement dat is the name of a 16 bit pointer (instead of "pointer") which is a little like an 8.8 variable except it's 16. and that pointer is intialized with the location of the data and since it's 16 bits you can reach 65536 bytes of data but sread only goes through them sequentially however you can change the pointer I don't think you even need the sdata statement you just need to pass sread a pointer/variable
  21. I don't know what DPC+ does but normally if you use rand in the predicate of an if statement it does'nt call the rand function it just references the rand seed/variable
  22. DPC+ uses a better random number generator
  23. I don't understand the drawscreens are part of the levelend routine they go were ever the levelend routine is I thought you were just flashing the screen between levels so the draw screens shouldn't slow the game down they should only slow the flashing. here's another variant the timer counts drawscreens and cycles in ~4.25 seconds so ~.85 seconds per bkx untested levelend player0x=250: player0y=150 timer = 0 levelend2 temp1 = timer/2 : temp1 = (temp1/4 + temp1)/32 ; temp1 = timer/51 on temp1 gosub bk1 bk2 bk3 bk4 bk5 drawscreen timer = timer + 1 if timer then levelend2 a = a + 1: g = 0: h = 0: b = 0: return otherbank
  24. I can't help but wonder where it would matter. The simplest way I can think of is make one of player0x or player0y an 8.8 variable so you can move in fractional pixels So eg if 3 * y = 4 * x dim p0y = player0y.y player0x = player0x + 1 : p0y = p0y + 0.75
×
×
  • Create New...