Привет еще раз. Пишу игру Охотник на мышек=) Столкнулся с проблемой: как выполнять две процедуры одновременно? Ответ: никак =) Есть процедура, которая генерит вывод мышей на экран. Еще есть процедура, которая рисует охотника в центре экрана, которым нужно управлять. Но как управлять охотником, если уже выполняется процедура вывода мышей на экран? ReadKey не помогает, он останавливает программу в ожидании нажатия клавиши.
Второй вопрос, но тоже по теме. Чтобы убить мышку, нужно направить ружьё охотника на неё и нажать клавишу "Пробел". Как это можно реализовать в моём коде?
Видимо не верно ты ридкей юзать пытаешься ... Делай так :
while keypressed do ch := readkey;
Это выход, но все равно скорости работы явно не хватает. Может, есть принципиально другие решения? И что с вторым вопросом?
Вот это
PutPixel(xT,yT,0);
Пишу именно лабораторку..
Всем доброе время суток. Переписал алгоритм, используя GetImage. Сама по себе эта функция не устранила тормоза, но с ней работать оказалось гораздо удобнее.
For i:=1 To m Doв PutPixel i и j нужно поменять местами, чтобы мышка выводилась на экран не в перевернутом виде? То есть если я пишу
For j:=1 To n Do
PutPixel(j,i,Mouse^[i,j]);
PutPixel(i,j,Mouse^[i,j]);, то изображение выводится на экран, повернутое на 90 град. против часовой стрелки.
2) Так, наверное, и сделать - сравнить углы. Нужно только поместить начало координат в пузо охотнику
Вот функция пересчета из декартовых координат в полярный угол (перевел с сишного алгоритма с 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-файл, содержащий матрицу 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.
Ну так вот:
в этом цикле
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;
For i:=1 To m Do
For j:=1 To n Do
PutPixel(i,j,Mouse^[i,j]);
Поменяй в этом цикле
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;
Тем более, что матрица-то квадратная, 18х18, так что m и n равны. Сколько их не меняй...
Спасибо! А как заюзать функу angle? Как поместить начало координат в центр охотника(центр экрана)?
Ну...
Предположим, что режим 640 на 480. И начало координат вверху слева. И ось У направлена вниз. Так, как это обычно в графических режимах бывает. Пусть Xg и Yg - это координаты точки в данной системе отсчета.
Переносим начало координат в центр экрана и разворачиваем ось Y.
X1 := Xg - 320;
Y1 := 240 - Yg;
Ugol := Angle(Xm-320.0, 240.0-Ym);
Опять косяк.. Я неправильно использую функу 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;
Отвечу завтра. Единственное замечание - стоит ли сравнивать углы на точное равенство? Не лучше ли вычислять их разность и сравнивать ее с некоторой дельтой? Тем более что и мышка ведь не точечная...
Я так и хотел сделать, но сначала я хотел разобраться с точными данными, чтобы потом можно было вносить погрешности.
Простой корявый пример, иллюстрирущий идею.
Прикрепленные файлы
short.pas ( 2.4 килобайт )
Кол-во скачиваний: 287
Круто! Бродяжник, спасибо! Вот, что примерно получилось. Уже играть можно))
MAIN.PAS ( 5.97 килобайт )
Кол-во скачиваний: 541
Теперь нужно перевести это в объекты.
Мужики, зацените мой первый опыт в ООП =) Переписал в ООП охотника из игры. Нормально?
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.
Переписываю мышь в ООП =) Написал с использованием BMP, но не пойму, где ошибка( Мужики, помогите! Почему не работает?
Uses Graph,Crt,Bmp;
Const m=18;
n=18;
Mouses=10;
Type
MouseData=Record
x,y: Integer;
End;
Data=Array[1..m,1..n] Of Integer;
TMouse=Object
Public
Constructor Init(MousePath,KillPath: String; xC,yC: Integer);
Destructor Done;
Function Work: Boolean;
Function xW: Integer;
Function yW: Integer;
Procedure DrawMouse;
Private
x,y: Integer;
Mouse,Kill: String;
Working: Boolean;
End;
Constructor TMouse.Init(MousePath,KillPath: String; xC,yC: Integer);
Begin
Mouse:=MousePath;
Kill:=KillPath;
x:=xC;
y:=yC;
Working:=True;
End;
Destructor TMouse.Done;
Begin
BMPDisplay(Kill,x,y,False);
Delay(10000);
BMPDisplay(Kill,x,y,True);
Working:=False;
End;
Function TMouse.Work: Boolean;
Begin
Work:=Working;
End;
Function TMouse.xW: Integer;
Begin
xW:=x;
End;
Function TMouse.yW: Integer;
Begin
yW:=y;
End;
Procedure TMouse.DrawMouse;
Begin
BMPDisplay(Mouse,x,y,False);
End;
Var Mas: Array[1..Mouses] Of ^TMouse;
i,GD,GM,xT,yT: Integer;
Function RandCoord(Coord: Char): Integer;
Var z,i: Integer;
Flag: Boolean;
Begin
If Coord='x' Then {m}
Begin
Repeat
Flag:=True;
z:=Random(640);
For i:=1 To Mouses Do
If (ABS(z-Mas[i]^.xW))<20 Then
Begin
Flag:=False;
Break
End;
Until (z<622) AND Flag AND ((z<280) Or (z>360));
End;
If Coord='y' Then {n}
Begin
Repeat
Flag:=True;
z:=Random(480);
For i:=1 To Mouses Do
If (ABS(z-Mas[i]^.yW))<20 Then
Begin
Flag:=False;
Break
End;
Until (z<462) AND Flag AND ((z<200) Or (z>280));
End;
RandCoord:=z;
End;
Begin
GD:=Detect;
InitGraph(GD,GM,'');
Randomize;
Repeat
Repeat i:=Random(Mouses) Until i>0;
If Mas[i]^.Work Then
Begin
Mas[i]^.Done
End
Else
Begin
xT:=RandCoord('x');
yT:=RandCoord('y');
Mas[i]^.Init('Mouse.bmp','Kill.bmp',xT,yT);
Mas[i]^.DrawMouse;
End;
Delay(65535);
Until KeyPressed;
End.
If Mas[i]^.Work Then ...формально ты допускаешь грубую ошибку - пытаешься обратиться к переменной объекта, который, возможно, еще не инициализирован. Если твой Object будет содержать виртуальные методы (а то, что ты использовал Constructor - первый шаг к этому), то программа просто вылетит у тебя при первой же попытке выполнения вышеприведенной строки. Да и сама инициализация объектов хромает... Вот так попробуй:
Type
PTMouse = ^TMouse;
Begin
GD:=Detect;
InitGraph(GD,GM,'');
Randomize;
Repeat
Repeat i:=Random(Mouses) Until i>0;
If Mas[i] <> nil then Begin
Dispose(Mas[i], Done); { Это - корректный вызов деструктора }
Mas[i] := nil;
End
Else Begin
xT:=RandCoord('x');
yT:=RandCoord('y');
{ А вот это - правильная инициализация }
Mas[i] := New(PTMouse, Init('Mouse.bmp','Kill.bmp',xT,yT));
Mas[i]^.DrawMouse;
End;
Delay(65535);
Until KeyPressed;
End.
volvo, спасибо большое! Ты очень мне помог