
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[216.73.216.52] |
![]() |
|
Сообщ.
#1
,
|
|
|
Здравствуйте, сделала перемещение корабля с помощью стрелок «вперёд, назад».
Корабль движется в том направлении в котором находиться мышка, если мышку переместить, то корабль развернётся и полетит в противоположное направление - пример gif-анимации. ![]() Проблема заключается в том что не получается остановить корабль, при первом нажатии начинается движение. Единственное, что удалось сделать это чтобы можно было изменить движение в зависимости от направлении, если объект летит вперёд, то нажав назад, корабль полетит назад. Если назад то можно направить вперёд. Вообщем как сделать чтобы корабль перемещался только от кнопок (стрелок) клавиатуры. Когда пользователь отпускает кнопку, корабль останавливался? Вот пример кода на Delphi7: Исходники для скачивания: https://disk.yandex.ru/d/8EGNaWHgS3PT4A ![]() ![]() unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, AppEvnts, StdCtrls,Math; type TPoint1 = record mouseX,mouseY:Currency ; end; TForm1 = class(TForm) Image1: TImage; ApplicationEvents1: TApplicationEvents; Label1: TLabel; Timer1: TTimer; Label2: TLabel; ListBox1: TListBox; procedure FormCreate(Sender: TObject); procedure ApplicationEvents1Message(var Msg: tagMSG; var Handled: Boolean); procedure Timer1Timer(Sender: TObject); procedure FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); procedure ListBox1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); private { Private declarations } public { Public declarations } end; TMatrix1 = class private a, b, c,d,tx,ty: Real; x1,y1:Integer; fr:TForm; bitmap0:TBitmap; Cs:TCanvas; //Новые _xvel,_yvel,_xaccel,_yaccel,_nextx,_nexty,_prevx,_prevy,_maxvel,_spin:Real; _colliding,_accelerating:Boolean; public constructor Create(_bitmap:TBitmap;_Cs:TCanvas;_fr:TForm;_a, _b,_c,_d, _tx, _ty: Real; _xvel0,_yvel0, _xaccel0,_yaccel0,_nextx0,_nexty0,_prevx0,_prevy0,_maxvel0, _spin0:Real;_colliding0,_accelerating0:Boolean;_x1,_y1:Integer); Procedure Draw(); function identity ():TMatrix1; function appendTransform (x, y, scaleX, scaleY:Real; rotation:Integer; skewX, skewY, regX, regY:Real):TMatrix1; function append(a2, b2, c2, d2, tx2, ty2:Real):TMatrix1; Procedure proceed(power:Integer); procedure backup(power:Integer); procedure applyForce(angle, power:Integer); procedure setSpeed(speed:Real); procedure accelerate(); procedure animate(); end; function getDistance(delta_x, delta_y:Real):Real; function getDegrees(radians:Real):Real; function getRadians(delta_x, delta_y:Real):Real; var Form1: TForm1; bmp1: TBitmap; rotate1:Integer = 90; pt:TPoint1; mtx:TMatrix1; leftb,rightb,downb,upb : Boolean; implementation {$R *.dfm} function getRadians(delta_x, delta_y:Real):Real; var r:Real; begin r:=ArcTan2(delta_y, delta_x); if delta_y < 0 then begin r := r + 6.283; end; Result:=r; end; function getDegrees(radians:Real):Real; begin Result:=radians / 0.01745; end; function getDistance(delta_x, delta_y:Real):Real; begin Result:=sqrt((delta_x*delta_x)+(delta_y*delta_y)); end; constructor TMatrix1.Create(_bitmap:TBitmap;_Cs:TCanvas;_fr:TForm;_a, _b,_c,_d, _tx, _ty: Real;_xvel0,_yvel0, _xaccel0,_yaccel0,_nextx0,_nexty0,_prevx0,_prevy0,_maxvel0, _spin0:Real;_colliding0,_accelerating0:Boolean;_x1,_y1:Integer); begin inherited Create; fr:=_fr; bitmap0:=_bitmap; Cs:=_Cs; a:=_a; b:=_b; c:=_d; tx:=_tx; ty:=_ty; x1:=_x1; y1:=_y1; //Новые переменные _xvel:=_xvel0; _yvel:=_yvel0; _xaccel:=_xaccel0; _yaccel:=_yaccel0; _nextx:=_nextx0; _nexty:=_nexty0; _prevx:=_prevx0; _prevy:=_prevy0; _spin:=_spin0; _maxvel:=_maxvel0; _colliding:=_colliding0; _accelerating:=_accelerating0; end; procedure TMatrix1.proceed(power:Integer); var a,a1,a2:Real; begin a1:=Math.Floor(_xvel*_xvel); a2:=Math.Floor(_yvel*_yvel); a := Sqrt(a1 + a2); if power = 0 then power := 2 else power := Math.Min(2,power); //if a < _maxvel then // fireEngine(power, offset); setSpeed(_maxvel); end; procedure TMatrix1.backup(power:Integer); var a,a1,a2:Real; begin a1 := Math.Floor(_xvel * _xvel); a2 := Math.Floor(_yvel * _yvel); a := Sqrt(a1 + a2); setSpeed(0 - _maxvel); end; procedure TMatrix1.accelerate(); begin _xvel:=_xvel+_xaccel; _yvel:=_yvel+_yaccel; _accelerating:=False; _xaccel:=0; _yaccel:=0; end; procedure TMatrix1.animate(); begin if (Abs(_xvel) >= 0.3) or (Abs(_yvel) >= 0.3) or _accelerating or _colliding then begin _nextx := x1 + _xvel + _xaccel; _nexty := y1 + _yvel + _yaccel; if _colliding then begin _colliding := false; _yaccel := 0; _xaccel := 0; end else begin accelerate(); end; _prevx := x1; _prevy := y1; x1 := x1 + Math.min(Math.Floor(_maxvel), Math.max(Math.Floor(0 - _maxvel), Math.Floor(_xvel))); y1 := y1 + Math.min(Math.Floor(_maxvel), Math.max(Math.Floor(0 - _maxvel), Math.Floor(_yvel))); end; end; procedure TMatrix1.Draw(); var HDC2:THandle; M:TXFORM; begin mtx.identity(); mtx.appendTransform(x1, y1, 1, 1, rotate1, 0, 0, 16, 29.5); hDc2 := Cs.Handle; SetGraphicsMode(hDc2, GM_ADVANCED); SaveDC(hDc2); fillChar(M, sizeOf(M), 0); M.eM11 := mtx.a; M.eM12 := mtx.b; M.eM21 := mtx.c; M.eM22 := mtx.d; M.eDx := mtx.tx; M.eDy := mtx.ty; ModifyWorldTransform(hDc2, M, MWT_LEFTMULTIPLY); Cs.Draw(0,0,bitmap0); RestoreDC(HDC2,1); end; procedure TMatrix1.applyForce(angle, power:Integer); begin end; function TMatrix1.identity():TMatrix1; begin a := 1; d := 1; b := 0; c := 0; tx := 0; ty := 0; Result:=mtx; end; function TMatrix1.appendTransform(x, y, scaleX, scaleY:Real; rotation:Integer; skewX, skewY, regX, regY:Real):TMatrix1; var r, cos1, sin1:Real; a1:Integer; begin a1:=rotation mod 360; if a1 < 360 then begin r := rotation*PI/180; cos1 := cos(r); sin1 := sin(r); end else begin cos1 := 1; sin1 := 0; end; append(cos1*scaleX, sin1*scaleX, -sin1*scaleY, cos1*scaleY, x, y); tx := tx - (regX*a+regY*c); ty := ty - (regX*b+regY*d); Result:=mtx; end; function TMatrix1.append(a2, b2, c2, d2, tx2, ty2:Real):TMatrix1; var a1,b1,c1,d1:Real; begin a1:=a; b1:=b; c1:=c; d1:=d; if (a2 <> 1) or (b2 <> 0) or (c2 <> 0) or (d2 <> 1) then begin a := a1*a2+c1*b2; b := b1*a2+d1*b2; c := a1*c2+c1*d2; d := b1*c2+d1*d2; end; tx:=a1*tx2+c1*ty2+tx; ty:=b1*tx2+d1*ty2+ty; Result:=mtx; end; procedure TMatrix1.setSpeed(speed:Real); var a:Real; begin a := 0.0174532925199 * rotate1; speed := Math.min(_maxvel, Math.max(speed, 0 - _maxvel)); _xvel := Cos(a) * speed; _yvel := Sin(a) * speed; _accelerating := true; end; procedure TForm1.FormCreate(Sender: TObject); begin bmp1 := TBitmap.Create; bmp1.LoadFromFile('.\WeaponQuadSkin.bmp'); mtx:=TMatrix1.Create(bmp1,Image1.Canvas,Form1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,false,false,225,275); Timer1.Enabled:=True; end; procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG; var Handled: Boolean); var P : TPoint; begin if Msg.message = WM_MOUSEMOVE then begin P:=Image1.ScreenToClient(Mouse.CursorPos); pt.mouseX := P.X; pt.mouseY := P.Y; end; end; procedure TForm1.Timer1Timer(Sender: TObject); var dx1, dy1, _rotateTo:Real; power:Integer; _trueRotation:Real; begin if rightb = true then begin end; if leftb = true then begin end; if upb = true then begin mtx.backup(power); end; if downb = true then begin mtx.proceed(power); end; dx1 := mtx.x1 - pt.mouseX; dy1 := mtx.y1 - pt.mouseY; _rotateTo := getDegrees(getRadians(dx1, dy1)); Form1.Image1.Canvas.Brush.Color:=clWhite; Form1.Image1.Canvas.FillRect(Form1.Image1.ClientRect); if rotate1 > 180 then rotate1 := -180; if rotate1 < -180 then rotate1 := 180; if _rotateTo > rotate1 + 180 then _rotateTo := _rotateTo - 360; if _rotateTo < rotate1 - 180 then _rotateTo := _rotateTo + 360; _trueRotation := (_rotateTo - rotate1); rotate1:=Trunc(rotate1+_trueRotation); // Label2.Caption:=FloatToStr(rotate1); mtx.animate; mtx.Draw(); end; procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); begin //case Key of //vk_RIGHT: rightb := false; //vk_LEFT: leftb := false; //vk_UP: upb := false; //vk_DOWN: downb := false; //end; end; procedure TForm1.ListBox1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin case key of vk_RIGHT: rightb := true; vk_LEFT: leftb := true; vk_UP: begin upb := true; downb := false; end; vk_DOWN: begin upb := false; downb := true; end; end; end; end. |
Сообщ.
#2
,
|
|
|
А почему у вас в KeyUp закомментирован код, который записывает отжатие кнопок и соответственно снимает состояние движения?
|
Сообщ.
#3
,
|
|
|
У вас нажатие procedure TForm1.ListBox1KeyDown, а вот отпускание вы ловите у procedure TForm1.FormKeyUp
|
Сообщ.
#4
,
|
|
|
Да даже если раскомментировать отпускание кнопок, то ничего не поменяется корабль будет бесконечно двигаться при нажатии. Отпускание кнопок никакую роль не играют.
![]() ![]() unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, AppEvnts, StdCtrls,Math; type TPoint1 = record mouseX,mouseY:Currency ; end; TForm1 = class(TForm) Image1: TImage; ApplicationEvents1: TApplicationEvents; Label1: TLabel; Timer1: TTimer; Label2: TLabel; ListBox1: TListBox; procedure FormCreate(Sender: TObject); procedure ApplicationEvents1Message(var Msg: tagMSG; var Handled: Boolean); procedure Timer1Timer(Sender: TObject); procedure FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); procedure ListBox1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); private { Private declarations } public { Public declarations } end; TMatrix1 = class private a, b, c,d,tx,ty: Real; x1,y1:Integer; fr:TForm; bitmap0:TBitmap; Cs:TCanvas; //Новые _xvel,_yvel,_xaccel,_yaccel,_nextx,_nexty,_prevx,_prevy,_maxvel,_spin:Real; _colliding,_accelerating:Boolean; public constructor Create(_bitmap:TBitmap;_Cs:TCanvas;_fr:TForm;_a, _b,_c,_d, _tx, _ty: Real; _xvel0,_yvel0, _xaccel0,_yaccel0,_nextx0,_nexty0,_prevx0,_prevy0,_maxvel0, _spin0:Real;_colliding0,_accelerating0:Boolean;_x1,_y1:Integer); Procedure Draw(); function identity ():TMatrix1; function appendTransform (x, y, scaleX, scaleY:Real; rotation:Integer; skewX, skewY, regX, regY:Real):TMatrix1; function append(a2, b2, c2, d2, tx2, ty2:Real):TMatrix1; Procedure proceed(power:Integer); procedure backup(power:Integer); procedure applyForce(angle, power:Integer); procedure setSpeed(speed:Real); procedure accelerate(); procedure animate(); end; function getDistance(delta_x, delta_y:Real):Real; function getDegrees(radians:Real):Real; function getRadians(delta_x, delta_y:Real):Real; var Form1: TForm1; bmp1: TBitmap; rotate1:Integer = 90; pt:TPoint1; mtx:TMatrix1; leftb,rightb,downb,upb : Boolean; implementation {$R *.dfm} function getRadians(delta_x, delta_y:Real):Real; var r:Real; begin r:=ArcTan2(delta_y, delta_x); if delta_y < 0 then begin r := r + 6.283; end; Result:=r; end; function getDegrees(radians:Real):Real; begin Result:=radians / 0.01745; end; function getDistance(delta_x, delta_y:Real):Real; begin Result:=sqrt((delta_x*delta_x)+(delta_y*delta_y)); end; constructor TMatrix1.Create(_bitmap:TBitmap;_Cs:TCanvas;_fr:TForm;_a, _b,_c,_d, _tx, _ty: Real;_xvel0,_yvel0, _xaccel0,_yaccel0,_nextx0,_nexty0,_prevx0,_prevy0,_maxvel0, _spin0:Real;_colliding0,_accelerating0:Boolean;_x1,_y1:Integer); begin inherited Create; fr:=_fr; bitmap0:=_bitmap; Cs:=_Cs; a:=_a; b:=_b; c:=_d; tx:=_tx; ty:=_ty; x1:=_x1; y1:=_y1; //Новые переменные _xvel:=_xvel0; _yvel:=_yvel0; _xaccel:=_xaccel0; _yaccel:=_yaccel0; _nextx:=_nextx0; _nexty:=_nexty0; _prevx:=_prevx0; _prevy:=_prevy0; _spin:=_spin0; _maxvel:=_maxvel0; _colliding:=_colliding0; _accelerating:=_accelerating0; end; procedure TMatrix1.proceed(power:Integer); var a,a1,a2:Real; begin a1:=Math.Floor(_xvel*_xvel); a2:=Math.Floor(_yvel*_yvel); a := Sqrt(a1 + a2); if power = 0 then power := 2 else power := Math.Min(2,power); //if a < _maxvel then // fireEngine(power, offset); setSpeed(_maxvel); end; procedure TMatrix1.backup(power:Integer); var a,a1,a2:Real; begin a1 := Math.Floor(_xvel * _xvel); a2 := Math.Floor(_yvel * _yvel); a := Sqrt(a1 + a2); setSpeed(0 - _maxvel); end; procedure TMatrix1.accelerate(); begin _xvel:=_xvel+_xaccel; _yvel:=_yvel+_yaccel; _accelerating:=False; _xaccel:=0; _yaccel:=0; end; procedure TMatrix1.animate(); begin if (Abs(_xvel) >= 0.3) or (Abs(_yvel) >= 0.3) or _accelerating or _colliding then begin _nextx := x1 + _xvel + _xaccel; _nexty := y1 + _yvel + _yaccel; if _colliding then begin _colliding := false; _yaccel := 0; _xaccel := 0; end else begin accelerate(); end; _prevx := x1; _prevy := y1; x1 := x1 + Math.min(Math.Floor(_maxvel), Math.max(Math.Floor(0 - _maxvel), Math.Floor(_xvel))); y1 := y1 + Math.min(Math.Floor(_maxvel), Math.max(Math.Floor(0 - _maxvel), Math.Floor(_yvel))); end; end; procedure TMatrix1.Draw(); var HDC2:THandle; M:TXFORM; begin mtx.identity(); mtx.appendTransform(x1, y1, 1, 1, rotate1, 0, 0, 16, 29.5); hDc2 := Cs.Handle; SetGraphicsMode(hDc2, GM_ADVANCED); SaveDC(hDc2); fillChar(M, sizeOf(M), 0); M.eM11 := mtx.a; M.eM12 := mtx.b; M.eM21 := mtx.c; M.eM22 := mtx.d; M.eDx := mtx.tx; M.eDy := mtx.ty; ModifyWorldTransform(hDc2, M, MWT_LEFTMULTIPLY); Cs.Draw(0,0,bitmap0); RestoreDC(HDC2,1); end; procedure TMatrix1.applyForce(angle, power:Integer); begin end; function TMatrix1.identity():TMatrix1; begin a := 1; d := 1; b := 0; c := 0; tx := 0; ty := 0; Result:=mtx; end; function TMatrix1.appendTransform(x, y, scaleX, scaleY:Real; rotation:Integer; skewX, skewY, regX, regY:Real):TMatrix1; var r, cos1, sin1:Real; a1:Integer; begin a1:=rotation mod 360; if a1 < 360 then begin r := rotation*PI/180; cos1 := cos(r); sin1 := sin(r); end else begin cos1 := 1; sin1 := 0; end; append(cos1*scaleX, sin1*scaleX, -sin1*scaleY, cos1*scaleY, x, y); tx := tx - (regX*a+regY*c); ty := ty - (regX*b+regY*d); Result:=mtx; end; function TMatrix1.append(a2, b2, c2, d2, tx2, ty2:Real):TMatrix1; var a1,b1,c1,d1:Real; begin a1:=a; b1:=b; c1:=c; d1:=d; if (a2 <> 1) or (b2 <> 0) or (c2 <> 0) or (d2 <> 1) then begin a := a1*a2+c1*b2; b := b1*a2+d1*b2; c := a1*c2+c1*d2; d := b1*c2+d1*d2; end; tx:=a1*tx2+c1*ty2+tx; ty:=b1*tx2+d1*ty2+ty; Result:=mtx; end; procedure TMatrix1.setSpeed(speed:Real); var a:Real; begin a := 0.0174532925199 * rotate1; speed := Math.min(_maxvel, Math.max(speed, 0 - _maxvel)); _xvel := Cos(a) * speed; _yvel := Sin(a) * speed; _accelerating := true; end; procedure TForm1.FormCreate(Sender: TObject); begin bmp1 := TBitmap.Create; bmp1.LoadFromFile('.\WeaponQuadSkin.bmp'); mtx:=TMatrix1.Create(bmp1,Image1.Canvas,Form1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,false,false,225,275); Timer1.Enabled:=True; end; procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG; var Handled: Boolean); var P : TPoint; begin if Msg.message = WM_MOUSEMOVE then begin P:=Image1.ScreenToClient(Mouse.CursorPos); pt.mouseX := P.X; pt.mouseY := P.Y; end; end; procedure TForm1.Timer1Timer(Sender: TObject); var dx1, dy1, _rotateTo:Real; power:Integer; _trueRotation:Real; begin if rightb = true then begin end; if leftb = true then begin end; if upb = true then begin mtx.backup(power); end; if downb = true then begin mtx.proceed(power); end; dx1 := mtx.x1 - pt.mouseX; dy1 := mtx.y1 - pt.mouseY; _rotateTo := getDegrees(getRadians(dx1, dy1)); Form1.Image1.Canvas.Brush.Color:=clWhite; Form1.Image1.Canvas.FillRect(Form1.Image1.ClientRect); if rotate1 > 180 then rotate1 := -180; if rotate1 < -180 then rotate1 := 180; if _rotateTo > rotate1 + 180 then _rotateTo := _rotateTo - 360; if _rotateTo < rotate1 - 180 then _rotateTo := _rotateTo + 360; _trueRotation := (_rotateTo - rotate1); rotate1:=Trunc(rotate1+_trueRotation); // Label2.Caption:=FloatToStr(rotate1); mtx.animate; mtx.Draw(); end; procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); begin case Key of //vk_RIGHT: rightb := false; //vk_LEFT: leftb := false; vk_UP: upb := false; vk_DOWN: downb := false; end; end; procedure TForm1.ListBox1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin case key of vk_RIGHT: rightb := true; vk_LEFT: leftb := true; vk_UP: begin upb := true; //downb := false; end; vk_DOWN: begin //upb := false; downb := true; end; end; end; end. |
Сообщ.
#5
,
|
|
|
Так вы опять обработчик нажатия ловите у одного объекта (ListBox), а отпускания ждете у другого(Form). Так нельзя. Создайте обработчик отпускания для ListBox'а
|
Сообщ.
#6
,
|
|
|
Причём тут обработчик ListBox и Form это вообще никак не влияет корабль будет двигаться бесконечно не зависимо на что я повещу нажатие кнопок. Я проверала на других языках программирования там тоже самое что и на delphi. Там нет не ListBox, ни Form.
|
Сообщ.
#7
,
|
|
|
Вы поставили у формы KeyPreview? После этого проверьте, что кнопки отлавливаются (например, в обработчиках KeyUp и KeyDown выводите в заголовок код клавиши Key)
|
Сообщ.
#8
,
|
|
|
Так. Вы по таймеру вызываете mtx.backup(power); и mtx.proceed(power);
Они устанавливают переменную скорость у объекта. Поэтому просто установив кнопку в false вы не обнуляете скорость. Если хотите остановить объект вызовите mtx.setSpeed(0); Но для этого выделите скажем кнопку backspace иначе у вас объект потеряет инерцию движения. |