gfxgfxFreeBASIC Games Directory Forumgfxgfx
gfx gfx
gfx
Welcome, Guest. Please login or register. May 23, 2013, 09:15:37 PM

Login with username, password and session length
11.5.2013 - Added a webpage for the latest FBGD competition.

13.3.2013 - Members registrations temporary disabled. For all membership requests, please email me: lachie13@yahoo.com

30.11.2012 - The ninth issue of BASIC Gaming is out! Read it here: http://games.freebasic.net/forum/index.php?topic=560.0

22.11.2012 - Be sure to check our currently running annual FBGD game making competition. This year's theme is SEASONS OF THE YEAR, 300 $ first place prize, and the competition runs till 18th of February. Link: http://games.freebasic.net/forum/index.php?topic=559.0
gfx
gfx
*
gfxgfx
gfxgfx gfxgfx
gfxgfx Home Help Search Login Register   gfxgfx
gfx gfx
gfx
Pages: [1] 2
Print
Author Topic: Sparkling star drawing routine  (Read 3445 times)
Lachie Dazdarian
Double dipper
Administrator
Forum Sage
*****
Gender: Male
Posts: 1195


lachie13
View Profile WWW Email
« on: February 14, 2008, 05:10:18 PM »

Some of you might remember this awesome (ehm) polygon and star drawing routine of mine I posted quite some time ago in fb.net's Tips and Tricks section:

http://www.freebasic.net/forum/viewtopic.php?t=9603

Anyway, I slightly modified the star drawing code to create a sparkling star effect. You know, like those stars that blink in the sky or like the effect you get when a distant light is facing at you. Something I would like to be able to use in certain animations.

#include "fbgfx.bi"
Using FB

const FALSE = 0
const TRUE = 1
const PI = 3.141593

DECLARE SUB DrawPolygon (centerx as integer, centery as integer, num_of_corners as integer, pradius as integer, pcolor as uinteger, start_angle as SINGLE)
DECLARE SUB DrawStar (centerx as integer, centery as integer, num_of_spikes as integer, inner_radius as integer, outer_radius AS INTEGER, pcolor as uinteger, start_angle as SINGLE)

DIM SHARED AS INTEGER rnd_number, current_corners, current_angle, current_centerx, current_centery, current_radius, current_outer_radius

SCREENRES 640, 480, 32, 1, GFX_ALPHA_PRIMITIVES+GFX_WINDOWED

current_corners = 4
current_angle = 38
current_centerx = 200
current_centery = 200
current_radius = 8
current_outer_radius = 40

DO
   
screenlock

CLS

rnd_number = INT(RND * 5) + 1

Draw String (10,10), "PGUP/PGDOWN - change the number of corners", RGB(255,0,0)
Draw String (10,20), "ARROW UP/DOWN/LEFT/RIGHT - move the polygon", RGB(255,0,0)
Draw String (10,30), "A,S - change the starting angle", RGB(255,0,0)
Draw String (10,40), "1,2 - change the inner angle", RGB(255,0,0)
Draw String (10,50), "3,4 - change the outer angle (with stars)", RGB(255,0,0)

IF MULTIKEY(SC_UP) THEN current_centery = current_centery - 3
IF MULTIKEY(SC_DOWN) THEN current_centery = current_centery + 3
IF MULTIKEY(SC_LEFT) THEN current_centerx = current_centerx - 3
IF MULTIKEY(SC_RIGHT) THEN current_centerx = current_centerx + 3
IF MULTIKEY(SC_S) THEN current_angle = current_angle + 4
IF MULTIKEY(SC_A) THEN current_angle = current_angle - 4
IF MULTIKEY(SC_1) THEN current_radius = current_radius - 2
IF MULTIKEY(SC_2) THEN current_radius = current_radius + 2
IF MULTIKEY(SC_3) THEN current_outer_radius = current_outer_radius - 2
IF MULTIKEY(SC_4) THEN current_outer_radius = current_outer_radius + 2

