Skip to content

Refactor stepping & units; add polygon utilities (v2.0.0)#2

Merged
GoetzDeBouville merged 7 commits intomainfrom
dev
Mar 2, 2026
Merged

Refactor stepping & units; add polygon utilities (v2.0.0)#2
GoetzDeBouville merged 7 commits intomainfrom
dev

Conversation

@GoetzDeBouville
Copy link
Copy Markdown
Owner

@GoetzDeBouville GoetzDeBouville commented Mar 2, 2026

Description:

  • Move fixed-timestep/accumulator logic into the simulation loop and simplify engine stepping.
  • Make command units explicit (impulse in Px, velocity in Px/s), rename related fields, and clarify sleep/collision semantics.
  • Add polygon utilities + docs updates; bump version to 2.0.0 and refresh dependencies.

Breaking changes:

  • Named-argument calls may need updates due to renamed impulse/velocity fields.

Summary by CodeRabbit

Примечания к выпуску

  • Новые функции

    • Добавлены утилиты для работы с многоугольниками в физическом движке
  • Документация

    • Расширена документация с описанием новых инструментов для полигонов и примерами их использования
  • Улучшения

    • Оптимизирован физический движок с переходом на однопроходный алгоритм расчёта
    • Улучшена синхронизация гравитации между сценами
    • Обновлены зависимости библиотек (Compose Multiplatform, Activity Compose)
    • Удалена неиспользуемая библиотека логирования

Версия: 1.0.4

…mand units explicit

- move fixed-timestep ownership (accumulator/maxSubSteps/fixed dt) to PhysicsSimulationLoop
- change internal PhysicsWorldEngine.step signature to accept deltaSeconds + StepConfig + SolverIterations
- make JVM PhysicsWorldEngine.step execute exactly one world.step(...) per call (or 0 when paused)
- remove engine-side accumulator/clamp/substep loop and related state
- rename command fields:
  - EnqueueImpulse: impulseX/impulseY -> impulseXPx/impulseYPx
  - EnqueueVelocity: velocityX/velocityY -> velocityXPxPerSec/velocityYPxPerSec
- update all command call sites and engine conversions to the new field names
- update KDoc in PhysicsCommand and PhysicsBoxState to explicitly state Px and Px/s units
- clarify sleep callback semantics: parameter is isSleeping (true means sleeping)
make worldManifold as property
remove NoOpEventSink
update docs
update version
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 2, 2026

Общее описание

Обновление включает переименование параметров физических команд (impulseX/Y → impulseXPx/impulseYPx), изменение сигнатуры метода PhysicsWorldEngine.step(), добавление новых утилит для полигональных форм, обновление версий зависимостей и рефакторинг системы событий физического движка.

Изменения

