Jump to content
IGNORED

screen memory


Descolado

Recommended Posts

Hi,

 

Sorry my english.

I'm working in a game that use several screens. My player can move between screens, by example, he can move from Screen 1 to Screen 2 and can go back to Screen 1.

After draw the screen I'm putting objects using PRINT AT (my MOB not use "COL" to colision detection, I'm using other system).

 

In Screen 1 my player can open a door or touch a obstacle and I replace the card) and move to Screen 2.

 

If my player go back to Screen 1 I need "remember" what Card he touched and not to put it back on the screen.

 

When my player touch a CARD I need "save" this CARD in any place in memory but I don't know how because CARDs can't be "marked".

I can use a "screen memory":
Screen_0(X), Screen_1(X), etc, where "X" is the number of sprites in my screen that my MOB can "hit" but I think it's going to be a lot of work because I have more than 50 screens.

Link to comment
Share on other sites

Hi,

 

Sorry my english.

I'm working in a game that use several screens. My player can move between screens, by example, he can move from Screen 1 to Screen 2 and can go back to Screen 1.

After draw the screen I'm putting objects using PRINT AT (my MOB not use "COL" to colision detection, I'm using other system).

 

In Screen 1 my player can open a door or touch a obstacle and I replace the card) and move to Screen 2.

 

If my player go back to Screen 1 I need "remember" what Card he touched and not to put it back on the screen.

 

When my player touch a CARD I need "save" this CARD in any place in memory but I don't know how because CARDs can't be "marked".

I can use a "screen memory":

Screen_0(X), Screen_1(X), etc, where "X" is the number of sprites in my screen that my MOB can "hit" but I think it's going to be a lot of work because I have more than 50 screens.

That's actually a common problem. One way would be to pack the screen "hit" data in some custom format and store it in memory, as an array.

 

For 50 screens, an array with a byte for every card on screen may be too expensive, but perhaps there are patterns that you could identify in order to pack them.

 

For instance, if it is only the state of a door, and there are 4 doors per screen, then you need at most 4 bits to store the state of each screen. You can then pack 4 screens in a 16-bit variable, which will reduce your RAM requirements to 13 words.

 

I can't help further because I am not familiar with the nature of the state data you wish to track.

 

I hope this helps.

 

dZ.

Link to comment
Share on other sites

In Sydney Hunter and the Sacred Tribe, all rooms have the objects drawn in the rooms, but I've a small list for each room, similar to this:

 

    DATA 6*20+10,1  ' Position and type of object
    DATA 0
I think you could use a simple 8-bits array for keeping item state, and once you detected the item is taken, you mark the element of array with a bit to one (in case you have several items).

 

When drawing the room, you erase the object if the bit is set for that room.

 

For keeping an inventory you need to choose between only having one item at a time, or several items. If you have upto 8 items at same time then you can use a single byte to keep track of it.

 

If you can have more objects than these, the you would use another 8-bits array and insert/displace when taking item/losing item.

Link to comment
Share on other sites

It should take 4 bytes to remember which tile been taken. You should have a screenID number for the screens that you have, You store the screen number, x,y, #TileID, in 5 bytes. You can probably split the TileID into 2 bytes and not waste word on tileID. After the screen has being printed on screen, you can check what screen ID is in your array, if it is, then poke that tile on screen.

Link to comment
Share on other sites

Hmmm... interesting suggestions!

 

Sem título

 

I was thinking. Many cards in my screen are statics, how doors, keys and others objects. When my MOB touch it I "delete" the card (PRINT AT X_Card, 0).
When my player touch a CARD I can take only two informations about it: SCREEN and COORDENATES.
Before create a screen, I need save this two informations in someplace. I was thinking save in array:

 

DIM Screen_5(3)
Screen_5(0) = 181 'left door X position
Screen_5(1) = 186 'key X position
Screen_5(2) = 197 'right X door position

 

Then, if my player touch the KEY card, I will put "zero" in index 1 (Screen_5(1) = 0). If my player go back to the screen 5, I will read all index of Screen_5:

 

If CurrentScreen = 5 THEN
If Screen_5(0) > 0 THEN PRINT AT Screen_5(0), DOOR_LEFT
If Screen_5(1) > 0 THEN PRINT AT Screen_5(1), KEY
If Screen_5(2) > 0 THEN PRINT AT Screen_5(2), DOOR_RIGHT
END IF

 

