Family BASIC Sprite flickers when animated

Started by zmaster18, August 19, 2015, 02:36:12 pm

Previous topic - Next topic

zmaster18

August 19, 2015, 02:36:12 pm Last Edit: August 19, 2015, 07:33:39 pm by zmaster18
Today I was playing around with making a sprite move and animate when I use the arrow keys and no matter which method I use to program the movement of the sprite, there is some flickering. I am using DEF SPRITE. I'm starting to think this is caused from the slow performance of BASIC.

The method to animate a sprite requires you to SWAP the frames of animation and then erase the previous frames of animation. I think my code is efficient, but maybe I'm missing something here.

EDIT: I edited the code a little bit and made things a little smoother. The order that the frames of animation being erased helps. I also tweaked the speed of the penguin moving. There's still the slightest bit of flickering, and it's not consistent in any way.
Here's my code to move the penguin right or left using the arrow keys:



1 CLS:CGSET 1,2
2 PALETB 0,25,48,48,48
10 READ A,B,C,D,X,S
15 DATA 0,1,2,3,100,1
20 DEF SPRITE 0,(0,1,0,0,0)="アイウエ"
30 DEF SPRITE 1,(0,1,0,0,0)="オカキク"
40 DEF SPRITE 2,(0,1,0,1,0)="イアエウ"
50 DEF SPRITE 3,(0,1,0,1,0)="カオクキ"
60 I$=INKEY$
70 IF I$=CHR$(29) THEN S=A:X=X-3:SWAP A,B:
SPRITE C:SPRITE D:SPRITE A
80 IF I$=CHR$(28) THEN S=C:X=X+3:SWAP C,D:
SPRITE A:SPRITE B:SPRITE C
90 SPRITE S,X,100:PAUSE 5
100 GOTO 60


I really don't like how animation is done in BASIC. It requires you to use all 8 of your DEF SPRITE slots if you want to have 4 directions with 2 frames of animation each - just if you want smooth animation.  :mario:

You can use 1 DEF SPRITE slot for the sprite and redefine the sprite every time it draws, but goddamn does it make the sprite flash...or mostly be invisible.

I would imagine using assembly would be better for handling sprite animation, but I wouldn't know how to do this.

UglyJoe

The examples that I've seen redefine the sprite every frame so that it shows the proper animation frame, rather than defining a unique sprite "object" for each frame. 

I haven't tried these examples in a while, but I don't remember it flickering.  Check out some of the examples from this book I scanned a while ago: http://imgur.com/a/CBnOi

zmaster18

Wow, that book your provided is great! I only just skimmed through it but there are some great techniques in there! I had no idea that for STICK you can also put the values for diagonals by adding the 2 directions you want. For example, the instruction manual says you can put the values 1,2,4, and 8. But this book tells you you can put 3,5,6, and 10 for diagonal directions! What a handy technique!

I also like the technique used for making a music player loop during gameplay. I could have figured it out myself, but it's nice to see that my idea was correct.

P

Quote from: zmaster18 on August 20, 2015, 06:07:28 am
I had no idea that for STICK you can also put the values for diagonals by adding the 2 directions you want. For example, the instruction manual says you can put the values 1,2,4, and 8. But this book tells you you can put 3,5,6, and 10 for diagonal directions! What a handy technique!

Yeah that's one of those things that isn't obvious for a beginner and I don't think it's explained in the manual either.

