在WPF C#中使用Canvas跟踪玩家的动作

thtygnil  于 2023-01-10  发布在  C#
关注(0)|答案(1)|浏览(171)

我试图建立一个项目的原始吃豆人游戏在WPF的C#使用画布和我卡住了鬼的跟踪和运动。这个想法是为了检查如果鬼将通过一堵墙移动的下一步,并防止它。
但很明显我的程序是错的,鬼魂一直移动到墙那里,然后后退一步,然后又移到墙那里,等等。
我该怎么修正算法呢,当然,如果你有其他想法我很乐意听听.
谢谢!
下面是幽灵运动的相关代码:

//flags are used to check if the ghosts next move is through a wall
        double x1 = Canvas.GetTop(pacman);
        double y = Canvas.GetLeft(pacman);
        if (Math.Abs(Canvas.GetTop(redGuy) - x1) > Math.Abs(Canvas.GetLeft(redGuy) - y) && (flagUp == false || flagDown == false))
        {
            if (Canvas.GetTop(redGuy) < x1)
            {
                if (flagDown == false)
                {
                    Canvas.SetTop(redGuy, Canvas.GetTop(redGuy) + ghostSpeed);
                }
                else if (flagRight == false || flagLeft == false)
                {
                    if (Canvas.GetLeft(redGuy) < y && flagLeft == false)
                    {
                        Canvas.SetLeft(redGuy, Canvas.GetLeft(redGuy) + ghostSpeed);
                    }
                    else if (flagRight == false)
                    {
                        Canvas.SetLeft(redGuy, Canvas.GetLeft(redGuy) - ghostSpeed);
                    }
                }
            }
            else
            {
                if (flagUp == false)
                {
                    Canvas.SetTop(redGuy, Canvas.GetTop(redGuy) - ghostSpeed);
                }
                else if (flagRight == false || flagLeft == false)
                {
                    if (Canvas.GetLeft(redGuy) < y && flagLeft == false)
                    {
                        Canvas.SetLeft(redGuy, Canvas.GetLeft(redGuy) + ghostSpeed);
                    }
                    else if (flagRight == false)
                    {
                        Canvas.SetLeft(redGuy, Canvas.GetLeft(redGuy) - ghostSpeed);
                    }
                }
            }
        }
        else if (flagRight == false || flagLeft == false)
        {
            if (Canvas.GetLeft(redGuy) < y)
            {
                if (flagLeft == false)
                {
                    Canvas.SetLeft(redGuy, Canvas.GetLeft(redGuy) + ghostSpeed);
                }
                else if (flagUp == false || flagDown == false)
                {
                    if (Canvas.GetTop(redGuy) > x1 && flagUp == false)
                    {
                        Canvas.SetTop(redGuy, Canvas.GetTop(redGuy) - ghostSpeed);
                    }
                    else if (flagDown == false)
                    {
                        Canvas.SetTop(redGuy, Canvas.GetTop(redGuy) + ghostSpeed);
                    }
                }
            }
            else
            {
                if (flagRight == false)
                {
                    Canvas.SetLeft(redGuy, Canvas.GetLeft(redGuy) - ghostSpeed);
                }
                else if (flagUp == false || flagDown == false)
                {
                    if (Canvas.GetTop(redGuy) > x1 && flagDown == false)
                    {
                        Canvas.SetTop(redGuy, Canvas.GetTop(redGuy) - ghostSpeed);
                    }
                    else if (flagRight == false)
                    {
                        Canvas.SetTop(redGuy, Canvas.GetTop(redGuy) + ghostSpeed);
                    }
                }
            }
        }
laawzig2

laawzig21#

我认为你的主要问题是游戏设计。
不要将UI用作数据存储。
而是使用UI作为数据的表示。
我不确定这是否真的是一个适合SO的答案,但它不适合评论。
把你的游戏区域想象成一个正方形的网格。大约是你的吃豆人/玩家的大小。
用一个2d数组来表示它,大致可以说是Square[100,80]。
一个给定的吃豆人或幽灵有一个广场,他们与使用整数x,y坐标。
如果一个鬼魂和玩家有相同的坐标,那么他们就抓住了他。
你仍然可以在画布上定位精灵,并计算它们从坐标中的位置。或者,棋盘可以用itemscontrol来表示,画布作为itemspanel。这是一个相当常见的方法,如果你搜索的话,你应该能够找到。但是基本上你绑定了一个observablecollection到itemscontrol的itemssource。这个集合有一个类型化的视图模型来指示它是什么。一个playerviewmodel,ghostviewmodel、wallviewmodel等。然后使用datatype将这些模板化到UI中,以匹配viewmodel与datatemplate。您可以通过公开x、y属性并将它们绑定到项目容器的canvas、left和www.example.com属性来定位网格canvas.top。使用转换器从平方值计算px值。
如果x和y是px值:

<ItemsControl.ItemContainerStyle>
    <Style TargetType="ContentPresenter">
        <Setter Property="Canvas.Left" Value="{Binding Path=XPos}" />
        <Setter Property="Canvas.Top" Value="{Binding Path=YPos}" />
    </Style>
  </ItemsControl.ItemContainerStyle>

但是一个正方形比一个px大,所以你需要通过一个转换器进行乘法转换。
你可能会认为这种模板业务效率很低。但它的伸缩性很好。对于我们的Map编辑应用程序,你可以做的事情之一是“画”出一个树林的轮廓。这是翻译成屏幕上的一个区域,然后充满了树木。可以有成千上万的树木。
对于每一个都有一个treevm和一个datatemplate,使用3个模板中的一个。
https://i.imgur.com/dyhuzrt.png
一旦你有了一个网格,你可以使用路径算法,如空间A*,如果鬼向吃豆人移动。我不记得他们是否这样做或只是随机移动。
如果你对设计游戏感兴趣,那么很多游戏都需要路径,空间A* 可能是最常用的。特别是当所有方块的成本都相同时。我们的游戏使用的是可变成本的空间A*。
阿米特的文章写得不错:
http://theory.stanford.edu/~amitp/GameProgramming/

相关问题