我目前正在开展一个学校项目,我需要开发一个等距游戏。不幸的是,由于我的老师对游戏开发一无所知(已经专注于转换到新学校),我被困住了。
现在我可以轻松地绘制游戏地图,但它会停止。当我添加角色时,我看到它被渲染但我无法移动它。我很可能搞乱了IsoToScreen和ScreenToIso数学问题。
当我试图将我的角色移动1px时,由于某种原因,它会立即离开屏幕。
这是我用来将简单2D转换为2.5D等距
的IsoMath类using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
namespace Beowulf
{
class IsoMath
{
private double tw, th, tx, ty, sx, sy;
public IsoMath(double width, double height)
{
tw = width;
th = height;
}
public Vector2 ScreenToIsoTile(Vector2 start, Vector2 offset, Vector2 screenOriginPoint)
{
Vector2 ret = new Vector2(0, 0);
sx = start.X - (screenOriginPoint.X + offset.X);
sy = start.Y - (screenOriginPoint.Y + offset.Y);
tx = System.Math.Round((sx / (tw * 2)) + (sy / (th * 2))) - 1;
ty = System.Math.Round((-sx / (tw * 2)) + (sy / (th * 2)));
ret.X = (float)tx;
ret.Y = (float)ty;
return ret;
}
public Vector2 ScreenToIsoPoint(float x, float y)
{
Vector2 ret = new Vector2(0, 0);
tx = (x - y) * tw;
ty = (x + y) * th;
ret.X = (float)tx * .5f;
ret.Y = (float)ty * .5f;
return ret;
}
public Vector2 IsoToScreenPoint(float x, float y)
{
Vector2 ret = new Vector2(0, 0);
tx = (x + y) / tw;
ty = (x - y) / th;
ret.X = (float)tx / .5f;
ret.Y = (float)ty * -1;
return ret;
}
public Vector2 ScreenToIso(float x, float y)
{
Vector2 ret = new Vector2(0, 0);
tx = (x - y);
ty = (x + y);
ret.X = (float)tx;
ret.Y = (float)ty;
return ret;
}
public Vector2 IsoToScreen(float x, float y)
{
Vector2 ret = new Vector2(0, 0);
tx = (x + y);
ty = (x - y);
ret.X = (float)tx * .5f;
ret.Y = -(float)ty / 2;
return ret;
}
}
}
我的Player类只是一个带有Draw的占位符(SpriteBatch sp,vector2 playerPostition);顾名思义的方法在给定位置绘制字符(此位置在主Draw方法中预先计算)
这是我将我的角色画到屏幕上的方式。它适用于固定的x14,y14位置(Floats),但是当我向这两个值中的任何一个添加1f时,该角色无处可寻。
Vector2 plPos = isoMath.ScreenToIsoPoint(pl.X, pl.Y);
plPos.X += x;
plPos.Y += y;
pl.Draw(spriteBatch, plPos);
我使用以下代码(在绘制角色之前)来渲染我的地图。大量的if语句用于剔除屏幕拼贴。
for (int i = 0; i < scene.width; i++)
{
for (int j = 0; j < scene.height; j++)
{
Vector2 p = isoMath.ScreenToIsoPoint(i, j);
Rectangle r = new Rectangle(0, 0, graphics.PreferredBackBufferWidth, graphics.PreferredBackBufferHeight);
if (r.Contains(new Point((int)(((p.X) + x)), (int)((p.Y) + y))) || r.Contains(new Point((int)((p.X) + x) + tile.Width, (int)((p.Y) + y + tile.Height))) || r.Contains(new Point((int)((p.X) + x) + tile.Width, (int)((p.Y) + y))) || r.Contains(new Point((int)((p.X) + x), (int)((p.Y) + y + tile.Height))))
{
spriteBatch.Draw(tile, new Rectangle((int)((p.X) + x), (int)((p.Y) + y), (int)(tile.Width * 1.02), (int)(tile.Height * 1.02)), Color.White);
}
}
}
如果您认为我没有提供足够的信息,您可以click here (1.13Mb)下载整个项目的zip存档。
答案 0 :(得分:1)
这是我的代码,它适用于任何地图大小。它基于普通的2d平铺显示。
Texture2D[] texture;
Rectangle rec;
int[] mapData = {
0,0,1,1,
0,0,0,0,
0,0,0,0};
int mapWidth = 4;
int mapY = 0;
int mapX = 0;
public Map(Texture2D[] tex)
{
texture = tex;
rec = new Rectangle(200, 10, tex[0].Width, tex[0].Height);
}
public void draw(SpriteBatch spriteBatch)
{
spriteBatch.Begin();
for (int i = 1; i < mapData.Length; i++)
{
if (mapX >= mapWidth)
{
mapY++;
mapX = 0;
}
else
{
mapX++;
spriteBatch.Draw(texture[mapData[i]], new Rectangle((200 - ((rec.Width / 2) * (mapX))) + (rec.X + ((rec.Width / 2) * (mapY))), (rec.Y + (16 * (mapX))) + (16) * mapY, rec.Width, rec.Height), Color.White);
}
}
spriteBatch.End();
}
那么这里发生了什么?
所以在spriteBatch.draw函数中,有一个计算,我最终锻炼,我不确定它是如何做到的,但我只是使用反复试验,找到计算。
因此,每当它从列表中读取mapData字符串时,它就会添加到mapX,这意味着下一个图块将移动到基于等轴测图的x-coord,当mapX对地图的maxX做出反应时,它会设置为零,并在mapY中添加一个,这意味着下一个tile将移动到下一个等距y-coord。
所以x和y都是同时设置的,它真的像旋转整个地图一样,但它使用等距坐标,而不是仅使用2d瓷砖。
现在唯一的问题是,它似乎缩短了几个磁贴,但只需在数组中添加几个字符串值即可修复它。
如何使用它:
首先声明
Texture2D [] tex = new Texture2D [2];
然后宣布
MapEngine.Map map;
2是你拥有的不同瓷砖的数量。
第二次将tex设置为
tex [0] = Content.Load(@“grass”); tex [1] = Content.Load(@ “污垢”);
然后将map设置为(但 NEVER 将此设置为loadcontent函数) 把它放在更新或绘图功能中。(它会远离视图)
map = new MapEngine.Map(tex);
其中0是地图ID,而grass是图像的名称。
现在在游戏中绘制地图,使用
map.draw(spriteBatch);
答案 1 :(得分:0)
你是如何尝试移动角色的?
如果它是每帧1.0f(即在更新或绘图方法中完成),这是一个很大的移动,特别是如果你在具有非固定帧速率的PC上。