Когорта / Файл(ы) Резюме
Документация и утилиты полигонов
docs/shapes.md, physicsbox/src/commonMain/kotlin/dev/zinchenko/physicsbox/utils/PolygonShapeUtils.kt
Добавлена документация для новых функций regularPolygonNormalized и polygonComposeShape для создания и рендеринга правильных полигонов. Реализованы утилиты для преобразования полигонов между физическим и Compose пространствами.
Конфигурация и зависимости
gradle/libs.versions.toml, sharedUI/build.gradle.kts
Обновлены версии: packageVersion 1.0.3→1.0.4, compose-multiplatform 1.10.0→1.10.1, androidx-activityCompose 1.12.3→1.12.4. Удалена зависимость Kermit logging.
Переименование параметров физических команд
physicsbox/src/commonMain/kotlin/dev/zinchenko/physicsbox/PhysicsBoxState.kt, physicsbox/src/commonMain/kotlin/dev/zinchenko/physicsbox/PhysicsCommand.kt
Переименованы параметры в публичных API: impulseX/Y → impulseXPx/impulseYPx, velocityX/Y → velocityXPxPerSec/velocityYPxPerSec для явного указания единиц измерения в пиксельных координатах контейнера.
Архитектура физического движка
physicsbox/src/commonMain/kotlin/dev/zinchenko/physicsbox/engine/PhysicsWorldEngine.kt, physicsbox/src/commonMain/kotlin/dev/zinchenko/physicsbox/layout/PhysicsSimulationLoop.kt, physicsbox/src/jvmMain/kotlin/dev/zinchenko/physicsbox/engine/PhysicsWorldEngine.kt
Обновлена сигнатура метода step() с добавлением параметров stepConfig и solverIterations. Удалена логика многошагового подсчёта, упрощён цикл выполнения движка.
Синхронизация состояния движка
physicsbox/src/commonMain/kotlin/dev/zinchenko/physicsbox/layout/PhysicsBox.kt
Добавлен EngineSyncState для отслеживания экземпляра движка и синхронизации гравитации один раз за экземпляр. Движок теперь ключируется по границам вместо полной конфигурации.
Система событий
physicsbox/src/commonMain/kotlin/dev/zinchenko/physicsbox/engine/PhysicsEventSink.kt, physicsbox/src/commonMain/kotlin/dev/zinchenko/physicsbox/events/CollisionEvent.kt, physicsbox/src/jvmMain/kotlin/dev/zinchenko/physicsbox/engine/PhysicsContactListener.kt
Удалена реализация NoOpEventSink. Обновлена документация CollisionEvent для уточнения масштабирования импульса. Оптимизирована PhysicsContactListener с переиспользованием экземпляра WorldManifold.
Документация обратных вызовов
physicsbox/src/commonMain/kotlin/dev/zinchenko/physicsbox/physicsbody/PhysicsBody.kt, physicsbox/src/commonMain/kotlin/dev/zinchenko/physicsbox/physicsbody/PhysicsBodyCallbacks.kt
Уточнена документация параметра onSleepChanged. Удалена пустая строка в PhysicsBodyCallbacks.
Обновления демонстрационных экранов
sharedUI/src/commonMain/kotlin/com/zinchenkodev/app/demos/BasicStackingDemoScreen.kt, sharedUI/src/commonMain/kotlin/com/zinchenkodev/app/demos/BoundariesConfigDemoScreen.kt, sharedUI/src/commonMain/kotlin/com/zinchenkodev/app/demos/PhysicsBoxStateDemoScreen.kt
Удалены локальные реализации polygonComposeShape и regularPolygonNormalized, теперь используются внешние утилиты. Обновлены вызовы enqueueImpulse с новыми именами параметров. Добавлен параметр gravityScale в PhysicsBodyConfig.

Оценка сложности рецензирования

🎯 3 (Moderate) | ⏱️ ~25 minutes

Стихотворение

🐰 Версии танцуют в версиях строк,
Параметры хорошо переименованы,
Полигоны правильные рождены,
Движок поёт, системы слиты,
И гравитация синхронизирована с любовью,
Коробка физики блестит в обновлении!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.34% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main changes: refactoring stepping and units logic, adding polygon utilities, and bumping to version 2.0.0.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch dev

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (3)
physicsbox/src/commonMain/kotlin/dev/zinchenko/physicsbox/events/CollisionEvent.kt (1)

14-16: Уберите дублирующую формулировку про px-scale.

На Line 14-16 повторяется одна и та же мысль, из‑за чего KDoc читается тяжелее. Лучше оставить одну формулировку.

Предлагаемая правка
- * - Treat this as a px-scaled magnitude suitable for UX effects (sound/haptics/FX thresholds),
- * not as raw physics units.
- * - Treat as px-scaled magnitude (UI scale), not N·s and not m·kg/s.
+ * - Treat this as a px-scaled magnitude suitable for UX effects (sound/haptics/FX thresholds),
+ *   not as raw physics units (i.e., not N·s / kg·m/s).
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@physicsbox/src/commonMain/kotlin/dev/zinchenko/physicsbox/events/CollisionEvent.kt`
around lines 14 - 16, In the KDoc for the CollisionEvent (the commented bullet
lines describing px-scaling), remove the duplicated sentence and keep a single
clear phrasing; e.g. retain one bullet such as "Treat as a px-scaled magnitude
suitable for UX effects (sound/haptics/FX thresholds), not as raw physics
units." Ensure you edit the KDoc block above the CollisionEvent declaration so
only one px-scale bullet remains and formatting remains consistent.
physicsbox/src/commonMain/kotlin/dev/zinchenko/physicsbox/PhysicsBoxState.kt (1)

209-215: Рекомендую унифицировать имена параметров enqueueVelocity с явными единицами.

Сейчас KDoc уже говорит про Px/s, но сигнатура всё ещё velocityX/velocityY. Для консистентности публичного API лучше перейти на velocityXPxPerSec/velocityYPxPerSec.

Предложенный diff
-    fun enqueueVelocity(
-        key: Any,
-        velocityX: Float,
-        velocityY: Float,
-    ) {
+    fun enqueueVelocity(
+        key: Any,
+        velocityXPxPerSec: Float,
+        velocityYPxPerSec: Float,
+    ) {
         enqueueCommand(
             PhysicsCommand.EnqueueVelocity(
                 key = key,
-                velocityXPxPerSec = velocityX,
-                velocityYPxPerSec = velocityY,
+                velocityXPxPerSec = velocityXPxPerSec,
+                velocityYPxPerSec = velocityYPxPerSec,
             ),
         )
     }

Also applies to: 220-221

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@physicsbox/src/commonMain/kotlin/dev/zinchenko/physicsbox/PhysicsBoxState.kt`
around lines 209 - 215, Rename the parameters in the public function
enqueueVelocity from velocityX/velocityY to velocityXPxPerSec/velocityYPxPerSec
to match the KDoc units; update the function signature in
PhysicsBoxState.enqueueVelocity, all internal references inside that method, any
overloaded variants or duplicate signatures (the other enqueueVelocity
occurrences), and all call sites/tests to use the new names, and adjust the KDoc
param tags if needed so the API and docs are consistent.
physicsbox/src/commonMain/kotlin/dev/zinchenko/physicsbox/layout/PhysicsBox.kt (1)

