IPB
ЛогинПароль:

2 страниц V  1 2 >  
 Ответить  Открыть новую тему 
> Оптимизация алгоритма, Помогите устранить тормоза в игре!
сообщение
Сообщение #1


Новичок
*

Группа: Пользователи
Сообщений: 44
Пол: Мужской

Репутация: -  0  +


Привет еще раз. Пишу игру Охотник на мышек=) Столкнулся с проблемой: как выполнять две процедуры одновременно? Ответ: никак =) Есть процедура, которая генерит вывод мышей на экран. Еще есть процедура, которая рисует охотника в центре экрана, которым нужно управлять. Но как управлять охотником, если уже выполняется процедура вывода мышей на экран? ReadKey не помогает, он останавливает программу в ожидании нажатия клавиши.
Второй вопрос, но тоже по теме. Чтобы убить мышку, нужно направить ружьё охотника на неё и нажать клавишу "Пробел". Как это можно реализовать в моём коде?

" (Показать/Скрыть)
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #2


Perl. Just code it!
******

Группа: Пользователи
Сообщений: 4 100
Пол: Мужской
Реальное имя: Андрей

Репутация: -  44  +


Видимо не верно ты ридкей юзать пытаешься ... Делай так :

 while keypressed do ch := readkey; 


Паузы в ожидании нажатия не будет.


--------------------
perl -e 'print for (map{chr(hex)}("4861707079204E6577205965617221"=~/(.{2})/g)), "\n";'
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #3


Новичок
*

Группа: Пользователи
Сообщений: 44
Пол: Мужской

Репутация: -  0  +


Это выход, но все равно скорости работы явно не хватает. Может, есть принципиально другие решения? И что с вторым вопросом?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #4


Бывалый
***

Группа: Пользователи
Сообщений: 206
Пол: Мужской

Репутация: -  3  +


Вот это
PutPixel(xT,yT,0);

ЗЛО.
Злое злостное зло.
Рисовать ПутПикселем медленно.
Лучше использовать PutImage.
И вообще Unit Graph тормозной. С его помощью быструю игру не сделаешь. И прозрачность в спрайтах он не поддерживает. Конечно, если все дело в том, что нужно сделать лабораторку, тогда ничего не попишешь, а так-то лучше перейти на Delphi и использовать что-то вроде Asphyre. Для "Охотника на мышей" самое то.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #5


Гость






Пишу именно лабораторку..
 К началу страницы 
+ Ответить 
сообщение
Сообщение #6


Новичок
*

Группа: Пользователи
Сообщений: 44
Пол: Мужской

Репутация: -  0  +


Всем доброе время суток. Переписал алгоритм, используя GetImage. Сама по себе эта функция не устранила тормоза, но с ней работать оказалось гораздо удобнее. smile.gif

Вот код: (Показать/Скрыть)


А теперь вопросы smile.gif
1) Почему в коде
     For i:=1 To m Do
For j:=1 To n Do
PutPixel(j,i,Mouse^[i,j]);
в PutPixel i и j нужно поменять местами, чтобы мышка выводилась на экран не в перевернутом виде? То есть если я пишу
PutPixel(i,j,Mouse^[i,j]);
, то изображение выводится на экран, повернутое на 90 град. против часовой стрелки.
2) Так никто и не ответил на вопрос, как проверить то, что я правильно прицелился на мышь, когда выстрелил? Нужно сравнить углы положения ружья и мышки относительно центра, и если они будут равны, то я удачно прицелился? Так? Как это сделать?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #7


Бывалый
***

Группа: Пользователи
Сообщений: 206
Пол: Мужской

Репутация: -  3  +


2) Так, наверное, и сделать - сравнить углы. Нужно только поместить начало координат в пузо охотнику smile.gif
Вот функция пересчета из декартовых координат в полярный угол (перевел с сишного алгоритма с algolist.ru).
function Angle(x, y: real): real;
var theta: real;
begin
if (x = 0.0) and (y = 0.0) then
Angle := -1.0
else if x = 0.0 then
begin
if y > 0
then Angle := 0.5*Pi
else Angle := 1.5*Pi;
end
else
begin
theta := arctan(y/x);

if x > 0.0 then
begin
if y > 0.0
then Angle := theta
else Angle := 2*Pi+theta;
end
else Angle := Pi + theta;
end;
end;


Возвращает полярный угол в радианах для точки с координатами Х,У (в нормальной декартовой системе!).
Если бы еще был выложен файл Mouse.Dat, можно было бы подумать над какими-то улучшениями, а так ведь без него программу не запустить...
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #8


Новичок
*

Группа: Пользователи
Сообщений: 44
Пол: Мужской

Репутация: -  0  +


