游戏技术基础:实验记录七
net: [[C#]]
1. 模拟小球的自由落体运动,直至小球静止不动。
以下是使用C#语言和Windows Forms应用程序在窗体上实现模拟自由落体运动的示例代码:
创建Form1.cs文件并插入以下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85using System;
using System.Drawing;
using System.Windows.Forms;
namespace FreeFallSimulation
{
public partial class Form1 : Form
{
private const double Gravity = 9.81; // 重力加速度
private double _time = 0; // 时间
private double _velocity = 0; // 速度
private double _displacement = 0; // 位移
private double _initialHeight = 200; // 小球的初始高度
private readonly int _ballRadius = 20; // 小球的半径
private readonly int _updateInterval = 16; // 界面更新的间隔,单位为毫秒
private Timer _timer; // 定时器
private Point _ballPosition; // 小球的位置
public Form1()
{
InitializeComponent();
InitializeTimer();
InitializeBallPosition();
}
private void InitializeTimer()
{
_timer = new Timer();
_timer.Interval = _updateInterval;
_timer.Tick += Timer_Tick;
}
private void InitializeBallPosition()
{
_ballPosition = new Point(ClientSize.Width / 2 - _ballRadius / 2, Convert.ToInt32(_initialHeight));
}
private void Timer_Tick(object sender, EventArgs e)
{
Simulation(); // 模拟自由落体运动
UpdateBallPosition(); // 更新小球的位置
Invalidate(); // 刷新界面
}
private void Simulation()
{
_time += _updateInterval / 1000.0; // 计算时间
_displacement = _initialHeight + 0.5 * Gravity * _time * _time; // 计算位移
_velocity = -Gravity * _time; // 计算速度
if (_displacement < 0) // 小球落到底部停止运动
{
_displacement = 0;
_velocity = 0;
_timer.Stop();
}
}
private void UpdateBallPosition()
{
_ballPosition.Y = Convert.ToInt32(_displacement);
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.FillEllipse(Brushes.Red, _ballPosition.X, _ballPosition.Y, _ballRadius, _ballRadius);
}
private void Form1_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
_time = 0;
_velocity = 0;
_initialHeight = e.Location.Y;
InitializeBallPosition();
_timer.Start();
}
}
}
}运行程序并单击窗体中的任意位置,程序将启动模拟自由落体运动,直至小球停止不动。
注:本示例程序中,使用定时器每隔16毫秒更新界面,模拟小球自由落体运动;单击鼠标左键,程序将重新计算小球的初始高度,并从头开始模拟自由落体运动。
2. 在矩形内小球碰撞运动
以下是使用C#语言和Windows Forms应用程序在窗体上实现小球在矩形框中运动的示例代码:
创建Form1.cs文件并插入以下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122using System;
using System.Drawing;
using System.Windows.Forms;
namespace RectangleSimulation
{
public partial class Form1 : Form
{
private const double Gravity = 9.81; // 重力加速度
private const double CoefficientOfRestitution = 0.8; // 弹性系数,即碰撞后速度变化的比例
private readonly int _ballRadius = 20; // 小球的半径
private readonly int _rectangleMargin = 30; // 矩形框与窗体边缘的间隔
private readonly int _updateInterval = 16; // 界面更新的间隔,单位为毫秒
private Timer _timer; // 定时器
private Point _ballPosition; // 小球的位置
private Size _ballVelocity; // 小球的速度
private Rectangle _rectangle; // 矩形框
public Form1()
{
InitializeComponent();
InitializeTimer();
InitializeBall();
InitializeRectangle(ClientSize);
}
private void InitializeTimer()
{
_timer = new Timer();
_timer.Interval = _updateInterval;
_timer.Tick += Timer_Tick;
}
private void InitializeBall()
{
_ballPosition = new Point(ClientSize.Width / 2 - _ballRadius / 2, ClientSize.Height / 2 - _ballRadius / 2);
_ballVelocity = new Size(0, 0);
}
private void InitializeRectangle(Size clientSize)
{
_rectangle = new Rectangle(_rectangleMargin, _rectangleMargin, clientSize.Width - _rectangleMargin * 2, clientSize.Height - _rectangleMargin * 2);
}
private void Timer_Tick(object sender, EventArgs e)
{
Simulation(); // 模拟运动
UpdateBallPosition(); // 更新小球的位置
CheckCollision(); // 检测碰撞
Invalidate(); // 刷新界面
}
private void Simulation()
{
double timeInterval = _updateInterval / 1000.0; // 时间间隔,单位为秒
// 计算速度
_ballVelocity.Height = Convert.ToInt32(_ballVelocity.Height + Gravity * timeInterval);
_ballVelocity.Width = Convert.ToInt32(_ballVelocity.Width);
// 计算位移
_ballPosition.X += _ballVelocity.Width;
_ballPosition.Y += _ballVelocity.Height;
}
private void UpdateBallPosition()
{
// 将小球移回矩形框内,以防止小球越界
if (_ballPosition.X < _rectangle.Left)
{
_ballPosition.X = _rectangle.Left;
}
else if (_ballPosition.X + _ballRadius > _rectangle.Right)
{
_ballPosition.X = _rectangle.Right - _ballRadius;
}
if (_ballPosition.Y < _rectangle.Top)
{
_ballPosition.Y = _rectangle.Top;
}
else if (_ballPosition.Y + _ballRadius > _rectangle.Bottom)
{
_ballPosition.Y = _rectangle.Bottom - _ballRadius;
}
}
private void CheckCollision()
{
// 检测与矩形框四壁的碰撞
if (_ballPosition.X < _rectangle.Left || _ballPosition.X + _ballRadius > _rectangle.Right)
{
_ballVelocity.Width = -Convert.ToInt32(_ballVelocity.Width * CoefficientOfRestitution);
}
if (_ballPosition.Y < _rectangle.Top || _ballPosition.Y + _ballRadius > _rectangle.Bottom)
{
_ballVelocity.Height = -Convert.ToInt32(_ballVelocity.Height * CoefficientOfRestitution);
}
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.graphics
g.FillRectangle(Brushes.White, ClientRectangle); // 清空缓冲图像
g.FillEllipse(Brushes.Red, _ballPosition.X, _ballPosition.Y, _ballRadius, _ballRadius); // 绘制小球
g.DrawRectangle(Pens.Black, _rectangle); // 绘制矩形框
e.Graphics.DrawImage(_backBuffer, 0, 0); // 绘制缓冲图像
}
private void Form1_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
_ballPosition = e.Location;
_ballVelocity = new Size(0, 0);
_timer.Start();
}
}
}
}运行程序并单击窗体中的任意位置,程序将启动小球在矩形框中运动,碰到矩形框四壁将发生反弹。程序使用双缓冲消除闪烁。
References
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 wcdd的藏经阁!
