现在的位置: 首页 > 综合 > 正文

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

2013年12月05日 ⁄ 综合 ⁄ 共 6072字 ⁄ 字号 评论关闭
文章目录

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)项目总结

       本项目是典型的有关图形的移动处理的示例;在这方面自己还存在很大不足,需要加倍努力。
       程序中的不足:
  • 图形存在闪烁(双缓存可以解决)
  • 代码整体设计需要部分重构
       完全代码已上传至资源中心
 

 













抱歉!评论已关闭.