Greymem
вот такой итеративный алгоритм вроде работает:
1) расчетная_позиция = позиция_цели
2) дистанция = |расчетная_позиция - позиция_бота|
3) время_полета = дистанция / скорость_снаряда
4) упрежденная_позиция = позиция_цели + скорость_цели * время_полета
пункты 2,3,4 повторить несколько раз
некогда все грамотно расписывать, поэтому глянь эту говнодемку
при 5 итерациях ~60% попаданий, но это из-за того что цель отскакивает от стен, т.е. меняет направление когда выстрел уже произошел.
SuperStrict
Framework BRL.Blitz
Import BRL.Math
Import BRL.LinkedList
Import BRL.KeyCodes
Import BRL.GLMax2D
Type TBullet
Field Link:TLink
Field Force:Int
Field PositionX:Float
Field PositionY:Float
Field DirectionX:Float
Field DirectionY:Float
End Type
Const BulletSpeed:Float = 5
Local Bullets:TList = CreateList()
Local TargetPositionX:Float = 100
Local TargetPositionY:Float = 100
Local TargetDirectionX:Float = Sin(45)
Local TargetDirectionY:Float = Cos(45)
Const TargetSpeed:Float = 3
Local BotPositionX:Float = 400
Local BotPositionY:Float = 300
Local TicksCount:Int = 0
Local ShootTick:Int = 0
Local ShotsCount:Int = 0
Local HitsCount:Int = 0
Graphics(800, 600)
Repeat
TicksCount :+ 1
' движение цели
TargetPositionX :+ TargetDirectionX * TargetSpeed
TargetPositionY :+ TargetDirectionY * TargetSpeed
' отскок от стен
If TargetPositionX < 0 Then
TargetPositionX = 0
TargetDirectionX = -TargetDirectionX
End If
If TargetPositionX >= 800 Then
TargetPositionX = 800 - 1
TargetDirectionX = -TargetDirectionX
End If
If TargetPositionY < 0 Then
TargetPositionY = 0
TargetDirectionY = -TargetDirectionY
End If
If TargetPositionY >= 600 Then
TargetPositionY = 600 - 1
TargetDirectionY = -TargetDirectionY
End If
' стрельба
If TicksCount >= ShootTick Then
ShootTick = TicksCount + 10
ShotsCount :+ 1
' расчет упреждения
Local DeflexionX:Float = TargetPositionX
Local DeflexionY:Float = TargetPositionY
Local TargetVelocityX:Float = TargetDirectionX * TargetSpeed
Local TargetVelocityY:Float = TargetDirectionY * TargetSpeed
For Local ComputingPass:Int = 1 To 5
Local DeltaX:Float = DeflexionX - BotPositionX
Local DeltaY:Float = DeflexionY - BotPositionY
Local Distance:Float = Sqr(DeltaX * DeltaX + DeltaY * DeltaY)
Local Time:Float = Distance / BulletSpeed
DeflexionX = TargetPositionX + TargetVelocityX * Time
DeflexionY = TargetPositionY + TargetVelocityY * Time
Next
' выстрел
Local Bullet:TBullet = New TBullet
Bullet.Link = Bullets.AddLast(Bullet)
Local DeltaX:Float = DeflexionX - BotPositionX
Local DeltaY:Float = DeflexionY - BotPositionY
Local Distance:Float = Sqr(DeltaX * DeltaX + DeltaY * DeltaY)
Bullet.DirectionX = DeltaX / Distance
Bullet.DirectionY = DeltaY / Distance
Bullet.PositionX = BotPositionX
Bullet.PositionY = BotPositionY
Bullet.Force = 100
End If
' обновление пуль
For Local Bullet:TBullet = EachIn Bullets
If Bullet.Force <= 0 Then
Bullet.Link.Remove()
Continue
End If
' полет
Bullet.Force :- 1
Bullet.PositionX :+ Bullet.DirectionX * BulletSpeed
Bullet.PositionY :+ Bullet.DirectionY * BulletSpeed
' проверка на попадание в цель
Local DeltaX:Float = TargetPositionX - Bullet.PositionX
Local DeltaY:Float = TargetPositionY - Bullet.PositionY
Local Distance:Float = Sqr(DeltaX * DeltaX + DeltaY * DeltaY)
If Distance <= 8 Then
HitsCount :+ 1
Bullet.Link.Remove()
End If
Next
' отрисовка
Cls()
SetColor(0, 255, 0)
DrawOval(BotPositionX - 8, BotPositionY - 8, 16, 16)
SetColor(255, 0, 0)
DrawOval(TargetPositionX - 8, TargetPositionY - 8, 16, 16)
SetColor(255, 255, 0)
For Local Bullet:TBullet = EachIn Bullets
DrawOval(Bullet.PositionX - 3, Bullet.PositionY - 3, 6, 6)
Next
SetColor(255, 255, 255)
DrawText(String.FromInt(HitsCount * 100 / ShotsCount) + "%", 10, 10)
Flip()
Until KeyDown(KEY_ESCAPE)
End