Проблема позиционирования CCSprite поверх других CCSprite, поскольку она оживляет экран?

В моем приложении есть персонаж, у которого есть ноги, и я хочу сделать так, чтобы в моем приложении он выглядел так, как будто он стоит поверх другого CCSprite, когда он перемещается вверх по экрану (анимация). Все работает отлично, КРОМЕ есть небольшая проблема позиционирования, которую я просто не могу понять! Позвольте мне объяснить проблему немного подробнее, когда персонаж находится на вершине CCSprite, кажется, что персонаж движется вверх /вниз примерно на 10 пунктов за очень короткие промежутки времени.

Кто-нибудь знает, почему это происходит?

Спасибо!

ЗАКЛЮЧИТЕЛЬНОЕ РЕДАКТИРОВАНИЕ . Еще раз хочу поблагодарить вас за помощь во всем этом. Во-первых, я удалил все остальные правки, поскольку сообщение становилось слишком длинным, и если вам по какой-либо причине нужно ссылаться на старые правки, просто просмотрите мою историю изменений!

Итак, примерно через час тестирования я сузил вопрос до одной проблемы, о которой вы упоминали ранее: операторы if, проверяющие, сталкиваются ли символ и элемент пола, НЕ вызывают каждый итерация в игровом цикле, когда они ДОЛЖНЫ быть (насколько они выглядят в пользовательском интерфейсе).

Мой журнал cocosGameLoop находится вне и до всего кода обнаружения столкновений, но все еще находится в игровом цикле.

Я также заметил шаблон в моих NSLogs, как вы можете видеть ниже:

2012-05-27 17:00:54.791 App[2769:707] cocosGameLoop
2012-05-27 17:00:54.811 App[2769:707] cocosGameLoop
2012-05-27 17:00:54.825 App[2769:707] cocosGameLoop
2012-05-27 17:00:54.841 App[2769:707] cocosGameLoop
2012-05-27 17:00:54.858 App[2769:707] cocosGameLoop
2012-05-27 17:00:54.874 App[2769:707] cocosGameLoop
2012-05-27 17:00:54.891 App[2769:707] cocosGameLoop
2012-05-27 17:00:54.908 App[2769:707] cocosGameLoop
2012-05-27 17:00:54.924 App[2769:707] cocosGameLoop
2012-05-27 17:00:54.928 App[2769:707] collisiontwo
2012-05-27 17:00:54.929 App[2769:707] two
2012-05-27 17:00:54.941 App[2769:707] cocosGameLoop
2012-05-27 17:00:54.944 App[2769:707] collisiontwo
2012-05-27 17:00:54.945 App[2769:707] two
2012-05-27 17:00:54.958 App[2769:707] cocosGameLoop
2012-05-27 17:00:54.974 App[2769:707] cocosGameLoop
2012-05-27 17:00:54.991 App[2769:707] cocosGameLoop
2012-05-27 17:00:55.008 App[2769:707] cocosGameLoop
2012-05-27 17:00:55.025 App[2769:707] cocosGameLoop
2012-05-27 17:00:55.043 App[2769:707] cocosGameLoop
2012-05-27 17:00:55.058 App[2769:707] cocosGameLoop
2012-05-27 17:00:55.076 App[2769:707] cocosGameLoop
2012-05-27 17:00:55.078 App[2769:707] collisiontwo
2012-05-27 17:00:55.078 App[2769:707] two
2012-05-27 17:00:55.091 App[2769:707] cocosGameLoop
2012-05-27 17:00:55.094 App[2769:707] collisiontwo

Что я также заметил, когда в NSLog координата Y символа была в том, что она остается в одной точке в течение нескольких взаимодействий (даже если она должна сталкиваться, чтобы она совпала с кучей вызовов cocosGameLoop в NSLog выше), затем, когда он действительно сталкивается (программно), он перемещается вверх примерно на 14 пунктов от координаты Y ранее. Таким образом, дрожание составляет около 14 пунктов вверх /вниз.

Итак, суть в том, как сделать так, чтобы код столкновения назывался КАЖДОЙ итерацией и не колебался около 14 точек? Я не хочу менять опорные точки, так как это повлияет на мое расположение анимации и так далее. Во всяком случае, что вы рекомендуете? Также имейте в виду, что я использую только Box2D для обнаружения столкновений, поэтому я должен хранить все в коде Cocos2D.