Mouse.dat-файл, содержащий матрицу 18х18=) Вот генератор:
Uses Crt;
Const m=18;n=18;
Type Data=Array[1..m,1..n] Of Integer;
Var Mouse: Data;
FT: File Of Data;
T: Text;
Str: Char;
i,j,vStr,Err: Integer;
Begin
ClrScr;
Assign(T,'Picture.txt');
Assign(FT,'Mouse.Dat');
ReSet(T);
ReWrite(FT);
For i:=1 To n Do
Begin
For j:=1 To m Do
Begin
Read(T,Str);
Val(Str,vStr,Err);
Mouse[i,j]:=vStr;
Write(vStr);
End;
ReadLn(T);
WriteLn
End;
Write(FT,Mouse);
Close(FT);
Close(T);
ReadLn;
End.


Файл Picture.txt
Цитата
002220000000222000
020002000002000200
200000200020000020
200000200020000020
020002020202000200
200000002000000020
200022200022200020
200200020200020020
200202020202020020
200022200022200020
020000002000000200
020000002000000200
002000020200002000
002000000000002000
000200222220020000
000200200020020000
000020022200200000
000002222222000000

=) Вообще хотелось бы грузить мышку из стандартного bmp-шника.

Сообщение отредактировано: volvo -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #9


Бывалый
***

Группа: Пользователи
Сообщений: 206
Пол: Мужской

Репутация: -  3  +


Ну так вот:
в этом цикле
	 For i:=1 To n Do
Begin
For j:=1 To m Do
Begin
Read(T,Str);
Val(Str,vStr,Err);
Mouse[i,j]:=vStr;
Write(vStr);
End;
ReadLn(T);
WriteLn
End;


индекс i отвечает за строки, а j за столбцы. То есть Mouse[строка,столбец].
А в этом цикле
	 For i:=1 To m Do
For j:=1 To n Do
PutPixel(i,j,Mouse^[i,j]);


наоборот: индекс j отвечает за строки, а i за столбцы. То есть PutPixel(столбец,строка). Поэтому и приходится переставлять индексы местами.
А что тормозит? Охотник медленно вертится, или мыши редко появляются? А то у меня компьютер быстрый, может я не замечаю чего...
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #10


Новичок
*

Группа: Пользователи
Сообщений: 44
Пол: Мужской

Репутация: -  0  +


Поменяй в этом цикле
     For i:=1 To n Do
Begin
For j:=1 To m Do
Begin
Read(T,Str);
Val(Str,vStr,Err);
Mouse[i,j]:=vStr;
Write(vStr);
End;
ReadLn(T);
WriteLn
End;

m и n местами-и ничего не произойдет-изображение все равно придется переворачивать. Я так и не разобрался, почему. Тормозов больше в игре нет, я же писал. smile.gif

Сообщение отредактировано: volvo -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #11


Гость






Цитата
Поменяй в этом цикле <...> m и n местами-и ничего не произойдет
Правильно... у тебя индексы-то по-прежнему перепутаны: I так же отвечает за строки, а J - за столбцы... Чего ты добился заменой M <-> N ???

Тебе I и J менять надо...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #12


Бывалый
***

Группа: Пользователи
Сообщений: 206
Пол: Мужской

Репутация: -  3  +


Тем более, что матрица-то квадратная, 18х18, так что m и n равны. Сколько их не меняй... smile.gif
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #13


Новичок
*

Группа: Пользователи
Сообщений: 44
Пол: Мужской

Репутация: -  0  +


Спасибо! smile.gif А как заюзать функу angle? Как поместить начало координат в центр охотника(центр экрана)?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #14


Бывалый
***

Группа: Пользователи
Сообщений: 206
Пол: Мужской

Репутация: -  3  +


Ну...
Предположим, что режим 640 на 480. И начало координат вверху слева. И ось У направлена вниз. Так, как это обычно в графических режимах бывает. Пусть Xg и Yg - это координаты точки в данной системе отсчета.
Переносим начало координат в центр экрана и разворачиваем ось Y.
X1 := Xg - 320;
Y1 := 240 - Yg;

Теперь у нас X1 и Y1 это координаты той же точки, но в декартовых координатах с началом отсчета в центре экрана. То есть, если экранные координаты мышонка Xm и Ym, то чтобы получить угол прицела на данную мышь, надо делать так:
Ugol := Angle(Xm-320.0, 240.0-Ym);

По-моему, так!
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #15


Новичок
*

Группа: Пользователи
Сообщений: 44
Пол: Мужской

Репутация: -  0  +


