forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   FAQ (http://forum.boolean.name/forumdisplay.php?f=15)
-   -   Пули. (http://forum.boolean.name/showthread.php?t=16497)

mr.DIMAS 18.03.2012 23:46

Пули.
 
Пули? Да, да. Тема-то заезжена, но не все знают как их правильно реализовывать. При стрельбе медленными снарядами( ракетами

и т.п. ) обычная блицевская коллизия работает прекрасно. С повышением скоростей объект часто не успевает столкнуться из-за

больших временных шагов при обработке столкновений. Как же этого избежать? Очень просто. Использовать комбинацию луч +

ентити.

Код:

Type Bullet
 Field entity
 Field target
 Field lifeTime
 Field speed
End Type

Это наша структура пули. Поле target предназначено для пивота с помощью которого определяются конечные координаты луча.

Инициализация происходит так.

Код:

Function CreateBullet( from% )
 bul.Bullet = New Bullet
 bul\entity = CreateSphere()
 bul\target = CreatePivot( bul\entity )
 bbPositionEntity( bul\target, 0, 0, 1000 ) ; отодвигаем "цель" подальше

 bbPositionEntity( bul\entity, EntityX( from, 1 ), EntityY( from, 1 ), EntityZ( from, 1 )
 bbRotateEntity( bul\entity, EntityPitch( from, 1 ), EntityYaw( from, 1 ), EntityRoll( from, 1)

 lifeTime = 0
 speed = 2
End Function

from - тот объект из которого пускается пуля - например моделька оружия
Теперь самая главная часть
Код:

Function UpdateBullets()
 For bul.Bullet = Each Bullet

 

  sx# = bbEntityX( bul\entity, 1 )
  sy# = bbEntityY( bul\entity, 1 )
  sz# = bbEntityZ( bul\entity, 1 )

  ex# = bbEntityX( bul\target, 1 )
  ey# = bbEntityY( bul\target, 1 )
  ez# = bbEntityZ( bul\target, 1 )

  MoveEntity( bul\entity, 0, 0, speed )
  dx# = sx - ex
  dy# = sy - ey
  dz# = sz - ez

  ent = LinePick( sx, sy, sz, dx, dy, dz, 1000 )
  if ent <> 0
  px# = PickedX()
  py# = PickedY()
  pz# = PickedZ()

  dx# = sx - px
  dy# = sy - py
  dz# = sz - pz

  dist2# = dx * dx + dy * dy + dz * dz
 
  if dist2 < speed * speed ; Попали
    FreeEntity bul\entity
    delete bul
  end if
 end if
 Next
End function

Как это работает? Пуля двигается как обычно - MoveEntity. В каждую итерацию цикла происходит проверка пересечения луча( пущенного из центра пули до цели ) с объектами сцены. Если пересечение есть, и расстояние от точки пересечения до центра пули меньше её скорости, то пуля попала в цель.

Почему условием попадания является "расстояние меньше скорости". Чтобы "столкновение" пули с объектом было устойчивым даже при маленьких дистанциях до цели. Пример: стрельба в упор из пистолета

Все объекты сцены должны быть "пикабельны" - EntityPickMode entity, 2

зы. Давно на блице не писал, поэтому могут быть ошибки в синтаксисе

Я сказал всё.

Платон Александрович 19.03.2012 05:30

Ответ: Пули.
 
mr.DIMAS
Открою тебе страшный секрет, в блице и так используется рейкаст для коллизий, и там ничего друг через друга не пролетает, даже на космической скорости ;)

pepel 19.03.2012 07:21

Ответ: Пули.
 
Цитата:

Сообщение от Платон Александрович (Сообщение 223001)
mr.DIMAS
Открою тебе страшный секрет, в блице и так используется рейкаст для коллизий, и там ничего друг через друга не пролетает, даже на космической скорости ;)

а можеш пример запилить?

Платон Александрович 19.03.2012 07:39

Ответ: Пули.
 
Цитата:

Сообщение от pepel (Сообщение 223002)
а можеш пример запилить?

Гм, а что там пилить-то? Ну вот например, сойдет?:)
Код:

Const CL_WALL% = 1
Const CL_BULLET% = 2

Graphics3D ( 800, 600, 0, 2 )

Local Wall% = CreateCube ( )
EntityColor ( Wall, 64, 64, 64 )
PositionEntity ( Wall, 5.0, 0, 0 )
EntityType ( Wall, CL_WALL )

Local Bullet% = CreateSphere ( 3 )
EntityColor ( Bullet, 255, 200, 100 )
EntityFX ( Bullet, 1 )
ScaleEntity ( Bullet, 0.05, 0.05, 0.05 )
EntityRadius ( Bullet, 0.05, 0.05 )
PositionEntity ( Bullet, -1.0, 0, 0 )
EntityType ( Bullet, CL_BULLET )

Collisions ( CL_BULLET, CL_WALL, 2, 1 )

Local Camera% = CreateCamera ( )
PositionEntity ( Camera, 0, 0, -10.0 )

Repeat
       
        If KeyDown ( 57 ) Then MoveEntity ( Bullet, 1000000.0, 0, 0 )
       
        UpdateWorld ( )
       
        RenderWorld ( )
       
        Text ( 10, 10, Str ( EntityX ( Bullet ) ) )
       
        Flip ( False )
       
Until KeyDown ( 1 )

End


pepel 19.03.2012 07:44

Ответ: Пули.
 
Цитата:

Сообщение от Платон Александрович (Сообщение 223004)
Гм, а что там пилить-то? Ну вот например, сойдет?:)
Код:

Const CL_WALL% = 1
Const CL_BULLET% = 2

Graphics3D ( 800, 600, 0, 2 )

Local Wall% = CreateCube ( )
EntityColor ( Wall, 64, 64, 64 )
PositionEntity ( Wall, 5.0, 0, 0 )
EntityType ( Wall, CL_WALL )

Local Bullet% = CreateSphere ( 3 )
EntityColor ( Bullet, 255, 200, 100 )
EntityFX ( Bullet, 1 )
ScaleEntity ( Bullet, 0.05, 0.05, 0.05 )
EntityRadius ( Bullet, 0.05, 0.05 )
PositionEntity ( Bullet, -1.0, 0, 0 )
EntityType ( Bullet, CL_BULLET )

Collisions ( CL_BULLET, CL_WALL, 2, 1 )

Local Camera% = CreateCamera ( )
PositionEntity ( Camera, 0, 0, -10.0 )

Repeat
       
        If KeyDown ( 57 ) Then MoveEntity ( Bullet, 1000000.0, 0, 0 )
       
        UpdateWorld ( )
       
        RenderWorld ( )
       
        Text ( 10, 10, Str ( EntityX ( Bullet ) ) )
       
        Flip ( False )
       
Until KeyDown ( 1 )

End


спасиб

Markova 19.03.2012 10:51

Ответ: Пули.
 
Цитата:

Сообщение от Платон Александрович (Сообщение 223001)
mr.DIMAS
Открою тебе страшный секрет, в блице и так используется рейкаст для коллизий, и там ничего друг через друга не пролетает, даже на космической скорости ;)

А вот и неправда, на космических пролетает If KeyDown ( 57 ) Then MoveEntity ( Bullet,9^50, 0, 0 =))

pepel 19.03.2012 11:47

Ответ: Пули.
 
Цитата:

Сообщение от Markova (Сообщение 223011)
А вот и неправда, на космических пролетает If KeyDown ( 57 ) Then MoveEntity ( Bullet,9^50, 0, 0 =))

аххахаххха))


Часовой пояс GMT +4, время: 17:06.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot