简体   繁体   中英

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.

I executed a script on certain coordinates, I tried to do it using the switch statement, but the function simply does not work

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 . 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:

  • 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

Then I created this enum to state the direction I wanted to move the picture box:

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 . 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

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:

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. 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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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