Starcontrol like melee AI aiming

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

Starcontrol like melee AI aiming

Post by lillo »

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: 232
Joined: May 27, 2005 15:14
Contact:

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

Post by Adigun A. Polack »

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: 1741
Joined: May 27, 2005 17:22
Location: Texas, USA
Contact:

Post by rdc »

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:

Post by SotSvart »

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:

Post by jupiter3888 »

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

Post by dafhi »

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