Also, props to anyone who can add a Simple and Clean precision step to this, so only the pixels that need to be drawn are, rather than just 0 to 360 step 1. With a small ellipse, it's a waste of CPU speed and with a larger ellipse, it's not enough to simply go 1 degree at a time for some.

Code: Select all

`#include once "fbgfx.bi"`

#define pi 3.14159265

#define RadToDeg(__rad__) (__rad__ * (180/Pi))

#define DegToRad(__rad__) (__rad__ * (pi/180))

Declare Sub DrawEllipse( ByVal X as Integer, ByVal Y as Integer, ByVal W as Integer, ByVal H as Integer, ByVal Ang as Integer )

Screenres 640, 480, 32

'' Our settings.

Dim as Integer X = 319, Y = 239, W = 60, H = 60, Ang

Screenlock

Do

'' Get Key Presses

'' Move the Ellipse

If Multikey(FB.SC_LEFT) then X -= 1

If Multikey(FB.SC_RIGHT) then X += 1

If Multikey(FB.SC_UP) then Y -= 1

If Multikey(FB.SC_DOWN) then Y += 1

'' Change Ellipse Width

If Multikey(FB.SC_A) then W -= 1

If Multikey(FB.SC_D) then W += 1

'' Change Ellipse Height

If Multikey(FB.SC_W) then H += 1

If Multikey(FB.SC_S) then H -= 1

'' Increase Our Angle

Ang += 1

'' Check all of our variables and make sure they are valid.

If W < 1 then W = 1

If H < 1 then H = 1

If Ang > 359 then Ang = 0

'' Draw our ellipse.

DrawEllipse( X, Y, W, H, Ang )

'' "GUI" - Uhmm...Just text information ;p

'' Background

Line (0,0)-(250, 40), rgb(10, 20, 80), bf

Line (0,0)-(250, 40), rgb(80, 20, 10), b

Locate 1, 1

'' Text

Draw String (2,2), "Move with Arrow Keys"

Draw String (2,10), "Stretch Ellipse with WASD"

Draw String (2,18), "Pos: " & "(" & str(x) & "," & str(y) & "," & str(Ang) & ")"

Draw String (2,26), "W/H: " & "(" & str(w) & "," & str(h) & ")"

'' Flip our Page

screenunlock

sleep 15, 1

screenlock

cls

Loop until multikey(FB.SC_ESCAPE)

screenunlock

Sub DrawEllipse( ByVal X as Integer, ByVal Y as Integer, ByVal W as Integer, ByVal H as Integer, ByVal Ang as Integer )

'' Ellipse Drawing Positions

Dim as Integer EX, EY

'' Rotated Positions

Dim as Double RX, RY

'' Our Sin/Cos Angles. No reason to calculate it every step.

Dim as Double SinAng = Sin(DegToRad(Ang)), CosAng = Cos(DegToRad(Ang))

'' Custom Ratios. Normally this would be r*cos(ang)

Ex = ( W * Cos(0) )

Ey = ( H * -Sin(0) )

'' Rotate our Ellipse. We're rotating around our own center.

'' Since we didn't include our Drawing Positions, no complex math needed!

'' FYI: This is rotate around ourself math, using our own center as origin!

Rx = ( Ex * CosAng ) - ( Ey * SinAng )

Ry = ( Ey * CosAng ) + ( Ex * SinAng )

'' Draw First Point.

'' We don't include X in the above math so we can have rotation free from

'' Our Ellipse Center

Pset ( X + Rx, Y + Ry ), rgb(255, 255, 255)

'' Loop through our ellipse angles.

For CurAng as Double = 1 to 360

'' Custom Ratios instead of Rad

Ex = ( W * Cos(DegToRad(CurAng)) )

Ey = ( H * -Sin(DegToRad(CurAng)) )

'' Rotate our Ellipse

Rx = ( Ex * CosAng ) - ( Ey * SinAng )

Ry = ( Ey * CosAng ) + ( Ex * SinAng )

'' A version of Line (x,y) - step (x2, y2)

'' Except this is nothing but a step.

Line - ( X + Rx, Y + Ry ), rgb(255, 255, 255)

Next

End Sub

