Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Игры";
Текущий архив: 2003.04.03;
Скачать: [xml.tar.bz2];

Вниз

разгоняться тормозить   Найти похожие ветки 

 
sany   (2002-10-25 01:05) [0]

Я решил игрушку с использованием delphix написать, вид сверху ездят авто... ну это не важно. У меня возникло несколько вопросов:
1. Как сделать чтобы это авто при нажатии вперёд или назад постепенно разгонялось и если клавишу отпустить то постепенно останавливалась.
2. Как написать условие когда я нажимаю клавишу1, надо проверить нажата ли клавиша2, если да, то выполнить действие1, если нет, то действие2.
3. Тормозной путь. как его реализоать. при нажатии на кнопку тормаз авто должно ещё некаторое расстояние катится.
Зарание спасибо. Если не трудно напишите кусочки кода. Из-за этих вопросов весь проект застыл.


 
pasha676   (2002-10-25 09:41) [1]

По факту скорости. Задаешь вектор скорости. Каждую итерацию (отрисовку, расчетный период времени) этот вектор плюсуется к вектору положения авто. Если нажат газ - то умножаешь/плюсуешь вектор скорости на определенные коэффиценты или увеличиваешь его по какому угодно закону (вообще изменяешь по заранее приспособленной формуле вообщем). С торможением - то же самое, только формула другая.
С клавишами ничего не подскажу,не работал я с ними, но наверное хуки помогут.


 
CHiF_   (2002-10-25 11:34) [2]

такое я делал как раз в моей игрушке, в принципе все просто,
распишу то что уже сказал pasha676 :

procedure TSimpleObject.addspeed;
begin
speedx:=speedx+cos256(cang)*val;
speedy:=speedy+sin256(cang)*val;
end;

где cang - угол под которым добавляем скорость( для движения вперед он соответственно равен направлению движения)
val - с какой силой, потом прибавляешь это к координатам:
x:=x+speedx;
y:=y+speedy;

можно(нужно) сделать проверку на максимальную скорость:
if sqr(speedx)+sqr(speedy)>sqr(maxspeed) then begin
//angle=arctan2(speedy, speedx) - угол под которым катиться машинка
speedx:=cos(angle)*maxspeed;
speedy:=sin(angle)*maxspeed;
end;

насчет остановки- каждый раз вычитаешь из скорости определенное значение, и если вдруг то что мы вычитаем по модулю больше скорости по модулю, то приравниваем ее к нулю (скорость)

и насчет клавиш - т.к. проект на delphix то можно написать вот так:
if dxinput1.Keyboard.Keys[key1] then
if dxinput1.Keyboard.Keys[key2] then action1 else action2;


вот :D как я много написал :))


 
Axis_of_Evil   (2002-10-25 11:34) [3]

Кинематику учить надо!
Книжку открой: "Движение по окружности",
"равноускоренное движение"


 
sany   (2002-10-25 17:45) [4]

Всем ответившим огромное спосибо, щас попробую, если что не пойму то напишу.


 
sany   (2002-10-26 01:42) [5]

Так, со вторым вопросом я разобрался. Но вот с 1 и 3 всёравно ничего не получается. Если надо посмотреть весь код, то он тут: http://afsoft.narod.ru/kod.txt


 
CHiF   (2002-10-26 11:35) [6]

ты неправильно там делаешь:
if isup in form1.DXInput1.States then
begin
speed:=+5
end;

какого же ты разгона/торможения таким образом добъешся если ты присваиваешь скорости фиксированное число, вместо это к скорости надо прибовлять это число, а не просто присваивать, складывается такое впечатление что у кого-то действительно проблемы с физикой
speed:=speed+5;


 
deema123   (2002-10-30 18:23) [7]

Sany! Подтверждаю мнение CHiF!
Но для ускорения работы проги лучше используй


Inc(Speed,5)

Это для увеличения V, для уменьшения V:
Dec(Speed,5)


 
Dr_Mike   (2002-10-31 01:21) [8]


unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
DXInput, DXClass, DXSprite, DXDraws;

