CircleFill - SMcNeill - 04-20-2022
Code: (Select All) SUB CircleFill (CX AS LONG, CY AS LONG, R AS LONG, C AS LONG)
DIM Radius AS LONG, RadiusError AS LONG
DIM X AS LONG, Y AS LONG
Radius = ABS(R)
RadiusError = -Radius
X = Radius
Y = 0
IF Radius = 0 THEN PSET (CX, CY), C: EXIT SUB
' Draw the middle span here so we don't draw it twice in the main loop,
' which would be a problem with blending turned on.
LINE (CX - X, CY)-(CX + X, CY), C, BF
WHILE X > Y
RadiusError = RadiusError + Y * 2 + 1
IF RadiusError >= 0 THEN
IF X <> Y + 1 THEN
LINE (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
LINE (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
END IF
X = X - 1
RadiusError = RadiusError - X * 2
END IF
Y = Y + 1
LINE (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
LINE (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
WEND
END SUB
RE: CircleFill - James D Jarvis - 04-23-2022
I had fun with this yesterday. Made variant sub called NoisyCircle.
Code: (Select All) sc& = _NewImage(800, 500, 256)
Screen sc&
'this would probably look better if you fill the screen with it
Randomize Timer
kk = Int(Rnd * 255)
CircleFill 250, 250, 10, kk
For z = 1 To 10
_Limit 10
Next z
Locate 1, 1: Print "Let's take a look at that star"
For z = 10 To 100
_Limit 60
CircleFill 250, 250, z, kk
Next z
reps = Int(Rnd * 600) + 90
For reps = 1 To reps
_Limit 60
If reps < reps / 2 Then NF = NF / 10 + 5
If reps > reps / 2 - 1 Then NF = 35 - kk / 10
NoisyCircle 250, 250, 100, kk, Int(Rnd * NF)
_Display
Next reps
kk = 0
For boom = 1 To 100
_Limit 60
'this part bogs down a bit , proabbaly should have swirtched to random points instead of
'still using the noisycircle but it helps to see how things work
NoisyCircle 250, 250, 100 + boom * 5, kk, 100 - boom
If boom > 50 Then
NoisyCircle 250, 250, (boom - 50) * (boom - 50), kk, 100 - boom
End If
_Display
Next boom
Sub CircleFill (CX As Long, CY As Long, R As Long, C As Long)
Dim Radius As Long, RadiusError As Long
Dim X As Long, Y As Long
Radius = Abs(R)
RadiusError = -Radius
X = Radius
Y = 0
If Radius = 0 Then PSet (CX, CY), C: Exit Sub
' Draw the middle span here so we don't draw it twice in the main loop,
' which would be a problem with blending turned on.
Line (CX - X, CY)-(CX + X, CY), C, BF
While X > Y
RadiusError = RadiusError + Y * 2 + 1
If RadiusError >= 0 Then
If X <> Y + 1 Then
Line (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
Line (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
End If
X = X - 1
RadiusError = RadiusError - X * 2
End If
Y = Y + 1
Line (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
Line (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
Wend
End Sub
Sub NoisyCircle (CX As Long, CY As Long, R As Long, C As Long, CHNC)
'CX and CY are ti plot of the circle center R is the radius, c is the primary color, CHNC is the chance for noise to vary from from primary color
Dim Radius As Long, RadiusError As Long
Dim X As Long, Y As Long
Radius = Abs(R)
RadiusError = -Radius
X = Radius
Y = 0
If Radius = 0 Then PSet (CX, CY), C: Exit Sub
'checking to see if we should use the base color of the circle or slap down some random noise
For tx = CX - X To CX + X
chance = Rnd * 100
If chance < CHNC Then
dotc = Int(Rnd * 256)
Else
dotc = C
End If
PSet (tx, CY), dotc 'drawing each point in the line because color can change from pixel to pixel
Next tx
While X > Y
RadiusError = RadiusError + Y * 2 + 1
If RadiusError >= 0 Then
If X <> Y + 1 Then
For tx = CX - Y To CX + Y
chance = Rnd * 100
If chance < CHNC Then
dotc = Int(Rnd * 256)
Else
dotc = C
End If
PSet (tx, CY - X), dotc
Next tx
For tx = CX - Y To CX + Y
chance = Rnd * 100
If chance < CHNC Then
dotc = Int(Rnd * 256)
Else
dotc = C
End If
PSet (tx, CY + X), dotc
Next tx
End If
X = X - 1
RadiusError = RadiusError - X * 2
End If
Y = Y + 1
For tx = CX - X To CX + X
chance = Rnd * 100
If chance < CHNC Then
dotc = Int(Rnd * 256)
Else
dotc = C
End If
PSet (tx, CY - Y), dotc
Next tx
For tx = CX - X To CX + X
chance = Rnd * 100
If chance < CHNC Then
dotc = Int(Rnd * 256)
Else
dotc = C
End If
PSet (tx, CY + Y), dotc
Next tx
Wend
End Sub
RE: CircleFill - SMcNeill - 11-15-2022
And, let me share an example here, for WHY one might want to use hardware images.
Code: (Select All) 'mode 33 copyimage test
SCREEN _NEWIMAGE(800, 600, 32)
RANDOMIZE TIMER
FOR i = 1 TO 100
LINE (RND * 800, RND * 600)-(RND * 800, RND * 600), _RGB32(RND * 256, RND * 256, RND * 256), BF
CircleFill RND * 800, RND * 600, RND * 200, _RGB32(RND * 256, RND * 256, RND * 256)
LINE (100, 100)-(200, 200), -1, BF 'white box to keep things simple
NEXT
PRINT "Let's take a moment and showcase WHY we might want to use hardware images."
PRINT
PRINT "First, let's start with an simple image, and let's copy it to hardware."
h2& = _COPYIMAGE(0)
h2hw& = _COPYIMAGE(0, 33) '<------ make a copy of the screen and make it a hardware copy
changedirection = -1
x = 400: y = 300
xchange = -1: ychange = 1
SLEEP
_DELAY .25
_KEYCLEAR
t# = TIMER
DO
fps = fps + 1
CLS
IF changedirection THEN xchange = -1 * xchange: ychange = -1 * ychange: changedirection = 0
x = x + xchange: y = y + ychange
IF x < 0 OR x > _WIDTH OR y < 0 OR y > _HEIGHT THEN changedirection = -1
_PUTIMAGE (x, y)-STEP(200, 200), h2& 'put the software image on the screen
IF TIMER > t# + 1 THEN out1$ = STR$(fps): t# = TIMER: fps = 0
PRINT "FPS:"; out1$; " with use of _PUTIMAGE with software screens and software "
_DISPLAY 'hardware images require a DISPLAY statement to render
LOOP UNTIL _KEYHIT
_DELAY .25
_KEYCLEAR
t# = TIMER: fps = 0
DO
fps = fps + 1
CLS
IF changedirection THEN xchange = -1 * xchange: ychange = -1 * ychange: changedirection = 0
x = x + xchange: y = y + ychange
IF x < 0 OR x > _WIDTH OR y < 0 OR y > _HEIGHT THEN changedirection = -1
_PUTIMAGE (x, y)-STEP(200, 200), h2hw& 'put the hardware image over the screen (they're separate layers, so you can overlap them)
IF TIMER > t# + 1 THEN out2$ = STR$(fps): t# = TIMER: fps = 0
PRINT "FPS:"; out1$; " with use of _PUTIMAGE with software screens and software images"
PRINT "FPS:"; out2$; " with use of _PUTIMAGE with software screens and hardware images"
_DISPLAY 'hardware images require a DISPLAY statement to render
LOOP UNTIL _KEYHIT
_DELAY .25
_KEYCLEAR
_DISPLAYORDER _HARDWARE 'notice I'm not using a software screen at all now. The PRINT Statements below will NOT show.
t# = TIMER: fps = 0
DO
fps = fps + 1
CLS
IF changedirection THEN xchange = -1 * xchange: ychange = -1 * ychange: changedirection = 0
x = x + xchange: y = y + ychange
IF x < 0 OR x > _WIDTH OR y < 0 OR y > _HEIGHT THEN changedirection = -1
_PUTIMAGE (x, y)-STEP(200, 200), h2hw& 'put the hardware image over the screen (they're separate layers, so you can overlap them)
IF TIMER > t# + 1 THEN out3$ = STR$(fps): t# = TIMER: fps = 0
PRINT "FPS:"; out1$; " with use of _PUTIMAGE with software screens and software images"
PRINT "FPS:"; out2$; " with use of _PUTIMAGE with software screens and hardware images"
_DISPLAY 'hardware images require a DISPLAY statement to render
LOOP UNTIL _KEYHIT
_DISPLAYORDER _SOFTWARE , _HARDWARE 'lets put the software screens back into our display
CLS
PRINT "FPS:"; out1$; " with use of _PUTIMAGE with software screens and software images"
PRINT "FPS:"; out2$; " with use of _PUTIMAGE with software screens and hardware images"
PRINT "FPS:"; out3$; " with use of _PUTIMAGE with hardware ONLY images and screens"
SUB CircleFill (CX AS LONG, CY AS LONG, R AS LONG, C AS LONG)
DIM Radius AS LONG, RadiusError AS LONG
DIM X AS LONG, Y AS LONG
Radius = ABS(R)
RadiusError = -Radius
X = Radius
Y = 0
IF Radius = 0 THEN PSET (CX, CY), C: EXIT SUB
' Draw the middle span here so we don't draw it twice in the main loop,
' which would be a problem with blending turned on.
LINE (CX - X, CY)-(CX + X, CY), C, BF
WHILE X > Y
RadiusError = RadiusError + Y * 2 + 1
IF RadiusError >= 0 THEN
IF X <> Y + 1 THEN
LINE (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
LINE (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
END IF
X = X - 1
RadiusError = RadiusError - X * 2
END IF
Y = Y + 1
LINE (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
LINE (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
WEND
END SUB
Now this is about as simple as a demo as I can imagine writing to showcase what needs to be shown here. All we're doing in this example is drawing a screen of simple lines and circles, and then we're saving that screen as an image. (Two images actually -- one software, one hardware, for comparison.)
We then throw that image onto a clean screen and move it in an unlimited loop, and count how many times it moves in a second. Once we know our FPS, the user can hit any key they want and see the *exact* same code and process, and how fast it'd run if we swapped in a hardware image instead of a software image. Once happy with seeing those results, the user can then hit any key they want and see that *exact* same code run with ONLY hardware support, and see what the difference is in performance.
I think the results, printed as a nice summery on the last page, speak for themselves as to why someone might want to start using hardware images over software.
|