Jump to content
IGNORED

Official 'Marathon Quest' help thread


Recommended Posts

Hi all -  a few of you here know I am trying to make my first original concept Intellivision game. This game is going to be a group effort for sure as right now I am just in over my head. So, I figured I would just make this one 'help' thread and moving forward instead of polluting the board with a bunch of threads.

 

I'm going to make sure I exhaust all my resources before coming here, ie.  searching the forum, reading through Oscar's 2 awesome books and studying the many generous code samples that are available. I will just need some gentle nudging in the right direction to make sure I am writing optimal code.


So, with that being said, here is my opener:

 

I am working on a basic character select screen.  What I want to do is create a simple table that stores metadata for 5 different runners. So, each will have a name, a picture (or sprite) and 3 integer stats that will be used in the game for calculating stuff. Coincidentally, my screen looks similar to page 5 of Oscar's new book where he shows the screen for Defender of the Crown, but obviously that code is not available. (I swear, I made mine before I saw this...lol) I used a bunch a nested IF statement and hard coded my through it, but this is totally inefficient.

 

I feel the data tables are the way to go, but I guess I am just not quite understanding exactly how to access and use them. I think my problem is that I am thinking of DATA as an Excel sheet that consists of rows and columns.

 

Currently, my data statement is this, which I know is fine: 

 

player_data:
DATA "Running Man",5,5,1
DATA "Abby Normal",4,5,4     <-- PS, this is the Mrs
DATA "Mad Mik",3,4,5            <-  This is me
DATA "Gorrest Fump",4,5,3
DATA "Banana Steve",5,5,2   <- My daughter's creation.....not related to Minecraft
 

I must not quite be understanding exactly how this is used, despite the book explanation and the dozens of use cases I've seen in sample programs.

 

Like I said, I think of it as an array with a 5 rows and 2 columns, so I'm assuming the string names would be in (1,1), (2,1), (3,1), (4,1), (5,1)

 

So, to print the name, I have:

 

page = 1 : col  = 1

PRINT AT 41 COLOR 7, player_data(page,col)   - This does not work
PRINT AT 41 COLOR 7, "Running Man" - this hard coded nonsense works
 

I'm clearly misunderstanding how DATA statements work.  I think part of the problem is that I still do not fully understand the STIC or all of the 'magic' values, as Oscar calls them in his book , ie $2000, etc.   

 

But let's start on this data statement....what am I missing?  I'm looking forward to having many "aha" moments in the future.

 

thanks in advance

 

Edited by Mik's Arcade
Link to comment
Share on other sites

The DATA statements are sequential. However strings are stored character by character (you can use PACKED to make them take less space) so you would want the names to be padded out to its maximum length, in this case 12 characters. Then you have the name at data address player_data(page * 15) to player_data(page * 15 + 11) and the stats at +12, +13, +14. Also I'm not sure if PRINT works particularly well with strings in data statements. At least previously it didn't but perhaps the compiler has been improved on that.

 

It leads me into the VARPTR syntax, one of the most powerful but also confusing parts of IntyBASIC. It has multiple purposes of which probably not all have been discovered yet. A number of years ago, I begun working on a football manager game and had similar issues like you're having. See below for an excerpt of my solution so far. Note that since I need the stats to be changeable over the game, as well as players able to be traded between teams, I'm using variables to keep track of pointers to players. With 120 players, 16 players per team and 8 teams, it would quickly use up all the 16-bit variable space in a standard Intellivision console. Thus I quickly decided that if I'll ever finish this, I will utilize JLP support which enables another 8000 decles (words) of RAM. It works out of the box on the LTO! Flash and can be enabled with a flag or built into the config file in jzintv emulation.

 

For your case with only five characters that may not need to change their stats over time, you probably can keep all of that in ROM in order to save on variables.

 

CONST PLAYERS = 110 : REM Regular players to allocate to teams	
CONST STARS = 10 : REM Star players on the FA market
CONST C_FGC = $3400 : REM Yellowgreen background, black text

  DIM #pltmp(PLAYERS+STARS) : REM 120 words

  REM By copying pointers to RAM, we can zero out pointers
  REM as players are assigned to respective team below.
  FOR i=0 TO PLAYERS+STARS
    #pltmp(i)=players(i)
  NEXT

  REM Assign players to their respective teams.
  FOR j=0 TO 7
    FOR i=0 TO 10
      DO:my=random(PLAYERS):LOOP WHILE #pltmp(my)=0
      #team(j*ROSTER+i)=#pltmp(my)
      #sl(j*ROSTER+i)=peek(#team(j*ROSTER+i))
      #pm(j*ROSTER+i)=random(10)
      #pltmp(my)=0 : REM player is assigned
    NEXT
  NEXT    

