' 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 const numofCPUobjects = 20 ' Custom data types for our misc. objects in the program (projectiles, ' cpu controlled objects, etc.). TYPE ObjType X AS SINGLE ' Used to flag object's x position. Y AS SINGLE ' Used to flag object's y position. AngleDeg AS INTEGER ' Used to flag object's angle in degrees. AngleRad AS SINGLE ' Used to flag object's angle in radians. Speed AS SINGLE ' Used to flag object's speed. RotationSpeed AS SINGLE ' Used to flag object's rotation speed Active AS INTEGER ' Used to flag object's status ActiveTime AS INTEGER ' Use to expire object's activity (once we activate it). Typ AS INTEGER ' Used to flag type of the object (if we want to ' have more kinds of the same object -> different ' ships, projectiles, etc.). END TYPE ' 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 ASmode AS INTEGER ' artificial smarts control (on/off) DIM SHARED CPUobject(numofCPUobjects) AS ObjType ' Our CPU controlled objects ' 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 ASMode = TRUE ' Get the random seed from the seconds past midnight (the ' best way to get random numbers). RANDOMIZE TIMER ' We loop through our cpu controlled object and initiate ' their variables. FOR initCPUobj AS INTEGER = 1 TO numofCPUobjects CPUobject(initCPUobj).X = INT(RND * 600) + 20 ' Randomize cpu object's position from 20 to 620 CPUobject(initCPUobj).Y = INT(RND * 440) + 20 ' Randomize cpu object's position from 20 to 460 CPUobject(initCPUobj).AngleDeg = INT(RND * 360) + 1 ' Randomize cpu object's angle from 1 to 360 CPUobject(initCPUobj).AngleRad = (CPUobject(initCPUobj).AngleDeg*PI)/180 CPUobject(initCPUobj).RotationSpeed = INT(RND * 2) + 2 ' Randomize cpu object's rotation speed from 2 to 3 CPUobject(initCPUobj).Speed = INT(RND * 3) + 1 ' Randomize cpu object's rotation speed from 1 to 3 CPUobject(initCPUobj).Active = TRUE ' All object active (alive) by default. NEXT initCPUobj ' 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 CLS ' Clear the screen FOR countCPUobj AS INTEGER = 1 TO numofCPUobjects ' Loop through all the objects ' If ASMode is true apply the artificial smart code on the CPU controlled object IF ASMode = TRUE THEN ' The following lines calculate the angle of direction ' from the current controlled object toward the main object. resultanglerad = ATAN2((-1)*(mainy-CPUobject(countCPUobj).Y),(mainx-CPUobject(countCPUobj).X)) 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 the CPU controled object's angle is larger than the ' result angle (angle between the CPU object and player's object)... IF CPUobject(countCPUobj).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-CPUobject(countCPUobj).AngleDeg+resultangledeg) >= (CPUobject(countCPUobj).AngleDeg-resultangledeg) THEN CPUobject(countCPUobj).AngleDeg = CPUobject(countCPUobj).AngleDeg - CPUobject(countCPUobj).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-CPUobject(countCPUobj).AngleDeg+resultangledeg) < (CPUobject(countCPUobj).AngleDeg-resultangledeg) THEN CPUobject(countCPUobj).AngleDeg = CPUobject(countCPUobj).AngleDeg + CPUobject(countCPUobj).RotationSpeed END IF ' Same as above but for situation when CPU object's angle is ' less that the result angle. IF CPUobject(countCPUobj).AngleDeg < resultangledeg THEN IF (360-resultangledeg+CPUobject(countCPUobj).AngleDeg) >= (resultangledeg-CPUobject(countCPUobj).AngleDeg) THEN CPUobject(countCPUobj).AngleDeg = CPUobject(countCPUobj).AngleDeg + CPUobject(countCPUobj).RotationSpeed IF (360-resultangledeg+CPUobject(countCPUobj).AngleDeg) < (resultangledeg-CPUobject(countCPUobj).AngleDeg) THEN CPUobject(countCPUobj).AngleDeg = CPUobject(countCPUobj).AngleDeg - CPUobject(countCPUobj).RotationSpeed END IF ' The following lines keep the current CPU object's angle within ' 0 to 360 degrees area. IF CPUobject(countCPUobj).AngleDeg<0 THEN CPUobject(countCPUobj).AngleDeg=CPUobject(countCPUobj).AngleDeg+360 IF CPUobject(countCPUobj).AngleDeg>359 THEN CPUobject(countCPUobj).AngleDeg=CPUobject(countCPUobj).AngleDeg-360 ' Convert the CPU object's angle from degrees to radians. CPUobject(countCPUobj).AngleRad = (CPUobject(countCPUobj).AngleDeg*PI)/180 ' Move the current 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. CPUobject(countCPUobj).X = CPUobject(countCPUobj).X + sin(CPUobject(countCPUobj).AngleRad)*CPUobject(countCPUobj).Speed CPUobject(countCPUobj).Y = CPUobject(countCPUobj).Y - cos(CPUobject(countCPUobj).AngleRad)*CPUobject(countCPUobj).Speed END IF ' We draw the current computer controlled object if active (alive). IF CPUobject(countCPUobj).Active = TRUE THEN LINE (CPUobject(countCPUobj).X, CPUobject(countCPUobj).Y)-(CPUobject(countCPUobj).X+sin(CPUobject(countCPUobj).AngleRad)*20,CPUobject(countCPUobj).Y-cos(CPUobject(countCPUobj).AngleRad)*20), RGB(2,117, 250) CIRCLE (CPUobject(countCPUobj).X, CPUobject(countCPUobj).Y), 3, RGB(2,117, 250) END IF NEXT countCPUobj ' 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) 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.