Jump to content
IGNORED

Backtab doesn't work. Help!


Recommended Posts

Did you shift from Color Stack mode to FG/BG mode?

 

In the file constants.bas, you have CS_CARD_DATA_MASK = $07F8 and FGBG_CARD_DATA_MASK = $01F8.

 

By converting those magical numbers to binary and comparing with the STIC, we find the following:

 

Color Stack mode
$0FF8 = 00 0 0 1 11111111 000
$07F8 = 00 0 0 0 11111111 000

The difference is that the value you used to use maintains the difference between GROM and GRAM.


FG/BG mode
$01F8 = 00 00 0 00 111111 000
$09F8 = 00 00 1 00 111111 000

Ditto, but notice that only 6 bits are used to point out which of the 64 GROM or GRAM cards. Two of the bits you accidentally masked with actually state the background colour.

  • Like 1
Link to comment
Share on other sites

4 hours ago, atari2600land said:

I screwed around with it and found backtab needed to be and #09f8 instead of #0ff8. It works now, but how?

I took the time to compile and run your code.  Sorry I couldn't respond sooner, but I had to hunt down a copy of constants.bas.

 

In Line 2, you're setting the graphics mode to Foreground/Background ("MODE 1").  Lines 92, 97, 102, and 107 are where you are calculating which card to look at based on player direction, as well as the bitmask to use.

 

The reason why $9F8 is the bitmask you want is because you're disregarding two of the background color bits.  Since your background color is white (color 7), those bits are raised.  Therefore, the IF statement:

IF #card = 319 * 8 THEN ...

in each of the following lines would never evaluate to TRUE, because it would depend upon having a black background (color 0).  (319 * 8, converted to Hexadecimal, equals $9F8.)

Link to comment
Share on other sites

No. The reason why it is $09F8 instead of $0FF8 is because you probably developed a game in CS mode before, but this one you're using FG/BG mode, much due to you are plotting a title screen.

 

By the way, you don't need to put the (c) sign using #BACKTAB. You can PRINT such characters too:

 

  MODE 1:DEFINE 63,1,graph:WAIT
  PRINT AT 140 color $1202,"\319","2021 CHRIS"

loop:  GOTO loop

graph:
  BITMAP "..****.."
  BITMAP ".*....*."
  BITMAP "*..***.*"
  BITMAP "*.*....*"
  BITMAP "*.*....*"
  BITMAP "*..***.*"
  BITMAP ".*....*."
  BITMAP "..****.."
Edited by carlsson
Link to comment
Share on other sites

OK, now I'm trying to make a puppy appear randomly inside the maze. I tried this:


    puppyx=rand(15)+1
    puppyx=(puppyx*8)+8
    
    puppyy=rand(10)+1
    puppyy=(puppyy*8)+8

    #card = #backtab((puppyy - 9) / 8 * 20 + (puppyx - 9) / 9) AND $09F8
    doigetnewpuppy=0     
    IF #card = 319 * 8 THEN doigetnewpuppy=1
    if prevpuppyx=puppyx and prevpuppyy=puppyy then doigetnewpuppy=1

(The dumb auto smiley face turns an 8 with a closed parenthesis into 8), so I changed it into 9 even though in the actual code it's an 8.)

This works, but the puppy only appears at a couple of spots every time, whereas I want it to appear at any place where there is no wall.

Link to comment
Share on other sites

I found this works.


    puppyx=(rand/16)+2
    puppyx=(puppyx*8)+8
    wait    
    puppyy=(rand/32)+3
    puppyy=(puppyy*8)+8
    wait
    #card = #backtab((puppyy-8)/8*20 + (puppyx-8)/8) AND $09F8
    doigetnewpuppy=0     
    IF #card = 319 * 8 THEN doigetnewpuppy=1
    if prevpuppyx=puppyx and prevpuppyy=puppyy then doigetnewpuppy=1

Essentially, putting "wait" into it really helps.

Link to comment
Share on other sites

Yes. The manual says that RAND and RAND(range) will generate a different number on each new frame, i.e. after a WAIT. You also have RANDOM(range) which is a little slower but doesn't require a new frame to get a new number.

 

Also I suppose puppyx and puppyy are meant to be sprite coordinates. Perhaps skip multiplying by 8 and adding the offset before you have checked the BACKTAB to simplify calculations a bit. You can make the "card2sprite" calculations after you have checked the BACKTAB.

