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