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

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

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

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 12.10.2011, 19:59   #1
arahis
Пользователь
 
Регистрация: 10.10.2011
Сообщений: 64
По умолчанию Создание 2d стрелялки "Замочить птичку" шаг за шагом.

Урок писался для тех кто не работал в Дэлфи но помнит Паскаль со школы.
Игра, исходники, картинки для создания: здесь

Ну что, поехали.

Шаг 1. Оформление формы.

Запустите Дэлфи. Перед вами серая форма. Не пугайтесь точек. В програме(в экзэшке) они не видны. Вообще то птичка должна летать в синем небе поэтому измените цвет формы на синий. Для этого выберите форму( клацните по ней один раз). Слева в Инспекторе Объектов(Object Inspector) вы увидите ее свойства в виде списка параметров. Окно инспектора разделено на два столба. Левый столб - название параметра(свойства объекта), правый - поле для его редактирования или выбора возможных значений. Найдите параметр "color" и клацните на поле справо от него. Выберите синий цвет. Учтите что на выбор даются несколько разных синих цветов. Посмотрите какой синий цвет на картинках с птичкой или тучками и попытайтесь выбрать похожый. Дальше, давайте сделаем так что бы в заголовке формы было не "form1" а название игры "Замочить птичку". Найдите параметр "caption", клацните на поле справо от него ну а дальше вы поймете.

Шаг 2. Размещение обьектов на форме

Киньте на форму обьект "mainmenu" в любое место. Для этого подведите курсор к какому то обьекту на панели "standart". Тогда под курсором высветится его название таким образом вы найдете наш обьект. Если вы не нашли обьект на панели "standart" значит он на другой панели. Клайните один раз по обьекту. Наведите курсор в нужное место и клацните левой кнопкой опять.Что бы удалить обьект выделите его и нажмите "delite". Киньте пять обьектов "image"(рисунок). image1 по высоте разместите по середине. Остальные image киньте в верху на немножко разной высоте. Киньте прямо на середину формы "panel"(панель). Киньте прямо на эту панель "combobox"(выпадающий список) и "button"(кнопка).
Киньте в низ формы еще один "panel"(панель). На эту панель киньте "label" 6 штук. Теперь вам их надо переименовать. Делается это также как и с формой. Переименуйте: label1 на Время:, label2 на 0, label3 на Очки:, label4 на 0, label5 на рекорд, label6 на 0. Названия будут написаны мелким шрифтом поэтому рекомендую его выделить. Делается так: выбираете нужнай вам label, ищете параметр "Font", клацаете на поле справа от него, тогда появится троеточие, клацаете на троеточие а дальше вы поймете.
Теперь надо загрузить в каждый image картинку для этого выберите его, найдите параметр "picture", клацните справа отнего на троеточие а там уже поймете.В остальные четыре image загрузите рисунки тучек. После того как вы загрузили изображение найдите параметр "proportional" и поменяйте его значение с "false"(неправда) на"true"(правда). После этого ростяните и ли стяните каждую картинку до нужных размеров.
Когда на форме появили панели вы увидели что по середине каждой из них написано ихнее название которое нам мешает. Как его убрать? Выберите панель, найдите параметр "caption" а там поймете. На кнопке которая находится на panel1 написано ее название а на нужно что бы было"Ок". Переименуйте ее спомощью параметра "caption".
Сделайте panel2 зеленого цвета с помощью параметра color.

Последний раз редактировалось MaTBeu; 22.10.2011 в 11:30.
arahis вне форума Ответить с цитированием
Старый 12.10.2011, 20:00   #2
arahis
Пользователь
 
Регистрация: 10.10.2011
Сообщений: 64
По умолчанию

Шаг 3. Меню.

Выберите ваш Mainmenu1(ОсновноеМеню1). Найдите параметр "items"(изделия). Клацните на поле справа от него, появится треточие. Клацните на троеточие. Справа вы увидете какой вид будет иметь ваша менюшка и там же можете переключатся между ее кнопками. Напротив "caption" напишите "Меню". Переключитесь на правое поле какогото другого параметра и вы увидете изменения. Теперь нажмите кнопку влево и вы увидите что снизу появилась еще одна кнопка. Нажмите на нее и напротив "caption" наришите "Выход". Переключитесь на правое поле другого парамтра и вы увидете изменения. Аналогично сделайте ниже кнопки "Новая игра" и "Параметры".
Клацните два раза на "Выход". После этого вы переключитесь в окно редактирования текста и перед вами будет функция:
Код:
procedure TForm1.N2Click(Sender: TObject);
begin