112-114: Уберите дублирование сборки runtime-конфига для engine.

На Line 133 повторно вычисляется config.copy(step = state.stepConfig), хотя уже есть runtimeConfig. Лучше использовать один источник, чтобы избежать будущих расхождений.

Предлагаемое упрощение
-            config = config.copy(step = state.stepConfig),
+            config = runtimeConfig,

Also applies to: 133-133

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@physicsbox/src/commonMain/kotlin/dev/zinchenko/physicsbox/layout/PhysicsBox.kt`
around lines 112 - 114, Уберите дублирование: вместо повторного вызова
config.copy(step = state.stepConfig) в участке кода, где инициализируется engine
(используя тот же выражение на Line 133), передавайте уже вычисленный
runtimeConfig (значение, созданное через remember) — то есть замените повторное
копирование на использование runtimeConfig при инициализации engine/вызове,
чтобы runtimeConfig, config и state.stepConfig оставались единым источником
правды.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@gradle/libs.versions.toml`:
- Line 7: The packageVersion field currently set as packageVersion = "1.0.4"
must be bumped to the breaking-change release version from the PR: update
packageVersion to "2.0.0" (i.e., change the value of the packageVersion key) to
reflect the major semver bump and ensure any release metadata (changelog/release
tag) aligns with this version.
- Around line 10-13: В файле libs.versions.toml замените значение переменной
material3, потому что текущая "1.10.0-alpha05" отсутствует в Google Maven;
откройте запись material3 и установите корректную доступную версию (например
"1.5.0-alpha15" или ближайшую стабильную "1.4.0"), затем пересоберите, чтобы
убедиться, что зависимость разрешается корректно.

In
`@physicsbox/src/jvmMain/kotlin/dev/zinchenko/physicsbox/engine/PhysicsContactListener.kt`:
- Around line 20-22: PhysicsContactListener currently ignores sensor contacts
because beginContact/endContact are no-ops and postSolve only fires for impulse
contacts; implement sensor handling in beginContact(contact: Contact) and
endContact(contact: Contact) to detect contact.isSensor or
Contact.fixtureA/fixtureB.isSensor, build and dispatch the existing event
payload (same shape as postSolve collision events) for sensors, or alternatively
add explicit documentation to docs/events.md and the public API docs in
PhysicsContactListener noting that only impulse collisions from postSolve are
emitted and sensor contacts are excluded; update the code paths that rely on
sensor events (postSolve handlers) to use the new beginContact/endContact sensor
events if you choose implementation.

---

Nitpick comments:
In
`@physicsbox/src/commonMain/kotlin/dev/zinchenko/physicsbox/events/CollisionEvent.kt`:
- Around line 14-16: In the KDoc for the CollisionEvent (the commented bullet
lines describing px-scaling), remove the duplicated sentence and keep a single
clear phrasing; e.g. retain one bullet such as "Treat as a px-scaled magnitude
suitable for UX effects (sound/haptics/FX thresholds), not as raw physics
units." Ensure you edit the KDoc block above the CollisionEvent declaration so
only one px-scale bullet remains and formatting remains consistent.

In
`@physicsbox/src/commonMain/kotlin/dev/zinchenko/physicsbox/layout/PhysicsBox.kt`:
- Around line 112-114: Уберите дублирование: вместо повторного вызова
config.copy(step = state.stepConfig) в участке кода, где инициализируется engine
(используя тот же выражение на Line 133), передавайте уже вычисленный
runtimeConfig (значение, созданное через remember) — то есть замените повторное
копирование на использование runtimeConfig при инициализации engine/вызове,
чтобы runtimeConfig, config и state.stepConfig оставались единым источником
правды.

In
`@physicsbox/src/commonMain/kotlin/dev/zinchenko/physicsbox/PhysicsBoxState.kt`:
- Around line 209-215: Rename the parameters in the public function
enqueueVelocity from velocityX/velocityY to velocityXPxPerSec/velocityYPxPerSec
to match the KDoc units; update the function signature in
PhysicsBoxState.enqueueVelocity, all internal references inside that method, any
overloaded variants or duplicate signatures (the other enqueueVelocity
occurrences), and all call sites/tests to use the new names, and adjust the KDoc
param tags if needed so the API and docs are consistent.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1bce6af and cf33fd0.

📒 Files selected for processing (18)
  • docs/shapes.md
  • gradle/libs.versions.toml
  • physicsbox/src/commonMain/kotlin/dev/zinchenko/physicsbox/PhysicsBoxState.kt
  • physicsbox/src/commonMain/kotlin/dev/zinchenko/physicsbox/PhysicsCommand.kt
  • physicsbox/src/commonMain/kotlin/dev/zinchenko/physicsbox/engine/PhysicsEventSink.kt
  • physicsbox/src/commonMain/kotlin/dev/zinchenko/physicsbox/engine/PhysicsWorldEngine.kt
  • physicsbox/src/commonMain/kotlin/dev/zinchenko/physicsbox/events/CollisionEvent.kt
  • physicsbox/src/commonMain/kotlin/dev/zinchenko/physicsbox/layout/PhysicsBox.kt
  • physicsbox/src/commonMain/kotlin/dev/zinchenko/physicsbox/layout/PhysicsSimulationLoop.kt
  • physicsbox/src/commonMain/kotlin/dev/zinchenko/physicsbox/physicsbody/PhysicsBody.kt
  • physicsbox/src/commonMain/kotlin/dev/zinchenko/physicsbox/physicsbody/PhysicsBodyCallbacks.kt
  • physicsbox/src/commonMain/kotlin/dev/zinchenko/physicsbox/utils/PolygonShapeUtils.kt
  • physicsbox/src/jvmMain/kotlin/dev/zinchenko/physicsbox/engine/PhysicsContactListener.kt
  • physicsbox/src/jvmMain/kotlin/dev/zinchenko/physicsbox/engine/PhysicsWorldEngine.kt
  • sharedUI/build.gradle.kts
  • sharedUI/src/commonMain/kotlin/com/zinchenkodev/app/demos/BasicStackingDemoScreen.kt
  • sharedUI/src/commonMain/kotlin/com/zinchenkodev/app/demos/BoundariesConfigDemoScreen.kt
  • sharedUI/src/commonMain/kotlin/com/zinchenkodev/app/demos/PhysicsBoxStateDemoScreen.kt
💤 Files with no reviewable changes (3)
  • sharedUI/build.gradle.kts
  • physicsbox/src/commonMain/kotlin/dev/zinchenko/physicsbox/physicsbody/PhysicsBodyCallbacks.kt
  • physicsbox/src/commonMain/kotlin/dev/zinchenko/physicsbox/engine/PhysicsEventSink.kt

Comment thread gradle/libs.versions.toml
minSdk = "23"

packageVersion = "1.0.3"
packageVersion = "1.0.4"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Версия релиза не соответствует заявленному breaking-change PR.

На Line [7] стоит packageVersion = "1.0.4", но в описании PR указан релиз v2.0.0 с breaking changes. Это создаст некорректную публикацию/семвер-сигнал для потребителей.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@gradle/libs.versions.toml` at line 7, The packageVersion field currently set
as packageVersion = "1.0.4" must be bumped to the breaking-change release
version from the PR: update packageVersion to "2.0.0" (i.e., change the value of
the packageVersion key) to reflect the major semver bump and ensure any release
metadata (changelog/release tag) aligns with this version.

Comment thread gradle/libs.versions.toml
Comment on lines +10 to +13
compose-multiplatform = "1.10.1"
material3 = "1.10.0-alpha05"
agp = "8.13.2"
androidx-activityCompose = "1.12.3"
kermit = "2.0.8"
androidx-activityCompose = "1.12.4"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Проверка compose-multiplatform 1.10.1 (Maven Central) ==="
curl -fsSL "https://repo1.maven.org/maven2/org/jetbrains/compose/compose-gradle-plugin/maven-metadata.xml" 2>/dev/null | grep -o '<version>1\.10\.1</version>' || echo "Версия 1.10.1 не найдена"

echo
echo "=== Проверка material3 1.10.0-alpha05 (Google Maven) ==="
curl -fsSL "https://dl.google.com/dl/android/maven2/androidx/compose/material3/material3/maven-metadata.xml" 2>/dev/null | grep -o '<version>1\.10\.0-alpha05</version>' || echo "Версия 1.10.0-alpha05 не найдена"

echo
echo "=== Проверка agp 8.13.2 (Google Maven) ==="
curl -fsSL "https://dl.google.com/dl/android/maven2/com/android/tools/build/gradle/maven-metadata.xml" 2>/dev/null | grep -o '<version>8\.13\.2</version>' || echo "Версия 8.13.2 не найдена"

echo
echo "=== Проверка androidx-activityCompose 1.12.4 (Google Maven) ==="
curl -fsSL "https://dl.google.com/dl/android/maven2/androidx/activity/activity-compose/maven-metadata.xml" 2>/dev/null | grep -o '<version>1\.12\.4</version>' || echo "Версия 1.12.4 не найдена"

Repository: GoetzDeBouville/PhysicsBox

Length of output: 409


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Поиск доступных версий material3 (Google Maven) ==="
curl -fsSL "https://dl.google.com/dl/android/maven2/androidx/compose/material3/material3/maven-metadata.xml" 2>/dev/null | grep -o '<version>[^<]*</version>' | tail -20 || echo "Не удалось получить метаданные"

echo
echo "=== Проверка специфично для alpha версий ==="
curl -fsSL "https://dl.google.com/dl/android/maven2/androidx/compose/material3/material3/maven-metadata.xml" 2>/dev/null | grep -i 'alpha' || echo "Alpha версии не найдены"

Repository: GoetzDeBouville/PhysicsBox

Length of output: 3775


Версия material3 "1.10.0-alpha05" недоступна в Google Maven и вызовет ошибку сборки.

Проверка показала:

  • compose-multiplatform 1.10.1 ✓ доступна
  • agp 8.13.2 ✓ доступна
  • androidx-activityCompose 1.12.4 ✓ доступна
  • material3 1.10.0-alpha05 ✗ не существует в репозитории

В Google Maven доступны версии material3 от 1.0.0-alpha* до 1.5.0-alpha15, но версии 1.10.0-alpha05 нет. Измените версию material3 на существующую (например, 1.5.0-alpha15 или ближайшую стабильную 1.4.0).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@gradle/libs.versions.toml` around lines 10 - 13, В файле libs.versions.toml
замените значение переменной material3, потому что текущая "1.10.0-alpha05"
отсутствует в Google Maven; откройте запись material3 и установите корректную
доступную версию (например "1.5.0-alpha15" или ближайшую стабильную "1.4.0"),
затем пересоберите, чтобы убедиться, что зависимость разрешается корректно.

Comment on lines +20 to +22
override fun beginContact(contact: Contact) = Unit

override fun endContact(contact: Contact) = Unit
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -name "PhysicsContactListener.kt" -type f

Repository: GoetzDeBouville/PhysicsBox

Length of output: 159


🏁 Script executed:

find . -type f -name "*.kt" | grep -i contact | head -20

Repository: GoetzDeBouville/PhysicsBox

Length of output: 159


🏁 Script executed:

git ls-files | grep -i listener | head -20

Repository: GoetzDeBouville/PhysicsBox

Length of output: 157


🏁 Script executed:

cat -n ./physicsbox/src/jvmMain/kotlin/dev/zinchenko/physicsbox/engine/PhysicsContactListener.kt

Repository: GoetzDeBouville/PhysicsBox

Length of output: 2673


🌐 Web query:

JBox2D ContactListener postSolve sensor contacts impulse

💡 Result:

In JBox2D (Box2D), sensor contacts do not produce collision response, so there’s no solver impulse to report.

  • PostSolve(contact, impulse) is only called for contacts that are “touching, solid, and awake.” Sensors are not “solid,” so you should not expect postSolve for sensor-vs-anything contacts, nor meaningful impulse values. [1]
  • PreSolve is not called for sensors (same reason: no collision response step to configure). [1]
  • Sensors “do not generate contact points” and are intended to be handled via BeginContact/EndContact (or contact.isTouching()). [2]
  • Therefore, ContactImpulse is effectively “not applicable” for sensors; if you need an “impact strength” for a sensor overlap, you must compute it yourself (e.g., using relative velocity / momentum at BeginContact). [2][3]

Practical rule:

  • Use BeginContact/EndContact for sensors.
  • Use PostSolve + ContactImpulse only for non-sensor (solid) contacts.

Sources: [1][2][3]


🏁 Script executed:

find . -type f \( -name "*.kt" -o -name "*.java" \) | xargs grep -l "sensor" | head -10

Repository: GoetzDeBouville/PhysicsBox

Length of output: 313


🏁 Script executed:

find . -type f -name "*Test*" -o -name "*test*" | grep -i contact | head -10

Repository: GoetzDeBouville/PhysicsBox

Length of output: 52


🏁 Script executed:

find . -type f -name "*.kt" | xargs grep -l "sensor" | head -5

Repository: GoetzDeBouville/PhysicsBox

Length of output: 313


🏁 Script executed:

rg "PhysicsContactListener" --type kt -A 3 -B 3

Repository: GoetzDeBouville/PhysicsBox

Length of output: 96


🏁 Script executed:

rg "PhysicsContactListener" -A 3 -B 3

Repository: GoetzDeBouville/PhysicsBox

Length of output: 1770


🏁 Script executed:

rg "beginContact|endContact" --type-list | head -5

Repository: GoetzDeBouville/PhysicsBox

Length of output: 459


🏁 Script executed:

rg "sensor" --max-count 20

Repository: GoetzDeBouville/PhysicsBox

Length of output: 2140


🏁 Script executed:

rg "CollisionEvent" -A 2 -B 2

Repository: GoetzDeBouville/PhysicsBox

Length of output: 14083


🏁 Script executed:

find . -type f -name "*.md" | xargs grep -l "sensor\|contact\|lifecycle" 2>/dev/null | head -5

Repository: GoetzDeBouville/PhysicsBox

Length of output: 108


🏁 Script executed:

cat -n ./docs/events.md

Repository: GoetzDeBouville/PhysicsBox

Length of output: 1790


🏁 Script executed:

cat -n ./physicsbox/src/commonMain/kotlin/dev/zinchenko/physicsbox/events/CollisionEvent.kt

Repository: GoetzDeBouville/PhysicsBox

Length of output: 2049


Потеря событий сенсорных контактов из-за полагания только на postSolve.

В JBox2D postSolve вызывается только для solid контактов с физическим ответом (когда есть impulse). Сенсорные контакты не генерируют impulses, поэтому postSolve для них никогда не срабатывает. Текущая реализация полностью теряет события таких контактов, так как beginContact и endContact пусты.

Требуется либо:

  • Реализовать обработку сенсорных контактов в beginContact/endContact, либо
  • Явно задокументировать в API и в docs/events.md, что сообщаются только импульсные столкновения из postSolve и сенсорные контакты исключены.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@physicsbox/src/jvmMain/kotlin/dev/zinchenko/physicsbox/engine/PhysicsContactListener.kt`
around lines 20 - 22, PhysicsContactListener currently ignores sensor contacts
because beginContact/endContact are no-ops and postSolve only fires for impulse
contacts; implement sensor handling in beginContact(contact: Contact) and
endContact(contact: Contact) to detect contact.isSensor or
Contact.fixtureA/fixtureB.isSensor, build and dispatch the existing event
payload (same shape as postSolve collision events) for sensors, or alternatively
add explicit documentation to docs/events.md and the public API docs in
PhysicsContactListener noting that only impulse collisions from postSolve are
emitted and sensor contacts are excluded; update the code paths that rely on
sensor events (postSolve handlers) to use the new beginContact/endContact sensor
events if you choose implementation.

@GoetzDeBouville GoetzDeBouville merged commit ef5b925 into main Mar 2, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant