C# 初学者RPG碰撞检测

C# 初学者RPG碰撞检测,c#,ascii,console-application,game-physics,C#,Ascii,Console Application,Game Physics,再次感谢您对我前面问题的帮助 我在RPG上取得了更多的进步,我正在为娱乐和教育而努力。我现在可以从一个.txt文件(彩色!)中显示我的地图,所以我很高兴所有这些都能正常工作 接下来我要实现的是碰撞检测系统。例如:如果我的玩家角色试图踩到“~”角色,程序不会移动玩家角色,因为“~”是水,不能在上面行走 我拥有的移动系统和加载地图的代码如下: using System; using System.IO; namespace TextFileReaderTest { class Program {

再次感谢您对我前面问题的帮助

我在RPG上取得了更多的进步,我正在为娱乐和教育而努力。我现在可以从一个.txt文件(彩色!)中显示我的地图,所以我很高兴所有这些都能正常工作

接下来我要实现的是碰撞检测系统。例如:如果我的玩家角色试图踩到“~”角色,程序不会移动玩家角色,因为“~”是水,不能在上面行走

我拥有的移动系统和加载地图的代码如下:

using System;
using System.IO;

namespace TextFileReaderTest
{
class Program
{
    public static int PosX;
    public static int PosY;
    static void DisplayMap()
    {

        string line;
        //Pass the file path and file name to the StreamReader constructor
        StreamReader sr = new StreamReader(@"D:\personal\tests\Tests\ascii map tools\map1.txt");

        //Read the first line of text
        line = sr.ReadLine();

        //Continue to read until you reach end of file
        while (line != null)
        {
            Char[] MapArray = line.ToCharArray();
            foreach (Char c in MapArray)
            {
                if (c == '/')
                {
                    Console.ForegroundColor = ConsoleColor.DarkGreen;
                    Console.Write('/');
                }
                else if (c == '^')
                {
                    Console.ForegroundColor = ConsoleColor.DarkGreen;
                    Console.Write('^');
                }
                else if (c == '|')
                {
                    Console.ForegroundColor = ConsoleColor.Green;
                    Console.Write('|');
                }
                else if (c == '.')
                {
                    Console.ForegroundColor = ConsoleColor.Green;
                    Console.Write('.');
                }
                else if (c == 'o')
                {
                    Console.ForegroundColor = ConsoleColor.DarkCyan;
                    Console.Write('o');
                }
                else if (c == '~')
                {
                    Console.ForegroundColor = ConsoleColor.DarkCyan;
                    Console.Write('~');
                }
                else
                {
                    Console.Write(c);
                    Console.ForegroundColor = System.ConsoleColor.White;
                }


            }
            //Read the next line
            line = sr.ReadLine();
        }

                //close the file
                sr.Close();

    }




