Starcontrol like melee AI aiming

Post your FreeBASIC tips and tricks here. Please don’t post your code without including an explanation.
lillo
Site Admin
Posts: 447
Joined: May 27, 2005 8:00
Location: Rome, Italy
Contact:

Starcontrol like melee AI aiming

Postby lillo » Nov 08, 2005 14:58

I'm on the last month of work on my master thesis (I graduate on mid-december!), and I've tried to stay out of anything that is not related to the thesis code-wise... but today, don't ask me why, I thought about the Starcontrol II melee AI and wondered how the smart aiming was done... You know, in that game the enemy ship did not fire a bullet directed towards the instantaneous player ship position, but rather it predicted where the player was going to be at his current velocity and direction, aiming there instead, also considering the bullet speed.
I couldn't resist to sit down with paper and pencil to analyze the problem from a mathematical point of view (my engineer soul calling), and when I solved it I coded the small demo attached here:

Code: Select all

option explicit

#include "fbgfx.bi"

#define SCR_W         640
#define SCR_H         480
#define SCR_B         16

const BULLET_SPEED as single = 3.7
const PLAYER_SPEED as single = 2.4
const PLAYER_ACCEL as single = 0.15

type OBJECT
   active as integer
   x as single
   y as single
   vx as single
   vy as single
end type

declare function get_fire_angle(byval src as OBJECT ptr, byval dest as OBJECT ptr, byval speed as single) as double
declare sub rest(byval t as single)

'':::::
function get_fire_angle(byval src as OBJECT ptr, byval dest as OBJECT ptr, byval speed as single) as double
   dim as single t, dx, dy, delta, cosine, sine

   speed *= speed
   dx = dest->x - src->x
   dy = dest->y - src->y

   delta = (speed * ((dx * dx) + (dy * dy))) - (((dest->vx * dy) - (dest->vy * dx)) * ((dest->vx * dy) - (dest->vy * dx)))
   t = -(dest->vx * dx) - (dest->vy * dy) - sqr(delta)
   t /= ((dest->vx * dest->vx) + (dest->vy * dest->vy) - speed)
   cosine = dx + (dest->vx * t)
   sine   = dy + (dest->vy * t)
   function = atan2(-sine, cosine)
end function

'':::::
sub rest(byval t as single)
   dim as single start

   start = timer
   while timer < start + t: wend
end sub


   '':::::
   dim as OBJECT turret, bullet, player
   dim as integer page
   dim as single angle

   screenres SCR_W, SCR_H, SCR_B, 2

   randomize(timer)
   player.x = rnd*SCR_W
   player.y = rnd*SCR_H

   turret.x = SCR_W / 2
   turret.y = SCR_H / 2

   do
      screenset page, page xor 1
      page xor= 1

      cls
      circle(player.x, player.y), 4, rgb(255, 255, 255),,, 1, F
      circle(turret.x, turret.y), 4, rgb(255, 128, 0),,, 1, F
      if (bullet.active) then
         circle(bullet.x, bullet.y), 4, rgb(255, 0, 0),,, 1, F
         bullet.x += bullet.vx
         bullet.y += bullet.vy
      end if

      if (multikey(SC_LEFT) and (player.vx > -PLAYER_SPEED)) then player.vx -= PLAYER_ACCEL
      if (multikey(SC_RIGHT) and (player.vx < PLAYER_SPEED)) then player.vx += PLAYER_ACCEL
      if (multikey(SC_UP)   and (player.vy > -PLAYER_SPEED)) then player.vy -= PLAYER_ACCEL
      if (multikey(SC_DOWN)  and (player.vy < PLAYER_SPEED)) then player.vy += PLAYER_ACCEL
      player.x += player.vx
      player.y += player.vy
      rest 0.02

      angle = get_fire_angle(@turret, @player, BULLET_SPEED)
      line(turret.x, turret.y)-(turret.x + (cos(angle) * SCR_W), turret.y - (sin(angle) * SCR_W)), rgb(128, 0, 0)
      if (multikey(SC_SPACE)) then
         bullet.x = turret.x
         bullet.y = turret.y
         bullet.vx = cos(angle) * BULLET_SPEED
         bullet.vy = -sin(angle) * BULLET_SPEED
         bullet.active = 1
      end if
   loop while not multikey(SC_ESCAPE)

Use the arrow keys to accelerate the "ship" in a given direction, and hit space to let the "turret" at the center of the screen to fire at you. The red line is the current aim of the turret, given your position/velocity and the bullet speed.
The get_fire_angle() function always succeeds as long as the bullet speed is always higher than the player speed (it would not make sense anyway in this case as if the bullet is slower than the player it can never catch him)
Hope you can make good use of this code :)
Now I'm going back to my thesis...

EDIT: optimized and cleaned up code a bit
Adigun A. Polack
Posts: 230
Joined: May 27, 2005 15:14
Contact:

Great piece of code there, lillo!! ^-^=b

Postby Adigun A. Polack » Nov 08, 2005 18:40

I gotta tell ‘ya, that code of yours just placed in this thread sure knows what it is doing, in that the firing of the turret towards the white ship is actually a *lot* smarter than it looks. EXCELLENT job on it!!! :D

Look, I sure hope you ace your master thesis successfully and graduate indeed, my man lillo! And welcome back to the official FB forums, by the way!! ^_-=b !
rdc
Posts: 1713
Joined: May 27, 2005 17:22
Location: Texas, USA
Contact:

Postby rdc » Nov 08, 2005 19:30

That could come in very handy. Thanks for the example. Good luck on the thesis!
SotSvart
Posts: 262
Joined: May 27, 2005 9:03
Location: Norway
Contact:

Postby SotSvart » Nov 09, 2005 2:34

Exellent pice of code! This could come in handy indeed. Good luck with your master thesis.
jupiter3888
Posts: 103
Joined: Jun 30, 2005 3:54
Location: adelaide, australia
Contact:

Postby jupiter3888 » Nov 09, 2005 9:54

holy cow! thats excellent work there, im impressed. good luck on your thesis.
dafhi
Posts: 1258
Joined: Jun 04, 2005 9:51

Postby dafhi » Nov 10, 2005 3:11

ship control feels great! the bullet looks like it follows a curved path when you're watching your ship

Return to “Tips and Tricks”

Who is online

Users browsing this forum: Majestic-12 [Bot], MSN [Bot] and 1 guest