FreeBASIC Games Directory Forum
 Welcome, Guest. Please login or register. May 23, 2013, 09:15:37 PM 1 Hour 1 Day 1 Week 1 Month Forever 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.022.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

Pages: [1] 2
 Author Topic: Sparkling star drawing routine  (Read 3445 times)
Lachie Dazdarian
Double dipper
Forum Sage

Gender:
Posts: 1195

 « 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)

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

current_corners = 4
current_angle = 38
current_centerx = 200
current_centery = 200

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 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
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

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:
Posts: 363

The Thirsty Smiley

 « Reply #1 on: February 14, 2008, 05:32:27 PM »

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

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

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
Forum Sage

Gender:
Posts: 1195

 « 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

 « 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:
Posts: 363

The Thirsty Smiley

 « 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.
 Logged

Lachie Dazdarian
Double dipper
Forum Sage

Gender:
Posts: 1195

 « 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

 « 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
Forum Sage

Gender:
Posts: 1195

 « 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:
Posts: 363

The Thirsty Smiley

 « 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

 « 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
Forum Sage

Gender:
Posts: 1195

 « 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 some_buffer AS ANY PTR

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

current_corners = 4
current_angle = 38
current_centerx = 200
current_centery = 200

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 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
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)
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

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

 « 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
Forum Sage

Gender:
Posts: 1195

 « 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:
Posts: 204

 « 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. 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:
Posts: 351

Who's the guy from 21 Jump Street?

 « 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