如何绘制随机 y 值的静态长度线
How to draw a static length line at random y values
我正在尝试创建一个小游戏,您必须使用 "turret" 来射击目标。目前我被困在我的目标线上。我的目标是让它以设定的 X 值生成,但每次我按下重绘按钮时它以随机的 Y 值生成。但是我的代码有问题。该线并非始终具有相同长度并以随机 Y 值生成,而是似乎以随机长度和随机 Y 值生成。如果有人能帮我找出我哪里出错了那将是完美的。
相关的变量有xTarget
,yTarget
(直线的第一个y值)yTargetEnd
(直线的第二个y值)targetLine
(行的静态长度)和 DrawLine()
方法调用 targetLine
.
在我看来,我设置它的方式很有意义,但它似乎并没有达到我的预期。我尝试将 yTarget
设置为随机数,然后将 yTargetEnd
设置为 yTarget + targetLine
,因此它的长度应该始终为 50,但这似乎根本不起作用?
public partial class Form1 : Form
{
Random rnd = new Random { };
double xEnd = 0;
double yEnd = 0;
double xOrigin = 30;
double yOrigin = 450;
double xFire;
double yFire;
double xTarget = 500;
double yTarget;
double yTargetEnd;
double xHor = 30;
double yHor = 350;
double xVert = 130;
double yVert = 450;
double fireLine = 750;
double lineLength = 50;
double targetLine = 50;
public Form1()
{
xEnd = xOrigin + lineLength;
yEnd = yOrigin;
xFire = xOrigin + fireLine;
yFire = yOrigin;
InitializeComponent();
}
private void LineDrawEvent(object sender, PaintEventArgs paint)
{
Graphics drawSurface = paint.Graphics;
Pen turretLine = new Pen(Color.Blue);
Pen graphHorizontal = new Pen(Color.Red);
Pen graphVertical = new Pen(Color.Red);
Pen firedLine = new Pen(Color.Blue);
Pen targetLine = new Pen(Color.Black);
float[] dashValues = { 5, 2 };
firedLine.DashPattern = dashValues;
drawSurface.DrawLine(graphVertical, (int)xOrigin, (int)yOrigin, (int)xHor, (int)yHor);
drawSurface.DrawLine(graphHorizontal, (int)xOrigin, (int)yOrigin, (int)xVert, (int)yVert);
drawSurface.DrawLine(firedLine, (int)xOrigin, (int)yOrigin, (int)xFire, (int)yFire);
drawSurface.DrawLine(targetLine, (int)xTarget, (int)yTarget, (int)xTarget, (int)yTargetEnd);
double angleInRadians = ConvertDegsToRads((double)trckBarAngle.Value);
xEnd = xOrigin + lineLength * Math.Cos(angleInRadians / 2.0);
yEnd = yOrigin - lineLength * Math.Sin(angleInRadians / 2.0);
drawSurface.DrawLine(turretLine, (int)xOrigin, (int)yOrigin, (int)xEnd, (int)yEnd);
this.Refresh();
}
private void trckBarAngle_Scroll(object sender, EventArgs e)
{
lblAngle.Text = "Angle is:" + Convert.ToString((double)trckBarAngle.Value / 2.0);
}
private double ConvertDegsToRads(double degrees)
{
return degrees * (Math.PI / 180.0);
}
private void btnFire_Click(object sender, EventArgs e)
{
double angleInDegrees = trckBarAngle.Value;
double angleInRadians = ConvertDegsToRads(angleInDegrees);
xFire = xOrigin + fireLine * Math.Cos(angleInRadians / 2.0);
yFire = yOrigin - fireLine * Math.Sin(angleInRadians / 2.0);
this.Refresh();
}
private void btnRedraw_Click(object sender, EventArgs e)
{
yTargetEnd = yTarget - targetLine;
yTarget = rnd.Next(100, 500);
}
}
设计师生成的代码:
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.lblAngle = new System.Windows.Forms.Label();
this.trckBarAngle = new System.Windows.Forms.TrackBar();
this.btnFire = new System.Windows.Forms.Button();
this.btnRedraw = new System.Windows.Forms.Button();
((System.ComponentModel.ISupportInitialize)(this.trckBarAngle)).BeginInit();
this.SuspendLayout();
//
// lblAngle
//
this.lblAngle.AutoSize = true;
this.lblAngle.Location = new System.Drawing.Point(13, 13);
this.lblAngle.Name = "lblAngle";
this.lblAngle.Size = new System.Drawing.Size(46, 17);
this.lblAngle.TabIndex = 0;
this.lblAngle.Text = "label1";
//
// trckBarAngle
//
this.trckBarAngle.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Right)));
this.trckBarAngle.LargeChange = 10;
this.trckBarAngle.Location = new System.Drawing.Point(732, 42);
this.trckBarAngle.Maximum = 360;
this.trckBarAngle.Minimum = -360;
this.trckBarAngle.Name = "trckBarAngle";
this.trckBarAngle.Orientation = System.Windows.Forms.Orientation.Vertical;
this.trckBarAngle.Size = new System.Drawing.Size(56, 495);
this.trckBarAngle.TabIndex = 1;
this.trckBarAngle.Scroll += new System.EventHandler(this.trckBarAngle_Scroll);
//
// btnFire
//
this.btnFire.Location = new System.Drawing.Point(632, 13);
this.btnFire.Name = "btnFire";
this.btnFire.Size = new System.Drawing.Size(75, 23);
this.btnFire.TabIndex = 2;
this.btnFire.Text = "Fire";
this.btnFire.UseVisualStyleBackColor = true;
this.btnFire.Click += new System.EventHandler(this.btnFire_Click);
//
// btnRedraw
//
this.btnRedraw.Location = new System.Drawing.Point(713, 13);
this.btnRedraw.Name = "btnRedraw";
this.btnRedraw.Size = new System.Drawing.Size(75, 23);
this.btnRedraw.TabIndex = 2;
this.btnRedraw.Text = "Redraw";
this.btnRedraw.UseVisualStyleBackColor = true;
this.btnRedraw.Click += new System.EventHandler(this.btnRedraw_Click);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 549);
this.Controls.Add(this.btnRedraw);
this.Controls.Add(this.btnFire);
this.Controls.Add(this.trckBarAngle);
this.Controls.Add(this.lblAngle);
this.Name = "Form1";
this.Text = "Form1";
this.Paint += new System.Windows.Forms.PaintEventHandler(this.LineDrawEvent);
((System.ComponentModel.ISupportInitialize)(this.trckBarAngle)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label lblAngle;
private System.Windows.Forms.TrackBar trckBarAngle;
private System.Windows.Forms.Button btnFire;
private System.Windows.Forms.Button btnRedraw;
}
基本问题归结为代码根本不符合您的预期。您写道:
I try to set yTarget
to a random number and then set yTargetEnd
to yTarget + targetLine
但这实际上不是代码的作用。您的代码以相反的顺序执行这两件事。因此 yTargetEnd
值始终基于 上一个 目标位置,而不是新选择的位置。
您的代码应该如下所示:
private void btnRedraw_Click(object sender, EventArgs e)
{
yTarget = rnd.Next(100, 500);
yTargetEnd = yTarget - targetLine;
}
即编写代码,使其符合您的规范。 :)
回答完之后,您的代码中还有一些其他重要问题需要解决:
- 首先,您以完全错误的方式更新屏幕。您不应从
Paint
事件处理程序调用 Refresh()
、Update()
或 Invalidate()
。相反,你应该在某处有单独的逻辑,例如基于计时器、后台线程等处理数据状态(即您的游戏世界)的控制,并且当数据以某种方式发生变化时使相关 window 或控件无效这将需要重新绘制它们。
- 此外,您应该尽可能使用库存
Pen
对象,如果不可能,请处理您的自定义 Pen
对象或将其存储在某个地方以供重复使用。
例如:
private static readonly Pen _firedLine =
new Pen(Color.Blue) { DashPattern = new [] { 5f, 2f } };
private void LineDrawEvent(object sender, PaintEventArgs paint)
{
Graphics drawSurface = paint.Graphics;
Pen turretLine = Pens.Blue;
Pen graphHorizontal = Pens.Red;
Pen graphVertical = Pens.Red;
Pen targetLine = Pens.Black;
drawSurface.DrawLine(graphVertical, (int)xOrigin, (int)yOrigin, (int)xHor, (int)yHor);
drawSurface.DrawLine(graphHorizontal, (int)xOrigin, (int)yOrigin, (int)xVert, (int)yVert);
drawSurface.DrawLine(_firedLine, (int)xOrigin, (int)yOrigin, (int)xFire, (int)yFire);
drawSurface.DrawLine(targetLine, (int)xTarget, (int)yTarget, (int)xTarget, (int)yTargetEnd);
double angleInRadians = ConvertDegsToRads((double)trckBarAngle.Value);
xEnd = xOrigin + lineLength * Math.Cos(angleInRadians / 2.0);
yEnd = yOrigin - lineLength * Math.Sin(angleInRadians / 2.0);
drawSurface.DrawLine(turretLine, (int)xOrigin, (int)yOrigin, (int)xEnd, (int)yEnd);
}
我正在尝试创建一个小游戏,您必须使用 "turret" 来射击目标。目前我被困在我的目标线上。我的目标是让它以设定的 X 值生成,但每次我按下重绘按钮时它以随机的 Y 值生成。但是我的代码有问题。该线并非始终具有相同长度并以随机 Y 值生成,而是似乎以随机长度和随机 Y 值生成。如果有人能帮我找出我哪里出错了那将是完美的。
相关的变量有xTarget
,yTarget
(直线的第一个y值)yTargetEnd
(直线的第二个y值)targetLine
(行的静态长度)和 DrawLine()
方法调用 targetLine
.
在我看来,我设置它的方式很有意义,但它似乎并没有达到我的预期。我尝试将 yTarget
设置为随机数,然后将 yTargetEnd
设置为 yTarget + targetLine
,因此它的长度应该始终为 50,但这似乎根本不起作用?
public partial class Form1 : Form
{
Random rnd = new Random { };
double xEnd = 0;
double yEnd = 0;
double xOrigin = 30;
double yOrigin = 450;
double xFire;
double yFire;
double xTarget = 500;
double yTarget;
double yTargetEnd;
double xHor = 30;
double yHor = 350;
double xVert = 130;
double yVert = 450;
double fireLine = 750;
double lineLength = 50;
double targetLine = 50;
public Form1()
{
xEnd = xOrigin + lineLength;
yEnd = yOrigin;
xFire = xOrigin + fireLine;
yFire = yOrigin;
InitializeComponent();
}
private void LineDrawEvent(object sender, PaintEventArgs paint)
{
Graphics drawSurface = paint.Graphics;
Pen turretLine = new Pen(Color.Blue);
Pen graphHorizontal = new Pen(Color.Red);
Pen graphVertical = new Pen(Color.Red);
Pen firedLine = new Pen(Color.Blue);
Pen targetLine = new Pen(Color.Black);
float[] dashValues = { 5, 2 };
firedLine.DashPattern = dashValues;
drawSurface.DrawLine(graphVertical, (int)xOrigin, (int)yOrigin, (int)xHor, (int)yHor);
drawSurface.DrawLine(graphHorizontal, (int)xOrigin, (int)yOrigin, (int)xVert, (int)yVert);
drawSurface.DrawLine(firedLine, (int)xOrigin, (int)yOrigin, (int)xFire, (int)yFire);
drawSurface.DrawLine(targetLine, (int)xTarget, (int)yTarget, (int)xTarget, (int)yTargetEnd);
double angleInRadians = ConvertDegsToRads((double)trckBarAngle.Value);
xEnd = xOrigin + lineLength * Math.Cos(angleInRadians / 2.0);
yEnd = yOrigin - lineLength * Math.Sin(angleInRadians / 2.0);
drawSurface.DrawLine(turretLine, (int)xOrigin, (int)yOrigin, (int)xEnd, (int)yEnd);
this.Refresh();
}
private void trckBarAngle_Scroll(object sender, EventArgs e)
{
lblAngle.Text = "Angle is:" + Convert.ToString((double)trckBarAngle.Value / 2.0);
}
private double ConvertDegsToRads(double degrees)
{
return degrees * (Math.PI / 180.0);
}
private void btnFire_Click(object sender, EventArgs e)
{
double angleInDegrees = trckBarAngle.Value;
double angleInRadians = ConvertDegsToRads(angleInDegrees);
xFire = xOrigin + fireLine * Math.Cos(angleInRadians / 2.0);
yFire = yOrigin - fireLine * Math.Sin(angleInRadians / 2.0);
this.Refresh();
}
private void btnRedraw_Click(object sender, EventArgs e)
{
yTargetEnd = yTarget - targetLine;
yTarget = rnd.Next(100, 500);
}
}
设计师生成的代码:
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.lblAngle = new System.Windows.Forms.Label();
this.trckBarAngle = new System.Windows.Forms.TrackBar();
this.btnFire = new System.Windows.Forms.Button();
this.btnRedraw = new System.Windows.Forms.Button();
((System.ComponentModel.ISupportInitialize)(this.trckBarAngle)).BeginInit();
this.SuspendLayout();
//
// lblAngle
//
this.lblAngle.AutoSize = true;
this.lblAngle.Location = new System.Drawing.Point(13, 13);
this.lblAngle.Name = "lblAngle";
this.lblAngle.Size = new System.Drawing.Size(46, 17);
this.lblAngle.TabIndex = 0;
this.lblAngle.Text = "label1";
//
// trckBarAngle
//
this.trckBarAngle.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Right)));
this.trckBarAngle.LargeChange = 10;
this.trckBarAngle.Location = new System.Drawing.Point(732, 42);
this.trckBarAngle.Maximum = 360;
this.trckBarAngle.Minimum = -360;
this.trckBarAngle.Name = "trckBarAngle";
this.trckBarAngle.Orientation = System.Windows.Forms.Orientation.Vertical;
this.trckBarAngle.Size = new System.Drawing.Size(56, 495);
this.trckBarAngle.TabIndex = 1;
this.trckBarAngle.Scroll += new System.EventHandler(this.trckBarAngle_Scroll);
//
// btnFire
//
this.btnFire.Location = new System.Drawing.Point(632, 13);
this.btnFire.Name = "btnFire";
this.btnFire.Size = new System.Drawing.Size(75, 23);
this.btnFire.TabIndex = 2;
this.btnFire.Text = "Fire";
this.btnFire.UseVisualStyleBackColor = true;
this.btnFire.Click += new System.EventHandler(this.btnFire_Click);
//
// btnRedraw
//
this.btnRedraw.Location = new System.Drawing.Point(713, 13);
this.btnRedraw.Name = "btnRedraw";
this.btnRedraw.Size = new System.Drawing.Size(75, 23);
this.btnRedraw.TabIndex = 2;
this.btnRedraw.Text = "Redraw";
this.btnRedraw.UseVisualStyleBackColor = true;
this.btnRedraw.Click += new System.EventHandler(this.btnRedraw_Click);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 549);
this.Controls.Add(this.btnRedraw);
this.Controls.Add(this.btnFire);
this.Controls.Add(this.trckBarAngle);
this.Controls.Add(this.lblAngle);
this.Name = "Form1";
this.Text = "Form1";
this.Paint += new System.Windows.Forms.PaintEventHandler(this.LineDrawEvent);
((System.ComponentModel.ISupportInitialize)(this.trckBarAngle)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label lblAngle;
private System.Windows.Forms.TrackBar trckBarAngle;
private System.Windows.Forms.Button btnFire;
private System.Windows.Forms.Button btnRedraw;
}
基本问题归结为代码根本不符合您的预期。您写道:
I try to set
yTarget
to a random number and then setyTargetEnd
toyTarget + targetLine
但这实际上不是代码的作用。您的代码以相反的顺序执行这两件事。因此 yTargetEnd
值始终基于 上一个 目标位置,而不是新选择的位置。
您的代码应该如下所示:
private void btnRedraw_Click(object sender, EventArgs e)
{
yTarget = rnd.Next(100, 500);
yTargetEnd = yTarget - targetLine;
}
即编写代码,使其符合您的规范。 :)
回答完之后,您的代码中还有一些其他重要问题需要解决:
- 首先,您以完全错误的方式更新屏幕。您不应从
Paint
事件处理程序调用Refresh()
、Update()
或Invalidate()
。相反,你应该在某处有单独的逻辑,例如基于计时器、后台线程等处理数据状态(即您的游戏世界)的控制,并且当数据以某种方式发生变化时使相关 window 或控件无效这将需要重新绘制它们。 - 此外,您应该尽可能使用库存
Pen
对象,如果不可能,请处理您的自定义Pen
对象或将其存储在某个地方以供重复使用。
例如:
private static readonly Pen _firedLine =
new Pen(Color.Blue) { DashPattern = new [] { 5f, 2f } };
private void LineDrawEvent(object sender, PaintEventArgs paint)
{
Graphics drawSurface = paint.Graphics;
Pen turretLine = Pens.Blue;
Pen graphHorizontal = Pens.Red;
Pen graphVertical = Pens.Red;
Pen targetLine = Pens.Black;
drawSurface.DrawLine(graphVertical, (int)xOrigin, (int)yOrigin, (int)xHor, (int)yHor);
drawSurface.DrawLine(graphHorizontal, (int)xOrigin, (int)yOrigin, (int)xVert, (int)yVert);
drawSurface.DrawLine(_firedLine, (int)xOrigin, (int)yOrigin, (int)xFire, (int)yFire);
drawSurface.DrawLine(targetLine, (int)xTarget, (int)yTarget, (int)xTarget, (int)yTargetEnd);
double angleInRadians = ConvertDegsToRads((double)trckBarAngle.Value);
xEnd = xOrigin + lineLength * Math.Cos(angleInRadians / 2.0);
yEnd = yOrigin - lineLength * Math.Sin(angleInRadians / 2.0);
drawSurface.DrawLine(turretLine, (int)xOrigin, (int)yOrigin, (int)xEnd, (int)yEnd);
}