C # XNA Draw метод и ошибки столкновения - PullRequest
0 голосов
/ 23 октября 2011

Я пытался сделать 2D RPG-игру после изучения C # XNA из книги, в которой написано 3 игры, но эти ошибки сводят меня с ума, и мне придется сдаться, поскольку я не могу найти никакого исправления.

Прежде всего, это метод Draw, у меня есть камни на экране, и они нарисованы на той же глубине, но нарисованы по порядку, так что он идет вдоль осей X, затем он увеличивает оси Y и сбрасывает X и такна.Поэтому они должны перекрывать другие камни над ними или слева, но это не работает.Они случайным образом идут друг на друга, когда я двигаюсь вокруг или стреляю стрелами, вот мой код, если это поможет:

Game1.cs Метод рисования

Protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);

        spriteBatch.Begin(
            SpriteSortMode.BackToFront,
            BlendState.AlphaBlend);

        TileMap.Draw(spriteBatch);
        ObjectManager.Draw(spriteBatch);
        player.Draw(spriteBatch);
        WeaponManager.Draw(spriteBatch);

        spriteBatch.End();

        base.Draw(gameTime);
    }

ObjectManager Метод рисования

static public void Draw(SpriteBatch spriteBatch)
    {
        // Get the tile locations of each corner tile on the screen
        int startX = (((int)Camera.Position.X) / 32) - 2;
        int endX = ((int)Camera.Position.X + Camera.ViewPortWidth) / 32;

        int startY = (((int)Camera.Position.Y) / 32) - 2;
        int endY = ((int)Camera.Position.Y + Camera.ViewPortHeight) / 32;

        // Go through all possible objects and draw them to the screen if they exist
        for (int y = startY; y <= endY; y++)
            for (int x = startX; x <= endX; x++)
            {
                if ((x > 0) && (y > 0) && (x < MapWidth - 1) && (y < MapHeight - 1))
                {
                    if (objects[x, y] != null)
                    {
                        spriteBatch.Draw(
                                texture,
                                Camera.Transform(objects[x, y].destinationRectangle),
                                objects[x, y].Frame,
                                new Color(256, 256, 256, objects[x, y].Transparency),
                                0,
                                new Vector2(0, 0),
                                SpriteEffects.None,
                                objects[x, y].Depth);
                    }
                }
            }
    }

Вторая проблема связана с моим столкновением, я использую столкновение ограничивающего прямоугольника с классом Rectangle для всего.Когда персонаж моего игрока перемещается, я создаю новый прямоугольник для новой локации, и если он сталкивается с любым из ограничивающих рамок любого объекта, то движение отменяется, но иногда он все равно перемещается в эту локацию и застревает в объекте.1 пиксельПросто не имеет никакого смысла, как это иногда случается, а иногда нет, даже с одним и тем же объектом.Если у кого-то есть идея, почему это может происходить, пожалуйста, напишите, здесь слишком много кода, чтобы вставить его, поэтому я оставлю его, меня больше беспокоит проблема метода Draw.

Ответы [ 3 ]

1 голос
/ 23 октября 2011

Вы делаете это:

 spriteBatch.Begin(
        SpriteSortMode.BackToFront,
        BlendState.AlphaBlend);

Это будет переупорядочивать ваши вызовы отрисовки, основанные на глубине.

Таким образом, если объекты с одинаковой глубиной, будут нарисованы быстро.

Лучше, если вы изменяете глубину камней, в зависимости от того, что вы хотите нарисовать.

float min_depth = 0.7f;
float max_depth = 0.5f;
int num_rocks_total;
int index_rocks;
for (rock_top_left to rock_bottom_right) 
  rock.depth = MathHelper.Lerp(min_depth, max_depth, index_rocks/ (float) num_rocks_total);

вторая ошибка может быть связана с точностью поплавка.

0 голосов
/ 23 октября 2011

Вместо SpriteSortMode.BackToFront вы можете использовать Deferred:

spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend);

Вот документация: http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.graphics.spritesortmode.aspx

0 голосов
/ 23 октября 2011

Задача 1 :

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

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

Проблема 2 :

Как сказал Блау, это также, вероятно, связано сточность плавания.Однако проблемы можно избежать.Представьте, что у вас есть движущаяся плитка, и ваш игрок ходит рядом с этой плиткой.Затем плитка перемещается поверх вашего игрока (потому что мы забыли кодировать плитку , а не to).Ваш игрок теперь не может двигаться, потому что любое направление, в котором игрок пытается двигаться, является «недопустимым», потому что он будет касаться этой плитки.

Проблема в том, что мы предотвращаемперсонаж из движущегося .Если бы персонаж всегда мог двигаться, у нас не было бы этой проблемы.Однако, если персонаж мог всегда двигаться, он мог бы просто более правильно проходить через вещи.Чтобы предотвратить это, нам нужно противоположное действие, действующее против персонажа, когда он движется против твердого объекта.

Решение :

Разрешить игроку двигаться в объект,а затем сканировать все объекты, к которым он прикасается.Если он касается какого-либо из них, определите, в каком направлении вы должны отодвинуть его на от каждого объекта, и объедините все эти направления в один вектор.Масштабируйте этот вектор до некоторой разумной величины (чтобы предотвратить резкое отталкивание персонажа).Переместите игрока в соответствии с этим вектором

Проблемы с этим методом :

Если у вас есть сила гравитации или тому подобное, вы можете обнаружить, что ваш персонаж "тонет"в землю.Это результат воздействия силы тяжести на силу, которая оттолкнула игрока от тайлов.Проблема может быть решена путем смещения персонажа от любых плиток перед применением силы на игрока, чтобы отодвинуть его от себя.

Это оказывается оченьсложная проблема, и она уже решена для вас.

Box 2D / Farseer Physics Engine :

Вы, наверное, слышали об этом раньшеи подумал: «О, я просто сверну свой, потому что это звучит супер весело!»И хотя программирование вашего собственного физического движка может быть очень увлекательным, оно также занимает очень много времени.Если вы хотите быстро запустить свою игру с физикой (даже если это простая физика, подобная Sonic), Эрин Катто заложил для вас все основы.:)

Проверьте это:

Box2D XNA: http://box2dxna.codeplex.com/

Физика Farseer: http://farseerphysics.codeplex.com/

...