Instead of thinking 8 means UP and so on, think what the first four bits in your variable looks like in binary. 8 in binary is 1000b (b means it's a number in the binary counting system), 4 is 0100b and so on. So these four bits contains each button state: UP, DOWN, LEFT, RIGHT (1=pressed, 0=not pressed). And combining them, for example pressing UP+LEFT would become 1010b which is 10 in decimal.
Same goes for STRIG (the bits are: A, B, SELECT, START).

zmaster18

August 20, 2015, 10:34:05 am #4 Last Edit: August 23, 2015, 08:58:07 am by zmaster18
Quote from: P on August 20, 2015, 09:13:24 am
Quote from: zmaster18 on August 20, 2015, 06:07:28 am
I had no idea that for STICK you can also put the values for diagonals by adding the 2 directions you want. For example, the instruction manual says you can put the values 1,2,4, and 8. But this book tells you you can put 3,5,6, and 10 for diagonal directions! What a handy technique!

Yeah that's one of those things that isn't obvious for a beginner and I don't think it's explained in the manual either.

Instead of thinking 8 means UP and so on, think what the first four bits in your variable looks like in binary. 8 in binary is 1000b (b means it's a number in the binary counting system), 4 is 0100b and so on. So these four bits contains each button state: UP, DOWN, LEFT, RIGHT (1=pressed, 0=not pressed). And combining them, for example pressing UP+LEFT would become 1010b which is 10 in decimal.
Same goes for STRIG (the bits are: A, B, SELECT, START).

I always noticed that the 1,2,4, and 8 were binary but never realized you could just combine the bits like that! The instruction manual doesn't teach you stuff like this. I feel like I really learned something today!  ;D


So I'm trying the method where you only use 1 slot for DEF SPRITE and there is noticeably more flickering. However, I'm using a giant IF multi-statement with a few colons separating the statements. After I LIST, I notice that when I go to the line with the long multi-statement and press RETURN, the Famicom halts for a few seconds and then moves the cursor to the next line. I think that these multi-statements are too slow for the Famicom to process and that's causing the flicker. I'm going to try doing a GOSUB routine instead and see if that makes the processing faster. 

I just modified the program to use GOSUB instead. It does work, but there is just slightly more flickering/flashing than my original program. This is gonna make people who play my games get seizures.

Post Merge: August 21, 2015, 08:22:26 am

I just made a program that moves the penguin with the keyboard in 4 directions using the DEF SPRITE method with GOSUB. It takes almost 1K of memory... I knew it would take a lot of memory, but not this much. I will try using DEF MOVE again once I fully understand it.

DEF SPRITE is easier to use and you have more control over how the sprite is defined. Moving it is simple - you just update its x and y coordinates.
DEF MOVE is a bit tricky because it must finish it's predefined path and must be erased and redrawn, unless I'm missing something. There are also a bunch of other commands like XPOS, YPOS, and POSITION that I must master. I remember when I used DEF MOVE the other day, the animation was flickering, but the character did flash when changing directions. That's because the sprite gets erased and redrawn every time that happens.

I don't think smooth animation is even possible for multi-directional sprites, but I'll keep trying.

Post Merge: August 21, 2015, 01:44:34 pm

Quote from: UglyJoe on August 20, 2015, 03:55:10 am
The examples that I've seen redefine the sprite every frame so that it shows the proper animation frame, rather than defining a unique sprite "object" for each frame. 

I haven't tried these examples in a while, but I don't remember it flickering.  Check out some of the examples from this book I scanned a while ago: http://imgur.com/a/CBnOi

I tried out the example 2 at the back of the book. The 'Pen-Pen' game uses DEF MOVE in a very simple way. It redefines DEF MOVE every time and has a variable DR for its direction. After pressing a directional button, it updates the direction, increase/decrease in X/Y coordinates, and then redraws using POSITION and then a MOVE command. Sadly, there is no animation at all in this method. It works ok and only uses around 200 bytes, but the way it moves is choppy and makes me dizzy and want to barf. When trying to change the speed from anything but 1, the sprite isn't displayed on the screen. This method is a quick, cheap-looking way to get 4 directional movement but there is no animation and it looks awkward and there's no way to slow it down.

I'm going to keep trying to figure out how to make a sprite look good while moving...if it's even possible in BASIC.   ???

Post Merge: August 22, 2015, 03:04:26 pm

I've tried the example in the instruction manual on page 35 that uses DEF MOVE. First of all, it only uses 200 bytes. It has issues with control because it has to wait for animation to stop in order to read the controller's next button press. Because of this, there is a bit of delay with control. The character won't change the direction you want to 100% of the time. The character flashes every time it changes direction but while moving in the same direction there is no flickering. The biggest problem with this method is that the character continues to move even when you aren't pressing the D-pad.

Here's my modified version of  the code to support the arrow keys on the keyboard:

5 CLS:SPRITE ON
10 SPRITE ON
20 CGSET 1,2
30 I$=INKEY$
40 IF I$=CHR$(30) THEN D=1
50 IF I$=CHR$(28) THEN D=3
60 IF I$=CHR$(31) THEN D=5
70 IF I$=CHR$(29) THEN D=7
80 IF MOVE(M)=-1 THEN 80                           //wait until movement is done. Remove this line for more responsive control
90 IF M=D THEN 120                                         //if copy is the same as direction, skip to 120 and keep moving
95 DEF MOVE(D)=SPRITE(4,D,1,2,)              //define character with new direction
100 ERA M:POSITION D,XPOS(M),YPOS(M):M=D    //erase old copy,get position of copy and put new direction here. make a copy of this direction
110 MOVE D:GOTO 30                                                   //move new direction
120 MOVE M:GOTO 30                                                  //keep moving copy of direction


So what's happening in this code is first input is read from the keyboard, and if the direction is a new direction redraw the character. If the direction is the same, keep moving the character.

Post Merge: August 23, 2015, 08:58:07 am

Ok, here's the new and improved version that stops the character movement if no key is pressed:

10 CLS:SPRITE ON:CGSET 1,2
20 I$=INKEY$
30 IF I$=CHR$(30) THEN D=1:GOTO 80
40 IF I$=CHR$(28) THEN D=3:GOTO 80
50 IF I$=CHR$(31) THEN D=5:GOTO 80
60 IF I$=CHR$(29) THEN D=7:GOTO 80
70 CUT D,M:GOTO 20
80 IF M=D THEN 120
90 DEF MOVE(D)=SPRITE(4,D,1,1)
100 ERA M:POSITION D,XPOS(M),YPOS(M):M=D
110 MOVE D:GOTO 20
120 MOVE M:GOTO 20


This time I've added the CUT command to stop movement of the character. I'm getting pretty satisfied with this method so far. I don't think it gets better than this! This is a  little bit more than 200 bytes and animation is perfect unless you change direction. I think the speed of the character is good as well with 1 as the speed. You can make it just a bit faster by increasing the distance from 1 like I have to 200. But the animation will look kinda silly because it's too fast.

zmaster18

I just found the better/more efficient way to get the value of keys pressed as well as controller d-pad:


5 S=STICK(0)
10 K=ASC(INKEY$)
20 IF K=28 OR S=1 THEN //right
30 IF K=29 OR S=2 THEN //left
40 IF K=30 OR S=8 THEN //up
50 IF K=31 OR S=4 THEN //down

80sFREAK

clap clap clap (where is thumbs up icon by the way?)
I don't buy, sell or trade at moment.
But my question is how hackers at that time were able to hack those games?(c)krzy