type
TForm1 = class(TForm)
DXDraw1: TDXDraw;
DXImageList1: TDXImageList;
DXSpriteEngine1: TDXSpriteEngine;
DXTimer1: TDXTimer;
DXInput1: TDXInput;
procedure DXDraw1Initialize(Sender: TObject);
procedure DXDraw1Finalize(Sender: TObject);
procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure FormCreate(Sender: TObject);
procedure DXTimer1Timer(Sender: TObject; LagCount: Integer);
end;

var

Form1 : TForm1;

speedx, speedy: Integer; // скорости по оси Х и У соответственно

kUp, kDown, // флаги - используются для того, чтобы
kLeft, kRight : Boolean; // определить, была в прошлый раз нажата
// соответствующая клавиша

implementation

{$R *.DFM}

type

TPlayerSprite = class(TImageSprite)
protected
procedure DoMove(MoveCount: Integer); override;
end;{TPlayerSprite}

procedure TPlayerSprite.DoMove(MoveCount: integer);
begin
inherited DoMove(MoveCount);
x:= x + speedx; { заодно даю одну маленькую задачку - }
y:= y + speedy; { как сделать более резким начало движения ? ;-) }
// скорость может быть как положительной, так и отрицательной -
// последнее означает, что спрайт движется в обратную сторону
{Left Key}
if kLeft then //ЕСЛИ клавиша была нажата в прошлый раз ТО
if (isLeft in Form1.DXInput1.States) then //ЕСЛИ она нажата и сейчас ТО
Dec(speedx)
else begin Inc(speedx); if speedx=0 then kLeft:= False; end //ЕСЛИ скорость
//падает до нуля, то забываем о предыдущих нажатиях
else if (isLeft in Form1.DXInput1.States) then //ЕСЛИ нажата впервые ТО
begin kLeft:= True; Dec(speedx); end; //запоминаем нажатие
{Right Key}
if kRight then
if (isRight in Form1.DXInput1.States) then Inc(speedx)
else begin Dec(speedx); if speedx=0 then kRight:= False; end
else if (isRight in Form1.DXInput1.States) then
begin kRight:= True; Inc(speedx); end;
{Up Key}
if kUp then
if (isUp in Form1.DXInput1.States) then Dec(speedy)
else begin Inc(speedy); if speedy=0 then kUp:= False; end
else if (isUp in Form1.DXInput1.States) then
begin kUp:= True; Dec(speedy); end;
{Down Key}
if kDown then
if (isDown in Form1.DXInput1.States) then Inc(speedy)
else begin Dec(speedy); if speedy=0 then kDown:= False; end
else if (isDown in Form1.DXInput1.States) then
begin kDown:= True; Inc(speedy); end;
{Bounds Check}
if x >= form1.DXDraw1.SurfaceWidth-image.Width then
x:= form1.DXDraw1.SurfaceWidth-image.Width;
if x <= 0 then x:= 1;
if y >= form1.DXDraw1.SurfaceHeight-image.Height then
y:= form1.DXDraw1.SurfaceHeight-image.Height;
if y <= 0 then y:= 1;
end;


procedure TForm1.DXDraw1Initialize(Sender: TObject);
begin
DXTimer1.Enabled:= True;
end;

procedure TForm1.DXDraw1Finalize(Sender: TObject);
begin
DXTimer1.Enabled:= False;
end;

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if Key=VK_ESCAPE then Close;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
Screen.Cursor := CrNone;
with TPlayerSprite.Create(DXSpriteEngine1.Engine) do
begin
PixelCheck:= true;
image:= form1.DXImageList1.Items.Find("pla");
x:= 270;
y:= 220;
width:= image.Width;
height:= image.Height;
end;
kUp:= False;
kDown:= False;
kLeft:= False;
kRight:= False;
speedx:= 0;
speedy:= 0;
end;

procedure TForm1.DXTimer1Timer(Sender: TObject; LagCount: Integer);
begin
if not DXDraw1.CanDraw then Exit;
with DXDraw1.Surface.Canvas do
begin
Brush.Style:= bsClear;
Font.Color:= clWhite;
Font.Size:= 12;
Textout(0, 0, "FPS: "+inttostr(DXTimer1.FrameRate));
Release;
end;
DXDraw1.Flip;
DXInput1.Update;
DXSpriteEngine1.Move(LagCount);
DXSpriteEngine1.Dead;
DXDraw1.Surface.Fill(0);
DXSpriteEngine1.Draw;
end;

end.


 
Dr_Mike   (2002-10-31 01:22) [9]


unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
DXInput, DXClass, DXSprite, DXDraws;

type
TForm1 = class(TForm)
DXDraw1: TDXDraw;
DXImageList1: TDXImageList;
DXSpriteEngine1: TDXSpriteEngine;
DXTimer1: TDXTimer;
DXInput1: TDXInput;
procedure DXDraw1Initialize(Sender: TObject);
procedure DXDraw1Finalize(Sender: TObject);
procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure FormCreate(Sender: TObject);
procedure DXTimer1Timer(Sender: TObject; LagCount: Integer);
end;

var

Form1 : TForm1;

speedx, speedy: Integer; // скорости по оси Х и У соответственно

kUp, kDown, // флаги - используются для того, чтобы
kLeft, kRight : Boolean; // определить, была в прошлый раз нажата
// соответствующая клавиша

implementation

{$R *.DFM}

type

TPlayerSprite = class(TImageSprite)
protected
procedure DoMove(MoveCount: Integer); override;
end;{TPlayerSprite}

procedure TPlayerSprite.DoMove(MoveCount: integer);
begin
inherited DoMove(MoveCount);
x:= x + speedx; { заодно даю одну маленькую задачку - }
y:= y + speedy; { как сделать более резким начало движения ? ;-) }
// скорость может быть как положительной, так и отрицательной -
// последнее означает, что спрайт движется в обратную сторону
{Left Key}
if kLeft then //ЕСЛИ клавиша была нажата в прошлый раз ТО
if (isLeft in Form1.DXInput1.States) then //ЕСЛИ она нажата и сейчас ТО
Dec(speedx)
else begin Inc(speedx); if speedx=0 then kLeft:= False; end //ЕСЛИ скорость
//падает до нуля, то забываем о предыдущих нажатиях
else if (isLeft in Form1.DXInput1.States) then //ЕСЛИ нажата впервые ТО
begin kLeft:= True; Dec(speedx); end; //запоминаем нажатие
{Right Key}
if kRight then
if (isRight in Form1.DXInput1.States) then Inc(speedx)
else begin Dec(speedx); if speedx=0 then kRight:= False; end
else if (isRight in Form1.DXInput1.States) then
begin kRight:= True; Inc(speedx); end;
{Up Key}
if kUp then
if (isUp in Form1.DXInput1.States) then Dec(speedy)
else begin Inc(speedy); if speedy=0 then kUp:= False; end
else if (isUp in Form1.DXInput1.States) then
begin kUp:= True; Dec(speedy); end;
{Down Key}
if kDown then
if (isDown in Form1.DXInput1.States) then Inc(speedy)
else begin Dec(speedy); if speedy=0 then kDown:= False; end
else if (isDown in Form1.DXInput1.States) then
begin kDown:= True; Inc(speedy); end;
{Bounds Check}
if x >= form1.DXDraw1.SurfaceWidth-image.Width then
x:= form1.DXDraw1.SurfaceWidth-image.Width;
if x <= 0 then x:= 1;
if y >= form1.DXDraw1.SurfaceHeight-image.Height then
y:= form1.DXDraw1.SurfaceHeight-image.Height;
if y <= 0 then y:= 1;
end;



 
Dr_Mike   (2002-10-31 01:24) [10]

