Mandelbrot viewer with colour cycling

Previous topic - Next topic

fuzzy70

Done more as a exercise than anything else  :D

I get 29fps @ 640x480 which is higher than I expected on my core 2 duo 2.13ghz & crappy gfx card, considering the amount of array modifying & MEM2SPRITE calls. There is probably a far better way of doing it but this is the only way that has popped into my head at the moment.

Do not change the MAX_ITERATION% variable as I have not got round to scaling the fractal data to a 0-255 colour range as yet. Also the MinY & MaxY coords are reversed when they are read into the type due to the image was flipped compared to winfracts output, so I assume winfract treats Y=0 as the bottom of the window & not top.

keys are as follows (although are commented in the code)

F1 = Start colour cycling
F2 = Stop colour cycling
F3 = Previous Fractal point (4 available)
F4 = Next Fractal point (4 available)
Cursor Up = cycle colours up
Cursor Down = cycle colours down
Cursor Left = previous palette
Cursor Right = next palette
Spacebar = Reload the pallette back to defaults (after cycling)

Have fun

Lee

Code (glbasic) Select

TYPE Tpalette
red%[256]
green%[256]
blue%[256]
memcolour[256] // MEM2SPRITE friendly values :)
total%
name$

FUNCTION cycle_memcolours: dir

LOCAL loop%,temp%

SELECT dir

CASE 1

temp%=self.memcolour%[0]
FOR loop = 1 TO 255
self.memcolour%[loop%-1]=self.memcolour%[loop%]
NEXT
self.memcolour%[255]=temp

CASE 0

temp%=self.memcolour%[255]
FOR loop = 255 TO 1 STEP -1
self.memcolour%[loop%]=self.memcolour%[loop%-1]
NEXT
self.memcolour%[0]=temp
ENDSELECT

ENDFUNCTION

ENDTYPE

TYPE Tfrac_coords
MinX#
MaxX#
MinY#
MaxY#
ENDTYPE

CONSTANT up_cursor%=200
CONSTANT down_cursor%=208
CONSTANT left_cursor%=203
CONSTANT right_cursor%=205
CONSTANT F1%=59
CONSTANT F2%=60
CONSTANT F3%=61
CONSTANT F4%=62
CONSTANT SPC%=57

GLOBAL palette[] AS Tpalette
GLOBAL frac_coords[] AS Tfrac_coords
GLOBAL Width%=640,Height%=480
GLOBAL screencolours%[]
GLOBAL screen%[]
GLOBAL currpal%=0
GLOBAL fracount%

LOCAL starttime,endtime,totaltime,fx%,fy%
LOCAL cyclestate%=0,cycledir%=0,curfract%=0

DIM screencolours%[Width%*Height%]
DIM screen%[Width%*Height%]

SETSCREEN Width%,Height%,0
SETCURRENTDIR("Media") // go to media files
LOADFONT "font.png",0
GETFONTSIZE fx%,fy%

loadpalette("palettedata.dat")
readfractcoords()
//draw initial set