end;
Что же она означает? Это функция виполнения действий по нажатию вашей кнопки "Выход" которая в програме имеет имя N2.(Слово которое вы написали на обьекте это не имя обьекта это просто слово!!! Вот такая особенность Дэлфи). Тоесть все те события которые вы написали в середине этой функции начнут выполнятся только после нажатия этой кнопки. Все что вы написали поза этой функцией не ждет когда же вы на нее нажмете.
Нам надо что бы после нажатия "Выход" программа выключалась. Это можно сделать несколькими способами. Я рекомендую написать halt;. Теперь нажмите F9 и Дэлфи создаст програму(экзэшку). Посмотрите что ваша кнопка работает.
Когда запускается програма на до что бы перед вами был просто синий экран, надо что бы рисунков и панелей не было видно. Для этого перейдите на форму(F12) клацните два раза поней и перед вами появится окно редактированея кода с таким текстом:
Код:
procedure TForm1.FormCreate(Sender: TObject);
begin

end;
Это функция выполнения действий сразу послетого как запускается программа тоесть создается форма. Теперь будем писать в середине ее. Начнем с image1. Кого вам нужно сделать не видимым? Нужно - image1. Тогда так и напишите: image1.(Точка это не опечатка ее поставьте обязательно!!!)
Дальше, у большинства обьектов есть параметр Visible(видимость) который имеет только два значения: false(неправда) и true(правда). Напишите: Visible:=false;. В итоге у вас должна выйти такая строчка: image1.Visible:=false;. Теперь нажмите F9 и вы увидите что птичку не видно.
Напишите аналогичные строчки для image2,image3,image4,image5,panel1, panel2. Внимание те обьекты которые размещены на панели автоматически становятся не видимыми вместе с ней! Дэлфи упростил написания кода. Наберите только часть кода, нажмите ctrl+пробел и перед вами появится список где можно выбрать нужное слово. Если его там нет тогда добавте еще букву.
По нажатию "Новая игра" все обьекты должны появится. Что вам делать? Скопируйте строчки с помощью которых вы сделали обьекты не видимыми. Переключитесь на форму(клавиша F12). Нажмите на mainmenu, нажмите на троеточие справа от items, нажмите два раза на "Новая игра" и перед вами появится:
Код:
procedure TForm1.N3Click(Sender: TObject);
begin

end;
Ставите в эту функцию код, удалите строчку Panel1.Visible:=false;, поменяйте значение false на true. Почему мы удалили ту строчку? Да потому что на этой панели будут высвечиватся параметры(точнее уровни) поэтому она будет доступна только после нажатие кнопки "Параметры". Вот это мы сейчас и сделаем. Перейдите на форму(F12), два раза клацните по mainmenu1, два раза по "Параметры". Откроется окно с:
Код:
procedure TForm1.N4Click(Sender: TObject);
begin

end;
Напишите в этой функии строчку: Panel1.Visible:=true;. Прекрасно теперь остало сделать так что бы эту панель закрывать. Думаю вы уже сами догадались как это сделать. И так panel1 будет закрыватся при нажатии на кнопку ""Ок". Тогда надо выбрать эту кнопку, два раза клацнуть по ней. Перед вами появится функция выполнения действий после нажатия этой кнопки:
Код:
procedure TForm1.Button1Click(Sender: TObject);
begin

end;
В середину этой функции вставте строчку(вы уже догадались какую) :
Код:
panel1.Visible:=false
Запустите вашу прогу( кнопка F9) и порадуйтесь.

Последний раз редактировалось MaTBeu; 22.10.2011 в 11:32.
arahis вне форума Ответить с цитированием
Старый 12.10.2011, 20:01   #3
arahis
Пользователь
 
Регистрация: 10.10.2011
Сообщений: 64
По умолчанию

Шаг 4. Время и псевдо время

