Показать сообщение отдельно
Старый 27.11.2011, 13:41   #113
Платон Александрович
Нуждающийся
 
Аватар для Платон Александрович
 
Регистрация: 05.10.2011
Адрес: Россия, Южно-Сахалинск
Сообщений: 66
Написано 42 полезных сообщений
(для 83 пользователей)
Ответ: Вопрос-Ответ (для новичков BlitzMax)

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

Последний раз редактировалось Платон Александрович, 27.11.2011 в 14:52. Причина: опечатки
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
Greymem (28.11.2011)