在C#中模拟雷达的最佳方法是什么?

时间:2009-08-16 16:29:40

标签: c# .net winforms graphics

我的表格中的组框内有一个图片框,其中雷达图片设置为背景图片。我的目的是在运行时动态加载雷达区域内的微小Jpeg图像(重叠),但我不确定实现这一目标的最佳方法。 欢迎所有疯狂的想法(但我更喜欢理智的做法)。 谢谢大家。

4 个答案:

答案 0 :(得分:3)

这很大程度上取决于你的“雷达”需要什么样,但几乎可以肯定你需要实现Paint事件处理程序,并自己绘制雷达显示的内容。一个图片框只会让你到目前为止(“不是很”)。

GDI +非常易于用于绘制圆形,线条,文本和图像,并可让您完全控制显示的外观。

答案 1 :(得分:2)

至于实际例子:

  // Among others
  using System.Collections.Generic;
  using System.Drawing;
  using System.IO;

  class TinyPic {
    public readonly Image Picture;
    public readonly Rectangle Bounds;

    public TinyPic(Image picture, int x, int y) {
      Picture = picture;
      Bounds = new Rectangle(x, y, picture.Width, picture.Height);
    }
  }

  class MyForm : Form {

    Dictionary<String, TinyPic> tinyPics = new Dictionary<String, TinyPic>();

    public MyForm(){
      InitializeComponent(); // assuming Panel myRadarBox
                             // with your background is there somewhere;
      myRadarBox.Paint += new PaintEventHandler(OnPaintRadar);
    }

    void OnPaintRadar(Object sender, PaintEventArgs e){
      foreach(var item in tinyPics){
        TinyPic tp = item.Value;
        e.Graphics.DrawImageUnscaled(tp.Picture, tp.Bounds.Location);
      }
    }

    void AddPic(String path, int x, int y){
      if ( File.Exists(path) ){
        var tp = new TinyPic(Image.FromFile(path), x, y);
        tinyPics[path] = tp;
        myRadarBox.Invalidate(tp.Bounds);
      }
    }

    void RemovePic(String path){
      TinyPic tp;
      if ( tinyPics.TryGetValue(path, out tp) ){
        tinyPics.Remove(path);
        tp.Picture.Dispose();
        myRadarBox.Invalidate(tp.Bounds);
      }
    }
  }

这当然是非常基本的,假设图像源是路径,并没有处理许多复杂的事情,但这是你可以建立的快速和肮脏的主题。

答案 2 :(得分:2)

Click here运行一个示例应用程序,演示如何进行雷达(或至少单向)的基础知识。注意:此应用程序不会对微小图像执行双缓冲或透明度。

该项目的源代码是here

更新代码:

public partial class Form1 : Form
{
    private Bitmap _canvas;
    private float _sweepStartAngle = -90;
    private float _sweepAngle = 15;
    private SolidBrush _sweepBrush = new SolidBrush(Color.Red);
    private Rectangle _sweepRect;
    private Timer _sweepTimer = new Timer();
    private Bitmap _submarine;
    private Point _submarinePosition = new Point(0, 0);
    private Random rnd = new Random();

    public Form1()
    {
        InitializeComponent();

        _canvas = new Bitmap(pbScope.Width, pbScope.Height);
        pbScope.Image = _canvas;
        _sweepRect = new Rectangle(0, 0, pbScope.Width, pbScope.Height);

        _submarine = (Bitmap)pbSubmarine.Image;

        RedrawScope();

        _sweepTimer.Interval = 100;
        _sweepTimer.Tick += new EventHandler(_sweepTimer_Tick);
        _sweepTimer.Start();
    }

    void _sweepTimer_Tick(object sender, EventArgs e)
    {
        _sweepStartAngle += _sweepAngle;
        RedrawScope();
    }

    private void RedrawScope()
    {
        using (Graphics g = Graphics.FromImage(_canvas))
        {
            // draw the background
            g.DrawImage(pbBackground.Image, 0, 0);

            // draw the "sweep"
            GraphicsPath piepath = new GraphicsPath();
            piepath.AddPie(_sweepRect, _sweepStartAngle, _sweepAngle);
            g.FillPath(_sweepBrush, piepath);
            //g.FillPie(_sweepBrush, _sweepRect, _sweepStartAngle, _sweepAngle);

            // move the submarine and draw it
            _submarinePosition.X += rnd.Next(3);
            _submarinePosition.Y += rnd.Next(3);
            // check if submarine intersects with piepath
            Rectangle rect = new Rectangle(_submarinePosition, _submarine.Size);
            Region region = new Region(piepath);
            region.Intersect(rect);
            if (!region.IsEmpty(g))
            {
                g.DrawImage(_submarine, _submarinePosition);
            }
        }
        pbScope.Image = _canvas;
    }

    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        _sweepTimer.Stop();
        _sweepTimer.Dispose();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        //GraphicsPath piepath = new GraphicsPath();
        //piepath.AddPie(

    }

}

   private void InitializeComponent()
    {
        System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
        this.pbScope = new System.Windows.Forms.PictureBox();
        this.pbBackground = new System.Windows.Forms.PictureBox();
        this.pbSubmarine = new System.Windows.Forms.PictureBox();
        ((System.ComponentModel.ISupportInitialize)(this.pbScope)).BeginInit();
        ((System.ComponentModel.ISupportInitialize)(this.pbBackground)).BeginInit();
        ((System.ComponentModel.ISupportInitialize)(this.pbSubmarine)).BeginInit();
        this.SuspendLayout();
        // 
        // pbScope
        // 
        this.pbScope.Location = new System.Drawing.Point(12, 12);
        this.pbScope.Name = "pbScope";
        this.pbScope.Size = new System.Drawing.Size(300, 300);
        this.pbScope.TabIndex = 0;
        this.pbScope.TabStop = false;
        // 
        // pbBackground
        // 
        this.pbBackground.Image = ((System.Drawing.Image)(resources.GetObject("pbBackground.Image")));
        this.pbBackground.Location = new System.Drawing.Point(341, 12);
        this.pbBackground.Name = "pbBackground";
        this.pbBackground.Size = new System.Drawing.Size(300, 300);
        this.pbBackground.TabIndex = 1;
        this.pbBackground.TabStop = false;
        this.pbBackground.Visible = false;
        // 
        // pbSubmarine
        // 
        this.pbSubmarine.Image = ((System.Drawing.Image)(resources.GetObject("pbSubmarine.Image")));
        this.pbSubmarine.Location = new System.Drawing.Point(658, 45);
        this.pbSubmarine.Name = "pbSubmarine";
        this.pbSubmarine.Size = new System.Drawing.Size(48, 48);
        this.pbSubmarine.TabIndex = 2;
        this.pbSubmarine.TabStop = false;
        this.pbSubmarine.Visible = false;
        // 
        // Form1
        // 
        this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
        this.ClientSize = new System.Drawing.Size(326, 328);
        this.Controls.Add(this.pbSubmarine);
        this.Controls.Add(this.pbBackground);
        this.Controls.Add(this.pbScope);
        this.Name = "Form1";
        this.Text = "Radar";
        this.Load += new System.EventHandler(this.Form1_Load);
        this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Form1_FormClosing);
        ((System.ComponentModel.ISupportInitialize)(this.pbScope)).EndInit();
        ((System.ComponentModel.ISupportInitialize)(this.pbBackground)).EndInit();
        ((System.ComponentModel.ISupportInitialize)(this.pbSubmarine)).EndInit();
        this.ResumeLayout(false);

    }

答案 3 :(得分:0)

最简单的方法是将微小的JPEG加载到微小的PictureBox中,并在运行时将它们添加到主PictureBox的Controls集合中(即将它们放在PictureBox上)。

由于这可能会产生闪烁,稍微复杂的方法是将主图片和小图片保留在类级别的Bitmap对象中,并在主PictureBox的Paint事件中,复制主图片,然后是每张小图片使用DrawImage方法在第二个类级别的Bitmap(名为_doubleBuffer或类似的东西)上,然后将_doubleBuffer复制到PictureBox上(也使用DrawImage)。每当您需要更新显示并重新绘制所有内容时,只需调用PictureBox的Invalidate方法即可。

这里有很多关于如何使用这些方法的示例。祝你好运,这听起来很有趣(如果你正在重写经典的街机游戏Submarine,请告诉我 - 我喜欢那款游戏)。