Вторник, 19 Марта 2024, 05:57

Приветствую Вас Гость

[ Новые сообщения · Игроделы · Правила · Поиск ]
  • Страница 1 из 1
  • 1
Форум игроделов » Программирование » Общие обсуждения программистов » Хранение локации в БД
Хранение локации в БД
KVinSДата: Вторник, 08 Мая 2012, 00:31 | Сообщение # 1
постоянный участник
Сейчас нет на сайте
Привет!
Натолкнулся на трудность в процессе разработки.
Не знаю как хранить локации (двумерный int массив) в БД
Если использовать таблицы для клеток, получается, что 5 полей (id, x, y, локация, тип) и множество записей. (для локации 100х100 10000 записей)
Кто может чего посоветовать?


Игра про лесных котов
vicmadДата: Вторник, 08 Мая 2012, 00:33 | Сообщение # 2
постоянный участник
Сейчас нет на сайте
Либо красить все в синий цвет, либо генератор карты писать cool
KVinSДата: Вторник, 08 Мая 2012, 00:39 | Сообщение # 3
постоянный участник
Сейчас нет на сайте
Quote (vicmad)
Либо красить все в синий цвет, либо генератор карты писать

Вы бы что ли в вопрос вникнули.


Игра про лесных котов
TimKruzДата: Вторник, 08 Мая 2012, 00:56 | Сообщение # 4
старожил
Сейчас нет на сайте
Quote (KVinS)
что 5 полей (id, x, y, локация, тип)

X и Y - координаты в массиве, по ним можно определить (вместо id) поле... Локация - номер/имя массива. Тип - один/два байта.
Получаем для поля 100*100 чуть менее 10/20 КБайт информации. В чём проблема сохранить этот массив?
Я не знаком с базами данных, но, думаю, можно записывать как [№ клетки][тип клетки], и отдельно записать количество столбцов на карте. А локации разделять по таблицам или ещё как-то.
Вообще лучше всего всё это добро хранить в файлах - проблем меньше, просто записываешь параметры [тип клетки] в одну строку... wacko


KVinSДата: Вторник, 08 Мая 2012, 01:15 | Сообщение # 5
постоянный участник
Сейчас нет на сайте
TimKruz, id для верности, а файлы использовать не хочу.

Игра про лесных котов
ЙакудДата: Вторник, 08 Мая 2012, 02:52 | Сообщение # 6
участник
Сейчас нет на сайте
KVinS, Тут все зависит от того какую бд ты используешь. 10 000 записей для MySQL это не много. Запросы же не постоянно к ней будут производиться!?

"Хороший художник – копирует, гениальный – ворует!" — Pablo Picasso
.blanco 2.0
KVinSДата: Среда, 09 Мая 2012, 01:47 | Сообщение # 7
постоянный участник
Сейчас нет на сайте
Quote (Йакуд)
KVinS, Тут все зависит от того какую бд ты используешь. 10 000 записей для MySQL это не много. Запросы же не постоянно к ней будут производиться!?

MySQL

Только при включение сервера


Игра про лесных котов
QuieteroksДата: Среда, 09 Мая 2012, 02:23 | Сообщение # 8
частый гость
Сейчас нет на сайте
KVinS, вы можете какую нибудь функцию написать для преобразования массива в строку и функцию распаковки обратно в массив?
Это наиболее часто встречающийся вариант хранения таких данных в БД. Просто пакуете массив в строку к примеру 145|25|33;10|26|33;10|27|33 и спокойно записываем в одну ячейку базы.
Если же вы хотите иметь возможность менять каждую клеточку, и использовать для этого обновление одной ячейки в базе, то конечно можно и каждую клетку хранить отдельно. Но проще все в одном, а при каком нибудь изменении просто вновь шифруется и обновляется опять таки одно поле. Тем более у Вас загрузка идет в момент запуска, оперативно не получится менять поля. И в итоге на каждую карту у вас одна строчка (локация, карта, тип).


Если вам все равно где вы находитесь, значит вы еще не заблудились.
TimKruzДата: Среда, 09 Мая 2012, 16:20 | Сообщение # 9
старожил
Сейчас нет на сайте
Quote (Quieteroks)
KVinS, вы можете какую нибудь функцию написать для преобразования массива в строку и функцию распаковки обратно в массив?
Это наиболее часто встречающийся вариант хранения таких данных в БД. Просто пакуете массив в строку к примеру 145|25|33;10|26|33;10|27|33 и спокойно записываем в одну ячейку базы.

В PHP для этого есть implode() и explode(). Первая объединяет, вторая разбивает.
Да, как-то я о таком способе не подумал... biggrin Но я же не знал, что запросы будут идти
Quote (KVinS)
Только при включение сервера.

Тогда логичнее упаковать в строку. Но вот вопрос, эта строка будет весить примерно 30-70 КБ для поля 100*100 - потому что на число 1-3 символа и на разделитель 1 символ.
Хотя можно сделать иначе. Если параметр изменяется в пределах 256, то хватит символа на значение (для 65536 вариантов - 2 байта). Просто берём значащий параметр (в данном случае - тип клетки поля) и представляем его в виде символа (или двух), код которого равен значению параметра. В PHP и некоторых других языках это делает функция chr(). Далее просто объединяем в одну строку, подряд, без разделителей. Получаем ряд значений массива в виде строки. Чтобы расшифровать, нужно знать число столбцов (или строк) и сколько байт занимает значение одной ячейки. Соответственно разбиваем строку на символы по группам (группа - строка или столбец массива, смотря в каком порядке записывали) и переводим в числа (функция ord() в PHP и некоторых других языках).
Для примера:
1. Имеем массив значений клеток поля:
Code
65 66 67
68 69 70
71 72 73

2. Переводим в строку символов:
Code
65=A, 66=B, 67=C, ... 73=I.

3. Получаем результат:
Code
ABCDEFGHI

4. Дописываем в начале строки символ равный 3, и отправляем его в БД.
И обратно:
1. Получаем строку из БД.
2. Переводим символы обратно в значения.
3. Зная (по первому символу), что в строке массива у нас по 3 значения (3 столбца в массиве), получаем исходный массив.


QuieteroksДата: Среда, 09 Мая 2012, 16:43 | Сообщение # 10
частый гость
Сейчас нет на сайте
TimKruz, в php есть более хороший способ хранения. base64_encode(serialize(array)) Размер конечно больше получится, но качество восстановления массива гораздо выше. Да и если не ошибаюсь, то implode не обрабатывает многомерные вложенные массивы и не сохраняет ключи, если они нужны.
А так же вряд ли в php это реализуется. Если при загрузке сервера карта открывается.
А вариант с цифровым преобразованием чисел методом chr/ord интересно. Но ограничение на размер карты повышается.
Тогда могу предложить еще цифровые значения преобразовывать в шестнадцатеричные, что их значительно в объеме уменьшит. Конечно не 1 символ, но из 3 уже будет 2.


Если вам все равно где вы находитесь, значит вы еще не заблудились.
ЙакудДата: Среда, 09 Мая 2012, 18:59 | Сообщение # 11
участник
Сейчас нет на сайте
Ну вообще как вариант хранить карту в бинарниках.. Еще меньше места будет занимать и довольно просто парсить будет..
Все же я думаю, что хранение пары сотен тысяч записей не большая проблема для БД, тем более что запросы не будут очень часто производиться.


