/
arti4
/
IndividualProject
Обзор
Документация
Войти
/
arti4
/
IndividualProject
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
MyGame/app/src/main/java/com/example/mygame/PhysicsWorld.java
285 строк
11 KB
arti4
upload files
18 ноя 2025, 12:41
18 ноя 2025, 12:41
f3a2f8a
Код
Авторство
О чём код?
package com.example.mygame; import org.jbox2d.collision.shapes.CircleShape; import org.jbox2d.common.Vec2; import org.jbox2d.dynamics.World; import org.jbox2d.dynamics.Body; import org.jbox2d.dynamics.BodyDef; import org.jbox2d.dynamics.BodyType; import org.jbox2d.dynamics.FixtureDef; import org.jbox2d.collision.shapes.PolygonShape; import org.jbox2d.dynamics.Filter; import org.jbox2d.callbacks.ContactListener; import org.jbox2d.callbacks.ContactImpulse; import org.jbox2d.dynamics.contacts.Contact; import org.jbox2d.collision.Manifold; import java.util.ArrayList; import java.util.List; public class PhysicsWorld { private World world; private float physicsScale = 0.01f; private Vec2 gravity = new Vec2(0.0f, 30.0f); public static final short CATEGORY_CAR = 0x0001; public static final short CATEGORY_GROUND = 0x0002; public static final short CATEGORY_OBSTACLE = 0x0004; public static final short CATEGORY_PLATFORM = 0x0008; public static final short CATEGORY_CRYSTAL = 0x0010; public static final short MASK_CAR = CATEGORY_GROUND | CATEGORY_OBSTACLE | CATEGORY_PLATFORM | CATEGORY_CRYSTAL; public static final short MASK_GROUND = CATEGORY_CAR; public static final short MASK_OBSTACLE = CATEGORY_CAR; public static final short MASK_PLATFORM = CATEGORY_CAR; private List<Body> bodiesToRemove = new ArrayList<>(); public PhysicsWorld() { world = new World(gravity); world.setAllowSleep(false); } public void update(float deltaTime) { world.step(deltaTime, 6, 2); for (Body body : bodiesToRemove) { world.destroyBody(body); } bodiesToRemove.clear(); } public Body createGroundBody(float x, float y, float width, float height, Object userData) { BodyDef bodyDef = new BodyDef(); bodyDef.type = BodyType.STATIC; bodyDef.position.set(x * physicsScale, y * physicsScale); Body body = world.createBody(bodyDef); PolygonShape shape = new PolygonShape(); shape.setAsBox(width * physicsScale / 2, height * physicsScale / 2); FixtureDef fixtureDef = new FixtureDef(); fixtureDef.shape = shape; fixtureDef.density = 0.0f; fixtureDef.friction = 0.1f; fixtureDef.restitution = 0.0f; fixtureDef.filter.categoryBits = CATEGORY_GROUND; fixtureDef.filter.maskBits = MASK_GROUND; body.createFixture(fixtureDef); body.setUserData(userData); return body; } public Body createMotorcycleBody(float x, float y, float width, float height, Object userData, int motorcycleType) { BodyDef bodyDef = new BodyDef(); bodyDef.type = BodyType.DYNAMIC; bodyDef.position.set(x * physicsScale, y * physicsScale); bodyDef.angle = 0; float[] linearDamping = {0.8f, 0.7f, 0.9f, 0.6f, 0.75f, 0.85f, 0.8f, 0.65f, 0.95f, 0.6f}; float[] angularDamping = {1.5f, 1.3f, 1.7f, 1.2f, 1.4f, 1.6f, 1.5f, 1.1f, 1.8f, 1.0f}; float[] widthMultipliers = {0.7f, 0.65f, 0.75f, 0.6f, 0.7f, 0.8f, 0.75f, 0.65f, 0.8f, 0.85f}; float[] heightMultipliers = {1f, 1f, 1.2f, 1.3f, 1f, 1.4f, 1.2f, 1.2f, 1f, 1.6f}; bodyDef.linearDamping = linearDamping[motorcycleType]; bodyDef.angularDamping = angularDamping[motorcycleType]; bodyDef.fixedRotation = false; Body body = world.createBody(bodyDef); float physicsWidth = width * widthMultipliers[motorcycleType]; float physicsHeight = height * heightMultipliers[motorcycleType]; PolygonShape shape = new PolygonShape(); shape.setAsBox(physicsWidth * physicsScale / 2, physicsHeight * physicsScale / 2); FixtureDef fixtureDef = new FixtureDef(); fixtureDef.shape = shape; float[] densities = {2.0f, 1.8f, 2.2f, 1.7f, 1.9f, 2.1f, 2.0f, 1.6f, 2.3f, 1.5f}; fixtureDef.density = densities[motorcycleType]; fixtureDef.friction = 0.9f; fixtureDef.restitution = 0.1f; fixtureDef.filter.categoryBits = CATEGORY_CAR; fixtureDef.filter.maskBits = MASK_CAR; body.createFixture(fixtureDef); body.setUserData(userData); return body; } public Body createRampBody(float x, float y, float width, float totalHeight, float startHeight, float endHeight, Object userData) { BodyDef bodyDef = new BodyDef(); bodyDef.type = BodyType.STATIC; float centerX = x + width / 2.0f; float centerY = y + totalHeight / 2.0f +15; bodyDef.position.set(centerX * physicsScale, centerY * physicsScale); Body body = world.createBody(bodyDef); PolygonShape shape = new PolygonShape(); float halfWidth = width / 2.0f * physicsScale; float halfHeight = totalHeight / 2.0f * physicsScale; Vec2[] vertices = new Vec2[4]; vertices[0] = new Vec2(-halfWidth, halfHeight); vertices[1] = new Vec2(-halfWidth, halfHeight - startHeight * physicsScale); vertices[2] = new Vec2(halfWidth, -halfHeight + endHeight * physicsScale); vertices[3] = new Vec2(halfWidth, halfHeight); shape.set(vertices, 4); FixtureDef fixtureDef = new FixtureDef(); fixtureDef.shape = shape; fixtureDef.density = 0.0f; fixtureDef.friction = 0f; fixtureDef.restitution = 0.1f; fixtureDef.filter.categoryBits = CATEGORY_GROUND; fixtureDef.filter.maskBits = MASK_GROUND; body.createFixture(fixtureDef); body.setUserData(userData); return body; } public Body createTriangleRampBody(float centerX, float centerY, float width, float height, Object userData) { BodyDef bodyDef = new BodyDef(); bodyDef.type = BodyType.STATIC; bodyDef.position.set(centerX * physicsScale, centerY * physicsScale); Body body = world.createBody(bodyDef); PolygonShape shape = new PolygonShape(); Vec2[] vertices = new Vec2[3]; vertices[0] = new Vec2(-width/2 * physicsScale, height/2 * physicsScale); vertices[1] = new Vec2(0, -height/2 * physicsScale); vertices[2] = new Vec2(width/2 * physicsScale, height/2 * physicsScale); shape.set(vertices, 3); FixtureDef fixtureDef = new FixtureDef(); fixtureDef.shape = shape; fixtureDef.density = 0.0f; fixtureDef.friction = 0.8f; fixtureDef.restitution = 0.1f; fixtureDef.filter.categoryBits = CATEGORY_GROUND; fixtureDef.filter.maskBits = MASK_GROUND; fixtureDef.userData = "triangle_ramp"; body.createFixture(fixtureDef); body.setUserData(userData); return body; } public Body createCrystalBody(float x, float y, float width, float height, Object userData) { BodyDef bodyDef = new BodyDef(); bodyDef.type = BodyType.STATIC; bodyDef.position.set(x * physicsScale, y * physicsScale); Body body = world.createBody(bodyDef); PolygonShape shape = new PolygonShape(); shape.setAsBox(width * physicsScale / 2, height * physicsScale / 2); FixtureDef fixtureDef = new FixtureDef(); fixtureDef.shape = shape; fixtureDef.density = 0.0f; fixtureDef.friction = 0.0f; fixtureDef.restitution = 0.0f; fixtureDef.isSensor = true; fixtureDef.filter.categoryBits = CATEGORY_CRYSTAL; fixtureDef.filter.maskBits = CATEGORY_CRYSTAL; body.createFixture(fixtureDef); body.setUserData(userData); return body; } public boolean hasGroundContact(Body body) { int contactCount = 0; for (Contact contact = world.getContactList(); contact != null; contact = contact.getNext()) { if (contact.isTouching()) { Body bodyA = contact.getFixtureA().getBody(); Body bodyB = contact.getFixtureB().getBody(); if (bodyA == body || bodyB == body) { Body otherBody = (bodyA == body) ? bodyB : bodyA; Object userData = otherBody.getUserData(); if (userData instanceof RoadSegment) { contactCount++; } } } } return contactCount > 0; } public Body createPlatformBody(float x, float y, float width, float height, Object userData) { BodyDef bodyDef = new BodyDef(); bodyDef.type = BodyType.KINEMATIC; bodyDef.position.set(x * physicsScale, y * physicsScale); Body body = world.createBody(bodyDef); PolygonShape shape = new PolygonShape(); shape.setAsBox(width * physicsScale / 2, height * physicsScale / 2); FixtureDef fixtureDef = new FixtureDef(); fixtureDef.shape = shape; fixtureDef.density = 0.0f; fixtureDef.friction = 0.7f; fixtureDef.restitution = 0.0f; fixtureDef.filter.categoryBits = CATEGORY_PLATFORM; fixtureDef.filter.maskBits = MASK_PLATFORM; body.createFixture(fixtureDef); body.setUserData(userData); return body; } public Body createObstacleBody(float x, float y, float width, float height, Object userData) { BodyDef bodyDef = new BodyDef(); bodyDef.type = BodyType.STATIC; bodyDef.position.set(x * physicsScale, y * physicsScale); Body body = world.createBody(bodyDef); PolygonShape shape = new PolygonShape(); shape.setAsBox(width * physicsScale / 2, height * physicsScale / 2); FixtureDef fixtureDef = new FixtureDef(); fixtureDef.shape = shape; fixtureDef.density = 0.0f; fixtureDef.friction = 0.3f; fixtureDef.restitution = 0.0f; fixtureDef.filter.categoryBits = CATEGORY_OBSTACLE; fixtureDef.filter.maskBits = MASK_OBSTACLE; body.createFixture(fixtureDef); body.setUserData(userData); return body; } public void setBodyPosition(Body body, float x, float y) { body.setTransform(new Vec2(x * physicsScale, y * physicsScale), body.getAngle()); } public Vec2 getBodyPosition(Body body) { Vec2 pos = body.getPosition(); return new Vec2(pos.x / physicsScale, pos.y / physicsScale); } public float getBodyAngle(Body body) { return body.getAngle(); } public void markBodyForRemoval(Body body) { bodiesToRemove.add(body); } public World getWorld() { return world; } public float getPhysicsScale() { return physicsScale; } public void dispose() { bodiesToRemove.clear(); } }