' We include FreeBASIC's built-in library and allow
' the usage of its additional constants and functions
' with Using FB.
#include "fbgfx.bi"
Using FB

' We set some needed constants.
const fpslimit = 60
const FALSE = 0
const TRUE = 1
const PI = 3.141593

' We declare the needed variables.
DIM SHARED workpage AS INTEGER

' The following 3 variables are used for
' frames per second control.
DIM SHARED st AS DOUBLE
DIM SHARED frameintvl As Double = 1.0/fpslimit
DIM SHARED sleepintvl As Integer

DIM SHARED angledeg AS INTEGER  ' Main object's angle in degrees
DIM SHARED anglerad AS SINGLE   ' Main object's angle in radians
DIM SHARED mainx AS SINGLE      ' Main object's x pos
DIM SHARED mainy AS SINGLE      ' Main object's y pos
DIM SHARED mainspeed AS SINGLE      ' Main object's speed
DIM SHARED main_rotationspeed AS SINGLE ' Main object's rotation speed
DIM SHARED resultangledeg AS INTEGER ' Angle between the cpu cont. object and main object in degrees
DIM SHARED resultanglerad AS SINGLE  ' Angle between the cpu cont. object and main object in radians
DIM SHARED CPUobjectx AS SINGLE    ' CPU controlled object's x pos
DIM SHARED CPUobjecty AS SINGLE    ' CPU controlled object's y pos
DIM SHARED CPUobj_angledeg AS INTEGER ' CPU controlled object's angle in degrees
DIM SHARED CPUobj_anglerad AS SINGLE  ' CPU controlled object's angle in radians
DIM SHARED CPUobject_rotationspeed AS SINGLE ' Rotation speed of the CPU controlled object
DIM SHARED CPUobjectspeed AS SINGLE ' CPU controlled object's speed
DIM SHARED ASmode AS INTEGER ' artificial smarts control (on/off)

' We set our screen to 640 width, 480 height, 32 color bit-depth,
' 2 work pages and full screen.
SCREENRES 640, 480, 32, 2, GFX_FULLSCREEN

' We set the initial values for the main object's
' and CPU controlled object's positions/angles/speeds.
mainx = 320
mainy = 220
mainspeed = 4
main_rotationspeed = 3
angledeg = 0
CPUobjectx = 200
CPUobjecty = 200
CPUobj_angledeg = 20
CPUobj_anglerad = (CPUobj_angledeg*PI)/180
CPUobject_rotationspeed = 3
CPUobjectspeed = 2
ASMode = TRUE

' Your average do loop.
DO
    
st = Timer ' Record the current time into st variable
           ' (used to limit FPS; no related to the
           ' topic of the example program).
  
screenlock ' Lock our screen (nothing will be
           ' displayed until we unlock the screen).
screenset workpage, workpage xor 1 ' Swap work pages.

' The control keys for the main (player's) object.
IF MULTIKEY(SC_LEFT) THEN angledeg = angledeg - main_rotationspeed
IF MULTIKEY(SC_RIGHT) THEN angledeg = angledeg + main_rotationspeed
' The following lines keep the angle between
' 0 and 360.
IF angledeg<0 THEN angledeg=angledeg+360
IF angledeg>359 THEN angledeg=angledeg-360
anglerad = (angledeg*PI)/180 ' Convert the angle from degrees to radians
IF MULTIKEY(SC_UP) THEN 
mainx = mainx + sin(anglerad)*mainspeed
mainy = mainy - cos(anglerad)*mainspeed
END IF

' For turning AS on/off.
IF MULTIKEY(SC_1) THEN ASMode = TRUE
IF MULTIKEY(SC_2) THEN ASMode = FALSE

' The following lines calculate the angle of direction
' from the controlled object toward the main object.
resultanglerad = ATAN2((-1)*(mainy-CPUobjecty),(mainx-CPUobjectx))
resultanglerad = PI/2 - resultanglerad
IF resultanglerad < 0 THEN resultanglerad = resultanglerad + 2*PI 

' The following line converts the result angle between the
' two objects from radians to degrees.
resultangledeg = (resultanglerad*180)/PI