Дальнейшие действия происходят в функции procedure TForm1.N3Click(Sender: TObject); (Функция выполнения действий после нажатия на "Новая игра")
И так наша птица летает в пространстве и во времени. Когда пройдет определенное время тогда игра закончится. Поэтому у нас сначала будет цикл по времени если точнее по псевдо времени. Давйте введем глобальную величину(тоесть пишите ее возле var который стоит перед всеми функциями) не целелого типа(real)(потому что число будет дробовое) которое будет называтся shot от слова шетчик. smile У вас должна выйти так:
Код:
var shot:real;
Form1: TForm1;
Пусть наш шетчик уменшается от 2000 тысяч до нуля. Пока он уменшится пройдет некоторое время поэтому он имеет некоторое отношение к времени. Но межде 2000 и 1999 не проходит одна секунда поэтому это число не секунды поэтому это псевдо время. Пишите такой цыкл после строчек где вы обьекты сделали видимыми:
Код:
shot:=2000;
while shot>=0 do
begin
shot:=shot-1;
end;
Теперь нам надо виводить псевдо время на экран на Label2. Значит над сторчкой где вы уменьшаете время пишите:Label2.. Думаю ввспоминая переименования формы и кнопки и панелей вы догадуетесь какое дальше слово. Правильно:Caption:=. Теперь казалось бы нам надо просто написать shot но нет не все так просто. Все то что отображается на обьектах формы должно существовать в строчном формате(string). Поэтому мы дальше пишем функцыю которая переводит велечину из формата real в string. Короче у вас должно выйти такое:Label2.Caption:=floattostr(sh ot);. Так как отобаражаемое число на форме изменяется то изображение всей формы должно перерисовыватся для этого служит команда: Application.ProcessMessages;. Напишите ее после: shot:=shot-1; Теперь запустите прогу и вы увидите как число уменьшается но слишком бысто. Что бы умедленить работу програмы используем команду sleep()(спать) где в дужках пишем величину задершки. Значит под Application.... напишите: sleep(50);. Запустите прогу и увидите что все в порядке. Ну как же тогда сделать из псевдо времени настоящее время. А так. Допустим вам нужно 3 минуты это 180 секунд. Тогда вместо x:=2000; напишите x:=180;. Запустите игру и секундомер и посмотрите за сколько настоящих секунд наш shot дойдет до нуля. Поделите это время на 180 и вместо +1 напишите +это число. У меня секундомера нет поэтоуму я так не заморачивался.

Последний раз редактировалось MaTBeu; 22.10.2011 в 11:33.
arahis вне форума Ответить с цитированием
Старый 12.10.2011, 20:02   #4
arahis
Пользователь
 
Регистрация: 10.10.2011
Сообщений: 64
По умолчанию

Шаг 5. Полет птицы
Добавляем глобальную величину х типа(формата) integer(целое число). х - будет горизонтальной координатой птички. Птичка то движется не только во времени но и еще по форме. Движется она с левого края формы который имеет горизонтальную координату 0 до правого который у меня имеет горизонтальную координату 800. Только птичка дошла до правого края(х=800) тогда она телепортируется( smile ) обратно на левый край(x:=0) и снова движется слево на право. Горизонтальная координата в Дэлфи называется "Left" а вертикальная "top". Птичка должна двигатся не только слева на право а еще вниз и вверх поэтому я выбрал движение по синусоиде. Короче у вас должно выйти так:
Код:
shot:=2000;
while shot>0 do
begin
x:=0;
while (x<=800) and (shot>=0) do
begin
Image1.Left:=x;
Image1.top:=round(200+100*sin(0.02*x));
Label2.Caption:=floattostr(shot);
shot:=shot-1;
x:=x+10;
Application.ProcessMessages;
sleep(50);
end;
end;
Почему я в условие внутренного цикла добавил проверку времени? Да потому что внутрений цыкл заканчивается только после того как птичка дойдет до правого края я времяже может закончится и раньше. Если вы хотите остановить игру тогда нажмите на "Меню".

Последний раз редактировалось MaTBeu; 22.10.2011 в 11:34.
arahis вне форума Ответить с цитированием
Старый 12.10.2011, 20:02   #5
arahis
Пользователь
 
