Почему столкновение платформеров прекрасно работает на одной платформе, но едва работает с массивом платформ? - PullRequest
0 голосов
/ 20 апреля 2019

Я прочитал все предложенные темы.Я хочу создать коллизии для платформерной игры с C #, .NET Gatgeteer, .NETMF 4.3 на VS 2013. Я начал с одной платформы, и через некоторое время коллизии на ней работали хорошо.Я думал, что для коллизий со многими платформами мне просто нужно было поставить массив платформ через проверку коллизий вместо одной платформы, но я ошибся.Я получаю массив моей платформы из карты уровней, которая является строковым массивом.До сих пор я сталкивался с этими проблемами:

1) Если ширина или высота платформы изменяется, это также меняет положение платформы, и, как бы я ни старался, я не мог найти причину.

2) Если я добавлю только одну платформу на карту (если в массиве только одна платформа), игрок падает через платформу и даже сквозь землю.

3) Если существует более одной платформы, столкновениелучше всего работает с последними созданными:

* Верхнее столкновение работает только в том случае, если в начале уровня, когда игрок падает, он падает только на платформе, созданной последней, и работает отлично.Вы можете прыгать столько раз, сколько захотите, пока не приземлитесь на землю.После этого верхнее столкновение исчезает.

* Столкновение сторон работает все время.Платформа, созданная последней, работает отлично.Пока игрок немного перемещается по другим платформам, пока я держу джойстик, сразу после того, как я выпустил джойстик, он возвращается к тому месту, где он должен находиться при столкновении.

Я читал в статье Stackoverflow "Столкновения платформы C #, не работающие с несколькими платформами », что в случае обнаружения конфликта цикл должен быть разорван.Я попробовал несколько его вариантов: for, foreach, хотя и с bool, но все они сильно отставали от игры (foreach зависает даже без перерыва).Использование тормоза должно привести к полной противоположности замедлению игры.

4) Столкновения работают только на уровне карты groud (карта [11]).

Спасибо, четыре раза, я хотел бывысоко ценю ответ на любой из моих вопросов.

------------------------------------------------------------КОД------------------------------------------------------------- Эта часть отвечает за карту и массив платформ.Столкновения работают только на уровне земли (карта [11]).

     //Map generation
     // -88 this offset makes the platform align with botom of the screen
     int basePositionTop = -88;
     int basePositionLeft = 0;
     int platformId = 0;
     int playerHeight = 30;
     int playerWidth = 30;
     Platform[] platformMap = new Platform[200];   

            void SetupUI()
            {
                // initialize window
                mainWindow = displayT43.WPFWindow; 

                // setup the layout
                layout = new Canvas();
                Border background = new Border();
                background.Background = new SolidColorBrush(Colors.Black);
                background.Height = 272;
                background.Width = 480;

                layout.Children.Add(background);
                Canvas.SetLeft(background, 0);
                Canvas.SetTop(background, 0);

                //add the player
                player = new Rectangle(playerWidth, playerHeight);
                player.Fill = new SolidColorBrush(Colors.Red);
                layout.Children.Add(player);

                // Platformer map
                string[] map = new string[12];
                map[0] =  ".....................................";
                map[1] =  ".....................................";
                map[2] =  ".....................................";
                map[3] =  ".....................................";
                map[4] =  ".....................................";
                map[5] =  ".....................................";
                map[6] =  ".....................................";
                map[7] =  ".....................................";
                map[8] =  ".....................................";
                map[9] =  ".....................................";
                map[10] = ".....................................";
                map[11] = ".....#..#............................";


                for (int i = 0; i < map.Length; i++)
                {
                    for (int j = 0; j < map[i].Length; j++)
                    {
                        if (map[i][j] == '#')
                        {
                            platformMap[platformId] = new Platform(platWidth, platHeight);
                            platformMap[platformId].set(basePositionLeft + j * platWidth , basePositionTop + i * platHeight);
                            platformId++;
                        }
                    }
                }

                // Adding platforms to screen
                for (int i = 0; i < platformId; i++)
                {               
                    layout.Children.Add(platformMap[i].get());
                }

                mainWindow.Child = layout;
            }

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

    int power; 
    int jumpPower = 36;
    bool jumped = true;
    int playerTopPosition; 
    int playerLeftPosition = 250;                       

 void jumpTimer_Tick(GT.Timer timer)
 {
    double y = joystick.GetPosition().Y;

     //Jump part
     if (!jumped) // if didn't jump
     {
       if (y >= 0.7) // and jumps
       {
          jumped = true;
          power = jumpPower;
       }
     }

     //Jump
     if (jumped)
     {
         playerTopPosition -= power;
         power -= 8;
     }

     // update player top position
     Canvas.SetTop(player, playerTopPosition);

  // Platform check loop                            
  for (int i = 0; i < platformId; i++)
  {

   //TOP AND BOTTOM COLLISION
   //Check if player is in platform bounds x axis
   if ((playerLeftPosition + playerWidth) >= platformMap[i].posLeft() 
                    && playerLeftPosition <= platformMap[i].posLeft() + platWidth) 
   {
    //TOP collision. (platHeight/2 -1) - even if player is in platform 
    // (from top) and doesn't touch the middle he is set on top 
    if (playerTopPosition + playerHeight >= platformMap[i].posTop() 
    && playerTopPosition + playerHeight <= platformMap[i].posTop() + (platHeight / 2 - 1))

    {
       playerTopPosition = platformMap[i].posTop() - playerHeight;
       jumped = false;                                        
    }

    //BOTTOM collision. (platHeight/2 + 1) - even if player is in platform 
    //(from bottom) and don't touch the middle he collides with bottom 
    if (playerTopPosition <= platformMap[i].posTop() + platHeight 
     && playerTopPosition >= platformMap[i].posTop() + (platHeight / 2 + 1))
    {
           playerTopPosition = platformMap[i].posTop() + platHeight;
           power = -1;// without this player gets stuck on platform bottom
    }
   }      
     else jumped = true; // if player steps off platform - he falls


    // the very bottom collision
    if (playerTopPosition + playerHeight >= displayT43.Height) 
    {
       playerTopPosition = displayT43.Height - playerHeight;
       jumped = false;
    }

    //SIDES COLLISION
    //Check if player is in platform bounds y axis
    if (playerTopPosition + playerHeight <= platformMap[i].posTop() + platHeight 
     && playerTopPosition >= platformMap[i].posTop())
    {
     //RIGHT collision. (platWidth / 2 - 1) - even if player is in platform 
     // (from left) and don't touch the middle he collides with left
     if ((playerLeftPosition + playerWidth) + 1 >= platformMap[i].posLeft() 
      && (playerLeftPosition + playerWidth) <= platformMap[i].posLeft() + (platWidth/2-1))
     {
        playerLeftPosition = platformMap[i].posLeft() - playerWidth;
        stopRight = true;// stops moving right
     }
       else stopRight = false;

     //LEFT collision. (platWidth / 2 - 1) - even if player is in platform 
     // (from right) and don't touch the middle he collides with right
     if (playerLeftPosition - 1 <= platformMap[i].posLeft() + platWidth 
          && playerLeftPosition >= platformMap[i].posLeft() + (platWidth / 2 + 1))
     {
        playerLeftPosition = platformMap[i].posLeft() + platWidth;
        stopLeft = true;// stops moving left
     }
       else stopLeft = false;

    }
      else
      {
         stopRight = false;
         stopLeft = false;               
      }

     // update player top position                          
     Canvas.SetTop(player, playerTopPosition); 
  }

 }

Это ответственно за левое / правое движение и действия при обнаружении левого или правого столкновения.

     bool stopLeft = false;// makes stop move left
     bool stopRight = false;// makes stop move right


     void JoystickTimer_Tick(GT.Timer timer)
     {
                double x = joystick.GetPosition().X; // joystic x scale [-1;1]
                // move left
                if (x < -0.3 && playerLeftPosition > 0 && !stopLeft)
                {
                    playerLeftPosition -= 5;
                }
                // move right
                else if (x > 0.7 && playerLeftPosition < displayT43.Width - playerWidth 
                                                                         && !stopRight)
                {
                    playerLeftPosition += 5;
                }

                Canvas.SetLeft(player, playerLeftPosition);// update player left postion
    }

Класс Platform.cs

    class Platform
    {
           private Rectangle platformRectangle { get; set; }

            int left = 0;
            int top = 0;

           public Platform()
           { 
           }

           public Platform(int Width, int Height)
           {
               this.platformRectangle = new Rectangle();
               this.platformRectangle.Height = Height;
               this.platformRectangle.Width = Width;

               platformRectangle.Fill = new SolidColorBrush(Colors.Orange);
           }
           public void set(int leftPosition, int topPosition)
           {
               Canvas.SetLeft(platformRectangle, leftPosition);
               Canvas.SetTop(platformRectangle, topPosition);
               this.left = leftPosition;
               this.top = topPosition;
           }

           public Rectangle get()
           {
               return platformRectangle;
           }
           public int posLeft()
           {
               return left;
           }
           public int posTop()
           {
               return top;
           }
   }
...