' If ASMode is true apply in the the CPU controlled object
IF ASMode = TRUE THEN
    ' If the CPU controled object's angle is larger than the
    ' result angle (angle between the CPU object and player's object)...
    IF CPUobj_angledeg > resultangledeg THEN
        ' If the difference between the current angle of the
        ' CPU controlled object and the result angle going
        ' counter-clockwise is less than this difference
        ' clockwise, rotate the CPU object counter-clockwise
        IF (360-CPUobj_angledeg+resultangledeg) >= (CPUobj_angledeg-resultangledeg) THEN CPUobj_angledeg = CPUobj_angledeg - CPUobject_rotationspeed
        ' If the difference between the current angle of the
        ' CPU controlled object and the result angle going
        ' clockwise is less that this difference counter-clockwise,
        ' rotate the CPU object clockwise
        IF (360-CPUobj_angledeg+resultangledeg) < (CPUobj_angledeg-resultangledeg) THEN CPUobj_angledeg = CPUobj_angledeg + CPUobject_rotationspeed
    END IF
    ' Same as above but for situation when CPU object's angle is
    ' less that the result angle.
    IF CPUobj_angledeg < resultangledeg THEN
        IF (360-resultangledeg+CPUobj_angledeg) >= (resultangledeg-CPUobj_angledeg) THEN CPUobj_angledeg = CPUobj_angledeg + CPUobject_rotationspeed
        IF (360-resultangledeg+CPUobj_angledeg) < (resultangledeg-CPUobj_angledeg) THEN CPUobj_angledeg = CPUobj_angledeg - CPUobject_rotationspeed
    END IF
    ' The following lines keep the CPU object's angle within
    ' 0 to 360 degrees area.
    IF CPUobj_angledeg<0 THEN CPUobj_angledeg=CPUobj_angledeg+360
    IF CPUobj_angledeg>359 THEN CPUobj_angledeg=CPUobj_angledeg-360
    ' Convert the CPU object's angle from degrees to radians.
    CPUobj_anglerad = (CPUobj_angledeg*PI)/180
    ' Move the CPU object according to angle and speed
    ' (note how SIN and COS functions are used).
    ' Since positive y axis goes down in FB, we need to reduce
    ' the y position of the object by the COS function and not add 
    ' it as in normal Cartesian coordinate system.
    CPUobjectx = CPUobjectx + sin(CPUobj_anglerad)*CPUobjectspeed
    CPUobjecty = CPUobjecty - cos(CPUobj_anglerad)*CPUobjectspeed
END IF

CLS ' Clear the screen

' We draw an help Cartesian coordinate system.
LINE (50, 80)-(110,80), RGB(255,255,255)
LINE (80, 50)-(80,110), RGB(255,255,255)
Draw String (77,40), "0", RGB(0, 176, 214)
Draw String (69,114), "180", RGB(0, 176, 214)
Draw String (114,76), "90", RGB(0, 176, 214)
Draw String (23,76), "270", RGB(0, 176, 214)

Draw String (12,200), "1 - AI On", RGB(0, 176, 214)
Draw String (12,210), "2 - AI Off", RGB(0, 176, 214)

' We display some useful textual information.
Draw String (320,10), "Main object's angle:"+STR$(angledeg), RGB(2,117, 190)
Draw String (320,20), "Computer controlled object's angle:"+STR$(CPUobj_angledeg), RGB(2,117, 190)
Draw String (320,30), "Angle between objects:"+STR$(resultangledeg), RGB(2,117, 190)

' We draw our objects (represented with small circles) and
' lines that emulate these objects' directions.
LINE (CPUobjectx, CPUobjecty)-(CPUobjectx+sin(CPUobj_anglerad)*20,CPUobjecty-cos(CPUobj_anglerad)*20), RGB(2,117, 250)
CIRCLE (CPUobjectx, CPUobjecty), 3, RGB(2,117, 250)
LINE (mainx, mainy)-(mainx+sin(anglerad)*20,mainy-cos(anglerad)*20), RGB(200, 0, 0)
CIRCLE (mainx, mainy), 3, RGB(200, 0, 0)

workpage xor = 1 ' Swap work pages.
screenunlock ' Unlock the page to display what has been drawn.

' Keep the FPS value within fpslimit (set above).
sleepintvl = Cint((st + frameintvl - Timer)*1000.0)
If sleepintvl>1 Then
  Sleep sleepintvl
end if

LOOP UNTIL MULTIKEY(SC_ESCAPE) ' Do loop until ESC is pressed.