Bitmap animation

Basic and Machine Language

Moderator: Moderators

User avatar
Ivanhoe76
Vic 20 Devotee
Posts: 200
Joined: Fri Sep 28, 2007 11:17 am
Location: Italy

Bitmap animation

Post by Ivanhoe76 »

I know, i'm a rookie, but I'm trying to learn how I can get a good smooth bitmap animation on the vic. I thought to use the way described on Compute! Magazine (i.e. create a series of u.d.g., each one shifted of one pixel to simulate a bitmap animation). My question is: is this the only way to create smooth animation in basic since it requires the waste of a lot of u.d.g.?
No one should tolerate death and violence because tolerance will generate habit.
carlsson
Class of '6502
Posts: 5516
Joined: Wed Mar 10, 2004 1:41 am

Post by carlsson »

I believe the thread you want to read is software sprites initiated by rhurst. Of course it requires you to at least party work in machine code, ideally using the ca65 assembler. The idea behind software sprites is to allocate a few user-definable characters and copy another graphic into them, dynamically shifted as you go.

Perhaps it would be possible to add a Basic API to the library, at least so you can set up sprites and get them animated by a series of SYS calls or similar.
Anders Carlsson

Image Image Image Image Image
User avatar
Mike
Herr VC
Posts: 4841
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: Bitmap animation

Post by Mike »

Ivanhoe76 wrote:i.e. create a series of u.d.g., each one shifted of one pixel to simulate a bitmap animation ...
At least three ways spring to my mind here:

1. All shifted specimen within the actual character set,
2. Some (e.g. 2 or 4) characters dedicated to the sprite, and copying from a set of pre-shifted data outside the actual character set, or
3. Only holding an un-shifted definition, computing the shifted sprite data on-the-fly.

While the 1st method occupies the most place within the "live" character set, it's also undoubtedly the fastest, since you only need to POKE 2 or 4 characters in screen RAM to move the figure by one pixel. It might even be viable from BASIC, as the article in Compute! suggests.

The 2nd, and 3rd method are only viable with ML, as you'll at least need to copy 16 or 32 bytes, let alone rotate them in place. The 3rd method essentially is the one used by Robert's Software Sprite Stack.

In MINIPAINT, I use a variant of the 2nd method to provide the cursor. The cursor does not need to be positioned at every pixel position within a char, but the hires cursor takes 4, and the multicolour cursor takes 2 different positions within a 3x2-character grid.

Greetings,

Michael
TBCVIC
Vic 20 Hobbyist
Posts: 127
Joined: Thu Mar 05, 2009 3:38 am

Post by TBCVIC »

Very nicely described Mike!
My new game uses the 2nd method too.
Ola Andersson
Image
User avatar
Ivanhoe76
Vic 20 Devotee
Posts: 200
Joined: Fri Sep 28, 2007 11:17 am
Location: Italy

Post by Ivanhoe76 »

Thanks guys, your explanation is very clear but a lot further from my knowledge... Currently I think the only easy way for me is the one described in Compute!, the first method mentioned by mike!
No one should tolerate death and violence because tolerance will generate habit.
carlsson
Class of '6502
Posts: 5516
Joined: Wed Mar 10, 2004 1:41 am

Post by carlsson »

Will you want objects to meet, i.e. a character walks straight into a wall? In that case the first method is unsuitable.

You also need to keep track which frame you have displayed, as the character may take 1-4 squares in possession depending of position. You can avoid this by defining two to four characters for each frame, depending on whether the character moves horizontally, vertically or both.

At worst, you may end up with 8*8 = 64 pre-defined custom characters just to animate one 8x8 pixel object. That is 512 bytes of mostly waste.

The second method is slightly better, but not by much. At least you could OR two different patterns into place to make things meet.

I believe a Basic API for the sprite stack is the most flexible and in the long run most memory conservative approach.
Anders Carlsson

Image Image Image Image Image
User avatar
Mike
Herr VC
Posts: 4841
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Post by Mike »

carlsson wrote:The second method is slightly better, but not by much. At least you could OR two different patterns into place to make things meet.
Or you can mask out parts of the background, and then OR in the data in a second step, so a pixel of the sprite definition is either transparent or is one of 2 or 4 colours - depending whether it is hires, or multicolour.
I believe a Basic API for the sprite stack is the most flexible and in the long run most memory conservative approach.
Providing pre-shifted data instead of constructing that data on the fly is one example of the space-vs-time trade-off. And then there's also the 'ease-of-implementation' issue. ;)
User avatar
Jeff-20
Denial Founder
Posts: 5759
Joined: Wed Dec 31, 1969 6:00 pm

Post by Jeff-20 »

Slightly off topic: Smooth animation begs for great collision detection. Have you ever played Witch Way? Grrr. I hate when I've (the player controlled character) made contact with an object that is clearly 7 pixels away!
High Scores, Links, and Jeff's Basic Games page.
carlsson
Class of '6502
Posts: 5516
Joined: Wed Mar 10, 2004 1:41 am

Post by carlsson »

