![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Сохранение игры [Delphi]
Hater © (2004-05-20 07:45:00)Я создаю игру - текстовый квест. У героя будет несколько характеристик. Как запрограммиравать сохранение? Помогите пожалуйста!
Evgeniy_K (2004-06-14 10:48:00) [1]Ини - лажа, не верь им, он не может быть тяжелее 64 Кб. Если хочешь сохранять игру, то работай с файлами:
var
f: TextFile;
AssignFile(f, '<FileName>');// <FileName> - имя файла
Reset(f);// - открыть файл на чтение
Rewrite(f);// - перезаписать файл
Append(f);// - дописать в файл с конца
CloseFile(f);// - закрыть файл
Писать в файл:
writeln(f, VARIABLE);// - где VARIABLE - переменная или значение
Читать из файла:
readlnln(f, VARIABLE);// - где VARIABLE - переменная
//"ln" - переходить или нет на след. строку
Учи ObjectPascal!
$HUR!K (2004-06-14 06:43:00) [2]Млин! Шоб я так жил!
Только начинающий программер озадаченно почесал макушку - так сразу вокруг него консилиум из десятка бородатых хацкеров :)
А на счет сейвгейма для новичка - по-мойму проще так:
procedure save;
var
f:textfile;
begin
assignfile(f,'save'); rewrite(f);
save(f,live);
save(f,bax);
save(f,condoms);
save(f,hrenznaetchto);
closefile(f);
end;
(2004-05-31 10:39:00) [3]Удалено модератором
Подкрадуха (2004-05-29 17:28:00) [4][4]...
Несмотря на ухмылки и насмешки других, я понял, что ты имел ввиду, говоря про профуровень.
Сам пытался сделать всё "на профуровне" - хотел даже начать со своего абстрактного класса и выписать героя с нуля, подумывал о своей серверной игровой и клиентской компоненте =) Но жизнь оказалась проще... И чем больше ты раздумываешь над красотой - тем меньше напишешь кода. Тогда, плюнув на всё, я взялся за старые добрые записи.
Вот что получилось...
Но сначала немного о том как это работает...
С клиента приходит на сервер запрос, сервер анализирует его и возвращает параметры героя на данный момент или ошибку.
Итак...
////////////////////////////////////////
// используется старый TServerSocket //
////////////////////////////////////////
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ScktComp;
type
TForm1 = class(TForm)
ServerSocket1: TServerSocket;
procedure ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
uses Analizator;
{$R *.dfm}
procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
begin
Socket.SendText(CheckCommand(Socket.ReceiveText));
end;
end.
Теперь сам файл Analizator.pas...
unit Analizator;
interface
uses
Windows, Classes;
type
THero = record
ch00: PChar; //ник
ch01: Cardinal; //цифровая ссылка на ник (unixtimestamp)
ch02: Real; //склонность
// 0 - нет склонности
// 0.5 - нейтрал
// 1-1.99 - Белое Братсво
// 2 - хаос
// 3 - Тёмное братство
// 4 - Серое Братство (зарезервировано)
// 99 - Истинный Хаос
// 100 - Ангел
ch03: Byte; //знак зодиака (от 1 до 12)
ch04: Integer; //клан
ch05: Byte; //уровень чара
ch06: Integer; //количество НР на момент последнего доступа к инфе
// ...и ещё около 70 параметров...
end;
procedure SaveHero(h: THero);
function ReadHero(name: String): THero;
function CheckCommand(cmd: String): String;
function HeroNew(nick: PChar; email: PChar; psw: PChar; realname: PChar; birtday: PChar; sex: PChar;
realcity: PChar; icq: PChar; homepage: PChar; deviz: PChar; color: PChar; hobby: PChar): String;
implementation
procedure SaveHero(h: THero);
var
f: file of THero;
begin
assignfile(f, h.ch00 +'.txt');
rewrite(f);
write(f, h);
closefile(f);
end;
function ReadHero(name: String): THero;
var
f: file of THero;
h: THero;
begin
assignfile(f, name +'.txt');
reset(f);
read(f, h);
closefile(f);
Result := h;
end;
function CheckCommand(cmd: String): String;
var
str: String;
sl: TStringList;
begin
sl := TStringList.Create;
sl.SetText(PChar(cmd));
str := sl.Strings[0];
if str = '/register' then Result := HeroNew(PChar(sl.Strings[1]), PChar(sl.Strings[2]), PChar(sl.Strings[3]),
PChar(sl.Strings[4]), PChar(sl.Strings[5]), PChar(sl.Strings[6]),
PChar(sl.Strings[7]), PChar(sl.Strings[8]), PChar(sl.Strings[9]),
PChar(sl.Strings[10]), PChar(sl.Strings[11]), PChar(sl.Strings[12]));
if str = '/join' then Result := 'ERR000' //ERR000 - значит, такой команды пока не существует в игре,
//после её отправки сервером - сервер отключает клиента
else Result := 'ERR000';
sl.Free;
end;
function HeroNew(nick: PChar; email: PChar; psw: PChar; realname: PChar; birtday: PChar; sex: PChar;
realcity: PChar; icq: PChar; homepage: PChar; deviz: PChar; color: PChar; hobby: PChar): String;
// создание героя,
// вместо "/register Nick Email Psw RealName Birtday Sex RealCity ICQ Homepage Deviz Color Hobby"
// вместо пробелов использовать #10#13 (TStringList!!!)
var
h: THero;
begin
with h do
begin
ch00 := nick;
ch01 := GetTickCount; // неправильно, но пока сойдет и так
// ...тут опять очень много полей, заполняемых на основе полученных данных
end;
SaveHero(h);
Result := 'список всех полей героя через #10#13, типа как для стринглиста';
end;
end.
Ну вот вроде и всё, всё лишнее вроде бы поудалял.
З.Ы. Это фрагмент был из игры "Combats Offline", по мотивам Великого Бойцовского Клуба ;-)
Удачи!
cdadmitriy (2004-05-27 12:14:00) [5]Можно исползовать
Var Ini:TMemIniFile; Begin
Ini:=TMemIniFile.Create (CurProgDir+'\'+NameIniFileParam);
With CommP do Begin
Ini.EraseSection(SectionEcrParam);
Ini.WriteInteger(SectionEcrParam,'Rsn1',ECR.Rsn1); Ini.WriteInteger(SectionEcrParam,'Rsn2',ECR.Rsn2);
Ini.WriteInteger(SectionEcrParam,'Tsn1',ECR.Tsn1); Ini.WriteInteger(SectionEcrParam,'Tsn2',ECR.Tsn2);
End;
Ini.UpdateFile; Ini.Free;
НО при больших ( размер ) данных скорость записи чтения не годится
я исползую BLOB поля в DB Paradox
Дм (2004-05-25 09:06:00) [6]Удалено модератором
TransparentGhost (2004-05-24 11:40:00) [7]V ternovnik :o)
Onanim (2004-05-24 11:38:00) [8]В ОРЕШНИК ЕГО!!!
TransparentGhost (2004-05-24 10:34:00) [9]Vse peremennije, kotorije nuzhno sohranit' ob'javljajesh podrjad, a pri sohranenii cherez WriteBlock s ukazanijem adresa pervoj peremennoj i kol-vo - obshij razmer vseh peremennih kotorije nuzhno sohranit'. Tochno tak zhe i vizivat' cherez BlockRead.
Takim obrazom mozhno obojtis' i bez "Record". Hotja smisl tot zhe.
Ландграф Павел (2004-05-23 13:37:00) [10]Н-да.. а начиналось как смотрю все с проблемы сохранения:) а зачем ты делаешь сохранение, вот мне интересно, если еще как акацца ничего вообще ненакодино?!
wiz (2004-05-23 12:29:00) [11]2 хм: ну я вроде сказал, что это для статических структур...
хм (2004-05-23 12:17:00) [12]>2 Sapersky: про ООП я только имел ввиду, что если TPlayerStats >= class (TObject), то нельзя сделать f:file of TPlayerStats; >придётся делать всё ручками (через указатель+смещение). Что я >обычно и делаю.
Только надо добавить, что данный способ не подходит для объектов с полями-указателями и длинными строками.
wiz (2004-05-23 12:03:00) [13]2 kas-t: см post [19]... и сам подумай что сказал.
2 Sapersky: про ООП я только имел ввиду, что если TPlayerStats = class (TObject), то нельзя сделать f:file of TPlayerStats; придётся делать всё ручками (через указатель+смещение). Что я обычно и делаю.
---
...здесь был Красный Космический Гонобобель
asm (2004-05-23 11:48:00) [14]на нажатие Button1
begin
ChangeAll(p1, p2, ...); // все меняет
end;
procedure ChangeAll(p1, p2, ...);
begin
ChangeText(..); // меняет текст в мемо
ChangeDescr(..); // меняет характеристики
end;
а дальше, чтобы без кейсов, текст можно читать из файла, определяя смещение по параметру какому-нибудь. или брать из массива, номер элемента также по параметру определяя.
примерно то же c характеристиками. как именно, сложно сказать, ничего не зная.
Sapersky (2004-05-23 11:00:00) [15]А что ini так долго читаются?
Читаются - не очень долго. Вот пишутся - очень, при большом кол-ве параметров лучше писать вручную, через StringList.
Хотя параметры игрока лучше писать в бинарном виде, записями, как тут и советовали.
Из ini можно сразу читать integer, без всяких последующих переводов:
expa:=MyIni.ReadInteger('save','expa',0);
Внутри всё равно выполняется преобразование.
А если там уже сделано всё через ООП ( TPlayerStats = class (TObject) )
Тогда ещё можно писать RTTI - хоть в бинарном, хоть в текстовом виде. Хотя это тоже не очень быстро, скорее всего.
kas-t (2004-05-23 10:42:00) [16]to wiz: Хочу тебя удивить... Из ini можно сразу читать integer, без всяких последующих переводов:
expa:=MyIni.ReadInteger('save','expa',0);
cyborg (2004-05-23 08:51:00) [17]Пока не покажешь как ты делаешь и не объяснишь как хотелось бы, то тебе трудно помочь. Показывай проблемные куски. Не нужно только все модули кидать, только конкретные участки кода.
Hater (2004-05-23 07:08:00) [18]Да нет, я знаю как. Просто... ну как же это обьяснить. Многократно. Я пытаюсь делать это в кейсах, но выходит как матрёшка - слишком громоздко. Может, можно как-то проще :(((
cyborg (2004-05-22 15:45:00) [19]
> Как по нажатию кнопки изменять текст квеста? И изменять
> хар-ки персонажа.
Ты что, издеваешься? Вперёд за учебники по программированию, про игры забудь!
Hater (2004-05-22 12:22:00) [20]Ещё одно. Как сделать, чтоб кнопка каждый раз производила разные действия. Т.е я имею ввиду то, что на форме есь Эдит1 и кнопка Батон1. В поле Мемо1 выводится текст квеста. Как по нажатию кнопки изменять текст квеста? И изменять хар-ки персонажа. При разном варианте разные изменения. И так много раз. Теоретически, я догадываюсь как это сделать, но мне нужен авторитетный совет.
ЗЫ: Спасибо вам всем за советы. Огромное.