A.D.A. Amiga Demoscene Archive

  Welcome guest! Please register a new account or log in

  

  

  

log in with SceneID

  

Demos Amiga Demoscene Archive Forum / Coding / 2D circle effect question

 

Author Message
kasie
Member
#1 - Posted: 15 Feb 2009 13:04 - Edited
Reply Quote
Hi all. Some days ago i see in some old game called Mickey-Mania (1994) (sega-megadrive console) a nice easy effect which is widely used in games in the past and still. This effect used for the same reassons like fade in/out effects: i.e. change scenes not by 'static' way, but for making 'smooth' feeling. Effect looks like this:

scene1
scene2
scene3
scene4

I.e. we have picture, and we have 'black area' which by 'circle' loop filled picture by black color (kind of fade down). steps are: full_pict,scene1,scene2,scene3,scene4,black_screen

And in other way: we have fully black color screen, and then picture are drawing by circle way and refill by yourself black area. Steps are: black_screen,scene4,scene3,scene2,scene1,full_pict ).

So, i have fucntion which draw a picture (x/y). I have double-buffering fucntion, how these easy effects can be realised ?

I mean somethink like:

void pict_2_black()
{
draw_picture(x,y);
draw_black_area_circle;
flip_for_double_buffer;
}

At moment i think only about drawing picture always in full size, and only change routine for black fill stuff. Or maybe will be better always fill screen by black color, and draw picture by some x/y ?
ZEROblue
Member
#2 - Posted: 15 Feb 2009 14:24 - Edited
Reply Quote
#define W 320
#define H 256

void circularmask(uint8 *framebuffer, uint8 *pict 
ure, uint32 radius) { radius *= radius; uint32 ysqr = H*H/4, ydelta = H*H/4-H+1 - ysqr; for(int y = H; y--;) { uint32 distsqr = W*W/4 + ysqr, xdelta = W*W/4-W+1 - W*W/4; for(int x = W; x--;) { if(distsqr < radius) *framebuffer = *picture; else *framebuffer = 0; framebuffer++; picture++; distsqr += xdelta; xdelta += 2; } ysqr += ydelta; ydelta += 2; } }



Edit:

Z5, another thing you could look into in the forum code is the pre-formatted code blocks, they only accept 44 chars even when there's plenty of room.
kasie
Member
#3 - Posted: 15 Feb 2009 15:07 - Edited
Reply Quote
@ZEROBlue

So, fucntion just build framebuffer line by line based on picturebuffer (picture) and initial black color buffer (initial framebuffer) and can be used per frame like this:

void pict_2_black()
{

  for(rad=100;rad>0; rad--)
  {
     circularmask(frame_buf, picture_buf, rad);
     draw_frame_buffer();
     flip_double_buffering();
  }

}

Correct ? Have any example of how you use it inside your code ?

ps. Z5, yep, very annoing this strange reformat stuff , a bit messed up code in end. Maybe better add somethink like code/code tags ?
ZEROblue
Member
#4 - Posted: 15 Feb 2009 16:02
Reply Quote
You're using it correctly. It redraws the entire frame buffer based on the radius value and the picture buffer. The contents of the frame buffer doesn't matter, you can call circlemask( ) with any radius value at any time and it will render the correct image.

It's a generalized drawing routine using a fast method, but it wouldn't run fast on f.ex an unexpanded A1200. For that you would have to change the algorithm and preferably rewrite in assembler.
kasie
Member
#5 - Posted: 15 Feb 2009 18:07 - Edited
Reply Quote
@ZEROblue

I think difference beetween this C fucntion and the same but on assembler which calc the ticks and so on, will be not so big. Maybe for plain 020 cpu it can be detected visually, but in general i have in mind 060 is minimum, so no problems at all with speed i think.

Only problem here, that i have 640x480 screen with 16bit data. It mean a bit more drawing for every frame: 615kb at frame. It's not so many data for 060 to render it for correct time i think.. Also in your algo you not use any memcpy and memcopy functions, so it must be a faster way too.. Imho even for 040 it must be ok.
ZEROblue
Member
#6 - Posted: 15 Feb 2009 19:03
Reply Quote
Well I rewrote that code in assembler, and on an unexpanded WinUAE A1200 it needs 13 frames to render a 320x256x1 screen. I wouldn't count on it pulling off 50 FPS for a 640x480x16 screen on an 060 :D

It's a neat example but for practical purposes on an Amiga you need to specialize the algorithm a bit.
kasie
Member
#7 - Posted: 15 Feb 2009 19:06 - Edited
Reply Quote
I tryed at moment this routine with 640x512x256 cols picture like by this way:

for(step=400;step>10;step-=1)
{
circularmask(frame_buff, logo, step);
WritePixelArray8(window->RPort,0,0,640-1,480-1,(ch ar *)frame_buff, &temp_rp);
WaitTOF();
}

Works just cool. Speed are ok even on 030-50mhz (i mean speed of rendering, not WritePixelArray:) ). The good think also that by 'step' value we can control the speed of effect and also can skip every 3 pixels frame for example and draw only 1/4.

But at all, for more good looking effect, better change this "absolutly right circle" to some kind of elipse maybe ?

How you count how many frames are used for rendering on winaue ? Just want try to setup 040 with 33mhz and check how many frames are need it for 640x480x8 picture
ZEROblue
Member
#8 - Posted: 15 Feb 2009 19:45
Reply Quote
How you count how many frames are used for rendering on winaue ? Just want try to setup 040 with 33mhz and check how many frames are need it for 640x480x8 picture


I worked around the weird "turbo effect" in WinUAE by using a copper interrupt to halt between line $137 and $0. After that I just let it render 200 frames and timed it with a stop watch.

 

  Please register a new account or log in to comment

  

  

  

 

A.D.A. Amiga Demoscene Archive, Version 3.0