IF current_corners < 2 THEN current_corners = 2

'DrawPolygon current_centerx, current_centery, current_corners, current_radius, RGB(255,255,255), current_angle*PI/180

FOR count_edge AS INTEGER = 10 TO 0 STEP -1
DrawStar current_centerx, current_centery, current_corners, current_radius+count_edge*3+rnd_number, current_outer_radius+count_edge*3+rnd_number, RGB(245-count_edge*20+rnd_number,245-count_edge*20+rnd_number,245-count_edge*20+rnd_number), current_angle*PI/180
NEXT count_edge

screenunlock

IF MULTIKEY(SC_PAGEUP) THEN
    current_corners = current_corners + 1
    DO
    SLEEP 1
    LOOP UNTIL NOT MULTIKEY(SC_PAGEUP)
END IF

IF MULTIKEY(SC_PAGEDOWN) THEN
    current_corners = current_corners - 1
    DO
    SLEEP 1
    LOOP UNTIL NOT MULTIKEY(SC_PAGEDOWN)
END IF

sleep 10

LOOP UNTIL MULTIKEY(SC_ESCAPE)

SUB DrawPolygon (centerx as integer, centery as integer, num_of_corners as integer, pradius as integer, pcolor as uinteger, start_angle as SINGLE)

DIM unit_angle AS DOUBLE

IF num_of_corners < 2 THEN EXIT SUB

unit_angle = 2*PI/num_of_corners

FOR countcorner AS INTEGER = 1 TO num_of_corners

LINE (centerx + sin(start_angle+unit_angle*(countcorner-1))*pradius, centery - cos(start_angle+unit_angle*(countcorner-1))*pradius) - (centerx + sin(start_angle+unit_angle*countcorner)*pradius, centery - cos(start_angle+unit_angle*countcorner)*pradius), pcolor
   
NEXT countcorner
 
END SUB

SUB DrawStar (centerx as integer, centery as integer, num_of_spikes as integer, inner_radius as integer, outer_radius AS INTEGER, pcolor as uinteger, start_angle as SINGLE)

IF num_of_spikes < 2 THEN EXIT SUB

DIM unit_angle AS DOUBLE

unit_angle = 2*PI/(num_of_spikes*2)

FOR countcorner AS INTEGER = 1 TO num_of_spikes*2
   
IF countcorner = 1 OR countcorner MOD 2 <> 0 THEN LINE (centerx + sin(start_angle+unit_angle*(countcorner-1))*outer_radius, centery - cos(start_angle+unit_angle*(countcorner-1))*outer_radius) - (centerx + sin(start_angle+unit_angle*countcorner)*inner_radius, centery - cos(start_angle+unit_angle*countcorner)*inner_radius), pcolor
IF countcorner > 1 AND countcorner MOD 2 = 0 THEN LINE (centerx + sin(start_angle+unit_angle*(countcorner-1))*inner_radius, centery - cos(start_angle+unit_angle*(countcorner-1))*inner_radius) - (centerx + sin(start_angle+unit_angle*countcorner)*outer_radius, centery - cos(start_angle+unit_angle*countcorner)*outer_radius), pcolor

NEXT countcorner

PAINT (centerx, centery), pcolor, pcolor

END SUB

One possible result:



Anyway, one big problem I have with this routine is that I can't use RGBA with PAINT and that leaves my star edges non-transparent. Just move it over the instructions text and you'll see why this sucks. The whole point of this routine is to have edges that get more and more transparent as they move apart from the center of the star. Is there any way I can do this but still keep the drawing real-time, meaning, that I wouldn't have to generate the star before and then grab it with GET?
« Last Edit: February 23, 2008, 11:21:06 AM by Lachie Dazdarian » Logged

"Things like Basic and Free Basic provide much-needed therapy and a return to sanity and a correct appreciation of people. The arrogant folk really hate a word like 'Basic' - fine, and good riddance." ~ pragmatist
KristopherWindsor
Forum Sage
*****
Gender: Male
Posts: 363


