Jump to content
IGNORED

The Sentinel - My first project


Recommended Posts

Hi guys,
I'm here to ask you some technical suggestions for my ambitious project, called "The Sentinel". My goal is to finish it and publish it (somewhen, somewhere, someway) as a paid (cheap ? ) product, if it will become nice. 
It wants to be a Cyber Protocol style game..that's a game I really like, I also reached the second place of the $1000 contest, and even if I never had my reward.....I still love it.


About the game: you're inside a grid, think to pacman, but every level has a different grid, or better it's a little maze. You have to collect coins and you'll encounter different kind of enemies in your journey. The particularity of your character is that its velocity is very fast, and you cannot brake: when you choose a direction to go, only a wall or an enemy can stop you. Or better, this is what happens in the original game, while in "The Sentinel" you'll have some kind of brakes enabled..
See here a video of the gameplay of the game.

 

I repeat, it's VERY ambitious, and I would have to fall down to a lot of trade-offs, but I want to try ?
So, I started develop the logic, and here (rom and level map ) you can find the first implementation, which is WITHOUT SCROLL. Please don't judge me for the graphic, I'm just still working on the skeleton of the game..

The enemies here are rendered as sprites (MOB)...but this kind of enemy will be the only one used as MOB, all the other ones will be rendere as changing background. Think to "Space Armada" or "Frogger", but in my case they won't be moveable.

The text file contains the map of the level. If you open it with notepad++, by double clicking on a 'II' (or on a 'XX') you can see the maze. And about all this, thanks to @nanochess for his book ?

 

image.png.7c516e75b5307efa872986028b4d145d.png

 

If you run the game (no coins yet. ? ), in the left-up part of the screen you can see some dots moving: that's the real logic of the game, a virtual 32x32 grid where every position is a pixel. I then render every position and sprite with the classic 8x8 bitmap related data. Of course, not the whole grid can be visible, without scrolling.


So I then created the scroll logic (on 8 directions), where the "camera" (sorry for using this word related to a futuristic concept ?) follows the character, which can move everywhere in the grid. You can find them here (rom and level map)

 

image.png.d9b0b937cfe05f37e0edf02fc8c8684a.png

 

And now it comes the problem, related to the 159x96 pixel screen and its obvious limitations.. I want to reproduce the 'fun' of the original game, but if a level is tricky, a continuous scroll I think would be annoying, and would generate some headaches too. So, exactly as the original game, I started to develop a kind of zoom-out, by reducing all sizes. Here is the result (it's just visible, not playable) of the now_became 48x48 grid:

(rom and level map)

 

image.png.e2b2a09265e885c078ca5facd739573d.png

As you can see, the level is 'shorter'.


And now come the technical suggestions I need. 
In order to zoom-out the level, I've taken a square of four continuous blocks of the level, and statically coded the 8x8 resulting block:

                     
|--------|--------|       |--------|
| 8x8    |  8x8   |       |8x8     |
| Wall   |  Wall  |       |Miniwall|
|        |        |       |        |
|        |        |       |        |
|--------|--------|  -->  |--------|  
|        |        |
| 8x8    |  8x8   |
| Wall   |  Wall  |
|        |        |
|--------|--------|


|--------|--------|       |--------|
| 8x8    |  8x8   |       |8x8     |
| Empty  |  Wall  |       |Halfwall|
|        |        |       |   1    |
|        |        |       |        |
|--------|--------|  -->  |--------|  
|        |        |
| 8x8    |  8x8   |
| Empty  |  Wall  |
|        |        |
|--------|--------|


|--------|--------|       |--------|
| 8x8    |  8x8   |       |8x8     |
| Wall   |  Empty |       |Halfwall|
|        |        |       |   2    |
|        |        |       |        |
|--------|--------|  -->  |--------|  
|        |        |
| 8x8    |  8x8   |
| Wall   |  Empty |
|        |        |
|--------|--------|

Etc...

 

I created all the possible combinations Wall-Empty, by coding statically the 8x8 bitmap representations for GRAM. This is obviously the wrong way, because it's unthinkable to statically create ALL the combinations Wall-Empy-Enemy1-Enemy2-Enemy3.., since enemies (and coins) will be like walls. But I had a (fake) ace in the hole, thinking that there was no problem on this: I thougth that there was no need to create every single combination, since with PEEK and POKE I could change dinamically every single pixel in a 8x8 tile of a rendered backtab. And I was wrong.. you can only change the whole 16bit pointer variable, which means that I can simply dinamically switch to another predefined 8x8 bitmap in GRAM..is this right?

 

So..my questions:
1) Can I dinamically change the pixel content (0 to 1 or viceversa) of an 8x8 tile on the screen (not with peek/poke but maybe with other directives)? Maybe not ?
2) Instead of a static way, is there a dynamic way for create my 8x8 bitmap to load?
3) If answer 2 is yes: lot of 8x8 bitmaps would be genereated, so in order to avoid to full the memory, can I unload some already-loaded 8x8 bitmaps from GRAM?
4) Do you see another way to 'reduce' four 8x8 blocks into one?

 

Thank you

 

EDIT:

Added also the "Zoomin version"

 

level_0_initial.bas level_0_scroll.bas level_0_zoomout.bas theSentinel_initial.rom theSentinel_scroll.rom theSentinel_zoomout.rom

theSentinel_zoomin.rom

Edited by jenergy
  • Like 7
Link to comment
Share on other sites

3 hours ago, jenergy said:

Hi guys,
I'm here to ask you some technical suggestions for my ambitious project, called "The Sentinel". My goal is to finish it and publish it (somewhen, somewhere, someway) as a paid (cheap ? ) product, if it will become nice. 
 

 

Welcome!  The game looks cool so far.  I will check it out this week.

 

Quote

 

So..my questions:
1) Can I dinamically change the pixel content (0 to 1 or viceversa) of an 8x8 tile on the screen (not with peek/poke but maybe with other directives)? Maybe not ?

If you are looking to update GRAM as if it were a bitmap, then you cannot.  You can access individual bytes for each card in GRAM, though, but you still need to manipulate the bits in a register, which means moving it in then out.

 

In IntyBASIC, this means using Peek() and Poke().  To update a BACKTAB word, you can access it directly using the #BACKTAB array, but the results are the same as Peek() and Poke().

 

For better or worse, the Intellivision is “word-addressable,” so you can only access a full 16-bit word at a time.  (For 8-bit memory, the upper byte is hardwired to zeros, but the principle remains.)


Moreover, updating GRAM can only be done during the “vertical blanking,” every 1/60th of a second (in NTSC), which adds an extra layer of limitations to your problem.


Updating the BACKTAB, however, can be done at any moment.

 

(And since you asked, you can change the GRAM card used in any particular location by changing the card index of a BACKTAB word.  You will have to read the value, mask the field, then add the new card index.

 

Note that the card index field starts at the fourth bit from the right, so you need to shift your values accordingly.)

 

Quote

2) Instead of a static way, is there a dynamic way for create my 8x8 bitmap to load?

If you use GRAM exclusively for it, then you can treat it as an 8x8 buffer for your maze.  Updating it bit by bit will still be very expensive (unless you can localize your changes to a very small set if cards per frame), so perhaps you’ll need to keep a buffer of the background in RAM.

 

A buffer of 64 8x8 cards will require 512 bytes, or 256 16-bit words.  That’s a big chunk, but typical modern cartridges include up to 8K of additional 16-bit RAM.

 

If anything, you could leverage the extra 2K of 8-bit RAM provided by the ECS.

 

It’s a lot, but maybe it is the easiest way to handle your requirements.  You can then manipulate the buffer and then blit the updated cards into GRAM on the next frame.

 

A game like yours does not strike me as one that requires “twitch-level” reaction and rendering at 60 Hz, so taking a few frames to compose your scene and update the world state should not be a big deal.

 

Quote


3) If answer 2 is yes: lot of 8x8 bitmaps would be genereated, so in order to avoid to full the memory, can I unload some already-loaded 8x8 bitmaps from GRAM?

 

GRAM can be changed at will throughout your game, provided it is done so during vertical blanking.

 

In other words, you don’t have to set GRAM once at the beginning and stick to it:  You can update it as needed.

 

As a matter of fact, this is a common technique used for animating sprites on an Intellivision:  Update it’s GRAM card on every frame or so.  We call it “GRAM cycling.”

 

Quote

 

4) Do you see another way to 'reduce' four 8x8 blocks into one?


 

What do you mean “reduce … into one”?

 

If you separate your rendering from the world state (as suggested above), then you can keep the state of your world using a more concise approach.

 

Maybe you can just record the position of walls or enemies as a set of bits within one or more 16-bit words.

 

You can then use that to track their movements.  Afterwards, you then use that information to compose your scene or update the GRAM cards and BACKTAB as necessary.

 

I hope this helps.  I’m sure other people can offer more suggestions.

 

    dZ.

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

2 hours ago, DZ-Jay said:

Welcome!  The game looks cool so far.  I will check it out this week.

Thanks, and thank you for your answer. And I'm very sorry for the questions I'm going to do ?

 

2 hours ago, DZ-Jay said:

In IntyBASIC, this means using Peek() and Poke().  To update a BACKTAB word, you can access it directly using the #BACKTAB array, but the results are the same as Peek() and Poke().

For better or worse, the Intellivision is “word-addressable,” so you can only access a full 16-bit word at a time.  (For 8-bit memory, the upper byte is hardwired to zeros, but the principle remains.)

Moreover, updating GRAM can only be done during the “vertical blanking,” every 1/60th of a second (in NTSC), which adds an extra layer of limitations to your problem.

Updating the BACKTAB, however, can be done at any moment.

(And since you asked, you can change the GRAM card used in any particular location by changing the card index of a BACKTAB word.  You will have to read the value, mask the field, then add the new card index.

Note that the card index field starts at the fourth bit from the right, so you need to shift your values accordingly.)

This is what I didn't understand.

Just suppose I want to change the first 8x8 cell of backtab:

 

#Mcard= peek ($200)

#Mcard= <manipulate it>

poke($200,#Mcard)

 

In the manipulation step, I cannot 'change' bits. With the exception of colors, I can only change a reference to an already statically defined memory block 8x8. So, I'm stucked, because I need to prefill all of them. Is this correct?

 

2 hours ago, DZ-Jay said:

If you use GRAM exclusively for it, then you can treat it as an 8x8 buffer for your maze.  Updating it bit by bit will still be very expensive (unless you can localize your changes to a very small set if cards per frame), so perhaps you’ll need to keep a buffer of the background in RAM.

...

It’s a lot, but maybe it is the easiest way to handle your requirements.  You can then manipulate the buffer and then blit the updated cards into GRAM on the next frame.

A game like yours does not strike me as one that requires “twitch-level” reaction and rendering at 60 Hz, so taking a few frames to compose your scene and update the world state should not be a big deal.

GRAM can be changed at will throughout your game, provided it is done so during vertical blanking.

In other words, you don’t have to set GRAM once at the beginning and stick to it:  You can update it as needed.

This thing of an 8x8 buffer seems interesting..how can I do this?

I mean: I don't need to update Backtab in every frame, I just need to update it only when the screen is scrolling, and I only need to update the first/last column/row, depending on the direction of scroll. The rest of the screen is automatically updated by the 'scroll' feature available in IntyBasic. So I can easily identify the exact 12 tiles to update (on horizontal scroll) or the 20 tiles to update (on vertical scroll)

 

And..you said I can update GRAM, which for me is different than say I can update BackTab..how can I do this?

 

2 hours ago, DZ-Jay said:

As a matter of fact, this is a common technique used for animating sprites on an Intellivision:  Update it’s GRAM card on every frame or so.  We call it “GRAM cycling.”

I already cycle through pre-defined 8x8 bitmaps, you say I can cycle through 8x8 buffered blocks?

 

 

2 hours ago, DZ-Jay said:

What do you mean “reduce … into one”?

Check screenshots:

 image.png.c2a1e6e0d8d439f9ab9dda24ca5de7d0.pngimage.png.23ad15d64b1dbd48cd1c81245bc592c1.png

 

The left one is the zoomIn version..you can see some 16x16 (= 4 blocks 8x8) colored blocks..and on the right, in the zoomOut version, you can see the same blocks 'reduced' into 8x8 blocks

 

In my previous post I added the zoomIn Version rom too, which is playable

 

Thanks

Edited by jenergy
Wrong image posted
Link to comment
Share on other sites

To answer your question about reducing four cards into one, there's Colored Squares, which is only available if you're using the Color Stack graphics mode.  It draws four solid-color blocks in a single card, each of which can be a different color.

 

You're limited to the first seven colors though, plus whatever the background color currently is set to be.  But if you're using the first two colors black and blue, that won't be an issue.

  • Thanks 1
Link to comment
Share on other sites

1 hour ago, jenergy said:

Thanks, and thank you for your answer. And I'm very sorry for the questions I'm going to do ?


 

 

No worries!  I can take it. :)

 

Quote

This is what I didn't understand.

Just suppose I want to change the first 8x8 cell of backtab:

 

#Mcard= peek ($200)

#Mcard= <manipulate it>

poke($200,#Mcard)

 

In the manipulation step, I cannot 'change' bits. With the exception of colors, I can only change a reference to an already statically defined memory block 8x8. So, I'm stucked, because I need to prefill all of them. Is this correct?


 

That, or swap it on the fly.

 

But, you are right:  The BACKTAB word only has an index to which card in GRAM it will use.  In order to change the graphic, you will have to either change the index to another card, or swap the underlying card in GRAM.

 

Quote

This thing of an 8x8 buffer seems interesting..how can I do this?

Well, just declare a two dimensional array of bytes (512) or words (256).  You will have to map the array elements to individual positions in GRAM, but you should be able to encapsulate that logic in a subroutine or macro.

 

Essentially, your buffer is a copy of GRAM, but one that allows you to manipulate it as you need, instead of only within vertical blanking.  Afterwards, you copy the modified elements into GRAM at the start of the next frame.

 

Quote

I mean: I don't need to update Backtab in every frame, I just need to update it only when the screen is scrolling, and I only need to update the first/last column/row, depending on the direction of scroll. The rest of the screen is automatically updated by the 'scroll' feature available in IntyBasic. So I can easily identify the exact 12 tiles to update (on horizontal scroll) or the 20 tiles to update (on vertical scroll)


 

If most of your visible screen is composed of static cards, like walls and such, then you can reuse them.  Think of GRAM as a character set, and BACKTAB as a page where you print different characters from that set, but which can reuse those characters in many words simultaneously.

 

 

Quote

And..you said I can update GRAM, which for me is different than say I can update BackTab..how can I do this?


 

Going with the analogy of a character set, if you print an "A" on the screen, you get that character.  If you change the font, all your letters "A" on the screen will take the new look.  If you then change the picture of "A" to, say, a smiley face, all the letters "A" on the screen will reflect that.

 

That is what GRAM is on the Intellivision, except that it supports the background scene and sprites as well.

 

With IntyBASIC, you use DEFINE to load cards from ROM into GRAM.  It will take care of buffering the change until the next vertical blanking (VBLANK) period.

 

You could also Peek and Poke directly to GRAM, but you will have to take care of doing it at the top of the frame, during the VBLANK period.

 

Quote

I already cycle through pre-defined 8x8 bitmaps, you say I can cycle through 8x8 buffered blocks?

 

 

Check screenshots:

 image.png.c2a1e6e0d8d439f9ab9dda24ca5de7d0.png
 

Wait, help me understand the scale of your graphics.  On that screenshot, what is a GRAM card?  Is it a block of 2x2 blue boxes, or a single box?

 

It may be that we are both overthinking this.  How many non-blue-boxy-thingies do you need to display at a time on the screen?  You may be able to get away with using MOBs (hardware sprites) for all the foreground stuff, which can be rendered independently over the background scene.


If the above screenshot represents the typical zoomed-in scene, I would do it by defining a single GRAM a card for the background (and stamp it as needed in the BACKTAB), and MOBs for everything else.

 

Furthermore, I would devise some concise format to define the "world map," including walls, paths, power-ups, etc. and use it to draw the big zoom-out screen on the fly.

 

Then, track the position of the cursor within the world map data structure as the player moves it, and render that sector on the fly by reading it from the map.

 

I'll have to play around with your ROM later to better understand what you need.  Right now, I'm going off by my mental image of your requirements based on your descriptions. So, I apologize if I am not getting it, or if my answers are too vague or unhelpful.

 

    dZ.

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

1 hour ago, jenergy said:

 

Check screenshots:

 image.png.c2a1e6e0d8d439f9ab9dda24ca5de7d0.pngimage.png.23ad15d64b1dbd48cd1c81245bc592c1.png

 

The left one is the zoomIn version..you can see some 16x16 (= 4 blocks 8x8) colored blocks..and on the right, in the zoomOut version, you can see the same blocks 'reduced' into 8x8 blocks

 

In my previous post I added the zoomIn Version rom too, which is playable

 

Thanks

OK, this is what I was missing.  So the first screenshot uses 8x8 tiles, so each block is a BACKTAB card.  Got it!

 

Then my suggestion at the end of my last post should work:  define the world map in some data structure that holds all the necessary information to describe the scene, so that you can use it to draw the big map, and the little one.

 

Then, track enemy and player/cursor positions within that map in variables.


This is similar to how Pac-Man (and by extension, my game) works.  In Pac-Man there is a single maze, but the layout of paths, tunnels, pills, walls, etc., is defined in a virtual map somewhere in memory.  This map is usually cleverly constructed for easy random access, like an array of bytes, where each bit means something.

 

Then, the player and enemy positions on the screen are translated to positions within the virtual map (or tracked separately).  When the sprites move, the map is consulted to determine if there is a wall, a path, a tunnel, or an edible item in the current position.

 

   dZ.

  • Thanks 1
Link to comment
Share on other sites

3 hours ago, DZ-Jay said:

 

Going with the analogy of a character set, if you print an "A" on the screen, you get that character.  If you change the font, all your letters "A" on the screen will take the new look.  If you then change the picture of "A" to, say, a smiley face, all the letters "A" on the screen will reflect that.

 

That is what GRAM is on the Intellivision, except that it supports the background scene and sprites as well.

 

With IntyBASIC, you use DEFINE to load cards from ROM into GRAM.  It will take care of buffering the change until the next vertical blanking (VBLANK) period.

I think that this is my answer!! I already use the DEFINE directive, at the beginning of the program, pointing to my static bitmaps..but you're saying that I can re-use it when I need, in order to overwrite the 'character set' GRAM tiles, and for doing it I can use a buffer that I can dinamically create.

If this is true, this can be my way..

 

3 hours ago, DZ-Jay said:

Then my suggestion at the end of my last post should work:  define the world map in some data structure that holds all the necessary information to describe the scene, so that you can use it to draw the big map, and the little one.

Then, track enemy and player/cursor positions within that map in variables.

This is similar to how Pac-Man (and by extension, my game) works.  In Pac-Man there is a single maze, but the layout of paths, tunnels, pills, walls, etc., is defined in a virtual map somewhere in memory.  This map is usually cleverly constructed for easy random access, like an array of bytes, where each bit means something.

Then, the player and enemy positions on the screen are translated to positions within the virtual map (or tracked separately).  When the sprites move, the map is consulted to determine if there is a wall, a path, a tunnel, or an edible item in the current position.

 

Yes but there's no scroll in pacman. I need to scroll screen, and the best way in this case is represent the level with the "repeat count" technique (explained in @nanochess book)

 

Considering the level in the zoomin rom I posted, you're saying that the whole level can be stored in memory like this:

image.thumb.png.5f4185d6b9d013342e4b0310a6c6e527.png

 

This is human readable (you can see the level!) but it's very expensive in memory. XX and II are constants which represent 16bit variables, pointing to predefined 8x8 bitmap blocks.

 

I actually represent the same level in memory like this instead:

 

image.thumb.png.f2d48d4627b722f553b93177e71b9b04.png

 

which means, for example for column 4 (0 based), 

9 tiles of type 0 + 8 tiles of type 0 (= wall, statically coded) 

2 tiles of type 1 (= empty, statically coded)

3 tiles of type 0 (=wall, statically coded) 

4 tiles of type 1 (=empty, statically coded)

etc.. 

 

This is less expensive (and I can reduce it more, since I'm lazy and I'm actually using '9' as max size instead of 'F' which is 15)  and it's very useful when used in combination with the 'scroll' feature of IntyBasic, because by keeping a pointer to the last column rendered, if you scroll you are ready to keep the exact tiles you want to render.

 

At this point, I can create something similar for the zoomout version, and dinamically create in memory my buffers for the GRAM, for using them later with DEFINE directive. If I can do it in the 'loading level' phase, all comes free, since I already implemented the scrolling feature.

But I have to invent some kind of trick, because while for the big version for the moment I only need two kind of tiles (0=Wall and 1=Empty), in the zoomout version I need much more of them, and the limit with repeat count trick is 16 (from 0 to 'F' in hexadecimal).

 

4 hours ago, Zendocon said:

To answer your question about reducing four cards into one, there's Colored Squares, which is only available if you're using the Color Stack graphics mode.  It draws four solid-color blocks in a single card, each of which can be a different color.

 

You're limited to the first seven colors though, plus whatever the background color currently is set to be.  But if you're using the first two colors black and blue, that won't be an issue.

I have to check this too

Thanks again!

 

 

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

12 hours ago, jenergy said:

I think that this is my answer!! I already use the DEFINE directive, at the beginning of the program, pointing to my static bitmaps..but you're saying that I can re-use it when I need, in order to overwrite the 'character set' GRAM tiles, and for doing it I can use a buffer that I can dinamically create.

If this is true, this can be my way..


 

Yes, that is what I was suggesting.

 

Quote

Yes but there's no scroll in pacman. I need to scroll screen, and the best way in this case is represent the level with the "repeat count" technique (explained in @nanochess book)


 

There is in the Ms. Pac-Man implementation for the Intellivision, and Pac-Man Jr. ;)

 

My point is that the world map is tracked separately from the display, which is produced from it.  This allows you to compress the world map into a concise data structure, rather than a mirror of the full world as displayed, which would be too big.

 

Quote

 

Considering the level in the zoomin rom I posted, you're saying that the whole level can be stored in memory like this:

image.thumb.png.5f4185d6b9d013342e4b0310a6c6e527.png

 

This is human readable (you can see the level!) but it's very expensive in memory. XX and II are constants which represent 16bit variables, pointing to predefined 8x8 bitmap blocks.

 

 

 

Well, I was actually suggesting compressing that sort of thing into a more compact structure, not literally word by word.  As you rightly point out below, that would be wasteful.

 

Quote

I actually represent the same level in memory like this instead:

 

image.thumb.png.f2d48d4627b722f553b93177e71b9b04.png

 

which means, for example for column 4 (0 based), 

9 tiles of type 0 + 8 tiles of type 0 (= wall, statically coded) 

2 tiles of type 1 (= empty, statically coded)

3 tiles of type 0 (=wall, statically coded) 

4 tiles of type 1 (=empty, statically coded)

etc.. 

That's precisely what I meant by a "concise data structure," so we are both in agreement.  It looks like a form of Run-Length Encoding (RLE).


But I was actually suggesting that perhaps it could be compacted more, treating the 16-bit word as a bitfield rather than a proxy for BACKTAB.

Quote

This is less expensive (and I can reduce it more, since I'm lazy and I'm actually using '9' as max size instead of 'F' which is 15)  and it's very useful when used in combination with the 'scroll' feature of IntyBasic, because by keeping a pointer to the last column rendered, if you scroll you are ready to keep the exact tiles you want to render.

 

At this point, I can create something similar for the zoomout version, and dinamically create in memory my buffers for the GRAM, for using them later with DEFINE directive. If I can do it in the 'loading level' phase, all comes free, since I already implemented the scrolling feature.

 

I guess I am not quite clear what the GRAM demands are, since the screenshots look like a very simple set of patterns.  Actually, they look like a single card to represent the blocks and paths.  You should be able to preload those into GRAM at the start of the game, and only manipulate BACKTAB when zooming in and out, and scrolling.

 

I still haven't played the ROM, so I may be missing something.

 

Quote

 

But I have to invent some kind of trick, because while for the big version for the moment I only need two kind of tiles (0=Wall and 1=Empty), in the zoomout version I need much more of them, and the limit with repeat count trick is 16 (from 0 to 'F' in hexadecimal).

 

OK, I think I get it now.  Then let is see what is it that you need for the big map.  How many kinds of tiles are there for the big map?  You may need to use a different encoding.

 

Also, rather than having one set of data for the big map, and one for the smaller one, there should really be only one.  From there you should be able to construct both maps.  The zoomed-in portions should be done by tracking where in the larger map the cursor is, and decoding it.  That's what I do in my games in similar situations.

 

Another idea would be to track background scene and enemy/items positions separately. That way your world map data structure could still use the two cards for the maze.  Then a separate array keeps track of the position of enemies, which can then be used to render on the map.

 

However, it is not clear to me what are the set of combinations of tiles you say you need.  Maybe they can be encoded differently, rather than as tile combinations.

 

   dZ. 

 

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

Just a quick note:  I took a look at the ROMs this morning and I will say that they work rather well.  I find that the player sprite moves a bit too fast, but it the scrolling and transitions seem stable, smooth, and effective.

 

I am still not entire sure I understand where the problem lies:  the background itself seems to be a very simple grid, which should not take more than a couple of cards to render -- in both the zoomed-in and zoomed-out versions.  Unless, the ROMs are not representative of the final layout.  If this is the case, then could you provide some information on what the layout and graphics should be and how many permutations of cards you think you need?

 

I am also not familiar with the game, so I do not know what the enemies look like, how many there are, and how much variety there is.

 

This is the part of your description that confuses me:

On 5/10/2022 at 7:57 AM, jenergy said:

image.png.e2b2a09265e885c078ca5facd739573d.png

As you can see, the level is 'shorter'.


And now come the technical suggestions I need. 
In order to zoom-out the level, I've taken a square of four continuous blocks of the level, and statically coded the 8x8 resulting block:

                     
|--------|--------|       |--------|
| 8x8    |  8x8   |       |8x8     |
| Wall   |  Wall  |       |Miniwall|
|        |        |       |        |
|        |        |       |        |
|--------|--------|  -->  |--------|  
|        |        |
| 8x8    |  8x8   |
| Wall   |  Wall  |
|        |        |
|--------|--------|


|--------|--------|       |--------|
| 8x8    |  8x8   |       |8x8     |
| Empty  |  Wall  |       |Halfwall|
|        |        |       |   1    |
|        |        |       |        |
|--------|--------|  -->  |--------|  
|        |        |
| 8x8    |  8x8   |
| Empty  |  Wall  |
|        |        |
|--------|--------|


|--------|--------|       |--------|
| 8x8    |  8x8   |       |8x8     |
| Wall   |  Empty |       |Halfwall|
|        |        |       |   2    |
|        |        |       |        |
|--------|--------|  -->  |--------|  
|        |        |
| 8x8    |  8x8   |
| Wall   |  Empty |
|        |        |
|--------|--------|

Etc...

 

It is not clear to me what you mean.  When you say you "statically coded the 8x8 resulting block," do you mean that you created a separate static data structure to describe the zoomed-in block?

 

This is also something I do not fully understand:

On 5/10/2022 at 7:57 AM, jenergy said:

I created all the possible combinations Wall-Empty, by coding statically the 8x8 bitmap representations for GRAM.

 

What are the "possible combinations Wall-Empty ..."?

 

After playing around with the ROMs, I have an idea of how I would implement such a game, but since I am not familiar with the game-play, I need some help understanding the expectations and requirements.  These will certainly influence the design.

  • Is the entire world map (a level or full, zoomed-out maze) statically defined, or does is the maze itself randomly generated at runtime?
  • Same for the enemies or items (coins, etc.), are they statically defined, or randomly placed on the maze at runtime?
  • Is there a limit on the number of enemies or items in the world map?
  • Is there a limit on the number of enemies or items within a particular region (e.g., when zoomed in, no more than x number of enemies can appear on screen at a time)?

If the world is statically defined, then the problem becomes easier, since the entire map can be represented in some compact data structure in ROM and used to build the display scenes.  Then the problem statement becomes, what sort of information is needed to describe the world?  For instance, the open paths and walls, the placement of items, etc.

 

Even if the placement of enemies or items is dynamically determined, it should be described separately -- unless they are fixtures of the world itself (i.e., a door, a teleporter, an interactive wall, etc.), rather than mere foreground items.

 

     -dZ.

Link to comment
Share on other sites

8 hours ago, DZ-Jay said:

There is in the Ms. Pac-Man implementation for the Intellivision, and Pac-Man Jr. ;)

Ah! You're right, one (or both) have scroll

 

8 hours ago, DZ-Jay said:

My point is that the world map is tracked separately from the display, which is produced from it.  

 

Yes, actually the logic layer is independent from the rendering layer. In other words,I can play even if nothing is rendered.

 

8 hours ago, DZ-Jay said:

Also, rather than having one set of data for the big map, and one for the smaller one, there should really be only one.  From there you should be able to construct both maps.  The zoomed-in portions should be done by tracking where in the larger map the cursor is, and decoding it.  That's what I do in my games in similar situations.

 

That's an interesting alternative

 

6 hours ago, DZ-Jay said:

Just a quick note:  I took a look at the ROMs this morning and I will say that they work rather well.  I find that the player sprite moves a bit too fast, but it the scrolling and transitions seem stable, smooth, and effective.

 

Thanks! I'm glad that you gave it a try

 

6 hours ago, DZ-Jay said:

It is not clear to me what you mean.  When you say you "statically coded the 8x8 resulting block," do you mean that you created a separate static data structure to describe the zoomed-in block?

The scrolling version you played is what I call the "Zoom In" version. All is simple in there, because I just had to declare an 8x8 bitmap:

 

game_bitmaps_0:
    BITMAP "XXXXXXXX"   ' 0 - Wall
    BITMAP "X......X"
    BITMAP "X......X"
    BITMAP "X......X"
    BITMAP "X......X"
    BITMAP "X......X"
    BITMAP "X......X"
    BITMAP "XXXXXXXX"

 

