我正在尝试使鼠标单击一定距离的形状移动。我尝试为鼠标点击事件的x和y创建变量,并在x和y中创建到达鼠标点击位置的距离,并使用计时器划分+截断值以使形状在该方向上移动,虽然我的问题是我需要移动特定距离的形状,无论光标在哪里,只需使用鼠标单击方向,以及使用此方法不会以恒定速度移动的形状。
当前代码: 鼠标按下:
mx := x;
my := y;
计时器:
shape1.left := shape1.Left + (mx - shape1.left + 8) div 32;
shape1.top := shape1.top + (my - shape1.top + 8) div 32;
答案 0 :(得分:5)
您的方法存在的问题是,您每单位时间移动的数量与形状和鼠标点击位置之间的距离成正比。从鼠标位置获得的所有方法都是一个方向,获得方向的标准方法是规范化感兴趣点之间形成的向量。
除以感兴趣点之间形成的线段的大小,在您想要的方向上产生长度为1px的单位矢量。然后必须通过速度缩放以产生运动增量。
这与整数一样笨拙,因为你的增量必须在每一步舍入,但可以按如下方式完成:
procedure TForm1.Timer1Timer(Sender: TObject);
const
SPEED = 5;
var
dx, dy : integer;
mag : double;
begin
dx := mx - Shape1.Left; {vector x}
dy := my - Shape1.Top; {vector y}
mag := Sqrt(dx*dx + dy*dy); {vector magnitude}
if (Abs(dx) > SPEED) or (Abs(dy) > SPEED) then
begin
{ use Ceil to move at least 1px. }
Shape1.Left := Shape1.Left
+ Sign(dx)*Ceil(SPEED*Abs(dx)/mag); {divide by mag}
Shape1.Top := Shape1.Top {to give a unit}
+ Sign(dy)*Ceil(SPEED*Abs(dy)/mag); {vector in the}
end else begin {required direction}
Shape1.Left := mx; {snap to mx/my if close enough}
Shape1.Top := my; {deals with rounding issues...}
end;
end;
否则,更优雅的是,您可以将形状的位置存储在浮点对中,并仅在设置控件的位置时舍入为整数。这避免了整个过程中每个步骤的整数精度问题。
答案 1 :(得分:1)
以下内容考虑了距离和恒定速度,并使用浮点数进行计算以获得更高的精度。
以下列形式声明:
private
mx, my: integer; // mouse down
Steps: integer;
StepCount: integer;
OrgPos: TPoint; // original position
TrgPos: TPoint; // target position at angle and distance from orig. pos.
DeltaX: single; // x movement per step
DeltaY: single; // y movement per step
表格OnMouseDown:
var
angle: single;
dx, dy: single;
dist: single;
begin
mx := X;
my := Y;
Steps := 32;
StepCount := 0;
dist := 100.0;
// shape origin
OrgPos.X := Shape1.Left;
OrgPos.Y := Shape1.Top;
// get the angle
dx := Abs(mx - OrgPos.X);
if dx = 0 then dx := 0.00000001;
dy := Abs(my - OrgPos.Y);
if dy = 0 then dy := 0.00000001;
angle := arctan(dy/dx);
// correction for quadrant
if (OrgPos.X>mx) and (OrgPos.Y<my) then angle := Pi-angle;
if (OrgPos.X>mx) and (OrgPos.Y>my) then angle := Pi+angle;
if (OrgPos.X<mx) and (OrgPos.Y>my) then angle := 2*Pi-angle;
// endpoint based on angle and distance
TrgPos.X := round(OrgPos.X + dist*cos(angle));
TrgPos.Y := round(OrgPos.Y + dist*sin(angle));
// x and y changes per step
DeltaX := (TrgPos.X - OrgPos.X) / Steps;
DeltaY := (TrgPos.Y - OrgPos.Y) / Steps;
Timer1.Enabled := True;
end;
计时器代码:
Inc(StepCount);
Shape1.Left := OrgPos.X + Round(StepCount * DeltaX);
Shape1.Top := OrgPos.Y + Round(StepCount * DeltaY);
if StepCount >= Steps then
Timer1.Enabled := False;
将新位置计算为OrgPos.X + Round(StepCount * DeltaX);
可防止出现级联错误。
答案 2 :(得分:0)
无需使用计时器。如果按下鼠标左键,则可以移动形状。
Running experiment with config {
"training": {
"env": "Asteroids-v0",
"run": "DQN",
"stop": {
"training_iteration": 1
},
"local_dir": "/opt/ml/output/intermediate",
"checkpoint_freq": 10,
"config": {
"double_q": false,
"dueling": false,
"num_atoms": 1,
"noisy": false,
"prioritized_replay": false,
"n_step": 1,
"target_network_update_freq": 8000,
"lr": 6.25e-05,
"adam_epsilon": 0.00015,
"hiddens": [
512
],
"learning_starts": 20000,
"buffer_size": 1000000,
"sample_batch_size": 4,
"train_batch_size": 32,
"schedule_max_timesteps": 2000000,
"exploration_final_eps": 0.01,
"exploration_fraction": 0.1,
"prioritized_replay_alpha": 0.5,
"beta_annealing_fraction": 1.0,
"final_prioritized_replay_beta": 1.0,
"num_gpus": 0.2,
"timesteps_per_iteration": 10000
},
"checkpoint_at_end": true
},
"trial_resources": {
"cpu": 1,
"extra_cpu": 3
}
}
Important! Ray with version <=7.2 may report "Did not find checkpoint file" even if the experiment is actually restored successfully. If restoration is expected, please check "training_iteration" in the experiment info to confirm.
Traceback (most recent call last):
File "train-ray.py", line 83, in <module>
MyLauncher().train_main()
File "/opt/ml/code/sagemaker_rl/ray_launcher.py", line 332, in train_main
launcher.launch()
File "/opt/ml/code/sagemaker_rl/ray_launcher.py", line 313, in launch
run_experiments(experiment_config)
File "/usr/local/lib/python3.6/dist-packages/ray/tune/tune.py", line 296, in run_experiments
experiments = convert_to_experiment_list(experiments)
File "/usr/local/lib/python3.6/dist-packages/ray/tune/experiment.py", line 199, in convert_to_experiment_list
for name, spec in experiments.items()
File "/usr/local/lib/python3.6/dist-packages/ray/tune/experiment.py", line 199, in <listcomp>
for name, spec in experiments.items()
File "/usr/local/lib/python3.6/dist-packages/ray/tune/experiment.py", line 122, in from_json
raise TuneError("No trainable specified!")
ray.tune.error.TuneError: No trainable specified!
2020-04-22 13:21:15,784 sagemaker-containers ERROR ExecuteUserScriptError:
Command "/usr/bin/python train-ray.py --rl.training.checkpoint_freq 1 --rl.training.stop.training_iteration 1 --s3_bucket XXXXX
创建表单时。
var
LeftMousePressed2 : Boolean ;
X_original,Y_original : cardinal ;
在这里您可以获得鼠标的原始坐标
procedure TForm1.FormCreate(Sender: TObject);
begin
LeftMousePressed2 := false ;
end;
移动(按下鼠标+左键)时,形状也会移动:
procedure TForm1.Shape1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Button = mbLeft then
begin
X_original:=x;
Y_original:=y;
LeftMousePressed2 := true ;
end;
从鼠标上抬起手指时
procedure TForm1.Shape1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y : Integer);
begin
if LeftMousePressed2 then
begin
shape1.Left := Shape1.Left +(x-X_original);
shape1.Top := shape1.Top + (y-Y_original);
end;
end;