But if I use SCREEN_0(X), SCREEN_1(X)... SCREEN_50(X) etc, I don't will have enough 8bits variables to save ALL cards because each screen can have 3 to 10 objects that my MOB can "hit" and I have only 179 8-bit variables available. I can use JLP but I do not like this idea.

 

Thanks by suggestions, I'll look for more information in the forum about it.

 

Link to comment
Share on other sites

You could limit each room to 8 interactive objects and dedicate an object status variable to each room.
Dedicate another variable to door status for 4 rooms, and toggle bits when items are hit or doors are opened/closed.
Keep all of the coordinate data in tables.

Assuming 50 rooms, 50 object vars + (50/4) door vars = 63 8-bit variables

 

If you were to limit the amount of rooms to 40 or 45, you could pack each room into its own 16-bit variable.

This allows you to add more doors and items to each room while leaving a couple 16-bit variables for other uses.

 

Example code:

 

Screen_5678_Door_Status = 0000 0000
                          |||| ||||
                          |||| |||5L
                          |||| ||5R
                          |||| |6L
                          |||| 6R
                          ||||
                          |||7L
                          ||7R
                          |8L
                          8R
 
Screen_5_Objects = 0000 0000
                   |||| ||||
                   |||| |||object 0
                   |||| ||object 1
                   |||| |object 2
                   |||| object 3
                   ||||
                   |||object 4
                   ||object 5
                   |object 6
                   object 7