calc_mandel(frac_coords[curfract%].MinX#,frac_coords[curfract%].MaxX#,frac_coords[curfract%].MinY#,frac_coords[curfract%].MaxY#)


WHILE NOT KEY(1)

starttime=GETTIMERALL()

IF KEY(up_cursor) THEN cycledir%=1 // UP cursor = cycle colours up
IF KEY(down_cursor) THEN cycledir%=0 // Down cursor = cycle colours down

IF KEY(right_cursor) AND currpal%<palette[0].total%-1 // Right cursor = next palette
INC currpal%,1
refresh_sprite()
SLEEP 200
ENDIF

IF KEY(left_cursor) AND currpal%>0 // Left cursor = previous palette
DEC currpal%,1
refresh_sprite()
SLEEP 200
ENDIF

IF KEY(F1) THEN cyclestate%=1 // F1 = Start Cycle colours
IF KEY(F2) THEN cyclestate%=0 // F2 = Stop Cycle colours

IF KEY(F3) AND curfract%>0 // F3 = Previous fractal
DEC curfract%,1
calc_mandel(frac_coords[curfract%].MinX#,frac_coords[curfract%].MaxX#,frac_coords[curfract%].MinY#,frac_coords[curfract%].MaxY#)
ENDIF

IF KEY(F4) AND curfract%<fracount%-1 // F4 = Next fractal
INC curfract%,1
calc_mandel(frac_coords[curfract%].MinX#,frac_coords[curfract%].MaxX#,frac_coords[curfract%].MinY#,frac_coords[curfract%].MaxY#)
ENDIF

IF KEY(SPC)        // Press space to reload default palette
loadpalette("palettedata.dat")
refresh_sprite()
ENDIF

IF cyclestate%=1
palette[currpal%].cycle_memcolours(cycledir%)
refresh_sprite()
ENDIF

DRAWSPRITE 10,0,0
totaltime=1000/(GETTIMERALL()-starttime)
PRINT "FPS="+INTEGER(totaltime),0,0,1
PRINT "Current palette="+currpal%,0,fx%,1
PRINT "Palette Name="+palette[currpal%].name$,0,fx%*2,1

SHOWSCREEN

WEND

KEYWAIT

FUNCTION calc_mandel: MinX#,MaxX#,MinY#,MaxY#

LOCAL dx#,dy#,x%,y%

dx=(MaxX-MinX)/Width%
dy=(MaxY-MinY)/Height%

FOR y=0 TO Height%-1

FOR x=0 TO Width%-1
screencolours%[x+(y*Width%)]=calc_pixel(MinX+x*dx,MinY+y*dy)
screen%[x+(y*Width%)]=palette%[currpal%].memcolour[screencolours%[x+(y*Width%)]]
NEXT

NEXT

MEM2SPRITE(screen%[],10,Width%,Height%)

ENDFUNCTION

FUNCTION calc_pixel: CA#,CBi#

LOCAL MAX_ITERATION%=255
LOCAL OLD_A#
LOCAL ITERATION%
LOCAL A#,Bi#
LOCAL LENGTH_Z#

A=0
Bi=0

ITERATION=0

REPEAT

OLD_A=A

A=A*A-Bi*Bi+CA
Bi=2*OLD_A*Bi+CBi

LENGTH_Z=A*A+Bi*Bi

IF ITERATION > MAX_ITERATION THEN RETURN MAX_ITERATION
INC ITERATION
UNTIL LENGTH_Z > 4

RETURN ITERATION-1

ENDFUNCTION

FUNCTION refresh_sprite:

LOCAL x%,y%

FOR y=0 TO Height%-1
FOR x=0 TO Width%-1
screen%[x+(y*Width%)]=palette%[currpal%].memcolour[screencolours%[x+(y*Width%)]]
NEXT
NEXT
MEM2SPRITE(screen%[],10,Width%,Height%)
ENDFUNCTION

FUNCTION loadpalette: filename$

LOCAL palcount%,namesize%,palname$,r%,g%,b%,pal_loop%,col_loop%

OPENFILE (1,filename$,TRUE)
READUBYTE 1,palcount
DIM palette[palcount]

palette[0].total%=palcount

FOR pal_loop=0 TO palcount-1

READUBYTE 1,namesize
READSTR 1,palname$,namesize
palette[pal_loop].name$=palname$

FOR col_loop=0 TO 255
READUBYTE 1,r%
palette[pal_loop].red%[col_loop]=r
READUBYTE 1,g%
palette[pal_loop].green%[col_loop]=g
READUBYTE 1,b%
palette[pal_loop].blue%[col_loop]=b
palette[pal_loop].memcolour[col_loop]=RGB(r,g,b)+INTEGER(0xff000000)
NEXT

NEXT

CLOSEFILE 1

ENDFUNCTION

FUNCTION drawpalette: id%

LOCAL x%,y%,r%,g%,b%,cur_colour%

PRINT palette[id].name$,0,10

FOR y=0 TO 15
FOR x=0 TO 15
r=palette[id].red%[cur_colour%]
g=palette[id].green%[cur_colour%]
b=palette[id].blue%[cur_colour%]

DRAWRECT x*16,(y*16)+20,15,15,RGB(r,g,b)

INC cur_colour%,1
NEXT
NEXT

ENDFUNCTION

FUNCTION readfractcoords:

LOCAL amount%,loop%,value#

RESTORE fracdata
READ amount%
fracount%=amount%
DIM frac_coords[amount%]

FOR loop%=0 TO amount%-1
READ value#
frac_coords[loop%].MinX#=value#
READ value#
frac_coords[loop%].MaxX#=value#
READ value#
frac_coords[loop%].MaxY#=value#
READ value#
frac_coords[loop%].MinY#=value#
DEBUG frac_coords[loop%].MinX#+"\n"
DEBUG frac_coords[loop%].MaxX#+"\n"
DEBUG frac_coords[loop%].MinY#+"\n"
DEBUG frac_coords[loop%].MaxY#+"\n"
NEXT
ENDFUNCTION


STARTDATA fracdata:
DATA 4
DATA -2.500000000000,1.499999660000,-1.499999730000,1.500000000000
DATA -1.611111110000,-0.985133316000,0.194154827000,0.663883090000
DATA -1.204480370000,-1.190686790000,0.309634963000,0.319990810000
DATA -0.655607441000,-0.649605315000,0.492290244000,0.496800002000
ENDDATA



[attachment deleted by admin]
"Why don't you just make ten louder and make ten be the top number and make that a little louder?"
- "These go to eleven."

This Is Spinal Tap (1984)

Hemlos

Bing ChatGpt is pretty smart :O

Ian Price

That is incredibly neat - I love the "firestorm" palette and the "blues" on the zoomed in "tentacles" - the blues makes it look like ice/frost is forming.

Nice one :)
I came. I saw. I played.

fuzzy70

Quote from: Ian Price on 2012-Nov-03
That is incredibly neat - I love the "firestorm" palette and the "blues" on the zoomed in "tentacles" - the blues makes it look like ice/frost is forming.

Nice one :)

Thanks Ian, I done it more as a test for playing around with. The FPS was a lot higher than expected which means colour cycled sprites like small logos or highscore tables etc should be possible without a big performance hit.

Lee

Sent from my GT-I5700 using Tapatalk 2

"Why don't you just make ten louder and make ten be the top number and make that a little louder?"
- "These go to eleven."

This Is Spinal Tap (1984)