The Thirsty Smiley


View Profile WWW Email
« Reply #1 on: February 14, 2008, 05:32:27 PM »

Why doesn't Paint() work with RGBA()?  Shocked

Anyway, you need to split some of your function calls onto multiple lines so they are legible. Tongue

    Line (_
      centerx + Sin(start_angle + unit_angle * (countcorner - 1)) * pradius, _
      centery - Cos(start_angle + unit_angle * (countcorner - 1)) * pradius _
      ) - ( _
      centerx + Sin(start_angle + unit_angle * countcorner) * pradius, _
      centery - Cos(start_angle + unit_angle * countcorner) * pradius _
      ), pcolor
Logged

Lachie Dazdarian
Double dipper
Administrator
Forum Sage
*****
Gender: Male
Posts: 1195


lachie13
View Profile WWW Email
« Reply #2 on: February 14, 2008, 05:41:57 PM »

Well, I tried to use RGBA with Paint and it didn't work (my entire screen was white or something. Am I doing something wrong? And did you test it yourself?

Logged

"Things like Basic and Free Basic provide much-needed therapy and a return to sanity and a correct appreciation of people. The arrogant folk really hate a word like 'Basic' - fine, and good riddance." ~ pragmatist
relsoft
Recruit
**
Posts: 48


View Profile Email
« Reply #3 on: February 14, 2008, 06:55:34 PM »

Why do it in realtime when GET would:

1. Make rendering faster?
2. Give you some crazy effects (blinking, etc)?
Logged
KristopherWindsor
Forum Sage
*****
Gender: Male
Posts: 363


The Thirsty Smiley


View Profile WWW Email
« Reply #4 on: February 14, 2008, 07:24:08 PM »

Well, I tried to use RGBA with Paint and it didn't work (my entire screen was white or something. Am I doing something wrong? And did you test it yourself?

Yes, I tried it, and got the same all-light-gray effect.
Maybe you can suggest a Paint() update so this works?
It seems the painting only stops when hitting a pixel of the correct color, if it is fully opaque. Shocked
Logged

Lachie Dazdarian
Double dipper
Administrator
Forum Sage
*****
Gender: Male
Posts: 1195


lachie13
View Profile WWW Email
« Reply #5 on: February 15, 2008, 04:22:29 PM »

Well rel, I want to be able to rotate the star and perhaps change its size during animation, so grabbing it before to place it into a memory buffer won't help. Or maybe I'm reading your wrong.

Anyway, no ideas how to make the edges more and more translucent? I have no idea how to do that.
Logged

"Things like Basic and Free Basic provide much-needed therapy and a return to sanity and a correct appreciation of people. The arrogant folk really hate a word like 'Basic' - fine, and good riddance." ~ pragmatist
Pritchard
Global Moderator
Forum Howler
*****
Posts: 149



View Profile Email
« Reply #6 on: February 15, 2008, 05:48:56 PM »

draw on a buffer and paste the buffer with alpha
Logged
Lachie Dazdarian
Double dipper
Administrator
Forum Sage
*****
Gender: Male
Posts: 1195


lachie13
View Profile WWW Email
« Reply #7 on: February 15, 2008, 06:10:05 PM »

How do I paste certain parts with one alpha value, and other parts of the buffer with another alpha value? You know, center of the star - alpha blender = 255, far end of the star - alpha blender = 10.
Logged

"Things like Basic and Free Basic provide much-needed therapy and a return to sanity and a correct appreciation of people. The arrogant folk really hate a word like 'Basic' - fine, and good riddance." ~ pragmatist
KristopherWindsor
Forum Sage
*****
Gender: Male
Posts: 363


The Thirsty Smiley


View Profile WWW Email
« Reply #8 on: February 15, 2008, 06:26:59 PM »

Maybe you can make the innermost lines solid, and make the other lines RGBA()?
Logged

Pritchard
Global Moderator
Forum Howler
*****
Posts: 149



View Profile Email
« Reply #9 on: February 15, 2008, 07:00:44 PM »

How do I paste certain parts with one alpha value, and other parts of the buffer with another alpha value? You know, center of the star - alpha blender = 255, far end of the star - alpha blender = 10.
Don't put anything after alpha.
Logged
Lachie Dazdarian
Double dipper
Administrator
Forum Sage
*****
Gender: Male
Posts: 1195


lachie13
View Profile WWW Email
« Reply #10 on: February 16, 2008, 02:28:17 PM »

Erm...this will work only if the star is drawn with embedded alpha values, and I can't use RBGA with PAINT. I need PAINT to fill in the star. Or is there some other way to do that?

Edit:

Ok. After many attempts, this is the best I could think of.

#include "fbgfx.bi"
Using FB

const FALSE = 0
const TRUE = 1
const PI = 3.141593

DECLARE SUB DrawPolygon (centerx as integer, centery as integer, num_of_corners as integer, pradius as integer, pcolor as uinteger, start_angle as SINGLE)
DECLARE SUB DrawStar (centerx as integer, centery as integer, num_of_spikes as integer, inner_radius as integer, outer_radius AS INTEGER, pcolor as uinteger, start_angle as SINGLE)

DIM SHARED AS INTEGER rnd_number, current_corners, current_angle, current_centerx, current_centery, current_radius, current_outer_radius
DIM SHARED some_buffer AS ANY PTR
DIM SHARED read_col AS UINTEGER

SCREENRES 640, 480, 32, 1, GFX_ALPHA_PRIMITIVES+GFX_WINDOWED

current_corners = 4
current_angle = 38
current_centerx = 200
current_centery = 200
current_radius = 1
current_outer_radius = 30

some_buffer = IMAGECREATE(170,170,0)

DO
   
screenlock

CLS

rnd_number = INT(RND * 5) + 1

Draw String (10,10), "PGUP/PGDOWN - change the number of corners", RGB(255,0,0)
Draw String (10,20), "ARROW UP/DOWN/LEFT/RIGHT - move the polygon", RGB(255,0,0)
Draw String (10,30), "A,S - change the starting angle", RGB(255,0,0)
Draw String (10,40), "1,2 - change the inner angle", RGB(255,0,0)
Draw String (10,50), "3,4 - change the outer angle (with stars)", RGB(255,0,0)

IF MULTIKEY(SC_UP) THEN current_centery = current_centery - 3
IF MULTIKEY(SC_DOWN) THEN current_centery = current_centery + 3
IF MULTIKEY(SC_LEFT) THEN current_centerx = current_centerx - 3
IF MULTIKEY(SC_RIGHT) THEN current_centerx = current_centerx + 3
IF MULTIKEY(SC_S) THEN current_angle = current_angle + 4
IF MULTIKEY(SC_A) THEN current_angle = current_angle - 4
IF MULTIKEY(SC_1) THEN current_radius = current_radius - 2
IF MULTIKEY(SC_2) THEN current_radius = current_radius + 2
IF MULTIKEY(SC_3) THEN current_outer_radius = current_outer_radius - 2
IF MULTIKEY(SC_4) THEN current_outer_radius = current_outer_radius + 2

IF current_corners < 2 THEN current_corners = 2

Line some_buffer, (0, 0)-(170, 170), RGB(0,0,0), BF

FOR count_edge AS INTEGER = 10 TO 0 STEP -1
DrawStar current_centerx, current_centery, current_corners, current_radius+count_edge*3+rnd_number, current_outer_radius+count_edge*3+rnd_number, RGB(245-count_edge*20+rnd_number,245-count_edge*20+rnd_number,245-count_edge*20+rnd_number), current_angle*PI/180
NEXT count_edge

FOR x AS INTEGER = 1 TO 170-1
    FOR y AS INTEGER = 1 TO 170-1
        read_col = POINT (X, Y, some_buffer)
        IF read_col<>RGB(0,0,0) THEN
            FOR check_rgb AS INTEGER = 1 TO 255
                IF read_col = RGB(check_rgb, check_rgb, check_rgb) THEN PSET (x+current_centerx, y+current_centery), RGBA(255,255,255,check_rgb)
            NEXT check_rgb
        END IF
    next y
next x

screenunlock

IF MULTIKEY(SC_PAGEUP) THEN
    current_corners = current_corners + 1
    DO
    SLEEP 1
    LOOP UNTIL NOT MULTIKEY(SC_PAGEUP)
END IF

IF MULTIKEY(SC_PAGEDOWN) THEN
    current_corners = current_corners - 1
    DO
    SLEEP 1
    LOOP UNTIL NOT MULTIKEY(SC_PAGEDOWN)
END IF

sleep 10

LOOP UNTIL MULTIKEY(SC_ESCAPE)

IMAGEDESTROY some_buffer

SUB DrawPolygon (centerx as integer, centery as integer, num_of_corners as integer, pradius as integer, pcolor as uinteger, start_angle as SINGLE)

DIM unit_angle AS DOUBLE

IF num_of_corners < 2 THEN EXIT SUB

unit_angle = 2*PI/num_of_corners

FOR countcorner AS INTEGER = 1 TO num_of_corners

LINE (centerx + sin(start_angle+unit_angle*(countcorner-1))*pradius, centery - cos(start_angle+unit_angle*(countcorner-1))*pradius) - (centerx + sin(start_angle+unit_angle*countcorner)*pradius, centery - cos(start_angle+unit_angle*countcorner)*pradius), pcolor
   
NEXT countcorner
 
END SUB

SUB DrawStar (centerx as integer, centery as integer, num_of_spikes as integer, inner_radius as integer, outer_radius AS INTEGER, pcolor as uinteger, start_angle as SINGLE)

IF num_of_spikes < 2 THEN EXIT SUB

centerx = 80
centery = 80

DIM unit_angle AS DOUBLE

unit_angle = 2*PI/(num_of_spikes*2)

FOR countcorner AS INTEGER = 1 TO num_of_spikes*2

IF countcorner = 1 OR countcorner MOD 2 <> 0 THEN LINE some_buffer,(centerx + sin(start_angle+unit_angle*(countcorner-1))*outer_radius, centery - cos(start_angle+unit_angle*(countcorner-1))*outer_radius) - (centerx + sin(start_angle+unit_angle*countcorner)*inner_radius, centery - cos(start_angle+unit_angle*countcorner)*inner_radius), pcolor
IF countcorner > 1 AND countcorner MOD 2 = 0 THEN LINE some_buffer,(centerx + sin(start_angle+unit_angle*(countcorner-1))*inner_radius, centery - cos(start_angle+unit_angle*(countcorner-1))*inner_radius) - (centerx + sin(start_angle+unit_angle*countcorner)*outer_radius, centery - cos(start_angle+unit_angle*countcorner)*outer_radius), pcolor

NEXT countcorner

PAINT some_buffer, (centerx, centery), pcolor, pcolor

END SUB

The result:


Yeah, it's quite slow, but it's the result I wanted to acomplish. Do you have any ideas how to optimized this code?

If nothing else, I'll be able to use this effect staticly.
« Last Edit: February 16, 2008, 04:00:35 PM by Lachie Dazdarian » Logged

"Things like Basic and Free Basic provide much-needed therapy and a return to sanity and a correct appreciation of people. The arrogant folk really hate a word like 'Basic' - fine, and good riddance." ~ pragmatist
Pritchard
Global Moderator
Forum Howler
*****
Posts: 149



View Profile Email
« Reply #11 on: February 16, 2008, 09:14:10 PM »

Quote
Erm...this will work only if the star is drawn with embedded alpha values, and I can't use RBGA with PAINT. I need PAINT to fill in the star
Probably would want to code your own PAINT routine then...
Logged
Lachie Dazdarian
Double dipper
Administrator
Forum Sage
*****
Gender: Male
Posts: 1195


