您的位置:首页 > 编程语言 > C#

基于C#的2D太阳、地球、月亮运动轨迹模拟实现

2012-03-25 00:31 489 查看

1.题目要求:

   如题所示----基于C#的2D太阳、地球、月亮运动轨迹模拟实现。

2.研究思路:

     此题目属于图形学中比较典型的有关运动轨迹实现的问题。
     首先二话不说,站在面向对象的角度考虑至少包含太阳、地球、月亮三个类。由于是模拟实现,故有些相关数据并非的绝对正确。在此我们假设太阳位于屏幕的画布的中心,且静止不动(虽然有自转,但是由于是2D不好显示,并且如此假设也不影响最终整体效果,故假设之);地球围绕太阳公转(假设运行轨迹为圆);月亮围绕地球公转。
      问题难点:地球在围绕太阳转动的同时,月亮也在围绕地球公转,并且地球公转的角速度是月亮角速度的1/12.

3.程序说明:

      运行平台:windows 7
      开发工具:Microsoft Visual Studio 2010
      开发语言:C# 、GDI+
      程序类型:Windows窗体应用程序

4.具体实现:

    1)兴建工程(在此我们将此工程命名为SunEarthMoon)
          打开Visual Studio 2010 -->文件-->兴建-->项目;选择Windows窗体应用程序,在"名称"后面上SunEarthMoon, 然后选择程序保存的路径,单击确定即可。
  


如果你在你的“解决方案资源管理器”中看到有如下图示文件目录结构,那么说明你的
SunEarthMoon工程已经成功创建可以成功跳至2)了;否之,你还需要返回1),直到成功为止。



2)业务逻辑类实现

(1)在模拟的时候,由于太阳,地球,月亮他们有很多相似的地方,故在此抽象出了一个
Start的父类,里面主要包含一些公共的属性并提供一个待子类重写的draw()虚函数。
代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace SunEarthMoon
{
class  Start
{
public  Point center;          // 星球的球星
public  Point movingCenter;    //星球公转轨迹的中心
public  int radius;            //星球的半径
public  int movingRadius;      //星球公转的半径
public  Graphics graphics;      //绘制的画布
public  Color bgcolor;          //星球的背景色

public virtual void draw() {

}

}
}

      (2)然后是Sun、Earth、Moon类的具体实现;他们都继承至Start,都重写了draw方法而已。
代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace SunEarthMoon
{
class Sun :Start
{

public Sun()
{

}

public Sun(Point center, Point movingCenter, int radius, int movingRadius ,Graphics graphics,Color bgColor)
{
this.center = center;
this.movingCenter = movingCenter;
this.radius = radius;
this.movingRadius = movingRadius;
this.graphics = graphics;
this.bgcolor = bgColor;

}

public override void draw()
{
graphics.FillPie(new SolidBrush(bgcolor), center.X-radius, center.Y-radius, 2 * radius, 2 * radius, 0, 360);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace SunEarthMoon
{
class Earth :Start
{
public Earth()
{

}
public Earth(Point center, Point movingCenter, int radius, int movingRadius, Graphics graphics, Color bgColor)
{
this.center = center;
this.movingCenter = movingCenter;
this.radius = radius;
this.movingRadius = movingRadius;
this.graphics = graphics;
this.bgcolor = bgColor;

}

public override void draw()
{
graphics.FillPie(new SolidBrush(bgcolor), center.X-radius, center.Y-radius, 2 * radius, 2 * radius, 0, 360);
}
}
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace SunEarthMoon
{
class Moon :Start
{
public Moon()
{

}

public Moon(Point center, Point movingCenter, int radius, int movingRadius, Graphics graphics, Color bgColor)
{
this.center = center;
this.movingCenter = movingCenter;
this.radius = radius;
this.movingRadius = movingRadius;
this.graphics = graphics;
this.bgcolor = bgColor;

}

public override void draw()
{
graphics.FillPie(new SolidBrush(bgcolor), center.X-radius, center.Y-radius, 2 * radius, 2 * radius, 0, 360);

}
}
}

          (3)为了方便与前台窗体的交互,在此专门设计了一个Space的类
来容纳太阳、地球、月亮;并提供与窗体的直接交互功能。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Threading;

namespace SunEarthMoon
{
class Space
{

private Graphics graphics;
private Start sun;
private Start earth;
private Start moon;
private Point screenCenter;
private bool isMoving = false;
private double d_angle = 2 * 3.14 * 1 / 360;
private  double angle ;

public Space(Graphics graphics, Point screenCenter)
{
this.graphics = graphics;
this.screenCenter = screenCenter;
this.sun = new Sun(screenCenter,screenCenter,50,50,graphics,Color.Yellow);
this.earth = new Earth(new Point(screenCenter.X + 200, screenCenter.Y), screenCenter, 25, 200, graphics, Color.Blue);
this.moon = new Moon(new Point(earth.center.X+50,earth.center.Y),earth.center,15,50,graphics,Color.White);
this.angle = d_angle;
}

public void draw(bool isMoving)
{
this.IsMoving = isMoving;
ThreadStart threadStart = new ThreadStart(threadDraw);
Thread thread = new Thread(threadStart);
thread.Start();

}

public void drawBg()
{
graphics.Clear(Color.Black);
}

private void threadDraw()
{
int dx_e = 200;
int dx_m = 50;
while (true)
{
sun.draw();
earth.draw();
moon.draw();
earth.center.X = screenCenter.X + (int)(dx_e * Math.Cos(angle));
earth.center.Y = screenCenter.Y + (int)(dx_e * Math.Sin(angle));
moon.center.X = earth.center.X + (int)(dx_m * Math.Cos(-angle * 12));
moon.center.Y = earth.center.Y + (int)(dx_m * Math.Sin(-angle * 12));
moon.movingCenter = earth.center;
angle += d_angle;
Thread.Sleep(400);
if (!IsMoving)
break;
drawBg();

}
}

public bool IsMoving
{
get { return isMoving; }
set { isMoving = value; }
}

public double D_angle
{
get { return d_angle; }
set { d_angle = value; }
}
}
}


3)窗体设计(包含窗体事件的实现)

      (1) 窗体界面设计 

          左键双击 解决方案中的“Form1.cs”;利用VS2010自带的工具箱,在Form1的设计界面上(Form1.cs[设计]),设计出如下界面;并通过修改控件属性,达到如图效果:
         


       (2)Form1界面事件具体实现

             左键双击Form1界面中的任意一个控件,即可跳到Form1.cs界面,在这里我们将添加所有控件的响应事件。      
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace SunEarthMoon
{
public partial class Form1 : Form
{
private Space space;
private bool isMoving = false;
private double i = 1;
public Form1()
{
InitializeComponent();
space = new Space(this.panel2.CreateGraphics(),new Point(this.panel2.Width/2,this.panel2.Height/2));
}

private void panel2_Paint(object sender, PaintEventArgs e)
{
space.drawBg();
}

private void button1_Click(object sender, EventArgs e)
{
if (!isMoving )
isMoving = true;
space.draw(isMoving);

label1.Text = "速度:" + i + "*X";

}

private void button2_click(object sender, EventArgs e)
{

space.IsMoving = false;
isMoving = false;
label1.Text = "暂停中...";
}

private void button3_click(object sender, EventArgs e)
{
if (isMoving)
{
i = i * 2;
space.D_angle = 2.0 * space.D_angle;
label1.Text = "速度:" + i + "*X";
}
else {
label1.Text = "暂停中...";
}

}

private void button4_click(object sender, EventArgs e)
{
if (isMoving)
{
i = i / 2.0;
space.D_angle = space.D_angle / 2.0;
label1.Text = "速度:" + i + "*X";
}
else {
label1.Text = "暂停中...";
}

}

}
}


4)动画演示 

          在此我们的程序已经全部设计编 码完成,如果顺利的话,我们将看到如下的动画演示图像:

        (1)程序初始界面   

         (2)单击“开始演示”按钮
           


       
 (3)单击“暂停演示”按钮
         

                                                                       
  (4)单击“运动加速”
注:必须是在运行状态下才单击此按钮才有用,如果是暂停状态中,那么请点击“开始按钮”使其处于运行状态即可。

   


   

(5)单击“运动减速”
注:必须是在运行状态下才单击此按钮才有用,如果是暂停状态中,那么请点击“开始按钮”使其处于运行状态即可。
 


(6)退出程序
    此程序的退出最好是在暂停的状态下,然后单击右上方的”X“即可。
    

5)项目总结

       本项目是典型的有关图形的移动处理的示例;在这方面自己还存在很大不足,需要加倍努力。
       程序中的不足:

图形存在闪烁(双缓存可以解决)
代码整体设计需要部分重构
       完全代码已上传至资源中心

      请到 http://download.csdn.net/detail/small_fish__/4170429 下载

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c# object button sun class thread