I don't think we've even addressed collisions yet.

Space vs time.. that's true, I had forgotten most VIC-20 users these days have at least 8-16K expansion memory, many even have 32K in one form or another. Since Ghislain just released a great 32K game, chances are that even more people will get themselves a good memory expansion which also lets other developers trade bytes for raster lines. ;-)
Anders Carlsson

Image Image Image Image Image
TBCVIC
Vic 20 Hobbyist
Posts: 127
Joined: Thu Mar 05, 2009 3:38 am

Post by TBCVIC »

I'll release my game on a 4GB cart :)
Ola Andersson
Image
User avatar
Mike
Herr VC
Posts: 4841
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Post by Mike »

Just for fun I made a quick byte poll. The cursor display in MINIPAINT uses:

- 288 bytes for 6 shifted copies of the cursor @ 48 bytes each,
- 66 bytes for pre-calculated address tables, and state data,
- 273 bytes for code contained in 3 sub-routines.

Not counting the calls from the main program into these sub-routines. Together 627 bytes.

Here's the sub-routine, which updates the cursor display, i.e. makes it blink. Register A contains the desired colour source on entry:

Code: Select all

.C:4da3   85 F9      STA $F9
.C:4da5   AD E7 4C   LDA $4CE7    ; get pointer to definition, and copy to ZP $FB/$FC
.C:4da8   85 FB      STA $FB
.C:4daa   AD E8 4C   LDA $4CE8
.C:4dad   85 FC      STA $FC
.C:4daf   A0 00      LDY #$00
.C:4db1   B1 FB      LDA ($FB),Y
.C:4db3   49 FF      EOR #$FF
.C:4db5   39 D0 1B   AND $1BD0,Y  ; clear non-background pixels,
.C:4db8   85 FA      STA $FA
.C:4dba   B1 FB      LDA ($FB),Y
.C:4dbc   25 F9      AND $F9      ; apply colour source to cursor data,
.C:4dbe   05 FA      ORA $FA      ; merge into background data, and store.
.C:4dc0   99 D0 1B   STA $1BD0,Y
.C:4dc3   C8         INY
.C:4dc4   C0 30      CPY #$30     ; loop over 48 bytes
.C:4dc6   D0 E9      BNE $4DB1
.C:4dc8   60         RTS
To display the cursor, characters 122 .. 127 in the character set beginning at $1800 are used, i.e. $1BD0 .. $1BFF.
Last edited by Mike on Fri Oct 23, 2009 3:46 am, edited 1 time in total.
User avatar
Ivanhoe76
Vic 20 Devotee
Posts: 200
Joined: Fri Sep 28, 2007 11:17 am
Location: Italy

Post by Ivanhoe76 »

You're right Jeff, I haven't thought of collisions!!! That will be a greater problem than a smooth animation!!! There's too much I still have to learn about programming...
No one should tolerate death and violence because tolerance will generate habit.
carlsson
Class of '6502
Posts: 5516
Joined: Wed Mar 10, 2004 1:41 am

Post by carlsson »

Hm. In multicolour mode you get wider pixels and less smooth animation. On the other hand you get fewer frames to precalculate and it will take slightly less space, in particular if you restrict yourself to a vertical resolution as low as the horizontal one even if not required.
Anders Carlsson

Image Image Image Image Image
User avatar
Mike
Herr VC
Posts: 4841
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Post by Mike »

If you arrange the destination character bytes on screen in column-major order, there's no need to store different versions for vertical displacements. You'll just have to pad the definition at the top with up to 7 zero bytes, and begin reading with 0 to -7 bytes offset from the original start to shift down the result.

That's a space optimisation I didn't do in the cursor display yet. It would save me maybe around 100 bytes. But that still wouldn't allow the program to work with a +8K expansion only. ;)
Last edited by Mike on Fri Oct 23, 2009 3:59 am, edited 1 time in total.
carlsson
Class of '6502
Posts: 5516
Joined: Wed Mar 10, 2004 1:41 am

Post by carlsson »

Ivanhoe76 wrote:There's too much I still have to learn about programming...
Do you have a prototype game using traditional character graphics? Otherwise perhaps you should begin there, and convert it to smoother graphics later on. I imagine one needs to keep track of virtual coordinates of a high resolution screen to practically solve collisions. Perhaps several sets of arrays which have the indexes intact:

DIM O$(20),X(20),Y(20),T(20)

X and Y would keep track of virtual coordinates. T would have a numerical value for what kind of object it is: enemy, bullet, dangerous or ignorable object. O$ may be used to name objects if needed. Some of these could be put in a multi-dimensional array but I think it takes more memory. You could also store the numerical values directly into memory using PEEK and POKE instead of using variables.

When something moves, you check the screen matrix as usual. As soon as two objects get within the same 8x8 square, you need to decide whether they can co-exist and how close they can get by calculating the virtual coordinate and determine which object it may be you encountered. This can get problematic if more than two objects occupy the same square.
Anders Carlsson

Image Image Image Image Image
Post Reply