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

来源:互联网 发布:淘宝客服话术下载 编辑:程序博客网 时间:2024/04/29 13:52

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 下载