Screen_5_Data:
   data (#)    left door x position
   data (#)    'right door x position
   
   data (#)    'object 0 position
   data (#)    'object 1 position
   data (#)    'object 2 position
   data (#)    'object 3 position
   data (#)    'object 4 position
   data (#)    'object 5 position
   data (#)    'object 6 position
   data (#)    'object 7 position

'==========Example 16-bit variable==========
Screen_5_Status: 0000 0000 0000 0000
                 |||| |||| |||| ||||
                 |||| |||| |||| |||left door 0 status
                 |||| |||| |||| ||right door 0 status
                 |||| |||| |||| |left door 1 status
                 |||| |||| |||| right door 1 status
                 |||| |||| ||||
                 |||| |||| |||object 0 status
                 |||| |||| ||object 1 status
                 |||| |||| |object 2 status
                 |||| |||| object 3 status
                 |||| ||||
                 |||| |||object 4 status
                 |||| ||object 5 status
                 |||| |object 6 status
                 |||| object 7 status
                 ||||
                 |||object 8 status
                 ||object 9 status
                 |object 10 status
                 object 11 status

 

 

  • Like 2
Link to comment
Share on other sites

Expanding on Emerson's ideas...

 

You can't pick up doors, only open or close them? Does each screen have a different number of doors? I'm thinking something like in ROM you have each room defined in some way, and then you could pack bits:

 

DIM north_doors(7), south_doors(7), east_doors(7), west_doors(7) : REM would be enough for 7*8 = 56 rooms

 

bit = 1

i = CurrentScreen % 8

WHILE i>0 : bit = bit * 2: i=i-1 : WEND : REM I didn't find any ^ operator in the language?

 

IF (north_door(CurrentScreen / 8 ) AND bit) > 0 THEN ...

IF (south_door(CurrentScreen / 8 ) AND bit) > 0 THEN ...

 

In case you only have doors in two directions as indicated by the screenshot, you can of course omit two of the arrays.

Edited by carlsson
Link to comment
Share on other sites

i = CurrentScreen % 8

WHILE i>0 : bit = bit * 2: i=i-1 : WEND : REM I didn't find any ^ operator in the language?

 

You're probably better off using a lookup table here. And with some DEF FN macros, you can get some rather compact and readable code.

 

Borrowing some code I wrote in a different thread:

.

DEF FN SetBit(var, bit) = var = NOT (NOT var AND ClrMask(bit))
DEF FN ClrBit(var, bit) = var = var AND ClrMask(bit)
DEF FN TstBit(val, bit) = ((val) AND SetMask(bit))

' This is the same as the power-of-2 table, so you can reuse that
' if you've already got it somewhere, rather than adding a redundant table.
SetMask:  DATA $0001, $0002, $0004, $0008
          DATA $0010, $0020, $0040, $0080
          DATA $0100, $0200, $0400, $0800
          DATA $1000, $2000, $4000, $8000

' This is the bitwise-inverse of the SetMask table.
ClrMask:  DATA $FFFE, $FFFD, $FFFB, $FFF7
          DATA $FFEF, $FFDF, $FFBF, $FF7F
          DATA $FEFF, $FDFF, $FBFF, $F7FF
          DATA $EFFF, $DFFF, $BFFF, $7FFF

.

Taking that a step further, you can extend these to index into 8-bit and 16-bit arrays. Note, SetBitXX and ClrBitXX burn one 8-bit variable named 'tmp', but it makes for slightly faster code. You can get rid of 'tmp' by replacing 'tmp' with '(idx)/8'. It's only about 11 cycles slower if I counted right, and doesn't burn an 8-bit variable.

.

' Manipulate bitmaps built on 8-bit arrays
DEF FN SetBitA8(arr, idx) = tmp = (idx)/8 : arr(tmp) = NOT (NOT arr(tmp) AND ClrMask((idx)%)
DEF FN ClrBitA8(arr, idx) = tmp = (idx)/8 : arr(tmp) = arr(tmp) AND ClrMask((idx)%
DEF FN TstBitA8(arr, idx) = (arr((idx)/8) AND SetMask((idx)%)

' Manipulate bitmaps built on 16-bit arrays
DEF FN SetBitA16(arr, idx) = tmp = (idx)/16 : arr(tmp) = NOT (NOT arr(tmp) AND ClrMask((idx)%16))
DEF FN ClrBitA16(arr, idx) = tmp = (idx)/16 : arr(tmp) = arr(tmp) AND ClrMask((idx)%16)
DEF FN TstBitA16(arr, idx) = (arr((idx)/16) AND SetMask((idx)%16))

.

So, with that, your example becomes:

.

DIM NorthDoors(7), SouthDoors(7), EastDoors(7), WestDoors(7) : REM would be enough for 7*8 = 56 rooms
 
IF TstBitA8(NorthDoors, CurrentScreen) THEN ...
IF TstBitA8(SouthDoors, CurrentScreen) THEN ...
IF TstBitA8(EastDoors,  CurrentScreen) THEN ...
IF TstBitA8(WestDoors,  CurrentScreen) THEN ...

.

The TstBitA8 sequences above generate pretty decent code as far as IntyBASIC code goes:

.

    ;[34]     IF TstBitA8(NorthDoors, CurrentScreen) THEN A = 1
    SRCFILE "/tmp/doors.bas",34
    MVII #array_NORTHDOORS,R1
    MVI var_CURRENTSCREEN,R2
    SLR R2,2
    SLR R2,1
    ADDR R2,R1
    MVI@ R1,R0
    MVII #label_SETMASK,R1
    MVI var_CURRENTSCREEN,R2
    ANDI #7,R2
    ADDR R2,R1
    AND@ R1,R0
    BEQ T2
    MVII #1,R0
    MVO R0,var_A

.

The SetBitA8 / ClrBitA8 are handy if you need to change the state of the bits in the bitmap—say, to open or close a door or something.

Edited by intvnut
  • Like 1
Link to comment
Share on other sites

Thanks for help, guys. I'm learning to program at Intybasic so sorry, I'm a noob.

I'm using TABLES to save X and Y sprites (this project is teaching me a lot of cool things about Intybasic) but your knowledge is a little beyond my understanding.

I understand what I need to do, I just need some tips on HOW to do this.

 

Question: How do I verify each BIT position in a 8-bit variable?

Example:

 

DIM MyScreen5: MyScreen5 = 255 'REM 1111 1111

 

When my MOB touch one KEY, I will change variable:

 

MyScreen5 = 1111 1110 'REM Bit[7] OFF

 

If my MOB open a DOOR in screen5, I will change to:

 

MyScreen5 = 1111 1010 'REM BIT[5] OFF

 

Then, positions [5] and [7] are OFF.

 

How I check this positions? I can't use FOR I = 0 TO 7 because "MyScreen5" is not an ARRAY.

 

Thanks!

Link to comment
Share on other sites

Thanks for help, guys. I'm learning to program at Intybasic so sorry, I'm a noob.

 

I'm using TABLES to save X and Y sprites (this project is teaching me a lot of cool things about Intybasic) but your knowledge is a little beyond my understanding.

I understand what I need to do, I just need some tips on HOW to do this.

 

Question: How do I verify each BIT position in a 8-bit variable?

Example:

 

DIM MyScreen5: MyScreen5 = 255 'REM 1111 1111

 

When my MOB touch one KEY, I will change variable:

 

MyScreen5 = 1111 1110 'REM Bit[7] OFF

 

If my MOB open a DOOR in screen5, I will change to:

 

MyScreen5 = 1111 1010 'REM BIT[5] OFF

 

Then, positions [5] and [7] are OFF.

 

How I check this positions? I can't use FOR I = 0 TO 7 because "MyScreen5" is not an ARRAY.

 

Thanks!

 

 

You can use AND with a lookup table to test individual bits. For example:

.

FOR I = 0 TO 7
  IF MyScreen5 AND SetMask(I) THEN
    ' Handle case where bit is set
  ELSE
    ' Handle case where bit is clear
  END IF
NEXT I


' Elsewhere, outside of a Procedure,
' include this lookup table:
SetMask: DATA $0001, $0002, $0004, $0008
         DATA $0010, $0020, $0040, $0080
         DATA $0100, $0200, $0400, $0800
         DATA $1000, $2000, $4000, $8000

.

Earlier in the thread, I offered some macros and lookup tables that make this even more convenient:

.

DEF FN SetBit(var, bit) = var = NOT (NOT var AND ClrMask(bit))
DEF FN ClrBit(var, bit) = var = var AND ClrMask(bit)
DEF FN TstBit(val, bit) = ((val) AND SetMask(bit))

' This is the same as the power-of-2 table, so you can reuse that
' if you've already got it somewhere, rather than adding a redundant table.
SetMask:  DATA $0001, $0002, $0004, $0008
          DATA $0010, $0020, $0040, $0080
          DATA $0100, $0200, $0400, $0800
          DATA $1000, $2000, $4000, $8000

' This is the bitwise-inverse of the SetMask table.
ClrMask:  DATA $FFFE, $FFFD, $FFFB, $FFF7
          DATA $FFEF, $FFDF, $FFBF, $FF7F
          DATA $FEFF, $FDFF, $FBFF, $F7FF
          DATA $EFFF, $DFFF, $BFFF, $7FFF

.

This is how you'd use them to set/clear/test flags in your example:

.

DIM MyScreen5

MyScreen5 = 255

' To clear bit 7 in MyScreen5:
ClrBit(MyScreen5, 7)

' To clear bit 5 in MyScreen5:
ClrBit(MyScreen5, 5)

' To clear bit indicated by variable I in MyScreen5:
ClrBit(MyScreen5, I)

' Set bit 7 in MyScreen5:
SetBit(MyScreen5, 7)


' To test a single bit:
IF TstBit(MyScreen5, 5) THEN ...

' To test a bit in a loop:
FOR I = 0 to 7
  IF TstBit(MyScreen5, I) THEN
    ' Handle the bit set case
  ELSE
    ' Handle the bit clear case
  END IF
NEXT I

.

And just a note: Typically bits are numbered in decreasing order, rather than increasing order. That is, the bit order goes 76543210. That corresponds to the value of each bit numerically. Bit 7 = 128 = 27, while bit 0 = 1 = 20.

 

If you write them in that order, then the relationship between binary and hexadecimal also becomes clearer, and shows the advantage of using hexadecimal when dealing with bitmaps:

.

 Dec   Hex   7654_3210  <- Bit numbers
----------------------
   0 = $00 = 0000_0000
   1 = $01 = 0000_0001
   2 = $02 = 0000_0010
   4 = $04 = 0000_0100
   8 = $08 = 0000_1000
  16 = $10 = 0001_0000
  32 = $20 = 0010_0000
  64 = $40 = 0100_0000
 128 = $80 = 1000_0000

 255 = $FF = 1111_1111
 254 = $FE = 1111_1110
 253 = $FD = 1111_1101
 251 = $FB = 1111_1011
 247 = $F7 = 1111_0111
 239 = $EF = 1110_1111
 223 = $DF = 1101_1111
 191 = $BF = 1011_1111
 127 = $7F = 0111_1111

  • Like 1
Link to comment
Share on other sites

You can also flip bits with XOR. That is, sometimes you know already the state of a bit and you just need to toggle it without testing which way it is. The trick to bear in mind when using masks is this:

  • XOR:
    • 0 = leave the bit the same
    • 1 = toggle the bit (if 0, then 1; if 1 then 0)
  • AND:
    • 1 = leave the bit the same
    • 0 = clear the bit

 

So, let's say that you want to clear bit 5:

      bit 5 = 1
      |
      v
    11101101
AND 11011111
    --------
    11001101  = Bit 5 cleared without changing the others

Or let's say you need to toggle that bit instead, so that if it is zero, it turns to one; and if it is one, it turns to zero:

      bit 5 = 1
      |
      v
    11101101
XOR 00100000
    --------
    11001101  = Bit 5 is zero now


      bit 5 = 0
      |
      v
    11001101
XOR 00100000
    --------
    11101101  = Bit 5 is one now
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...