Giter VIP home page Giter VIP logo

cljbox2d's Introduction

cljbox2d

cljdoc badge Clojars Project

Idiomatic and cross-platform Clojure version of the Box2D physics engine API. Wraps jBox2D (Clojure) and Planck.js (ClojureScript).

Box2D is just a physics engine, you most likely want to combine it with a graphics library to show something on the screen. We bundle some helpers to get you started on Quil or Clojure2D, see the namespaces lambdaisland.cljbox2d.quil or lambdaisland.cljbox2d.clojure2d respectively, or browse the examples under lambdaisland.cljbox2d.demo.*

Rationale

The Box2D API is highly imperative, to create a body or a fixture you first create a BodyDef or FixtureDef object, call a bunch of setters to set the right parameters, then use that to construct the actual object. Yuck.

For us it's all just data. For comparison

;; create bodyDef
b2BodyDef groundBodyDef;
groundBodyDef.position.Set(0.0f, -10.0f);

;; use it to create a body
b2Body* groundBody = world.CreateBody(&groundBodyDef);

;; Add a fixture 
b2PolygonShape groundBox;
groundBox.SetAsBox(50.0f, 10.0f);
groundBody->CreateFixture(&groundBox, 0.0f);

With cljbox2d:

(b/populate world [{:position [0 -10]
                    :fixtures [{:shape [:rect 50 10]}]}])

Demos

Run these commands to see cljbox2d in action:

clojure -Sdeps '{:deps {com.lambdaisland/cljbox2d {:mvn/version "0.8.46"} quil/quil {:mvn/version "4.0.0-SNAPSHOT"}}}' -M -m lambdaisland.cljbox2d.demo.simple-shapes
clojure -Sdeps '{:deps {com.lambdaisland/cljbox2d {:mvn/version "0.8.46"} quil/quil {:mvn/version "4.0.0-SNAPSHOT"}}}' -M -m lambdaisland.cljbox2d.demo.pyramid
clojure -Sdeps '{:deps {com.lambdaisland/cljbox2d {:mvn/version "0.8.46"} quil/quil {:mvn/version "4.0.0-SNAPSHOT"}}}' -M -m lambdaisland.cljbox2d.demo.platformer

Or if you already have a REPL open then simply open any of the lambdaisland.cljbox2d.demo.* namespaces, evaluate them, and then run the (-main) function.

(require 'lambdaisland.cljbox2d.demo.pyramid)
(lambdaisland.cljbox2d.demo.pyramid/-main)

To start your own project you can copy lambdaisland.cljbox2d.demo.template (for Quil) or lambdaisland.cljbox2d.demo.clojure2d.template (for Clojure2D) over to your own project and take it from there.

Installation

To use the latest release, add the following to your deps.edn (Clojure CLI)

com.lambdaisland/cljbox2d {:mvn/version "0.8.46"}

or add the following to your project.clj (Leiningen)

[com.lambdaisland/cljbox2d "0.8.46"]

You will also need a library to deal with graphics and user interaction. If unsure you can start with Quil.

Getting started

There's a template file that you can use to set up your first project with cljbox2d and Quil.

You'll want to learn about the main Box2D concepts: bodies, shapes, fixtures, and joints. The clearest explanation I've come across is in these iForce2D tutorials: bodies, fixtures & shapes. There are also the official Box2D docs. Until we get more comprehensive documentation of our own together you'll have to make due with these, and the convert to cljbox2d.

The demos contain a number of examples you can study, from trivial (template, simple-shapes, pyramid), to more full-fledged (platformer).

Writing portable code

The following jBox2D features are not supported by planck.js

  • ConstantVolumeJoin
  • Particles (and thus particle raycast)

Lambda Island Open Source

 

cljbox2d is part of a growing collection of quality Clojure libraries created and maintained by the fine folks at Gaiwan.

Pay it forward by becoming a backer on our Open Collective, so that we may continue to enjoy a thriving Clojure ecosystem.

You can find an overview of our projects at lambdaisland/open-source.

 

 

Contributing

Everyone has a right to submit patches to cljbox2d, and thus become a contributor.

Contributors MUST

  • adhere to the LambdaIsland Clojure Style Guide
  • write patches that solve a problem. Start by stating the problem, then supply a minimal solution. *
  • agree to license their contributions as MPL 2.0.
  • not break the contract with downstream consumers. **
  • not break the tests.

Contributors SHOULD

  • update the CHANGELOG and README.
  • add tests for new functionality.

If you submit a pull request that adheres to these rules, then it will almost certainly be merged immediately. However some things may require more consideration. If you add new dependencies, or significantly increase the API surface, then we need to decide if these changes are in line with the project's goals. In this case you can start by writing a pitch, and collecting feedback on it.

* This goes for features too, a feature needs to solve a problem. State the problem it solves, then supply a minimal solution.

** As long as this project has not seen a public release (i.e. is not on Clojars) we may still consider making breaking changes, if there is consensus that the changes are justified.

License

Copyright © 2021-2022 Arne Brasseur and Contributors

Licensed under the term of the Mozilla Public License 2.0, see LICENSE.

cljbox2d's People

Contributors

folcon avatar genmeblog avatar plexus avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

cljbox2d's Issues

Instructions on how to use

Notes for others :)

  • comment out the lambdaisland/jbox2d-testbed-jogl dependency in deps.edn (gave me a "Could not find artifact" error)
  • run clj -Adev and then (require 'cljbox2d.demo) in the repl

Zoom never sets the zoom, just adds to it?

I was trying to use zoom! to change the zoom level to 1px = 1m away from the default of 100px = 1m.

However it was really unclear that zoom! is actually adding to the current zoom level instead of setting it.

In this case a doc to that effect or naming it zoom+! may be better?

So the correct operation is actually:

(b/zoom! -99)

not

(b/zoom! 1)

Otherwise this looks like quite a nice library, thanks for creating it!

Odd issues when following a processing tutorial

So I've been using this lib and following on with a series of tutorials by coding train and I'm seeing some odd behaviour + some minor issues. I thought it might be worthwhile documenting them here for the moment.

If they're in scope as things to fix to improve the library and need new issues focused on them to be opened for traceability / reproduction steps, happy to help and write up.

  1. Access Error, perhaps related to newer JVM versions:
        lambdaisland.cljbox2d/add-body                          cljbox2d.cljc                           :606
        clojure.core/run!                                       core.clj                                :7778
        clojure.core/reduce                                     core.clj                                :6885
        clojure.lang.PersistentVector::reduce                   PersistentVector.java                   :343
        clojure.core/run!/fn--8880                              core.clj                                :7783
        clojure.core/partial/fn--5908                           core.clj                                :2641
        lambdaisland.cljbox2d/add-fixture                       cljbox2d.cljc                           :593
        lambdaisland.cljbox2d/fixture-def                       cljbox2d.cljc                           :344
        clojure.lang.MultiFn::invoke                            MultiFn.java                            :229
        lambdaisland.cljbox2d/eval8293/fn--8295                 cljbox2d.cljc                           :265
IllegalAccessError: Update to non-static final field org.jbox2d.collision.shapes.CircleShape.m_p attempted from a different class (lambdaisland.cljbox2d$eval8293$fn__8295) than the field's declaring class

This occurred when I tried creating:

(b/add-body
  world
  {:position pos
   :type :dynamic
   :fixtures [{:shape [:circle [20 20] 20]}]})
  1. Access Error, on distance joint:
        lambdaisland.cljbox2d/add-joint                         cljbox2d.cljc                           :618
        lambdaisland.cljbox2d/joint-def                         cljbox2d.cljc                           :420
IllegalAccessError: Update to non-static final field org.jbox2d.dynamics.joints.DistanceJointDef.localAnchorA attempted from a different class (lambdaisland.cljbox2d$joint_def) than the field's declaring class

This occurred when I tried creating:

(b/add-joint
  world
  {:type :distance
   :bodies [(keyword (str next-id)) (keyword (str (inc next-id)))]
   :local-anchors [[0 0] [0 0]]
   :frequency 3
   :damping 0.1
   :length 32}]})

I'm trying to figure out a workaround for these and there is some information available however, getting the correct module name for org.jbox2d.dynamics.joints.DistanceJointDef is like pulling teeth...
"", does not appear to be acceptable with many variants of:

WARNING: Unknown module: org.jbox2d.dynamics specified to --add-opens

Trying to filter the module layer does not seem to work either:

(-> (java.lang.ModuleLayer/boot)
  (.modules)
  (.stream)
  (.filter (proxy [java.util.function.Predicate] []
             (test [i] (.contains (.getPackages i) "org.jbox2d"))))
  (.findAny))
=> #object[java.util.Optional 0x78e02422 "Optional.empty"]

I'll add more here as I find issues.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.