PrintString: procedure	
  REM This routine lets you print strings in DATA statements of dynamic length.
  REM k is player number in the global range (0-119), i is position/line in the team (1-11)

  #addr = #team(k)+1 : REM Bypass SL which is stored separately
  #where = SCREENADDR(5,i)

  WHILE (peek(#addr)<>0)
    #data = peek(#addr)*8 + C_FGC : REM To convert string data to character data
    POKE #where,#data
    #addr = #addr + 1
    #where = #where + 1
  WEND
end

players:
  DATA VARPTR ply001(0)
  DATA VARPTR ply002(0)
  DATA VARPTR ply003(0)
  [...]
  DATA VARPTR ply119(0)
  DATA VARPTR ply120(0)

REM Player data here is arranged as skill level, name and an end
REM of string marker (see WHILE peek(#addr)<>0 above)

ply001:  DATA 1,"CAMPBELL",0
ply002:  DATA 1,"CLARK",0
ply003:  DATA 1,"DANBURY",0
[..]
ply119:  DATA 9,"DOCHERTY",0
ply120:  DATA 9,"ROBINSON",0

What I'm achieving here is that players can be addressed as 0-119, and each player consists of a pointer to where the actual data (name, skill etc) is. The reason I put skill parameters before the name is of course due to skills are the same number of fields for each player while name can be dynamic and zero terminated.

 

Like I wrote above, you probably wouldn't need to store pointers to players in variables, so you could set #addr to player(X) and then use peek(#addr) to get the content to what each VARPTR points to.

Edited by carlsson
Link to comment
Share on other sites

Unfortunately, DATA doesn't work the way you think.  You can think of the DATA statement as a unidimensional array, rather than a table.  You access it one element at a time.


You can treat the DATA set as a multidimensional array by clever manipulation of indices.  Essentially, you use arithmetic expressions to jump around the elements.

 

Consider the following table:

table:
  DATA  1,  2,  3,  4
  DATA  5,  6,  7,  8
  DATA  9, 10, 11, 12


Even though you arranged them in columns and rows, to the compiler, that's just a sequential list of 12 data elements.  Yet, because they do logically align in a pattern of 4 columns and 3 rows, you could access them directly using the following formula:

   index = column + (row * width)

Remember, the "column" and "row" are zero-based, because array indices are zero-based.

 

For example, to get the first column on the first row, you use:

value = table(0 + 0 * 4)

 

To get the third element on the second row, you use:

value = table(2 + 1 * 4)


Notice that this is the same as saying:

value = table(6)


And that should make sense, because if you see the DATA set as a long sequential list, the third element on the second row is actually the 7th element, which is index #6.
 

There is one more complication with what you are trying to do:  each DATA element is actually a single 16-bit value.  Strings are actually stored as a series of bytes representing the characters, each byte in its own DATA element.

 

The reason that I say this complicates matters is because you can't really treat the string as a single element in a list with other elements, like your code suggests.  You would have to store the length somewhere to know when it ends.  Remember, the "table" is still a unidimensional array of 16-bit words, and the string is just a bunch of character values in that array.

 

I hope this at least gives you some idea of where to start.

 

   dZ.

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

10 minutes ago, DZ-Jay said:

Unfortunately, DATA doesn't work the way you think.  You can think of the DATA statement as a unidimensional array, rather than a table.  You access it one element at a time.


You can treat the DATA set as a multidimensional array by clever manipulation of indices.  Essentially, you use arithmetic expressions to jump around the elements.

 

Consider the following table:


table:
  DATA  1,  2,  3,  4
  DATA  5,  6,  7,  8
  DATA  9, 10, 11, 12


Even though you arranged them in columns and rows, to the compiler, that's just a sequential list of 12 data elements.  Yet, because they do logically align in a pattern of 4 columns and 3 rows, you could access them directly using the following formula:


   index = column + (row * width)

Remember, the "column" and "row" are zero-based, because array indices are zero-based.

 

For example, to get the first column on the first row, you use:


value = table(0 + 0 * 4)

 

To get the third element on the second row, you use:


value = table(2 + 1 * 4)


Notice that this is the same as saying:


value = table(6)


And that should make sense, because if you see the DATA set as a long sequential list, the third element on the second row is actually the 7th element, which is index #6.
 

There is one more complication with what you are trying to do:  each DATA element is actually a single 16-bit value.  Strings are actually stored as a series of bytes representing the characters, each byte in its own DATA element.

 

The reason that I say this complicates matters is because you can't really treat the string as a single element in a list with other elements, like your code suggests.  You would have to store the length somewhere to know when it ends.  Remember, the "table" is still a unidimensional array of 16-bit words, and the string is just a bunch of character values in that array.

 

I hope this at least gives you some idea of where to start.

 

   dZ.

Yes, it does, thanks...I can slice and dice a 20 item list into a  5 x 4 grid with math like you noted above

 

I bet if I was just working with only numbers I would have figured it out.  I knew the strings were making it more complicated.  i've seen code that literally deals with one letter at a time using GROM values when dealing with strings 

Link to comment
Share on other sites

And whoa.....carlsson......that is some pretty advanced stuff you are talking about there.  I was looking at DATA PACKED and VARPTR in the book but didn't find any specific examples until your post.....thanks. I did see a thread discussing how complicated VARPTR is though...haha.

 

Link to comment
Share on other sites

If you pad out your strings so you know exactly how many bytes each entry takes, you can modify your existing approach easily. However I'm still not sure that PRINT will play nice with the strings stored in DATA statements, regardless if those are zero terminated or not, so you might still need the PrintString procedure that uses a WHILE statement and either POKEs or for that matter PRINTs one letter at a time until it reached maximum string length or zero termination. If you add the VARPTR variant, you can more easily access each player/character through the two step process of first finding a pointer to where the data begins, and then reading the values from there on, instead of having to multiply player number by the size of each entry.

  • Like 1
Link to comment
Share on other sites

2 minutes ago, Mik's Arcade said:

And whoa.....carlsson......that is some pretty advanced stuff you are talking about there.  I was looking at DATA PACKED and VARPTR in the book but didn't find any specific examples until your post.....thanks. I did see a thread discussing how complicated VARPTR is though...haha.

 

VARPTR is essentially a pointer reference:  it gives you the address in memory of a variable, array, or label, so that you could access the underlying data indirectly.


The way that @carlsson is using it is to create a table of pointers to records.  He creates a table just like you wanted, but assigns each record a label.  That way, you don't have to compute the starting point of each record, especially since the strings cause them to be of arbitrary length, and therefore they are not aligned neatly as you hoped.

 

Then he creates another table to just hold the pointers to each of those records, by using VARPTR on their labels.

 

This allows you to easily navigate your list of records to pointers, and then use those to get to the individual records in the other table.
 

   dZ.

  • Like 1
Link to comment
Share on other sites

For such a small list of data, I may go the easy approach and just flat out print the names using IF statements like I originally did to test out the screen layout and use the data statements for the simple unsigned integers

 

I'll have bigger fish to fry once I'm in the main body of the program and avoiding PRINT statement altogether.

 

And again, thanks for chiming in.  I'm really trying hard to be self sufficient, but it's great knowing how helpful the members of this forum is on us newcomers.  I search the forum and come up hundreds of unrelated topics so it is sometimes hard to find things that were already discussed.

 

I'm trying to recruit my best friend since first grade to start tinkering with this stuff too. We live in different states now soit would be fun to collaborate with him. After all, he was the one to introduce me to the Intellivision to begin with.

  • Like 1
Link to comment
Share on other sites

See also the syntax ON expr GOSUB [label], [label], [label] which would allow you to keep a character 1-5 in a variable and based on which one it is, jump to a subroutine that prints out the name and a background story, perhaps loads graphics data to plot an avatar, could set up various stats etc. It could obviously be combined with various DATA statements depending on how much you want to separate code and data, at the same time it gets a little more structured than a series of IF statements.

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

today was a good day.  Ran 17 miles this AM, and got the character select up and running using the DATA table.  I just took the names out and set them separately and used the integer data to drive the FOR LOOPS I needed to set up the player profiles. So, I am all set for the moment.

 

On a funny side note, I also took the code for Oscar's Monkey Moon (Donkey Kong clone) and am in the process or repurposing it into a clone of Lode Runner so I can test out a few other things when I want a break from my game.   The SDK is working great too!

 

Edited by Mik's Arcade
  • Like 3
Link to comment
Share on other sites

14 hours ago, Mik's Arcade said:

today was a good day.  Ran 17 miles this AM, and got the character select up and running using the DATA table.  I just took the names out and set them separately and used the integer data to drive the FOR LOOPS I needed to set up the player profiles. So, I am all set for the moment.

 

On a funny side note, I also took the code for Oscar's Monkey Moon (Donkey Kong clone) and am in the process or repurposing it into a clone of Lode Runner so I can test out a few other things when I want a break from my game.   The SDK is working great too!

 

Great. Be encouraged!

For what it's worth, VARPTR can also be used for graphics and everything else. In a game I'm working-on, there are a lot of images and each one has two stages of "animation". To select a given image from ROM and put it into GRAM for display, I'm using VARPTR from a base offset to get the nth image and then the nth+1, it is easier to navigate large sets of graphics that way rather than add names to each one. 

Enjoy!

  • Like 1
Link to comment
Share on other sites

1 hour ago, First Spear said:

Great. Be encouraged!

For what it's worth, VARPTR can also be used for graphics and everything else. In a game I'm working-on, there are a lot of images and each one has two stages of "animation". To select a given image from ROM and put it into GRAM for display, I'm using VARPTR from a base offset to get the nth image and then the nth+1, it is easier to navigate large sets of graphics that way rather than add names to each one. 

Enjoy!

 

1 hour ago, carlsson said:

Yeah, I'm expecting a future 3rd book on IntyBASIC to be named "Tales of the VARPTR".

 

I think that the trouble and confusion newcomers have with VARPTR is because it's such an alien concept in BASIC, which typically does not support pointers.  However, it's a rather simple and straightforward concept, once you get your head around it.

 

@Mik's Arcade, think of it this way:  all variables, data statements, procedures, etc. -- in fact, all program code, resides in memory somewhere.  In general, there are two kinds of memory and you are already familiar with them:  ROM and RAM.  The former holds all stuff that never changes in the program, e.g., the game code, the procedures, the DATA statements, etc.  The latter holds all the stuff that changes, namely the variables.

 

This applies to any flavour of BASIC; actually, it applies to virtually all programming languages.  The reason you don't typically think about this facet of a program is because the language abstracts those things for you.  You don't normally have to know where anything resides in memory, you can just call things by name or invoke statements or commands that know where to find the stuff.  Yet, in memory they reside, and internally, IntyBASIC keeps track of their location, by noting their respective memory addresses, and associating them with those names and labels.  It just does this work for you under the hood, like magic.

 

So, for example, when you say in BASIC, "DIM MyVar," all it means in reality is that, there is this new thing called "MyVar," and because you've asked IntyBASIC to declare its existence, it will find an available spot in memory, note its address, and link it to its name.  Thereon forth, whenever your code refers to "MyVar," IntyBASIC will internally look up its memory address, and access the variable contents in there.  It does a similar thing whenever you define a label or a data table.

 

All of this is a purely mechanical and technical job that IntyBASIC does to make your life easier, and it is therefore completely invisible to you; and for the most part, that's how we like it, and life is good.

 

What VARPTR does is simply peek behind that veil to grant you the power of insight into the memory addresses of those names and labels.

 

But ... why would you want that?  Why should you care where things are in memory if IntyBASIC does its job fine without you getting in the way?

 

Well, because it turns out that memory address are just fancy numbers, and what do we do with numbers?  We store them and access them in memory, and manipulate them arithmetically!

 

You see, VARPTR doesn't just grant you the power of insight into the inner workings of IntyBASIC; it opens up the opportunity for you to perform your own magic with it, which is kind of like a super-power.

 

Still ... why is that important and why should you care?

 

It's a very good question, and the answer is that, maybe you do not care.  You may be quite content to just call things by names.

 

However, consider that calling things by name requires you to know their names to begin with.  What if you don't?

 

Consider, for example, a situation in which you have a bunch of graphics cards for a level and you need to decide which cards to load into GRAM depending on some condition.  You could group your cards by sets and assign each one a label.  But what if there are dozens, or maybe even hundreds, of sets?  You could end up with hundreds of labels, plus you would then need a bunch of "IF/ELSE" statements even though each case does exactly the same thing, their only difference being the set of cards in use.

 

On top of all that, you would have to remember the name of each set and keep them straight in your head to avoid confusing one with another.  Alternatively, you could give them generic names like "SET_1," "SET_2," "SET_3," etc.; and arrange them in some sort of order.

 

That would work, but you still need all those IF/ELSE statements for each one, even though all you want to do is say something like, "load the set of graphics for the current screen number."

 

Wouldn't it be easier if you could just tell IntyBASIC something like, "use the current screen number to determine the graphics set, and load it"?  That would be a lot easier to do.

 

Well, that's what VARPTR allows you to do.  For instance, if you know the starting point of the table that contains all the graphics, and you know that all sets are the same size, and you have a variable that holds the current screen number; then you could use all that information to compute the address of the set that you want, and give that to the DEFINE statement to load.  One computation, one DEFINE statement, done.

' NOTES:
'   - The label graphics_sets points to the start of all graphic sets
'   - The variable CurrentScreen holds the current screen number
'   - Let us assume that each set contains 25 cards.

	' Load graphics set for MyScreen
	'   - Starting at GRAM card #0
	'   - Load 25 cards
	'   - Table position = [the address of "graphics_sets"] + [the value of "MyScreen" x 25 cards]
	DEFINE 0, 25, VARPTR graphics_sets(MyScreen * (25 * 4))


' All graphics sets are here.
' Every 25 cards is one set for one screen.
' They are all stored in order.
graphics_sets:
	BITMAP "........"
	BITMAP "........"
	BITMAP "........"
	BITMAP "........"
	BITMAP "........"
	BITMAP "........"
	BITMAP "........"
	BITMAP "........"

	BITMAP "........"
	BITMAP "........"
	BITMAP "........"
	BITMAP "........"
	BITMAP "........"
	BITMAP "........"
	BITMAP "........"
	BITMAP "........"

	BITMAP "........"
	BITMAP "........"
	BITMAP "........"
	BITMAP "........"
	BITMAP "........"
	BITMAP "........"
	BITMAP "........"
	BITMAP "........"

	BITMAP "........"
	BITMAP "........"
	BITMAP "........"
	BITMAP "........"
	BITMAP "........"
	BITMAP "........"
	BITMAP "........"
	BITMAP "........"

	' etc.

 

The address computed would be different and specific to each screen.  This address is called a pointer, because it points to a location in memory.  This is whence VARPTR gets its name:  Variable Pointer, a pointer to a variable (actually to any label or name).

 

 

Anyway, I hope this offers at least some guidance on what VARPTR does and how.  That's just one of the many things it can be used for.

 

One way you could look at this is that VARPTR turn everything into an array.  With the memory address of a label or variable, you can then perform arithmetic operations on it to compute an index from that position in memory, just as if you were working with an actual array.

 

Plus, because a pointer is merely a number, you can assign it to a variable and pass it around as any other value.

 

As you continue working with IntyBASIC and your programs get bigger and more complex, the VARPTR will become a very useful tool that allows you to write code which is cleaner, simpler, less repetitive, and more compact and efficient.

 

      -dZ.

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

  • 2 weeks later...

hey all -

 

I know it's been a while but I have have not been idle.  I've been studying Oscar's new book and testing lots of different things to ensure I under stand how they work.  I've actually started not only 1, but 2 OTHER games in addition to this. I was playing a classic 1982 game last week and was like....I can totally make this with IntyBasic!!!!  More to come on those later.

 

Today I want to ask for some tips and tricks on creating graphics, in particular characters.  Since the core aspect of my game is that you will be controlling one character that really stays in the same spot the entire game, I want to try to make some decent looking IntyBasic character models.

 

So....I realize that a sprite is limited to 8x16.  Obviously, this leaves little room for making compelling and distinct looking runners.  I've seen some tricks on going bigger and using sprites for the moveable parts, but not sure if that's really going to work...I think an 8x16 character will be fine for a scrolling screen game that will have sort of a HUD on the bottom of screen. I can always double size if I want to go big....  Also, I know we are limited to 2 colors per BITMAP or DATA statement, and you have to use the color stack + color square mode to get more.  It seems this is the way to go.   Anyone have any good examples or demos i can play with?  Oscar's new book was perfect timing because I learned a lot from the very first chapter.

 

What I did was play with the running man demo.  It has a total of 7 frames of animation

 

I recreated them in PAINT by making rm1.bmp through rm7.bmp, each being 8x16 pixels.  I realize I could have probably just made 1 bmp as 56x16 and just stacked them on top of one another. IntyColor turned this into 2 data statements per BMP. In PAINT, each # was created in blue color since the running man demo is in also in blue. I left all the background as white, or maybe it means no color? (I don't know if this matters)

 

rem    running 1
        BITMAP     ".....##."
        BITMAP     ".....#.."
        BITMAP     "...####."
        BITMAP     "...##..."

        BITMAP     "...##..."
        BITMAP     "...##..."
        BITMAP     "...##..."
        BITMAP     "...##..."

        BITMAP     "...##..."
        BITMAP     "...##..."
        BITMAP     ".####..."
        BITMAP     ".####..."

        BITMAP     ".#.#...."
        BITMAP     "...#...."
        BITMAP     "...#...."
        BITMAP     "...##..."

 

I won't paste all  7 here....but here is what IntyColor spits out....wasn't quite what I was expecting

 

    DATA $0406,$181E,$1818,$1818  ' same as running 1, but created in PAINT and IntyColor
    DATA $1818,$7878,$1050,$1810

 

Interestingly enough, all 7 BMP generated the exact same screen cards? I thought they would all be slighty different....

REM 1x2 cards

screen_cards:

    DATA $2E01
    DATA $2E09

 

Can anyone how we get from these 16 BITMAP to those 2 data results?  It seems that 8 BITMAPS is the equivalent of 4 values in a DATA statement, so does that mean that DATA 0, ie $0406 is the result of the top two BITMAP statements?   This seems true because that would mean that DATA 2, 3 and 4 that have the same value as $1818 would be BITMAPS 5-6, 7-8 and 9-10 and they are all the same....I'd really like to learn more about exactly how GRAM interprets that $0406....I think this is the key to me really getting an understanding on how it all works....or maybe I don't need to sweat this stuff?

 

At least it works.....I replaced the BITMAPS with the data statement, defined them, recompiled and it works exactly the same on the screen....

 

So, what would you suggest is the best way to tackle this? I guess I'm looking to make a handful of different looking characters but obviously need to be both creative and confined to a limited 8x16 canvas.....I will probably have less running animations than the running man demo (don't need 7) but will have a couple of special case animations.  It does seem like using data statement DOES save me some real estate in terms of the DEFINE statements.

 

thanks in advance all!  I've got a nice 19 mile run in the AM and then I plan on putting my feet up and working on this stuff some more.

 

Link to comment
Share on other sites

The first set of 8 DATA statements represents your BITMAP data, actually two cards since IntyColor will consider those to be 8x8 pixels each. The fact that a MOB can use two cards aligned at an even GRAM to display a 8x16 pattern is different from how it is stored in memory.

 

The data statements actually are arranged as bitmap row 2 (high byte) + row 1 (low byte), row 4 + row 3, row 6 + row 5, row 8 + row 7. That is why you're getting $0406 when you might expect $0604 for the first two bitmap rows.

 

Since you run IntyColor 7 times, it will generate a new file for each frame. The screen_cards are indexes to the GRAM cards you will have defined from the bitmap DATA. Every BMP you fed contains data for 2 GRAM cards so that is why the screen_cards have two values. These are raw STIC BACKTAB parameter values consisting of colour 1 (blue) on background $2E (white) and then an offset of 0 for first card and 8 for second card, which explains why the second is $2E09.

 

When you combine all those bitmaps into one program, you will DEFINE 7*2 = 14 GRAM cards and would have to update the screen_cards accordingly by adding $08 to each card. Now you probably don't want to plot the graphic frame by frame onto the BACKTAB anyway, but instead set up a MOB that is animated using different GRAM cards so you can mostly ignore the screen_cards for this purpose. Remember though that your DEFINE must begin at an even position 0, 2, 4, ... in order for the MOB to utilize 8x16 pixels.

 

Your mention of coloured squares mode is interesting but I'm not sure if it would benefit you here. You get a resolution of 40x24 pixels + MOBs on top as far as I can tell. Yes, you could use three more colours per card but you lose almost all form of resolution and definition. For some types of games it could be useful, but as far as I know, it is not a selectable mode per BACKTAB card, it is either on or off for the screen.

 

Also regarding scrolling and a HUD, you should know right away that if you'll use the excellent hardware based scroll, everything on the BACKTAB will scroll along, including scores and other displays. You can use MOBs to display such information to have it float on the screen, but then again you only have 8 of those for the screen so you might want to think about your layout. Other variants would include soft scrolling only certain elements of the graphics by redefining them (think software sprites). IIRC there is a Moon Patrol type game that works in that way, but it also is a bit advanced to get to work.

Link to comment
Share on other sites

9 hours ago, carlsson said:

Your mention of coloured squares mode is interesting but I'm not sure if it would benefit you here. You get a resolution of 40x24 pixels + MOBs on top as far as I can tell. Yes, you could use three more colours per card but you lose almost all form of resolution and definition. For some types of games it could be useful, but as far as I know, it is not a selectable mode per BACKTAB card, it is either on or off for the screen.

 

Although I agree with your sentiment that Colored Square mode is not very good for much of anything, your comment is not very accurate.  Colored Squares is not strictly a "mode" per se, and it is not selectable as a screen mode.  It is actually a special feature of Color Stack mode.

 

To use Color Squares, you first have to set the mode to Color Stack, then set bit #12 to 1, and bit #11 to 0.  In other words, it is a "GROM" card with "pastel" (high) colour.  That's one of the limitations of the Color Stack mode:  you can use any foreground colour you want on GRAM cards, but GROM cards are limited to the "primary" set.  Setting the "pastel" color flag when the card GROM/GRAM flag is set to zero (bit #11) will take the card value as a Colored Square instead.


This means that you can mix regular background cards with Colored Square cards in any way you want, within Color Stack mode.

 

    -dZ.

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

Thanks for the clarification. It means that details like national flags, perhaps crude parts of the ground, it is a possible sub mode if using CS mode and one wants that extra colour resolution at the expense of detail. ISTR that on the TMS VDP, its coloured squares mode is either or, which means the GI STIC has yet another advantage over the TI from roughly the same time period (though the TMS VDP has higher resolution).

Link to comment
Share on other sites

Hmmm....thanks as usual guys.  I think I overcomplicated my question.

 

Let's take the awesome 2020 contest game Infiltrator.  The main character seems to follow the 8x16 size for a sprite but has at least 3 different colors in the form of a flesh color, the green outfit and the black boots and whatnot.  Is three the most you can squeeze out of a sprite? And how exactly is that done?  Is it 2 spites layered on top of one another or is he making use of the color square mode I talked about?  I want to make a 3 or 4 unique looking characters like that so I don't just have boring looking people......do you think he did that with simple BITMAP statements and tricks with colors or?   I've been tinkering with these ideas and not having a lot of success.....

Link to comment
Share on other sites

11 minutes ago, Mik's Arcade said:

Is three the most you can squeeze out of a sprite? And how exactly is that done?  Is it 2 spites layered on top of one another or is he making use of the color square mode I talked about?  I want to make a 3 or 4 unique looking characters like that so I don't just have boring looking people......do you think he did that with simple BITMAP statements and tricks with colors or?

It is layered with 3 sprites out of 8 available. There's seperate bitmap statements for those sprites.  I have made sprites into paint shop pro then mentally key them in 3 16 lines of bitmap statement with it own color. I use the comment character ' to tell me what color to key the sprite in and what sprite to remind me.

 

For the bomber sprite I did, I used 2 sprites.  You can combine them in the normal game loop by,

sprite 6,bomberx+$200,17+$180,$800+48
sprite 7,bomberx+$200,17+$180,$800+39

And the bitmap I use is,

laughter1:
'white
bitmap "........"
bitmap "........"
bitmap ".XX..XX."
bitmap "........"
bitmap ".XXXXXX."
bitmap ".X....X."
bitmap ".X....X."
bitmap "..X..X.."

bitmap "..XXXX.."
bitmap "...XX..."
bitmap "X.X..X.X"
bitmap "XXX..XXX"
bitmap "........"
bitmap "...XX..."
bitmap "...XX..."
bitmap "...XX..."
'black
bitmap "..XXXX.."
bitmap ".XXXXXX."
bitmap "X..XX..X"
bitmap ".XXXXXX."
bitmap "........"
bitmap "..XXXX.."
bitmap "..XXXX.."
bitmap "...XX..."

bitmap ".X....X."
bitmap "XXX..XXX"
bitmap ".X.XX.X."
bitmap "...XX..."
bitmap "XXXXXXXX"
bitmap "..X..X.."
bitmap "..X..X.."
bitmap "..X..X.."

A frame when he was laughing. 



 

Link to comment
Share on other sites

Yeah. I did the same in my Lucia game. You would have to consider how many different moving objects you want on the screen at the same time, if the marathon is a solo run or if you will have other runners at the same time, and in that case if those need to move smoothly like sprites, possibly implemented as single colour software sprites. The amount of free MOBs dictates how many you can put on top of eachother for improved colour resolution.

 

lucia-spriteuse.png.37b582ff57c3a8e93c23fe26e24c0406.png

Link to comment
Share on other sites

thank you both (Kiwi/carlsson).....this is exactly the information I will looking for.

 

Not being an artist it will be tricky for me to envision each piece I want, but I know what I need to do and there is really only so much you can do with pixel art so this is perfect for my art skills.  I will just have to play around with how many sprites I want to use. I will make things like shorts, headbands or a ponytail that may need unique colors or move as separate parts.  It seems like 3 might be a good magic number because it is what you both used

 

I should be good to use a lot because I don't plan on have more than 2 other sprites on screen.....but that depends on how I use scroll. I envision having lots of things happen in the background, but this should not be using sprites.

 

Excellent....now I have a firm direction of where I want to go next.  Hopefully the next time I need help I will be deep into the actual gameplay experience.

 

 

Link to comment
Share on other sites

  • 2 weeks later...

Hi all -

 

Wow....just 18 days until I run my first official marathon.....now I am in taper mode before the race and running less = more time to code.

 

Hopefully these are quick and easy questions....

 

I've started working on scrolling backgrounds for the game.

 

1)  I'm using paint.net to create 160 x 96 screens. I created the title screen in this manner, but I have a lot of replication and cutting and pasting of chunks to create a series of long scrolls and was wondering if there was a better tool to use for this task. I don't want to use anything TOO complicated, at least PAINT is easy to use.

 

2) If I create a bunch of these scrolls....say between 10-15, do you think I will run into any intybasic limits?   Should I keep it more simple?  I was hoping to to have some unique backgrounds that will be easter eggs to other intellivision games.....some might surprise you all!  Plus, I have to change it up to keep players from being bored.....

 

thanks!

 

Edited by Mik's Arcade
  • Like 1
Link to comment
Share on other sites

23 hours ago, Mik's Arcade said:

1)  I'm using paint.net to create 160 x 96 screens. I created the title screen in this manner, but I have a lot of replication and cutting and pasting of chunks to create a series of long scrolls and was wondering if there was a better tool to use for this task. I don't want to use anything TOO complicated, at least PAINT is easy to use.

You can make an image the size of your scrolling area.

 

23 hours ago, Mik's Arcade said:

2) If I create a bunch of these scrolls....say between 10-15, do you think I will run into any intybasic limits?   Should I keep it more simple?  I was hoping to to have some unique backgrounds that will be easter eggs to other intellivision games.....some might surprise you all!  Plus, I have to change it up to keep players from being bored.....

 

thanks!

 

At some point your scrolling area will be so big that you must check the generated .CFG file to see if it spills out of the available memory areas, using ASM ORG $C100 just before including your scrolling area will get you the biggest segment possible.

 

There is an example in my first book (Bouncing Cube) where it shows how to compress scrolling levels, for example if you have few cards of terrain and lots of sky.

 

Link to comment
Share on other sites

3 hours ago, nanochess said:

You can make an image the size of your scrolling area.

 

At some point your scrolling area will be so big that you must check the generated .CFG file to see if it spills out of the available memory areas, using ASM ORG $C100 just before including your scrolling area will get you the biggest segment possible.

 

There is an example in my first book (Bouncing Cube) where it shows how to compress scrolling levels, for example if you have few cards of terrain and lots of sky.

 

thanks Nano....and yes, I will be leaning on your Bouncy Cube example.....it is what inspired this game to begin with.  I will have to use very simple terrain a lot of time but want to mix in some changes of scenery and other objects (such as signs with messages) in random (and specific) intervals.  If the game goes the way I am hoping, there are certain 'events' that will happen.

  • Like 1
Link to comment
Share on other sites

On 5/4/2021 at 5:17 PM, Mik's Arcade said:

Hi all -

 

Wow....just 18 days until I run my first official marathon.....now I am in taper mode before the race and running less = more time to code.

 

Best of luck on your marathon.  Unfortunately age finally caught up to my knees so I will only be doing a 10km race this month but grateful to be doing that.

 

Didn't mean to sidetrack the discussion.  Carry on.

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