Регистрация: 10.10.2011
Сообщений: 64
По умолчанию

Шаг 6. Полет тучек или полет декораций

Запустите прогу(F9) и скажите что вы перед собой видите. Вы видите как нещясная птичка снова и снова пролетает над тем же самым участком неба. Тоесть она летает по кругу. Это не красиво. Надо сделать так что бы игроку казалось что птичка летит все дальше и дальше. Для этого надо что бы тучки двигались на встречу птице(тоесть справа на лево) с меньшей скоростью.
Как это сделать? Ну во первых и дураку ясно что тучки тоже летят во времени. Значит то что мы напишем будет в середине цикла по псевдо времени. Вы скажите если это движение значит мы должны написать цикл. И тут вы ошиблись. Если написать наш цикл после первого цикла тогда сначало выполнится первый цикл а уж потом второй. Тоесть сначало птичка пролетит от правого края до левого а уж только потом тучка сдвинется с места. Если перед тогда наоборот. А если внутри вложеного(внутреннего) цыкла тогда вообще полный бред начнется. Короче надо без цикла.
Во первых надо ввести величины x2,x3,x4,x5 формата integer. Они будут горизонтальними координатами соответствующих image тоесть тучек. Код будем писать внутри внутренего(вложеного) цикла тоесть вот тут:
Код:
while (x<=800) and (shot>=0) do
begin
<=
end;
Что бы придумать код нам нужно понять что мы хотим от тучки. А хотим мы вот что. Возьмем первую тучку(image2) с координатой x2. Если тучка не зашла за левий край который имеет координату 0 (if Image2.Left>=0) тогда(then) двигаем тучку справа на лево на один пиксель(begin x2:=x2-1; Image2.Left:=x2; end). В противном случае телепортируем тучку назад на првый край который имеет координату 800
(else begin x2:=800; Image2.Left:=x2; end. В итоге у вас должно выйти такое:
Код:
if Image2.Left>=0 then
begin
x2:=x2-1;
Image2.Left:=x2;
end
else
begin
x2:=800;
Image2.Left:=x2;
end;
Пишите под этим внизу аналогичную вещь для: image3 и x3, image4 и x4, image5 и x5.
Ой чуть не забыл если вы так сделаете тогда они собьются в одну кучу и будут лететь в месте. Перед полетом их надо по раставлять на форме в разних местах с помощью кода. Короче надо для иксов тучек после строки shot:=2000; но перед циклом присвоить начальные значения. Например:
Код:
x2:=88;
x3:=272;
x4:=464;
x5:=648;

Последний раз редактировалось MaTBeu; 22.10.2011 в 11:35.
arahis вне форума Ответить с цитированием
Старый 12.10.2011, 20:03   #6
arahis
Пользователь
 
Регистрация: 10.10.2011
Сообщений: 64
По умолчанию

Шаг 7. Псевдо анимация

В Дэлфи есть обьект с помощью которого можно вставить видео без звука. Но мы этим элементом не возпользуемся. Почему узнаете позже. Мы сами сделаем анимацию. Что такое анимация? Примитивно говоря это кадры которые бысто идут друг за другом. У нас есть два рисунка: птичка подняла крылышки и птичка опустила крылишки. Если их поочередно загружать в image1 то создастся эфект как будто она действительно махает крыльями. Но вот проблема как указывать програме когда загружать одну картинку а когда другую да ище и поочередно. Выход оказался гениально прост - использовать свойства чисел.
И так введите еще одну глобальную величину img формата integer. это типа от слова image. После while shot>=0 do begin но перед while (x<=800) and (shot>=0) do присвоим ей начальное значение: img:=1;. А в середине цыкла который под этой строчкой пропишем:img:=img+1;. Тоесть у нас есть величина и мы ее увиличиваем. А дальше пишем такое. Если наша величина парное число тоесть делится на два без остачи тогда мы загружаем в image1 одну картинку в противном случае - другую:
Код:
if img mod 2 =0 then
begin
Image1.Picture.LoadFromFile('Ptichka1.bmp');
end
else
begin
Image1.Picture.LoadFromFile('Ptichka2.bmp');
end;
А теперь запустите програму и почувствуйте себя крутым перцем.

Последний раз редактировалось MaTBeu; 22.10.2011 в 11:35.
arahis вне форума Ответить с цитированием
Старый 12.10.2011, 20:04   #7
arahis
Пользователь
 
Регистрация: 10.10.2011
Сообщений: 64
По умолчанию

Шаг 8. Регулировка времени или уровни сложности

Вот вы смотрите на птичку и вам нравится как она летит. Но это субьективное мнение. Для кого то это слишком медленно а для кого то - быстро. Создадим уровни сложности: "Новичок"(летает медленно), "Любитель", "Профессионал"(Летает быстро).
Выберите ComboBox1 который на panel1. Найдите параметр items, клацните по полю справа, клацните по троеточию и перед вами появится окошко. Введите "Новичок", клацните Энтэр, "Любитель", клацните Энтэр, "Профессионал", клацните Ок. Каждая строка имеет свой номер(itemindex). Нумерация начинается с нуля. Найдите параметр itemindex и поставте значение 0. После этого в ComboBox1 по умолчанию выбрана первая строка(Новичок).
Что бы изменять скорость игры на до изменять величину которая стоит в sleep(). Введите новую величину zad формата integer. В строчке sleep(50)вместо 50 напишите zad. Выберете ComboBox1 и два раза клацните на него. Перед вами появится функцыя выполнения действий после изменение строчки. Теперь думаем если мы выбрали первую строчку тоесть номер строчки равно 0 тогда наш zad имеет одно значение. Если номер строчки равно 1 тогда наш zad имеет другое значение. А если 2 тогда третье. Короче вот так:

Код:
procedure TForm1.ComboBox1Change(Sender: TObject);
begin
if ComboBox1.ItemIndex=0 then
begin
zad:=50;
end;
if ComboBox1.ItemIndex=1 then
begin
zad:=40;
end;
if ComboBox1.ItemIndex=2 then
begin
zad:=30;
end;
end;
Но возникает проблема. При переключении будет быстрее двигатся не только птица а и псевдо время. Его можна замедлить уменьшывшы величину на которое оно уменьшается. Поэтому вводим новую величину shag формата real. В строчке shot:=shot-1; вместо 1 пишем shag. Мы знаем что при меньшем zad надо взять меньший shag. Но насколько меньшый? Если взять за ориентир первое значение тогда так. Во сколько раз второй zad меньшый чем первый во столько же второй shag меньшый чем первый. Короче по соотношению. Я над таким не заморачивался. Я написал цыфры от фонаря и у меня вышло вот такое:

Код:
procedure TForm1.ComboBox1Change(Sender: TObject);
begin
if ComboBox1.ItemIndex=0 then
begin
zad:=50;
shag:=1;
end;
if ComboBox1.ItemIndex=1 then
begin
zad:=40;
shag:=0.8;
end;
if ComboBox1.ItemIndex=2 then
begin
zad:=30;
shag:=0.5;
end;
end;
Нету добра без худа возникает вторая проблема. Если вы не выберете уровень и сразу нажмете "Новая игра" тогда то что мы написали несрабатывает. Почему? Да потому что оно будет работать только после смены строки в ComboBox1. А нам нужно что бы оно работало сразу после открытия програмы(создания формы). Ну так тогда скопируйте этот код и идите в функцию виполнения действий сразу после создания формы(два раза клацните по форме). В ставте этот код туда. И все заработает как надо.

Последний раз редактировалось MaTBeu; 22.10.2011 в 11:36.
arahis вне форума Ответить с цитированием
Старый 12.10.2011, 20:04   #8
arahis
Пользователь
 
Регистрация: 10.10.2011
Сообщений: 64
По умолчанию

Шаг 9. Попадание - очки
Думаю вы уже догадались что надо ввести новую величину. Правильно. Введите ochk формата integer.
Только запускается програма(создается форма) как количество очков должно выставится на ноль. Вот и идите в эту функцыю(два раз клацните по форме) и напишитеchk:=0;.
Теперь думаем что такое попадание? Это когда наш курсор находится на птичке(image1) и мы нажымаем на нее(ведь что бы выстрелить надо нажать на левую клавишу мышки). Тогда думаю что вы догадались второй раз: нам нужна функция выполнения действий после нажатия на image1. Для этого выберите его и нажмите два раза. Дальнейшые действия будут происходить в:
Код:
procedure TForm1.Image1Click(Sender: TObject);
begin

end;
Что мы должны сделать с очками при попадании? Увеличить их на единицу. Тогда так и напишитеchk:=ochk+1;. Дальше выводим очки на лабле тоесть переименовуем его. Думаю вы это уже умеете делать:Label4.Caption:=;. Мы не можем дальше написать просто ochk. Потому что ochk в формате integer а записывать величину можно только в формате string. Мы должны перевести величину с одного формата в другой. В итоге у вас выйдет:Label4.Caption:=inttostr(och k);. Все получилось.

Добавлено (11.10.2011, 15:46)
---------------------------------------------
Шаг 10. Попадание - рекорд

Значение рекорда у нас должно где то хранится. Экзешка это не записная книжка там нельзя хранить. Хранить надо в каком то файлике. Поэтому создайте через блокнот 1.txt инапишите туда "0". Файлик вложите в папку с игрой. Добавте к глобальным величинам следущие:
Код:
f: TextFile;
a: extended;
Вот вам код и обьяснения:

procedure TForm1.Image1Click(Sender: TObject);
begin
ochk:=ochk+1;
Label4.Caption:=inttostr(ochk);
AssignFile(f, '1.txt'); <= Ассоцыируем величину которая отвечяет за файл с самим файлом.
reset(f); <=Открываем файл только для чтения.
read(f, a); <= Читаем файл и то что прочитали присваеваим величине "а".
if ochk>a then
begin
CloseFile(f); <= Закрыли файл.
a:=ochk;
rewrite(f); <=Открыли для перезаписи.
write(f, a: 8: 0);[/b] <=Записуем в файл даные величины "а"
CloseFile(f);
reset(f);
read(f, a);
Label6.Caption:=floattostr(a);
CloseFile(f);
end
else CloseFile(f);
end;

end;
---------------------------------------------
Все прога готова. Если вам понравилось работать в Дєлфи тогда пишите и мы с вами попробуем сделать 2d платформер. Удачи вам игроделы.

Последний раз редактировалось Beermonza; 24.10.2011 в 15:24.
arahis вне форума Ответить с цитированием
Старый 14.10.2011, 15:56   #9
Beermonza
Инженер ИС
Старожил
 
Аватар для Beermonza
 
Регистрация: 13.12.2006
Сообщений: 2,671
По умолчанию

Быстренько исправьте ошибки в тексте. Оформите по-человечески с выделением разделов. Для кода есть тэг "CODE", значок "#" в редакторе сообщений.

Цитата:
Все прога готова. Если вам понравилось работать в Дєлфи тогда пишите и мы с вами попробуем сделать 2d платформер "Спаси свою задницу". Удачи вам игроделы.
За это штраф, простите, но правила есть правила.
Руководитель проекта MMO 2D RPG: Настоящее имя Денис Стрижак (10.05.1981-6.02.2019) Мир духу его
Beermonza вне форума Ответить с цитированием
Старый 15.10.2011, 15:40   #10
arahis
Пользователь
 
Регистрация: 10.10.2011
Сообщений: 64
По умолчанию

Цитата:
Сообщение от arahis Посмотреть сообщение
"Спаси свою задницу"
Кнопку "Редактировать" или как там она называлась я нигде не вижу. Поэтому единственное что могу сделать это извенится. Извените.
arahis вне форума Ответить с цитированием
Ответ


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

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

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


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Поясните мне этот код шаг за шагом kroatoani Общие вопросы Delphi 5 21.09.2010 14:21
Как обойти "преобразование типа из "string" в "float" невозможно" lexluter1988 Помощь студентам 1 07.08.2010 12:23
"ОКРВВЕРХ", "ОКР", "ЕСЛИ". Как бы их связать. Каравай Microsoft Office Excel 13 17.02.2010 09:53
при вводе на листе "магазин"- код товара появлялось "описание" товара из "склада" с "продажной ценой" aleksei78 Microsoft Office Excel 13 25.08.2009 12:04