How to erase without flicker?

The place for codemasters or beginners to talk about programming any language for the Spectrum.
Post Reply
llewelyn
Manic Miner
Posts: 205
Joined: Thu Feb 22, 2018 3:27 pm
Location: virginias eastern shore
Contact:

How to erase without flicker?

Post by llewelyn »

I'm experimenting with a character that moves by itself.
Using CLS is causing the character to flicker, is there a way to avoid this?
I have a vague idea that OVER may be the answer I need but I havent used it before.

Heres the test program.

5 FOR x = 0 to 20 step 1
10 PRINT AT 0, x; "A"
20 CLS
30 NEXT X
User avatar
PeterJ
Site Admin
Posts: 6855
Joined: Thu Nov 09, 2017 7:19 pm
Location: Surrey, UK

Re: How to erase without flicker?

Post by PeterJ »

I would try printing a space in the previous character position on each iteration of the loop, rather than clearing the screen each time.
llewelyn
Manic Miner
Posts: 205
Joined: Thu Feb 22, 2018 3:27 pm
Location: virginias eastern shore
Contact:

Re: How to erase without flicker?

Post by llewelyn »

Thankyou Peter, I tried that and it sort of worked but then it caused another effect that was unexpected, lots of A 's briefly following the original. So I added more spaces and that reduced the 'ghosts' but what I found was the character moved too quickly so I slowed it down with a PAUSE statement and that got rid of the ghosts!
User avatar
Joefish
Rick Dangerous
Posts: 2041
Joined: Tue Nov 14, 2017 10:26 am

Re: How to erase without flicker?

Post by Joefish »

CLS takes its time because it clears the screen, both pixels and atributes.
If you're not averse to a little bit of machine code, you can have a routine that simply sets the attributes of all characters so that their INK and PAPER are the same, so the screen appears empty. It's a lot quicker.

Code: Select all

org 65368
ld hl,22528
ld de,22529
ld (hl),0
ld bc,735
ldir
ret
This translates into 14 bytes:

Code: Select all

DATA 33,0,88,17,1,88,54,0,1,223,2,237,176,201
Just POKE these bytes in wherever you want in memory and do RANDOMIZE USER nnnn or LET Z=USR nnnnn with the address you poked them to to activate it. For example, to POKE it in just below the UDGs in memory, do CLEAR 65353 (to tell BASIC to reserve the memory above this address) then POKE these 14 numbers in from 65354-65367 and call it with LET Z=USR 65354 (here Z is just some throwaway variable because calls like this always return a number. You may have seen RANDOMIZE USR before, but if you kept using that in a game it would keep resetting the random number generator).

The eighth byte (the second appearance of a zero) is the key one - this is the attribute byte that gets applied to the whole screen. Use 0 for Black. 127 for Bright White. Use Colour * 9 and add 64 if you want BRIGHT. e.g. 6*9 + 64 = 118 for Bright Yellow, 5*9 = 45 for Dull Cyan.

Another byte you might want to fiddle with is that 223 - subtract 32 or 64 bytes (or more x32) off this number to leave one or two (or more) rows at the bottom of the screen untouched, for scores etc.

Also a good idea to do PAUSE 1 at some point in your main game loop. That will synch you up to the TV refresh.
llewelyn
Manic Miner
Posts: 205
Joined: Thu Feb 22, 2018 3:27 pm
Location: virginias eastern shore
Contact:

Re: How to erase without flicker?

Post by llewelyn »

Thanks Joe but thats way above my head, I can barely manage Basic as it is! However I appreciate your feedback and I've saved this post and will have a go at it a little later. What I've got so far works and is:-

10 CLS
20 PRINT AT 10,10; "Press s to STOP"
30 REM perpetual motion experiment
40 REM
50 FOR x=0 TO 30 STEP 1
60 PRINT AT 0,x; " A"
65 REM adjust this for speed
70 PAUSE 5
80 IF x=30 THEN GOTO 10
85 REM emergency stop button
90 IF INKEY$="s" THEN STOP
100 NEXT x
User avatar
R-Tape
Site Admin
Posts: 6353
Joined: Thu Nov 09, 2017 11:46 am

Re: How to erase without flicker?

Post by R-Tape »

It depends what you ultimately have in mind but if you're only moving a small number of characters at a time then CLS (BASIC or machine code) is a steamroller to crack a walnut IMO. I think Peter's suggestion of deleting the old position next time around looks best (though that can still have a slight flicker of the old position*). Here's another way, it's an example of a single # moving around the screen controlled by QAOP.

