Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > разработка игр, графический дизайн и моделирование > Gamedev - cоздание игр: Unity, OpenGL, DirectX
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 05.10.2012, 16:24   #21
Slin
Пользователь
 
Регистрация: 06.09.2012
Сообщений: 14
По умолчанию

phomm, может и в виде байтов будет проще, но, к сожалению, пока я не знаком с ними.
Цитата:
Сообщение от Beermonza Посмотреть сообщение
Показать пример, или не нужно сложностей? ...это эффективнее.
Да, конечно, если можно, то лучше показать пример. А то от прочитанного глаза на лоб вылезли, но надо же когда-то начинать, волков бояться - в лес не ходить.
Зы: с потоками раньше работал немного.
Я так понимаю, данные в ОЗУ будут храниться? Если что, я хотел реализовать сохранение карты на ЖД (Харде).

Последний раз редактировалось Slin; 05.10.2012 в 16:35.
Slin вне форума Ответить с цитированием
Старый 05.10.2012, 21:23   #22
phomm
personality
Старожил
 
Аватар для phomm
 
Регистрация: 28.04.2009
Сообщений: 2,882
По умолчанию

Мы с Beermonza говорим примерно об одном, работа с файлами из байтов через файлстрим или мемористрим и делается. Данные вообще удобно так хранить - на диск и с диска читать и писать можно методами файлстрима, и загружать сразу в игровой массив без обработки какой-либо, т.е. 1 байт (ну или другой тип) прямиком загружается в массив , карты например, только в случае с 2мерной картой надо просто регулировать индексатор массива ( с помощью div mod )
Схемы загрузки подобным образом я нередко приводил, например тут и продолжение тут
phomm вне форума Ответить с цитированием
Старый 06.10.2012, 15:50   #23
Beermonza
Инженер ИС
Старожил
 
Аватар для Beermonza
 
Регистрация: 13.12.2006
Сообщений: 2,671
По умолчанию

Цитата:
Сообщение от Slin Посмотреть сообщение
Я так понимаю, данные в ОЗУ будут храниться? Если что, я хотел реализовать сохранение карты на ЖД (Харде).
Да, конечно, данные будут в памяти, и ты волен делать с ними всё, что требуется, ...тем более, если немного знаком с потоками, будет проще понять.

Вначале нужна переменная:

Код:
var
  MapFileStream: TMemoryStream;
Далее перед считыванием в этот поток данных с файла, нужно создать экземпляр:

Код:
  // создание потока
  MapFileStream := TMemoryStream.Create;
Есть стандартные процедуры для чтения_в/записи_из потоков:

Код:
  // чтение файла в поток
  MapFileStream.LoadFromFile('Map.gmf');

  // запись из потока в файл
  MapFileStream.SaveToFile('Map.gmf');
Map.gmf - некий байтовый файл, находящийся в каталоге исполнительного EXE проекта, или путь, полный или сокращенный.

gmf - Game Map File, аббревиатура, которую сочиняешь по ходу создания проекта, для типизирования файлов.

Когда поток не нужен, нужно от него избавиться, дабы не занимать память:

Код:
  // освободить поток
  MapFileStream.Free;
Поток обрабатывается блоками и нужно следить за позицией начала считывания, устанавливать перед каждым обращением к потоку:

Код:
  // поток в начало
  MapFileStream.Position := 0;

  // поток на 10-й байт
  MapFileStream.Position := 9;

  // поток на байт, позиция которого в переменной i_Map (Integer +)
  MapFileStream.Position := i_Map;
Считывание и запись:

Код:
  // считать в переменную n_Map байт данных
  MapFileStream.Read(n_Map, 1);

  // считать поток в динамический массив MapMas (Array Of Byte)
  MapFileStream.Read(MapMas[0], MapFileStream.Size);

  // записать в поток значение переменной n_Map
  MapFileStream.Write(n_Map, 1);

  // записать в поток динамический массив MapMas
  MapFileStream.Write(MapMas[0], MapDataLength);
Динамические массивы создаются и освобождаются стандартно:

Код:
  // выделить блок памяти
  GetMem(MapMas, MapDataLength);
  
  // освободить память, занятую массивом
  FreeMem(MapMas);
Всё, начинай создавать код, ...если не получится сразу, выкладывай сюда, поможем.

...я не написал готовый код, наверное понятно почему.
Руководитель проекта MMO 2D RPG: Настоящее имя Денис Стрижак (10.05.1981-6.02.2019) Мир духу его

Последний раз редактировалось Beermonza; 06.10.2012 в 15:58.
Beermonza вне форума Ответить с цитированием
Старый 07.10.2012, 12:20   #24
Slin
Пользователь
 
Регистрация: 06.09.2012
Сообщений: 14
По умолчанию

Что-то не получается у меня, ошибку выдает при выполнении процедуры загрузки, при сохранении - все хорошо.
Но, обо всем по порядку. Для лучшего понятия, я создал простую программу, в которой в первое поле вводится число, оно сохраняется в файли через поток, а во втором поле, по нажатию кнопки, оно же и выводится.
Код:
procedure TForm1.Button1Click(Sender: TObject);  //Запись
var
  Stream: TMemoryStream;
  per: Byte;
begin
  per := StrToInt(Edit1.Text);
  Stream := TMemoryStream.Create;
  Stream.Write(per, 2);
  Stream.SaveToFile('Str.chc');
  Stream.Free;
end;

procedure TForm1.Button2Click(Sender: TObject);  //Чтение
var
  Stream: TMemoryStream;
  a: Byte;
begin
  Stream := TMemoryStream.Create;
  Stream.LoadFromFile('Str.chc');
  Stream.Read(a, Stream.Size);
  Edit2.Text := IntToStr(a);
  Stream.Free;
end;
Эта программа помогла мне несколько глубже вникнуть в тему.
А вот в моей игре, как я уже сказал ранее, почему-то не работает. Выдает ошибку (Фото ошибки прикрепил к сообщению). Вот процедура сохранения:
Код:
procedure TForm1.SaveG;    //Сохранение
var
  MapFileStream: TMemoryStream;
  i, j:Integer;
  z:Byte;
begin
  MapFileStream := TMemoryStream.Create;
  z:=3;
  for i := 0 to 15 do
    for j := 0 to 15 do
      begin
        MapFileStream.Write(z, 255);   //z использую для наглядности.
      end;
  MapFileStream.SaveToFile('Map.gmf');  //Запись
  MapFileStream.Free;
end;
А вот процедура загрузки, в ней судя по всему и есть ошибка:
Код:
procedure TForm1.LoadSG;       //Занрузка
var
  MapFileStream: TMemoryStream;
  i, j:integer;
begin
  MapFileStream := TMemoryStream.Create;  //Создание
  MapFileStream.LoadFromFile('Map.gmf');  
  MapFileStream.Position := 0;
  for i := 0 to 15 do
    for j := 0 to 15 do
    begin
      MapFileStream.Read(Map_Mass[i, j].View, MapFileStream.Size);
      if Map_Mass[i, j].View<>0 then  //если это не пустая ячейка (View=0 у земли, а земля- пусто)
      Map_mass[i,j].Texture:=shovel; //текстура лопаты так же для наглядности
    end;
   MapFileStream.Free;
end;

UPD:

Так, свою ошибку нашел, она была в этой строке:
Код:
MapFileStream.Write(z, 255);
Совершил ее из-за незнания, если честно, то и сейчас я не очень понимаю, почему вместо 255 (Размер 2д массива у меня, думал он нужен), нужно ставить 1, но факт остается фактом - с единицей работает, с иными числами - ошибка. Не могли бы Вы объяснить, что задает этот параметр? Длину чего он задает?

UPD2 (Опять вопрос):
А с чем может быть связано, что он не по порядку считывает? Может разделитель какой нужен? Создал я два "отладочных" мемо, на входе записывается это:
Цитата:
x=0 y=0 View: 13
x=0 y=1 View: 10
x=0 y=2 View: 19
x=0 y=3 View: 27
x=0 y=4 View: 10
x=0 y=5 View: 0
x=0 y=6 View: 6
x=0 y=7 View: 6
x=0 y=8 View: 2
x=0 y=9 View: 0
А на выходе получаю это:
Цитата:
x=0 y=0 View: 13
x=0 y=1 View: 0
x=0 y=2 View: 0
x=0 y=3 View: 0
x=0 y=4 View: 0
x=0 y=5 View: 0
x=0 y=6 View: 0
x=0 y=7 View: 0
x=0 y=8 View: 0
x=0 y=9 View: 0
Опять же бросаю код (Загрузка игры):
Map_Mass[y, x].View - это вид игрового объекта, их у меня 28, тип переменной View: byte.
Код:
procedure TForm1.LoadSG;       //Загрузка сохраненной игры
var
  MapFileStream: TMemoryStream;
  i, j:integer;
  x, y:Integer;
begin
  MapFileStream := TMemoryStream.Create;  //Создание
  MapFileStream.LoadFromFile('Map.gmf');  //чтение
  ShowMessage('Объем: '+IntToStr(MapFileStream.Size));
  MapFileStream.Position := 0;
  for x := 0 to 15 do
    for y := 0 to 15 do
    begin
      MapFileStream.Read(Map_Mass[y, x].View, MapFileStream.Size);
      memo1.Lines.Add('x='+IntToStr(x)+' y='+IntToStr(y)+' View: '+IntToStr(Map_Mass[y, x].View));
    end;
   MapFileStream.Free;
end;
Сохранение:
Код:
procedure TForm1.SaveG;    //Сохранение игры
var
  MapFileStream: TMemoryStream;
  x, y:Integer;
begin
  MapFileStream := TMemoryStream.Create;
  memo2.Lines.Clear;
  for x := 0 to 15 do
    for y := 0 to 15 do
      begin
        MapFileStream.Write(map_mass[y,x].View, 1);   //map_mass[i,j].View
        Memo2.Lines.Add('x='+IntToStr(x)+' y='+IntToStr(y)+ ' View: '+IntTostr(map_mass[y, x].View));
     end;
  MapFileStream.SaveToFile('Map.gmf');  //Запись
  MapFileStream.Free;
end;
Подскажите, пожалуйста, где мой косяк?
Изображения
Тип файла: jpg Ошибка1.jpg (338.4 Кб, 147 просмотров)
Тип файла: jpg Ошибка2.jpg (467.3 Кб, 148 просмотров)

Последний раз редактировалось Slin; 07.10.2012 в 19:30.
Slin вне форума Ответить с цитированием
Старый 07.10.2012, 19:34   #25
phomm
personality
Старожил
 
Аватар для phomm
 
Регистрация: 28.04.2009
Сообщений: 2,882
По умолчанию

Без проекта тяжело сказать, но то, что я увидел по скрину - предполагаю массив не создан, надо вызвать до чтения из потока setlength(Map_Mass, 16, 16)
Ну и опять же , где константы под энто дело )) ?
phomm вне форума Ответить с цитированием
Старый 07.10.2012, 20:21   #26
Slin
Пользователь
 
Регистрация: 06.09.2012
Сообщений: 14
По умолчанию

Вот проект: Garden.rar.
Если честно, то мне опять стыдно за мой код, но обещаю, что исправлю его.
Только разрешение надо подправить, я делал под свое 1280*1024.

UPD:
Свою проблему решил созданием еще одного массива в самой процедуре загрузки, теперь все хорошо. Вот ее вид:
Код:
procedure TForm1.LoadSG; // Занрузка
var
  MapFileStream: TMemoryStream;
  i, j: Integer;
  X, Y: Integer;
  map_mas: array [0..15,0..15] of byte;   //Новый массив.
begin
  MapFileStream := TMemoryStream.Create; // Создание
  MapFileStream.LoadFromFile('Map.gmf'); // чтение
  //ShowMessage('Объем: ' + IntToStr(MapFileStream.Size));
  MapFileStream.Position := 0;
  for X := 0 to 15 do
    for Y := 0 to 15 do
    begin
      MapFileStream.Read(Map_mas[Y, X], MapFileStream.Size);
      { if Map_Mass[i, j].View<>0 then
        Map_mass[i,j].Texture:=shovel; }
      Memo1.Lines.Add('x=' + IntToStr(X) + ' y=' + IntToStr(Y) + ' View: ' +
        IntToStr(Map_mas[Y, X]));
    end;
  MapFileStream.Free;
end;

Последний раз редактировалось Slin; 07.10.2012 в 22:33.
Slin вне форума Ответить с цитированием
Старый 08.10.2012, 01:48   #27
Beermonza
Инженер ИС
Старожил
 
Аватар для Beermonza
 
Регистрация: 13.12.2006
Сообщений: 2,671
По умолчанию

Slin, ты не понял как читать данные с потока.

MapFileStream.Read(Map_mas[Y, X], MapFileStream.Size); - ошибка на пустом месте. Size возвращает размер потока в байтах, т.е. файла. Читать нужно по 1 байту, или по сколько у тебя клетка. Position потока двигается самостоятельно при каждом чтении на величину считываемого фрагмента, поэтому нужно ставить его при начале считывания и далее он сам двигается. Переделай.

...я не все почитал, сейчас нет времени, завтра все посмотрю.
Руководитель проекта MMO 2D RPG: Настоящее имя Денис Стрижак (10.05.1981-6.02.2019) Мир духу его

Последний раз редактировалось Beermonza; 08.10.2012 в 01:50.
Beermonza вне форума Ответить с цитированием
Старый 08.10.2012, 09:32   #28
phomm
personality
Старожил
 
Аватар для phomm
 
Регистрация: 28.04.2009
Сообщений: 2,882
По умолчанию

Такс, на работе с утра прогнал проект.
Как уже заметил Beermonza, косяк с чтением не того размера данных приводил к ошибкам чтения.
Помимо этого была ещё одна существенная проблема. Пока я старался понять её причину - переписал начатую, но незаконченую буферизацию, а то программа постоянно грузила картинки с диска, отрисовка с перезаписыванием в текстуры. Я сделал, что текстуры неизменны, а вся отрисовка ведётся в буфер, и только он выводится.
Ну а ошибка - использование object вместо record . Обжект - устаревший тип и не рекомендуется к использованию. Если делать по простому - то использовать record, а если хочется посложнее - классы (полностью поддерживающие ООП вместо обжекта)

Насчёт грамотного кода - конечно же повыводить многое в константы. Но ещё лучше произвести инкапсуляцию всяких вспомогательных вещей. Первее всего просятся "кнопки" - можно завести сущность кнопки - в ней указать положение и размер (4 числами - 2 координаты точек - левверх и правниз, а можно координаты левверха и ширина+высота) и текстуру. Написать функцию, которой передавать координаты мыши, а она будет выдавать какая кнопка в этих координатах. В самой функции просто организовать цикл по кнопкам с 1 (одним) IF, а не с 20 как сейчас.

Ещё мне не очень нравится проверка по текстурам, а не по кодам (которые потом можно перевести в иные сущности, типа енумов, а текстуры - нет)
Ну и хочу сразу сказать, что скорее всего, разные сущности - цветы, посадки и интерьер, или ещё какие, да и на случай переработки тоже, надо бы хранить в разных наборах, а клетку карты сделать хранящей код для каждой категории (чтобы, например, на плитку посадить кошку)

Вот код исправленного модуля - в приложении.
Вложения
Тип файла: zip Unit1.zip (2.5 Кб, 17 просмотров)
phomm вне форума Ответить с цитированием
Старый 08.10.2012, 17:08   #29
Slin
Пользователь
 
Регистрация: 06.09.2012
Сообщений: 14
По умолчанию

Beermonza, phomm,
Спасибо, код исправил, сделал сохранение и загрузку, доделал буфер, изменил загрузку текстур.
Только появился вопрос, как можно запомнить тип объекта, на котором располагается поставленный еще один объект? Как-то плохо выразился, лучше на примере объясню:
В ячейку с координатами (0;0), я размещаю газон, т.е. Map_mass[0,0].View:=18 (18- номер Газона), потом я на газон хочу посадить кошку=> у ячейки (0;0) Map_mass[0,0].view:=14 (14 - Номер кошки, текстура - прозрачная). При загрузке сохраненной игры, получается, что в ячейке (0;0) располагается текстура кошки, без текстуры газона на заднем фоне. Как это можно решить?
Можно ли создать еще одну переменную у массива, допустим Map_mass[x,y].BackFon и в нее записывать номер объекта, который находился в (x;y), до размещения туда другого объекта? А при загрузке сохраненной игры, восстанавливать сначала задний фон, а потом передний? Или есть какое - либо более логичное решение?

Последний раз редактировалось Slin; 08.10.2012 в 17:11.
Slin вне форума Ответить с цитированием
Старый 09.10.2012, 10:14   #30
phomm
personality
Старожил
 
Аватар для phomm
 
Регистрация: 28.04.2009
Сообщений: 2,882
По умолчанию

Я об этом и писал выше. В данном случае, разумно будет выделить для клетки набор параметров (полей для записи о клетке), которые были бы независимы от других(т.е. задний фон не зависит от объекта на клетке - 2 параметра). В базовом исполнении, можно просто в клетке хранить соответствующие номера объектов (при желании можно и текстуры, точнее ссылки на них, в целом, так и есть сейчас).
Но при более сложной работе, это будет неоптимально по ряду критериев. Посему обозначьте примерный план для конечной цели проекта, будет проще советовать, какую схему удобнее выбрать.
phomm вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Игра "Змейка" на 2 персоны [Dethklok] Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 1 07.06.2011 14:24
Assembler.Игра "змейка". Пупкин Помощь студентам 0 27.05.2010 00:08
Игра "Змейка" program123 Общие вопросы Delphi 2 08.03.2009 23:49
Игра "Змейка" spamer Общие вопросы Delphi 1 09.01.2009 04:22
Ещё одна игра "Змейка" Simply-Art Софт 17 05.07.2007 04:10