Jump to content
pedgarcia

Plot and Flickering in Action!

Recommended Posts

Hi all,

 

I've been playing with Action! and created this small program where a little ship travels from left to right on screen. The ship is made of 3x5 pixels with the following shape:

 

X
 X
 XX
 X
X

And this is the program:

 byte WAIT_SYNC=$D40A,       
      VCOUNT=$D40B           
                             
 proc plotShip(byte x,y,c)   
   color=c                   
   plot(x+1,y)               
   plot(x+1,y+1)             
   plot(x+2,y)               
   plot(x+1,y-1)             
   plot(x,y-2)               
   plot(x,y+2)               
 return                      
                             
                             
 proc eraseShip(byte x,y,c)  
   color=c                   
   plot(x-1,y-2)             
   plot(x,y-1)               
   plot(x-1,y+2)             
   plot(x,y+1)               
   plot(x,y)                 
 return    

                                     
 proc main()                         
   card i,r,J                        
                                     
   graphics(7+16)                    
   setcolor(4,0,0) ;black background 
   setcolor(0,4,8) ;pink             
   setcolor(1,7,8) ;lt.blue          
                                     
                                     
   for i=2 to 150                    
   do                                
     plotShip(i,40,1) ;DRAW     
     do until vcount&128 od          
     eraseShip(i,40,0) ;ERASE  
   od                                
   ; pause                           
   for i=0 to 32767 do od            
                                     
 return                                                

What I noticed is that if I remove the line waiting for VCOUNT in the main loop, the ship travels with the correct shape but flickering a lot. I was expecting the flickering because I am drawing and erasing the ship in the same loop even considering my erase function is intended to erase the trace the ship would "leave" behind.

 

Then I thought I would add the VCOUNT loop to wait for the vertical line would reach the end of the screen to then erase the ship. My assumption was that I'd draw in one frame, and erase in the other, and that would make the animation smoother. (As I write this I feel I am wrong :| ) . Anyways, what I see on screen is indeed less flickering but the animation is more "jittery" and leaving a small trace, as if the ship is twice as wide.

 

What I am missing here? Is there a better way to do something similar (without using PMG) as my idea is to illustrate the basic built-in graphic functions in action.

 

Thanks

 

 

Share this post


Link to post
Share on other sites

The OS plot routine is slow regardless of language in use.  Finding a VCount sweet spot might be possible but likely not work for the full screen range, be inconsistent PAL/NTSC and maybe be speed inconsistent as well.

 

One thing that can help (sort of) is keep "old x/y" then plot "new x/y" then immediately erase "old" (but first test that new is different to old)

The tradeoff is you might then have a trail rather than flicker.

 

Or better idea - just use a custom plot routine.  Without too much effort a table-based plot routine should be 2-3 times quicker than the OS one.

Edited by Rybags

Share this post


Link to post
Share on other sites

Well here clearly something like player is being drawn. Using bitmap graphics or PMG is way to do it. Certainly not lines, and certainly not OS lines.

Share this post


Link to post
Share on other sites

I don't know Action but in Fastbasic putting the pause before the plotship instead of between plotship and eraseship works better.

 

for x=2 to 150
	pause 0
	exec draw_ship
	exec erase_ship
next

 

Edited by Preppie

Share this post


Link to post
Share on other sites
6 minutes ago, Preppie said:

putting the pause before the plotship

That doesn't make sense as the ship is then erased for the greater proportion of time, there would be little sense in drawing it.

Share this post


Link to post
Share on other sites

He's drawing the new ship then erasing the old ship, if you pause between this then you end up with two ships in view (hence the trail).

 

 

Share this post


Link to post
Share on other sites

No he's not, the loop draws at xpos of I and then waits and then erases at I and then I is incremented, then repeat.

The pause is in-between the draw and erase and so only one ship is view, he just considered about a trail (which would occur if you incremented I before the erase and then draw at the same I)

 

As others have already covered, the slowness of the plot function is more than likely causing either screen tearing or flicking (e.g. if the time to erase & draw is exceeding 1 frame)

Share this post


Link to post
Share on other sites
7 minutes ago, Wrathchild said:

No he's not, the loop draws at xpos of I and then waits and then erases at I and then I is incremented, then repeat.

The pause is in-between the draw and erase and so only one ship is view, he just considered about a trail (which would occur if you incremented I before the erase and then draw at the same I)

 

As others have already covered, the slowness of the plot function is more than likely causing either screen tearing or flicking (e.g. if the time to erase & draw is exceeding 1 frame)

 

 

If this was the case he could draw and erase with the same procedure by just changing the color as the coordinates would be the same.  But the coordinates in the erase proc are not the coords of the ship that has just been drawn, but are of the previously drawn ship.

 

 

Share this post


Link to post
Share on other sites

Sorry Preppie, how was I blind to that :dunce:

 

Indeed, there only needs to be the plotShip and not the eraseShip function and just call plotShip with color zero to erase

Share this post


Link to post
Share on other sites

No problem :)  Confused me a little to start with.  Why is there 2 procs?  Why does the erase proc have 5 plots and the draw proc have 6 plots? 

Share this post


Link to post
Share on other sites

To answer the questions about the two functions.

 

At first I was using the plot one calling twice, one with color 0, but then the results were not good, so I created the eraseShip plotting over the trail the ship would leave behind (therefore 5 points instead of 6). Again, this are just experiences and not suitable for a game, for example :)

 

Based on all the comments, looks like the OS plot routines are very slow and it would be hard to get better results while using them. Is it possible using fast plot functions to plot everything in one single frame?

 

Is the

do until vcount&128 od   

making any difference there at all, or just make it run slower?

 

Thanks again

 

Edited by pedgarcia
typos and more explanations.