Прошу прощения, второй раз случайно вышло, попрошу модераторов почистить, как только увижу кого-нибудь :(((


 
pasha676   (2002-10-31 08:50) [11]

2deema123
Ни фига Inc и Dec не увеличивают скорость работы. Даже если ты увеличиваешь на 1 (полный аналог команды ассемблера), что INc(A), что A:=A+1 будут работать однофигственно - в дельфине это вроде оптимизатор отслеживает. К тому же при разгоне-торможении, имхо нужна для реалистичности формула позурьезней, ее через сложения не реализовать.

2Dr_Mike
В иделале ты должен подобрать одну формулу при которой не задавалось бы вопросов типа:
заодно даю одну маленькую задачку -
как сделать более резким начало движения ? ;-)

Или

ЕСЛИ скорость падает до нуля, то забываем о предыдущих нажатиях



 
Dr_Mike   (2002-11-01 01:36) [12]

>pasha676 (31.10.02 08:50)
Честно говоря, я вообще, не понял при чем тут идеал, или мои коментарии к исходному тексту ???

Что касается подбора оптимальной формулы для обеспечения реалистичности (или хотя бы того, что мы привыкли считать таковой) движения, то их существует такое количество, что отдать предпочтение какой-то одной было бы непредусмотрительно - ведь все зависит только от того, какой именно объект будет изображен на спрайте. А маленькой задачкой я назвал это только потому, что даже при беглом взгляде приходит в голову не менее десятка подобных формул - так что пусть народ учиться думать и представлять :-)))

Что касается комментариев, то все они давались тоже только с одной целью (впрочем, как и сам факт наличия ответа, и тем более, приведения исходного кода в полном объеме) - попытаться научить людей мыслить категориями, отличными от тех, которыми они привыкли оперировать при программировании под ДОС :-)))

И тоже, исключительно с образовательной целью. а совсем не из любви к педантизму, я попытался хоть немного отформатироть исходный текст программы, чтобы показать, насколько применение таких простых приемов облегчает жизнь программисту.

А что касается Inc и Dec, то оптимизатор то , конечно, пытается отследить подобные ситуации, но получаемый в результате код операции различается ровно на один байт по длине - а представьте теперь, что подобных команд у вас встречается пару тысяч раз (что кстати, для игровых программ совсем не редкость) ?


 
pasha676   (2002-11-01 11:08) [13]

На счет "в идеале" - это выражение такое с идеалом ничего общего не имеющее. Ну если хочешь перефразирую - надо подобрать формулу движения близкой к реалистичной, быстро считаемую и чтоб можно было обойтись без проверок нажатий клавишь типа "если нет движения, то нажатие влево не считается". Вообщем ерунда - не обращай внимания :).

Насчет оптимизатора. Я не знаю точно как отличается в машинном коде inc(А) от А:=A+1. Но думаю что оптимизатор это делает и автоматом заменяет в маш коде A:=A+1 на inc, для тех типов переменных где это возможно. Если ты практически проверял и оказалось что код с инками короче и быстрее работает - то другое дело. Функции типа inc(speed,5) - точно будут аналогичны speed:=speed+5, т.к. вроде в ассемблере нет такой команды Inc(X,Y), если память моя еще работает, за ассемблером давно не сидел.



 
Asteroid   (2002-11-01 20:28) [14]

> pasha676 (01.11.02 11:08)
Есть в инструкциях пента команда inc


 
xm   (2002-11-01 23:39) [15]

>Насчет оптимизатора. Я не знаю точно как отличается в машинном >коде inc(А) от А:=A+1.
чтобы посмореть, что там оптимизатор наоптимизировал, достаточно поставить брякпоинт на нужную строку, и , во время остановки, посмотреть окно debug>cpu



Страницы: 1 вся ветка

Форум: "Игры";
Текущий архив: 2003.04.03;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.52 MB
Время: 0.009 c
1-6502
DenisLK
2003-03-24 15:54
2003.04.03
qtintf.dll ???


3-6303
VL
2003-03-14 13:00
2003.04.03
про DBGrid


1-6464
som
2003-03-24 12:50
2003.04.03
Файлы и каталоги


3-6337
paa
2003-03-14 10:22
2003.04.03
Работа с таблицей EXCEL


8-6626
Zirus
2002-12-26 13:22
2003.04.03
Звук





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский