|
24.04.2012, 10:18
|
#286
|
Бывалый
Регистрация: 22.12.2011
Сообщений: 844
Написано 150 полезных сообщений (для 275 пользователей)
|
Ответ: Vivo
А не могли бы в еще отписаться о скорости ваших жестких дисков, ведь как я понял, при прямом использовании файлов(они открываются, оттуда считывается информация, они закрываются, и все это в риалтайме) важна именно она.
В аттаче версия, без чанков, без файлов, просто двумерный массив. Просто и сердито. Карта 10000х10000(381 мб рамки). Генерируется приблизительно 5 секунд. Также, пожалуйста, отпишитесь о фпс и укажите характеристики своего компьютера( тут уже скорость винчестера не влият ).
Хотя признаюсь, был шокирован столь низким фпс в предыдущей версии. Видимо всё же с массивами надо колдовать...
Последний раз редактировалось Nikich, 24.04.2012 в 19:53.
|
(Offline)
|
|
24.04.2012, 12:18
|
#287
|
Знающий
Регистрация: 06.12.2010
Адрес: Луганск
Сообщений: 252
Написано 112 полезных сообщений (для 166 пользователей)
|
Ответ: Vivo
Генерируется приблизительно 5 секунд
|
Генерировалось примерно 10 минут.
ФПС стабильный, около 55, без падений.
__________________
AMD Sempron(tm) 1.41Ггц, 1024МБ ОЗУ, GeForce 6200 128МБ, WinXP SP3.
|
(Offline)
|
|
24.04.2012, 12:22
|
#288
|
Бывалый
Регистрация: 22.12.2011
Сообщений: 844
Написано 150 полезных сообщений (для 275 пользователей)
|
Ответ: Vivo
Почти
А в предыдущей версии(кликабельно)?
Nite, блин, как у тебя всё просто. "А если он решит и назад прогуляться генерируешь новые чанки". Отлично! Игрок решил прогуляться за грибами, возвращается, а на месте его дома уже чистая земелька. Так ведь тоже не катит. Не выйдет тут массивами. По крайней мере так просто не выйдет.
И кстати, у Нотча всё разбито на файлы.
Пруф
"Игровой мир (или Карта) представляет собой иерархическую систему директорий и файлов, хранящую информацию о каждом блоке, предмете и существе в мире и об их состоянии."
|
(Offline)
|
|
24.04.2012, 13:20
|
#289
|
Дэвелопер
Регистрация: 04.09.2005
Адрес: Красноярск
Сообщений: 1,376
Написано 491 полезных сообщений (для 886 пользователей)
|
Ответ: Vivo
Какова цель игры? Может игроку и нет смысла на 10 тыщ клеток ходить, а достаточно сделать более насыщенное игровое действо на поле меньшего размера.
|
(Offline)
|
|
24.04.2012, 13:42
|
#290
|
Знающий
Регистрация: 06.12.2010
Адрес: Луганск
Сообщений: 252
Написано 112 полезных сообщений (для 166 пользователей)
|
Ответ: Vivo
В предыдущей версии фпс около 27, иногда падения до 5 - 10
При переходах между квадтатами постоянно подтормаживает.
__________________
AMD Sempron(tm) 1.41Ггц, 1024МБ ОЗУ, GeForce 6200 128МБ, WinXP SP3.
|
(Offline)
|
|
24.04.2012, 13:53
|
#291
|
Бывалый
Регистрация: 22.12.2011
Сообщений: 844
Написано 150 полезных сообщений (для 275 пользователей)
|
Ответ: Vivo
О целях дискуссии уже были.
Эту игру можно смело называть клоном майнкрафта, с более выраженным упором на выживание. Целей нету. Хотя нет, неверно. Цель такая же как в майнкрафте.
Бесконечная (МоКа, большая ) карта, скорее всего просто как испытание. Я сомневаюсь что и в майнкрафте всем так нужна бесконечная( большая ) карта. Просто ЧСВ, да игра солиднее выглядит. Согласитесь, фраза:" Ну карта не бесконечная, не смог ", звучит слабовато. А то что площадь мира в моей игре больше площади Земли в 36 164 раз звучит очень даже круто.
Последний раз редактировалось Nikich, 24.04.2012 в 19:56.
|
(Offline)
|
|
24.04.2012, 20:54
|
#292
|
Бывалый
Регистрация: 22.12.2011
Сообщений: 844
Написано 150 полезных сообщений (для 275 пользователей)
|
Ответ: Vivo
Фух, мозг что-то вообще варить перестал, как я за эти массивы взялся. Пожалуйста, можете помочь? Видимо мой способ не является самым лучшим, так как столько геморроя я ещё не испытывал. Сейчас я объясню свою задумку максимально подробно.
Возьмём массив Sector(6,6,15,15), первые два элемента которого отвечают за х и у чанка, относительно игрока(!). Для начала их заполним, взяв всю инфу из файлов. А вот как они должны рисоваться:
for i=0 to 6
for i1=0 to 6
for i2=0 to 15
for i3=0 to 15
drawimage block(Sector(i,i1,i2,i3)),((3-i)+chunk_x)*512+32*i2-camera_x,((3-i1)+chunk_y)*512+32*i3-camera_y
next
next
next
А теперь комментарии. block(Sector(i,i1,i2,i3)) - картинка, соответствующая блоку. ((3-i)+chunk_x)*512+32*i2-camera_x - на первый взгляд вообще дикая непонятная формула, в которой никто не захочет разбираться. Но всё достаточно просто. Игрок всегда должен находится в 3 чанке, относительно сектора, поэтому мы берём значение 3. ''-i'' мы берём я определение местоположения чанка относительно чанка в котором расположен игрок.
Таблица, поясняющая суть:
Больший квадрат - сектор, меньшие - чанки, центральный - тот в коором находится игрок. Как вы могли заметить, находить он в 3,3 - вот откуда берётся это i-3. ((3-i)+chunk_x)*512 - почему же 512? Потому что 512 - это количество пикселей, которое занимает один чанк(он состоит из 16 блоков, 32х32 каждый). i2*32 - координата блока, умноженная на 2 из-за его ширины. С осью у тоже самое.
Фух, с пробежкой мы разобрались. Теперь нам надо сделать так, чтобы если игрок переходит на следующий чанк, массив подгружал в себя новые чанки, и записывал в файл крайние чанки. Тут то и заключается проблема. Я вообще не знаю, как бы это красиво обыграть. Знаю как некрасиво - взять наш Sector, сделать четверной перебор, чтобы сдвинуть все чанки, потом ещё перебор на загрузки новых чанков, а потом ещё перебор на выгрузку старых. Остановился я на определении, в какую сторону нужно производить сдвиг. Вот моя функция для перемещения игрока:
Function UpdateCamera()
dy=KeyDown(31)-KeyDown(17)
dx=KeyDown(32)-KeyDown(30)
chunk_x=(camera_x+R1/2)/512
chunk_y=(camera_y+R2/2)/512
If (dx<>0 And dy=0) Or (dy<>0 And dx=0) Or (dy<>0 And dx<>0) gdx=dx:gdy=dy
If MilliSecs()-frame_timer>40 frame=frame+1:frame_timer=MilliSecs()
If frame>10 frame=0
next_chunk_x=(camera_x+dx*6*player_speed+R1/2)/512
next_chunk_y=(camera_y+dy*6*player_speed+R2/2)/512
If Not Collision()
If (dx=0 And dy<>0) Or (dx<>0 And dy=0)
camera_x=camera_x+dx*player_speed
camera_y=camera_y+dy*player_speed
Else
camera_x=camera_x+dx*diag_player_speed
camera_y=camera_y+dy*diag_player_speed
EndIf
EndIf
change_x=(camera_x+R1/2)/512-chunk_x
change_y=(camera_y+R2/2)/512-chunk_y
End Function
Поскольку название переменных у меня совпадает с их назначением, пояснять и думаю их не надо. Конечно, это выглядит так, будто я хочу чтоб вы мне написали готовые функции. Но это не так! Всё это я показал лишь для того, чтобы если вы захотели помочь мне, оперировали не просто словами, а теми переменными которые у меня используются.
З.Ы. особо интересует объяснения Nite'a. Как я понял, у него есть идея по реализации, но что-то я в ней не особо варю
|
(Offline)
|
|
24.04.2012, 21:00
|
#293
|
[object Object]
Регистрация: 01.08.2008
Адрес: В России
Сообщений: 4,355
Написано 2,471 полезных сообщений (для 6,853 пользователей)
|
Ответ: Vivo
Аттачи не прикрепились
__________________
Retry, Abort, Ignore? █
Intel Core i7-9700 4.70 Ghz; 64Gb; Nvidia RTX 3070
AMD Ryzen 7 3800X 4.3Ghz; 64Gb; Nvidia 1070Ti
AMD Ryzen 7 1700X 3.4Ghz; 8Gb; AMD RX 570
AMD Athlon II 2.6Ghz; 8Gb; Nvidia GTX 750 Ti
|
(Offline)
|
|
24.04.2012, 21:21
|
#294
|
Бывалый
Регистрация: 22.12.2011
Сообщений: 844
Написано 150 полезных сообщений (для 275 пользователей)
|
Ответ: Vivo
Пофикил.
|
(Offline)
|
|
26.04.2012, 07:55
|
#295
|
Дэвелопер
Регистрация: 04.09.2005
Адрес: Красноярск
Сообщений: 1,376
Написано 491 полезных сообщений (для 886 пользователей)
|
Ответ: Vivo
Я написал псевдо-код с комментариями, посмотри, может тебе пригодится такое.
Global chunks.TChunk[9] ;ближайшие к игроку чанки
Dim IMAGES%(100) ;масив для картинок-тайлов, идентификатор тайла соответствует идентификатору массива
;при старте уровня можно создать сколько-нибудь чанков
;при создании чанков указываем их соседей, тогда можно при движении в стороны сразу выцеплять соседей
Local xx%, yy%, countX% = 100, countY% = 100
Local ch.TChunk, ch2.TChunk
Dim temp.TChunk(countX*countY) ;тут временно сохраним чанки, чтоб соседей назначить
;Local dx# = 32*16, dy# = 32*16
Local index%
For xx = 0 To countX-1
For yy = 0 To countY-1
ch = CreateChunk(xx,yy)
temp(xx*yy) = ch
;тут соседей назначаем
If(xx > 0)
index = GetLinearIndex(xx-1,yy,countX) ;чанк слева от нового
ch2 = temp(index)
ch\chunks[0] = ch2
ch2\chunks[2] = ch ;а этому ставим правого соседа
EndIf
If(yy > 0)
index = GetLinearIndex(xx,yy-1,countX) ;чанк сверху от нового
ch2 = temp(index)
ch\chunks[1] = ch2
ch2\chunks[3] = ch ;а этому ставим нижнего соседа
EndIf
Next
Next
;назначаем начальные чанки из середины поля
Local x0% = Rand(40,60)
Local y0% = Rand(40,60)
For xx=0 To 2
For xx=0 To 2
chunks[xx*yy] = temp(GetLinearIndex(x0+xx,y0+yy,countX))
Next
Next
;в игровом цикле нужно рисовать только наши 9 чанков
For k% = 0 To 8
DrawChunk(chunks[k], scrollX, scrollY) ;рисуем с учётом скролла
Next
;при движении игрока в сторону - по достижении границы чанков - делаем сдвиг чанков
ShiftChunks(direction) ;direction - направление: 0-влево, 1-вверх, 2-вправо, 3-вниз
;получение индекса в одномерном массиве через значения индексов двухмерного
Function GetLinearIndex%(x%, y%, dimX%)
Return y*dimX + x
End Function
;сдвигаем, беря соседние в зависимости от направления
;и сохраняем то что уходит за экран
;если соседа нет, то загружаем из файла или генерируем
Function ShiftChunks(direction%)
Local ch.TChunk;, ch2.TChunk
Local xx%, yy%
Select(direction)
Case 0 ;сдвиг влево, сохраняем правый ряд
For yy=0 To 2
ch = chunks[GetLinearIndex(2,yy,3)]
SaveChunk(ch)
chunks[GetLinearIndex(2,yy,3)] = GetNextChunk(ch, 0) ;получаем соседний чанк
Delete(ch) ;и удаляем тех кто ушёл за экран
Next
Case 1 ;сдвиг вверх, сохраняем нижний ряд
For xx=0 To 2
SaveChunk(chunks[GetLinearIndex(xx,2,3)])
Next
Case 2 ;сдвиг вправо, сохраняем левый ряд
For yy=0 To 2
SaveChunk(chunks[GetLinearIndex(0,yy,3)])
Next
Case 3 ;сдвиг вниз, сохраняем верхний ряд
For xx=0 To 2
SaveChunk(chunks[GetLinearIndex(xx,0,3)])
Next
End Select
For xx=0 To 2
For xx=0 To 2
chunks[xx*yy] = temp(GetLinearIndex(x0+xx,y0+yy,countX))
Next
Next
End Function
;получаем соседний чанк, если он есть
;если нет, то пробуем загрузить из файла
;если файла нет, то генерируем новый
Function GetNextChunk.TChunk(ch.TChunk, dir%)
Local chunk.TChunk = ch\chunks[dir]
If(chunk <> Null) Then Return chunk
;пробуем из файла
Local path$
If(dir = 0) ;влево идём
path$ = "ch-"+(ch\cellX-1)+"-"+ch\cellY+".txt"
Else If(dir = 0) ;влево вверх
path$ = "ch-"+ch\cellX+"-"+(ch\cellY-1)+".txt"
Else If(dir = 0) ;влево вправо
path$ = "ch-"+(ch\cellX+1)+"-"+ch\cellY+".txt"
Else If(dir = 0) ;влево вниз
path$ = "ch-"+ch\cellX+"-"+(ch\cellY+1)+".txt"
EndIf
If(FileType(path) = 1)
;грузим
chunk = New TChunk
LoadChunk(chunk, path)
Return chunk
Else
chunk = GenerateChunk() ;генерируем
EndIf
;здесь нужно указать соседство левого с правым и т.д. для всех направлений
;и другие параметры/ cellX, cellY
Return chunk
End Function
Function GenerateChunk.TChunk()
End Function
Function LoadChunk(ch.TChunk, path$)
End Function
Function SaveChunk(ch.TChunk)
;тут записываем в файл с именем ch-x-y.txt инфу о тайлах
;x - ch\cellX
;y - ch\cellY
End Function
;создание чанка
Function CreateChunk.TChunk(cellX%, cellY%, dimX%=15, dimY%=15, size%=32)
Local ch.TChunk = New TChunk
ch\dimX = dimX ;16-1
ch\dimY = dimY ;16-1
ch\size = size
ch\cellX = cellX
ch\cellY = cellY
ch\x0 = cellX*size*(dimX+1)
ch\y0 = cellY*size*(dimY+1)
GenerateTiles(ch) ;генерим тайлики в чанк
Return ch
End Function
;генерим тайлы для чанка - если есть файл с таким чанком то надо загрузить из файла
Function GenerateTiles(ch.TChunk)
Local xx%, yy%
For xx = 0 To ch\dimX
For yy = 0 To ch\dimY
ch\imagesId[xx*yy] = Rand(0, IMAGES_COUNT-1) ;в реале конечно простой рандом не прокатит, это пример получения идентификатора картинки
Next
Next
End Function
;рисование чанка, х и у - сдвиг, который позволяет скроллировать карту
Function DrawChunk(chunk.TChunk, x#, y#)
Local xx%, yy%
For xx = 0 To chunk\dimX
For yy = 0 To chunk\dimY
DrawImage(IMAGES(chunk\imagesId[xx*yy]), x+chunk\x0, y+chunk\y0)
Next
Next
End Function
Type TChunk
Field cellX%, cellY% ;индекс чанка в глобальном мире
Field x0#, y0# ;координаты левого верхнего угла, относительно которых будем рисовать
Field dimX%, dimY% ;количество тайлов в чанке по х и по у, н-р: 16x16, или на 1 меньше хранить, чтоб в циклах не отнимать каждый раз
Field size% ;размер тайла, н-р: 32
Field imagesId%[16*16] ;идентификаторы картинок-тайлов. т.к. двумерный массив тут нельзя добавить, в одномерный вставим
Field chunks.TChunk[4] ;соседи слева-справа-сверху-снизу
End Type
|
(Offline)
|
|
Сообщение было полезно следующим пользователям:
|
|
27.04.2012, 15:47
|
#296
|
Бывалый
Регистрация: 22.12.2011
Сообщений: 844
Написано 150 полезных сообщений (для 275 пользователей)
|
Ответ: Vivo
А теперь сколько фпс? Делал всё же по своему, но с массивами. Заметен не плавный переход в те области, где чанков ещё нету.
|
(Offline)
|
|
28.04.2012, 06:31
|
#297
|
Дэвелопер
Регистрация: 04.09.2005
Адрес: Красноярск
Сообщений: 1,376
Написано 491 полезных сообщений (для 886 пользователей)
|
Ответ: Vivo
фпс: 19-29, в основном 19-20, комп 4 ядра, но видео встроенная AMD 760G.
Я смотрю у тебя главный герой в картинке идёт в одну сторону, а в игре во все, то есть программно поворачивается, это тоже тормоза прибавляет. Как сказано в справке блитца для RotateImage: This command is not fast enough to render rotations in real time!
Но ты уже в сторону блитцмакса идёшь, так что поворот перестанет быть проблемой.
|
(Offline)
|
|
28.04.2012, 08:49
|
#298
|
Бывалый
Регистрация: 22.12.2011
Сообщений: 844
Написано 150 полезных сообщений (для 275 пользователей)
|
Ответ: Vivo
Я риалтаймом и не вращаю. Делаю массив, и в него вбиваю уже повернутые картинки, а потом рисую уже эти картинки, в зависимости от направления игрока.
З.Ы. Это точно из-за видеокарты, я забыл сделать так, чтобы рисовались только те блоки что видны
|
(Offline)
|
|
Сообщение было полезно следующим пользователям:
|
|
28.04.2012, 14:57
|
#299
|
Unity/C# кодер
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений (для 5,323 пользователей)
|
Ответ: Vivo
Стабильно 45 FPS - core i5 со встроенным видео.
|
(Offline)
|
|
28.04.2012, 16:38
|
#300
|
Бывалый
Регистрация: 16.09.2011
Сообщений: 863
Написано 257 полезных сообщений (для 546 пользователей)
|
Ответ: Vivo
59 fps, i5 2500k 3.3, 4 ядра
Загрузка видна только 1 раз, когда пересекаю самую первую зону. Возможно в этот момент генерируется многа файлов сразу, поэтому так. А при остальных пересечениях не генерируются, пока не дойду до определенной зоны.
|
(Offline)
|
|
Ваши права в разделе
|
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 19:06.
|