Ray of lights

Previous topic - Next topic

Albert

Hi!

I'm experimenting with ray of lights. You can download the fully commented project from here or you can found in the attachment.
http://dl.dropbox.com/u/292449/lightrays.zip




[attachment deleted by admin]

Albert

#1
Here is the code:

Code (glbasic) Select

// --------------------------------- //
// Project: Shadow
// Start: September 21, 2011
// IDE Version: 9.006

//written by Bence Dobos, 2011

SETCURRENTDIR("Media") // seperate media and binaries?
SYSTEMPOINTER TRUE

LOADFONT "smalfont2.png",1
SETFONT 1

//card
GLOBAL maxcard = 4
GLOBAL spr_card = 0
GLOBAL card_w, card_h
GLOBAL map[]

//player
GLOBAL spr_player = 10
GLOBAL plr_x=1000, plr_y=1050

//blob
GLOBAL spr_blob = 20 //first blob

//screen
GLOBAL scr_w, scr_h
GLOBAL scr_wf, scr_hf //half

//gui object
GLOBAL gui AS UIState

//all the variables you can change using the GUI
GLOBAL r=255,g=255,b=255
GLOBAL alpha=150
GLOBAL alpha2=20
GLOBAL LightSource=TRUE
GLOBAL iter=2 //keep it low for slower machines
GLOBAL raystep=1
GLOBAL scale=10
GLOBAL nblob=0
GLOBAL showGUI=FALSE
GLOBAL lightrays=TRUE
GLOBAL controlsheme=0 //0 keyboard, 1 mouse
//init
GETSCREENSIZE scr_w, scr_h
scr_wf=scr_w/2
scr_hf=scr_h/2

//creating random map, for a nice background
DIM map[10][10]
FOR x=0 TO 9
FOR y=0 TO 9
map[x][y]=RND(maxcard-1)
NEXT
NEXT

//loadind cards
//NOTE: all the graphics from Draco by Puli Games (c)
FOR i=0 TO maxcard-1
LOADSPRITE "card"+i+".png", spr_card+i
NEXT
GETSPRITESIZE spr_card, card_w, card_h
DEBUG card_w+"\n"
DEBUG card_h+"\n"
IF card_w=0 OR card_h=0
DEBUG "card not loaded!\n"
END
ENDIF


//loading player
//NOTE: all the graphics from Draco by Puli Games (c)
LOADSPRITE "player0.png", spr_player

//loading blobs
LOADSPRITE "blob.png", spr_blob
LOADSPRITE "blobinv.png", spr_blob+1
LOADSPRITE "blobtrans.png", spr_blob+2

//creating screens
CREATESCREEN 5, 250, scr_w, scr_h
CREATESCREEN 6, 251, scr_w, scr_h

//gameloop
WHILE KEY(1)=0
//prepare the gui, and catch all the interesting keyboard and mouse events
gui.prepare()

//render the background
ALPHAMODE 0
rendermap()

IF lightrays
//render ray of lights
USESCREEN 5
CLEARSCREEN

//initial light source
ALPHAMODE (alpha-100)/100.0
PolySprite( spr_blob+nblob, scr_wf-plr_x+1000, scr_hf-plr_y+1050, scale/10.0, scale/10.0, RGB(r,g,b),0.5,0.5,0.0)

//overlapping player sprite rendered in black
ALPHAMODE 0
PolySprite( spr_player, scr_wf+plr_x-1000, scr_hf+plr_y-1050, 0.5, 0.5, RGB(0,0,0),0.5,0.5,0.0)

//now we have the light source with some covering black image in it (the player)

//this is the trick
//copying the same image to itself, but zooming it bigger every time
//we have to use two screens, and wsitching them.
//IF you using only one AND copying it on itself, you get unexpected result
LOCAL m
LOCAL n
FOR i=1 TO (iter)*2 //start from odd (1), end to even (3,5,7,etc.)!
m=MOD(i,2) //this is the destination screen
n=1-m //this is the source screen
USESCREEN 5+m //we want draw into the destination screen
m=250+m
n=250+n
//copy the whole source screen
DRAWSPRITE n, 0, 0
//then draw again the source screen but zoom it and blend
ALPHAMODE (alpha-100)/100.0
PolySprite( n, scr_wf, scr_hf, 1+(i)/(raystep+1), 1+(i)/(raystep+1), RGB(r,g,b),0.5,0.5,0.0)
NEXT

//back to normal screen
USESCREEN -1

IF LightSource
//a strong additional light to the background, only for fun
ALPHAMODE (190-100)/100.0
PolySprite( spr_blob, scr_wf-plr_x+1000, scr_hf-plr_y+1050, scale/10.0, scale/10.0, RGB(r,g,b),0.5,0.5,0.0)
ENDIF