10 LET v=12: LET h=15: LET ov=v: LET oh=h
50 PAUSE 1: PRINT AT ov,oh;" ";AT v,h;"#";
55 LET ov=v: LET oh=h
60 IF INKEY$="o" AND h>0 THEN LET h=h-1
70 IF INKEY$="p" AND h<31 THEN LET h=h+1
80 IF INKEY$="q" AND v>0 THEN LET v=v-1
90 IF INKEY$="a" AND v<21 THEN LET v=v+1
100 GO TO 50

The critical bit is line 50. PAUSE 1 means the TV screen has only just started being drawn, then you delete the old (ov,oh) and redraw the new (v,h) as quickly as possible - before the TV is drawn. That way there is hardly any flicker. Line 55 updates the old position to delete next time around.

It gets a bit trickier the more you want to print.

*Your code has a bit of this, a quick flicker of the old A is usually present. It's rapid enough to get away with it tho.
User avatar
Seven.FFF
Manic Miner
Posts: 735
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: How to erase without flicker?

Post by Seven.FFF »

*waves at Mike*
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins
llewelyn
Manic Miner
Posts: 205
Joined: Thu Feb 22, 2018 3:27 pm
Location: virginias eastern shore
Contact:

Re: How to erase without flicker?

Post by llewelyn »

Likewise Robin.
llewelyn
Manic Miner
Posts: 205
Joined: Thu Feb 22, 2018 3:27 pm
Location: virginias eastern shore
Contact:

Re: How to erase without flicker?

Post by llewelyn »

Thanks R-Tape I'll give that a try, took me a bit to figure it out. I wanted to understand how to achieve the move/erase starting with one block then I'll work up to doing it with 4 chrs until I eventually have a sprite move subroutine thats reliable and next after that is to design the character and then possibly a wee animation. Should keep me busy all summer!
User avatar
Seven.FFF
Manic Miner
Posts: 735
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: How to erase without flicker?

Post by Seven.FFF »

You can probably get away with printing spaces to clear your sprites, at least for a while. And if you’re moving in whole character jumps.

If you start exploring moving one pixel at a time, or your flicker gets too bad, then it might be worth exploring OVER. There’s two variants:

Think of OVER 1 as overprinting. Like if you hit backspace on a typewriter and typed a second letter on top of an existing one.

Think of OVER 0 as an unPRINT. Like using tippex paper on a typewriter. It’s similar to what you’re doing with spaces, but printing a space is more like a big blob of tippex fluid - an entire 8x8 block of pixels gets erased.

Which technique you use doesn't matter so much until you start having scenery that your sprites move over. Then being able to overprint and unprint more precisely gives you a lot more flexibility.
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins
llewelyn
Manic Miner
Posts: 205
Joined: Thu Feb 22, 2018 3:27 pm
Location: virginias eastern shore
Contact:

Re: How to erase without flicker?

Post by llewelyn »

Thanks Robin, yes I am anticipating eventually moving by pixels but first things first. I need to cut and paste all these useful pieces of programming info, thats the trouble with message bases, locating the hidden gems!
Nomad
Manic Miner
Posts: 600
Joined: Thu Dec 28, 2017 12:38 pm

Re: How to erase without flicker?

Post by Nomad »

Another reason to be more careful about the use of CLS. You are giving up control of how you refresh the screen. If at some point you want to have more elements on the screen odds are you don't want to re-draw them every time you move the player object. CLS throws everything in the bin. The overwrite techniques give you flexibility/options that you wouldn't otherwise have.

A little bit of ghosting I wouldn't sweat as long as it didn't impact gameplay. You got to think about how much time/effort its going to take to get something perfect and if it is possible/worth it. Depends how you are wired I guess.
llewelyn
Manic Miner
Posts: 205
Joined: Thu Feb 22, 2018 3:27 pm
Location: virginias eastern shore
Contact:

Re: How to erase without flicker?

Post by llewelyn »

You're quite right Nomad and I think R-Tape said much the same thing. I only used CLS in the first iteration as a quick and dirty, easy way to get the job done. Also I have since discovered that chasing the ghosts isnt worth it, eventually hopefully no one will notice if theres other things going on to take their mind off minor glitches. Sometimes the ghosts actually work in my favour as can be seen if this is run:-

4BLOKSPRITE.sna

10 CLS
20 PRINT AT 10,10; "Press s to STOP"
30 FOR x=1 TO 30 STEP 1
40 PRINT AT 1,x;" AB "
50 PRINT AT 2,x;" CD "
60 PAUSE 5
70 IF x=30 THEN GOTO 10
80 IF INKEY$="s" THEN STOP
90 NEXT X
dfzx
Manic Miner
Posts: 673
Joined: Mon Nov 13, 2017 6:55 pm
Location: New Forest, UK
Contact:

Re: How to erase without flicker?

Post by dfzx »

Well intentioned as they are, I don't think people trying to push you towards machine code or hacks that clear the previous position with a preceding space are quite what you're after.

Try to think clearly about what you want to do. I would suggest that this psuedo-code is roughly what you're after:

Code: Select all

new_x,new_y = 10,10
print sprite at new_x,new_y

loop:
  old_x,old_y = current sprite position
  decide where you want the sprite to move to
  new_x,new_y = newly decided sprite position
  print a space at old_x,old_y
  print the sprite at new_x,new_y
  loop back to loop:
So start the sprite character at 10,10, then decide where you want it to move to (based on user input or just your simple left-to-right loop for starters). That gives you a new x,y position. Then print a space over the top of the current character to remove it, then print the character in the new location.

Then go round again: note where the character currently is, decide where you want it, then print a space over it to remove it and print it again in its new place. Repeat.

Once you can see what this is doing, convert it to BASIC. :)
Derek Fountain, author of the ZX Spectrum C Programmer's Getting Started Guide and various open source games, hardware and other projects, including an IF1 and ZX Microdrive emulator.
llewelyn
Manic Miner
Posts: 205
Joined: Thu Feb 22, 2018 3:27 pm
Location: virginias eastern shore
Contact:

Re: How to erase without flicker?

Post by llewelyn »

Nicely explained dfzx - thank you.

You are quite correct about the machine code aspect. I have tried and tried, read books, watched video instructions about it but the sad fact of the matter is that I cannot get my head around it and believe me I have tried!

Which is fine, I'm just a dabbler doing a spot of Basic problem solving for the enjoyment of it. I have no ambition to advance beyond Basic and its only because of its Basic that I remain so fond of the machine - emulator - I wish it was a genuine rubber key 48k Mk1 Speccy.
llewelyn
Manic Miner
Posts: 205
Joined: Thu Feb 22, 2018 3:27 pm
Location: virginias eastern shore
Contact:

Re: How to erase without flicker?

Post by llewelyn »

Okay this is a development from the original moving blob. Nothing to write home about really although it took me 8 hours to work out the UDG's and then arrange them to get a moving - staying in one spot but the tracks move - Mk 1 tank! I hope to have it able to move according to keyboard input later, probably take me a couple more days.

Its a .SNA file that has to be downloaded and run in your emulator or machine of choice.

http://s000.tinyupload.com/index.php?fi ... 9323534450
User avatar
R-Tape
Site Admin
Posts: 6353
Joined: Thu Nov 09, 2017 11:46 am

Re: How to erase without flicker?

Post by R-Tape »

Nice wee (not so wee!) UDG tank.

Drawing the tank is a bit cumbersome though & it'll become a pain if you develop the idea.

I'd suggest storing the tank top and bottom as strings, then you can print with a lot less code.

LET TY=8:LET TX=8

LET A$="ABCD":LET B$="EFGH":LET C$="IJKL"

Then to print the tank you can do this:

PRINT AT TY,TX;A$;AT TY+1,TX;B$;

then you can move the tank by manipulating TY,TX.
llewelyn
Manic Miner
Posts: 205
Joined: Thu Feb 22, 2018 3:27 pm
Location: virginias eastern shore
Contact:

Re: How to erase without flicker?

Post by llewelyn »

Thanks R-Tape! I'll give that a test to see how it works.

UDG design can be a real test of patience. What looks good on graph paper doesnt appear like that on screen because of its being so tiny you often have to exaggerate features enough to make them visible. Yet on graph paper it can look really awful, you can hardly make out what it is.

I used BASin to draw them and I wrote the print at code in BASin then saved it as a .sna and transferred it to Fuse which I find much easier to code with.

Before I develop the program I need to rethink the UDGs to get a better looking sprite. More detail and a bit of colour might help which means altering the placement within the character square. Trial and error takes forever.
User avatar
Joefish
Rick Dangerous
Posts: 2041
Joined: Tue Nov 14, 2017 10:26 am

Re: How to erase without flicker?

Post by Joefish »

Yep, you can also use arrays to store how the tank looks going in different directions. But remember that a string is already an array (of characters). So if you want an array with 2 different 'looks', 2 rows of UDGs, and each one 4 characters long, that's a 2x2x4 3-dimensional array.
Post Reply