Лучший способ переместить прямоугольник в XNA / C # - PullRequest
0 голосов
/ 25 февраля 2012

Я новичок в XNA и пытаюсь сделать игру в понг.
Я смог сделать игру в понг, но весь код был в одном классе. Поэтому я хотел бы добавить немного ООП, и я сделал класс для мяча и один для пэда.

Мяч движется отлично, но я не могу заставить мяч отскочить от подушек.

Вот коды, которые я использую:
Для перемещения колодок
Game1.cs

#region left
    if (_KBS.IsKeyDown(Keys.W) || _KBS.IsKeyDown(Keys.Z))
        Left.MoveUp();
    else if (_KBS.IsKeyDown(Keys.S))
        Left.MoveDown();
#endregion

#region right
    if (_KBS.IsKeyDown(Keys.Up))
        Right.MoveUp();
    else if (_KBS.IsKeyDown(Keys.Down))
        Right.MoveDown();
#endregion

pad.cs

public void MoveUp() {
    if (!paused)
        RecPad.Offset(0, -speed);

    CheckBorders();
}

public void MoveDown() {
    if (!paused)
        RecPad.Offset(0, speed);

    CheckBorders();
}

private void CheckBorders() {
    MathHelper.Clamp(recPad.Y, borders.Top, borders.Bottom - recPad.Height);
}

Чтобы проверить, отскочил ли мяч
ball.cs

public void CheckBounce() {
    if ((myBounds.Intersects(left) && movement.X < 0) || (myBounds.Intersects(right) && movement.X > 0))
            movement.X *= -1;
}

public void Draw(SpriteBatch sBatch, Texture2D texture, Color color, Rectangle left, Rectangle right) {
    this.left = left;
    this.right = right;

    Move();

    sBatch.Begin();
    sBatch.Draw(texture, myBounds, color);
    sBatch.End();
}

pad.cs

public Rectangle RecPad {
    get { return recPad; }
    private set { recPad = value; }
}

Game1.cs

Ball.Draw(spriteBatch, ball, Color.White, Left.RecPad, Right.RecPad);

Я, кажется, вернул прокладки к работе
Похоже, что проблема решена с помощью оригинального recPad вместо конструктора RecPad
Теперь мне нужно только заставить мои границы работать, потому что MathHelper.Clamp, похоже, не работает
См. мой код для получения дополнительной информации

Этот код теперь исправил мою проблему с границей

private void CheckBorders() {
        if (recPad.Top < borders.Top)
            recPad.Location = new Point(recPad.X, borders.Top);
        if (recPad.Bottom > borders.Bottom)
            recPad.Location = new Point(recPad.X, borders.Bottom - recPad.Height);
    }

1 Ответ

2 голосов
/ 25 февраля 2012

Это сразу бросается в глаза (из CheckBounce):

    movement.X *= 1;

Возможно, произошла ошибка копирования, или вы забыли поставить '-'.

Также рассмотрите возможность использованияRectangle.Contains / Intersects метод (ы), чтобы упростить некоторый код столкновения, и MathHelper.Clamp, чтобы держать ваши весла в пределах.Это больше для справки в будущем, поскольку ваши методы работают, но приятно воспользоваться преимуществами полезных инструментов в XNA.

Редактировать: Об этих «полезных инструментах»:

Класс Rectangleимеет методы Intersect и Contains, которые могут сообщить вам, пересекает ли этот прямоугольник другой прямоугольник или содержит определенную точку соответственно.Вы говорите, что ваш шар - это просто верхняя левая позиция и текстура, но я вижу, что при вашем столкновении вы проверяете радиус шара.Я думаю, вам будет проще определить прямоугольник, ограничивающий область для вашего мяча, и использовать метод Intersects для проверки на столкновение.Это упрощает ваш код столкновения до:

public void CheckBounce()
{
    if (myBounds.Intersects(LeftPaddle.Bounds) || myBounds.Intersects(RightPaddle.Bounds))
        movement.X *= -1;
}

Довольно просто, но не совсем безопасно - если мячу удается продвинуться достаточно далеко в весло, то один кадр движения не освободит его от границ этого веслаВы бы застряли, постоянно инвертируя скорость X, производя эффект «застрявшего шара».Таким образом, мы можем добавить немного больше проверочного кода, чтобы избежать этого:

public void CheckBounce()
{
    if ((myBounds.Intersects(LeftPaddle.Bounds) && movement.X < 0) ||
     (myBounds.Intersects(RightPaddle.Bounds) && movement.X > 0))
        movement.X *= -1;
}

Я прошу прощения, если встроенные условия являются слишком плотными.Это означает, что если мяч движется влево и ударяется о правое весло, инвертирует X. Аналогично, если он движется вправо и ударяется о левое весло, инвертирует X. Это устраняет «залипание».

Теперь, что касается MathHelper.Clamp, в вашей ситуации я бы использовал его для ограничения движения весла.MathHelper.Clamp просто ограничивает значение между верхней и нижней границами.Это эквивалентно использованию Math.Min, а затем Math.Max.

private void CheckBorders()
{
    //clamps a       value  to a   min  and a           max
    MathHelper.Clamp(recPad.Y, borders.Top, borders.Bottom - recPad.Height);
}

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

...