Link to comment
Share on other sites

WHY DOES THIS HAVE TO BE SO HARD?! WHY DO I HAVE TO BE SO STUPID?!

All I want to do is if the square is \319 make it \317 and if it is \317 then make it \319 at the push of a button. Something else I can't do.


    if cont.button and movetimer=0 then
            buttonpressed=1
            #card = #backtab(cursory - 8 /8) * 20 + (cursorx - 8 /8) AND $09F8
            if #card = 317*8 then print at ((cursory-8)/8)*20+(cursorx-8)/8 color #color1,"\319" : buttonpressed=2
            if buttonpressed=1 and #card=319*8 then print at ((cursory-8)/8)*20+(cursorx-8)/8 color $2607,"\317" : buttonpressed=0    
            buttonpressed=0
        end if

This should work, but nooooooooo.

savethepuppiesintellivision.bas

Link to comment
Share on other sites

If you have the variables to spare, try to calculate the BACKTAB location once - not only in order to save code space and speed, but also to eliminate sources of error. I don't understand what buttonpressed is supposed to do, since #card only gets its value once.

 

Untested, I wrote write the above code passage like this:

 

IF CONT.BUTTON AND movetimer=0 THEN
  temp = ((cursory-8)/8)*20 + (cursorx-8)/8
  #card = #BACKTAB(temp) AND $09F8
  IF #card = 317*8 THEN PRINT AT temp COLOR #color1,"\319"
  IF #card = 319*8 THEN PRINT AT temp COLOR $2607,"\317"
  buttonpressed=0
END IF

 

Edited by carlsson
Link to comment
Share on other sites

That works, but why didn't my code? Buttonpressed was supposed to tell what the computer to do, like its status on card changing. I tried this on my LTO and the screen came up bare with no blocks. I had to modify the code a lot to make it so it displayed them. By the way, your code needed a thing to check to see if the key was being pressed. I put this in all my games:


CheckforNOKeys: Procedure
    Rem this procedure is to make sure the key buffer is cleared so presses don't fall thru.
    clearloop:
    k=cont
    wait
    if k then goto clearloop
    wait
end       

I don't know where it came from or who wrote it, but it works great.

Link to comment
Share on other sites

8 minutes ago, atari2600land said:

That works, but why didn't my code? Buttonpressed was supposed to tell what the computer to do, like its status on card changing. I tried this on my LTO and the screen came up bare with no blocks. I had to modify the code a lot to make it so it displayed them. By the way, your code needed a thing to check to see if the key was being pressed. I put this in all my games:

 


CheckforNOKeys: Procedure
    Rem this procedure is to make sure the key buffer is cleared so presses don't fall thru.
    clearloop:
    k=cont
    wait
    if k then goto clearloop
    wait
end       

 

I don't know where it came from or who wrote it, but it works great.

I believe this is your problem:

#card = #backtab(cursory - 8 /8) * 20 + (cursorx - 8 /8) AND $09F8

You forgot the parentheses to surround "(cursory - 8)," which causes the division to be performed first.  Division and multiplication have higher precedence than addition and subtraction, so your statement above is interpreted as this:

#card = #backtab(cursory - (8/8)) * 20 + (cursorx - (8/8)) AND $09F8

Notice the "(8/8)" which evaluates to "1".

 

    -dZ.

 

P.S. I want to make a suggestion, and I hope you do not take it in any negative way:  It would perhaps be more profitable if you were to avoid venting your frustrations in your comments, for it may be turning off some people who may otherwise be willing to help.  I know it can be frustrating when you encounter a problem, but the constant self-berating and exclamations about how hard it is or how incapable you are, is not really the best way to ask for assistance.  Take this as you will, but it is intended as a friendly advice.

 

Edited by DZ-Jay
Link to comment
Share on other sites

Yeah, I never downloaded the full source code so I got a chance to evaluate it.

 

Generally if you have a somewhat complex formula that you need to use twice or more, you benefit a lot from calculating it once and storing the result in a temporary variable. If nothing else, you only have one error source instead of three in your original code.

 

As for waiting for a key and make sure it is released, I have begun to use this code:

 

WHILE CONT=0:WEND
WHILE CONT<>0:WEND

 

Code example where you can test that it works for every key:

  MODE 1:WAIT
  i=240

loop:
  IF i>220 THEN
    FOR i=0 TO 11:PRINT AT i*20,"                    ":NEXT
    i=0
  END IF

  PRINT AT i,"PRESS A BUTTON"
  WHILE CONT=0:WEND
  WHILE CONT<>0:WEND
  i=i+20
  GOTO loop

 

It saves you a variable and no need (??) to wait for a new frame since you busy loop anyway.

Edited by carlsson
Link to comment
Share on other sites

9 minutes ago, carlsson said:

Yeah, I never downloaded the full source code so I got a chance to evaluate it.

 

As for waiting for a key and make sure it is released, I have begun to use this code:

 

WHILE CONT=0:WEND
WHILE CONT<>0:WEND

 

Code example where you can test that it works for every key:

 


  MODE 1:WAIT

  i=240

loop:
  IF i>220 THEN
    FOR i=0 TO 11:PRINT AT i*20,"                    ":NEXT
    i=0
  END IF

  PRINT AT i,"PRESS A BUTTON"
  WHILE CONT=0:WEND
  WHILE CONT<>0:WEND
  i=i+20
  GOTO loop

 

 

It saves you a variable and no need (??) to wait for a new frame since you busy loop anyway.

 

I agree with that approach.  In fact, I personally would encapsulate it in a subroutine so that it can be reused at any point.  This is the code I typically have.

'' ======================================================================== ''
''  WaitForIdle                                                             ''
''      Waits for the hand-controller to be completely idle.                ''
''                                                                          ''
''      Input:                                                              ''
''          None.                                                           ''
''                                                                          ''
''      Output:                                                             ''
''          None.                                                           ''
'' ======================================================================== ''
WaitForIdle: Procedure
    Do : Loop Until (CONT = 0)
    Return
End

Notice that my loop is slightly different.  This is because "Loop Until <test>" will fall-through when the test fails, branching back otherwise; whereas "while <test>" performs the test first and branches out on failure, but still branches back unconditionally at the bottom.  The former generates slightly more efficient code.

 

A "DEF FN" macro would be even faster, if you need that, but would generate bulkier code, since it would have to inject the code repeatedly on every use.

 

My typical game loop then includes something like:

MainLoop:
    Wait
    Gosub WaitForIdle
    Gosub DecodeInput

    ' ...
Goto MainLoop

 

     -dZ.

Edited by DZ-Jay
  • Like 1
Link to comment
Share on other sites

I suppose in this use case, one would want to read the controllers on the fly. If it was non-zero, you would store the input, wait for the key to be released and then move on. That can certainly be put in a subroutine, and the main program acts on whether the variable holding last keypress is set or not. The exact usage may vary depending on situation.

Link to comment
Share on other sites

40 minutes ago, carlsson said:

I suppose in this use case, one would want to read the controllers on the fly. If it was non-zero, you would store the input, wait for the key to be released and then move on. That can certainly be put in a subroutine, and the main program acts on whether the variable holding last keypress is set or not. The exact usage may vary depending on situation.

There are various use cases, one of them being "wait for the controller to be released, then return when any key is pressed."  You could write code specifically for each use case, but you could also just generalize the functions for "wait for the controller to be released" and the "wait for any key."  That way, depending on the use case, "wait for any key" could be replaced by "get disc input," or "decode full controller input," or "is button pressed?," etc. -- all of which could require a "wait for the controller to be released" first.

 

In my experience so far, for most cases, this generalization should work and is practical -- especially for the kind of games that Chris typically makes*.  Perhaps a highly complex game that maximizes hardware resources would require a more optimized approach in order to keep up with the speed of the game; but then, I would suspect that those are the kind of specialized games that require specialized solutions for many other things as well.

 

From what I've seen of most IntyBASIC games that read the hand controller at 60 Hz, once per frame, calling a subroutine to do so is hardly the bottleneck choking point.

 

   -dZ.

 

 

* Not to be taken as a slight at all.

Edited by DZ-Jay
Link to comment
Share on other sites

I guess I can share what I have now. This game is called "Save the Puppies!" This game has you going around collecting puppies that pop up on the screen. Eventually I will add enemies. I think I'm close to that point now. I have in sound effects and music. And a game editor that lets you build your own levels.

