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 |
|
| |
|