This is what I mean with "statically coded block": declared and later loaded with DEFINE ?

 

For the empty spaces I can simply use the value $0100 from the ROM, so I don't need to create a tile for it

 

So all is easy: if you have the wall, render this defined tile, otherwise render from ROM $0100 (which is an empty 8x8 block). No issues here.

 

6 hours ago, DZ-Jay said:

What are the "possible combinations Wall-Empty ..."?

Things become a little complicated if I want to see a larger window of the level (what I call "Zoom Out"). I have obviously to reduce size of everything, and we can say that what you see in a zone of the "Zoom In" version must be 'reduced' to the half in the "Zoom Out" version.

 

So: an 8x8 zone corresponds to a 4x4 zone. Or, for convenience, we can say that a 16x16 zone must be reduced to a 8x8 zone. This is what I meant with 'reduce': four blocks 8x8 (which is a 16x16 zone) must be reduced ( better word is 'remapped'?) to a block 8x8.

 

image.png.e5b63556fcca97eb52e93506ed24ab39.png

 

So I created all 13 possible tiles 8x8:

 

WW

WW (for example, the red square)

 

WO

WW (for example, yellow square)

 

WW

WO

 

WW

OW


OW
WW

 

OO

WW

 

WO

WO

 

WW

OO

 

OW
OW

 

WO

OO  (ex: green square)

 

OW

OO  (ex: purple square)

 

OO

OW

 

OO

WO

 

I report only a couple of examples:

 

game_bitmaps_1:
    BITMAP "XXXXXXXX"   
    BITMAP "X..XX..X"
    BITMAP "X..XX..X"  WW
    BITMAP "XXXXXXXX"  OO
    BITMAP "........"
    BITMAP "........"
    BITMAP "........"
    BITMAP "........"

 

    BITMAP "XXXX...."  
    BITMAP "X..X...."  WO
    BITMAP "X..X...."  WW
    BITMAP "XXXX...."
    BITMAP "XXXXXXXX"
    BITMAP "X..XX..X"
    BITMAP "X..XX..X"
    BITMAP "XXXXXXXX"

 

    BITMAP "XXXX...."   
    BITMAP "X..X...."  WO
    BITMAP "X..X...."  OO
    BITMAP "XXXX...."
    BITMAP "........"
    BITMAP "........"
    BITMAP "........"
    BITMAP "........"

 

 

 

This is what I meant with "all possible combinations wall-empty"

If the game would be finished here, that would be acceptable, but the problem are the enemies (see below)

 

6 hours ago, DZ-Jay said:
  • Is the entire world map (a level or full, zoomed-out maze) statically defined, or does is the maze itself randomly generated at runtime?

The level is statically defined, but in the original game some 'empty' blocks are special if you traverse them, thay become a wall. If things become complicated, I can avoid this.

We can say that level is statically defined.

 

6 hours ago, DZ-Jay said:
  • Is the entire world map (a level or full, zoomed-out maze) statically defined, or does is the maze itself randomly generated at runtime?
  • Same for the enemies or items (coins, etc.), are they statically defined, or randomly placed on the maze at runtime?

The problem is here.

If you play the non-scrolling rom, you can see some enemies. Thoose are the only enemies I want to render as sprite. This because:

  • I don't want to limit the enemies. And I want to model my character with two sprites, maybe with different colours
  • All the other enemies I want to implement are some kind of traps which comes out (and then disappear) in empty spaces. If you see the video I posted in the first post, that should be clear. So, I have to represent them as background, not as sprite. Same thing for coins: Every level has dozens of coins, they must be background.

 

The 'sprite' enemies start in a pre-fixed position, and then they move with a predefined pattern.

The 'background' enemies are fixed in a pre-fixed position, but they 'appear' and 'disappear'

 

And this is the problem: if I only have Wall and Empty block, thirteen tiles are enough, because they cover all the permutations. But if I have Wall, Empty, Coin, Enemy 1, Enemy2 etc, it's impossible to have all the permutations.

6 hours ago, DZ-Jay said:
  • Is there a limit on the number of enemies or items within a particular region (e.g., when zoomed in, no more than x number of enemies can appear on screen at a time)?

If things become complicated, I will have to limit, but it's not planned to limit them

 

6 hours ago, DZ-Jay said:

Even if the placement of enemies or items is dynamically determined, it should be described separately -- unless they are fixtures of the world itself (i.e., a door, a teleporter, an interactive wall, etc.), rather than mere foreground items.

There are special entites 'fixed' (like teleports) and enemies which appear and disappear. If you see the video, it should be clear

 

 

Thanks again!

Edited by jenergy
Link to comment
Share on other sites

Hi, @jenergy,

 

Judy a quick note to say that I now fully understand and appreciate the problem, and it is close to what I originally thought: rendering enemies as modified grid background cards.

 

Thanks for the thorough description.

 

I’ll try to provide a more nuanced response later today, when I get home from the office.

 

In the meantime, out of the top of my head, I can think of two options:

  • Dynamically updating GRAM in a buffer and swapping the cards, as I mentioned in an earlier post; or
  • Statically defining the combinations of cards for walls and enemies, and implementing them by brute force.

Either way, you will have to contend with an important limitation:  GRAM offers only 64 cards, so it cannot be used to represent the full screen, which comprises 240 cards (20 x 12).  This means that you probably will need to compromise on the number of potential combinations of enemy/wall that can exists, to no more than 64.

 

If you manage that, then I would imagine the brute force approach to be the easiest one:  each GRAM card represents a variant of the background, and you update BACKTAB card indices to point to the appropriate one for each tile on the screen.  That map is encoded in the full world data structure which statically describes the maze and its contents.


The fact that it would be a big data structure should not matter, unless we come up against ROM limitations.  If we do, we can then look into compression, bank-switching or any other technique.

 

My view is that this data structure/display issue is one of those problems that is not intrinsic to your game play, so the easier and faster we can get it out of the way, the sooner you can work on the actual game. :)

 

    dZ.

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

I just took a look at the video and read your response more thoroughly, and I now have a better appreciation of the problem and of the game mechanics and display.

 

First, a few observations, just to make sure I'm on the right track.  Please let me know if these assumptions are incorrect:

  • The static objects (traps, teleporters, coins, etc.) seem to never overlap, so a particular block on the screen can have either a wall, an open path, an object, or one of the obstacles.
  • The layout of the play-field is a maze, similar to Pac-Man, which does not necessarily require the rendering as blocks -- just a set of walls (this may simplify rendering requirements).
  • When the objects or obstacles are removed from play, they can be replaced by a different one, or by an open path.

With that in mind, I think it is important to understand what are all the types of elements that can take the spot of a block.  I know of walls and coins, and you have mentioned something about traps and enemies; but I would like to quantify all of them.

 

18 hours ago, jenergy said:

The 'sprite' enemies start in a pre-fixed position, and then they move with a predefined pattern.

The 'background' enemies are fixed in a pre-fixed position, but they 'appear' and 'disappear'

 

And this is the problem: if I only have Wall and Empty block, thirteen tiles are enough, because they cover all the permutations. But if I have Wall, Empty, Coin, Enemy 1, Enemy2 etc, it's impossible to have all the permutations.

Before jumping to such conclusions, let us assess what the actual extent of the problem.  GRAM supports up to 64 unique cards to be used in the background.  This set must cover all walls, objects, enemies, and sprites.  Moreover, there is an entire set of 256 GROM characters which, along with the standard Intellivision text fonts, includes some general geometric shapes and lines, which we could leverage in some way as well.

 

GROM is static (it is read-only memory, after all), but GRAM can be updated at will -- within the constraints of the vertical blanking interrupt (but IntyBASIC handles this for you).  Although individual bytes in GRAM can be updated independently, we typically update full cards at a time.  Still, byte-level access is available if needed.

 

Moreover, the BACKTAB is a two dimensional array of cards, where each can represent any GROM or GRAM card (with some limitations on the colors depending on the screen mode selected), and can be updated easily at any point.

 

Quote

If things become complicated, I will have to limit, but it's not planned to limit them

Of course, that's the last recourse, so let us first start by defining the actual problem, i.e., the extent of objects that we want to render simultaneously on the screen, and go from there.

 

     -dZ.

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

9 hours ago, DZ-Jay said:
  • The static objects (traps, teleporters, coins, etc.) seem to never overlap, so a particular block on the screen can have either a wall, an open path, an object, or one of the obstacles.

This is a potential limitation I already thought: theoretically you can have a coin (background) for example inside an 'exploding trap' (background): you can traverse that position to collect the coin, but you also trigger the bomb for exploding after a second.  If you traverse again that position during explosion (half second) you die. This is valid also for other enemies I want to reproduce. But this can be avoided ? Maybe this is one of the needed trade-off to accept, and I will have to put coins only on empty spaces.

 

But about enemies, you can have only one enemy on a position, with the exception of the 'sprite' enemies: they can overlap with other enemies, but there's no problem on this.

 

9 hours ago, DZ-Jay said:
  • The layout of the play-field is a maze, similar to Pac-Man, which does not necessarily require the rendering as blocks -- just a set of walls (this may simplify rendering requirements).

Absolutely correct! And I already planned, in a second time, to render walls smoother like the original game, by adding more tiles (only for the ZoomIn Version).

But I never thought about it as a possible semplification of how to represent the level! This can be another alternative to consider!! 

 

9 hours ago, DZ-Jay said:
  • When the objects or obstacles are removed from play, they can be replaced by a different one, or by an open path.

Yes. Or better, enemies that I want to reproduce are static: their positions will always be the same, they are never 'removed', but they appear and disappear at fixed intervals. 

  • Exploding Traps: see point 1
  • Laser: an horizontal or vertical line of contiguous enemies turns on for a second, then turns off for another second etc. If you traverse them while they're turned on, you die
  • Square of dead: like laser, but composed by 8 blocks all around a single wall block
  • Teleports: you can imagine ?

 

In my plans, I want to add also other 'bonus', just like brakes and colored keys to use to 'open' some walls, but this is very ambitious.

 

