winforms 开发火柴人平台游戏时在C# windows窗体中将对象设置为“Solid”

mzillmmw  于 2022-11-25  发布在  C#
关注(0)|答案(2)|浏览(167)

为了一个学校项目,我需要开发一个纯C# Windows窗体的平台风格游戏,不能使用任何其他语言。我已经整理了重力和移动系统,但我的角色仍然能够跳出Map或跳过图片框。我将如何让这些对象成为实体,使角色无法穿过它们。以下是我的代码
我的游戏外观:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }
    bool left;
    bool right;

    int gravity = 20;
    int force;
    bool jump;

    private void Timer(object sender, EventArgs e)
    {
        if (left == true)
        {
            Character.Left -= 15;
            if (Character.Image != Properties.Resources.LeftChar)
            {
                Character.Image = Properties.Resources.LeftChar;
            }
        }

        if (right == true)
        {
            Character.Left += 15;
            if (Character.Image != Properties.Resources.RightChar)
            {
                Character.Image = Properties.Resources.RightChar;
            }
        }

        if (jump == true)
        {
            Character.Top -= force;
            force -= 1;
        }
  

        if (Character.Top + Character.Height >= GameBoundary.Height)
        {
            Character.Top = GameBoundary.Height - Character.Height;
            jump = false;
        }
        else
        {
            Character.Top += 10; 
        }

    }
    private void keydown(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.A)
            left = true;
        if (e.KeyCode == Keys.D)
            right = true;
        if (jump != true)
        {
            if (e.KeyCode == Keys.W)
            {
                jump = true;
                force = gravity;
            }
        }
    }

    private void keyup(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.A)
            left = false;
        if (e.KeyCode == Keys.D)
            right = false;
    }
}

我创建了一个与游戏大小相同的隐形面板,叫做“游戏边界”,这使得玩家可以在窗口底部行走,但我不知道如何将其应用到代码的其余部分。如果有人有任何建议,将非常欢迎。C#还不太好!

f2uvfpb9

f2uvfpb91#

你需要实现碰撞检测。在你的人和任何你不想让他穿过的物体周围画一个假想的盒子。检查是否有任何盒子重叠。如果有,把一个或两个物体都移回来,直到盒子不再重叠。

z9smfwbn

z9smfwbn2#

下面是一个基本的碰撞检测系统:

public class CollisionDetection
    {
        public static bool ObjectTouchingOthers(Control Object, int SpaceBetweenObjects)
        {
            for (int i = 0; i < Object.Parent.Controls.Count; i++)
            {
                if (Object.Parent.Controls[i].Name != Object.Name)
                {
                    if (Object.Left + Object.Width + SpaceBetweenObjects > Object.Parent.Controls[i].Left && Object.Top + Object.Height + SpaceBetweenObjects > Object.Parent.Controls[i].Top && Object.Left < Object.Parent.Controls[i].Left + Object.Parent.Controls[i].Width + SpaceBetweenObjects && Object.Top < Object.Parent.Controls[i].Top + Object.Parent.Controls[i].Height + SpaceBetweenObjects)
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        public static bool ObjectTouchingOthers(Control Object, int SpaceBetweenObjects,  Control[] ControlsToExclude )
        {
            for (int i = 0; i < Object.Parent.Controls.Count; i++)
            {
                if (ControlsToExclude.Contains(Object.Parent.Controls[i]) == false && Object.Parent.Controls[i].Name != Object.Name)
                {
                    if (Object.Left + Object.Width + SpaceBetweenObjects > Object.Parent.Controls[i].Left && Object.Top + Object.Height + SpaceBetweenObjects > Object.Parent.Controls[i].Top && Object.Left < Object.Parent.Controls[i].Left + Object.Parent.Controls[i].Width + SpaceBetweenObjects && Object.Top < Object.Parent.Controls[i].Top + Object.Parent.Controls[i].Height + SpaceBetweenObjects)
                    {
                        return true;
                    }
                }
            }
            return false;
        }
    }

第一个参数Object是要进行冲突检测的控件,它只会检测同一容器中的其他控件,因此,例如,如果将它用于panel中的控件,它只会对面板中的其他控件起作用。第二个参数简单地指定了当控件接触时,它们之间的距离。如果您使用的是second overload,第三个参数是一个不需要冲突检测的控件数组。这就是您使用第二个重载的方式:

private void btnMoveLeft_Click(object sender, EventArgs e)
    {
        btnPlayer.Left -= 1;
        if (CollisionDetection.ObjectTouchingOthers(btnPlayer, 1, new Control[] {button1, button2}) == true)
        { 
            btnPlayer.Left += 1;
        }
    }

使用这个多载,它会继续执行您在数组中指定的控件。
最后,我们来看一个基本的例子,说明如何设置冲突检测:

private void btnMoveLeft_Click(object sender, EventArgs e)
    {
        btnPlayer.Left -= 1;
        if (CollisionDetection.ObjectTouchingOthers(btnPlayer, 1) == true)
        { 
            btnPlayer.Left += 1;
        }
    }

    private void btnMoveRight_Click(object sender, EventArgs e)
    {
        btnPlayer.Left += 1;
        if (CollisionDetection.ObjectTouchingOthers(btnPlayer, 1) == true)
        {
            btnPlayer.Left -= 1;
        }
    }

    private void btnMoveUp_Click(object sender, EventArgs e)
    {
        btnPlayer.Top -= 1;
        if (CollisionDetection.ObjectTouchingOthers(btnPlayer, 1) == true)
        {
            btnPlayer.Top += 1;
        }
    }

    private void btnMoveDown_Click(object sender, EventArgs e)
    {
        btnPlayer.Top += 1;
        if (CollisionDetection.ObjectTouchingOthers(btnPlayer, 1) == true)
        {
            btnPlayer.Top -= 1;
        }
    }

请记住,您必须更改代码中控件的名称。作为参考,下面是我的测试表单:

相关问题