"Хороший художник – копирует, гениальный – ворует!" — Pablo Picasso
.blanco 2.0
QuieteroksДата: Среда, 09 Мая 2012, 20:44 | Сообщение # 12
частый гость
Сейчас нет на сайте
Йакуд, если планируется только одна карта, то да. А когда таких карт будет свыше 100? 100 * 10 000 = 10 000 000
Запуск будет весьма длителен для такого запроса. Ладно еще что это всего то запуск и инициализация карт, может не так часто.
Но мы же не знаем, что там планируется. Может при запуске командной игры это будет. Один запуск один запрос. И выборка из более чем трех миллиона записей уже проблематично может быть для некоторых систем.
И опять таки, смотря как реализуется получение данных из БД. По опыту php знаю, что цикл по обработке 1000 записей уже не приятная штука для быстродействия. С++ конечно с этим в десятки раз быстрее справится.
Мне кажется обработать уже полученные данные из строки будет работать быстрее чем построчный из БД.


Если вам все равно где вы находитесь, значит вы еще не заблудились.
KVinSДата: Среда, 09 Мая 2012, 22:48 | Сообщение # 13
постоянный участник
Сейчас нет на сайте
Я планировал хранить в строке.
Но получается невесело ~150 000 символов.
Просто в строку не влезает.


Игра про лесных котов
AssasinДата: Среда, 09 Мая 2012, 23:42 | Сообщение # 14
web-coder
Сейчас нет на сайте
Пример полной карты:
[x,y,type]
Code
1,1,1;20,13,2|12

type 1 - непроходимая ячейка
type 2 - телепорт на локацию 12
Это вся карта, в которой остальные 100*100-2 ячейки свободные, т.е. = 0
Подготавливаем карту для использования в редакторе к примеру:
- Читаем карту и разбиваем её по символу ; ($a = explode(";",$map))
- Создаем цыкл по х и внутри еще один цыкл по у
- Создаем двумерный массив маску $b[x][y] = 0
- Создаем цыкл по длине массива $a
- Заполняем маску $b[$a[i][x]][$a[i][y]] = $a[i][type]

Вот и все. Инфы в файле меньше, остальное на совести программы.
ТритонДата: Пятница, 11 Мая 2012, 08:54 | Сообщение # 15
постоянный участник
Сейчас нет на сайте
Жалкие 10 000 записей - это микроскопическая база. Но даже её можно сократить, если один тип клетки принять за дефолт и подразумевать при отсутствии записи.

Не всё так плохо, как оно есть на самом деле.

Сообщение отредактировал Тритон - Пятница, 11 Мая 2012, 08:55
TimKruzДата: Пятница, 11 Мая 2012, 22:33 | Сообщение # 16
старожил
Сейчас нет на сайте
Quote (Assasin)
Вот и все. Инфы в файле меньше, остальное на совести программы.

Я так понял, что у тебя первые два числа - x и y, третье - тип, и ещё символы-разделители. Для почти пустой карты это, возможно, идеальный вариант, но кто захочет играть на карте 100*100, если в ней 9998 клеток - чистые (трава), плюс один камень и один телепорт? biggrin
Тут нужно рассчитать, при какой заполненности разными типами клеток карты данный метод себя оправдывает (должен быть определённый порог, после которого твой метод будет поглощать гораздо больше памяти).
Quote (Quieteroks)
А вариант с цифровым преобразованием чисел методом chr/ord интересно. Но ограничение на размер карты повышается.

На размер - нет ограничения. А количество типов - два байта обеспечат чуть больше 65 тысяч типов клеток - для игры более чем достаточно.
Quote (Quieteroks)
Тогда могу предложить еще цифровые значения преобразовывать в шестнадцатеричные, что их значительно в объеме уменьшит. Конечно не 1 символ, но из 3 уже будет 2.

Мне кажется, преобразование 10->16 будет обрабатываться дольше, чем число->символ... И потом, два байта (00-FF) хранят в таком случае только 256 значений, что нерационально (в два раза меньше возможного).
Quote (KVinS)
Я планировал хранить в строке.
Но получается невесело ~150 000 символов.

А ты разбей на несколько строк.