You could add an arc begin/end to this by changing the For loop to go from StartAng to EndAng rather than 1 to 360, with only minor configuration.

Here's the more advanced version:

Code: Select all

`#include once "fbgfx.bi"`

#define pi 3.14159265

#define RadToDeg(__rad__) (__rad__ * (180/Pi))

#define DegToRad(__rad__) (__rad__ * (pi/180))

'' An ellipse object.

'' Store info on the object here, render it.

Type Ellipse

'' Ellipse Drawing Center

X as Integer

Y as Integer

'' Width/Height Ratios

W as Integer

H as Integer

'' Rotation Angle

Rot as Double = 0

'' Start/End Ang

BegAng as Double = 0

EndAng as Double = 360

'' Direction. This is our loop step.

ArcStep as Integer = 1

'' Fill or not? 0 = No Fill. <> 0 = Fill

'' Only fills if BegAng is 0, and EndAng is 360

Fill as Integer = 0

'' Draw the Ellipse.

Declare Sub Draw()

End Type

Screenres 640, 480, 32

'' Our settings.

Dim as Ellipse MyArc

'' Position

MyArc.X = 319

MyArc.Y = 239

'' Size

MyArc.W = 60

MyArc.H = 60

Screenlock

Do

'' Get Key Presses

'' Move the Ellipse

If Multikey(FB.SC_LEFT) then MyArc.BegAng -= 1

If Multikey(FB.SC_RIGHT) then MyArc.BegAng += 1

If Multikey(FB.SC_UP) then MyArc.EndAng -= 1

If Multikey(FB.SC_DOWN) then MyArc.EndAng += 1

'' Change Ellipse Width

If Multikey(FB.SC_A) then MyArc.W -= 1

If Multikey(FB.SC_D) then MyArc.W += 1

'' Change Ellipse Height

If Multikey(FB.SC_W) then MyArc.H += 1

If Multikey(FB.SC_S) then MyArc.H -= 1

'' Increase Our Angle

MyArc.Rot += 1

'' Check all of our variables and make sure they are valid.

If MyArc.W < 1 then MyArc.W = 1

If MyArc.H < 1 then MyArc.H = 1

If MyArc.Rot > 359 then MyArc.Rot = 0

If MyArc.BegAng < 0 then MyArc.BegAng += 360

If MyArc.BegAng > 360 then MyArc.BegAng -= 360

If MyArc.EndAng < 0 then MyArc.EndAng += 360

If MyArc.EndAng > 360 then MyArc.EndAng -= 360

'' Reverse Drawing Direction if our End Angle's less than our start angle.

If MyArc.EndAng < MyArc.BegAng then

MyArc.ArcStep = -1

Else

MyArc.ArcStep = 1

End If

'' Fill if we have a full Ellipse.

If ( MyArc.BegAng = 0 ) then

If ( MyArc.EndAng = 360 ) then

MyArc.Fill = 1

Else

MyArc.Fill = 0

End If

Else

MyArc.Fill = 0

End If

'' Draw our ellipse.

MyArc.Draw()

'' "GUI" - Uhmm...Just text information ;p

'' Background

Line (0,0)-(250, 48), rgb(10, 20, 80), bf

Line (0,0)-(250, 48), rgb(80, 20, 10), b

Locate 1, 1

'' Text

Draw String (2,2), "Change Arc With Arrow Keys"

Draw String (2,10), "Stretch Ellipse with WASD"

Draw String (2,18), "Pos: " & "(" & str(MyArc.x) & "," & str(MyArc.y) & "," & str(MyArc.Rot) & ")"

Draw String (2,26), "W/H: " & "(" & str(MyArc.w) & "," & str(MyArc.h) & ")"

Draw String (2,34), "Start/End Ang: " & "(" & str(MyArc.BegAng) & "," & str(MyArc.EndAng) & ")"

'' Flip our Page

screenunlock

sleep 15, 1

screenlock

cls

Loop until multikey(FB.SC_ESCAPE)

screenunlock

Sub Ellipse.Draw()

'' Ellipse Drawing Positions

Dim as Integer EX, EY

'' Rotated Positions

Dim as Double RX, RY

'' Our Sin/Cos Angles. No reason to calculate it every step.

Dim as Double SinAng = Sin(DegToRad(This.Rot)), CosAng = Cos(DegToRad(This.Rot))