And, finally, the interesting object is the 'potential wall': it's an empty space that becomes wall when you traverse it. This is a fun part of the original game: if you traverse it, you automatically create a different path because it's no more empty but it's a wall!

Avoiding implementing this can be another sad trade-off ?

 

Only coins (and other bonus, if available) can disappear, leaving the space to an open path (or to an already present enemy, in agreement with the answer of the first point)

 

9 hours ago, DZ-Jay said:

Before jumping to such conclusions, let us assess what the actual extent of the problem.  GRAM supports up to 64 unique cards to be used in the background.  This set must cover all walls, objects, enemies, and sprites.

Yes, that's the origin of all the bad things ?

And as reported in old posts, with my actual representation of the level I can reference only 16 of them, so maybe another compact and performant structure must be invented. ?

 

9 hours ago, DZ-Jay said:

Moreover, there is an entire set of 256 GROM characters which, along with the standard Intellivision text fonts, includes some general geometric shapes and lines, which we could leverage in some way as well.

You are right! I forgot it! There was an example too in the set of examples of IntyBasic! Another alternative to consider I didn't think!!

 

9 hours ago, DZ-Jay said:

Of course, that's the last recourse, so let us first start by defining the actual problem, i.e., the extent of objects that we want to render simultaneously on the screen, and go from there.

Another potential trade-off. One of the captivating things of the game is that you 'discover' enemies gradually through the levels, and once you discover them, you can have them in potentially all subsequent levels. In the last hard levels, you are face to face with all the enemies you 'discovered' in your journey.

An alternative is to start defying this as a fixed value, and find an optimized way to represent all, depending on it.

But another alternative can be to consider it as a variable..I mean, an 'unknown quantity' which can be deduced subsequently, after having found the best optimized way to represent all.

 

I need some further thoughts on all of this.

 

I'm really happy and glad and thankful for your contributions

?

 

 

 

 

Edited by jenergy
I forgot teleports and other bonus
Link to comment
Share on other sites

On 5/12/2022 at 5:56 PM, jenergy said:

This is a potential limitation I already thought: theoretically you can have a coin (background) for example inside an 'exploding trap' (background): you can traverse that position to collect the coin, but you also trigger the bomb for exploding after a second.  If you traverse again that position during explosion (half second) you die. This is valid also for other enemies I want to reproduce. But this can be avoided ? Maybe this is one of the needed trade-off to accept, and I will have to put coins only on empty spaces.

 

Another thing to consider is that a background card can only have at most two colors:  one foreground and one background.  Moreover, if you intend to use the GROM shapes, you will be constrained to what is called "Color Stack" mode, which has some ... hmm ... interesting ... limitations on the use of colors.  For this type of game, which depends on a grid of repeatable patterns, this does not strike me as a big deal (plus, I'm rather good at playing in "Color Stack," so I can help there as well).

 

All that points to the notion that layering multiple elements on the same tile may not be practical, due to the platform's limitations.  This may not be as bad as it sounds, since the game-play can still be rich and interesting with the other mechanics.

 

 

Quote

But about enemies, you can have only one enemy on a position, with the exception of the 'sprite' enemies: they can overlap with other enemies, but there's no problem on this.

By "enemy," do you mean the hazards like lasers, exploding traps, etc.?

 

Quote

Absolutely correct! And I already planned, in a second time, to render walls smoother like the original game, by adding more tiles (only for the ZoomIn Version).

But I never thought about it as a possible semplification of how to represent the level! This can be another alternative to consider!! 

I mentioned it could simplify rendering because the maze becomes a series of lines and curves to describe the walls, which can be accomplished with very few cards for each.  For instance, in my own game, (originally based on a port of Pac-Man I was working on, so the concept applies to both), I used only 7 custom pictures (and the blank) to describe the walls of the maze, and just swap the 7-tile set for each maze to give it a distinctive look.

 

For instance, this set:

@@ICE_CUBE_3:
; 0: T-Right
; 1: T-Left
; 2: vertical
; 3: T-Up
; 4: T-Down
; 5: horizontal
; 6: junction
:0       :1       :2       :3       :4       :5       :6
..####.. ..####.. ..####.. .######. ........ ........ ..####..
..#..### ###..#.. ..#..#.. .#....#. ........ ........ ..#..#..
..####.# #.####.. ..####.. ######## ######## ######## ########
..#..#.# #.#..#.. ..#..#.. #.#..#.# #.#..#.# #.#..#.# #.#..#.#
..#..#.# #.#..#.. ..#..#.. #.#..#.# #.#..#.# #.#..#.# #.#..#.#
..####.# #.####.. ..####.. ######## ######## ######## ########
..#..### ###..#.. ..#..#.. ........ .#....#. ........ ..#..#..
..####.. ..####.. ..####.. ........ .######. ........ ..####..

Is used to draw this maze:

1751957775_l8-TwistedToyland.thumb.gif.e1db49a15c987e06ed4594edcb328bfd.gif

 

 

And this set:

@@ICE_CUBE_2:
; 0: Left-top corner
; 1: Right-top corner
; 2: Right-bottom corner
; 3: Left-bottom corner
; 4: horizontal
; 5: vertical
; 6: junction/solid
:0       :1       :2       :3       :4       :5       :6
....#### #####... ######.. ..###### .####### ..####.. .######.
...#.### ######.. ####.#.. ..##.### ##.##### ..#.##.. #.....##
..###### ###.##.. ######.. ..###### ####.##. ..##.#.. #.#..#.#
..###### ..####.. ###.#... ..#.##.. ...###.. ..####.. ##..#..#
..####.# ..####.. .##.#... ....#... ........ ..#.##.. #..#.#.#
..##.#.# ..##.#.. .#...... ....#... ........ ..####.. #...#.##
..#.##.. ..#.##.. .#...... ........ ........ ..##.#.. #..#.#.#
..##.#.. ..##.#.. ........ ........ ........ ..####.. .######.

 

Is used to draw this maze:

651402128_l4-IcicleLane.thumb.gif.d227263e3e01dfbb0d1f9d486bbba655.gif

 

Of course, if push comes to shove and you are low on GRAM, you could go with a single grid-like pattern, like you have today, which would require only one block for all walls -- but it is not as interesting as the curvy Pac-Man-esque design of the original Cyber Protocol game in the video. ;)

 

 

Quote

Yes. Or better, enemies that I want to reproduce are static: their positions will always be the same, they are never 'removed', but they appear and disappear at fixed intervals. 

That should be easy to do, and there are various techniques at our disposal:

  • Changing foreground color to the background color, to hide the enemy;
  • Swapping the GRAM card that describes the enemy;
  • Changing the GRAM card index in the BACKTAB word for the tile to another one.

Note that the first two will affect all background tiles using the same card, so it can be useful if you have a set of enemies all appearing and disappearing at the same time, which I am not sure applies to your game.

 

Quote
  • Exploding Traps: see point 1
  • Laser: an horizontal or vertical line of contiguous enemies turns on for a second, then turns off for another second etc. If you traverse them while they're turned on, you die
  • Square of dead: like laser, but composed by 8 blocks all around a single wall block
  • Teleports: you can imagine ?

Are those it, or are there more hazards and enemies?

 

Quote

In my plans, I want to add also other 'bonus', just like brakes and colored keys to use to 'open' some walls, but this is very ambitious.

Would they be more "card types" in the arsenal?  If so, we may want to include them in the plan.

 

Quote

And, finally, the interesting object is the 'potential wall': it's an empty space that becomes wall when you traverse it. This is a fun part of the original game: if you traverse it, you automatically create a different path because it's no more empty but it's a wall!

Avoiding implementing this can be another sad trade-off ?

 

I don't see why you wouldn't be able to.  All these features you are describing (and going by what I saw on the video), seem to follow the same pattern:  they are all variations of the same problem, so once we crack it for a one, we have a solution for all.

 

Quote

Only coins (and other bonus, if available) can disappear, leaving the space to an open path (or to an already present enemy, in agreement with the answer of the first point)

I would imagine that you could have a coin with a "hidden" enemy underneath, so when the player passes over the coin, it disappears and "reveals" the enemy.  That's just a card swap (like everything else), so I do not see why it would be a problem.

 

Quote

Yes, that's the origin of all the bad things ?

And as reported in old posts, with my actual representation of the level I can reference only 16 of them, so maybe another compact and performant structure must be invented. ?

At this point, I wouldn't worry too much about performance.  If we ever encounter some barrier, we can always optimize routines in Assembly Language, which is actually my own personal preference.

 

As for the data format, I think we first need to determine how many different "card types" we can have on the screen, and go from there.  One thing to note is that, apart from the card index in a BACKTAB word, there are some spare bits that remain unused by the display hardware, which we can leverage to track metadata, such as the existence (or visibility) of an enemy in the tile.  I use this to great effect in my own Pac-Man clone, where four spare bits describe if the tile has a candy, snowflake, present, etc.  Because the BACKTAB is still RAM, I can update the bits to reflect the state of the board when the player picks up an item.

 

Because your game is scrolling, this may be more tricky, so perhaps there are other ways to do it.

 

 

 

Quote

You are right! I forgot it! There was an example too in the set of examples of IntyBasic! Another alternative to consider I didn't think!!

For what it's worth, here's the entire GROM character set:

Spoiler

; =============================================================================
; This is the font set from the Mattel Intellivision, extracted from GROM.
; =============================================================================

; x0     x1       x2       x3       x4       x5       x6       x7       x8       x9       xA       xB       xC       xD       xE       xF
:0       :1       :2       :3       :4       :5       :6       :7       :8       :9       :10      :11      :12      :13      :14      :15
........ ..##.... .##..##. ........ ...#.... ........ ...#.... ...#.... ....###. .###.... ...#.... ........ ........ ........ ........ .......# ; 0x
........ ..##.... .##..##. ...#.#.. #######. .##...#. .#####.. ..#..... ....#... ...#.... ..###... ...##... ........ ........ ........ ......#.
........ ..##.... ........ ..#####. ##.#.... .##..#.. .##..... .#...... ....#... ...#.... .##.##.. ...##... ........ ........ ........ .....#..
........ ..##.... ........ ...#.#.. #######. ....#... ..###... ........ ....#... ...#.... ..###... .######. ........ .######. ........ ....#...
........ ..##.... ........ ..#####. ...#.##. ...#.... .##..... ........ ....#... ...#.... ...#.... ...##... ........ ........ ........ ...#....
........ ........ ........ ...#.#.. ##.#.##. ..#..##. .#####.. ........ ....#... ...#.... ........ ...##... ...##... ........ ...##... ..#.....
........ ..##.... ........ ........ #######. .#...##. ...#.... ........ ....#... ...#.... ........ ........ ...##... ........ ...##... .#......
........ ........ ........ ........ ...#.... ........ ........ ........ ....###. .###.... ........ ........ ....#... ........ ........ #.......

