游戏技术基础:实验五记录
net: [[C#]]
使用的新工具
ArrayList类
ArrayList类是C#编程语言和.NET Framework中的一个类,它提供了在动态数组中存储对象的能力。使用ArrayList类,开发者可以方便地添加、删除、查找和排序动态数组中的元素。
ArrayList类的特点包括:
元素类型不需要提前指定。在必要时,ArrayList会自动调整其类型以适应添加的元素类型。
可以存储任何类型的对象,包括简单类型(例如int、bool等)和复杂类型(例如自定义的类实例)。
与普通的数组相比,动态数组可以在运行时自动调整大小,并且不需要手动管理内存。
支持在数组中插入、删除、查找和排序元素。
提供了一些有用的属性和方法,例如Count属性来获取数组的长度,Add方法来添加新的元素,IndexOf方法来查找元素的位置等。
需要注意的是,由于ArrayList存储的是对象,因此在将对象添加到ArrayList中时,实际上是添加了一个指向该对象的引用。这意味着如果修改了一个对象,那么在ArrayList中保存的引用也会受到影响。另外,在使用ArrayList类时还需要小心其性能,因为在一些情况下,使用更专门的集合类(例如List)可能会更高效。
GraphicsPath类
GraphicsPath是.NET Framework中的一个类,可以用来构建、查询和绘制图形路径。可以将GraphicsPath看作是一个路径,它由一系列线段、曲线段和其他形状组成。在创建GraphicsPath对象后,可以添加多段路径,使用LineTo、CurveTo、AddPie、AddRectangle、AddEllipse等方法添加图形。GraphicsPath还提供了一些查询方法,例如获取路径的边界、是否包含某个点等。
GraphicsPath类在绘制复杂的形状时非常有用。例如,如果需要绘制一条平滑的曲线,可以创建一个GraphicsPath对象,添加多个点,然后使用DrawPath或FillPath方法绘制。
下面是一个示例代码,该示例绘制了一个由多个线段和圆组成的图形路径:
1 | private void Form1_Paint(object sender, PaintEventArgs e) |
在此示例中,创建了一个GraphicsPath对象,将其添加到图形路径中,然后使用DrawPath方法绘制路径。此示例绘制的路径由一条直线、一段贝塞尔曲线、一段弧线、一条直线和一个椭圆组成。
实现方法
创建相关变量,用于存储笔的状态,点的位置以及橡皮状态。
1
2
3
4
5
6// 用于存储所有已经画出的点
private ArrayList points = new ArrayList();
// 当前线条的颜色和粗细
private Color lineColor = Color.Black; private int lineWidth = 3;
// 表示是否正在擦除线条
private bool isErasing = false;实现线条的绘制,以下是初代方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21private void Form1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
// 画线
if (!isErasing)
{
Graphics g = this.CreateGraphics();
Pen pen = new Pen(lineColor, lineWidth);
g.DrawLine(pen, e.X, e.Y, e.X, e.Y);
points.Add(new Point(e.X, e.Y));
}
// 擦除线条
else
{
Graphics g = this.CreateGraphics();
Pen pen = new Pen(this.BackColor, lineWidth);
g.DrawLine(pen, e.X, e.Y, e.X, e.Y);
}
}
}经检查,该方法存在以下几个问题:
在画线时,每次MouseDown事件只画了一个点,而没有实现用鼠标拖动时画出连续的线条。
在擦除线条时,MouseUp事件也应该触发擦除,否则可能出现用户按下左键后移出窗体后,线条不能被完全清除的情况。
CreateGraphics方法创建的Graphics对象是临时的,并不会保存在窗体中。当窗体重绘时,先前画的图形就会被清除掉。因此,在处理Paint事件时,应该使用已经创建好的e.Graphics对象来绘制图形。
在擦除线条时,只是画一条背景色的线,并没有真正地从points列表中删除被擦除的线条。
1 | private void Form1_MouseDown(object sender, MouseEventArgs e) |
橡皮功能
1
2
3
4
5
6private void 橡皮ToolStripMenuItem_Click(object sender, EventArgs e)
{
// 开始擦除线条
isErasing = true;
this.Invalidate();
}然而这就造成了一个问题,在将所有的点都清除后,(ArrayList)points[points.Count - 1]其中points.Count会变成0,所以points.Count-1就会成为-1,造成索引失败,如下图。

这样的话,我们直接将原来的Form1_MouseMose函数中的((ArrayList)points[points.Count - 1]).Add(new Point(e.X, e.Y));改为1
2
3
4
5
6
7
8
9if(points.Count == 0)
{
points.Add(new ArrayList());
}
else
{
((ArrayList)points[points.Count - 1]).Add(new Point(e.X, e.Y));
}修改字体颜色,这里我用的是
colordialog组件可以更加直观的修改颜色。1
2
3
4
5
6
7
8
9
10private void 颜色ToolStripMenuItem_Click(object sender, EventArgs e)
{
// 设置线条颜色
ColorDialog dialog = new ColorDialog();
if (dialog.ShowDialog() == DialogResult.OK)
{
lineColor = dialog.Color;
this.Invalidate();
}
}最后是粗细调整,因为没有现成的组件,只好新建一个窗口,用来输入数字。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21//form1.cs
public Form1()
{//初始化中要构造form2
InitializeComponent();
Form2 form2 = new Form2();
this.MouseDown += new MouseEventHandler(Form1_MouseDown);
this.MouseUp += new MouseEventHandler(Form1_MouseUp);
this.MouseMove += new MouseEventHandler(Form1_MouseMove);
this.Paint += new PaintEventHandler(Form1_Paint);
}
private void 粗细ToolStripMenuItem_Click(object sender, EventArgs e)
{
Form2 form2 = new Form2();
form2.ShowDialog();
// 获取从Form2中输入的文本
lineWidth = form2.LineWidth;
// 在MessageBox中显示输入的文本
MessageBox.Show("设置的粗细为:" + lineWidth);
}
1 | //form2.cs |