lachie13
View Profile WWW Email
« Reply #12 on: February 17, 2008, 09:52:40 AM »

Well yeah. Dr_D showed me something he coded that does that. Wasn't quite fast.

And I personally can't think of a custom PAINT faster than what I'm doing now in my code.

Oh, well. I guess nobody is interested to do this better than me so I'll have to deal with my own solution.
Logged

"Things like Basic and Free Basic provide much-needed therapy and a return to sanity and a correct appreciation of people. The arrogant folk really hate a word like 'Basic' - fine, and good riddance." ~ pragmatist
Dr_D
Forum Sage
*****
Gender: Male
Posts: 204


dr_davenstein
View Profile WWW Email
« Reply #13 on: February 17, 2008, 04:46:54 PM »

Lachie, my example used pset and point. If you converted those to direct buffer reads/writes, I'm sure it wold be quite fast. Wink I can do it, if you want...


EDIT:
Here it is... seems fast enough to me. It should be faster than one that uses function-call recursion.

const False=0, True = not False, ScreenWidth = 640, ScreenHeight = 480

type FloodVars
    X as integer
    Y as integer
end type

declare sub Paint2(byval X as integer, byval Y as integer, byval Col as uinteger)


screen 12
circle(320, 240), 239, 4
Paint2( 320, 240, 1 )
sleep



sub Paint2( byval X as integer, byval Y as integer, byval Col as uinteger)
   
    dim as integer i = 0
    dim as FloodVars ptr FloodId = new FloodVars[ ScreenWidth * ScreenHeight ]
    FloodId[i].X = X
    FloodId[i].Y = Y
   
    dim as ubyte ptr scr = screenptr
   
    do
        PushPixel:
        X = FloodId[i].X
        Y = FloodId[i].Y
        'Pset(X,Y),Col
        scr[y*640+x] = col
       
       
        if Y-1 >-1 then
            'if point(X,Y-1) = 0 then
              if scr[(y-1)*640+x] = 0 then
                Y-=1
                i+=1
                FloodId[i].X= X
                FloodId[i].Y= Y
                goto PushPixel
            end if   
        end if
       
        if X-1>-1 then
            'if point(X-1,Y) = 0 then
                if scr[(y)*640+(x-1)] = 0 then
                X-=1
                i+=1
                FloodId[i].X= X
                FloodId[i].Y= Y
                goto PushPixel
            end if
        end if   
       
        if Y+1<=ScreenHeight then
            'if point(X,Y+1) = 0 then
            if scr[(y+1)*640+(x)] = 0 then
                Y+=1
                i+=1
                FloodId[i].X= X
                FloodId[i].Y= Y
                goto PushPixel
            end if
        end if   
       
        if X+1<=ScreenWidth then   
            'if point(X+1,Y) = 0 then
            if scr[(y)*640+(x+1)] = 0 then
                X+=1
                i+=1
                FloodId[i].X= X
                FloodId[i].Y= Y
                goto PushPixel
            end if
        end if
        i-=1
    loop until i = 0
   
    delete[]FloodId
   
end sub
« Last Edit: February 17, 2008, 05:03:29 PM by Dr_D » Logged

The idea that I can be presented with a problem, set out to logically solve it with the tools at hand, and wind up with a program that could not be legally used because someone else followed the same logical steps some years ago and filed for a patent on it is horrifying.

John Carmack
notthecheatr
Global Moderator
Forum Sage
*****
Gender: Male
Posts: 351


Who's the guy from 21 Jump Street?

notthecheatr TheMysteriousStrangerFromMars
View Profile WWW Email
« Reply #14 on: February 17, 2008, 11:07:35 PM »

Well that's an odd problem with Paint... Lachie you should ask in the Official Forums for it to be fixed.
Logged

The funniest thing happened yesterday.
Pages: [1] 2
Print
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines
Cerberus design by Bloc
Valid XHTML 1.0! Valid CSS!
gfx
gfxgfx gfxgfx