[bb] 2D turret firing algorhytms by Matt Merkulov [ 1+ years ago ]

Started by BlitzBot, June 29, 2017, 00:28:42

Previous topic - Next topic

BlitzBot

Title : 2D turret firing algorhytms
Author : Matt Merkulov
Posted : 1+ years ago

Description : From article:<a href="http://blitzetcetera.org/index.php/СÑ,рельба_на_опережение" target="_blank"> Forestalling</a> (rus)

Code :
Code (blitzbasic) Select
'Turret firing algorhytms including forestalling and self-training AI by Matt Merkulov

Graphics3D 800, 600

PositionEntity CreateCamera(), 0, 0, -20
RotateEntity CreateLight(), 45, 45, 45

; Type for a turret - coordinates, angle, mode of shooting, handles for 3D - objects, variables for AI
Type turret
Field x#, y#, Mode, head, barrel, ang#, dir#, dx#, dy#
End Type

; Type for a shot - coordinates, increments, handle of 3D - object,
; Distance from a turret, auxiliary variables for AI
Type shot
Field x#, y#, dx#, dy#, h, r#, tx#, ty#, dir#, t.turret
End Type

Const aimax = 200, aistp# = .2
Dim aiang# (aimax)

SetFont LoadFont("arial", 14)
SetBuffer BackBuffer()

; Constants - the period of shooting, speed of shells, speed of the player
Const frq = 200, v0# = .01, vp# = .005
; Const frq = 200, v0# = .2, vp# = .1
Const bs# = 2

Global x#, y#

; createturret 1:createturret 2:createturret 3:createturret 4
createturret 5:createturret 4:createturret 2


; Creation of the player
p = CreateSphere(16)
h = CreateSphere(8, p)
PositionEntity h, 1, 0, 0
ScaleEntity h, .4, .4, .4

Repeat
tim = MilliSecs()

For t.turret = Each turret

; Auxiliary variables + targetting on the player by default
dx# = x# - tx
dy# = y# - ty
cang# = ATan2(dy#, dx)
tdx# = dx#
tdy# = dy#
tdir# = cang#
pr# = Sqr(dx# * dx# + dy# * dy#)

; Modes of an aiming of turrets:
Select tMode
Case 0; shooting in the given direction
cang = 0
Case 1; shooting with rotation
cang# = tang# + .05 * dt#
Case 2; exact targetting on object

Case 3; shooting by a fan
cang# = cang# + Sin(dcang#) * 30
dcang# = dcang# + 2
Case 4; shooting on an forestalling
; Calculation of factors of a quadratic
a# = v# * v# - v0# * v0#
b# = 2.0 * v# * (dx# * Cos(ang#) + dy# * Sin(ang#) -bs#)
c# = dx# * dx# + dy# * dy# - bs# * bs#
; Calculation of a discriminant
d# = b# * b# - 4.0 * a# * c#
If d# >= 0 Then
; Calculation of the moment of a meeting of a shell and the player
t1# = (-b# + Sqr(d#)) / 2.0 / a#
t2# = (-b# - Sqr(d#)) / 2.0 / a#
If t2# > 0 Then t1# = t2#
If t1# >= 0 Then
; Calculation of a angle through coordinates of object during the found moment of time
cang# = ATan2(y# + t1# * v# * Sin(ang#) - ty#, x# + t1# * v# * Cos(ang#) - tx#)
End If
End If
Case 5; a self - training turret (the amendment to a angle undertakes from a file)
cang# = cang# + aiang(Int(pr# * aistp#))
End Select

; Turn of a turret
rotateturret t, cang#
; Return of a barrel on former position
If EntityX(tarrel) < .75 Then MoveEntity tarrel, 0, - .25 / frq * dt#, 0

; A shot and displacement of a barrel inside of a turret
If nextshot <= tim Then
fire t
PositionEntity tarrel, .5, 0, 0
End If
Next

; Delay between shots
If nextshot <= tim Then nextshot = tim + frq

For s.shot = Each shot
; Moving bullets
sx# = sx# + sdx# * dt#
sy# = sy# + sdy# * dt#
s# = s# + v0# * dt#
PositionEntity sh, sx#, sy#, 0
; If distances from a turret up to a bullet and up to the player are equal,
If pr# <= s# And sdir# < 999 Then
; The adjusting angle for the given distance is calculated
Newang# = s dir# - sdir#
; Squeezes into borders (-180, 180)
Newang# = Newang# - Floor((Newang# + 180.0) / 360.0) * 360.0
; Also storing it in a file,
aiang(Int(pr# * aistp#)) = Newang#
;(A next line - for not to store this bullet in a file once again)
sdir# = 999
End If
If(sx# - x#) ^ 2 + (sy# - y#) ^ 2 < 1 Then
FreeEntity sh: Delete s
red = 255
hits# = hits# + 1
Else
; Removing the bullets which have overstepped the bounds of the screen
If Abs(sx#) + Abs(sy#) > 40 Then FreeEntity sh:Delete s
End If
Next

; Indication of hit
If red > 0 Then
red = red - Int(dt / 3)
Else
red = 0
End If
EntityColor p, 255, 255 - red, 255 - red

; Moving and turn of the player (speed is calculated depending on last time)
PositionEntity p, x#, y#, 0
RotateEntity p, 0, 0, ang#
v# = (KeyDown(200) - KeyDown(208)) * vp#
ang# = ang# + .3 * dt# * (KeyDown(203) - KeyDown(205))
x# = x# + v# * Cos(ang#) * dt#
y# = y# + v# * Sin(ang#) * dt#

RenderWorld
; Counter
Text 0, 0, "Hits / sec:" + (hits# / sec#)
Flip
; Time, spent for this cycle (fractional as it is multiplied by fractional values)
dt# = MilliSecs() - tim
sec# = sec# + 0.001 * dt#
Until KeyHit(1)

Function createturret(Mode)
; Creation of a head part
t.turret = New turret
thead = CreateCylinder(6)
ScaleMesh thead, 1, .5, 1
RotateMesh thead, 90, 0, 0
; A barrel created separately, but to adhere to a head part
tarrel = CreateCylinder(16, False)
RotateEntity tarrel, 0, 0, 90
ScaleEntity tarrel, .2, 1, .2
PositionEntity tarrel, .75, 0, 0
h = CreateCylinder(16, True)
ScaleEntity h, .3, .3, .3
RotateEntity h, 0, 0, 90
PositionEntity h, 2, 0, 0
EntityParent tarrel, thead
EntityParent h, tarrel
; Setting random coordinates of a turret
tx# = Rnd(-20, 20)
ty# = Rnd(-20, 20)
PositionEntity thead, tx#, ty#, 0
tMode = Mode
End Function

Function rotateturret(t.turret, ang#)
tang# = ang#
RotateEntity thead, 0, 0, ang#
End Function

Function fire(t.turret)
ang# = tang#
s.shot = New shot
sx# = tx# + Cos(ang#) * r
sy# = ty# + Sin(ang#) * r
s# = r
sdx# = Cos(ang#) * v0#
sdy# = Sin(ang#) * v0#
sh = CreateSphere(2)
ScaleEntity sh, .15, .15, .15
EntityColor sh, 255, 255, 0
; Auxiliary variables(for AI)
s x# = tx#
s y# = ty#
sdir = tdir#
s = t
End Function


Comments : none...