    static void Main(string[] args)
    {
        Console.WindowWidth = 128;
        Console.WindowHeight = 32;
        DisplayMap();
        Console.SetCursorPosition(10, 10); //the cursor will be set at x = 10 and y = 10

        while (true)
        {
            ConsoleKeyInfo input = Console.ReadKey(true);
            PosX = Console.CursorLeft;
            PosY = Console.CursorTop;

            switch (input.KeyChar)
            {

                case 'w':
                    if (PosY >= 1)
                    {
                        Console.SetCursorPosition(PosX + 0, PosY - 1);
                        PosX = Console.CursorLeft;
                        PosY = Console.CursorTop;
                        //if (PosX == 11 && PosY == 11 )            //this is a portal
                        //{
                        //    Console.SetCursorPosition(20, 20);    // clear console, teleport player, load new map 
                        //}
                    }
                    break;

                case 'a':
                    if (PosX >= 1)
                    {
                        Console.SetCursorPosition(PosX - 1, PosY + 0);
                    }
                    break;

                case 's':
                    if (PosY < 31)
                    {
                        Console.SetCursorPosition(PosX + 0, PosY + 1);
                    }
                    break;

                case 'd':
                    if (PosX < 127)
                    {
                        Console.SetCursorPosition(PosX + 1, PosY + 0);
                    }
                    break;

            }
        }
    }
}
使用系统;
使用System.IO;
命名空间TextFileReaderTest
{
班级计划
{
公共静态int-PosX;
公共静态整数;
静态void DisplayMap()
{
弦线;
//将文件路径和文件名传递给StreamReader构造函数
StreamReader sr=新的StreamReader(@“D:\personal\tests\tests\ascii映射工具\map1.txt”);
//读课文的第一行
line=sr.ReadLine();
//继续读取,直到到达文件末尾
while(行!=null)
{
Char[]MapArray=line.ToCharArray();
foreach(MapArray中的字符c)
{
如果(c=='/'))
{
Console.ForegroundColor=ConsoleColor.DarkGreen;
Console.Write('/');
}
else if(c=='^')
{
Console.ForegroundColor=ConsoleColor.DarkGreen;
Console.Write(“^”);
}
else如果(c=='|')
{
Console.ForegroundColor=ConsoleColor.Green;
控制台。写入(“|”);
}
else如果(c=='。)
{
Console.ForegroundColor=ConsoleColor.Green;
Console.Write('.');
}
else如果(c='o')
{
Console.ForegroundColor=ConsoleColor.DarkCyan;
控制台。写('o');
}
else如果(c=='~')
{
Console.ForegroundColor=ConsoleColor.DarkCyan;
Console.Write(“~”);
}
其他的
{
控制台。写入(c);
Console.ForegroundColor=System.ConsoleColor.White;
}
}
//读下一行
line=sr.ReadLine();
}
//关闭文件
高级关闭();
}
静态void Main(字符串[]参数)
{
Console.WindowWidth=128;
Console.WindowHeight=32;
DisplayMap();
Console.SetCursorPosition(10,10);//光标将设置为x=10和y=10
while(true)
{
ConsoleKeyInfo输入=Console.ReadKey(true);
PosX=Console.CursorLeft;
PosY=Console.CursorTop;
开关(input.KeyChar)
{
案例“w”:
如果(位置>=1)
{
控制台。设置光标位置(PosX+0,PosY-1);
PosX=Console.CursorLeft;
PosY=Console.CursorTop;
//if(PosX==11&&PosY==11)//这是一个门户
//{
//Console.SetCursorPosition(20,20);//清除控制台,传送播放器,加载新地图
//}
}
打破
案例“a”:
如果(PosX>=1)
{
Console.SetCursorPosition(PosX-1,PosY+0);
}
打破
案例s:
if(PosY<31)
{
Console.SetCursorPosition(PosX+0,PosY+1);
}
打破
案例“d”:
if(PosX<127)
{
Console.SetCursorPosition(PosX+1,PosY+0);
}
打破
}
}
}
}
}

许多“if-else”语句用于地图中的颜色。请不要介意我的代码中有很多注释。每当我有了一个想法,我通常会在任何可以实现的地方写评论。另外,这是其他程序员的解释,我觉得很有用。我还是个初学者,如果你能解释一下你的解决方案,我将不胜感激


提前谢谢你

为特定的事物设置特定的类是一个很好的实践。例如,处理地图的
Map
类,处理玩家的
Player
类,等等

现在,为了处理碰撞,我将有两个
Map
s,一个用于存储和显示播放器图标等等,还有一个用于磁贴的参考
Map
(这样可以更容易地检查播放器正在使用什么磁贴,并以这种方式移动)

Map
s应该有一个
private char[][]
字段来存储分幅,以便快速调用所述分幅

将角色的当前位置存储在
Player
类中的两个字段中,
X
Y
,然后将下一个位置存储到另外两个字段中,
NewX
NewY
。在移动
播放器之前,将当前坐标存储到
PrevX
PrevY

如果
TileMap[Player.NewX][Player.NewY]
上的磁贴是玩家不应该移动到的,请不要更改
Player.X
Player.Y
。否则,将
Player.NewX
存储到
Player.X
中,将
Player.NewY
存储到
Player.Y

TL;医生:

播放器的示例
public class Player{
    public int X, Y;
    private int NewX, NewY;
    private int PrevX, PrevY;

    public Player(){
        X = 10;
        Y = 10;
        NewX = 0;
        NewY = 0;
        PrevX = 0;
        PrevY = 0;
    }

    //Add other constructors to initialize the coordinates

    public void Update(){
        //Call this method in `Main()` in a loop.  Make sure to add a delay between each call!
        PrevX = X;
        PrevY = Y;

        ConsoleKeyInfo input = Console.ReadKey(true);
        switch(input.KeyChar){
            case 'w':
                NewX = X;
                NewY = Y - 1;
                break;
            case 'a':
                NewX = X - 1;
                NewY = Y;
                break;
            case 's':
                NewX = X;
                NewY = Y + 1;
                break;
            case 'd':
                NewX = X + 1;
                NewY = Y;
        }

        //Add code to restrict the player to the window

        if(RPG.ReferenceMap[NewX][NewY] == '~'){  //Water tile
            NewX = X;
            NewY = Y;
        }

        //Check for other tiles the player should not walk on

        X = NewX;
        Y = NewY;
    }
}
public class Map{
    public char[][] TileMap;
    public int Height, Width;

    public Map(){
        TileMap = new char[16][16];  //Default to a 16x16 map
        Height = 16;
        Width = 16;
    }
    public Map(string file){
        //Load the map like you did above, but store the chars read into the TileMap array
        //Give the 'Height' and 'Width' fields the height and width of the map
    }

    public void Update(){
        //Call this AFTER Player.Update()

        //Use the reference map to add the correct tile to the previous position
        //and then update the Player's icon
        TileMap[Player.PrevX][Player.PrevY] = RPG.ReferenceMap.TileMap[Player.PrevX][Player.PrevY];

        TileMap[Player.X][Player.Y] = 'O';  //Assuming that 'O' is your player icon
    }

    public void Draw(){
        //Use the "TileMap" field to refresh the map

        Console.Clear();  //Clear the console

        foreach(char[] array in TileMap){
            foreach(char tile in array){
                //Use the logic you used in your "foreach" loop to draw the tiles.
            }
        }
    }
}
public class RPG{
    Player player;
    Map ReferenceMap, ActualMap;

    public static void Main(){
        player = new Player();  //Use the default constructor or another constructor
                                //to set the starting coords of the player

        ActualMap = new Map();  //Load the data into the map

        ReferenceMap = ActualMap;  //Since they are the same for now, just store
                                   //the data already there
        while(true){
            //Add a delay using Stopwatch, preferably 1/60th of a second
            Update();
        }
    }

    public void Update(){
        Player.Update();
        ActualMap.Update();

        ActualMap.Draw();
    }
}
^^^^^^^^^^^^^^^
|||||||||||||||

  ~~~          
 ~~~~~         
  ~~~          

...............
...............
...............
...............
using System;
using System.IO;

namespace TextFileReaderTest
{
    class Program
    {
        static char GetTerrainAt(string[] map, int x, int y)
        {
            return map[y][x];
        }

        static void PrintCharacter(int x, int y)
        {
            Console.SetCursorPosition(x, y);
            Console.ForegroundColor = ConsoleColor.Magenta;
            Console.Write('X');
        }

        static void PrintTerrainAt(string[] map, int x, int y)
        {
            char terrain = GetTerrainAt(map, x, y);

            switch (terrain)
            {
                case '/':
                    Console.ForegroundColor = ConsoleColor.DarkGreen;
                    break;
                case '^':
                    Console.ForegroundColor = ConsoleColor.DarkGreen;
                    break;
                case '|':
                    Console.ForegroundColor = ConsoleColor.Green;
                    break;
                case '.':
                    Console.ForegroundColor = ConsoleColor.Green;
                    break;
                case 'o':
                    Console.ForegroundColor = ConsoleColor.DarkCyan;
                    break;
                case '~':
                    Console.ForegroundColor = ConsoleColor.DarkCyan;
                    break;
                default:
                    Console.ForegroundColor = ConsoleColor.White;
                    break;
            }

            Console.SetCursorPosition(x, y);
            Console.Write(terrain);
        }

        static void Main()
        {
            // initialize (once)
            var map = File.ReadAllLines(@"D:\personal\tests\Tests\ascii map tools\map1.txt");

            var posX = 10;
            var posY = 10;

            Console.WindowWidth = map[0].Length; // length of first line, make sure all lines in the file are of same length
            Console.WindowHeight = map.Length; // number of lines
            Console.CursorVisible = false;

            // print whole map once
            for (int x = 0; x < Console.WindowWidth; x++)
            {
                for (int y = 0; y < Console.WindowHeight; y++)
                {
                    PrintTerrainAt(map, x, y);
                }
            }

            // print character starting pos
            PrintCharacter(posX, posY);

            // start
            while (true)
            {
                var input = Console.ReadKey(true);

                // next move for now: stay in the same place
                var nextX = posX;
                var nextY = posY;

                // find out where the next move will take us
                switch (input.KeyChar)
                {
                    case 'w':
                        nextY--;
                        break;

                    case 'a':
                        nextX--;
                        break;

                    case 's':
                        nextY++;
                        break;

                    case 'd':
                        nextX++;
                        break;
                }

                // make sure it's a legal move 
                if (nextY >= Console.WindowHeight || nextY < 0 || nextX >= Console.WindowWidth || nextX < 0)
                {
                    // illegal move, beep and continue the while loop from the top without moving the character
                    Console.Beep();
                    continue;
                }

                char terrainToMoveTo = GetTerrainAt(map, nextX, nextY);

                // this should probably be moved into a function "IsTerrainPassable(terrainToMoveTo)"
                if (terrainToMoveTo == '~')
                {
                    // illegal move, beep and continue the while loop from the top without moving the character
                    Console.Beep();
                    continue;
                }

                // okay, legal move, move our character:

                // clean up old position (if you comment this out, you will see a "snake")
                PrintTerrainAt(map, posX, posY);

                // move character
                posX = nextX;
                posY = nextY;

                // print character at new position
                PrintCharacter(posX, posY);
            }
        }
    }
}