forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   Проекты C++ (http://forum.boolean.name/forumdisplay.php?f=56)
-   -   [TrueHorror] - разработка (http://forum.boolean.name/showthread.php?t=17293)

mr.DIMAS 06.12.2014 18:36

Ответ: [TrueHorror] - разработка
 
Как правильно организовать перемещение персонажа? Сейчас у меня метод "в лоб". Создаем капсулу вокруг игрока и задаем ей линейную скорость в нужно направлении, отсюда всякие косяки в виде плохого перемещения по лестницам и наклонным поверхностям( даже когда трение выставлено в ноль ). Поэтому появилась идейка сделать перемещение на рейкастинге. Замысел такой: бросаем луч вниз под игроком, находим точку пересечения и перемещаем в нее игрока, затем кидаем еще луч перед игроком на небольшом расстоянии от него тоже вниз но с начальной точкой чуть выше точки пересечения первого луча( то бишь - высота шага ), если есть пересечение то можно сделать шаг -> делаем интерполяцию между двумя полученными точками. В принципе, такой подход работает и довольно неплохо. Но как делают труЪ пацаны?

Mr_F_ 06.12.2014 18:51

Ответ: [TrueHorror] - разработка
 
Цитата:

но с начальной точкой чуть выше точки пересечения первого луча( то бишь - высота шага )
а если типа стол стоит?
по-твоему получается что можно идти сквозь стол, т.к. лучи все проверяться под столом будут.

ARA 06.12.2014 18:57

Ответ: [TrueHorror] - разработка
 
Цитата:

Но как делают труЪ пацаны?
Делать коллайдеры лестниц и всех непонятных мест для столкновений с гг в виде наклонённой сплошной плоскости.

Вован 07.12.2014 01:12

Ответ: [TrueHorror] - разработка
 
L.D.M.T. Выкладывал исходники для Blitz3D и среди прочих, лежал ничем не примечательный - fpstest. Вот в нём, идеальное управление, мне так кажется. Думаю, тебе не составит труда адаптировать его под C++

Вот кусок.
Цитата:

Function UpdatePlayer()

;look
mxspd=MouseXSpeed()*0.25
myspd=MouseYSpeed()*0.25
MoveMouse GraphicsWidth()/2,GraphicsHeight()/2
pitch=pitch+myspd
yaw=yaw-mxspd
If pitch<-90 Then pitch=-90
If pitch>90 Then pitch=90
RotateEntity camera,pitch,yaw,0
RotateEntity player,0,yaw,0

;movement
If KeyDown(200)
vz=vz+0.05
ElseIf KeyDown(208)<-- Это скобка.
vz=vz-0.05
EndIf
vz=vz*0.9
If KeyDown(203)
vx=vx-0.05
ElseIf KeyDown(205)
vx=vx+0.05
EndIf
vx=vx*0.9

;steps and floor collisions
pick=LinePick (EntityX(player),EntityY(player),EntityZ(player),0 ,-playerheight,0)
If pick
PositionEntity player,EntityX(player),PickedY()+playerheight,Enti tyZ(player)
vy=0
EndIf
vy=vy-0.2
vy=vy*0.9


;move player pivot
MoveEntity player,vx,0,vz
TranslateEntity player,0,vy,0

;move camera + player meshes smoothly
PositionEntity camera,EntityX(player),EntityY(camera),EntityZ(pla yer)
TranslateEntity camera,0,(EntityY(player)-(EntityY(camera)-cameraheight))*0.1,0
Весь.
;fps level, graphics & code by rob cummings ([email protected])
;unoptimised

;framerate variables
Const FPS=85
Const debug=0

;collision variables
Global col_level=1,col_player=2,col_bullet=3

;player variables
Global pitch#,yaw#,mxspd#,myspd#,vx#,vy#,vz#,camera,playe r,gun,pick,gunsight,guntarget,hand

;other vars
Global firetex,firetexpos#,bob#,target,scorchsprite,plasm asprite,shockwavesprite,recoil#

Global cameraheight#=3.5 ;height of player eyes
Global playerheight#=4 ;height of collision sphere
Global playerradius#=2 ;radius of collision sphere

;types
Type plasma
Field ent,rot#
End Type

Type scorch
Field ent,life#
End Type

Type shockwave
Field ent,life#,size#
End Type

;display
AppTitle "FPS Example"
Text 20,2,"Choose mode by pressing a number key:"
Text 20,32,"(1) 800,600 windowed "
Text 20,48,"(2) 800,600 fullscreen"
Text 20,64,"(3) 1024,768 fullscreen"
Text 20,80,"(4) 1600,1200 fullscreen"
Repeat
If KeyDown(2) Or debug Then xres=800:yres=600:mode=2:Exit
If KeyDown(3) Then xres=800:yres=600:mode=1:Exit
If KeyDown(4) Then xres=1024:yres=768:mode=1:Exit
If KeyDown(5) Then xres=1600:yres=1200:mode=1:Exit
VWait
Forever
Graphics3D xres,yres,0,mode
HidePointer

;setup
camera=CreateCamera()
CameraRange camera,0.2,400
CameraFogMode camera,1
CameraFogColor camera,140,140,120
CameraFogRange camera,-100,800

;hud
tex=LoadTexture("target.png",2)
TextureBlend tex,2
target=CreateSprite()
EntityTexture target,tex
EntityFX target,1
EntityOrder target,-1
EntityBlend target,3
EntityParent target,camera
MoveEntity target,0,0,12
EntityAlpha target,0.8

;player
player=CreatePivot()
hand=CreatePivot()
EntityParent hand,camera
MoveEntity hand,.8,-.8,.8

;gun
gun=LoadAnimMesh("gun.b3d")
firetex=LoadTexture("fury.png")
For i=1 To CountChildren(gun)
If EntityName(GetChild(gun,i))="red" EntityTexture GetChild(gun,i),firetex
Next
gunsight=CreatePivot()
EntityParent gunsight,camera
MoveEntity gunsight,-2,2,500
guntarget=CreatePivot()

;weapon effects - plasma
tex=LoadTexture("plasma.png",2)
TextureBlend tex,2
plasmasprite=CreateSprite()
EntityTexture plasmasprite,tex
EntityFX plasmasprite,1
EntityBlend plasmasprite,3
EntityAlpha plasmasprite,0.8
ScaleSprite plasmasprite,1,2
HideEntity plasmasprite

;weapon effects - scorch
tex=LoadTexture("scorch.png",2)
;TextureBlend tex,2
scorchsprite=CreateSprite()
EntityTexture scorchsprite,tex
EntityFX scorchsprite,1
EntityAlpha scorchsprite,0.8
ScaleSprite scorchsprite,1,2
SpriteViewMode scorchsprite,2
HideEntity scorchsprite


;weapon effects - shockwave
tex=LoadTexture("shockwave.png",2)
TextureBlend tex,2
shockwavesprite=CreateSprite()
EntityTexture shockwavesprite,tex
EntityFX shockwavesprite,1
EntityBlend shockwavesprite,3
EntityAlpha shockwavesprite,0.8
ScaleSprite shockwavesprite,1,2
SpriteViewMode shockwavesprite,2
HideEntity shockwavesprite

;level
level=LoadAnimMesh("final.b3d")

;level collisions
EntityType level,col_level,1

;remove collision on sky (a hack cos I didn't want to go back and change the level)
sky=FindChild(GetChild(level,1),"sky glow")
EntityType sky,0

;set up picking - this is because shooting and stair climbing needs pickable geometry. You can use picks for other stuff too
ent = level ; specify your level
While ent
EntityPickMode ent,2
ent = NextChild(ent)
Wend


;other collisions
EntityType player,col_player
EntityRadius player,playerradius,playerradius/2
Collisions col_player,col_level,2,2
PositionEntity player,100,10,-65
ResetEntity player
Collisions col_bullet,col_level,2,1



;mainloop
period=1000/FPS
time=MilliSecs()-period
While Not KeyHit(1)
Repeat
elapsed=MilliSecs()-time
Until elapsed

ticks=elapsed/period
tween#=Float(elapsed Mod period)/Float(period)

For k=1 To ticks
time=time+period
If k=ticks Then CaptureWorld

UpdateWorld
UpdatePlayer
UpdatePlasma
UpdateScorch
UpdateShockwave

Next

RenderWorld
Flip
Wend
End

Function UpdatePlayer()

;look
mxspd=MouseXSpeed()*0.25
myspd=MouseYSpeed()*0.25
MoveMouse GraphicsWidth()/2,GraphicsHeight()/2
pitch=pitch+myspd
yaw=yaw-mxspd
If pitch<-90 Then pitch=-90
If pitch>90 Then pitch=90
RotateEntity camera,pitch,yaw,0
RotateEntity player,0,yaw,0

;movement
If KeyDown(200)
vz=vz+0.05
ElseIf KeyDown(208)
vz=vz-0.05
EndIf
vz=vz*0.9
If KeyDown(203)
vx=vx-0.05
ElseIf KeyDown(205)
vx=vx+0.05
EndIf
vx=vx*0.9

;steps and floor collisions
pick=LinePick (EntityX(player),EntityY(player),EntityZ(player),0 ,-playerheight,0)
If pick
PositionEntity player,EntityX(player),PickedY()+playerheight,Enti tyZ(player)
vy=0
EndIf
vy=vy-0.2
vy=vy*0.9


;move player pivot
MoveEntity player,vx,0,vz
TranslateEntity player,0,vy,0

;move camera + player meshes smoothly
PositionEntity camera,EntityX(player),EntityY(camera),EntityZ(pla yer)
TranslateEntity camera,0,(EntityY(player)-(EntityY(camera)-cameraheight))*0.1,0


;gun
x1#=EntityX(gun,1)
y1#=EntityY(gun,1)
z1#=EntityZ(gun,1)
x2#=EntityX(gunsight,1)
y2#=EntityY(gunsight,1)
z2#=EntityZ(gunsight,1)
pick=LinePick(x1,y1,z1,x2-x1,y2-y1,z2-z1)
If pick
PositionEntity guntarget,PickedX(),PickedY(),PickedZ()
EndIf

PositionEntity gun,EntityX(hand,1),EntityY(hand,1)-((Cos(bob)*Sqr(vx*vx+vz*vz))*.2),EntityZ(hand,1)
MoveEntity gun,0,0,recoil#
PointEntity gun,guntarget
PositionTexture firetex,firetexpos,firetexpos
firetexpos=firetexpos+0.01
bob=bob+4
recoil=recoil*.9

;firing code
If MouseHit(1) ShootPlasma() : recoil=-.6

End Function

Function ShootPlasma()
p.plasma=New plasma
p\ent=CopyEntity(plasmasprite)
PositionEntity p\ent,EntityX(gun),EntityY(gun),EntityZ(gun)
PointEntity p\ent,guntarget
MoveEntity p\ent,0,0,-1
p\rot=Rand(360)
EntityType p\ent,col_bullet
End Function

Function UpdatePlasma()
For p.plasma=Each plasma
MoveEntity p\ent,0,0,2.5
RotateSprite p\ent,p\rot
p\rot=p\rot+20
If EntityCollided(p\ent,col_level)

;find angle of collision
nx#=0
ny#=0
nz#=0
num#=CountCollisions(p\ent)
For i=1 To num
nx=nx+CollisionNX(p\ent,i)
ny=ny+CollisionNY(p\ent,i)
nz=nz+CollisionNZ(p\ent,i)
x#=x#+CollisionX(p\ent,i)
y#=y#+CollisionY(p\ent,i)
z#=z#+CollisionZ(p\ent,i)
Next
nx=nx/num
ny=ny/num
nz=nz/num
x=x/num
y=y/num
z=z/num




;scorch
s.scorch=New scorch
s\ent=CopyEntity(scorchsprite)
s\life#=0.8
RotateSprite s\ent,Rand(360)
temp#=1+Rnd(2)
ScaleSprite s\ent,temp#,temp#
PositionEntity s\ent,x,y,z
AlignToVector s\ent,-nx,-ny,-nz,0
MoveEntity s\ent,0,0,-0.5

;shockwave
w.shockwave=New shockwave
w\ent=CopyEntity(shockwavesprite)
w\life#=2
w\size=0.2
RotateSprite w\ent,Rand(360)
PositionEntity w\ent,x,y,z
RotateEntity w\ent,EntityPitch(s\ent),EntityYaw(s\ent),0
MoveEntity w\ent,0,0,-0.5


FreeEntity p\ent
Delete p
EndIf
Next
End Function

Function UpdateScorch()
For s.scorch=Each scorch
EntityAlpha s\ent,s\life
s\life=s\life-0.005
If s\life<0
FreeEntity s\ent
Delete s
EndIf
Next
End Function

Function UpdateShockwave()
For s.shockwave=Each shockwave
EntityAlpha s\ent,s\life
ScaleSprite s\ent,s\size,s\size
s\life=s\life-0.06
s\size=s\size+0.1
If s\life<0
FreeEntity s\ent
Delete s
EndIf
Next
End Function

Function NextChild(ent)
If CountChildren(ent)>0
Return GetChild(ent,1)
EndIf

Local foundunused=False
Local foundent = 0, parent,sibling
While foundunused=False And ent<>0
parent = GetParent(ent)
If parent<>0
If CountChildren(parent)>1
If GetChild(parent,CountChildren(parent))<>ent
For siblingcnt = 1 To CountChildren(parent)
sibling = GetChild(parent,siblingcnt)
If sibling=ent
foundunused = True
foundent = GetChild(parent,siblingcnt+1)
EndIf
Next
EndIf
EndIf
EndIf
ent = parent
Wend
Return foundent
End Function


А вообще, игра нормально идёт. Умудрился провалиться со второго этажа сквозь пол, а так всё норм. Cтелс как в Skyrim, темно как Alone in the Dark, страшно как в кино, только графику подправить бы. Ты игры делаешь и ракеты запускаешь, мне бы твои таланты...

mr.DIMAS 14.12.2014 00:59

Ответ: [TrueHorror] - разработка
 
Исправил много багов и поправил прозводительность. В общем в каждой части рендера было много CreateStateBlock() и таким образом я доверял стейты директу, как выянилось после профайлинга на этих стейтблоках падает до 15 процентов производительности, выпилив их в взял контроль над стейтами в свои руки я повысили производительность на 20 процентов( убрав лишние изменения стейтов - у меня Pure-device ). Сделал выбор с вертикальной синхронизацией или без. Максимальный фпс на моей машине - 90 к\с в шахте( тени от спотов и FXAA ).

Так вот тут сразу вопрос. Обычно я считал дельта-тайминг и просто домножал все значения на него чтобы игра шла нормально при любом фпс. Когда фпс от 30 до 60 кадров то все нормас работает, когда выходит из этих границ начинается ебала. В общем игра начинает работать не стабильно и физика тупить начинает. Как труЪ пацаны делают дельта тайминг? Читал это , но мне тамошние подходы не помогают.

pax 14.12.2014 03:35

Ответ: [TrueHorror] - разработка
 
Я бы так сделал (в Unity ограничение по времени работы физики на кадр задается):

PHP код:

var physicsStep 1f/100f;  // 100 раз в секунду обновлять физику
var maxPhysicsTimePerFrame 0.15f// максимальное время работы физики за кадр
var lastTime Now();
var 
physicsTimer 0// накопитель времени физики

while(true){
   var 
currentTime Now();
   var 
deltaTime currentTime lastTime;
   
lastTime currentTime;

   
physicsTimer += deltaTime;

   
Update(deltaTime); 
   
Render();

   var 
physicsSteps = (int)(physicsTimer physicsStep); // число шагов физики
   
physicsTimer -= physicsStep*physicsSteps// сбрасываем таймер физики (оставляем остаток)

   
var physicsWorkTime 0;
   var 
physicsStartTimeNow(); 

   for(
int i 0physicsStepsi++){
      
UpdatePhysics(physicsStep); // обновление физики
      
var physicsEndTime Now();
      
physicsWorkTime += physicsEndTime physicsStartTime;
      
physicsStartTime physicsEndTime;

      
// ограничение по времени работы физики
      
if(physicsWorkTime >= maxPhysicsTimePerFrame )
         break;
   }



pax 14.12.2014 13:35

Ответ: [TrueHorror] - разработка
 
Я тут подумал, скорее всего Render() в самый конец надо бы поставить, после цикла физики... и в Unity 50 раз по умолчанию в секунду физика работает, т.е. шаг физики 0,02 с (1/50)

mr.DIMAS 14.12.2014 14:01

Ответ: [TrueHorror] - разработка
 
Попробую так сделать.

Вопрос теперь по графическому конвейру. Вызов SetRenderState( D3DRS_COLORWRITEENABLE, 0 ) выключает запись цвета в буфер кадра, исключает ли он при этом работу пиксельного шейдера? Иными словами, при выключенной записи в буфер кадра будет ли работать пиксельный шейдер?

Mr_F_ 14.12.2014 14:10

Ответ: [TrueHorror] - разработка
 
Цитата:

Иными словами, при выключанной записи в буфер кадра будет ли работать пиксельный шейдер?
не факт.
советуют ставить NULL на PS: http://www.gamedev.net/topic/641257-...pass-worth-it/

не факт, потому что, к примеру, ты можешь делать clip/discard в шейдере, что повлияет на глубину тоже.
мне думается, что умный драйвер может не выполнять шейдеры, если дискарда точно нет, и запись выключена, но я не проверял.

mr.DIMAS 14.12.2014 14:20

Ответ: [TrueHorror] - разработка
 
Я просто оптимизациями занимаюсь, и пока довольно успешно( ибо уже выжал 30% ). Так вот деферед у меня организован хорошо, но есть один момент.

Код:

для каждого источника света
{
    ставим простейшие шейдеры для отрисовки в трафарет
    рисуем  ограничивающий меш в трафарет
    ставим шейдеры для фулскрин квада( пиксельный отвечает за освещение )
    рисуем квад
}

как видно тут постоянно меняются шейдеры, хотелось бы этого избежать ибо смена шейдеров не быстрая. и я вот че подумал, может не менять шейдеры а просто в пиксельном шейдере освещения сделать ветвление типа
Код:

bool boundingVolumeRender;
...
if( boundingVolumeRender )
  return float4( 1, 1, 1, 1 );
else
  calculateLighting

получается в пиксельном шейдере статическое ветвление, оно практически бесплатно, вершинный шейдер тоже не проблема, ибо разница только в матрицах - для ограничивающего объема это worldViewProjection, а для квада это просто projection.

mr.DIMAS 14.12.2014 15:14

Ответ: [TrueHorror] - разработка
 
2pax, плохо работает, физику все равно начинает шатать, что аж улетаю в небеса. буду сидеть разбираться, может найду выход из этой тупой ситуации.

нашел это - http://bulletphysics.org/mediawiki-1...ical_Game_Loop
попробую реализовать

mr.DIMAS 14.12.2014 16:03

Ответ: [TrueHorror] - разработка
 
Наконец-то все работает так как должно. Нужно было сразу загуглить bullet physics low fps. :-D

В общем одной проблемой меньше

pax 14.12.2014 16:23

Ответ: [TrueHorror] - разработка
 
Цитата:

Сообщение от mr.DIMAS (Сообщение 290628)
2pax, плохо работает, физику все равно начинает шатать, что аж улетаю в небеса. буду сидеть разбираться, может найду выход из этой тупой ситуации.

:pardon: я предположил как работает физика Unity. В Unity есть еще FixedUpdate (для применения сил к телам), он срабатывает ровно столько же раз, сколько и обновление физики, т.е. перед каждым UpdatePhysics(physicsStep) из моего примера, а Update используется для логики игры. Но это было всего-лишь мое предположение :) как оно устроено.

mr.DIMAS 14.12.2014 16:30

Ответ: [TrueHorror] - разработка
 
Все равно спасибо за то, что помогаешь.


теперь в меню Авторы, "Особые благодарности" на одного человека больше

MiXaeL 14.12.2014 23:22

Ответ: [TrueHorror] - разработка
 
У тебя физика и рендер в одном потоке?
Теоретически физика может крутиться на отдельном ядре с ~фиксированным числом циклов в секунду, синхронизируясь каждый кадр с графикой и юзеринпутом.


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

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