Words Fail Posted December 4, 2022 Share Posted December 4, 2022 I am working on collision detection.. my game has 10 columns that it needs to check player position: coldet if player0x=21 then gosub coldet2 if player0x=33 then gosub coldet2 if player0x=45 then gosub coldet2 if player0x=57 then gosub coldet2 if player0x=69 then gosub coldet2 if player0x=81 then gosub coldet2 if player0x=93 then gosub coldet2 if player0x=105 then gosub coldet2 if player0x=117 then gosub coldet2 if player0x=129 then cosub coldet2 return otherbank Is there a way to shorten that? Only if your player0x is one of those coordinates does it need to continue to the second part. Quote Link to comment Share on other sites More sharing options...
Words Fail Posted December 4, 2022 Author Share Posted December 4, 2022 43 minutes ago, Words Fail said: I am working on collision detection.. my game has 10 columns that it needs to check player position: coldet if player0x=21 then gosub coldet2 if player0x=33 then gosub coldet2 if player0x=45 then gosub coldet2 if player0x=57 then gosub coldet2 if player0x=69 then gosub coldet2 if player0x=81 then gosub coldet2 if player0x=93 then gosub coldet2 if player0x=105 then gosub coldet2 if player0x=117 then gosub coldet2 if player0x=129 then cosub coldet2 return otherbank Is there a way to shorten that? Only if your player0x is one of those coordinates does it need to continue to the second part. I am assuming this will work on player0x goto coldet21 coldet33 coldet45 coldet57 coldet69 coldet81 coldet93 coldet105 coldet117 coldet129 return otherbank So if it's one of those values it'll goto something, otherwise it'll return? Quote Link to comment Share on other sites More sharing options...
+Karl G Posted December 4, 2022 Share Posted December 4, 2022 11 minutes ago, Words Fail said: I am assuming this will work on player0x goto coldet21 coldet33 coldet45 coldet57 coldet69 coldet81 coldet93 coldet105 coldet117 coldet129 return otherbank So if it's one of those values it'll goto something, otherwise it'll return? No, this won't work. on ... goto expects a value between 0 and whatever number, and it will goto one of the labels you provide after the "goto" depending on the value starting from 0. One other approach to shorten the code would be to put the values it is looking for in a data statement, then loop through them to look for a match. If one is found, then do your gosub. Something like: for temp5 = 0 to 9 if player0x = my_numbers[temp5] then gosub coldet2 next return otherbank [...] data my_numbers 21,33,45,57,69,81,93,105,117,129 end 2 Quote Link to comment Share on other sites More sharing options...
+Al_Nafuur Posted December 4, 2022 Share Posted December 4, 2022 9 hours ago, Words Fail said: I am working on collision detection.. my game has 10 columns that it needs to check player position: coldet if player0x=21 then gosub coldet2 if player0x=33 then gosub coldet2 if player0x=45 then gosub coldet2 if player0x=57 then gosub coldet2 if player0x=69 then gosub coldet2 if player0x=81 then gosub coldet2 if player0x=93 then gosub coldet2 if player0x=105 then gosub coldet2 if player0x=117 then gosub coldet2 if player0x=129 then cosub coldet2 return otherbank Is there a way to shorten that? Only if your player0x is one of those coordinates does it need to continue to the second part. Your subroutine (coldet2) will return to the next if condition after the one that had matched. Are you sure you want to keep on checking the player0x value after one of the previous conditions has matched? It will always be false! This will only take cycles. I haven't checked, but maybe this will be smaller and faster? coldet if player0x < 21 || player0x > 129 then coldet_return tempX = player0x - 21 coldet_check if tempx = 0 then gosub coldet2 : goto coldet_return tempX = tempX - 12 if tempx >= 0 then coldet_check coldet_return return otherbank Quote Link to comment Share on other sites More sharing options...
Words Fail Posted December 4, 2022 Author Share Posted December 4, 2022 1 hour ago, Karl G said: No, this won't work. on ... goto expects a value between 0 and whatever number, and it will goto one of the labels you provide after the "goto" depending on the value starting from 0. One other approach to shorten the code would be to put the values it is looking for in a data statement, then loop through them to look for a match. If one is found, then do your gosub. Something like: for temp5 = 0 to 9 if player0x = my_numbers[temp5] then gosub coldet2 next return otherbank [...] data my_numbers 21,33,45,57,69,81,93,105,117,129 end Thanks! Good to know I can do that for y also. I tried entering it, but it keeps giving me an error.. I see things need to be indented.. but not end statements. It says "Syntax Error: The "end" command appears to be indented." data pxn 21,33,45,57,69,81,93,105,117,129 end data pyn 18,26,34,42,50,58,66,74,82 end It does it no matter if I put one or two data statements. I also have it at the very end of my code in bank 3 if that's fine. Quote Link to comment Share on other sites More sharing options...
Words Fail Posted December 4, 2022 Author Share Posted December 4, 2022 1 minute ago, Al_Nafuur said: Your subroutine (coldet2) will return to the next if condition that had matched. Are you sure you want to keep on checking the player0x value after one of the previous conditions has matched? It will always be false! This will only take cycles. I haven't checked, but maybe this will be smaller and faster? coldet if player0x < 21 || player0x > 129 then coldet_return tempX = player0x - 21 coldet_check if tempx = 0 then gosub coldet2 : goto coldet_return tempX = tempX - 12 if tempx >= 0 then coldet_check coldet_return return otherbank Why would it always be false? What I have currently works.. just the chunky code I wrote takes up almost a whole 4k of code to do and a bunch of cycles. My current code first uses a bunch (10) if then statements to check if you're at one of the possible x coordinates. Based on that it goes to another subroutine (10 of them) which each have 9 if then statements! So it looked what x pos you were at, then looks at what y pos you were at and based on that removes a pixel. Quote Link to comment Share on other sites More sharing options...
Words Fail Posted December 4, 2022 Author Share Posted December 4, 2022 (edited) 7 minutes ago, Al_Nafuur said: Your subroutine (coldet2) will return to the next if condition that had matched. Are you sure you want to keep on checking the player0x value after one of the previous conditions has matched? It will always be false! This will only take cycles. I haven't checked, but maybe this will be smaller and faster? coldet if player0x < 21 || player0x > 129 then coldet_return tempX = player0x - 21 coldet_check if tempx = 0 then gosub coldet2 : goto coldet_return tempX = tempX - 12 if tempx >= 0 then coldet_check coldet_return return otherbank Also I don't think your statement would work? It's not if it's greater than 21 or less than 129.. it's if it is exactly 21, 33, 45, 57, 69, 81 93, 105, 117, or 129 is when it goes to the next subroutine. Someone else pointed me towards data statements, which seem like a good way to go, I just haven't got it to compile with them yet. Edited December 4, 2022 by Words Fail Quote Link to comment Share on other sites More sharing options...
bogax Posted December 5, 2022 Share Posted December 5, 2022 (edited) if you gosub in the middle of a bunch of if statements you will return to the middle of the if statements and do a bunch of if statements you don't need to do your numbers are (n * 12) + 21 you can subtract 21 and test for a multiple of 12 that is in range any multiple of 12 will be a multiple of 4 you can test for a multiple of 4 by testing for bits 0 and 1 being 0 that will immediately eliminate 3/4 of possible numbers if you subtract 21 from a number 0..20 you get a result in the range (256 - 21) to 255 so you can eliminate numbers > 129 - 21 divide by 4 and look for multiples of 3 (12 = 3 * 4) you could look for numbers that are n mod 3 = 0 but probably simpler and faster to just use a lookup table something like this (untested) [code] temp1 = player0x - 21 if temp1 & 3 || temp1 > 108 then skip temp1 = temp1 / 4 if x3tbl[temp1] then gosub coldet2 skip data x3tbl 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1 end [/code] edit: fixed the table edit: Crap! ok, this time I really fixed the table.. Edited December 5, 2022 by bogax Quote Link to comment Share on other sites More sharing options...
+Karl G Posted December 5, 2022 Share Posted December 5, 2022 20 hours ago, Words Fail said: Thanks! Good to know I can do that for y also. I tried entering it, but it keeps giving me an error.. I see things need to be indented.. but not end statements. It says "Syntax Error: The "end" command appears to be indented." data pxn 21,33,45,57,69,81,93,105,117,129 end data pyn 18,26,34,42,50,58,66,74,82 end It does it no matter if I put one or two data statements. I also have it at the very end of my code in bank 3 if that's fine. Yes, that is correct. Everything except labels and end statements need to be indented. Also, I think @Al_Nafuur meant to reply to me, and he is right: my suggested code should jump out of the for loop after executing the subroutine unless it's possible for there to be more than one match with your subroutine potentially getting called multiple times. If there can be only one match, then this would be better: for temp5 = 0 to 9 if player0x = my_numbers[temp5] then gosub coldet2 : goto ____done_coldet2 next ____done_coldet2 Quote Link to comment Share on other sites More sharing options...
+Al_Nafuur Posted December 5, 2022 Share Posted December 5, 2022 Just for ROM size comparison I compiled the different variants: Unrolled loop is the biggest (but fastest) with only 2760 bytes of ROM space left @Karl G's FOR loop variant is the smallest with 2840 bytes of ROM space left My bB loop has 2833 bytes of ROM space left @bogax's variant has 2805 bytes of ROM space left set smartbranching on set optimization noinlinedata coldet2 return rem 2760 bytes of ROM space left if player0x=21 then gosub coldet2 : goto coldet_skip if player0x=33 then gosub coldet2 : goto coldet_skip if player0x=45 then gosub coldet2 : goto coldet_skip if player0x=57 then gosub coldet2 : goto coldet_skip if player0x=69 then gosub coldet2 : goto coldet_skip if player0x=81 then gosub coldet2 : goto coldet_skip if player0x=93 then gosub coldet2 : goto coldet_skip if player0x=105 then gosub coldet2 : goto coldet_skip if player0x=117 then gosub coldet2 : goto coldet_skip if player0x=129 then gosub coldet2 coldet_skip return rem 2840 bytes of ROM space left for temp5 = 0 to 9 if player0x = my_numbers[temp5] then gosub coldet2 : goto coldet1_return next coldet1_return return data my_numbers 21,33,45,57,69,81,93,105,117,129 end rem 2833 bytes of ROM space left if player0x < 21 || player0x > 129 then coldet_return temp1 = player0x - 21 coldet_check if temp1 = 0 then gosub coldet2 : goto coldet_return temp1 = temp1 - 12 if temp1 >= 0 then coldet_check coldet_return return rem 2805 bytes of ROM space left temp1 = player0x - 21 if temp1 & 3 || temp1 > 108 then skip temp1 = temp1 / 4 if x3tbl[temp1] then gosub coldet2 skip return data x3tbl 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1 end 1 Quote Link to comment Share on other sites More sharing options...
bogax Posted December 5, 2022 Share Posted December 5, 2022 27 minutes ago, Al_Nafuur said: Unrolled loop is the biggest (but fastest) with only 2760 bytes of ROM space left I disagree (about fastest) you would do all 10 if statements for most numbers 1 Quote Link to comment Share on other sites More sharing options...
+Al_Nafuur Posted December 5, 2022 Share Posted December 5, 2022 8 minutes ago, bogax said: I disagree (about fastest) you would do all 10 if statements for most numbers Compared to my and @Karl G's code the unrolled loop is surely faster. Your code might have a good chance to be faster in an "worse case" scenario, but on average? I do not prevent anyone from cycle counting🤣 Quote Link to comment Share on other sites More sharing options...
+Al_Nafuur Posted December 5, 2022 Share Posted December 5, 2022 21 minutes ago, bogax said: I disagree (about fastest) After further investigation of your code, it appears to me that this is indeed the fastest solution. Quote Link to comment Share on other sites More sharing options...
Words Fail Posted December 7, 2022 Author Share Posted December 7, 2022 On 12/5/2022 at 7:51 AM, bogax said: if you gosub in the middle of a bunch of if statements you will return to the middle of the if statements and do a bunch of if statements you don't need to do your numbers are (n * 12) + 21 you can subtract 21 and test for a multiple of 12 that is in range any multiple of 12 will be a multiple of 4 you can test for a multiple of 4 by testing for bits 0 and 1 being 0 that will immediately eliminate 3/4 of possible numbers if you subtract 21 from a number 0..20 you get a result in the range (256 - 21) to 255 so you can eliminate numbers > 129 - 21 divide by 4 and look for multiples of 3 (12 = 3 * 4) you could look for numbers that are n mod 3 = 0 but probably simpler and faster to just use a lookup table something like this (untested) [code] temp1 = player0x - 21 if temp1 & 3 || temp1 > 108 then skip temp1 = temp1 / 4 if x3tbl[temp1] then gosub coldet2 skip data x3tbl 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1 end [/code] edit: fixed the table edit: Crap! ok, this time I really fixed the table.. Thanks. I see your comparison in the other post and it appears this one leaves with the most space left. I can compile with your code, I just can't understand the code in my head. Because that's only X checking, now I need to make up the code to check for Y as well. Based on the player X, Y position it'll do a pfread to see if that pixel is on. If it's on it turns it off (and the one next to it) and does a PFHLINE to get rid of two pixels. It then does a c=c-1 (that's the factor that determines your level is complete). .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. ................................ ................................ .XX.XX.XX.XX.XX.XX.XX.XX.XX.XX.. ................................ .XX.XX.XX.XX.XX.XX.XX.XX.XX.XX.. ................................ .XX.XX.XX.XX.XX.XX.XX.XX.XX.XX.. ................................ .XX.XX.XX.XX.XX.XX.XX.XX.XX.XX.. ................................ .XX.XX.XX.XX.XX.XX.XX.XX.XX.XX.. ................................ .XX.XX.XX.XX.XX.XX.XX.XX.XX.XX.. ................................ .XX.XX.XX.XX.XX.XX.XX.XX.XX.XX.. ................................ .XX.XX.XX.XX.XX.XX.XX.XX.XX.XX.. ................................ .XX.XX.XX.XX.XX.XX.XX.XX.XX.XX.. ................................ ................................ .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. ................................ end That's an example playfield.. ignore the top and bottom row of XXXXXXX's.. those are borders.. I may have them in the final game or I may not. I really wanted side borders also, but it's not possible because it needs to be a different color than the middle XX's. Unless I just chalk it up to only one color. Anyway, the XX in the middle, those are all the possible locations of what you can run over. There's spaces between the border and the actual playfield because the two lines look stupid next to each other. So the blocks you run over are only drawn in those XX locations and only in sets of two. When you run over them they both disappear using a PFHLINE command. For example, here's my long ass code for getting rid of the top two XX: coldet if player0x=21 then gosub col1 ... etc etc for each possible X. Then: col1 if player0y=18 then pfhline 1 3 2 off .. etc etc for each possible Y and I have a Google Spreadsheet wioth all the numbers so I could easily figure out what to turn off. Basically it's y position 3, 5, 7, 9, 11, 13, 15, 17, 19.. every other line. Then it returns to the other bank. That code takes up a whole freakin 4k bank and leaves me with 73 bytes. Which I don't need (at the moment) but would be nice to have if I need later. I also have no code currently for pfread, which will determine if the pixel is on or off. Quote Link to comment Share on other sites More sharing options...
Words Fail Posted December 7, 2022 Author Share Posted December 7, 2022 While I have people's attention.. I forget, is there some code I should run at the beginning of my game to kind of clear shit? Earlier when I started my game it always started with a black background.. I have COLUBK = $00. I don't know why, but sometimes my game starts with a random colored background. I just started the game red background, brown background, purple blackground, black FINALLY, then peach background, then peach again. I find if I put COLUBK into my mainloop it is always black, though. So I guess that's my answer for now. Quote Link to comment Share on other sites More sharing options...
+Karl G Posted December 7, 2022 Share Posted December 7, 2022 25 minutes ago, Words Fail said: While I have people's attention.. I forget, is there some code I should run at the beginning of my game to kind of clear shit? That shouldn't be necessary. bB games do an assembly routine at the beginning to have a clean start and be in a predictable state. 26 minutes ago, Words Fail said: Earlier when I started my game it always started with a black background.. I have COLUBK = $00. I don't know why, but sometimes my game starts with a random colored background. I just started the game red background, brown background, purple blackground, black FINALLY, then peach background, then peach again. That's very odd. That shouldn't happen, and I don't have any theories offhand other than in general it's probably a case of code you added since then not doing what you intended. You can probably get an idea of when it happens though with the Stella debugger. I can give details if you want to dig into it further. Quote Link to comment Share on other sites More sharing options...
bogax Posted December 7, 2022 Share Posted December 7, 2022 The more usual way is to check for a player-playfield collision and then convert player coordinates to playfield coordinates and use pfpixel Quote Link to comment Share on other sites More sharing options...
Words Fail Posted December 7, 2022 Author Share Posted December 7, 2022 9 minutes ago, bogax said: The more usual way is to check for a player-playfield collision and then convert player coordinates to playfield coordinates and use pfpixel Depends on your needs. Seems like it will not work for me. It's pixel perfect, meaning the front of my player touches the block it disappears. That's wrong. In mine you have to fly over the block to make it disappear, thus if you turn around mid flight because something is shooting at you or something, then the block does not disappear. That's how I have it setup and currently working. Quote Link to comment Share on other sites More sharing options...
Words Fail Posted December 7, 2022 Author Share Posted December 7, 2022 28 minutes ago, Karl G said: That shouldn't be necessary. bB games do an assembly routine at the beginning to have a clean start and be in a predictable state. That's very odd. That shouldn't happen, and I don't have any theories offhand other than in general it's probably a case of code you added since then not doing what you intended. You can probably get an idea of when it happens though with the Stella debugger. I can give details if you want to dig into it further. It all started when I tried to do this effect as seen in the attached post below. I downloaded it as a test, and ran it. Works fine. I added it to my code and it screwed things up, which I later found out you need the VBLANK function to be in the kernel bank, I guess bank1. Anyway, I removed the code and even reverted to an older version of my code. Now whenever I start the game I have no clue what the background color will be lol. Sometimes it's black 5 times in a row, sometimes multicolored and I won't see black for a few. Anyway putting COLUBK in my loop solved that. Quote Link to comment Share on other sites More sharing options...
+Karl G Posted December 7, 2022 Share Posted December 7, 2022 1 hour ago, Words Fail said: It all started when I tried to do this effect as seen in the attached post below. I downloaded it as a test, and ran it. Works fine. I added it to my code and it screwed things up, which I later found out you need the VBLANK function to be in the kernel bank, I guess bank1. Anyway, I removed the code and even reverted to an older version of my code. Now whenever I start the game I have no clue what the background color will be lol. Sometimes it's black 5 times in a row, sometimes multicolored and I won't see black for a few. Anyway putting COLUBK in my loop solved that. The kernel bank is the last bank, actually, so vblank needs to be defined there. Same goes for any included minikernels if you use any. I'm pretty confident that that is the cause of the weirdness. Edit: I missed that you said you removed the code in question, so that may not explain why you are encountering issues now. Quote Link to comment Share on other sites More sharing options...
bogax Posted December 7, 2022 Share Posted December 7, 2022 a variant of Karl G's for loop if (temp1 & 3) <> 1 then skip for temp1 = 21 to 129 step 12 if player0x = temp1 then gosub coldet2 goto skip next skip Quote Link to comment Share on other sites More sharing options...
Words Fail Posted December 7, 2022 Author Share Posted December 7, 2022 I saw someone on here had code to draw the playfield using data statements. I wonder if that is something I should look into. The data statements would define the initial level. If you run over something that has a one it would change it to zero, and also change my variable so it knows when the level is complete. Quote Link to comment Share on other sites More sharing options...
+Karl G Posted December 7, 2022 Share Posted December 7, 2022 5 hours ago, Words Fail said: I saw someone on here had code to draw the playfield using data statements. I wonder if that is something I should look into. The data statements would define the initial level. If you run over something that has a one it would change it to zero, and also change my variable so it knows when the level is complete. As it is now, the playfield is stored in RAM. The default 11 rows are in var0 - var43, and can be manipulated directly there (but see the manual for bit order). If you defined it in a data statement it would instead be in ROM and couldn't be changed. Quote Link to comment Share on other sites More sharing options...
Words Fail Posted December 13, 2022 Author Share Posted December 13, 2022 Just came back to working on this after a few days break. I have no idea how to proceed because it confuses me. I started working on trimming down my code a bit.. not sure if it all works yet, but I still don't know how to pfread the player0x/player0y coordinate. Someone suggested I can skip a bunch of code by not going over certain code if it doesn't need to.. good catch.. It's after midnight now, so I have to sleep, but I'll post some code tomorrow to try and figure this player0xy to pfread coordinate tomorrow. Quote Link to comment Share on other sites More sharing options...
KevKelley Posted December 13, 2022 Share Posted December 13, 2022 On 12/6/2022 at 9:36 PM, Words Fail said: Depends on your needs. Seems like it will not work for me. It's pixel perfect, meaning the front of my player touches the block it disappears. That's wrong. In mine you have to fly over the block to make it disappear, thus if you turn around mid flight because something is shooting at you or something, then the block does not disappear. That's how I have it setup and currently working. Couldn’t you just do the pfread conversions but define a temp variable depending on which direction you are going to add or subtract to the value so that the block doesn’t disappear until fully over it? Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.