更新一个对象的图像属性,每个计时器滴答c#

本文关键字:计时器 滴答 一个对象 图像 属性 更新 | 更新日期: 2023-09-27 18:14:30

我有一个精灵类,它有一个绘制爆炸的方法。这个类有一个image属性,用来作为将要绘制的图像。

我希望有这样的图像,即绘制是改变每5秒左右。

我的问题是:使用计时器控制,我怎么能编码它,使图像属性改为不同的图像每tick?

例如:Image 1 '5 seconds'> Image 2 '5 seconds'> Image 3 '5 seconds'> remove Image .

下面是绘制方法:

    public void DrawExplosion(Graphics graphics)
    {
        graphics.DrawImage(explosion_, xPos_, yPos_);
    }

和类

的Image属性
    public Image Explosion
    {
        get {return explosion_;}
        set {explosion_ = value;}
    }

感谢您的帮助/指导。

更新一个对象的图像属性,每个计时器滴答c#

我注意到我的回答对于这个简单的问题来说太复杂了。虽然我不认为这是不正确的,但我确实认为这使问题复杂化了。我想把它留在那里,以防别人发现它有用。但这里有一个简单的尝试。它使用了Sprite类外部的计时器、按钮和面板。我希望这对你有帮助。

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 CustomControl
{
public partial class Form1 : Form
{
    Sprites Explosion = new Sprites();

    public Form1()
    {
        InitializeComponent();
        //insert your images in this next line
        Explosion.Images=new Image[]{Properties.Resources.explode1,Properties.Resources.explode2,Properties.Resources.explode3};
        Explosion.ImageIndex = 0;
    }
    private void button1_Click(object sender, EventArgs e)
    {
        timer1.Enabled = true;
        //Draw the first image right away
        Explosion.Draw(panel1.CreateGraphics(), 0, 0);
        //set the index to the next image
        Explosion.ImageIndex++;
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        //if the Imageindex is not greater then the number of images
        if (Explosion.ImageIndex < Explosion.Images.Count() )
        {
            Explosion.Draw(panel1.CreateGraphics(), 0, 0);
            Explosion.ImageIndex++;
        }
        //if it is greater then reset the imageIndex and turn off the timer
        else
        {
            Explosion.ImageIndex = 0;
            timer1.Enabled = false;
            //Clear your images, however you need to do that
            panel1.CreateGraphics().Clear(Color.White);
        }

    }
}

public class Sprites
{
    public Image DisplayedImage { get { return Images[ImageIndex]; } }
    public int ImageIndex;
    public Image[] Images;
    public void Draw(Graphics graphics, int x, int y)
    {
        graphics.DrawImage(DisplayedImage, x, y);
    }

}
}

如果我的猜测是正确的,并且你正在编写一款游戏,那么你可能不希望在这里使用计时器。有很多关于游戏循环编程的文章都适合你的场景。

它们基本上将你的屏幕元素(这里是一个精灵)的逻辑更新从渲染中分离出来,并使用OS钩子来保持高性能。

编辑:我在下面添加了另一个答案。我发现这个答案对于这个问题来说太复杂了。

JRoughan可能是对的,可能有更好的方法来做到这一点。但根据你的要求,我写了一个类,将采取图像你提供和绘制他们一个时间到图形对象,然后清除图形对象。

我在一个方法中实例化了类,所以不能保证它不会超出作用域并在完全运行之前被收集,为了防止这种情况,你可能想让它成为全局的,然后每次你想使用它时都重新实例化它,用新的图像。但是如果你调用它两次,第一次就会丢失,所以我发现这个方法更好,它取决于上下文,你打算一次使用多少不同的动画等等。我还添加了一个ImageindexChanged事件,该事件可用于知道图像何时在类外更改。享受吧!我希望这就是你要找的。

我只是添加了一个按钮和一个面板。将按钮的click事件绑定到Button1_Click方法

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 CustomControl
{
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        //insert your images in this next line
    }
    private void button1_Click(object sender, EventArgs e)
    {
        Image[] explodingImages = new Image[] { Properties.Resources.explode1, Properties.Resources.explode2, Properties.Resources.explode3 };
        //initialize the explosion with the images from above
        Sprites Explosion = new Sprites(explodingImages,panel1.CreateGraphics());
        //the timer will start and it will draw all images from the above collection, then clear itself, then dispose of itself.
        Explosion.ImageIndex = 0;
    }
}

public class Sprites
{
    private Image _DisplayedImage;
    public Image DisplayedImage
    {
        get { return _DisplayedImage; } 
    }
    private Image[] Images{get;set;}
    private int _ImageIndex = 0;
    public event EventHandler ImageIndexChanged;
    public int ImageIndex
    {
        get { return _ImageIndex; }
        set
        {
            //Changes thh ImageIndexNumber
            _ImageIndex = value;
            //Updates the Displayed Image with the current Image as per index
            _DisplayedImage = Images[ImageIndex];
            //fires the ImageIndexChanged Event (if required)
            if (ImageIndexChanged != null)
                ImageIndexChanged(this, EventArgs.Empty);
            //draws the explosion to the graphics object
            DrawExplosion(G, 0, 0);
            //starts the timer
            changeImageTimer.Enabled = true;
        }
    }
    //local variable for the graphics object
    private Graphics G;
    //creats a timer for changing the Images
    Timer changeImageTimer = new Timer();
    //Constructor
    public Sprites(Image[] images,Graphics g)
    {
        //set the starting Images
        Images = images;
        //set the interval time to 5 seconds- in my opinion this number is rediculously high, but if that is what you want
        changeImageTimer.Interval = 5000;
        //Get the Tick event of the timer
        changeImageTimer.Tick += new EventHandler(changeImageTimer_Tick);
        //set the Graphics that you want to draw on
        G = g;
    }
    void changeImageTimer_Tick(object sender, EventArgs e)
    {
        int temp=ImageIndex+1;
        //if there are no more pictures to display stop the timer
        if (temp > Images.Count() - 1)
        {
            //stop the timer
            changeImageTimer.Enabled = false;
            //Clear the image, replace with your own background color, or draw an image or whatever you need to do to clear the images
            G.Clear(Color.White);
        }
        //if there are more pictures select the next picture
        else
            //Changeing the imageindex fires the draw method and the imageindexchanged event
            ImageIndex++;
    }
    public void DrawExplosion(Graphics graphics,int x, int y)
    {
        graphics.DrawImage(DisplayedImage, x, y);
    }
}
}