forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   3D-программирование (http://forum.boolean.name/forumdisplay.php?f=12)
-   -   Создание сетевой игры на 3D-примере (http://forum.boolean.name/showthread.php?t=3083)

Vyacheslav 02.04.2007 17:29

Создание сетевой игры на 3D-примере
 
Вложений: 2
Итак. Много я перечитал постов по поводу создания сетевой игры, потратил уйму времени и в конце концов до меня дошло примерно, как это делается. В этой статье я расскажу о том, как создать простое приложение, но не чат, а связанное с реальной 3D-сценой. По ходу постараюсь объяснить важные моменты. Думаю, многих интересует, как создать хотя бы 2 объекта, запустить на разных компьютерах и чтобы каждый игрок влиял на другого и каждый видел все, что происходит. Т.е. пример будет таковой: есть земля - небольшая плоскость и две сферы. Создается 2 сферы, каждой из которой управляет соответственный игрок. Разумеется, этот пример можно запустить и у себя, на одном компе. В этом случае IP рекомендую вводить 127.0.0.1 - таким образом программа будет ссылаться на один и тот же комп - т.е. на себя. Иначе говоря, можно запустить дважды программу и с помощью двух окон воспроизвести боевые условия :) .
Поехали (уверяю, просто и практически понятно):

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

Код:

i=Input("Enter 1 if you want to start Net game or else for one player game:")
netgame=i=1
If netgame
 sng=StartNetGame()
 is_host=sng=2
 netgame=sng>0
Else
 is_host=1
EndIf
name$=Input("Enter your name:")

Далее мы задаем графический режим и объявляем переменные, чтобы считать фпс и шрифт, в конце тип игрока:

Код:

Graphics3D 800,600,32,2
SetBuffer BackBuffer()
HidePointer()
SeedRnd MilliSecs()
Global Real_fps,Real_fps_time,Real_fps_count
Global fntHUD=LoadFont("Verdana",18,False,False,False)
 
Type TPlayer
 Field name$,id
 Field mesh,cam
End Type

Теперь проверяем - если игра сетевая, то создаем сетевого игрока, иначе - myid присваиваем 0. По больщому счету, эта строчка создает идентификационный номер игрока, иначе говоря, имя, по которому программа сможет найти его. Сам игрок будет создаваться дальше.
Код:

If netgame Then myid=CreateNetPlayer(name$) Else myid=0
Создадим ту самую "землю":
Код:

ground=CreateCube()
ScaleEntity ground,30,0.1,30
EntityColor ground,0,155,0

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

player.TPlayer = New TPlayer
player\id=myid
myent=CreateSphere()
ScaleEntity myent,2,2,2
EntityColor myent,Rand(0,255),Rand(0,255),Rand(0,255)
player\mesh=myent
player\cam=CreateCamera(player\mesh)
PositionEntity player\cam,0,5,-10
RotateEntity player\cam,20,0,0
myp.TPlayer=player.TPlayer
player\name=name

Итак, мы создали плеера - сферу, задали ей случайный цвет, создали камеру игрока и для удобства использовали немного замуток: myent, myp - это дл того, чтобы быстрее узнать себя, не рыться в цикле играчков. Т.е. запуская экзешник - тот, кто сидит за компом создает себе нового игрока, которым будет управлять. Через player\id мы сможем узнать - мы ли это или кто-то другой (он для каждого должен быть разным).

Лезем в цикл:

Код:

Repeat
 
 For player.TPlayer = Each TPlayer
  If player\name$=name$
  If KeyDown(200)
    MoveEntity player\mesh,0,0,0.5
  EndIf
 
  If KeyDown(208)
    MoveEntity player\mesh,0,0,-0.5
  EndIf
 
  If KeyDown(203)
    MoveEntity player\mesh,-0.5,0,0
  EndIf
 
  If KeyDown(205)
    MoveEntity player\mesh,0.5,0,0
  EndIf
 
  EndIf
 
 Next
 
 
 
 UpdateWorld()
 RenderWorld()

Для большей надежности (или по глупости :) ) я все же перебираю играков и ищу "себя" - нашел - отлично, двигаю свою сферу.

Подсчитаем фпс:

Код:

;#Region--- FPS count ---
 Real_fps_count=Real_fps_count+1
 If Real_fps_time=0 Then Real_fps_time=MilliSecs()
 If Real_fps_time+1000 < MilliSecs() Then
    Real_fps=Real_fps_count
    Real_fps_count=0
    Real_fps_time=MilliSecs()
 EndIf
 
;#End Region

Выведем немного инфы:

Код:

SetFont fntHUD
 Color 206,240,237
 
 Text 10,10,"FPS: "+Real_fps
 Text 10,30,"TRIS: "+TrisRendered()
 Text 10,50,"VideoMem: "+AvailVidMem()/1000000+"Mb/"+TotalVidMem()/1000000+"Mb"
 If is_host=1 Then Text 10,70,"My comp is server" Else Text 10,70,"My comp is client"
 Text 10,90,"my name: "+name$
 Text 10,110,"my id: "+myid

И последний кусочек:
Код:


 If netgame
  SendNetMsg 1,EntityX#(myp\mesh),myid,0,0
  SendNetMsg 2,EntityY#(myp\mesh),myid,0,0
  SendNetMsg 3,EntityZ#(myp\mesh),myid,0,0
 
  While RecvNetMsg()
 
  nt=NetMsgType()
 
  If nt=1
    x#=Float(NetMsgData())
 
  ElseIf nt=2
    y#=Float(NetMsgData())
           
 
  ElseIf nt=3
    z#=Float(NetMsgData())
 
 
  ElseIf nt=100
    player.TPlayer=New TPlayer
    player\id=NetMsgFrom()
    player\mesh=CreateSphere()
    ScaleEntity player\mesh,2,2,2
    EntityColor player\mesh,Rand(0,255),Rand(0,255),Rand(0,255)   
    player\name=NetPlayerName(player\id)
   
  EndIf
 
  For player.TPlayer = Each TPlayer
 
    If player\id=NetMsgFrom()
    PositionEntity player\mesh,x#,y#,z#
    EndIf
   
  Next
 
 
  Wend
 
 EndIf
 
 
Flip
Until KeyDown(1)

End

Его мы рассмотрим ближе. В самом начале проверяется. сетевая ли игра (If netgame) - если да, то следующие 3 строчки SendNetMsg посылают данные - координаты нашей сферы. Дальше работает RecvNetMsg()->NetMsgType(). Т.е. каждый пользователь отсылает всем (в нашем случае другому) свои координаты и в то же время принимает чужие. Для этих целей есть 100 каналов, которые могут быть в каналах 1-99. Значит, мы посылаем по первых трех каналах координаты и так же по этим трем принимаем (в едином формате). В один канал можно запаковать больше информации, но написать функцию, чтобы ее распознать - дело замутное :) , поэтому мы по-хозяйски нагло пользуемя аж 3-мя каналами, чтобы передать только координаты. Если NetMsgType() передал нам значение 100, то это значит, что подключился новый игрок. Потом мы смотрим принятые чужие координаты и ставим в своем окне чужака по ним.
Далее вам нужно создать экзешник, скинуть его другу или запустить дважды приложение, в одном из которых создать игру, в другом - подключиться (используя TCP).
Правда, я эксперементировал только с 2-мя игроками, поэтому если кто из акул геймдева не пожалеет сил подкорректировать код - я буду только рад. Спасибо. Надеюсь, вам понравилось, жду отзывов или вопросов. Вот весь код:


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

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