:16      :17      :18      :19      :20      :21      :22      :23      :24      :25      :26      :27      :28      :29      :30      :31
........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ .######. ; 1x
#######. ..###... .######. .######. .##..##. .######. .######. .######. .######. .######. ........ ........ .....##. ........ .##..... .##..##.
##...##. ...##... .##..##. .....##. .##..##. .##..... .##..... .....##. .##..##. .##..##. ...##... ...##... ...##... .######. ...##... .....##.
##.#.##. ...##... .....##. ..####.. .##..##. .######. .######. ....##.. ..####.. .##..##. ...##... ...##... .##..... ........ .....##. ...####.
##.#.##. ...##... .######. .....##. .######. .....##. .##..##. ...##... .##..##. .######. ........ ........ ...##... .######. ...##... ...##...
##...##. ...##... .##..... .....##. .....##. .##..##. .##..##. ..##.... .##..##. .....##. ...##... ...##... .....##. ........ .##..... ........
#######. .######. .######. .######. .....##. .######. .######. ..##.... .######. .######. ...##... ...##... ........ ........ ........ ...##...
........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ....#... ........ ........ ........ ........

:32      :33      :34      :35      :36      :37      :38      :39      :40      :41      :42      :43      :44      :45      :46      :47
#######. .######. .######. .######. .#####.. .######. .######. .######. .##..##. .######. .....##. .##..##. .##..... #.....#. .#...##. .######. ; 2x
#.....#. .##..##. .##..##. .##..##. .##..##. .##..... .##..... .##..##. .##..##. ...##... .....##. .##..##. .##..... ##...##. .##..##. .##..##.
#.###.#. .##..##. .##..##. .##..... .##..##. .##..... .##..... .##..... .##..##. ...##... .....##. .##.##.. .##..... ###.###. .###.##. .##..##.
#.#.#.#. .##..##. .#####.. .##..... .##..##. .#####.. .#####.. .##.###. .######. ...##... .....##. .####... .##..... #######. .######. .##..##.
#.#####. .######. .##..##. .##..... .##..##. .##..... .##..... .##..##. .##..##. ...##... .##..##. .##..##. .##..... ##.#.##. .##.###. .##..##.
#....... .##..##. .##..##. .##..##. .##..##. .##..... .##..... .##..##. .##..##. ...##... .##..##. .##..##. .##..... ##.#.##. .##..##. .##..##.
#######. .##..##. .######. .######. .#####.. .######. .##..... .######. .##..##. .######. .######. .##..##. .######. ##...##. .##...#. .######.
........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........

:48      :49      :50      :51      :52      :53      :54      :55      :56      :57      :58      :59      :60      :61      :62      :63
.######. .######. .######. .######. .######. .##..##. .##..##. ##...##. .##..##. .##..##. .######. ...####. #....... .####... ...#.... ....#... ; 3x
.##..##. .##..##. .##..##. .##..##. ...##... .##..##. .##..##. ##...##. .##..##. .##..##. .....##. ...##... .#...... ...##... ..###... ...#....
.##..##. .##..##. .##..##. .##..... ...##... .##..##. .##..##. ##.#.##. ..####.. .##..##. ....##.. ...##... ..#..... ...##... .#.#.#.. ..#.....
.##..##. .##..##. .##..##. .######. ...##... .##..##. ..#..#.. ##.#.##. ...##... .##..##. ...##... ...##... ...#.... ...##... #..#..#. .######.
.######. .##..##. .#####.. .....##. ...##... .##..##. ..####.. #######. ..####.. .######. ..##.... ...##... ....#... ...##... ...#.... ..#.....
.##..... .##.###. .##..##. .##..##. ...##... .##..##. ...##... .##.##.. .##..##. ...##... .##..... ...##... .....#.. ...##... ...#.... ...#....
.##..... .######. .##..##. .######. ...##... .######. ...##... .##.##.. .##..##. ...##... .######. ...##... ......#. ...##... ...#.... ....#...
........ ......## ........ ........ ........ ........ ........ ........ ........ ........ ........ ...####. .......# .####... ........ ........

:64      :65      :66      :67      :68      :69      :70      :71      :72      :73      :74      :75      :76      :77      :78      :79
....#... ........ .###.... ........ ....###. ........ ........ ........ .##..... ...##... .....##. .##..... ..###... ........ ........ ........ ; 4x
.....#.. ........ ..##.... ........ ....##.. ........ ..#####. ........ .##..... ........ ........ .##..... ...##... ........ ........ ........
......#. .#####.. ..#####. .######. .#####.. .######. ..##.... .######. .#####.. ..###... .....##. .##..##. ...##... #######. .######. .######.
........ ....##.. ..##.##. .##..##. .##.##.. .##..##. .#####.. .##.##.. .##.##.. ...##... .....##. .##.##.. ...##... ##.#.##. ..##.##. .##..##.
........ .#####.. ..##.##. .##..... .##.##.. .######. ..##.... .##.##.. .##.##.. ...##... .....##. .####... ...##... ##.#.##. ..##.##. .##..##.
........ .##.##.. ..##.##. .##..... .##.##.. .##..... ..##.... .#####.. .##.##.. ...##... ..##.##. .##..##. ...##... ##.#.##. ..##.##. .##..##.
........ .######. ..#####. .######. .#####.. .######. ..##.... ....##.. .##.###. .######. ..##.##. .##..##. .######. ##.#.##. ..##.##. .######.
........ ........ ........ ........ ........ ........ ........ .#####.. ........ ........ ..#####. ........ ........ ........ ........ ........

:80      :81      :82      :83      :84      :85      :86      :87      :88      :89      :90      :91      :92      :93      :94      :95
........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ....###. ...##... .###.... ........ ######## ; 5x
........ ........ ........ ........ ..##.... ........ ........ ........ ........ ........ ........ ....#... ...##... ...#.... ........ ########
.######. .#####.. .######. .######. .######. .##.##.. .##..##. ##.#.##. .##..##. .###.##. .######. ....#... ...##... ...#.... ........ ########
..##.##. .##.##.. ..##.##. .##..... ..##.... .##.##.. .##..##. ##.#.##. ..####.. ..##.##. .....##. ..##.... ...##... ....##.. .####... ########
..##.##. .##.##.. ..##.... .######. ..##.... .##.##.. .##..##. ##.#.##. ...##... ..##.##. ...##... ....#... ...##... ...#.... ...####. ########
..#####. .#####.. ..##.... .....##. ..##.... .##.##.. ..####.. #######. ..####.. ..#####. .##..... ....#... ...##... ...#.... ........ ########
..##.... ....##.. ..##.... .######. ..#####. .######. ...##... .##.##.. .##..##. .....##. .######. ....###. ...##... .###.... ........ ########
..##.... ....###. ........ ........ ........ ........ ........ ........ ........ ..#####. ........ ........ ...##... ........ ........ ########

:96      :97      :98      :99      :100     :101     :102     :103     :104     :105     :106     :107     :108     :109     :110     :111
........ ........ ######## ######## ........ ........ ######## ######## .....### ###..... ######## ######## ........ ........ ######## ######## ; 6x
........ ........ ...##### #####... ........ ........ ######## ######## ..###### ######.. ######## ######## ........ ........ ..###### ######..
........ ........ ......## ##...... .......# #....... ######## ######## ######## ######## ######## ######## ........ ........ ....#### ####....
........ ........ ........ ........ ....#### ####.... .####### #######. ######## ######## ######## ######## ........ ........ ......## ##......
........ ........ ........ ........ .####### #######. ....#### ####.... ######## ######## ######## ######## ......## ##...... ........ ........
......## ##...... ........ ........ ######## ######## .......# #....... ######## ######## ######## ######## ....#### ####.... ........ ........
...##### #####... ........ ........ ######## ######## ........ ........ ######## ######## ..###### ######.. ..###### ######.. ........ ........
######## ######## ........ ........ ######## ######## ........ ........ ######## ######## .....### ###..... ######## ######## ........ ........

:112     :113     :114     :115     :116     :117     :118     :119     :120     :121     :122     :123     :124     :125     :126     :127
......## ##...... ######## ######## .......# #....... ######## ######## ........ ........ ....#### ####.... ...##### #####... ######## ######## ; 7x
....#### ####.... ######## ######## ......## ##...... .####### #######. ........ ........ .....### ###..... ..###### ######.. ######## ########
..###### ######.. ######## ######## .....### ###..... ..###### ######.. ........ ........ ......## ##...... .####### #######. ######## ########
######## ######## ######## ######## ....#### ####.... ...##### #####... ........ ........ .......# #....... ######## ######## ######## ########
######## ######## ######## ######## ...##### #####... ....#### ####.... .......# #....... ........ ........ ######## ######## ######## ########
######## ######## ..###### ######.. ..###### ######.. .....### ###..... ......## ##...... ........ ........ ######## ######## .####### #######.
######## ######## ....#### ####.... .####### #######. ......## ##...... .....### ###..... ........ ........ ######## ######## ..###### ######..
######## ######## ......## ##...... ######## ######## .......# #....... ....#### ####.... ........ ........ ######## ######## ...##### #####...

:128     :129     :130     :131     :132     :133     :134     :135     :136     :137     :138     :139     :140     :141     :142     :143
...##### #####... ######## ######## .......# #....... ....#### ####.... ..###### ######.. ######## ######## .....### ###..... ..###### ######.. ; 8x
...##### #####... ######## ######## .......# #....... ....#### ####.... ..###### ######.. ######## ######## ....#### ####.... ...##### #####...
..###### ######.. .####### #######. ......## ##...... .....### ###..... .####### #######. ######## ######## ....#### ####.... ...##### #####...
..###### ######.. .####### #######. ......## ##...... .....### ###..... .####### #######. .####### #######. ....#### ####.... ...##### #####...
.####### #######. ..###### ######.. .....### ###..... ......## ##...... .####### #######. .####### #######. ...##### #####... ....#### ####....
.####### #######. ..###### ######.. .....### ###..... ......## ##...... ######## ######## .####### #######. ...##### #####... ....#### ####....
######## ######## ...##### #####... ....#### ####.... .......# #....... ######## ######## ..###### ######.. ...##### #####... ....#### ####....
######## ######## ...##### #####... ....#### ####.... .......# #....... ######## ######## ..###### ######.. ..###### ######.. .....### ###.....

:144     :145     :146     :147     :148     :149     :150     :151     :152     :153     :154     :155     :156     :157     :158     :159
.......# #....... .....### ###..... ........ ........ ........ ........ ........ ........ ....#### ####.... .......# #....... .....### ###..... ; 9x
.......# #....... .....### ###..... ........ ........ ........ ........ ........ ........ ######## ######## .......# #....... .....### ###.....
.......# #....... ......## ##...... ........ ........ ........ ........ ....#### ####.... ######## ######## .......# #....... .....### ###.....
......## ##...... ......## ##...... ........ ........ ........ ........ ######## ######## ######## ######## .......# #....... .....### ###.....
......## ##...... ......## ##...... ........ ........ ....#### ####.... ######## ######## ######## ######## ......## ##...... ....#### ####....
......## ##...... .......# #....... ........ ........ ######## ######## ######## ######## ######## ######## ......## ##...... ....#### ####....
.....### ###..... .......# #....... ....#### ####.... ######## ######## ######## ######## ######## ######## ......## ##...... ....#### ####....
.....### ###..... .......# #....... ######## ######## ######## ######## ######## ######## ######## ######## ......## ##...... ....#### ####....

:160     :161     :162     :163     :164     :165     :166     :167     :168     :169     :170     :171     :172     :173     :174     :175
...##### #####... .####### #######. ....#### ####.... ........ ........ ........ ........ ........ ........ ....#### ####.... ........ ........ ; Ax
...##### #####... .####### #######. ....#### ####.... ........ ........ ........ ........ ........ ........ ####.... ....#### ........ ........
...##### #####... .####### #######. ....#### ####.... ........ ........ ........ ........ ....#### ####.... ........ ........ ........ ........
...##### #####... .####### #######. ....#### ####.... ........ ........ ........ ........ ####.... ....#### ........ ........ ........ ........
..###### ######.. ######## ######## ....#### ####.... ........ ........ ....#### ####.... ........ ........ ........ ........ ........ ........
..###### ######.. ######## ######## ....#### ####.... ........ ........ ####.... ....#### ........ ........ ........ ........ ......## ##......
..###### ######.. ######## ######## ....#### ####.... ....#### ####.... ........ ........ ........ ........ ........ ........ ...###.. ..###...
..###### ######.. ######## ######## ....#### ####.... ####.... ....#### ........ ........ ........ ........ ........ ........ ###..... .....###

:176     :177     :178     :179     :180     :181     :182     :183     :184     :185     :186     :187     :188     :189     :190     :191
........ ........ .....### ###..... ........ ........ ......## ##...... ...#.... ....#... ........ ........ ##...... ......## ..##.... ....##.. ; Bx
........ ........ ..###... ...###.. ........ ........ ....##.. ..##.... ..#..... .....#.. ........ ........ ##...... ......## ..##.... ....##..
.......# #....... ##...... ......## ........ ........ ..##.... ....##.. .#...... ......#. ........ ........ ##...... ......## ..##.... ....##..
....###. .###.... ........ ........ ........ ........ ##...... ......## #....... .......# ........ ........ ##...... ......## ..##.... ....##..
.###.... ....###. ........ ........ ......## ##...... ........ ........ ........ ........ #....... .......# ##...... ......## ..##.... ....##..
#....... .......# ........ ........ ....##.. ..##.... ........ ........ ........ ........ .#...... ......#. ##...... ......## ..##.... ....##..
........ ........ ........ ........ ..##.... ....##.. ........ ........ ........ ........ ..#..... .....#.. ##...... ......## ..##.... ....##..
........ ........ ........ ........ ##...... ......## ........ ........ ........ ........ ...#.... ....#... ##...... ......## ..##.... ....##..

:192     :193     :194     :195     :196     :197     :198     :199     :200     :201     :202     :203     :204     :205     :206     :207
#....... .......# ...#.... ....#... ####.... ....#### ........ ........ ######## ........ ........ ........ ######## ........ ........ ........ ; Cx
#....... .......# ...#.... ....#... ####.... ....#### ........ ........ ######## ........ ........ ........ ........ ........ ........ ........
#....... .......# ...#.... ....#... ####.... ....#### ........ ........ ........ ######## ........ ........ ........ ........ ........ ........
#....... .......# ...#.... ....#... ####.... ....#### ........ ........ ........ ######## ........ ........ ........ ######## ........ ........
#....... .......# ...#.... ....#... ........ ........ ####.... ....#### ........ ........ ######## ........ ........ ........ ######## ........
#....... .......# ...#.... ....#... ........ ........ ####.... ....#### ........ ........ ######## ........ ........ ........ ........ ........
#....... .......# ...#.... ....#... ........ ........ ####.... ....#### ........ ........ ........ ######## ........ ........ ........ ........
#....... .......# ...#.... ....#... ........ ........ ####.... ....#### ........ ........ ........ ######## ........ ........ ........ ########

:208     :209     :210     :211     :212     :213     :214     :215     :216     :217     :218     :219     :220     :221     :222     :223
######## ........ .######. ........ ........ .#..##.# .##.##.. .##...## ..#..... .###..## ..#..... .###.#.. ........ #..#...# ....#... #.....#. ; Dx
######## ........ .######. ........ ######## .##....# .##..#.# .###..## .###.... ........ ..##...# .###.#.. #.....#. ....#... ..#..... ..#.#...
######## ........ .######. ........ ######## .###.#.. .##...## ..#..... .###..#. .#....## ..###..# .##..#.# #.#.###. .#....#. #...#.#. ....#.#.
######## ........ .######. ######## ######## .###.#.. .###.#.. ..#..... .##..#.# .##.#### ..###... .##.##.. ....#... ..#...#. ..#...## ..#.....
........ ######## .######. ######## ######## .##..#.# .###..#. ..#..... .###..## .###.... ..##.#.. ........ ##..#..# ......#. ......#. #.#.###.
........ ######## .######. ........ ######## .##.##.. .##.#### ..#..... .##..#.# .###..#. ..#..... ######## ...#.... #.....#. ......#. ..#.....
........ ######## .######. ........ ######## ..#..... .##.###. ..#..... .##.###. ..#..... .#..##.# ######## ...#.#.. ...##... ..#..... #...#.#.
........ ######## .######. ........ ........ .#...#.# .##.#..# ..#..... .###.#.. .#...... .##....# ..#..#.. #...#... #...#..# #.###... #.#.#.#.

:224     :225     :226     :227     :228     :229     :230     :231     :232     :233     :234     :235     :236     :237     :238     :239
#..#..#. #.....#. #.#.###. ....#.#. ...#.... ..#.##.. #.###... ...#.#.. ##.###.. ........ .##..... .....#.. .#..#### #.#....# .###...# ......## ; Ex
..#..... #...#... ....##.. .#..#.#. ..#.##.. ....###. .....#.. .##..... .#.##..# ##.###.. ....##.. ........ .#....## #.###..# ..#.#..# .#.....#
#...#.#. ###.#.#. ..#..### ##.#...# .....#.# ........ ##...... ....##.. ..#.#..# .#.##..# .....#.# ##.###.. .#.##### ######## ......## .##.#..#
#.###... #...#.#. ...#...# #.###... .#....#. ..##.#.. ##....## ......#. ....#.#. ..#.#..# #...#..# .#.##..# ....#.#. .....#.. .###...# .#####.#
#.....#. #.#.#.#. ...##### .....#.. .##...#. .....#.. .#....#. #.###... .#.##..# .....#.# .....#.. ..#.#..# ...##.#. ....##.# ....#### ####....
#...#... #.#.###. ........ .#.#...# .##...#. ........ .#..##.# ........ ....#..# ..#..... ....#.#. ....###. #.####.. #.###... .##.#..# ..#.##..
..#...#. #...#... ..#.#.## .###..#. .#####.. ##....## ##.#...# .....#.. ....#... ...#.#.# #.###... ..#..... ###.#... ....#... ...#.... ...#.##.
#.###... .##.#... ..##..#. .##.#.#. ####.... #..##... ##...... ........ .....#.. ...#.#.. ........ ..#..##. #.#..#.# ...#.... ..#...## .#.##.##

:240     :241     :242     :243     :244     :245     :246     :247     :248     :249     :250     :251     :252     :253     :254     :255
....#..# .#####.# ..#.##.. #.###.#. ..#.###. #.#....# ....#..# .####..# .###..#. .#####.. #.#..... ....##.. ..#.##.. ......## .#..#### #..##... ; Fx
...#.... .#.#.##. ....##.. ###.#### .....### ...##..# ...##.#. .###..#. ...#.... ####.... .##.#... .......# .....#.. ##.##..# .#....## .###.#.#
#.####.. ...#.... .#.##.## #.#..... .#.##.## .##.#..# #.###... .##.#..# ..#.##.. ..#.##.. .#####.. #.##.#.# ..####.. .#..#.## .####.#. #....#.#
###.#... ..#.##.. ....#..# #..#...# ....#..# .#####.# ....#... .#####.# ....#### .....#.# ####.... #.##.### ....#... ##.##..# .#.#..## ###..#.#
#.#..#.# .....#.. ....##.# .##.#..# ....#.#. ####.... #.####.. ####.... #.####.. #.##..## ..#.##.. ##...... #...#.## #...#.## #.#.#### ...#.#..
#.#....# .##.#.#. #.####.. .#.#.... #.####.. ..#.##.. ###.#... ..#.##.. ###.#... #.####.. .....#.# .##..... #.###.## #.###.## .#####.. .##..#.#
#.###... .#####.# ###.#... ...#..#. ###.#... .....##. #.#..#.# .....### #.##...# ###.#... #.##.... .#####.. ........ ##...... ####.... #.##.###
.....#.. ####.... #.#..#.# .##...#. #.#..#.# .#.##.## #.#....# .#....#. .##....# #.##.#.# ...#.... ####.... .....#.. ##.##..# ..#..#.. ........
; x0     x1       x2       x3       x4       x5       x6       x7       x8       x9       xA       xB       xC       xD       xE       xF

 

 

Something to consider.  Personally, I find it very useful when trying to conserve GRAM.  Some of those cards help fill in some edges in complex scenes or artwork, leaving GRAM for additional detail.  Just know that it does not come for free; many people here hate the Color Stack mode, but like everything else in the Intellivision, it has it's strengths and weaknesses.

 

Quote

Another potential trade-off. One of the captivating things of the game is that you 'discover' enemies gradually through the levels, and once you discover them, you can have them in potentially all subsequent levels. In the last hard levels, you are face to face with all the enemies you 'discovered' in your journey.

An alternative is to start defying this as a fixed value, and find an optimized way to represent all, depending on it.

Yes, I would recommend starting with an exhaustive list of enemies and their individual requirements, such as how many can appear simultaneously on the screen; can it be adjacent to another of the same, or different type; etc.

Quote

But another alternative can be to consider it as a variable..I mean, an 'unknown quantity' which can be deduced subsequently, after having found the best optimized way to represent all.

Sorry, but I don't follow ...

 

Quote

I need some further thoughts on all of this.

I'll read some more on the Cyber Protocol game and re-read your descriptions of The Sentinel to get a better feel of what you are trying to accomplish.  If I think of something, I'll let you know.

 

Quote

I'm really happy and glad and thankful for your contributions

?

It is purely my pleasure, I'm always happy to help.  I consider it a duty to pay it forward, since my own experience was built upon the assistance of others in this community.  Plus, it's always cool to see new games come to our little platform.  :)

 

    -dZ.

 

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

You know, I think I found a reasonable solution, with a few trade-offs.

 

Thanks to your suggestions/questions/conclusions, I found that my assumptions are wrong! Or better, they're no more needed.

In particular:

  • I don't need to create all the permutations, like I thought at the beginning.
  • I don't need to reference more than 16 cards to describe the level.

 

Why? 

Because I can think to model the level exactly how I do now (just walls and empty spaces). But just before rendering a particular block, I can refer to another map of enemies for that position, in order to understand if on that position there's something different than the 'standard' tile wall/empty, and in this case I can render the correct tile. As already reported, I just need to refresh background only when I scroll the screen, and I exactly know which tiles I have to update. Every time I need to draw a new column (or a new row), I can do this 'deviation' before rendering it. If this will have an effect with performance, we will see how to optimize it (with assembly maybe, as you suggested)

So I can keep the same representation of the level than now, with the difference that I will construct it for the 'zoomout', and not as now for the zoomin. The zoomin will be easily deduced by the other one.

 

Let's assume for the moment that I use  a single grid-like pattern, like now.

 

Considering the zoomout version, I need:

13 cards, for walls/empty permutations, as we already discussed.

 

Lasers

When you cross them while they're turned on, you die.

We have trade-offs here

 

The first trade-off is: I consider just pairs of widths. I need just 8 cards

0      1     2     3     4    5      6     7

LL  OL  OO  LO  LL  WL  WW  LW  

OO  OL  LL  LO  WW  WL  LL  LW

 

Where 

L= Laser

O= Empty

W=Wall

 

This implies that I cannot have lasers with odd width.

And this imples the second trade-off: no coins or any other background stuff near a laser.

But I can have potentially coins in the same position of lasers, because as you wrote me, I can swap cards when they are turned off ?

 

ezgif-3-db0d5457d6.gif.66bf862623171c968b7d14f42cf1d388.gif

 

 

I forgot to say you that laser must be red (or similar). This means that my two colors are blue and red. I can think to transform near walls in red (you know, the heat diffusion ? 

 

Exploding traps

They're turned off. When you cross them, you trigger an explosion after one second.

Same trade-offs, I consider just pairs of traps. I need just 8 cards

 

TT  OT  OO  TO  TT  WT  WW  TW  

OO  OT  TT  TO  WW  WT  TT  TW

 

Where 

T= Trap

O= Empty

W=Wall

trap.gif.ec3b9c78745f0793abaf1c1b7d39eee4.gif

 

No coins inside or near an exploding trap,  and no other background stuff near.

 For the explosion animation, I can reuse the laser ones ?

 

 

Square of the dead

Same behaviour than lasers.

I can re-use the same cards of laser, and 2 more :

 

ezgif-3-42e3602178.gif.40aa1408fde8ac139b5785a125ca02c8.gif

For positions:

NE-E -> I can use laser card 3

SW-S -> I can use laser card 4

W-NW-N -> I need a new card

SE -> I need a new card

 

 

Coins

13 cards for the coins to collect

image.png.25e89caa07bfb664388ecdaf60cc5401.png

 

Here there's the most great trade-off: No coins near walls ?

That's because, if we consider the thirteen tiles standard wall/empty, I can replace walls spaces with coin, or empty spaces with coins. Otherwise, I'll have to create all possible permutations

 

 

Materializable wall

When you cross them, they become solid wall.

It's always 'lonely', just 1 card for it (I will model level conveniently).

potentialgif.gif.a0ec2a133d681434e56935a99cad82d1.gif

 

trade-off: no coins and no other background stuff near inside or near materializable wall. Once you cross it, it becomes one of the 13 cards of the walls

 

Teleport  (no gif here ? )

When you reach them, you're teleported in another position

Same trade-offs.. 1 card, it's lonely, I will model level conveniently and no coins and no other background stuff near teleport

 

And then, for the ZoomIn version

card for wall

card for laser

card for coin

card for exploding trap

card for materializable wall

card for teleport

 

And now, for sprites:

cards for main character

cards for electric bombs (the movement will be smoother than this one in the gif.. you can see the so called 'initial' rom I posted, to see it in action)

ebgif.gif.726a361b238c4529ec01ce1947860496.gif

 

card for a collectable colored key (to transform particular walls to empty spaces)

card for another collectable bonus (like the brake)

I can think to define them once, since I can use embedded hardware features in order to reduce the size of the sprites.

 

If I missed something I can add other acceptable trade-offs. For example, I can avoid the teleport, or the square of the dead.

If I didn't miss anything, the total is 58 cards. Maybe that's too much anyway. But I still have some cards to use, and I can use sprite also for enemies/hazards if I model my levels accordingly.

For example: If I use 2 sprites for character, and only 2 "electric bombs" (which use 2 sprites each),  I still have 2 sprites for special situations (a coin in a particular position, for example).

 

So, If this is all correct, I don't need color stack mode, and I can say that if I model my level in an accurate way, I can have always 8 sprites active

 

On 5/13/2022 at 11:08 PM, DZ-Jay said:

 

By "enemy," do you mean the hazards like lasers, exploding traps, etc.?

 

Yes. But coins also

 

On 5/13/2022 at 11:08 PM, DZ-Jay said:

 

I mentioned it could simplify rendering because the maze becomes a series of lines and curves to describe the walls, which can be accomplished with very few cards for each.  For instance, in my own game, (originally based on a port of Pac-Man I was working on, so the concept applies to both), I used only 7 custom pictures (and the blank) to describe the walls of the maze, and just swap the 7-tile set for each maze to give it a distinctive look.

 

And, that's another good point. Try to see if what I wrote makes sense. Then I can think to model my levels in order to reduce the thirteen cards, and at the same time have a better look like yours

 

On 5/13/2022 at 11:08 PM, DZ-Jay said:

 

 

That should be easy to do, and there are various techniques at our disposal:

  • Changing foreground color to the background color, to hide the enemy;
  • Swapping the GRAM card that describes the enemy;
  • Changing the GRAM card index in the BACKTAB word for the tile to another one.

Note that the first two will affect all background tiles using the same card, so it can be useful if you have a set of enemies all appearing and disappearing at the same time, which I am not sure applies to your game.

Yes: lasers and square of the dead and exploding traps

 

Quote

I would imagine that you could have a coin with a "hidden" enemy underneath, so when the player passes over the coin, it disappears and "reveals" the enemy.  That's just a card swap (like everything else), so I do not see why it would be a problem.

Uhm no, you need to know always if an enemy is there

 

On 5/13/2022 at 11:08 PM, DZ-Jay said:

Yes, I would recommend starting with an exhaustive list of enemies and their individual requirements, such as how many can appear simultaneously on the screen; can it be adjacent to another of the same, or different type; etc.

Sorry, but I don't follow ...

If what I wrote is correct, I think that I have to spend attention on how I model my levels, in order to have an acceptable (and not too much demanding) number of objects appearing simultaneously on the screen..or not?

 

Quote

I'll read some more on the Cyber Protocol game and re-read your descriptions of The Sentinel to get a better feel of what you are trying to accomplish.  If I think of something, I'll let you know.

Or you can play it on Steam ?

 

Quote

 

It is purely my pleasure, I'm always happy to help.  I consider it a duty to pay it forward, since my own experience was built upon the assistance of others in this community.  Plus, it's always cool to see new games come to our little platform.  :)

Thanks!

 

 

Edited by jenergy
Link to comment
Share on other sites

13 hours ago, jenergy said:

Coins

13 cards for the coins to collect

image.png.25e89caa07bfb664388ecdaf60cc5401.png

 

Here there's the most great trade-off: No coins near walls ?

That's because, if we consider the thirteen tiles standard wall/empty, I can replace walls spaces with coin, or empty spaces with coins. Otherwise, I'll have to create all possible permutations

 

This is not completely true, I can have coins in a tile and a wall in next tile ?

 

 

  • Like 2
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...