//blend the raylight screen
ALPHAMODE (alpha2-100)/100.0
PolySprite( 250, scr_wf, scr_hf, 1, 1, RGB(r,g,b),0.5,0.5,0.0)

//player
ALPHAMODE 0
PolySprite( spr_player, scr_wf+plr_x-1000, scr_hf+plr_y-1050, 0.5, 0.5, RGB(255,255,255),0.5,0.5,0.0)

ELSE
//player
PolySprite( spr_player, scr_wf, scr_hf, 0.5, 0.5, RGB(255,255,255),0.5,0.5,0.0)
//blend
ALPHAMODE (alpha-100)/100.0
PolySprite( spr_blob+nblob, scr_wf, scr_hf, scale/10.0, scale/10.0, RGB(r,g,b),0.5,0.5,0.0)
ENDIF

//draw GUI
ALPHAMODE 0
LOCAL color
IF showGUI
IF nblob=0
color=RGB(128,255,128)
ELSE
color=RGB(64,64,64)
ENDIF
IF button(1, 5, 5, 110, 20, color, "blob.png")
nblob=0
ENDIF
IF nblob=1
color=RGB(128,255,128)
ELSE
color=RGB(64,64,64)
ENDIF
IF button(2, 115, 5, 110, 20, color, "blobinv.png")
nblob=1
ENDIF
IF nblob=2
color=RGB(128,255,128)
ELSE
color=RGB(64,64,64)
ENDIF
IF button(3, 225, 5, 110, 20, color, "blobtrans.png")
nblob=2
ENDIF
sliderH(5, 5, 30, 400, 200, alpha)
PRINT FORMAT$(2,1,alpha-100)+"% alpha", 450,30, TRUE
IF button(9, 420, 30, 20, 20, RGB(255,255,0), "0") THEN alpha=100
sliderH(6, 5, 50, 400, 400, scale)
PRINT FORMAT$(2,1,scale/10.0)+"% scale", 420,50, TRUE
sliderH(10, 5, 70, 255, 255, r)
PRINT "R "+r, 270,70, TRUE
sliderH(11, 5, 90, 255, 255, g)
PRINT "G "+g, 270,90, TRUE
sliderH(12, 5, 110, 255, 255, b)
PRINT "B "+b, 270,110, TRUE
IF lightrays
color=RGB(128,255,128)
ELSE
color=RGB(64,64,64)
ENDIF
IF button(13, 5, 130, 110, 18, color, "Light Rays")
lightrays = 1-lightrays
ENDIF
IF LightSource
color=RGB(128,255,128)
ELSE
color=RGB(64,64,64)
ENDIF
IF button(14, 150, 130, 110, 18, color, "Light Source")
LightSource = 1-LightSource
ENDIF
sliderH(15, 5, 150, 200, 20, iter)
iter = INTEGER(iter)
PRINT (iter)*2+" iterations", 215,150, TRUE
sliderH(16, 5, 170, 200, 20, raystep)
raystep = INTEGER(raystep)
PRINT (raystep+1)+" ray step", 215,170, TRUE
sliderH(17, 5, 190, 400, 200, alpha2)
PRINT FORMAT$(2,1,alpha2-100)+"% alpha2", 450,190, TRUE
IF button(18, 420, 190, 20, 20, RGB(255,255,0), "0") THEN alpha2=100
IF controlsheme=0
IF button(20, 5, 220, 120, 20, RGB(255,100,100), "Keyboard") THEN controlsheme=1
ELSE
IF button(20, 5, 220, 120, 20, RGB(255,100,100), "Mouse") THEN controlsheme=0
ENDIF
ENDIF
//draw buttons to bottom. Presets
IF button(50, 5, scr_h-30, 50, 20, RGB(0,255,0), "GUI") THEN showGUI=NOT showGUI
IF button(51, 105, scr_h-30, 90, 20, RGB(255,255,0), "Light")
nblob=0
alpha=145
r=255
g=255
b=255
scale=20
alpha2=200
ENDIF
IF button(52, 205, scr_h-30, 90, 20, RGB(255,255,0), "Sun")
nblob=1
alpha=145
r=255
g=240
b=180
scale=20
alpha2=200
ENDIF
IF button(53, 305, scr_h-30, 90, 20, RGB(255,255,0), "Light+dark")
nblob=1
alpha=5
r=255
g=255
b=255
iter=5
scale=40
alpha2=200
ENDIF
IF button(54, 405, scr_h-30, 90, 20, RGB(255,255,0), "Laser1")
nblob=2
alpha=200
r=255
g=255
b=255
iter=5
scale=70
alpha2=0
ENDIF
IF button(55, 505, scr_h-30, 90, 20, RGB(255,255,0), "Laser2")
nblob=2
alpha=200
r=255
g=255
b=255
iter=5
scale=70
alpha2=200
ENDIF

