├── .classpath ├── .gitignore ├── .project ├── .settings ├── org.eclipse.core.resources.prefs ├── org.eclipse.jdt.core.prefs └── org.eclipse.m2e.core.prefs ├── LICENSE.md ├── README.md ├── captures ├── BasketBall.gif ├── Billiards.gif ├── Platformer.gif ├── Ragdoll.gif ├── Tank.gif ├── Thrust.gif └── Truck.gif ├── pom.xml └── src └── main └── java └── org └── dyn4j └── samples ├── BasketBall.java ├── Billiards.java ├── Bowling.java ├── Bridge.java ├── Bucket.java ├── Concave.java ├── Crank.java ├── Decomposition.java ├── Destructible.java ├── Images.java ├── LinkTerrain.java ├── Maze.java ├── Organize.java ├── Platformer.java ├── Pyramid.java ├── Ragdoll.java ├── Stacking.java ├── Tank.java ├── Thrust.java ├── Tracking.java ├── Truck.java ├── UsingGraphics2D.java ├── UsingJogl.java ├── framework ├── Camera.java ├── Graphics2DRenderer.java ├── SimulationBody.java ├── SimulationFrame.java └── input │ ├── AbstractInputHandler.java │ ├── AbstractKeyboardInputHandler.java │ ├── AbstractMouseInputHandler.java │ ├── BooleanStateKeyboardInputHandler.java │ ├── BooleanStateMouseInputHandler.java │ ├── CodeExporter.java │ ├── ExportCodeKeyboardInputHandler.java │ ├── InputHandler.java │ ├── Key.java │ ├── MousePanningInputHandler.java │ ├── MousePickingInputHandler.java │ ├── MouseZoomInputHandler.java │ └── ToggleStateKeyboardInputHandler.java ├── package-info.java └── resources ├── Basketball.png └── Crate.png /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | dyn4j-samples 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding/=UTF-8 3 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 4 | org.eclipse.jdt.core.compiler.compliance=1.6 5 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 6 | org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled 7 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 8 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 9 | org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore 10 | org.eclipse.jdt.core.compiler.release=disabled 11 | org.eclipse.jdt.core.compiler.source=1.6 12 | -------------------------------------------------------------------------------- /.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010-2021, William Bittle 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the copyright holder nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dyn4j-samples 2 | A collection of samples that use the dyn4j library in a variety of ways. 3 | 4 | The intent of these samples is to provide a simple framework for building applications with the dyn4j library. The samples show how to use features like joints, static collision detection, raycasting, CCD, and so on. They also provide some creative ways to solve common problems like one-way platforms, jumping, destruction, player control, and so on. That said, none of these are intended to be complete solutions or even the correct solution for your use-case. 5 | 6 | * All samples support zoom and pan using the mouse and mouse wheel 7 | * All samples support object manipulation with the mouse 8 | * All samples have features like reset, reset camera, toggle rendering, etc. 9 | * Each sample may have it's own controls - see the console output when running for the full list of controls 10 | 11 | | Sample | Description | Concepts | 12 | | --- | --- | --- | 13 | | [BasketBall](https://github.com/dyn4j/dyn4j-samples/tree/master/src/main/java/org/dyn4j/samples/BasketBall.java) | A side view basketball game | Player Input, DistanceJoint, RevoluteJoint, Image Mapping/Texturing, Filtering, Bounds Listening | 14 | | [Billiards](https://github.com/dyn4j/dyn4j-samples/tree/master/src/main/java/org/dyn4j/samples/Billiards.java) | A top down billiards simulation | Density, Friction, Damping, Player Input | 15 | | [Bowling](https://github.com/dyn4j/dyn4j-samples/tree/master/src/main/java/org/dyn4j/samples/Bowling.java) | A side view of a bowling ball hitting pins | Density, Friction, Restitution, CategoryFilter | 16 | | [Bridge](https://github.com/dyn4j/dyn4j-samples/tree/master/src/main/java/org/dyn4j/samples/Bridge.java) | A side view of a bridge made from joined bodies | RevoluteJoint | 17 | | [Bucket](https://github.com/dyn4j/dyn4j-samples/tree/master/src/main/java/org/dyn4j/samples/Bucket.java) | A side view of a bucket with 200 random objects | Larger world | 18 | | [Concave](https://github.com/dyn4j/dyn4j-samples/tree/master/src/main/java/org/dyn4j/samples/Concave.java) | A side view of a concave object | Concave vs. Convex, Convex Composition | 19 | | [Crank](https://github.com/dyn4j/dyn4j-samples/tree/master/src/main/java/org/dyn4j/samples/Crank.java) | A side view of a piston | RevoluteJoint, PrismaticJoint | 20 | | [Decomposition](https://github.com/dyn4j/dyn4j-samples/tree/master/src/main/java/org/dyn4j/samples/Decomposition.java) | A side view of a few simple polygons decomposed | Convex Decomposition | 21 | | [Destructible](https://github.com/dyn4j/dyn4j-samples/tree/master/src/main/java/org/dyn4j/samples/Destructible.java) | A side view of destruction of a body and joint | Remove/Add Buffering | 22 | | [Images](https://github.com/dyn4j/dyn4j-samples/tree/master/src/main/java/org/dyn4j/samples/Images.java) | A side view of a scene where images are mapped to bodies | Image Mapping/Texturing | 23 | | [LinkTerrain](https://github.com/dyn4j/dyn4j-samples/tree/master/src/main/java/org/dyn4j/samples/LinkTerrain.java) | A side view of a link-based floor | Smooth Sliding, Link | 24 | | [Maze](https://github.com/dyn4j/dyn4j-samples/tree/master/src/main/java/org/dyn4j/samples/Maze.java) | A top down view of a maze with a player controled body | MotorJoint, Player Control | 25 | | [Organize](https://github.com/dyn4j/dyn4j-samples/tree/master/src/main/java/org/dyn4j/samples/Organize.java) | A side view of a scene where bodies are randomly joined and self organize | DistanceJoint | 26 | | [Platformer](https://github.com/dyn4j/dyn4j-samples/tree/master/src/main/java/org/dyn4j/samples/Platformer.java) | A side view of a platformer simulation | OnGround, Player Control, One-way Platform, Jumping | 27 | | [Pyramid](https://github.com/dyn4j/dyn4j-samples/tree/master/src/main/java/org/dyn4j/samples/Pyramid.java) | A side view of a Pyramid of stacked boxes | Stacking | 28 | | [Ragdoll](https://github.com/dyn4j/dyn4j-samples/tree/master/src/main/java/org/dyn4j/samples/Ragdoll.java) | A side view of a ragdoll made from joints | RevoluteJoint | 29 | | [Stacking](https://github.com/dyn4j/dyn4j-samples/tree/master/src/main/java/org/dyn4j/samples/Stacking.java) | A side view of a scene where the player can add boxes dynamically | Stacking, Add Bodies | 30 | | [Tank](https://github.com/dyn4j/dyn4j-samples/tree/master/src/main/java/org/dyn4j/samples/Tank.java) | A top down tank simulation | Raycasting, Player Control, FrictionJoint, RevoluteJoint | 31 | | [Thrust](https://github.com/dyn4j/dyn4j-samples/tree/master/src/main/java/org/dyn4j/samples/Thrust.java) | A side view of a scene with a rocket | Applying Forces | 32 | | [Tracking](https://github.com/dyn4j/dyn4j-samples/tree/master/src/main/java/org/dyn4j/samples/Tracking.java) | A scene where contact tracking is printed to the console | Contact Tracking | 33 | | [Truck](https://github.com/dyn4j/dyn4j-samples/tree/master/src/main/java/org/dyn4j/samples/Truck.java) | A scene where a truck filled with boxes moves through a world | WheelJoint, Fixture Composition | 34 | | [UsingGraphics2D](https://github.com/dyn4j/dyn4j-samples/tree/master/src/main/java/org/dyn4j/samples/UsingGraphics2D.java) | A scene with just a bunch of shapes rendered via Java 2D | Java 2D | 35 | | [UsingJogl](https://github.com/dyn4j/dyn4j-samples/tree/master/src/main/java/org/dyn4j/samples/UsingJogl.java) | A scene with a few shapes rendered via OpenGL via JOGL | JOGL | 36 | 37 | ### BasketBall 38 | Use angle, power, and position to attempt to make baskets. The sample only scores goals, so don't miss! If you are close you get 2 points, far away you get 3. Only if you get it in when you launch it is counted. 39 | 40 | ![BasketBall Sample](captures/BasketBall.gif?raw=true "BasketBall sample") 41 | 42 | ### Billiards 43 | Use the cue stick to hit the cue ball to hit the other balls. You must wait until the balls settle before your next hit. 44 | 45 | ![Billiards Sample](captures/Billiards.gif?raw=true "Billiards sample") 46 | 47 | ### Platformer 48 | Use the ball to "run" around the level and jump. You can jump onto platforms above you no matter where you are, but if you land on them, they are solid. You can drop down from the top level as well. Green means you are touching the ground and can jump. Purple means you are not touching the ground. 49 | 50 | ![Platformer Sample](captures/Platformer.gif?raw=true "Platformer sample") 51 | 52 | ### Ragdoll 53 | Use your mouse to drag around and contort the ragdoll 54 | 55 | ![Ragdoll Sample](captures/Ragdoll.gif?raw=true "Ragdoll sample") 56 | 57 | ### Tank 58 | Drive a tank! Independently operating the tracks and barrel. The barrel will be pushed aside by obstacles. The barrel is "shooting" a ray to see what it would hit. You can press a key to destroy the closest object you are aiming at. 59 | 60 | ![Tank Sample](captures/Tank.gif?raw=true "Tank sample") 61 | 62 | ### Thrust 63 | How hard can it be to fly a rocket? Using only front, back and side thrusters (applied force) fly a rocket around an enclosed area. Challenge yourself to land without tipping over or flying in a smooth trajectory. 64 | 65 | ![Thrust Sample](captures/Thrust.gif?raw=true "Thrust sample") 66 | 67 | ### Truck 68 | Drive a truck with cargo! Accelerate and decelerate using the keyboard or stop immediately. Watch the contents slide around as you drive. Use the mouse to manipulate the truck frame to see the suspension compress. 69 | 70 | ![Truck Sample](captures/Truck.gif?raw=true "Truck sample") 71 | 72 | -------------------------------------------------------------------------------- /captures/BasketBall.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dyn4j/dyn4j-samples/747a479d3a0059f73a4de62d33b6003d387d933e/captures/BasketBall.gif -------------------------------------------------------------------------------- /captures/Billiards.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dyn4j/dyn4j-samples/747a479d3a0059f73a4de62d33b6003d387d933e/captures/Billiards.gif -------------------------------------------------------------------------------- /captures/Platformer.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dyn4j/dyn4j-samples/747a479d3a0059f73a4de62d33b6003d387d933e/captures/Platformer.gif -------------------------------------------------------------------------------- /captures/Ragdoll.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dyn4j/dyn4j-samples/747a479d3a0059f73a4de62d33b6003d387d933e/captures/Ragdoll.gif -------------------------------------------------------------------------------- /captures/Tank.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dyn4j/dyn4j-samples/747a479d3a0059f73a4de62d33b6003d387d933e/captures/Tank.gif -------------------------------------------------------------------------------- /captures/Thrust.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dyn4j/dyn4j-samples/747a479d3a0059f73a4de62d33b6003d387d933e/captures/Thrust.gif -------------------------------------------------------------------------------- /captures/Truck.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dyn4j/dyn4j-samples/747a479d3a0059f73a4de62d33b6003d387d933e/captures/Truck.gif -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | org.dyn4j 4 | dyn4j-samples 5 | 1.0.0 6 | dyn4j-samples 7 | http://www.dyn4j.org 8 | A collection of samples that use the dyn4j library in a variety of ways 9 | 2010 10 | 11 | dyn4j 12 | http://www.dyn4j.org 13 | 14 | 15 | https://github.com/dyn4j/dyn4j-samples 16 | 17 | 18 | GitHub Issues 19 | https://github.com/dyn4j/dyn4j-samples/issues 20 | 21 | 22 | 6 23 | 24 | 25 | 26 | org.jogamp.jogl 27 | jogl-all-main 28 | 2.3.2 29 | 30 | 31 | org.jogamp.gluegen 32 | gluegen-rt-main 33 | 2.3.2 34 | 35 | 36 | org.dyn4j 37 | dyn4j 38 | 5.0.2 39 | 40 | 41 | 42 | 43 | 44 | 45 | maven-compiler-plugin 46 | 3.8.0 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /src/main/java/org/dyn4j/samples/Billiards.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2023 William Bittle http://www.dyn4j.org/ 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted 6 | * provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, this list of conditions 9 | * and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | * and the following disclaimer in the documentation and/or other materials provided with the 12 | * distribution. 13 | * * Neither the name of dyn4j nor the names of its contributors may be used to endorse or 14 | * promote products derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 23 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | package org.dyn4j.samples; 26 | 27 | import java.awt.Color; 28 | import java.awt.Graphics2D; 29 | import java.awt.event.KeyEvent; 30 | 31 | import org.dyn4j.collision.Filter; 32 | import org.dyn4j.dynamics.BodyFixture; 33 | import org.dyn4j.geometry.Geometry; 34 | import org.dyn4j.geometry.MassType; 35 | import org.dyn4j.geometry.Polygon; 36 | import org.dyn4j.geometry.Transform; 37 | import org.dyn4j.geometry.Vector2; 38 | import org.dyn4j.samples.framework.Camera; 39 | import org.dyn4j.samples.framework.SimulationBody; 40 | import org.dyn4j.samples.framework.SimulationFrame; 41 | import org.dyn4j.samples.framework.input.BooleanStateKeyboardInputHandler; 42 | import org.dyn4j.samples.framework.input.Key; 43 | import org.dyn4j.world.World; 44 | 45 | /** 46 | * A simple scene of two billiard balls colliding with one another 47 | * and a wall. 48 | *

