简体   繁体   English

我无法移动 PictureBox

[英]I can`t get move PictureBox

I can't make a function so that during the movement of the picturebox which happens with a while loop.我无法制作一个函数,以便在图片框移动期间发生 while 循环。

I executed a script on certain coordinates, I tried to do it using the switch statement, but the function simply does not work我在某些坐标上执行了一个脚本,我尝试使用 switch 语句来执行它,但该函数根本不起作用

When you run it, nothing happens, as if this line of code does not exist.当你运行它时,什么都没有发生,就好像这行代码不存在一样。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;

namespace shadowfiend_minigame
{
    public partial class Form1 : Form
    {
        private int _first_shadowrazeX = 404, _first_shadowrazeY = 204;
        private int _second_shadowrazeX = 724, _second_shadowrazeY = 204;
        private int _third_shadowrazeX = 1106, _third_shadowrazeY = 204;
        private int zeus_hp = 1000;
        private int shadow_fiend_hp = 2800;
        Point point = new Point(1106, 204);
        Point point2 = new Point(724, 204);
        Point point3 = new Point(404, 204);
        private int speed_zeus, damage_zeus;
        private int shadow_fiend_damage;
        Thread thread = new Thread(ShadowRaze_Click);

        public Form1()
        {
            InitializeComponent();            
            this.KeyDown += new KeyEventHandler(ShadowRaze_Click);
            KeyPreview = true;
        }

        bool CheckedBox()
        {
            bool checked1 = checkBox1.Checked;
            bool checked2 = checkBox2.Checked;
            bool checked3 = checkBox3.Checked;
            if (checked1 == false && checked2 == false && checked3 == false)
            {
                return false;
            }
            else return true;
        }


        private async void Start_Click(object sender, EventArgs e)
        {
            Thread thread = new Thread(Zeus);
            if (CheckedBox() == false)
            {
                MessageBox.Show("Выберите сложность игры!");
            }
            else
            {
                Start.Visible = false;
                checkBox1.Visible = false;
                checkBox2.Visible = false;
                checkBox3.Visible = false;
                thread.Start();
            }
        }

        private async void Zeus()
        {
            Thread thread = new Thread(Zeus);
            while (shadow_fiend_hp != 0)
            {
                for (int i = 0; i < 50; i++)
                {
                    var x = _zeus.Location.X;
                    this.Invoke(new Action(() => _zeus.Location = new Point(_zeus.Location.X - 20, _zeus.Location.Y)));
                    Thread.Sleep(speed_zeus);
                    switch (_zeus.Location.X)
                    /*
                     * Here it is necessary that when the picturebox reaches a certain point while moving, the function is executed
                     */
                    {
                        case 1106:
                            zeus_hp = zeus_hp - 200;
                            this.Invoke(new Action(() => label4.Text = "zeus_hp: " + zeus_hp));
                            break;
                        case 724:
                            zeus_hp = zeus_hp - 200;
                            this.Invoke(new Action(() => label4.Text = "zeus_hp: " + zeus_hp));
                            break;
                        case 404:
                            zeus_hp = zeus_hp - 200;
                            this.Invoke(new Action(() => label4.Text = "zeus_hp: " + zeus_hp));
                            break;
                    }
                }
                Zeus_Attack(damage_zeus);
                if (shadow_fiend_hp == 0)
                {
                    MessageBox.Show("You lose");
                    this.Invoke(new Action(() => Start.Visible = true)); 
                    this.Invoke(new Action(() => checkBox1.Visible = true));
                    this.Invoke(new Action(() => checkBox2.Visible = true));
                    this.Invoke(new Action(() => checkBox3.Visible = true));
                }
                else if (zeus_hp == 0)
                {
                    MessageBox.Show("You win");
                    this.Invoke(new Action(() => Start.Visible = true));
                    this.Invoke(new Action(() => checkBox1.Visible = true));
                    this.Invoke(new Action(() => checkBox2.Visible = true));
                    this.Invoke(new Action(() => checkBox3.Visible = true));
                }
                for (int i = 0; i < 50; i++)
                {
                    this.Invoke(new Action(() => _zeus.Location = new Point(_zeus.Location.X + 20, _zeus.Location.Y)));
                    Thread.Sleep(speed_zeus);
                }
            }
            thread.Join();
            ResetAll();
        }

        private void checkBox2_CheckedChanged(object sender, EventArgs e)
        {
            checkBox3.Checked = false;
            checkBox1.Checked = false;
            speed_zeus = 30;
            damage_zeus = 200;
        }

        private void checkBox3_CheckedChanged(object sender, EventArgs e)
        {
            checkBox1.Checked = false;
            checkBox2.Checked = false;
            speed_zeus = 10;
            damage_zeus = 400;
        }

        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            checkBox3.Checked = false;
            checkBox2.Checked = false;
            speed_zeus = 50;
            damage_zeus = 100;
        }

        private async void Zeus_Attack(int damage)
        {
            shadow_fiend_hp = shadow_fiend_hp - damage;
            this.Invoke(new Action(() => hp.Text = "HP: " + shadow_fiend_hp));
        }

        private async void ShadowFiend_Attack()
        {
            zeus_hp = zeus_hp - 200;
            this.Invoke(new Action(() => label4.Text = "HP: " + shadow_fiend_hp));

        }

        private void ResetAll() 
            => this.Invoke(new Action(() => hp.Text = "HP: 2800"));
      
        private async void ShadowRaze_Click(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.Z:
                    shock.Location = new Point(_first_shadowrazeX, _first_shadowrazeY);
                    shock.Visible = true;
                    this.Update();
                    Thread.Sleep(100);
                    shock.Visible = false;
                    break;
                case Keys.X:
                    shock.Location = new Point(_second_shadowrazeX, _second_shadowrazeY);
                    shock.Visible = true;
                    this.Update();
                    Thread.Sleep(100);
                    shock.Visible = false;
                    break;
                case Keys.C:
                    shock.Location = new Point(_third_shadowrazeX, _third_shadowrazeY);
                    shock.Visible = true;
                    this.Update();
                    Thread.Sleep(100);
                    shock.Visible = false;
                    break;
            }
        }
    }
}

Here's some pretty simple code to move a picture box around the screen using async and await .这是一些非常简单的代码,可以使用asyncawait在屏幕上移动图片框。 It's not based on your code - yours is far from being a Minimal Reproduceable Example.它不是基于您的代码 - 您的代码远非最小可复制示例。 This is.这是。

I dropped a few coptrols my form:我在表单中删除了一些 coptrols:

  • A combo box一个组合框
  • Two textboxes (Offset and Period)两个文本框(偏移量和周期)
  • Two Buttons (Go and Stop)两个按钮(开始和停止)
  • A PictureBox (I made this public and gave it an obvious background color一个 PictureBox(我把它公开并给它一个明显的背景颜色

Then I created this enum to state the direction I wanted to move the picture box:然后我创建了这个enum来说明我想要移动图片框的方向:

public enum Direction
{
    SouthEast,
    East,
    NorthEast,
    North,
    NorthWest,
    West,
    SouthWest,
    South,
}

Then I created this worker class:然后我创建了这个工人阶级:

internal class PictureBoxMover
{
    public bool enabled = true;
    Direction _direction;
    int _offset;
    int _period;
    Form1 _theForm;

    private static Dictionary<Direction, (int deltaX, int deltaY)> _deltaRules = new Dictionary<Direction, (int deltaX, int deltaY)> {
        { Direction.North, (0, -1) },
        { Direction.South, (0, 1) },
        { Direction.East, (1, 0) },
        { Direction.West, (-1, 0) },
        { Direction.NorthEast, (1, -1) },
        { Direction.NorthWest, (-1, -1) },
        { Direction.SouthEast, (1, 1) },
        { Direction.SouthWest, (-1, 1) },
    };

    public PictureBoxMover (Form1 parentForm, Direction direction, int offset, int period)
    {
        _theForm = parentForm;
        _direction=direction;
        _offset=offset;
        _period=period;
    }

    public void Disable()
    {
        enabled = false;
    }

    public async Task Run()
    {
        var directionRule = _deltaRules[_direction];
        var offsetXY = (directionRule.deltaX * _offset, directionRule.deltaY * _offset);
        while (enabled)
        {
            _theForm.pictureBox1.Location = new Point(_theForm.pictureBox1.Location.X + offsetXY.Item1, _theForm.pictureBox1.Location.Y + offsetXY.Item2);
            await Task.Delay(_period);
        }
    }
}

The static _deltaRules dictionary makes sense of the Directions .静态_deltaRules字典对Directions有意义。 The ( 1, -1 ) denotes a tuple of two integers (ie, _deltaRules is a dictionary with a Direction as key and a two integer tuple as value ( 1, -1 )表示两个整数的元组(即, _deltaRules是一个字典,其中一个Direction作为,一个两个整数元组作为

The main reason for instance of this class is to allow them to be easily cancellable (/disablable).此类实例的主要原因是允许它们轻松取消(/禁用)。

In the form's constructor, I bind the Direction dropdown combobox to the possible values of Direction:在表单的构造函数中,我将 Direction 下拉组合框绑定到 Direction 的可能值:

DirectionDropDown.DataSource = Enum.GetNames<Direction>();

The rest of the form's class looks like this:表单类的其余部分如下所示:

private PictureBoxMover? _currentPictureBoxMover = null;

private async void GoBtn_Click(object sender, EventArgs e)
{
    if (Enum.TryParse<Direction>(DirectionDropDown.SelectedItem.ToString(), out var direction) &&
        int.TryParse(OffsetTxt.Text, out var offset) &&
        int.TryParse(PeriodTxt.Text, out var period))
    {
        if (_currentPictureBoxMover != null)
        {
            _currentPictureBoxMover.Disable();
        }
        _currentPictureBoxMover = new PictureBoxMover(this, direction, offset, period);
        await _currentPictureBoxMover.Run();
    }
}

private void StopBtn_Click(object sender, EventArgs e)
{
    if (_currentPictureBoxMover != null)
    {
        _currentPictureBoxMover.Disable();
    }
    _currentPictureBoxMover = null;
}

I keep track of the _currentPictureBoxMover so that I can disable it when I start moving in a new direction.我跟踪_currentPictureBoxMover以便在我开始朝新方向移动时禁用它。 Otherwise the code is pretty self-explanatory.否则代码是不言自明的。

Note that because everything is done with async and await , I have no threading issues, and no timers to worry about.请注意,因为一切都是通过asyncawait完成的,所以我没有线程问题,也不需要担心计时器。

One thing to note: part of the reason for having the period/offset controls is to show (and prove to myself) that the form is fully functional while things are moving around需要注意的一件事:使用周期/偏移控制的部分原因是为了显示(并向我自己证明)表单在事物移动时功能齐全

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM