Software sprites?
Moderator: Moderators
-
- Omega Star Commander
- Posts: 1371
- Joined: Thu Jan 31, 2008 2:12 pm
- Website: https://robert.hurst-ri.us
- Location: Providence, RI
- Occupation: Tech & Innovation
Software sprites?
Is anyone interested in a generalized API to provide software sprite rendering on VIC? I am considering in writing that code for possible integration into a future game. I might just do it anyways for the mental exercise, but it would help my motivation if a single soul out there thought it may help him/her with a future game.
I already have a simple 8-sprite routine written. And I have some new lessons learned from the updated Quikman maze to integrate. But, I'd like to see how well it can perform with the addition of doubling height, width, both, and allowing for multiple "banks" of sprites, i.e, potentially allowing for up to 256 "simple" sprites, 64 "common" sprites, or 32 "multicolor" sprites, etc.
I already have a simple 8-sprite routine written. And I have some new lessons learned from the updated Quikman maze to integrate. But, I'd like to see how well it can perform with the addition of doubling height, width, both, and allowing for multiple "banks" of sprites, i.e, potentially allowing for up to 256 "simple" sprites, 64 "common" sprites, or 32 "multicolor" sprites, etc.
- Mike
- Herr VC
- Posts: 4866
- Joined: Wed Dec 01, 2004 1:57 pm
- Location: Munich, Germany
- Occupation: electrical engineer
Some random thoughts:
- compatible with "normal" text display.
- sprite size of 16x24 pixels (i.e. 3x4 chars),
- pixels can either be white, black, or transparent, requiring a mask,
- possible for a sprite to be partially off-screen,
- sprites are drawn from a character pool, in a copy of the regular charset. Used are characters xx-127, and yy-255 (so, where a character is used for a sprite, its reverse also is),
- flicker-free redraw, with priorities, i.e. new, unused chars from the pool are prepared for the old position, and new position of the sprite, and then written instantly. This will quite possibly require an off-screen map (-> which leads to a natural number of max. 8 sprites) - signifying on which position sprite #x is visible. (-> also usable for sprite collision check?),
- 8x12 = 96 + (12 for old position) + (12 for new position) ~= 120 chars -> 64..127, and 192..255 used for sprites,
- routine should check regularily, whether normal text chars have overwritten a sprite, regenerating that position (and taking the new char into account). (what happens, when the screen is scrolled?)
Greetings,
Michael
- compatible with "normal" text display.
- sprite size of 16x24 pixels (i.e. 3x4 chars),
- pixels can either be white, black, or transparent, requiring a mask,
- possible for a sprite to be partially off-screen,
- sprites are drawn from a character pool, in a copy of the regular charset. Used are characters xx-127, and yy-255 (so, where a character is used for a sprite, its reverse also is),
- flicker-free redraw, with priorities, i.e. new, unused chars from the pool are prepared for the old position, and new position of the sprite, and then written instantly. This will quite possibly require an off-screen map (-> which leads to a natural number of max. 8 sprites) - signifying on which position sprite #x is visible. (-> also usable for sprite collision check?),
- 8x12 = 96 + (12 for old position) + (12 for new position) ~= 120 chars -> 64..127, and 192..255 used for sprites,
- routine should check regularily, whether normal text chars have overwritten a sprite, regenerating that position (and taking the new char into account). (what happens, when the screen is scrolled?)
Greetings,
Michael
- Mike
- Herr VC
- Posts: 4866
- Joined: Wed Dec 01, 2004 1:57 pm
- Location: Munich, Germany
- Occupation: electrical engineer
This effectively implies a bitmapped screen. The size of the object then can be arbitrary large, and they can easily be erased by drawing them on the same place a second time. You need to decide, whether you pre-store all 8 possible shifts in x direction, or make real-time shifts.
But (and this is a great But), XOR'd objects are also a quite cheap solution, as those objects are not really independent off other screen content. When two of those overlap, corresponding pixels erase out. Over a block of foreground pixels, they appear inverse, if the screen has a chequered pattern you might not recognize them at all.
To get sensible a screen-independance, a sprite must remember the screen content beneath it, and be able to restore it. A sprite, which forces pixels to foreground colour will take the definitions of the underlying chars, write these into a mini-bitmap, OR in its own pattern, define new chars from it, store away the old content, and write its own chars on the text screen.
If you want sprites, that not only can force pixels to foreground, but also to background, you need a pattern and mask definition. The source is first ANDed with the mask, and then EORed with the pattern:
You see, the combination (mask=0, pattern=0) forces pixels to background, (mask=0, pattern=1) forces pixels to foreground, and (mask=1, pattern=0) makes that sprite pixel transparent. (mask=1, pattern=1) reproduces the XOR behaviour for that pixel.
Michael
But (and this is a great But), XOR'd objects are also a quite cheap solution, as those objects are not really independent off other screen content. When two of those overlap, corresponding pixels erase out. Over a block of foreground pixels, they appear inverse, if the screen has a chequered pattern you might not recognize them at all.
To get sensible a screen-independance, a sprite must remember the screen content beneath it, and be able to restore it. A sprite, which forces pixels to foreground colour will take the definitions of the underlying chars, write these into a mini-bitmap, OR in its own pattern, define new chars from it, store away the old content, and write its own chars on the text screen.
If you want sprites, that not only can force pixels to foreground, but also to background, you need a pattern and mask definition. The source is first ANDed with the mask, and then EORed with the pattern:
Code: Select all
source mask pattern result
0 0 0 0
0 0 1 1
0 1 0 0
0 1 1 1
1 0 0 0
1 0 1 1
1 1 0 1
1 1 1 0
Michael
Lunar Leeper has some of the best, smoothest hi-res graphics ever made for a VIC-20 game...so if this is the way you guys choose to go, I think the results will be very nice.eslapion wrote:In a thread on Lemon64, Dr. Bob, the creator of Lunar Leeper indicated he created virtual sprites on the VIC by XORing the "sprite" graphics on top of the background graphics.
-
- Omega Star Commander
- Posts: 1371
- Joined: Thu Jan 31, 2008 2:12 pm
- Website: https://robert.hurst-ri.us
- Location: Providence, RI
- Occupation: Tech & Innovation
First, thanks for the responses and interesting points. I will check out this Lunar Leeper reference to visualize what it is doing and what is capable. If necessary, I'll peek into the code.
My objective here is not to go bloated by way of a screen bitmap, but allow the programmer flexibility with the advantages of VIC custom & ROM characters. I have spent 2-hours drafting an objective, requirements, and API which I will (eventually) clean up and post for feedback.
Mike, you seem to have some robust ideas as to where you would like to see something like this go. Do you have a specific implementation that you are thinking to do? Regardless, I am definitely thinking the same way on:
My draft allows for (unlimited) sprite "banks" of eight each, and sprite sizes of 8x8, 8x16, 16x8, and 16x16. As far as collision-detection and transparency techniques are concerned, that might be included as an adhoc API call (not integrated), because those can be expensive operations in software that are might be better managed by the programmer. After all, this is a 1-mhz processor and VIC is slick but not quick!
Thanks, and please post more thoughts. I appreciate any feedback.[/quote]
My objective here is not to go bloated by way of a screen bitmap, but allow the programmer flexibility with the advantages of VIC custom & ROM characters. I have spent 2-hours drafting an objective, requirements, and API which I will (eventually) clean up and post for feedback.
Mike, you seem to have some robust ideas as to where you would like to see something like this go. Do you have a specific implementation that you are thinking to do? Regardless, I am definitely thinking the same way on:
But no so (at least to start) with:- compatible with "normal" text display.
- possible for a sprite to be partially off-screen
- sprites are drawn from a character pool, in a copy of the regular charset.
- routine should check regularily, whether normal text chars have overwritten a sprite, regenerating that position (and taking the new char into account).
In particular, I am thinker lighter-weight and general purpose to cover (hopefully) broader needs. Also, you mentioned flicker-free, but I did not think that is technically possible with VIC, because of the lack of a raster interrupt -- like on C64 -- or am I mistaken and some technique to do that is available? Of course, optimizing to reduce flickering (off-screen rendering and pulling from a dynamic character pool) will be implemented as long as size & speed is not impacted by it too much. The game needs CPU cycles, too!- sprite size of 16x24 pixels (i.e. 3x4 chars),
- pixels can either be white, black, or transparent, requiring a mask,
- flicker-free redraw, with priorities
My draft allows for (unlimited) sprite "banks" of eight each, and sprite sizes of 8x8, 8x16, 16x8, and 16x16. As far as collision-detection and transparency techniques are concerned, that might be included as an adhoc API call (not integrated), because those can be expensive operations in software that are might be better managed by the programmer. After all, this is a 1-mhz processor and VIC is slick but not quick!
Thanks, and please post more thoughts. I appreciate any feedback.[/quote]
- Mike
- Herr VC
- Posts: 4866
- Joined: Wed Dec 01, 2004 1:57 pm
- Location: Munich, Germany
- Occupation: electrical engineer
Some time ago one other Denial member brought up the Topic 'Sprites in ML', where, ultimately, the program Sprit-imation was discussed. That package went already quite far in the right direction. It even had an API callable from ML, and a BASIC extension included. But it had problems with flicker-free redraws if more than 1 sprite was displayed.rhurst wrote:Mike, you seem to have some robust ideas as to where you would like to see something like this go. Do you have a specific implementation that you are thinking to do?
Like tea can brewed in different strenghts.But no so (at least to start) with:sprite size of 16x24 pixels (i.e. 3x4 chars), [...] pixels can either be white, black, or transparent, requiring a mask, [...] flicker-free redraw, with priorities
Which will do 99% of flicker-free without using raster-IRQ's, ...Of course, optimizing to reduce flickering (off-screen rendering and pulling from a dynamic character pool) will be implemented as long as size & speed is not impacted by it too much.
... and one could sync a VIA IRQ to the raster beam, and thus force the update be done while the raster beam is outside the visible area - in the down, and top border. That would give the remaining 1%.flicker-free, but I did not think that is technically possible with VIC, because of the lack of a raster interrupt -- like on C64 -- or am I mistaken and some technique to do that is available?
Is is not quite clear to me, what you mean with these "banks". Could you explain?My draft allows for (unlimited) sprite "banks" of eight each,
Greetings,
Michael
-
- Omega Star Commander
- Posts: 1371
- Joined: Thu Jan 31, 2008 2:12 pm
- Website: https://robert.hurst-ri.us
- Location: Providence, RI
- Occupation: Tech & Innovation
I read that thread about spritimation ... the BASIC wedges sound compelling to integrate, too, but only after the ML API is declared a success.
As stated before, I have a very good 8-sprite routine now for unexpanded VIC. And I later modified that routine, so it is optimized for the fixed-width maze game in quikman2k8. I would like to expand the original routine's scope, but allow it to be more generalized / flexible to make for easy integration -- little to zero mods required by the game programmer. These enhanced sprite rendering routines might even allow for it to reside in an unexpanded VIC, for small games requiring a limited number of active sprites. Or, a fully-stocked VIC to make use of MANY active sprites and animations.
The notion behind sprite "banks" is to allow the programmer to have multiple 8-sprite allocations, with varying sizes, colors, and modes of operations. For example, it would be possible to have sprite bank0 to have two player ships at 8x16 pixels multi-colored, shooting up to 3-shots each using a single pixel in an 8x8 sprite ... ship1 + 3-shots + ship2 + 3-shots = 8 sprites. Sprite bank1 can have another 8 sprites, say a couple of floating asteroids, a space station to dock with, a spaceman to rescue, an alien ship firing, etc.
Clearly, the more active sprites you have at once on the screen, the more custom characters will get consumed, probably requiring that the game code be written in another 4K/8K block, leaving a sizeable portion of VIC's $1000-$1FFF RAM free for these graphics.
I am also thinking about "allowing" for sprites to automagically interlace, i.e., when two hires sprites happen to overlap, this effect significantly reduces color clash at the expense of reasonable flicker. Or, to interlace them if multiple banks of big sprites are in active use, and there are not enough (> 128) custom characters left in the pool to display all of them at once. For example, I would like to see how VIC can handle a single-pixel sprite, rendered inside an 8x8 cell, but exploding 256 of them (128x2 interlaced) into a starburst effect... this would require 32 banks of 8-sprites. While that is an inefficient implementation, and it may even prove to suck, why not write the API to allow for that kind of contingency?
Hopefully, if it is written well, the 6502 assembler code can be made relocatable, so that it may even port nicely to C16, Plus/4, C64, and C128 that have larger memory, color, and resolution.
As stated before, I have a very good 8-sprite routine now for unexpanded VIC. And I later modified that routine, so it is optimized for the fixed-width maze game in quikman2k8. I would like to expand the original routine's scope, but allow it to be more generalized / flexible to make for easy integration -- little to zero mods required by the game programmer. These enhanced sprite rendering routines might even allow for it to reside in an unexpanded VIC, for small games requiring a limited number of active sprites. Or, a fully-stocked VIC to make use of MANY active sprites and animations.
The notion behind sprite "banks" is to allow the programmer to have multiple 8-sprite allocations, with varying sizes, colors, and modes of operations. For example, it would be possible to have sprite bank0 to have two player ships at 8x16 pixels multi-colored, shooting up to 3-shots each using a single pixel in an 8x8 sprite ... ship1 + 3-shots + ship2 + 3-shots = 8 sprites. Sprite bank1 can have another 8 sprites, say a couple of floating asteroids, a space station to dock with, a spaceman to rescue, an alien ship firing, etc.
Clearly, the more active sprites you have at once on the screen, the more custom characters will get consumed, probably requiring that the game code be written in another 4K/8K block, leaving a sizeable portion of VIC's $1000-$1FFF RAM free for these graphics.
I am also thinking about "allowing" for sprites to automagically interlace, i.e., when two hires sprites happen to overlap, this effect significantly reduces color clash at the expense of reasonable flicker. Or, to interlace them if multiple banks of big sprites are in active use, and there are not enough (> 128) custom characters left in the pool to display all of them at once. For example, I would like to see how VIC can handle a single-pixel sprite, rendered inside an 8x8 cell, but exploding 256 of them (128x2 interlaced) into a starburst effect... this would require 32 banks of 8-sprites. While that is an inefficient implementation, and it may even prove to suck, why not write the API to allow for that kind of contingency?
Hopefully, if it is written well, the 6502 assembler code can be made relocatable, so that it may even port nicely to C16, Plus/4, C64, and C128 that have larger memory, color, and resolution.
- Mike
- Herr VC
- Posts: 4866
- Joined: Wed Dec 01, 2004 1:57 pm
- Location: Munich, Germany
- Occupation: electrical engineer
Agreed.rhurst wrote:I read that thread about spritimation ... the BASIC wedges sound compelling to integrate, too, but only after the ML API is declared a success.
But why do you want to separate the definitions at all? What is supposed to happen, when sprites of different "banks" interact on screen?The notion behind sprite "banks" is to allow the programmer to have multiple 8-sprite allocations, with varying sizes, colors, and modes of operations. [...]
I'm gladly willing to put the time-space trade-off wide into the direction of fast routines at the expense of memory, for this application.Clearly, the more active sprites you have at once on the screen, the more custom characters will get consumed, probably requiring that the game code be written in another 4K/8K block, leaving a sizeable portion of VIC's $1000-$1FFF RAM free for these graphics.
IMO, this effect calls for a bitmapped implementation. A table-driven address-calculation for a single pixel in a bitmap looks like this ...For example, I would like to see how VIC can handle a single-pixel sprite, rendered inside an 8x8 cell, but exploding 256 of them (128x2 interlaced) into a starburst effect...
Code: Select all
; X, Y: co-ordinates
TXA:PHA:LSR:LSR:LSR:TAX
LDA table_lo,X:STA xx:LDA table_hi,X:STA xx+1
PLA:AND #$07:TAX
LDA (xx),Y:EOR two_powers,X:STA (xx),Y
Another implementation could use 64 chars with each 1 pixel set at all possible positions. Did you mean this? Well, then:
Code: Select all
; X, Y: co-ordinates
TYA:PHA:LSR:LSR:LSR:TAY
LDA line_lo,Y:STA xx:LDA line_hi,Y:STA xx+1
PLA:AND #$07:STA char
TXA:PHA:AND #$07:ASL:ASL:ASL:ORA char:STA char
PLA:LSR:LSR:LSR:TAY
LDA char:STA (xx),Y
I'm really poor programming in machine language so I cannot suggest any enhancements but I'm imagining what could be done with this routine... A wonderful world is spreading out.... a world full of games of any type... go on guys, all my regards!!!
No one should tolerate death and violence because tolerance will generate habit.
-
- Omega Star Commander
- Posts: 1371
- Joined: Thu Jan 31, 2008 2:12 pm
- Website: https://robert.hurst-ri.us
- Location: Providence, RI
- Occupation: Tech & Innovation
Great feedback, thanks!
At the very least, I will write a large test application for demo purposes, complete with documentation and source. If it excites me enough, I can see me writing more VIC games using it, and remain quick enough to satisfy my short attention span.
So all of that said, I would like to propose a little time over the coming week or so to produce some alpha code for people to play with. I will post that progress here, and either off my VIC tribute page or a separate link if it gets bigger. I welcome anyone to contribute, criticize, request, applaud, etc. -- as long as it remains fun!
Generalization and flexibility. All active sprites, regardless of bank definition origin, will have to interact with each other, if the desired video effect is to be achieved. While it is yet to be proven, I get the sense that separating them into banks like this will allow for easier integration into a broader scope of games, both small and large.But why do you want to separate the definitions at all? What is supposed to happen, when sprites of different "banks" interact on screen?
Yeah, my example was just a lofty use-case to expand upon how generalized this routine set might be, that's all. This effort won't replace the expert from hand-coding / optimizing their own graphics and animations, because a generalized API cannot account for the objectives of every implementation. So, if it gets to a point where these software sprites are moderately fast for the number of active sprites requested, 96% flicker-free, and optimized to reduce color-clashing -- I would think the limited number of home-brew programmers out there might find it useful for their purposes. And you never know how it might evolve afterward from more implementations.IMO, this effect calls for a bit-mapped implementation.
At the very least, I will write a large test application for demo purposes, complete with documentation and source. If it excites me enough, I can see me writing more VIC games using it, and remain quick enough to satisfy my short attention span.
Yes, working for unexpanded VIC is not a primary objective, so I am not looking toward making it a requirement. If possible, it would be cool to glean a "lite" version out of it, as either separate source or possibly through assembler directives on one source.I'm gladly willing to put the time-space trade-off wide into the direction of fast routines at the expense of memory, for this application.
So all of that said, I would like to propose a little time over the coming week or so to produce some alpha code for people to play with. I will post that progress here, and either off my VIC tribute page or a separate link if it gets bigger. I welcome anyone to contribute, criticize, request, applaud, etc. -- as long as it remains fun!
-
- Omega Star Commander
- Posts: 1371
- Joined: Thu Jan 31, 2008 2:12 pm
- Website: https://robert.hurst-ri.us
- Location: Providence, RI
- Occupation: Tech & Innovation
FYI, I have made some head-way into this little project. I got Mike's raster timing stuff tweaked by some other code, and it now works with PAL mode (tested under VICE), too. Nifty tricks!
I anticipate three APIs will come out of this project: full-buffered, fast-buffered, and a lite version for unexpanded use.
The full-buffered one will mainly be worked on, as I am interested primarily by what VIC can do. Most of the built-in RAM ($1000 - $1FFF) will be required to use this API, so expanded RAM or ROM is required for the program and data.
The fast-buffered version will require less of the built-in RAM, but not nearly enough to make it useful for unexpanded use. I should be able to make a reasonable "lite" version from fast -- and it should be more dynamic than my original code, although probably not as fast.
I anticipate three APIs will come out of this project: full-buffered, fast-buffered, and a lite version for unexpanded use.
The full-buffered one will mainly be worked on, as I am interested primarily by what VIC can do. Most of the built-in RAM ($1000 - $1FFF) will be required to use this API, so expanded RAM or ROM is required for the program and data.
The fast-buffered version will require less of the built-in RAM, but not nearly enough to make it useful for unexpanded use. I should be able to make a reasonable "lite" version from fast -- and it should be more dynamic than my original code, although probably not as fast.
-
- Omega Star Commander
- Posts: 1371
- Joined: Thu Jan 31, 2008 2:12 pm
- Website: https://robert.hurst-ri.us
- Location: Providence, RI
- Occupation: Tech & Innovation
I have a lot going on (83yr old mother-in-law is hospitalized, her house got broken into, wife car repairs, replaced our washing machine, configuring new bladecenter at work, etc.)
... so I had very little time to work on this. That said, I optimized my time in waiting rooms and train rides, and made progress this past week anyways!
I have the first of nine possible character matrix layouts working. The work should get progressively easier as I code each, as it'll get more and more optimized along the way. Follows are the layouts:
The first column (fixed) represent when "float" is off for both X & Y directions -- simple character cell rendering with playfield.
The next two, float X or float Y, allows for sprite to freely move in the X or Y direction. Good for maze games & shooters which require limited motion.
Float X&Y means the sprite can be rendered anywhere within the visible screen area. All float modes allow for "clipping" will allow for the sprite to move partially to wholly off-screen.
Triple video/color buffering is in place, making for interesting effects. "POKE" to the video gets written to a separate playfield/color buffer, which maintains a dirty bitmap for faster updates to the dual screen/color buffers.
Even though I account for the multicolor bit as a sprite attribute, this first pass at this will not have sprite masking; only simple OR'ing with sprite and playfield.
... so I had very little time to work on this. That said, I optimized my time in waiting rooms and train rides, and made progress this past week anyways!
I have the first of nine possible character matrix layouts working. The work should get progressively easier as I code each, as it'll get more and more optimized along the way. Follows are the layouts:
Code: Select all
Sprite Matrix
------------- ----- float -----
HxW fixed X Y X&Y
8x8 @ @A @ @B
A AC
8x16 @A @AB @B @BD
AC ACE
16x8 @ @B @ @C
A AC A AD
B BE
16x16 @B @BD @C @CF
AC ACE AD ADG
BE BEH
The next two, float X or float Y, allows for sprite to freely move in the X or Y direction. Good for maze games & shooters which require limited motion.
Float X&Y means the sprite can be rendered anywhere within the visible screen area. All float modes allow for "clipping" will allow for the sprite to move partially to wholly off-screen.
Triple video/color buffering is in place, making for interesting effects. "POKE" to the video gets written to a separate playfield/color buffer, which maintains a dirty bitmap for faster updates to the dual screen/color buffers.
Even though I account for the multicolor bit as a sprite attribute, this first pass at this will not have sprite masking; only simple OR'ing with sprite and playfield.