//move player
IF controlsheme=0
IF gui.up THEN DEC plr_y
IF gui.down THEN INC plr_y
IF gui.left THEN DEC plr_x
IF gui.right THEN INC plr_x
ELSE
plr_x = gui.mousex + 1000 - scr_wf
plr_y = gui.mousey + 1050 - scr_hf
ENDIF
SHOWSCREEN

gui.finish()
WEND

//simplified render function from Draco
FUNCTION rendermap:
LOCAL x=plr_x-scr_wf, y=plr_y-scr_hf
LOCAL mx%=x/card_w, my%=y/card_h
LOCAL cx, cy
cx=mx*card_w-x
cy=my*card_h-y
WHILE my<10 AND cy<scr_h
IF (mx>=0 AND my>=0 AND mx<10 AND my<10)
DRAWSPRITE map[mx][my], cx, cy
ENDIF
INC mx, 1
INC cx, card_w
IF mx>scr_w
mx=x/card_w
cx=mx*card_w-x
INC my, 1
INC cy, card_h
ENDIF
WEND
ENDFUNCTION

//made for blobmondter by Bence Dobos

//Draw and colorize a sprite. You can set the handle point, rotation, scale and color of the sprite
//Written by Bence Dobos
//spr - the ID of the sprite
//scalex, scaley - the ratio of the sprite scale [0.0-inf]
//color - 0xffffff is the normal color
//xc,yc - the ratio of the handle point of the sprite [0.0-1.0], this point is used to draw the sprite, rotate and scale. 0,0 is the top-left point, 0.5,0.5 is the center point
//rot - rotation of the sprite [0-360]
//w,h - width, height of the sprite in pixel, if not specified it's determined automatically
FUNCTION PolySprite: spr, x, y, scalex, scaley, color=0xffffff, xc=0.0, yc=0.0, rot=0, w=-1, h=-1
IF w=-1
GETSPRITESIZE spr, w, h
ENDIF
LOCAL w2=w*scalex
LOCAL h2=h*scaley
LOCAL xcenter=x+xc*w2
LOCAL ycenter=y+yc*h2
LOCAL xr1=-xc*w2
LOCAL yr1=-yc*h2
LOCAL xr2=(1.0-xc)*w2
LOCAL yr2=-yc*h2
LOCAL xr3=(1.0-xc)*w2
LOCAL yr3=(1.0-yc)*h2
LOCAL xr4=-xc*w2
LOCAL yr4=(1.0-yc)*h2

LOCAL x1, y1, x2, y2
LOCAL x3, y3, x4, y4
IF rot<>0
LOCAL sp = SIN(rot)
LOCAL cp = COS(rot)
x1 = xr1*cp-yr1*sp+x
y1 = xr1*sp+yr1*cp+y
x2 = xr2*cp-yr2*sp+x
y2 = xr2*sp+yr2*cp+y
x3 = xr3*cp-yr3*sp+x
y3 = xr3*sp+yr3*cp+y
x4 = xr4*cp-yr4*sp+x
y4 = xr4*sp+yr4*cp+y
ELSE
x1=xr1+x
y1=yr1+y
x2=xr2+x
y2=yr2+y
x3=xr3+x
y3=yr3+y
x4=xr4+x
y4=yr4+y
ENDIF

STARTPOLY spr
  POLYVECTOR   x1, y1,  0,  0, color
  POLYVECTOR   x2, y2,  w,  0, color
  POLYVECTOR   x3, y3,  w,  h, color
  POLYVECTOR   x4, y4,  0,  h, color
ENDPOLY
ENDFUNCTION


About IMGUI: http://www.glbasic.com/forum/index.php?topic=5431.0

Ian Price

That's really cool. Nice one =D
I came. I saw. I played.

Albert

Changed the program a bit to adapt to the Galaxy S 800x480 resolution. Running fast on android.
However IMGUI not so good with touchscreen.

bigsofty

It's lovely affect, had fun just messing around with the params! ;)
Cheers,

Ian.

"It is practically impossible to teach good programming style to students that have had prior exposure to BASIC.  As potential programmers, they are mentally mutilated beyond hope of regeneration."
(E. W. Dijkstra)

Nathan

I agree with the above, superb work!

Marmor

thx a lot ! great work

Wampus


Albert

#8
You can create a whole bunch of light sources if you want, this not affect the speed, only the number of iteration and the screen's resolution.

So change the rows after the comment //initial light source

Code (glbasic) Select

//initial light source
ALPHAMODE (alpha-100)/100.0
//PolySprite( spr_blob+nblob, scr_wf-plr_x+1000, scr_hf-plr_y+1050, scale/10.0, scale/10.0, RGB(r,g,b),0.5,0.5,0.0)
DRAWRECT scr_wf-plr_x+1000 - 100, scr_hf-plr_y+1050 - 150, 50,50, RGB(255, 255, 255)
DRAWRECT scr_wf-plr_x+1000 - 50, scr_hf-plr_y+1050 + 100, 200,20, RGB(255, 255, 255)
DRAWRECT scr_wf-plr_x+1000 - 10, scr_hf-plr_y+1050 - 100, 30, 30, RGB(100, 100, 255)
DRAWRECT scr_wf-plr_x+1000 + 100, scr_hf-plr_y+1050 + 50, 50,50, RGB(255, 0, 255)
DRAWRECT scr_wf-plr_x+1000 + 10, scr_hf-plr_y+1050 + 100, 200,50, RGB(255, 255, 255)
DRAWRECT scr_wf-plr_x+1000 + 0, scr_hf-plr_y+1050 - 50, 20, 20, RGB(100, 100, 255)


This code draw some rectangles:


And with the ray light effect:


Oh this is very rough, even if you push up the iterations and the ray step parameters. It's cool if you use soft shapes, but very jaggy with theese rectangles.
Would be nice some sort of blur. It's easy to implement, just draw the screen to a temporary buffer, but scale it down (lower the resolution) then scale it back and draw.
To achieve this we need a new screen:
//creating screens
CREATESCREEN 5, 250, scr_w, scr_h
CREATESCREEN 6, 251, scr_w, scr_h
CREATESCREEN 7, 252, scr_wf, scr_hf

and change the iteration:
      //this is the trick
      //copying the same image to itself, but zooming it bigger every time
      //we have to use two screens, and wsitching them.
      //IF you using only one AND copying it on itself, you get unexpected result

      LOCAL o
      LOCAL m
      LOCAL n
      FOR i=1 TO (iter)*2 //start from odd (1), end to even (3,5,7,etc.)!
         o=MOD(i,2)   //this is the destination screen
         n=1-o      //this is the source screen
         USESCREEN 5+o   //we want draw into the destination screen
         m=250+o
         n=250+n
         //copy the whole source screen
         DRAWSPRITE n, 0, 0
         //blur
         USESCREEN 7
         STRETCHSPRITE n, 0, 0, scr_wf/i, scr_hf/i      

         //then draw again the source screen but zoom it and blend
         USESCREEN 5+o         
         ALPHAMODE (alpha-100)/100.0
         //PolySprite( n, scr_wf, scr_hf, 1+(i)/(raystep+1), 1+(i)/(raystep+1), RGB(r,g,b),0.5,0.5,0.0)
         PolySprite( 252, scr_wf, scr_hf, (1+(i)/(raystep+1))*i*2, (1+(i)/(raystep+1))*i*2, RGB(r,g,b),0.5,0.5,0.0, scr_wf/i, scr_hf/i)
      NEXT

Also change the draw order, draw the player before the completed ray light sprite.



Schranz0r

WOW... nothing more to say!
I <3 DGArray's :D

PC:
AMD Ryzen 7 3800X 16@4.5GHz, 16GB Corsair Vengeance LPX DDR4-3200 RAM, ASUS Dual GeForce RTX™ 3060 OC Edition 12GB GDDR6, Windows 11 Pro 64Bit, MSi Tomahawk B350 Mainboard

mentalthink

#10
Awesome!!!, only a question, I can implement part of your code in my developement, I think this effect, can be abosulty brutal in my game.

Kinds Regards,
Iván J.

PS: I test whit animates Sprite and it´s abosulutely a beatifull for look.

Albert

Iván of yourse you can! I would love to see what you guys can do with this effect.
I experimented with bloom effect, and I tried to add some very simple shader, but it's really buggy. Are you interested? It would be nice if somebody could fix my shader...

mentalthink

#12
QuoteI experimented with bloom effect, and I tried to add some very simple shader, but it's really buggy. Are you interested? It would be nice if somebody could fix my shader...

:nw: :nw: :nw: , We are speaking in 3D?¿, Sure my friend, I goes crazy for have a 3d Bloom effect, this can be absolutelly brutal.

If you can do, and not it´s too much disturb, for me will be great have a set of shaders.... or only the bloom FX

Thanks again, for your code, and  for permet the use in my game....

Kinds Regards,
Iván J.

Albert


mentalthink

Ok, it´s perfect too!!!, thanks again.