Perpetuum mobile

Buenas tardes, querido usuario habr.com! Este es el tercer artículo sobre el tema. Trabajo todo el día, no puedo separarme de la increíble biblioteca Box2D.

Si no ha leído el primer y el segundo artículo, asegúrese de mirar, ¡será divertido! Trabajo en Eclipse , escribo en Java. ¿Por qué llamé así a mi artículo? Sigue leyendo, ¡y muy pronto todo se aclarará! Spoiler: crearemos nuestra propia máquina de movimiento perpetuo (incluso para automóviles) y, tal vez, crearemos la máquina en sí.

imagen

Figura 1. Máquina de movimiento perpetuo.

Entonces, hoy intentaremos obtener algo como esto:

imagen

Figura 2. Máquina con motor.

Sí, esto no es un error tipográfico! Hoy haremos una máquina con un motor real, ¡será indistinguible del real! Este no es el "carrito" para ti desde el primer artículo.

Para conectar libGDX, vea el primer artículo.

Aquí hay una imagen que muestra cómo se ve mi ensamblaje. Agregué el paquete Utils con la clase Constantes a la carpeta Core, que contiene solo una constante: la cantidad de píxeles por metro. Esto es para que el mundo no sea gigantesco.

imagen

Figura 3. Mi construcción.

Aquí está el código para la clase DesktopLauncher de com.mygdx.game.desktop:

Pega este código en la clase y olvídalo.
package com.mygdx.game.desktop; import com.badlogic.gdx.backends.lwjgl.LwjglApplication; import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration; import com.mygdx.game.MyGdxGame; public class DesktopLauncher { public static void main(String[] arg) { LwjglApplicationConfiguration config = new LwjglApplicationConfiguration(); //   config.width = 720; //   config.height = 480; config.backgroundFPS = 60; config.foregroundFPS = 60; new LwjglApplication(new MyGdxGame(), config); } } 


El siguiente código para la clase MyGdxGame es del paquete com.mygdx.game. Todo está en los comentarios del código.

Creamos el mundo y la máquina.
 package com.mygdx.game; import com.badlogic.gdx.ApplicationAdapter; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input.Keys; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector3; import com.badlogic.gdx.physics.box2d.Body; import com.badlogic.gdx.physics.box2d.BodyDef; import com.badlogic.gdx.physics.box2d.Box2DDebugRenderer; import com.badlogic.gdx.physics.box2d.CircleShape; import com.badlogic.gdx.physics.box2d.FixtureDef; import com.badlogic.gdx.physics.box2d.PolygonShape; import com.badlogic.gdx.physics.box2d.World; import com.badlogic.gdx.physics.box2d.joints.RevoluteJointDef; import utils.Constants; public class MyGdxGame extends ApplicationAdapter { private OrthographicCamera camera; private boolean DEBUG = false; private World world; private Box2DDebugRenderer b2dr; //  private Body box; //   private Body backweel; //   private Body frontweel; private Body floor; private Body triangle; //   private float m = -20; public void create() { float w = Gdx.graphics.getWidth(); float h = Gdx.graphics.getHeight(); camera = new OrthographicCamera(); camera.setToOrtho(false, w / 2, h / 2); world = new World(new Vector2(0, -9.8f), false); b2dr = new Box2DDebugRenderer(); //   floor = createFloor(); //   triangle = createTriangle(20f, 40f, 30f, -2f, -2f, 5f); triangle = createTriangle(50f, 60f, 80f, -2f, 10f, -2f); triangle = createTriangle(100f, 160f, 200f, -2f, 20f, -2f); triangle = createTriangle(280f, 290f, 300f, -2f, 100f, -2f); //   box = createBox(); //   backweel = createWeel(-1f, 2f); frontweel = createWeel(4.5f, 2f); //        connected(); } //      public void connected() { revJoint(box, backweel, -1f * 10 / utils.Constants.PPM, -2f * 10 / utils.Constants.PPM); revJoint(box, frontweel, 4.5f * 10 / utils.Constants.PPM, -2f * 10 / utils.Constants.PPM); } //   !  ! public void revJoint(Body body1, Body body2, float xo, float yo) { //   RevoluteJointDef rjd = new RevoluteJointDef(); //    rjd.enableMotor = true; //  .      ,  ,  //  .    .   -   ! rjd.motorSpeed = m; //   rjd.maxMotorTorque = 30; rjd.collideConnected = false; rjd.bodyA = body1; rjd.bodyB = body2; rjd.localAnchorA.set(xo, yo); world.createJoint(rjd); } public void render() { update(Gdx.graphics.getDeltaTime()); Gdx.gl.glClearColor(0, 0, 0, 1); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); b2dr.render(world, camera.combined.scl(Constants.PPM)); } public void resize(int width, int height) { camera.setToOrtho(false, width / 2, height / 2); } public void dispose() { world.dispose(); b2dr.dispose(); } public void update(float delta) { world.step(1 / 60f, 6, 2); cameraUpdate(delta); inputUpdate(delta); } //       ,     public void inputUpdate(float delta) { if (Gdx.input.isKeyPressed(Keys.SPACE)) { box.setLinearVelocity(5, 5); } } //     public void cameraUpdate(float delta) { Vector3 position = camera.position; position.x = box.getPosition().x * Constants.PPM; position.y = box.getPosition().y * Constants.PPM; camera.position.set(position); camera.update(); } //     public Body createBox() { Vector2[] verticles = new Vector2[8]; verticles[0] = new Vector2(2f * 10 / utils.Constants.PPM, 2f * 10 / utils.Constants.PPM); verticles[1] = new Vector2(2f * 10 / utils.Constants.PPM, -2f * 10 / utils.Constants.PPM); verticles[2] = new Vector2(-2f * 10 / utils.Constants.PPM, 2f * 10 / utils.Constants.PPM); verticles[3] = new Vector2(-2f * 10 / utils.Constants.PPM, -2f * 10 / utils.Constants.PPM); verticles[4] = new Vector2(6f * 10 / utils.Constants.PPM, -2f * 10 / utils.Constants.PPM); verticles[5] = new Vector2(6f * 10 / utils.Constants.PPM, 0f * 10 / utils.Constants.PPM); verticles[6] = new Vector2(-1f * 10 / utils.Constants.PPM, -2f * 10 / utils.Constants.PPM); verticles[7] = new Vector2(4.5f * 10 / utils.Constants.PPM, -2f * 10 / utils.Constants.PPM); PolygonShape shape = new PolygonShape(); Body fBody; BodyDef def = new BodyDef(); def.type = BodyDef.BodyType.DynamicBody; def.position.set(0, 0); def.fixedRotation = false; fBody = world.createBody(def); shape.set(verticles); //    FixtureDef fd = new FixtureDef(); // ,     fd.shape = shape; //   fd.friction = 0.5f; //   fd.density = 3f; //   fd.restitution = 0.5f; fBody.createFixture(fd); fBody.createFixture(fd); shape.dispose(); return fBody; } //   public Body createWeel(float xo, float yo) { CircleShape shape = new CircleShape(); Body fBody; BodyDef def = new BodyDef(); def.type = BodyDef.BodyType.DynamicBody; def.position.set(xo * 10 / utils.Constants.PPM, yo * 10 / utils.Constants.PPM); def.fixedRotation = false; fBody = world.createBody(def); shape.setRadius(2.0f * 10 / utils.Constants.PPM); //    FixtureDef fd = new FixtureDef(); fd.shape = shape; fd.friction = 0.7f; fd.density = 3f; fd.restitution = 0.5f; fBody.createFixture(fd); shape.dispose(); return fBody; } //   public Body createFloor() { Vector2[] verticles = new Vector2[4]; verticles[0] = new Vector2(-100f * 10 / utils.Constants.PPM, -2f * 10 / utils.Constants.PPM); verticles[1] = new Vector2(300f * 10 / utils.Constants.PPM, -2f * 10 / utils.Constants.PPM); verticles[2] = new Vector2(300f * 10 / utils.Constants.PPM, -5f * 10 / utils.Constants.PPM); verticles[3] = new Vector2(-100f * 10 / utils.Constants.PPM, -5f * 10 / utils.Constants.PPM); PolygonShape shape = new PolygonShape(); Body fBody; BodyDef def = new BodyDef(); def.type = BodyDef.BodyType.StaticBody; def.position.set(0, 0); def.fixedRotation = true; fBody = world.createBody(def); shape.set(verticles); FixtureDef fd = new FixtureDef(); fd.shape = shape; fd.friction = 0.5f; fd.density = 3f; fd.restitution = 0.5f; fBody.createFixture(fd); shape.dispose(); return fBody; } //    ! public Body createTriangle(float xo, float x1, float x2, float yo, float y1, float y2) { Vector2[] verticles = new Vector2[3]; verticles[0] = new Vector2(xo * 10 / utils.Constants.PPM, yo * 10 / utils.Constants.PPM); verticles[1] = new Vector2(x1 * 10 / utils.Constants.PPM, y1 * 10 / utils.Constants.PPM); verticles[2] = new Vector2(x2 * 10 / utils.Constants.PPM, y2 * 10 / utils.Constants.PPM); PolygonShape shape = new PolygonShape(); Body fBody; BodyDef def = new BodyDef(); def.type = BodyDef.BodyType.StaticBody; def.position.set(0, 0); def.fixedRotation = true; fBody = world.createBody(def); shape.set(verticles); FixtureDef fd = new FixtureDef(); fd.shape = shape; fd.friction = 0.5f; fd.density = 10f; fd.restitution = 0f; fBody.createFixture(fd); shape.dispose(); return fBody; } } 



imagen
Figura 4. ¿Qué obtenemos al compilar?

Creamos nuestro automóvil un motor que hace girar sus ruedas. Pero funciona para siempre, porque no hay pérdidas de energía. ¡Así creamos nuestra máquina de movimiento perpetuo!

¿Y te preguntas qué hay al final del nivel? Enviar capturas de pantalla en los comentarios sobre la marcha. ¡Gracias por leer el artículo hasta el final! ¡Espero que puedas crear tu propio auto en Box2D!

PD: ¡Espero sus preguntas en los comentarios! ¡Viva la física de los juegos!

Source: https://habr.com/ru/post/450442/


All Articles