Воскресенье, 22 Декабря 2024, 06:49

Приветствую Вас Гость

[ Новые сообщения · Игроделы · Правила · Поиск ]
  • Страница 1 из 1
  • 1
2д столкновения
wcptДата: Суббота, 20 Октября 2012, 12:40 | Сообщение # 1
постоянный участник
Сейчас нет на сайте
Подскажите, как построить внятный и точный алгоритм обработки столкновений? Можно например так сделать - в LOAD занести массив цветов текстуры, сделать прямоугольник изображения, затем цикл - если цвет не равен нулю(т.е. если прозрачность не 100%) то в массив векторов2 занести точку изображения. И затем, если позиция объекта(вектор2) в следующем шаге не содержится в массиве, то для конкретных прямоугольников столкновения нет, если же содержится, то... и так далее
Позицию в сл. шаге я так измерил:

Hero.NextPos = Hero.SPD * gameTime.ElapsedGameTime.Milliseconds + Hero.POS;

Теперь главные вопросы - как же все-таки реализовать это? У меня есть код попиксельного столкновения, но самая загвоздка в том, что он не позволяет остановить объект ДО столкновения, и работает только во время перекрытия, т.е. приходится после столкновения изменять координату. А лучше было бы так - если в следующей позиции столкновение - координаты не изменять.
- что же делать после обнаружения столкновения? Если просто обнулять скорость - не получится хождения по кривой
- а что делать, если скорость одного объекта высока по сравнению с размерами другого и он может просто оставить позади себя в сл. шаге все координаты этого другого объекта?
arthurfokДата: Суббота, 20 Октября 2012, 22:52 | Сообщение # 2
частый гость
Сейчас нет на сайте
допустим , функция проверяющая столкновения:bool Intersects(Rectangle rect1, Color[] data1, Rectangle rect2, Color[] data2).
Где rect1 и data1 - это прямоугольник и массив цветов первого обьекта с позицией NextPos,, а rect2 и data2 - второго.
Тогда..

Code

if(!Intersects(Hero.rect,Hero.Data,Pulya.rect,Pulya.Data))  //То есть, если столкновении нет, то:
{
       Hero.POS=Hero.NextPos;
       // Pulya.POS=Pulya.NextPos;
       //...
       //...
}


Что то в этом роде.

Добавлено (20.10.2012, 22:52)
---------------------------------------------
Вот сама функция:

Code

bool Intersects(Rectangle rect1, Color[] data1, Rectangle rect2, Color[] data2)
         {
             int top = Math.Max(rect1.Top,rect2.Top);
             int bottom = Math.Min(rect1.Bottom, rect2.Bottom);
             int left = Math.Max(rect1.Left, rect2.Left);
             int right = Math.Min(rect1.Right, rect2.Right);

             for (int y = top; y < bottom; y++)
             {
                 for (int x = left; x < right; x++)
                 { http://gcup.ru/forum/66-27176-1#top
                     Color color1=data1[(x-rect1.Left)+(y-rect1.Top)*rect1.Width];
                     Color color2 = data2[(x - rect2.Left) + (y - rect2.Top) * rect2.Width];
                     if (color1.A != 0 && color2.A != 0)
                         return true;
                 }
             }
             return false;           
         }


Получение массива цветов:
Code

             Hero.Data = new Color[sprite.Width * sprite.Height];
             Hero.Sprite.GetData(Hero.Data);
wcptДата: Воскресенье, 21 Октября 2012, 12:03 | Сообщение # 3
постоянный участник
Сейчас нет на сайте
Да у меня все почти то же самое, проблема в том, что это не работает. Нет, сама проверка работает отлично, но что делать при столкновении? Необходимо изменить координату, чтобы перекрытие прекратилось. Мне же нужно сделать так, чтоб если в позиции, в которой будет объект в сл. шаге происходит перекрытие, то позицию не приращать.
Вот как ты у себя реализовал? Вот, например, мой код:

Code

      Hero.NextPos = Hero.SPD * gameTime.ElapsedGameTime.Milliseconds + Hero.POS;
                
          if (IntersectPixels(HeroRect, Hero_TextData, RockRect, Rock_TextData))
          {
              Hero.POS -= Hero.SPD;
              Hero.SPD = new Vector2(0, 0);
              Hero.Down = false;
          }
          else {
              Hero.POS=Hero.NextPos;
              Hero.POS += Hero.SPD;
              Hero.SPD.X -= Obj_Hero.frict * Hero.SPD.X;
              Hero.SPD.Y -= Obj_Hero.frict * Hero.SPD.Y;
          }

          if (Math.Abs(Hero.SPD.X)<2e-2)
              Hero.SPD.X = 0;

          if (myKeyboardState.IsKeyDown(Keys.Left) || myKeyboardState.IsKeyDown(Keys.Right))
          {
              if (myKeyboardState.IsKeyDown(Keys.Left))
                  Hero.SPD.X -= 2e-1f;

              if (myKeyboardState.IsKeyDown(Keys.Right))
                  Hero.SPD.X += 2e-1f;
          }
          else {
              if (myKeyboardState.IsKeyDown(Keys.Down))
                  if (!IntersectPixels(HeroRect, Hero_TextData, RockRect, Rock_TextData))
                      Hero.SPD.Y += 2e-1f;
              }

          if (myKeyboardState.IsKeyDown(Keys.Up))
              if (Hero.tt==0)
              {
                  Hero.Down = true;
                  if (Hero.Up == false && Hero.SPD.Y==0)
                  {
                      Hero.SPD.Y -= 7;
                      Hero.Up = true;
                  }
              }

          if (Hero.Down)
          {
              Hero.tt += 1e-1f;
              Hero.SPD.Y += 8e-2f * Hero.tt * Hero.tt;
          }
          else Hero.tt = 0;

          if (Hero.Up) {
              Hero.t += 0.1f;
              if (Hero.t > 1)
              {
                  Hero.Down = true;
                  Hero.Up = false;
                  Hero.t = 0;
              }
          }

          if (Hero.SPD.X > 9)
              Hero.SPD.X = 9;
          if (Hero.SPD.Y > 30)
              Hero.SPD.Y = 30;
          if (Hero.SPD.X < -9)
              Hero.SPD.X = -9;
          if (Hero.SPD.Y < -3)
              Hero.SPD.Y = -3;
                   


Сообщение отредактировал wcpt - Воскресенье, 21 Октября 2012, 12:04
arthurfokДата: Воскресенье, 21 Октября 2012, 15:57 | Сообщение # 4
частый гость
Сейчас нет на сайте
то есть, если в следующем шаге будет столкновение (например при нажатии Up) , то не пускать чтоб он пошел на верх, а только в другие направления??
Я правильно понял?
wcptДата: Воскресенье, 21 Октября 2012, 23:50 | Сообщение # 5
постоянный участник
Сейчас нет на сайте
Что-то не понял тебя. Up и Down просто boolean переменные. Если хочешь, могу пример выложить, посмотришь что да как.
arthurfokДата: Понедельник, 22 Октября 2012, 15:39 | Сообщение # 6
частый гость
Сейчас нет на сайте
)))
имел в виду кнопки на клаве : Keys.Up и Keys.Down ))
wcptДата: Понедельник, 22 Октября 2012, 16:18 | Сообщение # 7
постоянный участник
Сейчас нет на сайте
Тогда да, ты меня правильно понял

Добавлено (22.10.2012, 16:13)
---------------------------------------------
Короче нашел я вот такой код
Code

if Hero.spd!=0
{
         for(int i=0; i<Hero.dist; i++)
             if PlaceFree(Hero.POS.X+Hero.spd,Hero.POS.Y - i)
             {
                 Hero.POS.X+=Hero.spd;
                 Hero.POS.Y-=i;
                 if PlaceFree(Hero.POS.X,Hero.POS.Y+1)
                     if !PlaceFree(Hero.POS.X,Hero.POS.Y+Hero.dist+1)
                         for(int i=0 ;i<Hero.dist+1;i++)
                         {
                    if !PlaceFree(Hero.POS.X,Hero.POS.Y+i)
                    {
                    Hero.POS.Y+=i-1;
                    break;
                    }
                         }
                 break;
             }
             Hero.spd=Math.Sign(Hero.spd)*Math.Max(0,Math.Abs(Hero.spd)-Hero.frict)
}


Добавлено (22.10.2012, 16:18)
---------------------------------------------
spd - float переменная, значение которой изменяется при нажатии vk_left / vk_right
frict - некоторый коэфф. трения
dist - произвольная int переменная, указывающая, на сколько пикселей можно подняться
PlaceFree - метод, возвращающий true, если столкновение в позиции (x,y) есть. Кода самого метода нет. Прошу помочь с его написанием, и разъяснением кода, указанного выше(код не мой!).


Сообщение отредактировал wcpt - Понедельник, 22 Октября 2012, 19:50
  • Страница 1 из 1
  • 1
Поиск:

Все права сохранены. GcUp.ru © 2008-2024 Рейтинг