To use the level editor, press 2 on the title screen. You can't move the cursor to the upper-left spot, that spot is reserved for your starting point. To put in a block, press a button and to erase a block, move the cursor to one and press a button again. When you're all ready to play your game with your level you created, press Enter and the game will start with your custom level. Thoughts?

savethepuppiesintellivision.rom

  • Like 1
Link to comment
Share on other sites

I suppose the ability to only move one card at a time is a decision, not a coding limitation? It works in emulation, but I don't know how it will work on real hardware pressing the disc, release, pressing it again in the same direction, release etc. Have you considered diagonal movement? With the above ROM, I'm getting a blank white screen plus a few slash characters to the right, so navigating to the puppy is only a matter of pressing and releasing the controller enough times. The level editor sounds nice, but I can't seem to place any blocks regardless which key I press except Enter that ends the editor.

 

Edit: Also the player is able to escape the screen entirely, which may or may not be a game decision or I am missing something regarding boundaries.

Edited by carlsson
Link to comment
Share on other sites

Yes, much better. Now I get the level design and the slashes are replaced by a score counter. There must've been something weird happening with the bin2rom conversion, perhaps the JLP flag was omitted.

 

It pretty much eliminates diagonal movement. Others would have to comment how playable it is to push the disc repeatedly. The editor is fine, perhaps a bit on the slow side so that you thought you moved the cursor and press the button, to get a block erased in the previous location instead of placed in the new one.

 

If you want suggestions, you might want to consider a Pengo/Boulder Dash mechanic so the player can push blocks to the side, either to block or squish future enemies, of course avoiding squishing the puppy. Perhaps the enemies will throw a bone so the puppy runs after it, or they will simply steal the puppy.

Edited by carlsson
Link to comment
Share on other sites

27 minutes ago, atari2600land said:

I guess I can share what I have now. This game is called "Save the Puppies!" This game has you going around collecting puppies that pop up on the screen. Eventually I will add enemies. I think I'm close to that point now. I have in sound effects and music. And a game editor that lets you build your own levels.

To use the level editor, press 2 on the title screen. You can't move the cursor to the upper-left spot, that spot is reserved for your starting point. To put in a block, press a button and to erase a block, move the cursor to one and press a button again. When you're all ready to play your game with your level you created, press Enter and the game will start with your custom level. Thoughts?

savethepuppiesintellivision.rom 10.06 kB · 2 downloads

Cute!  It reminds me of another game ... :ponder:

 

It could use an octopus, though. :lol:

 

A few suggestions:

  • Do not force the player to release the disc in order to move; the avatar should continue to move for as long as the controller is pressed and there is a path.
  • Try to force the re-spawn of the puppy farther away from the player.  Right now, it seems rather common to get a new puppy right at my feet.  On one occasion, I noticed that the "pick-up-puppy" ring sound effect went much too long, and then I realized that it was that the new puppy popped up right under my feet!
  • Definitely needs some enemies.
  • In the absence of enemies, it occurs to me that perhaps the puppy could move around, albeit slowly, while you attempt to find your way to it.  After all, unleashed puppies seldom stay in one place.
  • The level editor is very cool, but perhaps it should not allow me to fill the entire screen with blocks.  Try to force at least two (I would suggest maybe more) contiguous empty spaces in the screen:
    shot0015.gif.3e6fb454fd70e0b14896d7c974323107.gif  (OMG!  There are no puppies!)

 

On that last item, you could do a final check before starting the game.  Then, if an "invalid screen" is detected, a buzzer could play and abort.  That way, you force the player to fix it before continuing.

 

If you need help validating the screen let us know.  I can think of some simple algorithms to do a check before exiting the editor.

 

   -dZ.

Edited by DZ-Jay
Link to comment
Share on other sites

I will be definitely adding in enemies.

As for validating the edited level, I would like it to make sure that there is no space that the guy can't get to, like in the screenshot below.

shot0024.gif.f1febb678332eb998f57d900c9da8709.gif

I'll try getting rid of the --jlp flag and see if that helps with the .ROM not working on LTO Flash. I wondered whether or not someone would try to do what DZ-Jay did. I thought the puppy would always show up at that spot and the game's score would keep going up and up (until an enemy is touched, once I add them in.)

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...
  • Recently Browsing   0 members

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