KVinSДата: Суббота, 12 Мая 2012, 01:00 | Сообщение # 17
постоянный участник
Сейчас нет на сайте
Ну у меня не всё так просто =)
Структура похожа на эклипс
То есть хранить то много. Терзаюсь блин. Вроде БД привычнее и удобнее, но и в файлах плюсы есть.
Code

Эффекты клетки

Над декор 2
Над декор 1

Декор 2
Декор 1
Фон


Игра про лесных котов
ТритонДата: Суббота, 12 Мая 2012, 10:03 | Сообщение # 18
постоянный участник
Сейчас нет на сайте
Quote (TimKruz)
Я так понял, что у тебя первые два числа - x и y, третье - тип, и ещё символы-разделители. Для почти пустой карты это, возможно, идеальный вариант, но кто захочет играть на карте 100*100, если в ней 9998 клеток - чистые (трава), плюс один камень и один телепорт
Чистых клеток и меньше ста быть не может и далеко не факт, что их меньше тысячи, а это уже даёт экономию на размере хоть базы, хоть файла.

Добавлено (12.05.2012, 09:57)
---------------------------------------------
Quote (Quote (Quieteroks))
Тогда могу предложить еще цифровые значения преобразовывать в шестнадцатеричные, что их значительно в объеме уменьшит. Конечно не 1 символ, но из 3 уже будет 2.
В базе они и так не в текстовой форме хранятся, а двоичным числом.

Добавлено (12.05.2012, 10:00)
---------------------------------------------

Quote (TimKruz)
Мне кажется, преобразование 10->16 будет обрабатываться дольше, чем число->символ... И потом, два байта (00-FF) хранят в таком случае только 256 значений, что нерационально (в два раза меньше возможного).
Это всего навсего табличное преобразование, оно выполняется максимально быстро, а любой int при вводе с клавы и выводе на экран/печать требует преобразования в двоичную форму или по тому же табличному алгоритму, или циклом, что как раз медленнее.

Добавлено (12.05.2012, 10:03)
---------------------------------------------

Quote (KVinS)
Я планировал хранить в строке.
Но получается невесело ~150 000 символов.
А в чём проблема увеличить? Скажем до полутора миллионов?


Не всё так плохо, как оно есть на самом деле.

Сообщение отредактировал Тритон - Суббота, 12 Мая 2012, 09:57
KVinSДата: Суббота, 12 Мая 2012, 10:53 | Сообщение # 19
постоянный участник
Сейчас нет на сайте
Quote (Тритон)
А в чём проблема увеличить? Скажем до полутора миллионов?

Оо
Размер строки. И кстати это получается больше макс длины.

Строение игры подразумевает одну полностью занятую плоскость и несколько частично.


Игра про лесных котов
ТритонДата: Суббота, 12 Мая 2012, 17:21 | Сообщение # 20
постоянный участник
Сейчас нет на сайте
У лонгострок максимум или 2 гигасимвола, или вообще нет явного формального ограничения, так как всё адресное пространство за таковое считать нельзя, его всё равно достичь размером одного данного не получится.

Добавлено (12.05.2012, 17:21)
---------------------------------------------
Quote (KVinS)
Структура похожа на эклипс
То есть хранить то много.
Десять килоклеток - это микроскопически мало. Две координаты по байту, байта 4 на идентификтор клетки, столько же на идентификатор карты, два байта на идентификатор типа клетки=12 байт на клетку, 120 килобайт без какого либо сжатия. Ты фотку то меньше 3-х мегабайт себе представляешь? А это карта. И от одного до нескольких процентов можно ещё с экономить на дефолтотипе.


Не всё так плохо, как оно есть на самом деле.

Сообщение отредактировал Тритон - Суббота, 12 Мая 2012, 17:22
Форум игроделов » Программирование » Общие обсуждения программистов » Хранение локации в БД
  • Страница 1 из 1
  • 1
Поиск:

Все права сохранены. GcUp.ru © 2008-2024 Рейтинг