Share this post


Link to post
Share on other sites

it's already fast enough to do it in one frame if this is all you want to do, but doing much more would be difficult.  I tried to do 2 ships in FastBasic and ended up with flicker.

 

Even with one ship In FastBasic if you set Y to less than 38 then you start to get problems as there's not enough time to draw the ship.  The more you need to draw the lower down on the screen you'll need to put it.

 

Action may move things along a bit faster, but ultimatly you're restricted by the slow OS plot/draw functions.

 

Edited by Preppie

Share this post


Link to post
Share on other sites

That makes totally sense. My intention was to illustrate the basic graphic capabilities, but maybe I should try something else instead. Or simplify it to the point where it makes sense to someone that knows nothing (almost like me:) )

 

Thanks again for all the input!

Share this post


Link to post
Share on other sites

Given that it's Action and fairly fast, you could probably do your own softsprite routine (even if it's just for a single dot)

Share this post


Link to post
Share on other sites

What is the theory behind soft sprites ? I would guess:

 

1 - save area where sprite will be placed 

2 - Place sprite ORd with background

 

When it moves:

 

3 - restore saved background done in #1

4 - Repeat 

 

Am I in the right track?
 

Thanks

 

 

Share this post


Link to post
Share on other sites

Close - before 2 you perform AND with background which masks out the area the softsprite will appear at, an OR only operation could see target pixel 01 ORed with old pixel 10 giving value 11.

 

An alternate is XOR softsprites where the sprite is simply XORed with the background.  The restore occurs when you XOR back.  Advantage of more speed but disadvantage that weird colours can result.

 

Share this post


Link to post
Share on other sites

More than that, if you have more than one software sprite:

- first "erase" all previous/old sprites in the screen

- then draw all new sprites

..repeat

 

Erasing means restoring the background and it can be done in different ways, for example:

- if you background is empty, you just put 0's in the old sprite position.

- or you could have a copy of the background in memory and just copy the area touched by the sprite from there.

- or use some other logic to restore the background, like when using background "tiles"..

 

Drawing can also be done in different ways, some of them faster but prone to more visual artifacts:

- just storing the sprite data on the screen without masking or caring for the sprite "borders" against the background.

- doing an OR or XOR/EOR of the sprite bytes against the background.

- doing the "proper" method of having a sprite mask (different than the sprite data) to AND against the background (basically cutting a hole with the shape of the sprite in the background),

and then ORing the sprite data against the background.

 

Then there is the problem with rotating the sprite bits inside a byte, because the graphic modes use 8, 4 or 2 pixels per byte.

This can be done in real time (slow) or having the rotations pre-calculated in memory (faster, but using a lot more memory).

 

All this is for graphic modes. Char based software sprites are a little more complex.

  • Like 2

Share this post


Link to post
Share on other sites

There's a method to stop 'tearing' or 'flickering' that a lot of programmers use in Demo's and have done for years, what you do is to create 2 DM's (Display Memories) and whilst 1 is being displayed do the plotting and unplotting, or screen clearing in the non-displaying DM, then switch to engage this DM, and then you clear and plot the image you want in the other DM and when done then switch that DM in etc.. OK?

 

 

EDIT: Another good way, I'm not sure if it has already been mentioned, but all you have to do is re-PLOT your image and just delete the one byte/or end depending on which way the image moves; if the image moves right PLOT it and erase the left bytes etc.

 

Edited by ac.tomo
  • Like 2

Share this post


Link to post
Share on other sites

Great info! I think I am a bit far from be able to achieve that, but I am going to try something similar for the little ship in my sample.

 

Cheers

 

Share this post


Link to post
Share on other sites

If I'm right, its:

 

LOOP

POKE DM-LSB, 1st LSB

POKE DM-MSB, 1st MSB

POKE 88, 2nd  LSB

POKE 89, 2nd MSB

 

plot, clear or whatever, then;

 

POKE DM-LSB, 2nd LSB

POKE DM-MSB, 2nd MSB

POKE 88, 1st LSB

POKE 89, 1st MSB

 

then plot, clear etc..

then LOOP

 

If your using strings use 2 strings for the 2 DM addresses.

LSB and MSB are obtained by:

 

DIM DM1$(1024), DM2$(1024)

 

D1=ADR(DM1$)

MSB1=INT(D1/256)

LSB1= D1-(256*MSB1)

 

D2=ADR(DM2$)

MSB2=INT(D2/256)

LSB2=D2-(256*MSB2)

 

then; DL=PEEK(560)+256*PEEK(561)

DM address:

POKE DL+4, LSB1 or LSB2

POKE DL+5, MSB1 or MSB2

 

Hope that's understandable.

 

  • Like 1

Share this post


Link to post
Share on other sites
15 hours ago, pedgarcia said:

Not sure if I understand what the pokes are doing. Can you explain please?

 

Thanks

I'm not exactly sure what you want me to explain; the DM's, LSB's and MSB's are basically variables. The DM variable points to the Display Memory (which is found at bytes 4 and 5 into the Display List), locations 88 and 89 point to the top-left corner of your graphics 0 screen, in this case you will have 2 Graphics 0 displays, ideally you would protect some RAM but I'll explain that when you get to grips with this.

Edited by ac.tomo

Share this post


Link to post
Share on other sites

Hi, ac.tomo

 

I think I understand now. You are swapping the animation in two "pages". Is that so?

 

Paulo

Share this post


Link to post
Share on other sites
On 5/8/2020 at 2:16 AM, pedgarcia said:

Hi, ac.tomo

 

I think I understand now. You are swapping the animation in two "pages". Is that so?

 

Paulo

2 different screens yes.

  • Thanks 1

Share this post


Link to post
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...