Проблемы с изометрической плиткой C # XNA - PullRequest
0 голосов
/ 03 апреля 2011

В настоящее время я работаю над школьным проектом, в котором мне нужно разработать изометрическую игру. К сожалению, поскольку мои учителя вообще ничего не знают о разработке игр (уже сосредоточившись на переходе в новую школу), я застрял.

Прямо сейчас я могу с легкостью рисовать игровую карту, но на этом она останавливается. Когда я добавляю персонажа, я вижу, что он визуализируется, но я не могу его переместить. Скорее всего, я перепутал математические задачи IsoToScreen и ScreenToIso.

Когда я пытаюсь переместить моего персонажа всего на 1 пиксель, он почему-то сразу исчезает с экрана.

Вот мой класс IsoMath, который я использую для преобразования простого 2D в 2,5D изометрического

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);
                }
            }
        }

Вы можете щелкнуть здесь (1,13Mb) , чтобы загрузить zip-архив всего проекта, если вы считаете, что я не предоставил достаточно информации.

Ответы [ 2 ]

1 голос
/ 17 января 2013

это код, который у меня есть, и он работает для любого размера карты.он основан на обычном 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, а когда mapX реагирует на maxX для карты, онаустанавливается в ноль и добавляет единицу к карте Y, что означает, что следующая плитка переместится к следующей изометрической координате y.

, поэтому и x, и y устанавливаются одновременно, и егоочень нравится вращать всю карту, но она использует изометрические координаты, а не просто использует 2-мерные плитки.

Теперь единственная проблема с этим состоит в том, что кажется, что она закоротила несколько плиток, но это можно исправить простодобавив еще несколько строковых значений в массив.

как его использовать:

сначала объявить

Texture2D [] tex = new Texture2D [2];

, затем объявите

MapEngine.Map map;

, где 2 - это количество различных плиток, которые у вас есть.

второй установить текс на

tex [0] = Content.Load (@ "grass");tex [1] = Content.Load (@ "dirt");

, затем установите карту в (но НИКОГДА не поместите это в функцию loadcontent) поместите ее либо в обновлениеили нарисовать функцию. (она будет удалена из вида)

map = new MapEngine.Map (tex);

с 0 - идентификатор карты, а трава -имя вашего изображения.

Теперь, чтобы нарисовать карту в игре, используйте

map.draw (spriteBatch);

0 голосов
/ 03 апреля 2011

Как вы пытались переместить своего персонажа?

Если он равен 1,0f на кадр (то есть выполняется методом обновления или рисования), это много движения, особенно если вы работаете на ПК с нефиксированной частотой кадров.

...