'' Custom Ratios. Normally this would be r*cos(ang)

Ex = ( This.W * Cos(DegToRad(This.BegAng)) )

Ey = ( This.H * -Sin(DegToRad(This.BegAng)) )

'' Rotate our Ellipse. We're rotating around our own center.

'' Since we didn't include our Drawing Positions, no complex math needed!

'' FYI: This is rotate around ourself math, using our own center as origin!

Rx = ( Ex * CosAng ) - ( Ey * SinAng )

Ry = ( Ey * CosAng ) + ( Ex * SinAng )

'' Draw First Point.

'' We don't include X in the above math so we can have rotation free from

'' Our Ellipse Center

Pset ( This.X + Rx, This.Y + Ry ), rgb(255, 255, 255)

'' Loop through our ellipse angles.

For CurAng as Double = This.BegAng + 1 to This.EndAng step This.ArcStep

'' Custom Ratios instead of Rad

Ex = ( This.W * Cos(DegToRad(CurAng)) )

Ey = ( This.H * -Sin(DegToRad(CurAng)) )

'' Rotate our Ellipse

Rx = ( Ex * CosAng ) - ( Ey * SinAng )

Ry = ( Ey * CosAng ) + ( Ex * SinAng )

'' A version of Line (x,y) - step (x2, y2)

'' Except this is nothing but a step.

Line - ( This.X + Rx, This.Y + Ry ), rgb(255, 255, 255)

Next

'' Fill our ellipse if we have chosen to do so.

If This.Fill <> 0 then

Paint (This.X, This.Y), rgb(255, 255, 255), rgb(255, 255, 255)

End If

End Sub

And finally, here's a version useful for enemy paths, if you want to curve to direct from the player (center, edge of ellipse) to the target. Replace the "Advanced" Ellipse.Draw Sub with This One:

Code: Select all

`Sub Ellipse.Draw()`

'' Ellipse Drawing Positions

Dim As Integer EX, EY

'' Rotated Positions

Dim As Double RX, RY

'' Origin Position

Dim as Integer OX, OY

'' Our Sin/Cos Angles. No reason to calculate it every step.

Dim As Double SinAng = Sin(DegToRad(This.Rot)), CosAng = Cos(DegToRad(This.Rot))

'' Set an origin point for all of the ellipse drawing.

Ox = ( This.W * Cos(DegToRad(This.BegAng)) )

Oy = ( This.H * -Sin(DegToRad(This.BegAng)) )

'' Custom Ratios. Normally this would be r*cos(ang)

Ex = ( This.W * Cos(DegToRad(This.BegAng)) ) + OX

Ey = ( This.H * -Sin(DegToRad(This.BegAng)) ) + OY

'' Rotate our Ellipse. We're rotating around our own center.

'' Since we didn't include our Drawing Positions, no complex math needed!

'' FYI: This is rotate around ourself math, using our own center as origin!

Rx = ( Ex * CosAng ) - ( Ey * SinAng )

Ry = ( Ey * CosAng ) + ( Ex * SinAng )

'' Draw First Point.

'' We don't include X in the above math so we can have rotation free from

'' Our Ellipse Center

Pset ( This.X + Rx, This.Y + Ry ), rgb(255, 255, 255)

'' Loop through our ellipse angles.

For CurAng As Double = This.BegAng + 1 To This.EndAng Step This.ArcStep

'' Custom Ratios instead of Rad

Ex = ( This.W * Cos(DegToRad(CurAng)) ) + OX

Ey = ( This.H * -Sin(DegToRad(CurAng)) ) + OY

'' Rotate our Ellipse

Rx = ( Ex * CosAng ) - ( Ey * SinAng )

Ry = ( Ey * CosAng ) + ( Ex * SinAng )

'' A version of Line (x,y) - step (x2, y2)

'' Except this is nothing but a step.

Line - ( This.X + Rx, This.Y + Ry ), rgb(255, 255, 255)

Next

'' Fill our ellipse if we have chosen to do so.

If This.Fill <> 0 Then

Paint (This.X + Rx / 2, This.Y + Ry / 2), rgb(255, 255, 255), rgb(255, 255, 255)

End If

End Sub