Наконец, я подумал, что в моем приложении были ошибки точки округления из-за силы тяжести, но даже когда я запутался со значениями, такими как изменение силы тяжести на целое, оно не устранило мерцание, поэтому проблема на 100% Я упоминал выше.

В любом случае, это суть проблемы, и я думаю, что вы можете увидеть то, чего я просто не могу! Дайте мне знать, что вы думаете:)

Большое спасибо!

5 голосов | спросил SimplyKiwi 13 Mayam12 2012, 11:18:12

1 ответ


0

Первое, что выглядит странно, - это проверка тегов сразу после комментария Some other tag collision checking before. Это будет иметь больше смысла:

else if ((spriteA.tag == 1 && spriteB.tag == 5) || (spriteB.tag == 1 && spriteA.tag == 5))
...
else if ((spriteA.tag == 6 && spriteB.tag == 1) || (spriteB.tag == 6 && spriteA.tag == 1))
...

то есть. это предполагает, что контакт столкновения, с которым вы проверяете, может дать вам два тела в любом порядке - например, для двух объектов, сталкивающихся, скажем, с характером и землей, слушатель контакта может дать землю как тело A и ноги как тело B, или ноги как тело A, так и землю как тело B. Приведенное выше утверждение гарантирует, что независимо от порядка вы выполняете одно и то же условный блок. Возможно ли, что ваш путь выполнения колеблется между двумя блоками else if и, следовательно, устанавливает неправильную позицию, когда он входит в неправильный блок?

Хорошо, если предположить, что все эти условные выражения верны (а я просто не вижу этого, поскольку я не знаю, на какие тела ссылаются теги, как настроен прослушиватель контактов и т. д.), тогда колебание должно быть вызвано физическим моделированием. Что происходит, когда вы устанавливаете положение CCSprite в Cocos2d с Box2D? Меняет ли установка положения спрайта также положение физического тела, или это два отдельных элемента (причем спрайт обычно отображается в местоположении физического тела)? Прошло много времени с тех пор, как я использовал Cocos2d, и он значительно изменился с первых дней, поэтому я не уверен в этом, не взломав последнюю версию и не посмотрев. Если изменение положения CCSprite также меняет положение физического тела, то это плохая вещь - все движения должны контролироваться физическим моделированием (поэтому, если вы хотите переместить физическое тело, вы должны приложение силы или импульса к ней, а не установка позиции напрямую). Изменение положения тела вне физики, вероятно, вызовет колебания или неправильные импульсы, приложенные к телу при выполнении следующего шага физического моделирования. Если вы хотите изменить положение спрайта без нарушения физического моделирования, рассмотрите возможность удаления физического тела, связанного с этим спрайтом, из физического моделирования на все время, когда вы хотите установить положение напрямую, а затем повторно добавьте его позже если вы хотите, чтобы это действовало в соответствии с физикой. Это может означать удаление тела физики и воссоздание его позже, если нет чистого способа добавить /удалить его из мира физики.

Другое решение - создать соединение между телами, которые вы хотите перемещать вместе. Дистанционное соединение или сварное соединение было бы наиболее подходящим. Это приведет к тому, что они будут соединены, поэтому, когда вы перемещаете одно, другое тоже перемещается, сохраняя одинаковое расстояние между двумя телами. В этом случае они оба будут действовать под физическим моделированием.

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

Если ваше изменение положения CCSprite на самом деле не меняет положение физического тела, и вы просто устанавливаете положение рендеринга игрока так, чтобы оно находилось в другом положении, чем физическое тело в мире. Затем вам нужно рассмотреть, что происходит с физическим телом. Он вращается, падает из мира, колеблется между какими-то другими объектами или чем-то еще? Мне трудно судить о том, что с этим может происходить, не зная больше о вашей игре. Но то, что происходит с ним, может повлиять на ваши расчеты позиции. Подумайте об удалении объекта физики из мира физики, если вы хотите передвигатьсяспрайты без них подлежат физическому моделированию. Наличие некоторого отладочного отрисовки неоценимо при работе с физическими телами, поэтому вы можете видеть точную форму и положение каждого тела и то, с чем оно взаимодействует, независимо от ваших собственных спрайтов или других художественных работ. Не уверен, что комбинированный Cocos2D /Box2D обеспечивает это из коробки, но если нет, то настоятельно рекомендуем реализовать его с простым способом включить /выключить его.

Еще одна вещь, которую следует учитывать, это два утверждения:

if (spriteA.position.x - spriteA.boundingBox.size.height*.5 <= spriteB.position.x + spriteB.boundingBox.size.height*.5)

и

if (spriteB.position.x - spriteB.boundingBox.size.height*.5 <= spriteA.position.x + spriteA.boundingBox.size.height*.5)

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

Надеюсь, что упомянутое выше решит вашу проблему или, по крайней мере, даст вам лучшее представление о том, с чего начать. Предоставление дополнительной информации в вашем вопросе - возможно, ответ на некоторые предположения /неизвестные, которые я упомянул - должно помочь нам разобраться в ваших проблемах:)

РЕДАКТИРОВАТЬ 1

Спасибо за то, что наполнили нас дополнительными подробностями - это проясняет ситуацию. То, что вы делаете, теперь имеет смысл, поскольку я знаю, что вы делаете обнаружение столкновений только с Box2D.

Я бы сказал, что для решения вашей проблемы, в вашем цикле for, где вы смотрите на контакты, где вы обнаруживаете, что контакт имеет сделано, вы должны просто установить флаг вместо изменения позиции персонажа в этой точке, например BOOL characterOnPlatform - установите для него значение YES при контакте обнаружен. За пределами этого цикла for (не обязательно в том же методе, хотя - он может быть где угодно, где вызывается каждый кадр, и где имеет смысл ) вы бы проверили этот флаг и, если characterOnPlatfom == YES, то установите положение символа в соответствии с вычислением положения, которое вы в данный момент выполняете в прослушивателе контактов. Цикл for. т.е. ничего не делать в слушателе контактов for цикл кроме изменить какое-либо состояние, на которое вы будете ссылаться в другом месте .

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

РЕДАКТИРОВАТЬ 2

На самом деле невозможно точно увидеть, что происходит с вашим новым кодом. Например, что происходит в вашем методе resetgravity? Как установить для hasCollided значение NO (т. Е. Как определить, что персонажа больше нет на платформе)? Ваш персонаж все еще дрожит в движении вверх или вниз, или мерцание, о котором вы упомянули, отличается от предыдущего?

Предполагая, что вы по-прежнему получаете движение вверх и вниз, я все равно ожидал бы, что это будет связано с тем, что опубликованный вами код не вызывается каждый кадр, или он борется с каким-то другим кодом позиционирования (например, куда бы вы ни перемещали персонажа в ответ на входные данные игрока, где вы применяете гравитацию и т. д.).

Убедитесь, что код, который удерживает персонажа на платформе, не устанавливает слишком высокое положение и не приводит к тому, что персонаж обнаруживается как не на платформе, так как тогда вы окажетесь в замкнутом круге:

  • персонаж сталкивается с платформой
  • позиция символа установлена ​​чуть вышеплатформа
  • Символ
  • больше не сталкивается с платформой, поэтому код позиционирования не выполняется, чтобы переместить его на платформу
  • персонаж падает вниз из-за гравитации (или как бы вы это ни симулировали)
  • персонаж сталкивается с платформой
  • ...

Если это так, то вам нужно улучшить обнаружение того, когда персонаж не сталкивается с платформой, или сместить ваш код позиционирования так, чтобы персонаж немного пересекался с платформой (если визуально это выглядит плохо может потребоваться немного сместить спрайт от формы Box2D, чтобы физическое тело слегка пересекалось с платформой, а ноги персонажа как будто точно на платформе.

РЕДАКТИРОВАТЬ 3

Похоже, вы исключили много вещей, которые могут вызывать дрожание! Я спросил другого разработчика игр, и он предположил, что ваша проблема может быть вызвана переходом из мирового пространства в экранное. Таким образом, вы можете попробовать зафиксировать мировую позицию вашего персонажа, а также позицию на экране, где он отображается (это может означать изменение кода в Cocos2D, где выполняется это преобразование). По крайней мере, просмотр вышедших значений может помочь сузить некоторые колебания /колебания. Вы также можете искать любые ошибки округления, которые вы можете вносить, например, усечение точности с плавающей точкой до целых чисел. Если ваше дрожание выглядит так, как будто оно находится только в области + или - 1 пикселя, то оно вполне может стоить взглянуть на мировую позицию в сравнении с положением экрана. Записать эти значения будет намного проще, чем останавливать отладчик каждый кадр.

ответил Rob B 20 Maypm12 2012, 17:33:24

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132