49 | * Primarily used to illustrate the computation of the mass and size 50 | * of the balls. See the {@link Billiards#initializeWorld()} method. 51 | * @author William Bittle 52 | * @version 5.0.2 53 | * @since 3.2.0 54 | */ 55 | public final class Billiards extends SimulationFrame { 56 | /** The serial version id */ 57 | private static final long serialVersionUID = -8518496343422955267L; 58 | 59 | private static final Object BALL_IDENTIFIER = new Object(); 60 | private SimulationBody cueBall; 61 | private SimulationBody cueStick; 62 | private Vector2 stickLocation = new Vector2(); 63 | 64 | private double angle; 65 | private double power; 66 | 67 | private final BooleanStateKeyboardInputHandler left; 68 | private final BooleanStateKeyboardInputHandler right; 69 | 70 | private final BooleanStateKeyboardInputHandler plus; 71 | private final BooleanStateKeyboardInputHandler minus; 72 | 73 | private final BooleanStateKeyboardInputHandler shoot; 74 | 75 | /** 76 | * Default constructor. 77 | */ 78 | public Billiards() { 79 | super("Billiards"); 80 | 81 | this.left = new BooleanStateKeyboardInputHandler(this.canvas, KeyEvent.VK_LEFT); 82 | this.right = new BooleanStateKeyboardInputHandler(this.canvas, KeyEvent.VK_RIGHT); 83 | this.plus = new BooleanStateKeyboardInputHandler(this.canvas, new Key(KeyEvent.VK_PLUS), new Key(KeyEvent.VK_ADD), new Key(KeyEvent.VK_EQUALS, KeyEvent.SHIFT_DOWN_MASK)); 84 | this.minus = new BooleanStateKeyboardInputHandler(this.canvas, KeyEvent.VK_MINUS, KeyEvent.VK_SUBTRACT); 85 | this.shoot = new BooleanStateKeyboardInputHandler(this.canvas, KeyEvent.VK_S); 86 | 87 | this.left.install(); 88 | this.right.install(); 89 | this.plus.install(); 90 | this.minus.install(); 91 | this.shoot.install(); 92 | } 93 | 94 | /* (non-Javadoc) 95 | * @see org.dyn4j.samples.SimulationFrame#initializeWorld() 96 | */ 97 | @Override 98 | protected void initializeWorld() { 99 | // no gravity on a top-down view of a billiards game 100 | this.world.setGravity(World.ZERO_GRAVITY); 101 | 102 | final double edgeDepth = 0.29 / 2.0; 103 | final double tableWidth = 1.83; 104 | final double tableHeight = 1.12; 105 | 106 | final double halfTableWidth = tableWidth / 2.0; 107 | final double halfTableHeight = tableHeight / 2.0; 108 | final double halfEdgeDepth = edgeDepth / 2.0; 109 | 110 | // 2.25 in diameter = 0.028575 m radius 111 | final double ballRadius = 0.028575; 112 | 113 | // 0.126 oz/in^3 = 217.97925 kg/m^3 114 | final double ballDensity = 217.97925; 115 | 116 | final double ballFriction = 0.08; 117 | final double ballRestitution = 0.9; 118 | 119 | // I wouldn't do this in practice - I'm being lazy and using a body 120 | // to render a green bottom to the billiards table. Instead, you should 121 | // just render the green bottom and not use a body. 122 | SimulationBody bottom = new SimulationBody(new Color(60, 164, 114)); 123 | BodyFixture bf = bottom.addFixture(Geometry.createRectangle(tableWidth, tableHeight), 1.0, 0.0, 0.0); 124 | bf.setFilter(new Filter() { 125 | @Override 126 | public boolean isAllowed(Filter filter) { 127 | return false; 128 | } 129 | }); 130 | bottom.setMass(MassType.INFINITE); 131 | world.addBody(bottom); 132 | 133 | SimulationBody wallRight = new SimulationBody(new Color(150, 75, 0)); 134 | BodyFixture fixture = wallRight.addFixture(Geometry.createRectangle(edgeDepth, tableHeight), 1.0, 0.4, 0.3); 135 | fixture.setRestitutionVelocity(0.0); 136 | wallRight.translate(halfTableWidth - halfEdgeDepth, 0); 137 | wallRight.setMass(MassType.INFINITE); 138 | wallRight.setAtRestDetectionEnabled(false); 139 | world.addBody(wallRight); 140 | 141 | SimulationBody wallLeft = new SimulationBody(new Color(150, 75, 0)); 142 | fixture = wallLeft.addFixture(Geometry.createRectangle(edgeDepth, tableHeight), 1.0, 0.4, 0.3); 143 | fixture.setRestitutionVelocity(0.0); 144 | wallLeft.translate(-halfTableWidth + halfEdgeDepth, 0); 145 | wallLeft.setMass(MassType.INFINITE); 146 | wallLeft.setAtRestDetectionEnabled(false); 147 | world.addBody(wallLeft); 148 | 149 | SimulationBody wallTop = new SimulationBody(new Color(150, 75, 0)); 150 | fixture = wallTop.addFixture(Geometry.createRectangle(tableWidth, edgeDepth), 1.0, 0.4, 0.3); 151 | fixture.setRestitutionVelocity(0.0); 152 | wallTop.translate(0, halfTableHeight - halfEdgeDepth); 153 | wallTop.setMass(MassType.INFINITE); 154 | wallTop.setAtRestDetectionEnabled(false); 155 | world.addBody(wallTop); 156 | 157 | SimulationBody wallBottom = new SimulationBody(new Color(150, 75, 0)); 158 | fixture = wallBottom.addFixture(Geometry.createRectangle(tableWidth, edgeDepth), 1.0, 0.4, 0.3); 159 | fixture.setRestitutionVelocity(0.0); 160 | wallBottom.translate(0, -halfTableHeight + halfEdgeDepth); 161 | wallBottom.setMass(MassType.INFINITE); 162 | wallBottom.setAtRestDetectionEnabled(false); 163 | world.addBody(wallBottom); 164 | 165 | cueBall = new SimulationBody(new Color(255, 255, 255)); 166 | fixture = cueBall.addFixture(Geometry.createCircle(ballRadius), ballDensity, ballFriction, ballRestitution); 167 | fixture.setRestitutionVelocity(0.001); 168 | cueBall.setUserData(BALL_IDENTIFIER); 169 | cueBall.translate(-0.25, 0.0); 170 | cueBall.setLinearDamping(0.8); 171 | cueBall.setAngularDamping(0.8); 172 | cueBall.setMass(MassType.NORMAL); 173 | cueBall.setBullet(true); 174 | this.world.addBody(cueBall); 175 | 176 | cueStick = new SimulationBody(new Color(180, 140, 50)); 177 | cueStick.addFixture(new Polygon( 178 | new Vector2(0.0, 0.008), 179 | new Vector2(-1.0, 0.015), 180 | new Vector2(-1.0, -0.015), 181 | new Vector2(0.0, -0.008))); 182 | cueStick.setMass(MassType.NORMAL); 183 | stickLocation = new Vector2(-0.25, 0.0); 184 | 185 | // billiard colors 186 | Color[] colors = new Color[] { 187 | // solid 188 | new Color(255, 215, 0), 189 | new Color(0, 0, 255), 190 | new Color(255, 0, 0), 191 | new Color(75, 0, 130), 192 | new Color(255, 69, 0), 193 | new Color(34, 139, 34), 194 | new Color(128, 0, 0), 195 | new Color(0, 0, 0), 196 | 197 | // striped (just do a lighter color) 198 | new Color(255, 215, 0).darker(), 199 | new Color(0, 0, 255).darker(), 200 | new Color(255, 0, 0).darker(), 201 | new Color(75, 0, 130).brighter(), 202 | new Color(255, 69, 0).darker(), 203 | new Color(34, 139, 34).brighter(), 204 | new Color(128, 0, 0).brighter(), 205 | new Color(0, 0, 0).brighter() 206 | }; 207 | 208 | final int rackSize = 5; 209 | final double sx = 0.45; 210 | final double sy = -ballRadius; 211 | 212 | // 5 columns 213 | int n = 0; 214 | for (int i = 0; i < rackSize; i++) { 215 | double x = sx - (ballRadius * 2.0 * (double)i); 216 | double columnHeight = ballRadius * 2.0 * (rackSize - i); 217 | double csy = columnHeight / 2.0; 218 | // 5 - i rows 219 | for (int j = 0; j < rackSize - i; j++) { 220 | double y = sy + csy - (ballRadius * 2.0 * j); 221 | 222 | SimulationBody ball = new SimulationBody(colors[n]); 223 | fixture = ball.addFixture(Geometry.createCircle(ballRadius), ballDensity, ballFriction, ballRestitution); 224 | fixture.setRestitutionVelocity(0.005); 225 | ball.setUserData(BALL_IDENTIFIER); 226 | ball.translate(x, y); 227 | ball.setLinearDamping(0.8); 228 | ball.setAngularDamping(0.8); 229 | ball.setMass(MassType.NORMAL); 230 | ball.setBullet(true); 231 | this.world.addBody(ball); 232 | 233 | n++; 234 | } 235 | } 236 | } 237 | 238 | /* (non-Javadoc) 239 | * @see org.dyn4j.samples.framework.SimulationFrame#initializeCamera(org.dyn4j.samples.framework.Camera) 240 | */ 241 | @Override 242 | protected void initializeCamera(Camera camera) { 243 | super.initializeCamera(camera); 244 | camera.scale = 250.0; 245 | } 246 | 247 | /* (non-Javadoc) 248 | * @see org.dyn4j.samples.framework.SimulationFrame#printControls() 249 | */ 250 | @Override 251 | protected void printControls() { 252 | super.printControls(); 253 | 254 | printControl("Rotate Left", "Left", "Use the left key to rotate counter-clockwise"); 255 | printControl("Rotate Right", "Right", "Use the right key to rotate clockwise"); 256 | printControl("Increase Power", "+", "Use the + key to increase the shoot power"); 257 | printControl("Decrease Power", "-", "Use the - key to decrease the shoot power"); 258 | printControl("Shoot", "s", "Use the s key to hit the cue ball"); 259 | } 260 | 261 | /* (non-Javadoc) 262 | * @see org.dyn4j.samples.framework.SimulationFrame#render(java.awt.Graphics2D, double) 263 | */ 264 | @Override 265 | protected void render(Graphics2D g, double elapsedTime) { 266 | super.render(g, elapsedTime); 267 | 268 | // check if all balls are at rest, if so, then reset the cue stick position 269 | if (allBallsAtRest()) { 270 | this.stickLocation = this.cueBall.getWorldCenter(); 271 | } 272 | 273 | Transform tx = new Transform(); 274 | tx.setTranslation(stickLocation.sum(-this.power - 0.05, 0.0)); 275 | tx.rotate(this.angle, stickLocation); 276 | 277 | this.cueStick.setTransform(tx); 278 | this.render(g, elapsedTime, cueStick); 279 | } 280 | 281 | private final boolean allBallsAtRest() { 282 | final int n = this.world.getBodyCount(); 283 | for (int i = 0; i < n; i++) { 284 | SimulationBody b = this.world.getBody(i); 285 | if (b.getUserData() == BALL_IDENTIFIER) { 286 | if (!b.isAtRest()) { 287 | return false; 288 | } 289 | } 290 | } 291 | 292 | return true; 293 | } 294 | 295 | /* (non-Javadoc) 296 | * @see org.dyn4j.samples.framework.SimulationFrame#reset() 297 | */ 298 | @Override 299 | public void reset() { 300 | super.reset(); 301 | 302 | this.angle = 0.0; 303 | this.power = 0.0; 304 | this.stickLocation.zero(); 305 | } 306 | 307 | /* (non-Javadoc) 308 | * @see org.dyn4j.samples.framework.SimulationFrame#handleEvents() 309 | */ 310 | @Override 311 | protected void handleEvents() { 312 | super.handleEvents(); 313 | 314 | if (allBallsAtRest()) { 315 | if (this.left.isActive()) { 316 | this.angle += 0.005; 317 | } 318 | 319 | if (this.right.isActive()) { 320 | this.angle -= 0.005; 321 | } 322 | 323 | if (this.plus.isActive()) { 324 | this.power += 0.005; 325 | } 326 | 327 | if (this.minus.isActive()) { 328 | this.power -= 0.005; 329 | if (this.power <= 0.0) { 330 | this.power = 0.0; 331 | } 332 | } 333 | 334 | if (this.shoot.isActiveButNotHandled()) { 335 | this.shoot.setHasBeenHandled(true); 336 | 337 | if (this.power > 0.0) { 338 | Vector2 v = new Vector2(this.cueStick.getTransform().getRotationAngle()); 339 | v.multiply(this.power * 10.0); 340 | this.cueBall.setAtRest(false); 341 | this.cueBall.setLinearVelocity(v); 342 | this.power = 0.0; 343 | } 344 | } 345 | } 346 | } 347 | 348 | /** 349 | * Entry point for the example application. 350 | * @param args command line arguments 351 | */ 352 | public static void main(String[] args) { 353 | Billiards simulation = new Billiards(); 354 | simulation.run(); 355 | } 356 | } 357 | -------------------------------------------------------------------------------- /src/main/java/org/dyn4j/samples/Bowling.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2022 William Bittle http://www.dyn4j.org/ 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted 6 | * provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, this list of conditions 9 | * and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | * and the following disclaimer in the documentation and/or other materials provided with the 12 | * distribution. 13 | * * Neither the name of dyn4j nor the names of its contributors may be used to endorse or 14 | * promote products derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 23 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | package org.dyn4j.samples; 26 | 27 | import java.util.List; 28 | 29 | import org.dyn4j.collision.CategoryFilter; 30 | import org.dyn4j.dynamics.BodyFixture; 31 | import org.dyn4j.geometry.Geometry; 32 | import org.dyn4j.geometry.Link; 33 | import org.dyn4j.geometry.MassType; 34 | import org.dyn4j.geometry.Vector2; 35 | import org.dyn4j.samples.framework.Camera; 36 | import org.dyn4j.samples.framework.SimulationBody; 37 | import org.dyn4j.samples.framework.SimulationFrame; 38 | 39 | /** 40 | * A scene where a bowling ball hits a set of pins. 41 | *

42 | * The pins can interact with anything in the ALL and BALL groups, but not with themselves. 43 | * @author William Bittle 44 | * @version 5.0.0 45 | * @since 3.2.1 46 | */ 47 | public class Bowling extends SimulationFrame { 48 | /** The serial version id */ 49 | private static final long serialVersionUID = 6102930425312889302L; 50 | 51 | private static final CategoryFilter ALL = new CategoryFilter(1, Long.MAX_VALUE); 52 | private static final CategoryFilter BALL = new CategoryFilter(2, Long.MAX_VALUE); 53 | private static final CategoryFilter PIN = new CategoryFilter(4, 1 | 2 | 8); 54 | private static final CategoryFilter NOT_BALL = new CategoryFilter(8, 1 | 4); 55 | 56 | /** 57 | * Default constructor. 58 | */ 59 | public Bowling() { 60 | super("Bowling"); 61 | } 62 | 63 | /** 64 | * Creates game objects and adds them to the world. 65 | */ 66 | protected void initializeWorld() { 67 | SimulationBody floor = new SimulationBody(); 68 | BodyFixture fixture = floor.addFixture(Geometry.createRectangle(15.0, 0.2), 0.9); 69 | fixture.setFilter(ALL); 70 | floor.setMass(MassType.INFINITE); 71 | this.world.addBody(floor); 72 | 73 | SimulationBody wall = new SimulationBody(); 74 | fixture = wall.addFixture(Geometry.createRectangle(0.2, 3.0)); 75 | fixture.setFilter(NOT_BALL); 76 | wall.setMass(MassType.INFINITE); 77 | wall.translate(7.0, 1.5); 78 | this.world.addBody(wall); 79 | 80 | SimulationBody top = new SimulationBody(); 81 | fixture = top.addFixture(Geometry.createRectangle(2.0, 0.2)); 82 | fixture.setFilter(ALL); 83 | fixture = top.addFixture(Geometry.createRectangle(1.0, 0.2)); 84 | fixture.setFilter(ALL); 85 | fixture.getShape().rotate(Math.toDegrees(60)); 86 | fixture.getShape().translate(-1.25, -0.25); 87 | top.setMass(MassType.INFINITE); 88 | top.translate(6.0, 2.0); 89 | this.world.addBody(top); 90 | 91 | SimulationBody channel = new SimulationBody(); 92 | Vector2[] verts = new Vector2[] { 93 | new Vector2(7.0, 0.5), 94 | new Vector2(8.0, 0.5), 95 | new Vector2(8.5, 0.25), 96 | new Vector2(9.0, 0.0), 97 | new Vector2(8.5, -0.25), 98 | new Vector2(8.0, -0.5), 99 | new Vector2(-8.0, -1.0), 100 | new Vector2(-9.0, -0.5), 101 | new Vector2(-10.0, 0.0), 102 | new Vector2(-9.0, 0.5), 103 | new Vector2(-8.0, 1.0) 104 | }; 105 | List links = Geometry.createLinks(verts, false); 106 | for (Link link : links) { 107 | channel.addFixture(link); 108 | } 109 | channel.setMass(MassType.INFINITE); 110 | this.world.addBody(channel); 111 | 112 | SimulationBody bowlingBall = new SimulationBody(); 113 | fixture = new BodyFixture(Geometry.createCircle(0.109)); 114 | fixture.setDensity(194.82); 115 | fixture.setRestitution(0.5); 116 | fixture.setFilter(BALL); 117 | bowlingBall.addFixture(fixture); 118 | bowlingBall.setMass(MassType.NORMAL); 119 | bowlingBall.setLinearVelocity(new Vector2(10.0, 0.0)); 120 | bowlingBall.setAngularDamping(0.5); 121 | bowlingBall.translate(-3.0, 0.1); 122 | this.world.addBody(bowlingBall); 123 | 124 | // create some pins 125 | double x = 6; 126 | for (int i = 0; i < 10; i++) { 127 | SimulationBody pin = new SimulationBody(); 128 | BodyFixture bf = pin.addFixture(Geometry.createRectangle(0.1, 0.5), 2.0, 0.5, 0.6); 129 | bf.setFilter(PIN); 130 | pin.setMass(MassType.NORMAL); 131 | pin.translate(x, 0.1 + 0.25); 132 | this.world.addBody(pin); 133 | x += 0.06; 134 | } 135 | } 136 | 137 | @Override 138 | protected void initializeCamera(Camera camera) { 139 | super.initializeCamera(camera); 140 | camera.scale = 64.0; 141 | camera.offsetX = -150.0; 142 | camera.offsetY = -100.0; 143 | } 144 | 145 | /** 146 | * Entry point for the example application. 147 | * @param args command line arguments 148 | */ 149 | public static void main(String[] args) { 150 | Bowling simulation = new Bowling(); 151 | simulation.run(); 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /src/main/java/org/dyn4j/samples/Bridge.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2022 William Bittle http://www.dyn4j.org/ 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted 6 | * provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, this list of conditions 9 | * and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | * and the following disclaimer in the documentation and/or other materials provided with the 12 | * distribution. 13 | * * Neither the name of dyn4j nor the names of its contributors may be used to endorse or 14 | * promote products derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 23 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | package org.dyn4j.samples; 26 | 27 | import org.dyn4j.dynamics.BodyFixture; 28 | import org.dyn4j.dynamics.joint.RevoluteJoint; 29 | import org.dyn4j.geometry.Convex; 30 | import org.dyn4j.geometry.Geometry; 31 | import org.dyn4j.geometry.MassType; 32 | import org.dyn4j.geometry.Vector2; 33 | import org.dyn4j.samples.framework.Camera; 34 | import org.dyn4j.samples.framework.SimulationBody; 35 | import org.dyn4j.samples.framework.SimulationFrame; 36 | 37 | /** 38 | * A scene where we create a suspension bridge via RevoluteJoints. 39 | * @author William Bittle 40 | * @version 5.0.0 41 | * @since 4.1.1 42 | */ 43 | public class Bridge extends SimulationFrame { 44 | /** The serial version id */ 45 | private static final long serialVersionUID = -2350301592218819726L; 46 | 47 | /** 48 | * Default constructor. 49 | */ 50 | public Bridge() { 51 | super("Bridge"); 52 | } 53 | 54 | /** 55 | * Creates game objects and adds them to the world. 56 | */ 57 | protected void initializeWorld() { 58 | // Ground 59 | SimulationBody ground = new SimulationBody(); 60 | ground.addFixture(Geometry.createRectangle(50.0, 1.0)); 61 | ground.translate(new Vector2(0.6875, -8.75)); 62 | ground.setMass(MassType.INFINITE); 63 | world.addBody(ground); 64 | 65 | final double y = 2.0; 66 | final int n = 20; 67 | final double hn = n / 2.0; 68 | final double w = 1.0; 69 | final double hw = w / 2.0; 70 | final double h = 0.25; 71 | 72 | SimulationBody prev = ground; 73 | for (int i = 0; i < n; i++) { 74 | SimulationBody section = new SimulationBody(); 75 | {// Fixture1 76 | Convex c = Geometry.createRectangle(w, h); 77 | BodyFixture bf = new BodyFixture(c); 78 | section.addFixture(bf); 79 | } 80 | section.translate(new Vector2(i - hn, y)); 81 | section.setMass(MassType.NORMAL); 82 | world.addBody(section); 83 | 84 | // connect the previous body with this body 85 | RevoluteJoint rj = new RevoluteJoint(prev, section, new Vector2(i - hn - hw, y)); 86 | world.addJoint(rj); 87 | 88 | prev = section; 89 | } 90 | 91 | // connect the last body with the ground 92 | RevoluteJoint rj = new RevoluteJoint(prev, ground, new Vector2(hn + hw, y)); 93 | world.addJoint(rj); 94 | } 95 | 96 | /* (non-Javadoc) 97 | * @see org.dyn4j.samples.framework.SimulationFrame#initializeCamera(org.dyn4j.samples.framework.Camera) 98 | */ 99 | @Override 100 | protected void initializeCamera(Camera camera) { 101 | super.initializeCamera(camera); 102 | camera.scale = 32.0; 103 | } 104 | 105 | /** 106 | * Entry point for the example application. 107 | * @param args command line arguments 108 | */ 109 | public static void main(String[] args) { 110 | Bridge simulation = new Bridge(); 111 | simulation.run(); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/main/java/org/dyn4j/samples/Bucket.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2022 William Bittle http://www.dyn4j.org/ 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted 6 | * provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, this list of conditions 9 | * and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | * and the following disclaimer in the documentation and/or other materials provided with the 12 | * distribution. 13 | * * Neither the name of dyn4j nor the names of its contributors may be used to endorse or 14 | * promote products derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 23 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | package org.dyn4j.samples; 26 | 27 | import java.util.Random; 28 | 29 | import org.dyn4j.geometry.Convex; 30 | import org.dyn4j.geometry.Geometry; 31 | import org.dyn4j.geometry.MassType; 32 | import org.dyn4j.geometry.Vector2; 33 | import org.dyn4j.samples.framework.Camera; 34 | import org.dyn4j.samples.framework.SimulationBody; 35 | import org.dyn4j.samples.framework.SimulationFrame; 36 | 37 | /** 38 | * A scene where we fill a "bucket" with shapes. 39 | * @author William Bittle 40 | * @since 5.0.0 41 | * @version 4.1.1 42 | */ 43 | public class Bucket extends SimulationFrame { 44 | /** The serial version id */ 45 | private static final long serialVersionUID = -3837218136220591307L; 46 | 47 | /** 48 | * Default constructor. 49 | */ 50 | public Bucket() { 51 | super("Bucket"); 52 | } 53 | 54 | /** 55 | * Creates game objects and adds them to the world. 56 | */ 57 | protected void initializeWorld() { 58 | // world.getSettings().setStepFrequency(1.0/30.0); 59 | // world.getSettings().setPositionConstraintSolverIterations(10); 60 | // world.getSettings().setVelocityConstraintSolverIterations(10); 61 | 62 | // Bottom 63 | SimulationBody bucketBottom = new SimulationBody(); 64 | bucketBottom.addFixture(Geometry.createRectangle(15.0, 1.0)); 65 | bucketBottom.setMass(MassType.INFINITE); 66 | world.addBody(bucketBottom); 67 | 68 | // Left-Side 69 | SimulationBody bucketLeft = new SimulationBody(); 70 | bucketLeft.addFixture(Geometry.createRectangle(1.0, 15.0)); 71 | bucketLeft.translate(new Vector2(-7.5, 7.0)); 72 | bucketLeft.setMass(MassType.INFINITE); 73 | world.addBody(bucketLeft); 74 | 75 | // Right-Side 76 | SimulationBody bucketRight = new SimulationBody(); 77 | bucketRight.addFixture(Geometry.createRectangle(1.0, 15.0)); 78 | bucketRight.translate(new Vector2(7.5, 7.0)); 79 | bucketRight.setMass(MassType.INFINITE); 80 | world.addBody(bucketRight); 81 | 82 | Random r = new Random(23); 83 | double xmin = -7.0; 84 | double xmax = 7.0; 85 | double ymin = 0.5; 86 | double ymax = 20.0; 87 | double maxSize = 0.6; 88 | double minSize = 0.2; 89 | 90 | for (int i = 0; i < 1000; i++) { 91 | double size = r.nextDouble() * maxSize + minSize; 92 | 93 | Convex c = null; 94 | 95 | int type = r.nextInt(2); 96 | switch (type) { 97 | case 0: 98 | c = Geometry.createRectangle(size, size); 99 | break; 100 | case 1: 101 | default: 102 | c = Geometry.createCircle(size * 0.5); 103 | break; 104 | } 105 | 106 | double x = r.nextDouble() * xmax * 2 + xmin; 107 | double y = r.nextDouble() * ymax + ymin; 108 | 109 | SimulationBody b = new SimulationBody(); 110 | b.addFixture(c); 111 | b.translate(new Vector2(x, y)); 112 | b.setMass(MassType.NORMAL); 113 | world.addBody(b); 114 | } 115 | } 116 | 117 | /* (non-Javadoc) 118 | * @see org.dyn4j.samples.framework.SimulationFrame#initializeCamera(org.dyn4j.samples.framework.Camera) 119 | */ 120 | @Override 121 | protected void initializeCamera(Camera camera) { 122 | super.initializeCamera(camera); 123 | camera.scale = 32.0; 124 | camera.offsetY = -200; 125 | } 126 | 127 | /** 128 | * Entry point for the example application. 129 | * @param args command line arguments 130 | */ 131 | public static void main(String[] args) { 132 | Bucket simulation = new Bucket(); 133 | simulation.run(); 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/main/java/org/dyn4j/samples/Concave.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2022 William Bittle http://www.dyn4j.org/ 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted 6 | * provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, this list of conditions 9 | * and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | * and the following disclaimer in the documentation and/or other materials provided with the 12 | * distribution. 13 | * * Neither the name of dyn4j nor the names of its contributors may be used to endorse or 14 | * promote products derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 23 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | package org.dyn4j.samples; 26 | 27 | import org.dyn4j.geometry.Convex; 28 | import org.dyn4j.geometry.Geometry; 29 | import org.dyn4j.geometry.MassType; 30 | import org.dyn4j.geometry.Vector2; 31 | import org.dyn4j.samples.framework.Camera; 32 | import org.dyn4j.samples.framework.SimulationBody; 33 | import org.dyn4j.samples.framework.SimulationFrame; 34 | 35 | /** 36 | * An example of using a "Concave" body. 37 | * @author William Bittle 38 | * @since 5.0.0 39 | * @version 4.1.1 40 | */ 41 | public class Concave extends SimulationFrame { 42 | /** The serial version id */ 43 | private static final long serialVersionUID = 8797361529527319100L; 44 | 45 | /** 46 | * Default constructor. 47 | */ 48 | public Concave() { 49 | super("Concave"); 50 | } 51 | 52 | /* (non-Javadoc) 53 | * @see org.dyn4j.samples.framework.SimulationFrame#initializeWorld() 54 | */ 55 | protected void initializeWorld() { 56 | // Ground 57 | SimulationBody ground = new SimulationBody(); 58 | ground.addFixture(Geometry.createRectangle(15.0, 1.0)); 59 | ground.setMass(MassType.INFINITE); 60 | world.addBody(ground); 61 | 62 | // Concave 63 | SimulationBody table = new SimulationBody(); 64 | { 65 | Convex c = Geometry.createRectangle(3.0, 1.0); 66 | c.translate(new Vector2(0.0, 0.5)); 67 | table.addFixture(c); 68 | } 69 | { 70 | Convex c = Geometry.createRectangle(1.0, 1.0); 71 | c.translate(new Vector2(-1.0, -0.5)); 72 | table.addFixture(c); 73 | } 74 | { 75 | Convex c = Geometry.createRectangle(1.0, 1.0); 76 | c.translate(new Vector2(1.0, -0.5)); 77 | table.addFixture(c); 78 | } 79 | table.translate(new Vector2(0.0, 4.0)); 80 | table.setMass(MassType.NORMAL); 81 | world.addBody(table); 82 | 83 | // Body3 84 | SimulationBody box = new SimulationBody(); 85 | box.addFixture(Geometry.createSquare(0.5)); 86 | box.translate(new Vector2(0.0, 1.0)); 87 | box.setMass(MassType.NORMAL); 88 | world.addBody(box); 89 | } 90 | 91 | @Override 92 | protected void initializeCamera(Camera camera) { 93 | super.initializeCamera(camera); 94 | camera.scale = 64.0; 95 | camera.offsetY = -200.0; 96 | } 97 | 98 | /** 99 | * Entry point for the example application. 100 | * @param args command line arguments 101 | */ 102 | public static void main(String[] args) { 103 | Concave simulation = new Concave(); 104 | simulation.run(); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/main/java/org/dyn4j/samples/Crank.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2022 William Bittle http://www.dyn4j.org/ 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted 6 | * provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, this list of conditions 9 | * and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | * and the following disclaimer in the documentation and/or other materials provided with the 12 | * distribution. 13 | * * Neither the name of dyn4j nor the names of its contributors may be used to endorse or 14 | * promote products derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 23 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | package org.dyn4j.samples; 26 | 27 | import org.dyn4j.dynamics.joint.PrismaticJoint; 28 | import org.dyn4j.dynamics.joint.RevoluteJoint; 29 | import org.dyn4j.geometry.Geometry; 30 | import org.dyn4j.geometry.MassType; 31 | import org.dyn4j.geometry.Vector2; 32 | import org.dyn4j.samples.framework.Camera; 33 | import org.dyn4j.samples.framework.SimulationBody; 34 | import org.dyn4j.samples.framework.SimulationFrame; 35 | 36 | /** 37 | * A scene that replicates a piston in an ICE. 38 | * @author William Bittle 39 | * @since 5.0.0 40 | * @version 4.1.1 41 | */ 42 | public class Crank extends SimulationFrame { 43 | /** The serial version id */ 44 | private static final long serialVersionUID = -602182516495632849L; 45 | 46 | /** 47 | * Default constructor. 48 | */ 49 | public Crank() { 50 | super("Crank"); 51 | } 52 | 53 | /* (non-Javadoc) 54 | * @see org.dyn4j.samples.framework.SimulationFrame#initializeWorld() 55 | */ 56 | protected void initializeWorld() { 57 | SimulationBody ground = new SimulationBody(); 58 | ground.addFixture(Geometry.createRectangle(10.0, 0.5)); 59 | ground.setMass(MassType.INFINITE); 60 | world.addBody(ground); 61 | 62 | // piston+crank 63 | 64 | SimulationBody crank = new SimulationBody(); 65 | crank.addFixture(Geometry.createRectangle(0.5, 2.0), 2.0, 0.0, 0.0); 66 | crank.translate(new Vector2(0.0, 5.0)); 67 | crank.setMass(MassType.NORMAL); 68 | world.addBody(crank); 69 | 70 | SimulationBody rod = new SimulationBody(); 71 | rod.addFixture(Geometry.createRectangle(0.5, 4.0), 2.0, 0.0, 0.0); 72 | rod.translate(new Vector2(0.0, 7.5)); 73 | rod.setMass(MassType.NORMAL); 74 | world.addBody(rod); 75 | 76 | SimulationBody piston = new SimulationBody(); 77 | piston.addFixture(Geometry.createRectangle(1.5, 1.5), 2.0, 0.0, 0.0); 78 | piston.translate(new Vector2(0.0, 9.75)); 79 | piston.setMass(MassType.FIXED_ANGULAR_VELOCITY); 80 | world.addBody(piston); 81 | 82 | // provides the motion 83 | RevoluteJoint crankShaftJoint = new RevoluteJoint(ground, crank, new Vector2(0.0, 4.25)); 84 | crankShaftJoint.setMotorEnabled(true); 85 | crankShaftJoint.setMotorSpeed(Math.toRadians(180.0)); 86 | crankShaftJoint.setMaximumMotorTorque(10000.0); 87 | world.addJoint(crankShaftJoint); 88 | 89 | // links the crank to the rod 90 | RevoluteJoint crankToRodJoint = new RevoluteJoint(crank, rod, new Vector2(0.0, 5.75)); 91 | world.addJoint(crankToRodJoint); 92 | 93 | // links the rod to the piston 94 | RevoluteJoint rodToPistonJoint = new RevoluteJoint(rod, piston, new Vector2(0.0, 9.25)); 95 | world.addJoint(rodToPistonJoint); 96 | 97 | // keeps the piston moving along the y-axis 98 | PrismaticJoint pistonPathJoint = new PrismaticJoint(ground, piston, new Vector2(0.0, 9.75), new Vector2(0.0, 1.0)); 99 | world.addJoint(pistonPathJoint); 100 | } 101 | 102 | /* (non-Javadoc) 103 | * @see org.dyn4j.samples.framework.SimulationFrame#initializeCamera(org.dyn4j.samples.framework.Camera) 104 | */ 105 | @Override 106 | protected void initializeCamera(Camera camera) { 107 | super.initializeCamera(camera); 108 | camera.scale = 32.0; 109 | camera.offsetY = -200.0; 110 | } 111 | 112 | /** 113 | * Entry point for the example application. 114 | * @param args command line arguments 115 | */ 116 | public static void main(String[] args) { 117 | Crank simulation = new Crank(); 118 | simulation.run(); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/main/java/org/dyn4j/samples/Decomposition.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2022 William Bittle http://www.dyn4j.org/ 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted 6 | * provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, this list of conditions 9 | * and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | * and the following disclaimer in the documentation and/or other materials provided with the 12 | * distribution. 13 | * * Neither the name of dyn4j nor the names of its contributors may be used to endorse or 14 | * promote products derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 23 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | package org.dyn4j.samples; 26 | 27 | import java.util.List; 28 | 29 | import org.dyn4j.geometry.Convex; 30 | import org.dyn4j.geometry.Geometry; 31 | import org.dyn4j.geometry.MassType; 32 | import org.dyn4j.geometry.Vector2; 33 | import org.dyn4j.geometry.decompose.Bayazit; 34 | import org.dyn4j.geometry.decompose.Decomposer; 35 | import org.dyn4j.geometry.decompose.EarClipping; 36 | import org.dyn4j.geometry.decompose.SweepLine; 37 | import org.dyn4j.samples.framework.Camera; 38 | import org.dyn4j.samples.framework.SimulationBody; 39 | import org.dyn4j.samples.framework.SimulationFrame; 40 | 41 | /** 42 | * An example of using the convex decomposition classes to 43 | * build a set of convex objects from a simple polygon. 44 | *

45 | * NOTE: Please review the definition of Simple Polygon. 46 | * @author William Bittle 47 | * @since 5.0.0 48 | * @version 4.1.1 49 | */ 50 | public class Decomposition extends SimulationFrame { 51 | /** The serial version id */ 52 | private static final long serialVersionUID = 805187905337457811L; 53 | 54 | /** 55 | * Default constructor. 56 | */ 57 | public Decomposition() { 58 | super("Decomposition"); 59 | } 60 | 61 | /* (non-Javadoc) 62 | * @see org.dyn4j.samples.framework.SimulationFrame#initializeWorld() 63 | */ 64 | protected void initializeWorld() { 65 | 66 | // Ground 67 | SimulationBody ground = new SimulationBody(); 68 | ground.addFixture(Geometry.createRectangle(15.0, 1.0)); 69 | ground.setMass(MassType.INFINITE); 70 | world.addBody(ground); 71 | 72 | // a (lowercase) "d" shape 73 | Vector2[] dVerticies = new Vector2[] { 74 | new Vector2(-0.703125, 0.859375), 75 | new Vector2(-0.828125, 0.625), 76 | new Vector2(-0.875, 0.25), 77 | new Vector2(-0.625, 0.0625), 78 | new Vector2(-0.359375, 0.046875), 79 | new Vector2(-0.1875, 0.1875), 80 | new Vector2(-0.21875, 0.0), 81 | new Vector2(0.0, -0.0), 82 | new Vector2(-0.015625, 1.625), 83 | new Vector2(-0.171875, 1.640625), 84 | new Vector2(-0.171875, 0.671875), 85 | new Vector2(-0.375, 0.84375) 86 | }; 87 | 88 | Decomposer bayazit = new Bayazit(); 89 | List parts = bayazit.decompose(dVerticies); 90 | SimulationBody d = new SimulationBody(); 91 | for (Convex c : parts) { 92 | d.addFixture(c); 93 | } 94 | d.rotate(Math.toRadians(-0.17453292519943292)); 95 | d.translate(new Vector2(-1.950745294864571, 0.4726801090249715)); 96 | d.setMass(MassType.NORMAL); 97 | world.addBody(d); 98 | 99 | // a (lowercase) "y" shape 100 | Vector2[] yVerticies = new Vector2[] { 101 | new Vector2(0.53125, -1.390625), 102 | new Vector2(1.1171875, -0.546875), 103 | new Vector2(1.703125, 0.296875), 104 | new Vector2(1.421875, 0.3125), 105 | new Vector2(1.015625, -0.34375), 106 | new Vector2(0.703125, 0.28125), 107 | new Vector2(0.4375, 0.265625), 108 | new Vector2(0.8125, -0.484375), 109 | new Vector2(0.25, -1.1875) 110 | }; 111 | 112 | Decomposer sweep = new SweepLine(); 113 | parts = sweep.decompose(yVerticies); 114 | SimulationBody y = new SimulationBody(); 115 | for (Convex c : parts) { 116 | y.addFixture(c); 117 | } 118 | y.getFixture(2).setSensor(true); 119 | y.translate(new Vector2(-2.1822787101720906, 1.4407710711648776)); 120 | y.setMass(MassType.NORMAL); 121 | world.addBody(y); 122 | 123 | // a (lowercase) "n" shape 124 | Vector2[] nVerticies = new Vector2[] { 125 | new Vector2(-0.03125, 0.984375), 126 | new Vector2(-0.015625, -0.015625), 127 | new Vector2(0.140625, -0.015625), 128 | new Vector2(0.15625, 0.375), 129 | new Vector2(0.34375, 0.578125), 130 | new Vector2(0.5, 0.71875), 131 | new Vector2(0.6875, 0.671875), 132 | new Vector2(0.765625, 0.5625), 133 | new Vector2(0.734375, -0.0), 134 | new Vector2(1.015625, -0.015625), 135 | new Vector2(1.046875, 0.640625), 136 | new Vector2(0.953125, 0.84375), 137 | new Vector2(0.78125, 0.96875), 138 | new Vector2(0.5, 0.96875), 139 | new Vector2(0.296875, 0.84375), 140 | new Vector2(0.1875, 0.734375), 141 | new Vector2(0.1875, 0.984375), 142 | }; 143 | 144 | Decomposer ear = new EarClipping(); 145 | parts = ear.decompose(nVerticies); 146 | SimulationBody n = new SimulationBody(); 147 | for (Convex c : parts) { 148 | n.addFixture(c); 149 | } 150 | n.translate(new Vector2(-0.5112465256848169, 0.6500452079566003)); 151 | n.setMass(MassType.NORMAL); 152 | world.addBody(n); 153 | 154 | // a "4" shape 155 | Vector2[] fourVerticies = new Vector2[] { 156 | new Vector2(0.8125, 0.8125), 157 | new Vector2(0.828125, 0.046875), 158 | new Vector2(1.125, 0.046875), 159 | new Vector2(1.125, 1.828125), 160 | new Vector2(0.859375, 1.828125), 161 | new Vector2(-0.21875, 0.8125) 162 | }; 163 | 164 | parts = bayazit.decompose(fourVerticies); 165 | SimulationBody four = new SimulationBody(); 166 | for (Convex c : parts) { 167 | four.addFixture(c); 168 | } 169 | four.translate(new Vector2(0.26865946239058014, 0.9649433050584864)); 170 | four.setMass(MassType.NORMAL); 171 | world.addBody(four); 172 | 173 | // a (lowercase) "j" shape 174 | Vector2[] jVerticies = new Vector2[] { 175 | new Vector2(0.90625, 0.203125), 176 | new Vector2(0.96875, 0.34375), 177 | new Vector2(1.0, 1.21875), 178 | new Vector2(0.78125, 1.265625), 179 | new Vector2(0.734375, 0.34375), 180 | new Vector2(0.5625, 0.296875), 181 | new Vector2(0.34375, 0.296875), 182 | new Vector2(0.234375, 0.4375), 183 | new Vector2(0.234375, 0.65625), 184 | new Vector2(0.046875, 0.65625), 185 | new Vector2(0.046875, 0.5), 186 | new Vector2(0.078125, 0.28125), 187 | new Vector2(0.203125, 0.109375), 188 | new Vector2(0.46875, 0.046875), 189 | new Vector2(0.734375, 0.109375), 190 | 191 | }; 192 | 193 | parts = bayazit.decompose(jVerticies); 194 | SimulationBody j = new SimulationBody(); 195 | for (Convex c : parts) { 196 | j.addFixture(c); 197 | } 198 | j.translate(new Vector2(0.8752422480620154, 0.4841370269037847)); 199 | j.setMass(MassType.NORMAL); 200 | world.addBody(j); 201 | } 202 | 203 | /* (non-Javadoc) 204 | * @see org.dyn4j.samples.framework.SimulationFrame#initializeCamera(org.dyn4j.samples.framework.Camera) 205 | */ 206 | @Override 207 | protected void initializeCamera(Camera camera) { 208 | super.initializeCamera(camera); 209 | camera.scale = 64.0; 210 | camera.offsetY = -200.0; 211 | } 212 | 213 | /** 214 | * Entry point for the example application. 215 | * @param args command line arguments 216 | */ 217 | public static void main(String[] args) { 218 | Decomposition simulation = new Decomposition(); 219 | simulation.run(); 220 | } 221 | } 222 | -------------------------------------------------------------------------------- /src/main/java/org/dyn4j/samples/Destructible.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2022 William Bittle http://www.dyn4j.org/ 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted 6 | * provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, this list of conditions 9 | * and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | * and the following disclaimer in the documentation and/or other materials provided with the 12 | * distribution. 13 | * * Neither the name of dyn4j nor the names of its contributors may be used to endorse or 14 | * promote products derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 23 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | package org.dyn4j.samples; 26 | 27 | import java.util.ArrayList; 28 | import java.util.List; 29 | 30 | import org.dyn4j.dynamics.Body; 31 | import org.dyn4j.dynamics.contact.Contact; 32 | import org.dyn4j.dynamics.joint.Joint; 33 | import org.dyn4j.dynamics.joint.WeldJoint; 34 | import org.dyn4j.geometry.Convex; 35 | import org.dyn4j.geometry.Geometry; 36 | import org.dyn4j.geometry.MassType; 37 | import org.dyn4j.geometry.Transform; 38 | import org.dyn4j.geometry.Vector2; 39 | import org.dyn4j.geometry.Wound; 40 | import org.dyn4j.samples.framework.Camera; 41 | import org.dyn4j.samples.framework.SimulationBody; 42 | import org.dyn4j.samples.framework.SimulationFrame; 43 | import org.dyn4j.world.ContactCollisionData; 44 | import org.dyn4j.world.listener.ContactListener; 45 | import org.dyn4j.world.listener.ContactListenerAdapter; 46 | 47 | /** 48 | * An example of destruction of bodies and joints 49 | * @author William Bittle 50 | * @since 5.0.0 51 | * @version 4.1.1 52 | */ 53 | public class Destructible extends SimulationFrame { 54 | private static final long serialVersionUID = -3302959427805814281L; 55 | 56 | public Destructible() { 57 | super("Destructible"); 58 | } 59 | 60 | /** 61 | * Extends the contact counter to implement the destruction 62 | * of a joint when a contact is encountered. Normally you would just 63 | * extend the {@link ContactListener} interface. 64 | * @author William Bittle 65 | */ 66 | public class Destructor extends ContactListenerAdapter { 67 | /** Used to flag that the joint has been removed */ 68 | private boolean removed = false; 69 | 70 | /** Used to flag that the test body has been destroyed */ 71 | private boolean broken = false; 72 | 73 | @Override 74 | public void begin(ContactCollisionData collision, Contact contact) { 75 | super.begin(collision, contact); 76 | 77 | // when a contact is added 78 | if (!this.removed) { 79 | Body jb1 = joint.getBody1(); 80 | Body jb2 = joint.getBody2(); 81 | Body b1 = collision.getBody1(); 82 | Body b2 = collision.getBody2(); 83 | 84 | // check the bodies involved 85 | if (b2 == jb1 || b2 == jb2 || b1 == jb1 || b1 == jb2) { 86 | // remove the joint 87 | toDeleteJoints.add(joint); 88 | this.removed = true; 89 | } 90 | } 91 | 92 | if (!this.broken) { 93 | Body b1 = collision.getBody1(); 94 | Body b2 = collision.getBody2(); 95 | 96 | // check the bodies involved 97 | if (b2 == icosigon || b1 == icosigon) { 98 | // remove the body from the world 99 | toDeleteBodies.add(icosigon); 100 | 101 | // make the test body into triangles 102 | 103 | // get the velocity 104 | Vector2 v = icosigon.getLinearVelocity().copy(); 105 | // half the velocity to give the effect of a broken body 106 | v.multiply(0.5); 107 | 108 | Convex convex = icosigon.getFixture(0).getShape(); 109 | Transform tx = icosigon.getTransform(); 110 | Vector2 center = convex.getCenter(); 111 | // we assume its a unit circle polygon to make 112 | // tessellation easy 113 | Vector2[] vertices = ((Wound) convex).getVertices(); 114 | int size = vertices.length; 115 | for (int i = 0; i < size; i++) { 116 | // get the first and second vertices 117 | Vector2 p1 = vertices[i]; 118 | Vector2 p2 = vertices[i + 1 == size ? 0 : i + 1]; 119 | // create a body for the triangle 120 | SimulationBody b = new SimulationBody(icosigon.getColor()); 121 | b.addFixture(Geometry.createTriangle(p1, p2, center), 1.0, 0.3, 0.0); 122 | b.setMass(MassType.NORMAL); 123 | // copy over the transform 124 | b.setTransform(tx.copy()); 125 | // copy over the velocity 126 | b.setLinearVelocity(v.copy()); 127 | b.setUserData("Piece" + (i + 1)); 128 | // add the new body to the world 129 | toAddBodies.add(b); 130 | } 131 | 132 | this.broken = true; 133 | 134 | // set the requires setMass flag 135 | world.setUpdateRequired(true); 136 | 137 | // don't allow the contact 138 | collision.getContactConstraint().setEnabled(false); 139 | } 140 | } 141 | } 142 | } 143 | 144 | /** The floor body */ 145 | private SimulationBody floor; 146 | 147 | /** The 20 sided body */ 148 | private SimulationBody icosigon; 149 | 150 | /** The weld joint */ 151 | private WeldJoint joint; 152 | 153 | /** The destrution class */ 154 | private Destructor destructor; 155 | 156 | // buffer the deletes/adds 157 | 158 | private List> toDeleteJoints = new ArrayList>(); 159 | private List toDeleteBodies = new ArrayList(); 160 | private List toAddBodies = new ArrayList(); 161 | 162 | /* (non-Javadoc) 163 | * @see org.dyn4j.samples.framework.SimulationFrame#initializeWorld() 164 | */ 165 | @Override 166 | public void initializeWorld() { 167 | 168 | // create the floor 169 | this.floor = new SimulationBody(); 170 | this.floor.addFixture(Geometry.createRectangle(15.0, 1.0)); 171 | this.floor.setMass(MassType.INFINITE); 172 | this.floor.setUserData("Floor"); 173 | 174 | // create the weld joint bodies 175 | SimulationBody top = new SimulationBody(); 176 | top.addFixture(Geometry.createRectangle(0.5, 1.0)); 177 | top.setMass(MassType.NORMAL); 178 | top.translate(0.0, 3.0); 179 | top.getLinearVelocity().set(2.0, 0.0); 180 | top.setUserData("Top"); 181 | 182 | SimulationBody bot = new SimulationBody(); 183 | bot.addFixture(Geometry.createRectangle(0.5, 1.0)); 184 | bot.setMass(MassType.NORMAL); 185 | bot.translate(0.0, 2.0); 186 | bot.setUserData("Bottom"); 187 | 188 | this.joint = new WeldJoint(top, bot, new Vector2(0.0, 2.5)); 189 | this.joint.setUserData("WeldJoint1"); 190 | 191 | this.icosigon = new SimulationBody(); 192 | this.icosigon.addFixture(Geometry.createUnitCirclePolygon(20, 1.0)); 193 | this.icosigon.setMass(MassType.NORMAL); 194 | this.icosigon.translate(-2.5, 2.0); 195 | this.icosigon.setUserData("Icosigon"); 196 | 197 | this.destructor = new Destructor(); 198 | 199 | this.world.addBody(this.floor); 200 | this.world.addBody(this.icosigon); 201 | this.world.addBody(top); 202 | this.world.addBody(bot); 203 | this.world.addJoint(this.joint); 204 | this.world.addContactListener(this.destructor); 205 | } 206 | 207 | /* (non-Javadoc) 208 | * @see org.dyn4j.samples.framework.SimulationFrame#initializeCamera(org.dyn4j.samples.framework.Camera) 209 | */ 210 | @Override 211 | protected void initializeCamera(Camera camera) { 212 | super.initializeCamera(camera); 213 | camera.scale = 64.0; 214 | } 215 | 216 | /* (non-Javadoc) 217 | * @see org.dyn4j.samples.framework.SimulationFrame#handleEvents() 218 | */ 219 | @Override 220 | protected void handleEvents() { 221 | super.handleEvents(); 222 | 223 | for (Joint joint : this.toDeleteJoints) { 224 | this.world.removeJoint(joint); 225 | } 226 | this.toDeleteJoints.clear(); 227 | 228 | for (SimulationBody body : this.toDeleteBodies) { 229 | this.world.removeBody(body); 230 | } 231 | this.toDeleteBodies.clear(); 232 | 233 | for (SimulationBody body : this.toAddBodies) { 234 | this.world.addBody(body); 235 | } 236 | this.toAddBodies.clear(); 237 | } 238 | 239 | /** 240 | * Entry point for the example application. 241 | * @param args command line arguments 242 | */ 243 | public static void main(String[] args) { 244 | Destructible simulation = new Destructible(); 245 | simulation.run(); 246 | } 247 | } -------------------------------------------------------------------------------- /src/main/java/org/dyn4j/samples/Images.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2022 William Bittle http://www.dyn4j.org/ 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted 6 | * provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, this list of conditions 9 | * and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | * and the following disclaimer in the documentation and/or other materials provided with the 12 | * distribution. 13 | * * Neither the name of dyn4j nor the names of its contributors may be used to endorse or 14 | * promote products derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 23 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | package org.dyn4j.samples; 26 | 27 | import java.awt.Color; 28 | import java.awt.Graphics2D; 29 | import java.awt.image.BufferedImage; 30 | import java.io.IOException; 31 | 32 | import javax.imageio.ImageIO; 33 | 34 | import org.dyn4j.dynamics.BodyFixture; 35 | import org.dyn4j.geometry.Circle; 36 | import org.dyn4j.geometry.Convex; 37 | import org.dyn4j.geometry.Geometry; 38 | import org.dyn4j.geometry.MassType; 39 | import org.dyn4j.geometry.Rectangle; 40 | import org.dyn4j.geometry.Vector2; 41 | import org.dyn4j.samples.framework.Camera; 42 | import org.dyn4j.samples.framework.SimulationBody; 43 | import org.dyn4j.samples.framework.SimulationFrame; 44 | 45 | /** 46 | * A simple scene illustrating the mapping of images to bodies. 47 | * @author William Bittle 48 | * @version 5.0.0 49 | * @since 3.2.0 50 | */ 51 | public class Images extends SimulationFrame { 52 | /** Generated serial version id */ 53 | private static final long serialVersionUID = -4165832122583574360L; 54 | 55 | // images 56 | 57 | /** The basketball image */ 58 | private static final BufferedImage BASKETBALL = getImageSuppressExceptions("/org/dyn4j/samples/resources/Basketball.png"); 59 | 60 | /** The create image */ 61 | private static final BufferedImage CRATE = getImageSuppressExceptions("/org/dyn4j/samples/resources/Crate.png"); 62 | 63 | /** Helper function to read the images from the class path */ 64 | private static final BufferedImage getImageSuppressExceptions(String pathOnClasspath) { 65 | try { 66 | return ImageIO.read(Images.class.getResource(pathOnClasspath)); 67 | } catch (IOException e) { 68 | return null; 69 | } 70 | } 71 | 72 | /** 73 | * A custom body that uses an image instead. 74 | * @author William Bittle 75 | * @version 3.2.1 76 | * @since 3.2.0 77 | */ 78 | private final class ImageBody extends SimulationBody { 79 | /** The image to use, if required */ 80 | public BufferedImage image; 81 | 82 | /* (non-Javadoc) 83 | * @see org.dyn4j.samples.SimulationBody#renderFixture(java.awt.Graphics2D, double, org.dyn4j.dynamics.BodyFixture, java.awt.Color) 84 | */ 85 | @Override 86 | protected void renderFixture(Graphics2D g, double scale, BodyFixture fixture, Color color) { 87 | // do we need to render an image? 88 | if (this.image != null) { 89 | // get the shape on the fixture 90 | Convex convex = fixture.getShape(); 91 | // check the shape type 92 | if (convex instanceof Rectangle) { 93 | Rectangle r = (Rectangle)convex; 94 | Vector2 c = r.getCenter(); 95 | double w = r.getWidth(); 96 | double h = r.getHeight(); 97 | g.drawImage(CRATE, 98 | (int)Math.ceil((c.x - w / 2.0) * scale), 99 | (int)Math.ceil((c.y - h / 2.0) * scale), 100 | (int)Math.ceil(w * scale), 101 | (int)Math.ceil(h * scale), 102 | null); 103 | } else if (convex instanceof Circle) { 104 | // cast the shape to get the radius 105 | Circle c = (Circle) convex; 106 | double r = c.getRadius(); 107 | Vector2 cc = c.getCenter(); 108 | int x = (int)Math.ceil((cc.x - r) * scale); 109 | int y = (int)Math.ceil((cc.y - r) * scale); 110 | int w = (int)Math.ceil(r * 2 * scale); 111 | // lets us an image instead 112 | g.drawImage(BASKETBALL, x, y, w, w, null); 113 | } 114 | } else { 115 | // default rendering 116 | super.renderFixture(g, scale, fixture, color); 117 | } 118 | } 119 | } 120 | 121 | /** 122 | * Default constructor. 123 | */ 124 | public Images() { 125 | super("Images"); 126 | } 127 | 128 | /** 129 | * Creates game objects and adds them to the world. 130 | */ 131 | protected void initializeWorld() { 132 | // create all your bodies/joints 133 | 134 | // create the floor 135 | SimulationBody floor = new SimulationBody(); 136 | floor.addFixture(Geometry.createRectangle(15, 1)); 137 | floor.setMass(MassType.INFINITE); 138 | // move the floor down a bit 139 | floor.translate(0.0, -4.0); 140 | this.world.addBody(floor); 141 | 142 | // create a circle 143 | ImageBody circle = new ImageBody(); 144 | circle.image = BASKETBALL; 145 | circle.addFixture(Geometry.createCircle(0.5), 1, 0.2, 0.5); 146 | circle.setMass(MassType.NORMAL); 147 | circle.translate(2.0, 2.0); 148 | // test adding some force 149 | circle.applyForce(new Vector2(-100.0, 0.0)); 150 | // set some linear damping to simulate rolling friction 151 | circle.setLinearDamping(0.05); 152 | this.world.addBody(circle); 153 | 154 | // try a rectangle 155 | ImageBody rectangle = new ImageBody(); 156 | rectangle.image = CRATE; 157 | rectangle.addFixture(Geometry.createRectangle(1, 1)); 158 | rectangle.setMass(MassType.NORMAL); 159 | rectangle.translate(0.0, 1.0); 160 | rectangle.getLinearVelocity().set(-2, 0); 161 | this.world.addBody(rectangle); 162 | } 163 | 164 | /* (non-Javadoc) 165 | * @see org.dyn4j.samples.framework.SimulationFrame#initializeCamera(org.dyn4j.samples.framework.Camera) 166 | */ 167 | @Override 168 | protected void initializeCamera(Camera camera) { 169 | super.initializeCamera(camera); 170 | camera.scale = 45.0; 171 | } 172 | 173 | /** 174 | * Entry point for the example application. 175 | * @param args command line arguments 176 | */ 177 | public static void main(String[] args) { 178 | Images simulation = new Images(); 179 | simulation.run(); 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /src/main/java/org/dyn4j/samples/LinkTerrain.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2022 William Bittle http://www.dyn4j.org/ 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted 6 | * provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, this list of conditions 9 | * and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | * and the following disclaimer in the documentation and/or other materials provided with the 12 | * distribution. 13 | * * Neither the name of dyn4j nor the names of its contributors may be used to endorse or 14 | * promote products derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 23 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | package org.dyn4j.samples; 26 | 27 | import java.util.List; 28 | 29 | import org.dyn4j.collision.narrowphase.Sat; 30 | import org.dyn4j.geometry.Geometry; 31 | import org.dyn4j.geometry.Link; 32 | import org.dyn4j.geometry.MassType; 33 | import org.dyn4j.geometry.Vector2; 34 | import org.dyn4j.samples.framework.Camera; 35 | import org.dyn4j.samples.framework.SimulationBody; 36 | import org.dyn4j.samples.framework.SimulationFrame; 37 | 38 | /** 39 | * A simple scene of a terrain made using the {@link Link}s to avoid 40 | * the internal edge collision problem. 41 | * @author William Bittle 42 | * @version 5.0.0 43 | * @since 3.2.2 44 | */ 45 | public class LinkTerrain extends SimulationFrame { 46 | /** The serial version id */ 47 | private static final long serialVersionUID = -3675099977835892473L; 48 | 49 | /** 50 | * Default constructor for the window 51 | */ 52 | public LinkTerrain() { 53 | super("LinkTerrain"); 54 | 55 | this.pause(); 56 | } 57 | 58 | /** 59 | * Creates game objects and adds them to the world. 60 | */ 61 | protected void initializeWorld() { 62 | this.world.setNarrowphaseDetector(new Sat()); 63 | 64 | // the terrain 65 | List links = Geometry.createLinks( 66 | new Vector2[] { 67 | new Vector2( 6.0, -0.5), 68 | new Vector2( 4.5, 0.3), 69 | new Vector2( 4.0, 0.2), 70 | new Vector2( 2.0, 0.0), 71 | new Vector2( 0.0, 0.0), 72 | new Vector2(-6.0, 0.5) 73 | }, false); 74 | 75 | SimulationBody floor = new SimulationBody(); 76 | for (Link link : links) { 77 | floor.addFixture(link); 78 | } 79 | floor.setMass(MassType.INFINITE); 80 | this.world.addBody(floor); 81 | 82 | // the body 83 | SimulationBody slider = new SimulationBody(); 84 | slider.addFixture(Geometry.createSquare(0.25)); 85 | slider.setMass(MassType.NORMAL); 86 | slider.setLinearVelocity(6.2, 0); 87 | slider.translate(-5.5, 1.0); 88 | this.world.addBody(slider); 89 | } 90 | 91 | /* (non-Javadoc) 92 | * @see org.dyn4j.samples.framework.SimulationFrame#initializeCamera(org.dyn4j.samples.framework.Camera) 93 | */ 94 | @Override 95 | protected void initializeCamera(Camera camera) { 96 | super.initializeCamera(camera); 97 | camera.scale = 64.0; 98 | } 99 | 100 | /** 101 | * Entry point for the example application. 102 | * @param args command line arguments 103 | */ 104 | public static void main(String[] args) { 105 | LinkTerrain simulation = new LinkTerrain(); 106 | simulation.run(); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/org/dyn4j/samples/Maze.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2022 William Bittle http://www.dyn4j.org/ 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted 6 | * provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, this list of conditions 9 | * and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | * and the following disclaimer in the documentation and/or other materials provided with the 12 | * distribution. 13 | * * Neither the name of dyn4j nor the names of its contributors may be used to endorse or 14 | * promote products derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 23 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | package org.dyn4j.samples; 26 | 27 | import java.awt.Color; 28 | import java.awt.Point; 29 | import java.awt.event.MouseAdapter; 30 | import java.awt.event.MouseEvent; 31 | 32 | import org.dyn4j.dynamics.joint.MotorJoint; 33 | import org.dyn4j.geometry.Geometry; 34 | import org.dyn4j.geometry.MassType; 35 | import org.dyn4j.geometry.Transform; 36 | import org.dyn4j.geometry.Vector2; 37 | import org.dyn4j.samples.framework.Camera; 38 | import org.dyn4j.samples.framework.SimulationBody; 39 | import org.dyn4j.samples.framework.SimulationFrame; 40 | import org.dyn4j.world.World; 41 | 42 | /** 43 | * Use the mouse to move the green body to the blue body. Notice how 44 | * the green body tries to work around the obstacles, but does not go 45 | * through them. 46 | * @author William Bittle 47 | * @since 5.0.0 48 | * @version 4.1.1 49 | */ 50 | public class Maze extends SimulationFrame { 51 | /** The serial version id */ 52 | private static final long serialVersionUID = -4132057742762298086L; 53 | 54 | /** The controller body */ 55 | private SimulationBody controller; 56 | 57 | /** The current mouse drag point */ 58 | private Point point; 59 | 60 | /** 61 | * A custom mouse adapter to track mouse drag events. 62 | * @author William Bittle 63 | */ 64 | private final class CustomMouseAdapter extends MouseAdapter { 65 | @Override 66 | public void mouseMoved(MouseEvent e) { 67 | // just create a new point and store it locally 68 | // later, on the next update we'll check for it 69 | point = new Point(e.getX(), e.getY()); 70 | } 71 | } 72 | 73 | /** 74 | * Default constructor for the window 75 | */ 76 | public Maze() { 77 | super("Maze"); 78 | 79 | this.setMousePickingEnabled(false); 80 | 81 | // setup the mouse listening 82 | MouseAdapter ml = new CustomMouseAdapter(); 83 | this.canvas.addMouseMotionListener(ml); 84 | this.canvas.addMouseWheelListener(ml); 85 | this.canvas.addMouseListener(ml); 86 | } 87 | 88 | /** 89 | * Creates game objects and adds them to the world. 90 | */ 91 | protected void initializeWorld() { 92 | // no gravity please 93 | this.world.setGravity(World.ZERO_GRAVITY); 94 | 95 | // player control setup 96 | 97 | this.controller = new SimulationBody(Color.CYAN); 98 | this.controller.addFixture(Geometry.createCircle(0.25)); 99 | this.controller.setMass(MassType.INFINITE); 100 | this.controller.setAtRestDetectionEnabled(false); 101 | this.world.addBody(this.controller); 102 | 103 | SimulationBody player = new SimulationBody(Color.GREEN); 104 | player.addFixture(Geometry.createCircle(0.25)); 105 | player.setMass(MassType.NORMAL); 106 | player.setAtRestDetectionEnabled(false); 107 | this.world.addBody(player); 108 | 109 | MotorJoint control = new MotorJoint(player, this.controller); 110 | control.setCollisionAllowed(false); 111 | control.setMaximumForce(1000.0); 112 | control.setMaximumTorque(1000.0); 113 | this.world.addJoint(control); 114 | 115 | // maze 116 | 117 | double wallWidth = 0.5; 118 | double mazeSize = 30; 119 | double mazeOffset = mazeSize / 2.0 - wallWidth / 2.0; 120 | double pathWidth = 1.5; 121 | 122 | // outer walls 123 | 124 | SimulationBody wall = new SimulationBody(); 125 | wall.addFixture(Geometry.createRectangle(wallWidth, mazeSize)); 126 | wall.setMass(MassType.INFINITE); 127 | wall.translate(mazeOffset, 0); 128 | this.world.addBody(wall); 129 | 130 | SimulationBody wall2 = new SimulationBody(); 131 | wall2.addFixture(Geometry.createRectangle(mazeSize - pathWidth, wallWidth)); 132 | wall2.setMass(MassType.INFINITE); 133 | wall2.translate(pathWidth * 0.5, mazeOffset); 134 | this.world.addBody(wall2); 135 | 136 | SimulationBody wall3 = new SimulationBody(); 137 | wall3.addFixture(Geometry.createRectangle(mazeSize - pathWidth, wallWidth)); 138 | wall3.setMass(MassType.INFINITE); 139 | wall3.translate(-pathWidth * 0.5, -mazeOffset); 140 | this.world.addBody(wall3); 141 | 142 | SimulationBody wall4 = new SimulationBody(); 143 | wall4.addFixture(Geometry.createRectangle(wallWidth, mazeSize)); 144 | wall4.setMass(MassType.INFINITE); 145 | wall4.translate(-mazeOffset, 0); 146 | this.world.addBody(wall4); 147 | 148 | // inner walls 149 | 150 | for (int i = 0; i < 7; i++) { 151 | SimulationBody wall5 = new SimulationBody(); 152 | wall5.addFixture(Geometry.createRectangle(wallWidth, mazeSize - pathWidth)); 153 | wall5.setMass(MassType.INFINITE); 154 | wall5.translate(-mazeOffset + (i + 1) * pathWidth, (i % 2 == 0 ? 1 : -1) * pathWidth / 2.0); 155 | this.world.addBody(wall5); 156 | } 157 | 158 | for (int i = 0; i < 18; i++) { 159 | SimulationBody wall5 = new SimulationBody(); 160 | wall5.addFixture(Geometry.createRectangle(mazeSize / 2 - pathWidth, wallWidth)); 161 | wall5.setMass(MassType.INFINITE); 162 | wall5.translate(-mazeOffset + 12 * pathWidth + (i % 2 == 0 ? 1 : -1) * pathWidth / 2.0, -mazeOffset + (i + 1) * pathWidth); 163 | this.world.addBody(wall5); 164 | } 165 | 166 | for (int i = 0; i < 3; i++) { 167 | SimulationBody wall5 = new SimulationBody(); 168 | wall5.addFixture(Geometry.createRectangle(wallWidth, mazeSize - pathWidth)); 169 | wall5.setMass(MassType.INFINITE); 170 | wall5.translate(0 + (i + 7) * pathWidth, (i % 2 == 0 ? -1 : 1) * pathWidth / 2.0); 171 | this.world.addBody(wall5); 172 | } 173 | } 174 | 175 | /* (non-Javadoc) 176 | * @see org.dyn4j.samples.framework.SimulationFrame#initializeCamera(org.dyn4j.samples.framework.Camera) 177 | */ 178 | @Override 179 | protected void initializeCamera(Camera camera) { 180 | super.initializeCamera(camera); 181 | camera.scale = 16.0; 182 | } 183 | 184 | /* (non-Javadoc) 185 | * @see org.dyn4j.samples.framework.SimulationFrame#handleEvents() 186 | */ 187 | @Override 188 | protected void handleEvents() { 189 | super.handleEvents(); 190 | 191 | // check if the mouse has moved/dragged 192 | if (this.point != null) { 193 | Vector2 v = this.toWorldCoordinates(this.point); 194 | 195 | // reset the transform of the controller body 196 | Transform tx = new Transform(); 197 | tx.translate(v.x, v.y); 198 | this.controller.setTransform(tx); 199 | 200 | // clear the point 201 | this.point = null; 202 | } 203 | } 204 | 205 | /** 206 | * Entry point for the example application. 207 | * @param args command line arguments 208 | */ 209 | public static void main(String[] args) { 210 | Maze simulation = new Maze(); 211 | simulation.run(); 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /src/main/java/org/dyn4j/samples/Organize.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2022 William Bittle http://www.dyn4j.org/ 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted 6 | * provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, this list of conditions 9 | * and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | * and the following disclaimer in the documentation and/or other materials provided with the 12 | * distribution. 13 | * * Neither the name of dyn4j nor the names of its contributors may be used to endorse or 14 | * promote products derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 23 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | package org.dyn4j.samples; 26 | 27 | import java.awt.event.KeyEvent; 28 | import java.util.ArrayList; 29 | import java.util.HashMap; 30 | import java.util.List; 31 | import java.util.Map; 32 | import java.util.Random; 33 | 34 | import org.dyn4j.dynamics.joint.DistanceJoint; 35 | import org.dyn4j.geometry.Geometry; 36 | import org.dyn4j.geometry.Mass; 37 | import org.dyn4j.geometry.MassType; 38 | import org.dyn4j.geometry.Vector2; 39 | import org.dyn4j.samples.framework.Camera; 40 | import org.dyn4j.samples.framework.SimulationBody; 41 | import org.dyn4j.samples.framework.SimulationFrame; 42 | import org.dyn4j.samples.framework.input.BooleanStateKeyboardInputHandler; 43 | 44 | /** 45 | * A scene where a set of different sized bodies are strung together with 46 | * distance = 0 DistanceJoints that causes the bodies to try to self 47 | * organize. 48 | * @author William Bittle 49 | * @version 5.0.0 50 | * @since 4.1.1 51 | */ 52 | public class Organize extends SimulationFrame { 53 | /** The serial version id */ 54 | private static final long serialVersionUID = -2350301592218819726L; 55 | 56 | /** A list of bodies that can be joined (i.e. excludes the static bodies) */ 57 | private List bodies; 58 | 59 | private final BooleanStateKeyboardInputHandler organize; 60 | 61 | /** True if the joints have been added */ 62 | private boolean jointsAdded = false; 63 | 64 | /** 65 | * Default constructor. 66 | */ 67 | public Organize() { 68 | super("Organize"); 69 | 70 | this.organize = new BooleanStateKeyboardInputHandler(this.canvas, KeyEvent.VK_O); 71 | 72 | this.organize.install(); 73 | } 74 | 75 | /* (non-Javadoc) 76 | * @see org.dyn4j.samples.framework.SimulationFrame#printControls() 77 | */ 78 | @Override 79 | protected void printControls() { 80 | super.printControls(); 81 | 82 | printControl("Organize", "o", "Use the o key to toggle the distance joints"); 83 | } 84 | 85 | /** 86 | * Creates game objects and adds them to the world. 87 | */ 88 | protected void initializeWorld() { 89 | SimulationBody bottom = new SimulationBody(); 90 | bottom.addFixture(Geometry.createRectangle(15.0, 1.0)); 91 | bottom.translate(new Vector2(0, -5)); 92 | bottom.setMass(MassType.INFINITE); 93 | world.addBody(bottom); 94 | 95 | SimulationBody top = new SimulationBody(); 96 | top.addFixture(Geometry.createRectangle(15.0, 1.0)); 97 | top.translate(new Vector2(0, 5)); 98 | top.setMass(MassType.INFINITE); 99 | world.addBody(top); 100 | 101 | SimulationBody left = new SimulationBody(); 102 | left.addFixture(Geometry.createRectangle(1.0, 15.0)); 103 | left.translate(new Vector2(-5, 0)); 104 | left.setMass(MassType.INFINITE); 105 | world.addBody(left); 106 | 107 | SimulationBody right = new SimulationBody(); 108 | right.addFixture(Geometry.createRectangle(1.0, 15.0)); 109 | right.translate(new Vector2(5, 0)); 110 | right.setMass(MassType.INFINITE); 111 | world.addBody(right); 112 | 113 | Random r = new Random(123); 114 | bodies = new ArrayList(); 115 | for (int i = 0; i < 20; i++) { 116 | SimulationBody body = new SimulationBody(); 117 | body.addFixture(Geometry.createCircle(r.nextDouble())); 118 | body.translate(r.nextDouble(),0); 119 | body.setMass(new Mass(new Vector2(), 1, 10)); 120 | world.addBody(body); 121 | 122 | bodies.add(body); 123 | } 124 | } 125 | 126 | /* (non-Javadoc) 127 | * @see org.dyn4j.samples.framework.SimulationFrame#initializeCamera(org.dyn4j.samples.framework.Camera) 128 | */ 129 | @Override 130 | protected void initializeCamera(Camera camera) { 131 | super.initializeCamera(camera); 132 | camera.scale = 48.0; 133 | } 134 | 135 | /* (non-Javadoc) 136 | * @see org.dyn4j.samples.framework.SimulationFrame#handleEvents() 137 | */ 138 | @Override 139 | protected void handleEvents() { 140 | super.handleEvents(); 141 | 142 | if (this.organize.isActiveButNotHandled()) { 143 | this.organize.setHasBeenHandled(true); 144 | 145 | if (!this.jointsAdded) { 146 | this.jointsAdded = true; 147 | Random r = new Random(44); 148 | Map used = new HashMap(); 149 | for (int i = 0; i < 10; i++) { 150 | int n = r.nextInt(19); 151 | int m = r.nextInt(19); 152 | String name = (n < m ? n : m) + "," + (n > m ? n : m); 153 | if (n != m && !used.containsKey(name)) { 154 | used.put(name, true); 155 | SimulationBody b1 = this.bodies.get(n); 156 | SimulationBody b2 = this.bodies.get(m); 157 | 158 | DistanceJoint dj = new DistanceJoint(b1, b2, b1.getWorldCenter(), b2.getWorldCenter()); 159 | dj.setCollisionAllowed(true); 160 | dj.setRestDistance(0.0); 161 | dj.setSpringEnabled(true); 162 | dj.setSpringDamperEnabled(true); 163 | dj.setSpringFrequency(2); 164 | dj.setSpringDampingRatio(1.0); 165 | this.world.addJoint(dj); 166 | } 167 | } 168 | } else { 169 | this.world.removeAllJoints(); 170 | this.jointsAdded = false; 171 | } 172 | } 173 | } 174 | 175 | /* (non-Javadoc) 176 | * @see org.dyn4j.samples.framework.SimulationFrame#reset() 177 | */ 178 | @Override 179 | public void reset() { 180 | super.reset(); 181 | this.jointsAdded = false; 182 | } 183 | 184 | /** 185 | * Entry point for the example application. 186 | * @param args command line arguments 187 | */ 188 | public static void main(String[] args) { 189 | Organize simulation = new Organize(); 190 | simulation.run(); 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /src/main/java/org/dyn4j/samples/Platformer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2022 William Bittle http://www.dyn4j.org/ 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted 6 | * provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, this list of conditions 9 | * and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | * and the following disclaimer in the documentation and/or other materials provided with the 12 | * distribution. 13 | * * Neither the name of dyn4j nor the names of its contributors may be used to endorse or 14 | * promote products derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 23 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | package org.dyn4j.samples; 26 | 27 | import java.awt.Color; 28 | import java.awt.event.KeyEvent; 29 | import java.util.List; 30 | 31 | import org.dyn4j.dynamics.TimeStep; 32 | import org.dyn4j.dynamics.contact.ContactConstraint; 33 | import org.dyn4j.geometry.AABB; 34 | import org.dyn4j.geometry.Geometry; 35 | import org.dyn4j.geometry.MassType; 36 | import org.dyn4j.geometry.Vector2; 37 | import org.dyn4j.samples.framework.Camera; 38 | import org.dyn4j.samples.framework.SimulationBody; 39 | import org.dyn4j.samples.framework.SimulationFrame; 40 | import org.dyn4j.samples.framework.input.BooleanStateKeyboardInputHandler; 41 | import org.dyn4j.world.ContactCollisionData; 42 | import org.dyn4j.world.PhysicsWorld; 43 | import org.dyn4j.world.listener.ContactListenerAdapter; 44 | import org.dyn4j.world.listener.StepListenerAdapter; 45 | 46 | /** 47 | * A simple scene of a circle that is controlled by the left and 48 | * right arrow keys that is moved by applying torques and forces. 49 | *

50 | * Also illustrated here is how to track whether the body is in 51 | * contact with the "ground." 52 | *

53 | * Always keep in mind that this is just an example, production 54 | * code should be more robust and better organized. 55 | * @author William Bittle 56 | * @since 5.0.1 57 | * @version 3.2.0 58 | */ 59 | public class Platformer extends SimulationFrame { 60 | /** The serial version id */ 61 | private static final long serialVersionUID = -313391186714427055L; 62 | 63 | private static final Color WHEEL_OFF_COLOR = Color.MAGENTA; 64 | private static final Color WHEEL_ON_COLOR = Color.GREEN; 65 | 66 | private static final Object CHARACTER = new Object(); 67 | private static final Object FLOOR = new Object(); 68 | private static final Object ONE_WAY_PLATFORM = new Object(); 69 | 70 | private final BooleanStateKeyboardInputHandler up; 71 | private final BooleanStateKeyboardInputHandler down; 72 | private final BooleanStateKeyboardInputHandler left; 73 | private final BooleanStateKeyboardInputHandler right; 74 | 75 | private SimulationBody character; 76 | private boolean onGround = false; 77 | 78 | /** 79 | * Default constructor for the window 80 | */ 81 | public Platformer() { 82 | super("Platformer"); 83 | 84 | this.up = new BooleanStateKeyboardInputHandler(this.canvas, KeyEvent.VK_UP); 85 | this.down = new BooleanStateKeyboardInputHandler(this.canvas, KeyEvent.VK_DOWN); 86 | this.left = new BooleanStateKeyboardInputHandler(this.canvas, KeyEvent.VK_LEFT); 87 | this.right = new BooleanStateKeyboardInputHandler(this.canvas, KeyEvent.VK_RIGHT); 88 | 89 | this.up.install(); 90 | this.down.install(); 91 | this.left.install(); 92 | this.right.install(); 93 | } 94 | 95 | /* (non-Javadoc) 96 | * @see org.dyn4j.samples.framework.SimulationFrame#initializeCamera(org.dyn4j.samples.framework.Camera) 97 | */ 98 | @Override 99 | protected void initializeCamera(Camera camera) { 100 | super.initializeCamera(camera); 101 | camera.scale = 32.0; 102 | } 103 | 104 | /** 105 | * Creates game objects and adds them to the world. 106 | */ 107 | protected void initializeWorld() { 108 | // the floor 109 | SimulationBody floor = new SimulationBody(); 110 | floor.addFixture(Geometry.createRectangle(50.0, 0.2)); 111 | floor.setMass(MassType.INFINITE); 112 | floor.translate(0, -3); 113 | floor.setUserData(FLOOR); 114 | this.world.addBody(floor); 115 | 116 | // some obstacles 117 | final int n = 5; 118 | for (int i = 0; i < n; i++) { 119 | SimulationBody sb = new SimulationBody(); 120 | double w = 1.0; 121 | double h = Math.random() * 0.3 + 0.1; 122 | sb.addFixture(Geometry.createIsoscelesTriangle(w, h)); 123 | sb.translate((Math.random() > 0.5 ? -1 : 1) * Math.random() * 5.0, h * 0.5 - 2.9); 124 | sb.setMass(MassType.INFINITE); 125 | sb.setUserData(FLOOR); 126 | this.world.addBody(sb); 127 | } 128 | 129 | // the platform 130 | SimulationBody platform = new SimulationBody(); 131 | platform.addFixture(Geometry.createRectangle(10.0, 0.2)); 132 | platform.setMass(MassType.INFINITE); 133 | platform.translate(0, 0); 134 | platform.setUserData(ONE_WAY_PLATFORM); 135 | this.world.addBody(platform); 136 | 137 | // some bounding shapes 138 | SimulationBody right = new SimulationBody(); 139 | right.addFixture(Geometry.createRectangle(0.2, 20)); 140 | right.setMass(MassType.INFINITE); 141 | right.translate(10, 7); 142 | this.world.addBody(right); 143 | 144 | SimulationBody left = new SimulationBody(); 145 | left.addFixture(Geometry.createRectangle(0.2, 20)); 146 | left.setMass(MassType.INFINITE); 147 | left.translate(-10, 7); 148 | this.world.addBody(left); 149 | 150 | // the wheel 151 | character = new SimulationBody(WHEEL_OFF_COLOR); 152 | // NOTE: lots of friction to simulate a sticky tire 153 | character.addFixture(Geometry.createCircle(0.5), 1.0, 20.0, 0.1); 154 | character.setMass(MassType.NORMAL); 155 | character.translate(0.0, -2.0); 156 | character.setUserData(CHARACTER); 157 | character.setAtRestDetectionEnabled(false); 158 | this.world.addBody(character); 159 | 160 | // Use a number of concepts here to support movement, jumping, and one-way 161 | // platforms - this is by no means THE solution to these problems, but just 162 | // and example to provide some ideas on how you might 163 | 164 | // One consideration might be to use a sensor body to get less accurate 165 | // on-ground detection so that it's not frustrating to the user. dyn4j 166 | // will detect them in collision, but small bouncing or other things could 167 | // cause it to look/feel wrong 168 | 169 | // SETP 1: 170 | // at the beginning of each world step, check if the body is in 171 | // contact with any of the floor bodies 172 | this.world.addStepListener(new StepListenerAdapter() { 173 | @Override 174 | public void begin(TimeStep step, PhysicsWorld world) { 175 | super.begin(step, world); 176 | 177 | boolean isGround = false; 178 | List> contacts = world.getContacts(character); 179 | for (ContactConstraint cc : contacts) { 180 | if (is(cc.getOtherBody(character), FLOOR, ONE_WAY_PLATFORM) && cc.isEnabled()) { 181 | isGround = true; 182 | } 183 | } 184 | 185 | // only clear it 186 | if (!isGround) { 187 | onGround = false; 188 | } 189 | } 190 | }); 191 | 192 | // STEP 2: 193 | // when contacts are processed, we need to check if we're colliding with either 194 | // the one-way platform or the ground 195 | this.world.addContactListener(new ContactListenerAdapter() { 196 | @Override 197 | public void collision(ContactCollisionData collision) { 198 | ContactConstraint cc = collision.getContactConstraint(); 199 | 200 | // set the other body to one-way if necessary 201 | disableContactForOneWay(cc); 202 | 203 | // track on the on-ground status 204 | trackIsOnGround(cc); 205 | 206 | super.collision(collision); 207 | } 208 | }); 209 | } 210 | 211 | /** 212 | * Helper method to determine if a body is one of the given types assuming 213 | * the type is stored in the user data. 214 | * @param body the body 215 | * @param types the set of types 216 | * @return boolean 217 | */ 218 | private boolean is(SimulationBody body, Object... types) { 219 | for (Object type : types) { 220 | if (body.getUserData() == type) { 221 | return true; 222 | } 223 | } 224 | return false; 225 | } 226 | 227 | /** 228 | * Returns true if the given platform should be toggled as one-way 229 | * given the position of the character body. 230 | * @param character the character body 231 | * @param platform the platform body 232 | * @return boolean 233 | */ 234 | private boolean allowOneWayUp(SimulationBody character, SimulationBody platform) { 235 | AABB wAABB = character.createAABB(); 236 | AABB pAABB = platform.createAABB(); 237 | 238 | // NOTE: this would need to change based on the shape of the platform and it's orientation 239 | // 240 | // one thought might be to store the allowed normal of the platform on the platform body 241 | // and check that against the ContactConstraint normal to see if they are pointing in the 242 | // same direction 243 | // 244 | // another option might be to project both onto the platform normal to see where they are overlapping 245 | if (wAABB.getMinY() < pAABB.getMinY()) { 246 | return true; 247 | } 248 | return false; 249 | } 250 | 251 | /** 252 | * Disables the constraint if it's between the character and platform and it 253 | * the scenario meets the condition for one-way. 254 | * @param contactConstraint the constraint 255 | */ 256 | private void disableContactForOneWay(ContactConstraint contactConstraint) { 257 | SimulationBody b1 = contactConstraint.getBody1(); 258 | SimulationBody b2 = contactConstraint.getBody2(); 259 | 260 | if (is(b1, CHARACTER) && is(b2, ONE_WAY_PLATFORM)) { 261 | if (allowOneWayUp(b1, b2) || down.isActiveButNotHandled()) { 262 | down.setHasBeenHandled(true); 263 | contactConstraint.setEnabled(false); 264 | } 265 | } else if (is(b1, ONE_WAY_PLATFORM) && is(b2, CHARACTER)) { 266 | if (allowOneWayUp(b2, b1) || down.isActiveButNotHandled()) { 267 | down.setHasBeenHandled(true); 268 | contactConstraint.setEnabled(false); 269 | } 270 | } 271 | } 272 | 273 | /** 274 | * Sets the isOnGround flag if the given contact constraint is between 275 | * the character body and a floor or one-way platform. 276 | * @param contactConstraint 277 | */ 278 | private void trackIsOnGround(ContactConstraint contactConstraint) { 279 | SimulationBody b1 = contactConstraint.getBody1(); 280 | SimulationBody b2 = contactConstraint.getBody2(); 281 | 282 | if (is(b1, CHARACTER) && 283 | is(b2, FLOOR, ONE_WAY_PLATFORM) && 284 | contactConstraint.isEnabled()) { 285 | onGround = true; 286 | } else if (is(b1, FLOOR, ONE_WAY_PLATFORM) && 287 | is(b2, CHARACTER) && 288 | contactConstraint.isEnabled()) { 289 | onGround = true; 290 | } 291 | } 292 | 293 | /* (non-Javadoc) 294 | * @see org.dyn4j.samples.framework.SimulationFrame#reset() 295 | */ 296 | @Override 297 | public void reset() { 298 | super.reset(); 299 | this.onGround = false; 300 | } 301 | 302 | /* (non-Javadoc) 303 | * @see org.dyn4j.samples.framework.SimulationFrame#handleEvents() 304 | */ 305 | @Override 306 | protected void handleEvents() { 307 | super.handleEvents(); 308 | 309 | // apply a torque based on key input 310 | if (this.left.isActive()) { 311 | character.applyTorque(Math.PI / 2); 312 | } 313 | if (this.right.isActive()) { 314 | character.applyTorque(-Math.PI / 2); 315 | } 316 | 317 | // only allow jumping if the body is on the ground 318 | if (this.up.isActiveButNotHandled()) { 319 | this.up.setHasBeenHandled(true); 320 | if (this.onGround) { 321 | character.applyImpulse(new Vector2(0.0, 7)); 322 | } 323 | } 324 | 325 | // color the body green if it's on the ground 326 | if (this.onGround) { 327 | character.setColor(WHEEL_ON_COLOR); 328 | } else { 329 | character.setColor(WHEEL_OFF_COLOR); 330 | } 331 | } 332 | 333 | /** 334 | * Entry point for the example application. 335 | * @param args command line arguments 336 | */ 337 | public static void main(String[] args) { 338 | Platformer simulation = new Platformer(); 339 | simulation.run(); 340 | } 341 | } 342 | -------------------------------------------------------------------------------- /src/main/java/org/dyn4j/samples/Pyramid.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2022 William Bittle http://www.dyn4j.org/ 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted 6 | * provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, this list of conditions 9 | * and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | * and the following disclaimer in the documentation and/or other materials provided with the 12 | * distribution. 13 | * * Neither the name of dyn4j nor the names of its contributors may be used to endorse or 14 | * promote products derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 23 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | package org.dyn4j.samples; 26 | 27 | import org.dyn4j.geometry.Geometry; 28 | import org.dyn4j.geometry.MassType; 29 | import org.dyn4j.geometry.Vector2; 30 | import org.dyn4j.samples.framework.Camera; 31 | import org.dyn4j.samples.framework.SimulationBody; 32 | import org.dyn4j.samples.framework.SimulationFrame; 33 | 34 | /** 35 | * A scene where we build a Pyramid of blocks. 36 | * @author William Bittle 37 | * @since 5.0.0 38 | * @version 4.1.1 39 | */ 40 | public class Pyramid extends SimulationFrame { 41 | /** The serial version id */ 42 | private static final long serialVersionUID = -3837218136220591307L; 43 | 44 | /** 45 | * Default constructor. 46 | */ 47 | public Pyramid() { 48 | super("Pyramid"); 49 | } 50 | 51 | /* (non-Javadoc) 52 | * @see org.dyn4j.samples.framework.SimulationFrame#initializeWorld() 53 | */ 54 | protected void initializeWorld() { 55 | // allow for better/more stable stacking 56 | world.getSettings().setVelocityConstraintSolverIterations(10); 57 | 58 | SimulationBody ground = new SimulationBody(); 59 | ground.addFixture(Geometry.createRectangle(15.0, 1.0)); 60 | ground.setMass(MassType.INFINITE); 61 | world.addBody(ground); 62 | 63 | int ph = 15; 64 | double size = 0.5; 65 | double s = size; 66 | 67 | for (int i = 0; i < ph; i++) { 68 | for (int j = 0; j < ph - i; j++) { 69 | 70 | SimulationBody b = new SimulationBody(); 71 | b.addFixture(Geometry.createSquare(size), 5.0, 0.5, 0.0); 72 | b.translate(new Vector2(j * s - (ph - i) * s * 0.5, 0.5 + size / 2.0 + i * size)); 73 | b.setMass(MassType.NORMAL); 74 | world.addBody(b); 75 | } 76 | } 77 | } 78 | 79 | /* (non-Javadoc) 80 | * @see org.dyn4j.samples.framework.SimulationFrame#initializeCamera(org.dyn4j.samples.framework.Camera) 81 | */ 82 | @Override 83 | protected void initializeCamera(Camera camera) { 84 | super.initializeCamera(camera); 85 | camera.scale = 48.0; 86 | camera.offsetY = -200; 87 | } 88 | 89 | /** 90 | * Entry point for the example application. 91 | * @param args command line arguments 92 | */ 93 | public static void main(String[] args) { 94 | Pyramid simulation = new Pyramid(); 95 | simulation.run(); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/main/java/org/dyn4j/samples/Ragdoll.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2022 William Bittle http://www.dyn4j.org/ 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted 6 | * provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, this list of conditions 9 | * and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | * and the following disclaimer in the documentation and/or other materials provided with the 12 | * distribution. 13 | * * Neither the name of dyn4j nor the names of its contributors may be used to endorse or 14 | * promote products derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 23 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | package org.dyn4j.samples; 26 | 27 | import org.dyn4j.dynamics.joint.RevoluteJoint; 28 | import org.dyn4j.geometry.Convex; 29 | import org.dyn4j.geometry.Geometry; 30 | import org.dyn4j.geometry.MassType; 31 | import org.dyn4j.geometry.Vector2; 32 | import org.dyn4j.samples.framework.Camera; 33 | import org.dyn4j.samples.framework.SimulationBody; 34 | import org.dyn4j.samples.framework.SimulationFrame; 35 | 36 | /** 37 | * A somewhat complex scene with a ragdoll. 38 | * @author William Bittle 39 | * @since 5.0.0 40 | * @version 3.2.0 41 | */ 42 | public class Ragdoll extends SimulationFrame { 43 | /** The serial version id */ 44 | private static final long serialVersionUID = -2350301592218819726L; 45 | 46 | /** 47 | * Default constructor. 48 | */ 49 | public Ragdoll() { 50 | super("Ragdoll"); 51 | } 52 | 53 | /** 54 | * Creates game objects and adds them to the world. 55 | */ 56 | protected void initializeWorld() { 57 | // Ground 58 | SimulationBody ground = new SimulationBody(); 59 | ground.addFixture(Geometry.createRectangle(100.0, 1.0)); 60 | ground.translate(new Vector2(0.6875, -8.75)); 61 | ground.setMass(MassType.INFINITE); 62 | world.addBody(ground); 63 | 64 | // the ragdoll 65 | 66 | // Head 67 | SimulationBody head = new SimulationBody(); 68 | head.addFixture(Geometry.createCircle(0.25)); 69 | head.setMass(MassType.NORMAL); 70 | world.addBody(head); 71 | 72 | // Torso 73 | SimulationBody torso = new SimulationBody(); 74 | torso.addFixture(Geometry.createRectangle(0.5, 1.0)); 75 | { 76 | Convex c = Geometry.createRectangle(1.0, 0.25); 77 | c.translate(new Vector2(0.00390625, 0.375)); 78 | torso.addFixture(c); 79 | } 80 | torso.translate(new Vector2(0.0234375, -0.8125)); 81 | torso.setMass(MassType.NORMAL); 82 | world.addBody(torso); 83 | 84 | // Right Humerus 85 | SimulationBody rightHumerus = new SimulationBody(); 86 | rightHumerus.addFixture(Geometry.createRectangle(0.25, 0.5)); 87 | rightHumerus.translate(new Vector2(0.4375, -0.609375)); 88 | rightHumerus.setMass(MassType.NORMAL); 89 | world.addBody(rightHumerus); 90 | 91 | // Right Ulna 92 | SimulationBody rightUlna = new SimulationBody(); 93 | rightUlna.addFixture(Geometry.createRectangle(0.25, 0.4)); 94 | rightUlna.translate(new Vector2(0.44140625, -0.98828125)); 95 | rightUlna.setMass(MassType.NORMAL); 96 | world.addBody(rightUlna); 97 | 98 | // Neck 99 | SimulationBody neck = new SimulationBody(); 100 | neck.addFixture(Geometry.createRectangle(0.15, 0.2)); 101 | neck.translate(new Vector2(0.015625, -0.2734375)); 102 | neck.setMass(MassType.NORMAL); 103 | world.addBody(neck); 104 | 105 | // Left Humerus 106 | SimulationBody leftHumerus = new SimulationBody(); 107 | leftHumerus.addFixture(Geometry.createRectangle(0.25, 0.5)); 108 | leftHumerus.translate(new Vector2(-0.3828125, -0.609375)); 109 | leftHumerus.setMass(MassType.NORMAL); 110 | world.addBody(leftHumerus); 111 | 112 | // Left Ulna 113 | SimulationBody leftUlna = new SimulationBody(); 114 | leftUlna.addFixture(Geometry.createRectangle(0.25, 0.4)); 115 | leftUlna.translate(new Vector2(-0.3828125, -0.9765625)); 116 | leftUlna.setMass(MassType.NORMAL); 117 | world.addBody(leftUlna); 118 | 119 | // Right Femur 120 | SimulationBody rightFemur = new SimulationBody(); 121 | rightFemur.addFixture(Geometry.createRectangle(0.25, 0.75)); 122 | rightFemur.translate(new Vector2(0.1796875, -1.5703125)); 123 | rightFemur.setMass(MassType.NORMAL); 124 | world.addBody(rightFemur); 125 | 126 | // Left Femur 127 | SimulationBody leftFemur = new SimulationBody(); 128 | leftFemur.addFixture(Geometry.createRectangle(0.25, 0.75)); 129 | leftFemur.translate(new Vector2(-0.1328125, -1.5703125)); 130 | leftFemur.setMass(MassType.NORMAL); 131 | world.addBody(leftFemur); 132 | 133 | // Right Tibia 134 | SimulationBody rightTibia = new SimulationBody(); 135 | rightTibia.addFixture(Geometry.createRectangle(0.25, 0.5)); 136 | rightTibia.translate(new Vector2(0.18359375, -2.11328125)); 137 | rightTibia.setMass(MassType.NORMAL); 138 | world.addBody(rightTibia); 139 | 140 | // Left Tibia 141 | SimulationBody leftTibia = new SimulationBody(); 142 | leftTibia.addFixture(Geometry.createRectangle(0.25, 0.5)); 143 | leftTibia.translate(new Vector2(-0.1328125, -2.1171875)); 144 | leftTibia.setMass(MassType.NORMAL); 145 | world.addBody(leftTibia); 146 | 147 | // Head to Neck 148 | RevoluteJoint headToNeck = new RevoluteJoint(head, neck, new Vector2(0.01, -0.2)); 149 | world.addJoint(headToNeck); 150 | 151 | // Neck to Torso 152 | RevoluteJoint neckToTorso = new RevoluteJoint(neck, torso, new Vector2(0.01, -0.35)); 153 | world.addJoint(neckToTorso); 154 | 155 | // Torso to Left Humerus 156 | RevoluteJoint torsoToLeftHumerus = new RevoluteJoint(torso, leftHumerus, new Vector2(-0.4, -0.4)); 157 | world.addJoint(torsoToLeftHumerus); 158 | 159 | // Torso to Right Humerus 160 | RevoluteJoint torsoToRightHumerus = new RevoluteJoint(torso, rightHumerus, new Vector2(0.4, -0.4)); 161 | world.addJoint(torsoToRightHumerus); 162 | 163 | // Right Humerus to Right Ulna 164 | RevoluteJoint rightHumerusToRightUlna = new RevoluteJoint(rightHumerus, rightUlna, new Vector2(0.43, -0.82)); 165 | world.addJoint(rightHumerusToRightUlna); 166 | 167 | // Left Humerus to Left Ulna 168 | RevoluteJoint leftHumerusToLeftUlna = new RevoluteJoint(leftHumerus, leftUlna, new Vector2(-0.4, -0.81)); 169 | world.addJoint(leftHumerusToLeftUlna); 170 | 171 | // Torso to Right Femur 172 | RevoluteJoint torsoToRightFemur = new RevoluteJoint(torso, rightFemur, new Vector2(0.16, -1.25)); 173 | world.addJoint(torsoToRightFemur); 174 | 175 | // Torso to Left Femur 176 | RevoluteJoint torsoToLeftFemur = new RevoluteJoint(torso, leftFemur, new Vector2(-0.13, -1.25)); 177 | world.addJoint(torsoToLeftFemur); 178 | 179 | // Right Femur to Right Tibia 180 | RevoluteJoint rightFemurToRightTibia = new RevoluteJoint(rightFemur, rightTibia, new Vector2(0.17, -1.9)); 181 | world.addJoint(rightFemurToRightTibia); 182 | 183 | // Left Femur to Left Tibia 184 | RevoluteJoint leftFemurToLeftTibia = new RevoluteJoint(leftFemur, leftTibia, new Vector2(-0.14, -1.9)); 185 | world.addJoint(leftFemurToLeftTibia); 186 | } 187 | 188 | /* (non-Javadoc) 189 | * @see org.dyn4j.samples.framework.SimulationFrame#initializeCamera(org.dyn4j.samples.framework.Camera) 190 | */ 191 | @Override 192 | protected void initializeCamera(Camera camera) { 193 | super.initializeCamera(camera); 194 | camera.scale = 64.0; 195 | camera.offsetY = 300; 196 | } 197 | 198 | /** 199 | * Entry point for the example application. 200 | * @param args command line arguments 201 | */ 202 | public static void main(String[] args) { 203 | Ragdoll simulation = new Ragdoll(); 204 | simulation.run(); 205 | } 206 | } 207 | -------------------------------------------------------------------------------- /src/main/java/org/dyn4j/samples/Stacking.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2022 William Bittle http://www.dyn4j.org/ 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted 6 | * provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, this list of conditions 9 | * and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | * and the following disclaimer in the documentation and/or other materials provided with the 12 | * distribution. 13 | * * Neither the name of dyn4j nor the names of its contributors may be used to endorse or 14 | * promote products derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 23 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | package org.dyn4j.samples; 26 | 27 | import java.awt.event.MouseEvent; 28 | 29 | import org.dyn4j.geometry.Geometry; 30 | import org.dyn4j.geometry.MassType; 31 | import org.dyn4j.geometry.Vector2; 32 | import org.dyn4j.samples.framework.Camera; 33 | import org.dyn4j.samples.framework.SimulationBody; 34 | import org.dyn4j.samples.framework.SimulationFrame; 35 | import org.dyn4j.samples.framework.input.BooleanStateMouseInputHandler; 36 | 37 | /** 38 | * A simple scene where you use Mouse Button 3 to create boxes. 39 | * @author William Bittle 40 | * @version 5.0.1 41 | * @since 3.2.0 42 | */ 43 | public class Stacking extends SimulationFrame { 44 | /** The serial version id */ 45 | private static final long serialVersionUID = -1366264828445805140L; 46 | 47 | private final BooleanStateMouseInputHandler create; 48 | 49 | /** 50 | * Default constructor. 51 | */ 52 | public Stacking() { 53 | super("Stacking"); 54 | 55 | this.create = new BooleanStateMouseInputHandler(this.canvas, MouseEvent.BUTTON3); 56 | 57 | this.create.install(); 58 | } 59 | 60 | /* (non-Javadoc) 61 | * @see org.dyn4j.samples.framework.SimulationFrame#initializeCamera(org.dyn4j.samples.framework.Camera) 62 | */ 63 | @Override 64 | protected void initializeCamera(Camera camera) { 65 | super.initializeCamera(camera); 66 | camera.scale = 32.0; 67 | } 68 | 69 | /** 70 | * Creates game objects and adds them to the world. 71 | */ 72 | protected void initializeWorld() { 73 | SimulationBody floor = new SimulationBody(); 74 | floor.addFixture(Geometry.createRectangle(20, 1), 1.0, 0.5, 0.0); 75 | floor.setMass(MassType.INFINITE); 76 | this.world.addBody(floor); 77 | } 78 | 79 | /* (non-Javadoc) 80 | * @see org.dyn4j.samples.framework.SimulationFrame#printControls() 81 | */ 82 | @Override 83 | protected void printControls() { 84 | super.printControls(); 85 | 86 | this.printControl("Create", "RMB", "Click the right mouse button to create a square"); 87 | } 88 | 89 | /* (non-Javadoc) 90 | * @see org.dyn4j.samples.framework.SimulationFrame#handleEvents() 91 | */ 92 | @Override 93 | protected void handleEvents() { 94 | super.handleEvents(); 95 | 96 | // see if the user clicked 97 | if (this.create.isActiveButNotHandled()) { 98 | this.create.setHasBeenHandled(true); 99 | // convert from screen space to world space coordinates 100 | Vector2 v = this.toWorldCoordinates(this.create.getMouseLocation()); 101 | 102 | // create a new body 103 | SimulationBody no = new SimulationBody(); 104 | no.addFixture(Geometry.createSquare(0.5), 1.0, 0.8, 0.0); 105 | no.translate(v.x, v.y); 106 | no.setMass(MassType.NORMAL); 107 | this.world.addBody(no); 108 | } 109 | } 110 | 111 | /** 112 | * Entry point for the example application. 113 | * @param args command line arguments 114 | */ 115 | public static void main(String[] args) { 116 | Stacking simulation = new Stacking(); 117 | simulation.run(); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/main/java/org/dyn4j/samples/Thrust.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2022 William Bittle http://www.dyn4j.org/ 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted 6 | * provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, this list of conditions 9 | * and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | * and the following disclaimer in the documentation and/or other materials provided with the 12 | * distribution. 13 | * * Neither the name of dyn4j nor the names of its contributors may be used to endorse or 14 | * promote products derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 23 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | package org.dyn4j.samples; 26 | 27 | import java.awt.Color; 28 | import java.awt.Graphics2D; 29 | import java.awt.event.KeyEvent; 30 | import java.awt.geom.Line2D; 31 | 32 | import org.dyn4j.dynamics.BodyFixture; 33 | import org.dyn4j.geometry.Geometry; 34 | import org.dyn4j.geometry.MassType; 35 | import org.dyn4j.geometry.Vector2; 36 | import org.dyn4j.samples.framework.Camera; 37 | import org.dyn4j.samples.framework.SimulationBody; 38 | import org.dyn4j.samples.framework.SimulationFrame; 39 | import org.dyn4j.samples.framework.input.BooleanStateKeyboardInputHandler; 40 | 41 | /** 42 | * Moderately complex scene of a rocket that has propulsion at various points 43 | * to allow control. Control is given by the left, right, up, and down keys 44 | * and applies forces when pressed. 45 | * @author William Bittle 46 | * @version 5.0.1 47 | * @since 3.2.0 48 | */ 49 | public class Thrust extends SimulationFrame { 50 | /** The serial version id */ 51 | private static final long serialVersionUID = 3770932661470247325L; 52 | 53 | /** The controlled ship */ 54 | private SimulationBody ship; 55 | 56 | // input control 57 | 58 | private final BooleanStateKeyboardInputHandler up; 59 | private final BooleanStateKeyboardInputHandler down; 60 | private final BooleanStateKeyboardInputHandler left; 61 | private final BooleanStateKeyboardInputHandler right; 62 | 63 | /** 64 | * Default constructor. 65 | */ 66 | public Thrust() { 67 | super("Thrust"); 68 | 69 | this.up = new BooleanStateKeyboardInputHandler(this.canvas, KeyEvent.VK_UP); 70 | this.down = new BooleanStateKeyboardInputHandler(this.canvas, KeyEvent.VK_DOWN); 71 | this.left = new BooleanStateKeyboardInputHandler(this.canvas, KeyEvent.VK_LEFT); 72 | this.right = new BooleanStateKeyboardInputHandler(this.canvas, KeyEvent.VK_RIGHT); 73 | 74 | this.up.install(); 75 | this.down.install(); 76 | this.left.install(); 77 | this.right.install(); 78 | } 79 | 80 | /* (non-Javadoc) 81 | * @see org.dyn4j.samples.framework.SimulationFrame#initializeCamera(org.dyn4j.samples.framework.Camera) 82 | */ 83 | @Override 84 | protected void initializeCamera(Camera camera) { 85 | super.initializeCamera(camera); 86 | camera.scale = 64.0; 87 | } 88 | 89 | /* (non-Javadoc) 90 | * @see org.dyn4j.samples.framework.SimulationFrame#printControls() 91 | */ 92 | @Override 93 | protected void printControls() { 94 | super.printControls(); 95 | 96 | printControl("Thrust Up", "Up", "Use the up key to apply thrust to move up"); 97 | printControl("Thrust Down", "Down", "Use the down key to apply thrust to move down"); 98 | printControl("Thrust Left", "Left", "Use the left key to apply thrust to move left"); 99 | printControl("Thrust Right", "Right", "Use the right key to apply thrust to move right"); 100 | } 101 | 102 | /** 103 | * Creates game objects and adds them to the world. 104 | */ 105 | protected void initializeWorld() { 106 | this.world.setGravity(new Vector2(0, -3)); 107 | 108 | // create all your bodies/joints 109 | 110 | // the bounds so we can keep playing 111 | SimulationBody l = new SimulationBody(); 112 | l.addFixture(Geometry.createRectangle(1, 15)); 113 | l.translate(-5, 0); 114 | l.setMass(MassType.INFINITE); 115 | this.world.addBody(l); 116 | 117 | SimulationBody r = new SimulationBody(); 118 | r.addFixture(Geometry.createRectangle(1, 15)); 119 | r.translate(5, 0); 120 | r.setMass(MassType.INFINITE); 121 | this.world.addBody(r); 122 | 123 | SimulationBody t = new SimulationBody(); 124 | t.addFixture(Geometry.createRectangle(15, 1)); 125 | t.translate(0, 5); 126 | t.setMass(MassType.INFINITE); 127 | this.world.addBody(t); 128 | 129 | SimulationBody b = new SimulationBody(); 130 | b.addFixture(Geometry.createRectangle(15, 1)); 131 | b.translate(0, -5); 132 | b.setMass(MassType.INFINITE); 133 | this.world.addBody(b); 134 | 135 | // the ship 136 | ship = new SimulationBody(); 137 | ship.addFixture(Geometry.createRectangle(0.5, 1.5), 1, 0.2, 0.2); 138 | BodyFixture bf2 = ship.addFixture(Geometry.createEquilateralTriangle(0.5), 1, 0.2, 0.2); 139 | bf2.getShape().translate(0, 0.9); 140 | ship.translate(0.0, 2.0); 141 | ship.setMass(MassType.NORMAL); 142 | this.world.addBody(ship); 143 | } 144 | 145 | /* (non-Javadoc) 146 | * @see org.dyn4j.samples.framework.SimulationFrame#render(java.awt.Graphics2D, double) 147 | */ 148 | @Override 149 | protected void render(Graphics2D g, double elapsedTime) { 150 | super.render(g, elapsedTime); 151 | 152 | final double scale = this.getCameraScale(); 153 | final double force = 1000 * elapsedTime; 154 | 155 | final Vector2 r = new Vector2(ship.getTransform().getRotationAngle() + Math.PI * 0.5); 156 | final Vector2 c = ship.getWorldCenter(); 157 | 158 | // apply thrust 159 | if (this.up.isActive()) { 160 | Vector2 f = r.product(force); 161 | Vector2 p = c.sum(r.product(-0.9)); 162 | 163 | ship.applyForce(f); 164 | 165 | g.setColor(Color.RED); 166 | g.draw(new Line2D.Double(p.x * scale, p.y * scale, (p.x - f.x) * scale, (p.y - f.y) * scale)); 167 | } 168 | if (this.down.isActive()) { 169 | Vector2 f = r.product(-force); 170 | Vector2 p = c.sum(r.product(0.9)); 171 | 172 | ship.applyForce(f); 173 | 174 | g.setColor(Color.RED); 175 | g.draw(new Line2D.Double(p.x * scale, p.y * scale, (p.x - f.x) * scale, (p.y - f.y) * scale)); 176 | } 177 | if (this.left.isActive()) { 178 | Vector2 f1 = r.product(force * 0.1).right(); 179 | Vector2 f2 = r.product(force * 0.1).left(); 180 | Vector2 p1 = c.sum(r.product(0.9)); 181 | Vector2 p2 = c.sum(r.product(-0.9)); 182 | 183 | // apply a force to the top going left 184 | ship.applyForce(f1, p1); 185 | // apply a force to the bottom going right 186 | ship.applyForce(f2, p2); 187 | 188 | g.setColor(Color.RED); 189 | g.draw(new Line2D.Double(p1.x * scale, p1.y * scale, (p1.x - f1.x) * scale, (p1.y - f1.y) * scale)); 190 | g.draw(new Line2D.Double(p2.x * scale, p2.y * scale, (p2.x - f2.x) * scale, (p2.y - f2.y) * scale)); 191 | } 192 | if (this.right.isActive()) { 193 | Vector2 f1 = r.product(force * 0.1).left(); 194 | Vector2 f2 = r.product(force * 0.1).right(); 195 | Vector2 p1 = c.sum(r.product(0.9)); 196 | Vector2 p2 = c.sum(r.product(-0.9)); 197 | 198 | // apply a force to the top going left 199 | ship.applyForce(f1, p1); 200 | // apply a force to the bottom going right 201 | ship.applyForce(f2, p2); 202 | 203 | g.setColor(Color.RED); 204 | g.draw(new Line2D.Double(p1.x * scale, p1.y * scale, (p1.x - f1.x) * scale, (p1.y - f1.y) * scale)); 205 | g.draw(new Line2D.Double(p2.x * scale, p2.y * scale, (p2.x - f2.x) * scale, (p2.y - f2.y) * scale)); 206 | } 207 | } 208 | 209 | /** 210 | * Entry point for the example application. 211 | * @param args command line arguments 212 | */ 213 | public static void main(String[] args) { 214 | Thrust simulation = new Thrust(); 215 | simulation.run(); 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /src/main/java/org/dyn4j/samples/Tracking.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2022 William Bittle http://www.dyn4j.org/ 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted 6 | * provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, this list of conditions 9 | * and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | * and the following disclaimer in the documentation and/or other materials provided with the 12 | * distribution. 13 | * * Neither the name of dyn4j nor the names of its contributors may be used to endorse or 14 | * promote products derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 23 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | package org.dyn4j.samples; 26 | 27 | import java.util.HashMap; 28 | import java.util.Map; 29 | 30 | import org.dyn4j.dynamics.BodyFixture; 31 | import org.dyn4j.dynamics.contact.Contact; 32 | import org.dyn4j.geometry.Geometry; 33 | import org.dyn4j.geometry.MassType; 34 | import org.dyn4j.geometry.Vector2; 35 | import org.dyn4j.samples.framework.Camera; 36 | import org.dyn4j.samples.framework.SimulationBody; 37 | import org.dyn4j.samples.framework.SimulationFrame; 38 | import org.dyn4j.world.ContactCollisionData; 39 | import org.dyn4j.world.listener.ContactListenerAdapter; 40 | 41 | /** 42 | * A simple scene with a few shape types that tracks the creation, 43 | * persistence and removal of contacts by using their unique ids. 44 | * @author William Bittle 45 | * @version 5.0.0 46 | * @since 3.0.0 47 | */ 48 | public class Tracking extends SimulationFrame { 49 | /** The serial version id */ 50 | private static final long serialVersionUID = -7551190289570564575L; 51 | 52 | /** 53 | * A simple class to generate "id"s. 54 | * @author William Bittle 55 | * @version 4.1.1 56 | * @since 4.1.1 57 | */ 58 | private class IdGenerator { 59 | private long lastId = -1; 60 | public final Object getId() { 61 | return Long.valueOf(++lastId); 62 | } 63 | } 64 | 65 | // contact listening 66 | 67 | /** A mapping of contact id to UUID */ 68 | private final Map idTracking = new HashMap(); 69 | 70 | /** The id generator */ 71 | private final IdGenerator idGenerator = new IdGenerator(); 72 | 73 | /** 74 | * A custom contact listener for tracking contacts. 75 | * @author William Bittle 76 | * @version 3.2.1 77 | * @since 3.2.1 78 | */ 79 | private class CustomContactListener extends ContactListenerAdapter { 80 | @Override 81 | public void begin(ContactCollisionData collision, Contact contact) { 82 | Object id = idGenerator.getId(); 83 | idTracking.put(contact, id); 84 | System.out.println("BEGIN: " + id); 85 | } 86 | 87 | @Override 88 | public void persist(ContactCollisionData collision, Contact oldContact, Contact newContact) { 89 | Object id = idTracking.get(oldContact); 90 | if (id == null) { 91 | System.err.println("Shouldn't happen"); 92 | } 93 | // since the contact object itself changes between iterations 94 | // remove the old contact and add the new contact with the same id 95 | idTracking.remove(oldContact); 96 | idTracking.put(newContact, id); 97 | } 98 | 99 | @Override 100 | public void end(ContactCollisionData collision, Contact contact) { 101 | Object id = idTracking.get(contact); 102 | if (id == null) { 103 | System.err.println("Shouldn't happen"); 104 | } 105 | System.out.println("END: " + id); 106 | idTracking.remove(contact); 107 | } 108 | } 109 | 110 | /** 111 | * Default constructor. 112 | */ 113 | public Tracking() { 114 | super("Tracking"); 115 | } 116 | 117 | /** 118 | * Creates game objects and adds them to the world. 119 | */ 120 | protected void initializeWorld() { 121 | // create all your bodies/joints 122 | 123 | // create the floor 124 | SimulationBody floor = new SimulationBody(); 125 | floor.addFixture(Geometry.createRectangle(15, 1)); 126 | floor.setMass(MassType.INFINITE); 127 | // move the floor down a bit 128 | floor.translate(0.0, -4.0); 129 | this.world.addBody(floor); 130 | 131 | // create a triangle object 132 | SimulationBody triangle = new SimulationBody(); 133 | triangle.addFixture(Geometry.createTriangle( 134 | new Vector2(0.0, 0.5), 135 | new Vector2(-0.5, -0.5), 136 | new Vector2(0.5, -0.5))); 137 | triangle.setMass(MassType.NORMAL); 138 | triangle.translate(-1.0, 2.0); 139 | // test having a velocity 140 | triangle.getLinearVelocity().set(5.0, 0.0); 141 | this.world.addBody(triangle); 142 | 143 | // create a circle 144 | SimulationBody circle = new SimulationBody(); 145 | circle.addFixture(Geometry.createCircle(0.5)); 146 | circle.setMass(MassType.NORMAL); 147 | circle.translate(2.0, 2.0); 148 | // test adding some force 149 | circle.applyForce(new Vector2(-100.0, 0.0)); 150 | // set some linear damping to simulate rolling friction 151 | circle.setLinearDamping(0.05); 152 | this.world.addBody(circle); 153 | 154 | // try a rectangle 155 | SimulationBody rectangle = new SimulationBody(); 156 | rectangle.addFixture(Geometry.createRectangle(1, 1)); 157 | rectangle.setMass(MassType.NORMAL); 158 | rectangle.translate(0.0, 2.0); 159 | rectangle.getLinearVelocity().set(-5.0, 0.0); 160 | this.world.addBody(rectangle); 161 | 162 | // try a polygon with lots of vertices 163 | SimulationBody polygon = new SimulationBody(); 164 | polygon.addFixture(Geometry.createUnitCirclePolygon(10, 1)); 165 | polygon.setMass(MassType.NORMAL); 166 | polygon.translate(-2.5, 2.0); 167 | // set the angular velocity 168 | polygon.setAngularVelocity(Math.toRadians(-20.0)); 169 | this.world.addBody(polygon); 170 | 171 | // try a compound object (Capsule) 172 | BodyFixture c1Fixture = new BodyFixture(Geometry.createCircle(0.5)); 173 | BodyFixture c2Fixture = new BodyFixture(Geometry.createCircle(0.5)); 174 | c1Fixture.setDensity(0.5); 175 | c2Fixture.setDensity(0.5); 176 | // translate the circles in local coordinates 177 | c1Fixture.getShape().translate(-1.0, 0.0); 178 | c2Fixture.getShape().translate(1.0, 0.0); 179 | SimulationBody capsule = new SimulationBody(); 180 | capsule.addFixture(c1Fixture); 181 | capsule.addFixture(c2Fixture); 182 | capsule.addFixture(Geometry.createRectangle(2, 1)); 183 | capsule.setMass(MassType.NORMAL); 184 | capsule.translate(0.0, 4.0); 185 | this.world.addBody(capsule); 186 | 187 | SimulationBody issTri = new SimulationBody(); 188 | issTri.addFixture(Geometry.createIsoscelesTriangle(1.0, 3.0)); 189 | issTri.setMass(MassType.NORMAL); 190 | issTri.translate(2.0, 3.0); 191 | this.world.addBody(issTri); 192 | 193 | SimulationBody equTri = new SimulationBody(); 194 | equTri.addFixture(Geometry.createEquilateralTriangle(2.0)); 195 | equTri.setMass(MassType.NORMAL); 196 | equTri.translate(3.0, 3.0); 197 | this.world.addBody(equTri); 198 | 199 | SimulationBody rightTri = new SimulationBody(); 200 | rightTri.addFixture(Geometry.createRightTriangle(2.0, 1.0)); 201 | rightTri.setMass(MassType.NORMAL); 202 | rightTri.translate(4.0, 3.0); 203 | this.world.addBody(rightTri); 204 | 205 | // attach the contact listener 206 | this.world.addContactListener(new CustomContactListener()); 207 | } 208 | 209 | /* (non-Javadoc) 210 | * @see org.dyn4j.samples.framework.SimulationFrame#initializeCamera(org.dyn4j.samples.framework.Camera) 211 | */ 212 | @Override 213 | protected void initializeCamera(Camera camera) { 214 | super.initializeCamera(camera); 215 | camera.scale = 45.0; 216 | } 217 | 218 | /** 219 | * Entry point for the example application. 220 | * @param args command line arguments 221 | */ 222 | public static void main(String[] args) { 223 | Tracking simulation = new Tracking(); 224 | simulation.run(); 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /src/main/java/org/dyn4j/samples/Truck.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2022 William Bittle http://www.dyn4j.org/ 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted 6 | * provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, this list of conditions 9 | * and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | * and the following disclaimer in the documentation and/or other materials provided with the 12 | * distribution. 13 | * * Neither the name of dyn4j nor the names of its contributors may be used to endorse or 14 | * promote products derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 23 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | package org.dyn4j.samples; 26 | 27 | import java.awt.event.KeyEvent; 28 | 29 | import org.dyn4j.dynamics.BodyFixture; 30 | import org.dyn4j.dynamics.ContinuousDetectionMode; 31 | import org.dyn4j.dynamics.joint.WheelJoint; 32 | import org.dyn4j.geometry.Convex; 33 | import org.dyn4j.geometry.Geometry; 34 | import org.dyn4j.geometry.MassType; 35 | import org.dyn4j.geometry.Vector2; 36 | import org.dyn4j.samples.framework.Camera; 37 | import org.dyn4j.samples.framework.SimulationBody; 38 | import org.dyn4j.samples.framework.SimulationFrame; 39 | import org.dyn4j.samples.framework.input.BooleanStateKeyboardInputHandler; 40 | 41 | /** 42 | * A scene where a truck is carrying other objects. 43 | * @author William Bittle 44 | * @since 5.0.1 45 | * @version 4.1.1 46 | */ 47 | public class Truck extends SimulationFrame { 48 | /** The serial version id */ 49 | private static final long serialVersionUID = 4610026750399376114L; 50 | 51 | private final BooleanStateKeyboardInputHandler left; 52 | private final BooleanStateKeyboardInputHandler right; 53 | private final BooleanStateKeyboardInputHandler stop; 54 | 55 | private double speed; 56 | private WheelJoint wj1; 57 | private WheelJoint wj2; 58 | 59 | /** 60 | * Default constructor. 61 | */ 62 | public Truck() { 63 | super("Truck"); 64 | 65 | this.left = new BooleanStateKeyboardInputHandler(this.canvas, KeyEvent.VK_LEFT); 66 | this.right = new BooleanStateKeyboardInputHandler(this.canvas, KeyEvent.VK_RIGHT); 67 | this.stop = new BooleanStateKeyboardInputHandler(this.canvas, KeyEvent.VK_S); 68 | 69 | this.left.install(); 70 | this.right.install(); 71 | this.stop.install(); 72 | } 73 | 74 | /* (non-Javadoc) 75 | * @see org.dyn4j.samples.framework.SimulationFrame#printControls() 76 | */ 77 | @Override 78 | protected void printControls() { 79 | super.printControls(); 80 | 81 | printControl("Move Left", "Left", "Use the left key to accelerate left"); 82 | printControl("Move Right", "Right", "Use the right key to accelerate right"); 83 | printControl("Stop", "s", "Use the s key to stop"); 84 | } 85 | 86 | /** 87 | * Creates game objects and adds them to the world. 88 | */ 89 | protected void initializeWorld() { 90 | this.world.getSettings().setContinuousDetectionMode(ContinuousDetectionMode.NONE); 91 | 92 | // Ground 93 | SimulationBody ground = new SimulationBody(); 94 | ground.addFixture(Geometry.createRectangle(50.0, 1.0), 1.0, 0.5, 0.0); 95 | ground.translate(new Vector2(-2.0, -4.0)); 96 | ground.setMass(MassType.INFINITE); 97 | world.addBody(ground); 98 | 99 | // Ramp 100 | SimulationBody ramp = new SimulationBody(); 101 | ramp.addFixture(Geometry.createRectangle(10.0, 0.2)); 102 | ramp.rotate(Math.toRadians(10.0)); 103 | ramp.translate(new Vector2(0.0, -3.0)); 104 | ramp.setMass(MassType.INFINITE); 105 | world.addBody(ramp); 106 | 107 | // Frame 108 | SimulationBody truck = new SimulationBody(); 109 | {// drive shaft 110 | truck.addFixture(Geometry.createRectangle(5.0, 0.25)); 111 | } 112 | {// body 113 | Convex c = Geometry.createRectangle(5.2, 0.5); 114 | c.translate(new Vector2(0.0, 0.5)); 115 | BodyFixture bf = new BodyFixture(c); 116 | truck.addFixture(bf); 117 | } 118 | {// tailgate 119 | Convex c = Geometry.createRectangle(0.25, 0.5); 120 | c.translate(new Vector2(-2.4, 1.0)); 121 | BodyFixture bf = new BodyFixture(c); 122 | truck.addFixture(bf); 123 | } 124 | {// cab 125 | Convex c = Geometry.createRectangle(2.0, 2.0); 126 | c.translate(new Vector2(2.4, 1.0)); 127 | BodyFixture bf = new BodyFixture(c); 128 | truck.addFixture(bf); 129 | } 130 | truck.translate(new Vector2(-23.0, -3.0)); 131 | truck.setMass(MassType.NORMAL); 132 | world.addBody(truck); 133 | 134 | // Rear Wheel 135 | SimulationBody rearWheel = new SimulationBody(); 136 | rearWheel.addFixture(Geometry.createCircle(0.5), 1.0, 0.5, 0.0); 137 | rearWheel.translate(-25.0, -3.0); 138 | rearWheel.setMass(MassType.NORMAL); 139 | world.addBody(rearWheel); 140 | 141 | // Front Wheel 142 | SimulationBody frontWheel = new SimulationBody(); 143 | frontWheel.addFixture(Geometry.createCircle(0.5), 1.0, 0.5, 0.0); 144 | frontWheel.translate(-21.0, -3.0); 145 | frontWheel.setMass(MassType.NORMAL); 146 | world.addBody(frontWheel); 147 | 148 | // Rear Motor 149 | WheelJoint rearWheelJoint = new WheelJoint(truck, rearWheel, new Vector2(-25.0, -3.0), new Vector2(0.0, -1.0)); 150 | rearWheelJoint.setMotorEnabled(true); 151 | rearWheelJoint.setMotorSpeed(0.0); 152 | rearWheelJoint.setMaximumMotorTorqueEnabled(true); 153 | rearWheelJoint.setMaximumMotorTorque(1000.0); 154 | world.addJoint(rearWheelJoint); 155 | this.wj1 = rearWheelJoint; 156 | 157 | // Front Motor 158 | WheelJoint frontWheelJoint = new WheelJoint(truck, frontWheel, new Vector2(-21.0, -3.0), new Vector2(0.0, -1.0)); 159 | frontWheelJoint.setMotorEnabled(true); 160 | frontWheelJoint.setMotorSpeed(0.0); 161 | frontWheelJoint.setMaximumMotorTorqueEnabled(true); 162 | frontWheelJoint.setMaximumMotorTorque(1000); 163 | world.addJoint(frontWheelJoint); 164 | this.wj2 = frontWheelJoint; 165 | 166 | // put some stuff in the back of the truck 167 | double x = -24; 168 | double y = -2.0; 169 | double s = 0.25; 170 | for (int i = 0; i < 10; i++) { 171 | for (int j = 0; j < 3; j++) { 172 | SimulationBody box = new SimulationBody(); 173 | box.addFixture(Geometry.createSquare(s), 1.0, 0.2, 0.0); 174 | box.translate(new Vector2(x + (i * s), y + (j * s))); 175 | box.setMass(MassType.NORMAL); 176 | world.addBody(box); 177 | } 178 | } 179 | } 180 | 181 | /* (non-Javadoc) 182 | * @see org.dyn4j.samples.framework.SimulationFrame#initializeCamera(org.dyn4j.samples.framework.Camera) 183 | */ 184 | @Override 185 | protected void initializeCamera(Camera camera) { 186 | super.initializeCamera(camera); 187 | camera.scale = 16.0; 188 | } 189 | 190 | /* (non-Javadoc) 191 | * @see org.dyn4j.samples.framework.SimulationFrame#reset() 192 | */ 193 | @Override 194 | public void reset() { 195 | super.reset(); 196 | this.speed = 0.0; 197 | } 198 | 199 | /* (non-Javadoc) 200 | * @see org.dyn4j.samples.framework.SimulationFrame#handleEvents() 201 | */ 202 | @Override 203 | protected void handleEvents() { 204 | super.handleEvents(); 205 | 206 | if (this.left.isActive()) { 207 | this.speed += Math.PI / 100; 208 | } 209 | if (this.right.isActive()) { 210 | this.speed -= Math.PI / 100; 211 | } 212 | if (this.stop.isActive()) { 213 | this.speed = 0.0; 214 | } 215 | 216 | if (this.wj1 != null) { 217 | this.wj1.setMotorSpeed(this.speed); 218 | } 219 | if (this.wj2 != null) { 220 | this.wj2.setMotorSpeed(this.speed); 221 | } 222 | 223 | 224 | } 225 | 226 | /** 227 | * Entry point for the example application. 228 | * @param args command line arguments 229 | */ 230 | public static void main(String[] args) { 231 | Truck simulation = new Truck(); 232 | simulation.run(); 233 | } 234 | } 235 | -------------------------------------------------------------------------------- /src/main/java/org/dyn4j/samples/UsingGraphics2D.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2022 William Bittle http://www.dyn4j.org/ 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted 6 | * provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, this list of conditions 9 | * and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | * and the following disclaimer in the documentation and/or other materials provided with the 12 | * distribution. 13 | * * Neither the name of dyn4j nor the names of its contributors may be used to endorse or 14 | * promote products derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 23 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | package org.dyn4j.samples; 26 | 27 | import org.dyn4j.dynamics.BodyFixture; 28 | import org.dyn4j.geometry.Capsule; 29 | import org.dyn4j.geometry.Circle; 30 | import org.dyn4j.geometry.Geometry; 31 | import org.dyn4j.geometry.MassType; 32 | import org.dyn4j.geometry.Polygon; 33 | import org.dyn4j.geometry.Rectangle; 34 | import org.dyn4j.geometry.Slice; 35 | import org.dyn4j.geometry.Triangle; 36 | import org.dyn4j.geometry.Vector2; 37 | import org.dyn4j.samples.framework.Camera; 38 | import org.dyn4j.samples.framework.SimulationBody; 39 | import org.dyn4j.samples.framework.SimulationFrame; 40 | 41 | /** 42 | * Class used to show a simple example of using the dyn4j project using 43 | * Java2D for rendering. 44 | *

45 | * This class can be used as a starting point for projects. 46 | * @author William Bittle 47 | * @version 5.0.0 48 | * @since 3.0.0 49 | */ 50 | public class UsingGraphics2D extends SimulationFrame { 51 | /** The serial version id */ 52 | private static final long serialVersionUID = 5663760293144882635L; 53 | 54 | /** 55 | * Default constructor for the window 56 | */ 57 | public UsingGraphics2D() { 58 | super("Graphics2D Example"); 59 | 60 | } 61 | 62 | /** 63 | * Creates game objects and adds them to the world. 64 | *

65 | * Basically the same shapes from the Shapes test in 66 | * the TestBed. 67 | */ 68 | protected void initializeWorld() { 69 | // create all your bodies/joints 70 | 71 | // create the floor 72 | Rectangle floorRect = new Rectangle(15.0, 1.0); 73 | SimulationBody floor = new SimulationBody(); 74 | floor.addFixture(new BodyFixture(floorRect)); 75 | floor.setMass(MassType.INFINITE); 76 | // move the floor down a bit 77 | floor.translate(0.0, -4.0); 78 | this.world.addBody(floor); 79 | 80 | // create a triangle object 81 | Triangle triShape = new Triangle( 82 | new Vector2(0.0, 0.5), 83 | new Vector2(-0.5, -0.5), 84 | new Vector2(0.5, -0.5)); 85 | SimulationBody triangle = new SimulationBody(); 86 | triangle.addFixture(triShape); 87 | triangle.setMass(MassType.NORMAL); 88 | triangle.translate(-1.0, 2.0); 89 | // test having a velocity 90 | triangle.getLinearVelocity().set(5.0, 0.0); 91 | this.world.addBody(triangle); 92 | 93 | // create a circle 94 | Circle cirShape = new Circle(0.5); 95 | SimulationBody circle = new SimulationBody(); 96 | circle.addFixture(cirShape); 97 | circle.setMass(MassType.NORMAL); 98 | circle.translate(2.0, 2.0); 99 | // test adding some force 100 | circle.applyForce(new Vector2(-100.0, 0.0)); 101 | // set some linear damping to simulate rolling friction 102 | circle.setLinearDamping(0.05); 103 | this.world.addBody(circle); 104 | 105 | // try a rectangle 106 | Rectangle rectShape = new Rectangle(1.0, 1.0); 107 | SimulationBody rectangle = new SimulationBody(); 108 | rectangle.addFixture(rectShape); 109 | rectangle.setMass(MassType.NORMAL); 110 | rectangle.translate(0.0, 2.0); 111 | rectangle.getLinearVelocity().set(-5.0, 0.0); 112 | this.world.addBody(rectangle); 113 | 114 | // try a polygon with lots of vertices 115 | Polygon polyShape = Geometry.createUnitCirclePolygon(10, 1.0); 116 | SimulationBody polygon = new SimulationBody(); 117 | polygon.addFixture(polyShape); 118 | polygon.setMass(MassType.NORMAL); 119 | polygon.translate(-2.5, 2.0); 120 | // set the angular velocity 121 | polygon.setAngularVelocity(Math.toRadians(-20.0)); 122 | this.world.addBody(polygon); 123 | 124 | // try a compound object 125 | Circle c1 = new Circle(0.5); 126 | BodyFixture c1Fixture = new BodyFixture(c1); 127 | c1Fixture.setDensity(0.5); 128 | Circle c2 = new Circle(0.5); 129 | BodyFixture c2Fixture = new BodyFixture(c2); 130 | c2Fixture.setDensity(0.5); 131 | Rectangle rm = new Rectangle(2.0, 1.0); 132 | // translate the circles in local coordinates 133 | c1.translate(-1.0, 0.0); 134 | c2.translate(1.0, 0.0); 135 | SimulationBody capsule = new SimulationBody(); 136 | capsule.addFixture(c1Fixture); 137 | capsule.addFixture(c2Fixture); 138 | capsule.addFixture(rm); 139 | capsule.setMass(MassType.NORMAL); 140 | capsule.translate(0.0, 4.0); 141 | this.world.addBody(capsule); 142 | 143 | SimulationBody issTri = new SimulationBody(); 144 | issTri.addFixture(Geometry.createIsoscelesTriangle(1.0, 3.0)); 145 | issTri.setMass(MassType.NORMAL); 146 | issTri.translate(2.0, 3.0); 147 | this.world.addBody(issTri); 148 | 149 | SimulationBody equTri = new SimulationBody(); 150 | equTri.addFixture(Geometry.createEquilateralTriangle(2.0)); 151 | equTri.setMass(MassType.NORMAL); 152 | equTri.translate(3.0, 3.0); 153 | this.world.addBody(equTri); 154 | 155 | SimulationBody rightTri = new SimulationBody(); 156 | rightTri.addFixture(Geometry.createRightTriangle(2.0, 1.0)); 157 | rightTri.setMass(MassType.NORMAL); 158 | rightTri.translate(4.0, 3.0); 159 | this.world.addBody(rightTri); 160 | 161 | SimulationBody cap = new SimulationBody(); 162 | cap.addFixture(new Capsule(1.0, 0.5)); 163 | cap.setMass(MassType.NORMAL); 164 | cap.translate(-3.0, 3.0); 165 | this.world.addBody(cap); 166 | 167 | SimulationBody slice = new SimulationBody(); 168 | slice.addFixture(new Slice(0.5, Math.toRadians(120))); 169 | slice.setMass(MassType.NORMAL); 170 | slice.translate(-3.0, 3.0); 171 | this.world.addBody(slice); 172 | } 173 | 174 | /* (non-Javadoc) 175 | * @see org.dyn4j.samples.framework.SimulationFrame#initializeCamera(org.dyn4j.samples.framework.Camera) 176 | */ 177 | @Override 178 | protected void initializeCamera(Camera camera) { 179 | super.initializeCamera(camera); 180 | camera.scale = 45.0; 181 | } 182 | 183 | /** 184 | * Entry point for the example application. 185 | * @param args command line arguments 186 | */ 187 | public static void main(String[] args) { 188 | UsingGraphics2D simulation = new UsingGraphics2D(); 189 | simulation.run(); 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /src/main/java/org/dyn4j/samples/framework/Camera.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2021 William Bittle http://www.dyn4j.org/ 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted 6 | * provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, this list of conditions 9 | * and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | * and the following disclaimer in the documentation and/or other materials provided with the 12 | * distribution. 13 | * * Neither the name of dyn4j nor the names of its contributors may be used to endorse or 14 | * promote products derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 23 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | package org.dyn4j.samples.framework; 26 | 27 | import java.awt.Point; 28 | 29 | import org.dyn4j.geometry.Vector2; 30 | 31 | /** 32 | * Stores the zoom and panning state of the camera. 33 | * @author William Bittle 34 | * @version 4.1.1 35 | * @since 4.1.1 36 | */ 37 | public class Camera { 38 | /** The scale (zoom) in pixels per meter */ 39 | public double scale; 40 | 41 | /** The pan-x in pixels */ 42 | public double offsetX; 43 | 44 | /** The pan-y in pixels */ 45 | public double offsetY; 46 | 47 | /** 48 | * Returns World coordinates for the given point given the width/height of the viewport. 49 | * @param width the viewport width 50 | * @param height the viewport height 51 | * @param p the point 52 | * @return Vector2 53 | */ 54 | public final Vector2 toWorldCoordinates(double width, double height, Point p) { 55 | if (p != null) { 56 | Vector2 v = new Vector2(); 57 | // convert the screen space point to world space 58 | v.x = (p.getX() - width * 0.5 - this.offsetX) / this.scale; 59 | v.y = -(p.getY() - height * 0.5 + this.offsetY) / this.scale; 60 | return v; 61 | } 62 | 63 | return null; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/org/dyn4j/samples/framework/SimulationBody.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2022 William Bittle http://www.dyn4j.org/ 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted 6 | * provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, this list of conditions 9 | * and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | * and the following disclaimer in the documentation and/or other materials provided with the 12 | * distribution. 13 | * * Neither the name of dyn4j nor the names of its contributors may be used to endorse or 14 | * promote products derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 23 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | package org.dyn4j.samples.framework; 26 | 27 | import java.awt.Color; 28 | import java.awt.Graphics2D; 29 | import java.awt.geom.AffineTransform; 30 | import java.awt.geom.Ellipse2D; 31 | 32 | import org.dyn4j.dynamics.Body; 33 | import org.dyn4j.dynamics.BodyFixture; 34 | import org.dyn4j.geometry.Convex; 35 | 36 | /** 37 | * Custom Body class to add drawing functionality. 38 | * @author William Bittle 39 | * @version 3.2.1 40 | * @since 3.0.0 41 | */ 42 | public class SimulationBody extends Body { 43 | /** The color of the object */ 44 | protected Color color; 45 | 46 | /** 47 | * Default constructor. 48 | */ 49 | public SimulationBody() { 50 | this.color = Graphics2DRenderer.getRandomColor(); 51 | } 52 | 53 | /** 54 | * Constructor. 55 | * @param color a set color 56 | */ 57 | public SimulationBody(Color color) { 58 | this.color = color; 59 | } 60 | 61 | /** 62 | * Draws the body. 63 | *

64 | * Only coded for polygons and circles. 65 | * @param g the graphics object to render to 66 | * @param scale the scaling factor 67 | */ 68 | public void render(Graphics2D g, double scale) { 69 | this.render(g, scale, this.color); 70 | } 71 | 72 | /** 73 | * Draws the body. 74 | *

75 | * Only coded for polygons and circles. 76 | * @param g the graphics object to render to 77 | * @param scale the scaling factor 78 | * @param color the color to render the body 79 | */ 80 | public void render(Graphics2D g, double scale, Color color) { 81 | // point radius 82 | final int pr = 4; 83 | 84 | // save the original transform 85 | AffineTransform ot = g.getTransform(); 86 | 87 | // transform the coordinate system from world coordinates to local coordinates 88 | AffineTransform lt = new AffineTransform(); 89 | lt.translate(this.transform.getTranslationX() * scale, this.transform.getTranslationY() * scale); 90 | lt.rotate(this.transform.getRotationAngle()); 91 | 92 | // apply the transform 93 | g.transform(lt); 94 | 95 | // loop over all the body fixtures for this body 96 | for (BodyFixture fixture : this.fixtures) { 97 | this.renderFixture(g, scale, fixture, color); 98 | } 99 | 100 | // draw a center point 101 | Ellipse2D.Double ce = new Ellipse2D.Double( 102 | this.getLocalCenter().x * scale - pr * 0.5, 103 | this.getLocalCenter().y * scale - pr * 0.5, 104 | pr, 105 | pr); 106 | g.setColor(Color.WHITE); 107 | g.fill(ce); 108 | g.setColor(Color.DARK_GRAY); 109 | g.draw(ce); 110 | 111 | // set the original transform 112 | g.setTransform(ot); 113 | } 114 | 115 | /** 116 | * Renders the given fixture. 117 | * @param g the graphics object to render to 118 | * @param scale the scaling factor 119 | * @param fixture the fixture to render 120 | * @param color the color to render the fixture 121 | */ 122 | protected void renderFixture(Graphics2D g, double scale, BodyFixture fixture, Color color) { 123 | // get the shape on the fixture 124 | Convex convex = fixture.getShape(); 125 | 126 | // brighten the color if asleep 127 | if (this.isAtRest()) { 128 | color = color.brighter(); 129 | } 130 | 131 | // render the fixture 132 | Graphics2DRenderer.render(g, convex, scale, color); 133 | } 134 | 135 | /** 136 | * Returns this body's color. 137 | * @return Color 138 | */ 139 | public Color getColor() { 140 | return this.color; 141 | } 142 | 143 | /** 144 | * Sets the body's color 145 | * @param color the color 146 | */ 147 | public void setColor(Color color) { 148 | this.color = color; 149 | } 150 | } -------------------------------------------------------------------------------- /src/main/java/org/dyn4j/samples/framework/input/AbstractInputHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2022 William Bittle http://www.dyn4j.org/ 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted 6 | * provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, this list of conditions 9 | * and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | * and the following disclaimer in the documentation and/or other materials provided with the 12 | * distribution. 13 | * * Neither the name of dyn4j nor the names of its contributors may be used to endorse or 14 | * promote products derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 23 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | package org.dyn4j.samples.framework.input; 26 | 27 | import java.util.ArrayList; 28 | import java.util.List; 29 | 30 | public abstract class AbstractInputHandler implements InputHandler { 31 | private boolean enabled; 32 | private boolean additive; 33 | private final List dependentBehaviors; 34 | 35 | public AbstractInputHandler() { 36 | this.enabled = true; 37 | this.additive = false; 38 | this.dependentBehaviors = new ArrayList(); 39 | } 40 | 41 | @Override 42 | public boolean isEnabled() { 43 | return this.enabled; 44 | } 45 | 46 | @Override 47 | public void setEnabled(boolean flag) { 48 | this.enabled = flag; 49 | } 50 | 51 | public List getDependentBehaviors() { 52 | return this.dependentBehaviors; 53 | } 54 | 55 | @Override 56 | public boolean isDependentBehaviorActive() { 57 | boolean result = false; 58 | for (InputHandler behavior : this.dependentBehaviors) { 59 | if (behavior.isActive()) { 60 | result = true; 61 | } 62 | } 63 | if (this.additive) return !result; 64 | return result; 65 | } 66 | 67 | @Override 68 | public boolean isDependentBehaviorsAdditive() { 69 | return this.additive; 70 | } 71 | 72 | @Override 73 | public void setDependentBehaviorsAdditive(boolean flag) { 74 | this.additive = flag; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/org/dyn4j/samples/framework/input/AbstractKeyboardInputHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2022 William Bittle http://www.dyn4j.org/ 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted 6 | * provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, this list of conditions 9 | * and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | * and the following disclaimer in the documentation and/or other materials provided with the 12 | * distribution. 13 | * * Neither the name of dyn4j nor the names of its contributors may be used to endorse or 14 | * promote products derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 23 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | package org.dyn4j.samples.framework.input; 26 | 27 | import java.awt.Component; 28 | import java.awt.event.KeyAdapter; 29 | import java.awt.event.KeyEvent; 30 | 31 | public abstract class AbstractKeyboardInputHandler extends AbstractInputHandler implements InputHandler { 32 | protected final Component component; 33 | protected final Key[] keys; 34 | 35 | private final KeyAdapter keyAdapter; 36 | 37 | public AbstractKeyboardInputHandler(Component component, Key... keys) { 38 | this.component = component; 39 | this.keys = keys; 40 | this.keyAdapter = new CustomKeyListener(); 41 | } 42 | 43 | public AbstractKeyboardInputHandler(Component component, int... keys) { 44 | this.component = component; 45 | this.keyAdapter = new CustomKeyListener(); 46 | this.keys = new Key[keys.length]; 47 | for (int i = 0; i < keys.length; i++) { 48 | this.keys[i] = new Key(keys[i]); 49 | } 50 | 51 | } 52 | 53 | private boolean isKeyMatch(int key, int modifiers) { 54 | for (int i = 0; i < this.keys.length; i++) { 55 | if (this.keys[i].key == key && this.keys[i].modifiers == modifiers) 56 | return true; 57 | } 58 | return false; 59 | } 60 | 61 | /** 62 | * Custom key adapter to listen for key events. 63 | * @author William Bittle 64 | * @version 3.2.1 65 | * @since 3.2.0 66 | */ 67 | private class CustomKeyListener extends KeyAdapter { 68 | @Override 69 | public void keyPressed(KeyEvent e) { 70 | if (e.isConsumed()) return; 71 | // System.out.println(e.getKeyChar() + " " + e.getKeyCode() + " " + e.getModifiersEx()); 72 | if (isKeyMatch(e.getKeyCode(), e.getModifiersEx())) { 73 | if (isEnabled() && !isDependentBehaviorActive()) { 74 | onKeyPressed(); 75 | } 76 | } 77 | } 78 | 79 | @Override 80 | public void keyReleased(KeyEvent e) { 81 | if (e.isConsumed()) return; 82 | 83 | if (isKeyMatch(e.getKeyCode(), e.getModifiersEx())) { 84 | if (isEnabled() && !isDependentBehaviorActive()) { 85 | onKeyReleased(); 86 | } 87 | } 88 | } 89 | } 90 | 91 | @Override 92 | public void install() { 93 | this.component.addKeyListener(this.keyAdapter); 94 | } 95 | 96 | @Override 97 | public void uninstall() { 98 | this.component.removeKeyListener(this.keyAdapter); 99 | } 100 | 101 | protected void onKeyPressed() { 102 | 103 | } 104 | 105 | protected void onKeyReleased() { 106 | 107 | } 108 | } -------------------------------------------------------------------------------- /src/main/java/org/dyn4j/samples/framework/input/AbstractMouseInputHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2022 William Bittle http://www.dyn4j.org/ 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted 6 | * provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, this list of conditions 9 | * and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | * and the following disclaimer in the documentation and/or other materials provided with the 12 | * distribution. 13 | * * Neither the name of dyn4j nor the names of its contributors may be used to endorse or 14 | * promote products derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 23 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | package org.dyn4j.samples.framework.input; 26 | 27 | import java.awt.Component; 28 | import java.awt.Point; 29 | import java.awt.event.MouseAdapter; 30 | import java.awt.event.MouseEvent; 31 | import java.awt.event.MouseWheelEvent; 32 | 33 | public abstract class AbstractMouseInputHandler extends AbstractInputHandler implements InputHandler { 34 | 35 | protected final Component component; 36 | protected final int button; 37 | 38 | private final MouseAdapter mouseAdapter; 39 | 40 | private Point dragCurrent; 41 | private Point dragStart; 42 | 43 | public AbstractMouseInputHandler(Component component, int button) { 44 | this.component = component; 45 | this.button = button; 46 | this.mouseAdapter = new CustomMouseAdapter(); 47 | } 48 | 49 | /** 50 | * A custom mouse adapter to track mouse drag events. 51 | * @author William Bittle 52 | * @version 3.2.1 53 | * @since 3.2.0 54 | */ 55 | private final class CustomMouseAdapter extends MouseAdapter { 56 | @Override 57 | public void mousePressed(MouseEvent e) { 58 | if (e.isConsumed()) return; 59 | 60 | if (e.getButton() == button) { 61 | // store the mouse click postion for use later 62 | dragCurrent = new Point(e.getX(), e.getY()); 63 | dragStart = dragCurrent; 64 | if (isEnabled() && !isDependentBehaviorActive()) { 65 | onMousePressed(dragStart); 66 | } 67 | } 68 | } 69 | 70 | @Override 71 | public void mouseDragged(MouseEvent e) { 72 | if (e.isConsumed()) return; 73 | 74 | dragCurrent = new Point(e.getX(), e.getY()); 75 | if (isEnabled() && !isDependentBehaviorActive() && dragStart != null) { 76 | onMouseDrag(dragStart, dragCurrent); 77 | } 78 | } 79 | 80 | @Override 81 | public void mouseReleased(MouseEvent e) { 82 | if (e.isConsumed()) return; 83 | 84 | if (e.getButton() == button) { 85 | dragCurrent = null; 86 | dragStart = null; 87 | if (isEnabled() && !isDependentBehaviorActive()) { 88 | onMouseRelease(); 89 | } 90 | } 91 | } 92 | 93 | @Override 94 | public void mouseWheelMoved(MouseWheelEvent e) { 95 | if (e.isConsumed()) return; 96 | 97 | double wheelRotation = e.getWheelRotation(); 98 | if (isEnabled() && !isDependentBehaviorActive()) { 99 | onMouseWheel(wheelRotation); 100 | } 101 | } 102 | } 103 | 104 | @Override 105 | public void install() { 106 | this.component.addMouseListener(this.mouseAdapter); 107 | this.component.addMouseMotionListener(this.mouseAdapter); 108 | this.component.addMouseWheelListener(this.mouseAdapter); 109 | } 110 | 111 | @Override 112 | public void uninstall() { 113 | this.component.removeMouseListener(this.mouseAdapter); 114 | this.component.removeMouseMotionListener(this.mouseAdapter); 115 | this.component.removeMouseWheelListener(this.mouseAdapter); 116 | } 117 | 118 | @Override 119 | public void setEnabled(boolean flag) { 120 | super.setEnabled(flag); 121 | if (!flag) { 122 | this.dragCurrent = null; 123 | this.dragStart = null; 124 | } 125 | } 126 | 127 | protected void onMousePressed(Point point) { 128 | 129 | } 130 | 131 | protected void onMouseDrag(Point start, Point current) { 132 | 133 | } 134 | 135 | protected void onMouseRelease() { 136 | 137 | } 138 | 139 | protected void onMouseWheel(double rotation) { 140 | 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /src/main/java/org/dyn4j/samples/framework/input/BooleanStateKeyboardInputHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2022 William Bittle http://www.dyn4j.org/ 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted 6 | * provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, this list of conditions 9 | * and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | * and the following disclaimer in the documentation and/or other materials provided with the 12 | * distribution. 13 | * * Neither the name of dyn4j nor the names of its contributors may be used to endorse or 14 | * promote products derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 23 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | package org.dyn4j.samples.framework.input; 26 | 27 | import java.awt.Component; 28 | 29 | public class BooleanStateKeyboardInputHandler extends AbstractKeyboardInputHandler { 30 | /** If the key state is active (pressed) */ 31 | private boolean active; 32 | 33 | /** True if the active state has been handled */ 34 | private boolean hasBeenHandled; 35 | 36 | public BooleanStateKeyboardInputHandler(Component component, Key... keys) { 37 | super(component, keys); 38 | this.active = false; 39 | this.hasBeenHandled = false; 40 | } 41 | 42 | public BooleanStateKeyboardInputHandler(Component component, int... keys) { 43 | super(component, keys); 44 | this.active = false; 45 | this.hasBeenHandled = false; 46 | } 47 | 48 | @Override 49 | protected void onKeyPressed() { 50 | super.onKeyPressed(); 51 | 52 | // save the old state 53 | boolean active = this.active; 54 | 55 | // set the state to active 56 | this.active = true; 57 | 58 | // if the state transitioned from inactive to active 59 | // flag that it needs to be handled 60 | if (!active) { 61 | this.hasBeenHandled = false; 62 | } 63 | } 64 | 65 | @Override 66 | protected void onKeyReleased() { 67 | super.onKeyReleased(); 68 | this.active = false; 69 | } 70 | 71 | @Override 72 | public boolean isActive() { 73 | return this.active; 74 | } 75 | 76 | public boolean isActiveButNotHandled() { 77 | if (this.hasBeenHandled) 78 | return false; 79 | 80 | return this.active; 81 | } 82 | 83 | public void setHasBeenHandled(boolean hasBeenHandled) { 84 | this.hasBeenHandled = hasBeenHandled; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/org/dyn4j/samples/framework/input/BooleanStateMouseInputHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2022 William Bittle http://www.dyn4j.org/ 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted 6 | * provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, this list of conditions 9 | * and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | * and the following disclaimer in the documentation and/or other materials provided with the 12 | * distribution. 13 | * * Neither the name of dyn4j nor the names of its contributors may be used to endorse or 14 | * promote products derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 23 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | package org.dyn4j.samples.framework.input; 26 | 27 | import java.awt.Component; 28 | import java.awt.Point; 29 | 30 | public final class BooleanStateMouseInputHandler extends AbstractMouseInputHandler { 31 | private final Object lock; 32 | 33 | private boolean active; 34 | private Point location; 35 | private boolean hasBeenHandled; 36 | 37 | public BooleanStateMouseInputHandler(Component component, int button) { 38 | super(component, button); 39 | this.lock = new Object(); 40 | } 41 | 42 | @Override 43 | protected void onMousePressed(Point point) { 44 | super.onMousePressed(point); 45 | synchronized (this.lock) { 46 | boolean active = this.active; 47 | 48 | this.active = true; 49 | this.location = point; 50 | 51 | // if the state transitioned from inactive to active 52 | // flag that it needs to be handled 53 | if (!active) { 54 | this.hasBeenHandled = false; 55 | } 56 | } 57 | } 58 | 59 | @Override 60 | protected void onMouseRelease() { 61 | this.active = false; 62 | super.onMouseRelease(); 63 | } 64 | 65 | @Override 66 | public void setEnabled(boolean flag) { 67 | super.setEnabled(flag); 68 | if (!flag) { 69 | this.clearState(); 70 | } 71 | } 72 | 73 | @Override 74 | public void uninstall() { 75 | super.uninstall(); 76 | this.clearState(); 77 | } 78 | 79 | private void clearState() { 80 | this.active = false; 81 | this.location = null; 82 | this.hasBeenHandled = false; 83 | } 84 | 85 | public Point getMouseLocation() { 86 | synchronized (this.lock) { 87 | return this.location; 88 | } 89 | } 90 | 91 | @Override 92 | public boolean isActive() { 93 | return this.active; 94 | } 95 | 96 | public boolean isActiveButNotHandled() { 97 | if (this.hasBeenHandled) 98 | return false; 99 | 100 | return this.active; 101 | } 102 | 103 | public void setHasBeenHandled(boolean hasBeenHandled) { 104 | this.hasBeenHandled = hasBeenHandled; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/main/java/org/dyn4j/samples/framework/input/ExportCodeKeyboardInputHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2022 William Bittle http://www.dyn4j.org/ 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted 6 | * provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, this list of conditions 9 | * and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | * and the following disclaimer in the documentation and/or other materials provided with the 12 | * distribution. 13 | * * Neither the name of dyn4j nor the names of its contributors may be used to endorse or 14 | * promote products derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 23 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | package org.dyn4j.samples.framework.input; 26 | 27 | import java.awt.Component; 28 | 29 | import org.dyn4j.samples.framework.SimulationBody; 30 | import org.dyn4j.world.World; 31 | 32 | public class ExportCodeKeyboardInputHandler extends AbstractKeyboardInputHandler { 33 | private final World world; 34 | 35 | public ExportCodeKeyboardInputHandler(Component component, int key, World world) { 36 | super(component, new Key(key)); 37 | this.world = world; 38 | } 39 | 40 | @Override 41 | protected void onKeyPressed() { 42 | super.onKeyPressed(); 43 | System.out.println(CodeExporter.export("SampleExport", this.world)); 44 | } 45 | 46 | @Override 47 | public boolean isActive() { 48 | return false; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/org/dyn4j/samples/framework/input/InputHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2022 William Bittle http://www.dyn4j.org/ 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted 6 | * provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, this list of conditions 9 | * and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | * and the following disclaimer in the documentation and/or other materials provided with the 12 | * distribution. 13 | * * Neither the name of dyn4j nor the names of its contributors may be used to endorse or 14 | * promote products derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 23 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | package org.dyn4j.samples.framework.input; 26 | 27 | import java.util.List; 28 | 29 | public interface InputHandler { 30 | public void install(); 31 | public void uninstall(); 32 | public boolean isEnabled(); 33 | public void setEnabled(boolean flag); 34 | public boolean isActive(); 35 | 36 | public List getDependentBehaviors(); 37 | public boolean isDependentBehaviorActive(); 38 | public boolean isDependentBehaviorsAdditive(); 39 | public void setDependentBehaviorsAdditive(boolean flag); 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/dyn4j/samples/framework/input/Key.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2022 William Bittle http://www.dyn4j.org/ 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted 6 | * provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, this list of conditions 9 | * and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | * and the following disclaimer in the documentation and/or other materials provided with the 12 | * distribution. 13 | * * Neither the name of dyn4j nor the names of its contributors may be used to endorse or 14 | * promote products derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 23 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | package org.dyn4j.samples.framework.input; 26 | 27 | /** 28 | * Represents a key code and modifiers. 29 | * @author William Bittle 30 | * @since 5.0.0 31 | * @version 5.0.0 32 | */ 33 | public final class Key { 34 | public final int key; 35 | public final int modifiers; 36 | 37 | public Key(int key) { 38 | this.key = key; 39 | this.modifiers = 0; 40 | } 41 | 42 | public Key(int key, int modifiers) { 43 | this.key = key; 44 | this.modifiers = modifiers; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/org/dyn4j/samples/framework/input/MousePanningInputHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2022 William Bittle http://www.dyn4j.org/ 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted 6 | * provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, this list of conditions 9 | * and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | * and the following disclaimer in the documentation and/or other materials provided with the 12 | * distribution. 13 | * * Neither the name of dyn4j nor the names of its contributors may be used to endorse or 14 | * promote products derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 23 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | package org.dyn4j.samples.framework.input; 26 | 27 | import java.awt.Component; 28 | import java.awt.Point; 29 | import java.awt.event.MouseEvent; 30 | 31 | import org.dyn4j.geometry.Vector2; 32 | 33 | public final class MousePanningInputHandler extends AbstractMouseInputHandler implements InputHandler { 34 | private final Object lock; 35 | 36 | private boolean panning; 37 | private Point start; 38 | 39 | private double x; 40 | private double y; 41 | 42 | public MousePanningInputHandler(Component component) { 43 | super(component, MouseEvent.BUTTON1); 44 | this.panning = false; 45 | this.lock = new Object(); 46 | } 47 | 48 | @Override 49 | protected void onMousePressed(Point point) { 50 | super.onMousePressed(point); 51 | this.handleMouseStart(point); 52 | } 53 | 54 | @Override 55 | protected void onMouseDrag(Point start, Point current) { 56 | super.onMouseDrag(start, current); 57 | this.handleMouseDrag(current); 58 | } 59 | 60 | @Override 61 | protected void onMouseRelease() { 62 | this.clearPanningState(); 63 | super.onMouseRelease(); 64 | } 65 | 66 | @Override 67 | public void setEnabled(boolean flag) { 68 | super.setEnabled(flag); 69 | if (!flag) { 70 | this.clearPanningState(); 71 | } 72 | } 73 | 74 | @Override 75 | public boolean isActive() { 76 | return this.panning; 77 | } 78 | 79 | @Override 80 | public void uninstall() { 81 | super.uninstall(); 82 | this.clearPanningState(); 83 | } 84 | 85 | private boolean handleMouseStart(Point start) { 86 | this.panning = true; 87 | this.start = start; 88 | return true; 89 | } 90 | 91 | private boolean handleMouseDrag(Point current) { 92 | this.panning = true; 93 | 94 | double x = current.getX() - this.start.getX(); 95 | double y = current.getY() - this.start.getY(); 96 | 97 | // input from the mouse should be queued for processing 98 | // to avoid mid-render changes to the camera 99 | // input from AWT is coming in from the main thread of 100 | // AWT, but rendering is performed on a different thread 101 | // as such we should lock on the changes just to be sure 102 | // we don't lose information 103 | synchronized (this.lock) { 104 | this.x += x; 105 | this.y -= y; 106 | } 107 | 108 | this.start = current; 109 | 110 | return true; 111 | } 112 | 113 | private void clearPanningState() { 114 | this.panning = false; 115 | this.start = null; 116 | } 117 | 118 | public Vector2 getOffsetAndReset() { 119 | synchronized (this.lock) { 120 | Vector2 offset = new Vector2(this.x, this.y); 121 | this.x = 0; 122 | this.y = 0; 123 | return offset; 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/main/java/org/dyn4j/samples/framework/input/MousePickingInputHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2022 William Bittle http://www.dyn4j.org/ 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted 6 | * provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, this list of conditions 9 | * and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | * and the following disclaimer in the documentation and/or other materials provided with the 12 | * distribution. 13 | * * Neither the name of dyn4j nor the names of its contributors may be used to endorse or 14 | * promote products derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 23 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | package org.dyn4j.samples.framework.input; 26 | 27 | import java.awt.Component; 28 | import java.awt.Point; 29 | import java.awt.event.MouseEvent; 30 | import java.util.Iterator; 31 | 32 | import org.dyn4j.dynamics.BodyFixture; 33 | import org.dyn4j.dynamics.joint.Joint; 34 | import org.dyn4j.dynamics.joint.PinJoint; 35 | import org.dyn4j.geometry.AABB; 36 | import org.dyn4j.geometry.Vector2; 37 | import org.dyn4j.samples.framework.Camera; 38 | import org.dyn4j.samples.framework.SimulationBody; 39 | import org.dyn4j.world.World; 40 | import org.dyn4j.world.result.DetectResult; 41 | 42 | public class MousePickingInputHandler extends AbstractMouseInputHandler implements InputHandler { 43 | private final Object lock; 44 | private final Camera camera; 45 | private final World world; 46 | 47 | // state maintained by the main thread 48 | private boolean dragging; 49 | private Vector2 point; 50 | private SimulationBody body; 51 | 52 | // state maintained by the render thread 53 | private Joint mouseHandle; 54 | 55 | public MousePickingInputHandler(Component component, Camera camera, World world) { 56 | super(component, MouseEvent.BUTTON1); 57 | this.lock = new Object(); 58 | this.camera = camera; 59 | this.world = world; 60 | } 61 | 62 | @Override 63 | protected void onMousePressed(Point point) { 64 | super.onMousePressed(point); 65 | this.handleMouseStartOrDrag(point); 66 | } 67 | 68 | @Override 69 | protected void onMouseDrag(Point start, Point current) { 70 | super.onMouseDrag(start, current); 71 | this.handleMouseStartOrDrag(current); 72 | } 73 | 74 | @Override 75 | protected void onMouseRelease() { 76 | this.onReleaseCleanUp(); 77 | super.onMouseRelease(); 78 | } 79 | 80 | @Override 81 | public void setEnabled(boolean flag) { 82 | super.setEnabled(flag); 83 | if (!flag) { 84 | this.onReleaseCleanUp(); 85 | } 86 | } 87 | 88 | @Override 89 | public boolean isActive() { 90 | return this.dragging; 91 | } 92 | 93 | @Override 94 | public void uninstall() { 95 | super.uninstall(); 96 | this.onReleaseCleanUp(); 97 | } 98 | 99 | private boolean handleMouseStartOrDrag(Point point) { 100 | Vector2 p = this.camera.toWorldCoordinates(this.component.getWidth(), this.component.getHeight(), point); 101 | 102 | synchronized (this.lock) { 103 | this.point = p; 104 | 105 | if (!this.dragging) { 106 | SimulationBody body = this.getBodyAt(p); 107 | if (body != null) { 108 | this.dragging = true; 109 | this.body = body; 110 | return true; 111 | } 112 | } else { 113 | return true; 114 | } 115 | } 116 | 117 | return false; 118 | } 119 | 120 | private void onReleaseCleanUp() { 121 | synchronized (this.lock) { 122 | this.point = null; 123 | this.body = null; 124 | this.dragging = false; 125 | } 126 | } 127 | 128 | public SimulationBody getBody() { 129 | if (this.mouseHandle != null) { 130 | return this.mouseHandle.getBody(0); 131 | } 132 | return null; 133 | } 134 | 135 | private SimulationBody getBodyAt(Vector2 p) { 136 | SimulationBody body = null; 137 | 138 | // detect bodies under the mouse pointer 139 | AABB aabb = new AABB(new Vector2(p.x, p.y), 0.0001); 140 | Iterator> it = this.world.detectIterator(aabb, null); 141 | while (it.hasNext()) { 142 | SimulationBody b = it.next().getBody(); 143 | 144 | // ignore infinite bodies 145 | if (b.getMass().isInfinite()) { 146 | continue; 147 | } 148 | 149 | // check point contains and take the first 150 | // one found 151 | if (b.contains(p)) { 152 | body = b; 153 | break; 154 | } 155 | } 156 | 157 | return body; 158 | } 159 | 160 | private Joint createControlJoint(SimulationBody body, Vector2 p) { 161 | PinJoint pj = new PinJoint(body, new Vector2(p.x, p.y)); 162 | pj.setSpringEnabled(true); 163 | pj.setSpringFrequency(4.0); 164 | pj.setSpringDamperEnabled(true); 165 | pj.setSpringDampingRatio(0.3); 166 | pj.setMaximumSpringForceEnabled(true); 167 | pj.setMaximumSpringForce(500); 168 | return pj; 169 | } 170 | 171 | public void updateMousePickingState() { 172 | boolean dragging = false; 173 | Vector2 point = null; 174 | SimulationBody body = null; 175 | 176 | synchronized (this.lock) { 177 | dragging = this.dragging; 178 | point = this.point; 179 | body = this.body; 180 | } 181 | 182 | // 1. mouse picking begins 183 | if (dragging && this.mouseHandle == null && point != null) { 184 | // create a joint with the body 185 | Joint joint = this.createControlJoint(body, point); 186 | this.mouseHandle = joint; 187 | this.world.addJoint(joint); 188 | this.onPickingStart(body); 189 | return; 190 | } 191 | 192 | // 2. mouse picking continues 193 | if (dragging && this.mouseHandle != null && point != null) { 194 | Joint joint = this.mouseHandle; 195 | if (joint instanceof PinJoint) { 196 | PinJoint pj = (PinJoint)joint; 197 | pj.setTarget(new Vector2(point.x, point.y)); 198 | } 199 | return; 200 | } 201 | 202 | // 3. mouse picking ends 203 | if (!dragging) { 204 | if (this.mouseHandle != null) { 205 | this.world.removeJoint(this.mouseHandle); 206 | this.onPickingEnd(body); 207 | } 208 | this.mouseHandle = null; 209 | return; 210 | } 211 | } 212 | 213 | public void onPickingStart(SimulationBody body) { 214 | 215 | } 216 | 217 | public void onPickingEnd(SimulationBody body) { 218 | 219 | } 220 | } 221 | -------------------------------------------------------------------------------- /src/main/java/org/dyn4j/samples/framework/input/MouseZoomInputHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2022 William Bittle http://www.dyn4j.org/ 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted 6 | * provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, this list of conditions 9 | * and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | * and the following disclaimer in the documentation and/or other materials provided with the 12 | * distribution. 13 | * * Neither the name of dyn4j nor the names of its contributors may be used to endorse or 14 | * promote products derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 23 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | package org.dyn4j.samples.framework.input; 26 | 27 | import java.awt.Component; 28 | 29 | public final class MouseZoomInputHandler extends AbstractMouseInputHandler implements InputHandler { 30 | private final Object lock; 31 | 32 | private double scale; 33 | 34 | public MouseZoomInputHandler(Component component, int button) { 35 | super(component, button); 36 | this.lock = new Object(); 37 | this.scale = 1.0; 38 | } 39 | 40 | @Override 41 | public boolean isActive() { 42 | return false; 43 | } 44 | 45 | @Override 46 | protected void onMouseWheel(double rotation) { 47 | super.onMouseWheel(rotation); 48 | 49 | // this happen sometimes on trackpads 50 | if (rotation == 0) 51 | return; 52 | 53 | // input from the mouse should be queued for processing 54 | // to avoid mid-render changes to the camera 55 | // input from AWT is coming in from the main thread of 56 | // AWT, but rendering is performed on a different thread 57 | // as such we should lock on the changes just to be sure 58 | // we don't lose information 59 | synchronized (this.lock) { 60 | if (rotation > 0) { 61 | this.scale *= 0.8; 62 | } else { 63 | this.scale *= 1.2; 64 | } 65 | } 66 | } 67 | 68 | public double getScaleAndReset() { 69 | synchronized (this.lock) { 70 | double scale = this.scale; 71 | this.scale = 1.0; 72 | return scale; 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/org/dyn4j/samples/framework/input/ToggleStateKeyboardInputHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2022 William Bittle http://www.dyn4j.org/ 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted 6 | * provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, this list of conditions 9 | * and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | * and the following disclaimer in the documentation and/or other materials provided with the 12 | * distribution. 13 | * * Neither the name of dyn4j nor the names of its contributors may be used to endorse or 14 | * promote products derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 23 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | package org.dyn4j.samples.framework.input; 26 | 27 | import java.awt.Component; 28 | 29 | public class ToggleStateKeyboardInputHandler extends AbstractKeyboardInputHandler { 30 | 31 | private boolean active; 32 | 33 | public ToggleStateKeyboardInputHandler(Component component, Key... keys) { 34 | super(component, keys); 35 | this.active = false; 36 | } 37 | 38 | public ToggleStateKeyboardInputHandler(Component component, int... keys) { 39 | super(component, keys); 40 | this.active = false; 41 | } 42 | 43 | @Override 44 | protected void onKeyPressed() { 45 | super.onKeyPressed(); 46 | this.active = !this.active; 47 | } 48 | 49 | public void setActive(boolean flag) { 50 | this.active = flag; 51 | } 52 | 53 | @Override 54 | public boolean isActive() { 55 | return this.active; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/org/dyn4j/samples/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2016 William Bittle http://www.dyn4j.org/ 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted 6 | * provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, this list of conditions 9 | * and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | * and the following disclaimer in the documentation and/or other materials provided with the 12 | * distribution. 13 | * * Neither the name of dyn4j nor the names of its contributors may be used to endorse or 14 | * promote products derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 23 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | /** 27 | * A package containing sample applications to accelerate getting started. 28 | * @author William Bittle 29 | * @since 3.2.0 30 | * @version 3.2.0 31 | */ 32 | package org.dyn4j.samples; 33 | -------------------------------------------------------------------------------- /src/main/java/org/dyn4j/samples/resources/Basketball.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dyn4j/dyn4j-samples/747a479d3a0059f73a4de62d33b6003d387d933e/src/main/java/org/dyn4j/samples/resources/Basketball.png -------------------------------------------------------------------------------- /src/main/java/org/dyn4j/samples/resources/Crate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dyn4j/dyn4j-samples/747a479d3a0059f73a4de62d33b6003d387d933e/src/main/java/org/dyn4j/samples/resources/Crate.png --------------------------------------------------------------------------------