Опять косяк.. sad.gif Я неправильно использую функу Angle?
Function Shot(xH,yH: Real): Boolean;
Var xM,yM,HunterAngle,MouseAngle: Real;
i: Integer;
Flag: Boolean;
St: String;
Begin
HunterAngle:=Angle(xH-320,240-yH);
SetColor(Black);
OutTextXY(10,460,St);
SetColor(Red);
Str(HunterAngle,St);
OutTextXY(10,460,St);
For i:=1 To Mouses Do
Begin
MouseAngle:=Angle(Mas[i]^.x-320,240-Mas[i]^.y);
If HunterAngle=MouseAngle Then
Begin
Flag:=True;
Break;
End;
End;
If Flag Then
Begin
MouseVis(Mas[i]^,True);
Shot:=True;
End
Else
Shot:=False;
End;

После выстрела появляются левые убитые мышки.. =(
Прикрепил доработанную полную версию. Прикрепленный файл  MAIN.PAS ( 5.55 килобайт ) Кол-во скачиваний: 287
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #16


Бывалый
***

Группа: Пользователи
Сообщений: 206
Пол: Мужской

Репутация: -  3  +


Отвечу завтра. Единственное замечание - стоит ли сравнивать углы на точное равенство? Не лучше ли вычислять их разность и сравнивать ее с некоторой дельтой? Тем более что и мышка ведь не точечная...
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #17


Новичок
*

Группа: Пользователи
Сообщений: 44
Пол: Мужской

Репутация: -  0  +


Я так и хотел сделать, но сначала я хотел разобраться с точными данными, чтобы потом можно было вносить погрешности.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #18


Бывалый
***

Группа: Пользователи
Сообщений: 206
Пол: Мужской

Репутация: -  3  +


Простой корявый пример, иллюстрирущий идею.


Прикрепленные файлы
Прикрепленный файл  short.pas ( 2.4 килобайт ) Кол-во скачиваний: 117
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #19


Новичок
*

Группа: Пользователи
Сообщений: 44
Пол: Мужской

Репутация: -  0  +


Круто! Бродяжник, спасибо! Вот, что примерно получилось. Уже играть можно)) Прикрепленный файл  MAIN.PAS ( 5.97 килобайт ) Кол-во скачиваний: 250
Теперь нужно перевести это в объекты.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #20


Новичок
*

Группа: Пользователи
Сообщений: 44
Пол: Мужской

Репутация: -  0  +


Мужики, зацените мой первый опыт в ООП =) Переписал в ООП охотника из игры. Нормально?
Program Hunt;
Uses Graph,Crt;
Const
Left = #75;
Right = #77;
Type
Hunter=Object
Public
Constructor Init(xC,yC,WeaponLen,Head,Hat: Integer; Speed: Real);
Destructor Done;
Function CountX(D: Real): Integer;
Function CountY(D: Real): Integer;
Procedure Direction(c: Char);
Procedure Draw;
Private
x0,y0,x1,y1,r,HIn,HOut: Integer;
Spd,t: Real;
End;
Constructor Hunter.Init(xC,yC,WeaponLen,Head,Hat: Integer; Speed: Real);
Begin
x0:=xC;
y0:=yC;
r:=WeaponLen;
HIn:=Head;
HOut:=Hat;
Spd:=Speed;
x1:=r+x0;
y1:=y0;
t:=0;
End;
Destructor Hunter.Done;
Begin
WriteLn('Done');
End;
Function Hunter.CountX(D: Real): Integer;
Begin
CountX:=Round(r*Cos(D))+x0;
End;
Function Hunter.CountY(D: Real): Integer;
Begin
CountY:=Round(r*Sin(D))+y0;
End;
Procedure Hunter.Direction(c: Char);
Begin
Case c Of
Left: t:=t-Spd;
Right: t:=t+Spd;
End;
If (t>=2*Pi) Or (t<=-2*Pi) Then t:=0;
End;
Procedure Hunter.Draw;
Begin
SetColor(Black);
Line(x0,y0,x1,y1);
x1:=CountX(t);
y1:=CountY(t);
SetColor(Red);
Line(x0,y0,x1,y1);
SetColor(Blue);
SetFillStyle(1,Blue);
PieSlice(x0,y0,0,360,HIn);
SetColor(Red);
SetFillStyle(1,Red);
PieSlice(x0,y0,0,360,HOut);
End;
Var GD,GM: Integer;
H: Hunter;
k: Char;
Begin
GD:=Detect;
InitGraph(GD,GM,'');
H.Init(320,240,20,10,6,0.1);
Repeat
k:=ReadKey;
H.Direction(k);
H.Draw;
Until k=#27;
CloseGraph;
H.Done;
ReadLn
End.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

2 страниц V  1 2 >
 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 




- Текстовая версия 19.09.2017 22:24
Хостинг предоставлен компанией "Веб Сервис Центр" при поддержке компании "ДокЛаб"