Jump to content
IGNORED

Teach me how to shorten this code if possible..


Words Fail
 Share

Recommended Posts

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.

Link to comment
Share on other sites

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?
 

Link to comment
Share on other sites

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

 

  • Like 2
Link to comment
Share on other sites

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

 

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

 

Link to comment
Share on other sites

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 by Words Fail
Link to comment
Share on other sites


  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 by bogax
Link to comment
Share on other sites

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

 

Link to comment
Share on other sites

 

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

 

 

 

  • Like 1
Link to comment
Share on other sites

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🤣

 

Link to comment
Share on other sites

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.

 

 

 

 

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

 

 

Link to comment
Share on other sites

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.

 

 

 

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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. 

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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?

 


 

 

Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...