├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── Makefile ├── README.md ├── doc ├── Makefile ├── arbiter.adoc ├── body.adoc ├── collisionhandler.adoc ├── colony.css ├── constraint.adoc ├── datatypes.adoc ├── index.adoc ├── index.html ├── introduction.adoc ├── miscellanea.adoc ├── powered-by-lua.gif ├── preface.adoc ├── shape.adoc ├── space.adoc └── toolbox.adoc ├── examples ├── demo │ ├── 00-logo-smash.lua │ ├── 01-pyramid-stack.lua │ ├── 02-plink.lua │ ├── 03-bench.lua │ ├── 04-tumble.lua │ ├── 05-pyramid-topple.lua │ ├── 06-planet.lua │ ├── 07-springies.lua │ ├── 08-pump.lua │ ├── 09-theo-jansen.lua │ ├── 10-query.lua │ ├── 11-one-way.lua │ ├── 12-joints.lua │ ├── 13-tank.lua │ ├── 14-chains.lua │ ├── 15-crane.lua │ ├── 16-contact-graph.lua │ ├── 17-buoyancy.lua │ ├── 18-player.lua │ ├── 19-slice.lua │ ├── 20-convex.lua │ ├── 21-unicycle.lua │ ├── 22-sticky.lua │ └── 23-shatter.lua ├── enumsandflags.lua ├── hello.lua ├── sounds │ ├── Explosion_00.wav │ ├── Jingle_Win_00.wav │ ├── LICENSE │ └── Shoot_00.wav ├── sprites │ ├── LICENSE │ ├── awesomeface.png │ └── block.png ├── toolboxtest.lua ├── ttf-bitstream-vera-1.10 │ ├── COPYRIGHT.TXT │ ├── README.TXT │ ├── RELEASENOTES.TXT │ ├── Vera.ttf │ ├── VeraBI.ttf │ ├── VeraBd.ttf │ ├── VeraIt.ttf │ ├── VeraMoBI.ttf │ ├── VeraMoBd.ttf │ ├── VeraMoIt.ttf │ ├── VeraMono.ttf │ ├── VeraSe.ttf │ ├── VeraSeBd.ttf │ └── local.conf └── version.lua ├── moonchipmunk └── toolbox.lua ├── src ├── Makefile ├── _make ├── arbiter.c ├── body.c ├── circle.c ├── collision_handler.c ├── compat-5.3.c ├── compat-5.3.h ├── constraint.c ├── constraint.h ├── damped_rotary_spring.c ├── damped_spring.c ├── datastructs.c ├── enums.c ├── enums.h ├── flags.c ├── gear_joint.c ├── groove_joint.c ├── internal.h ├── main.c ├── misc.c ├── moonchipmunk.h ├── objects.c ├── objects.h ├── pin_joint.c ├── pivot_joint.c ├── poly.c ├── ratchet_joint.c ├── rotary_limit_joint.c ├── segment.c ├── shape.c ├── simple_motor.c ├── slide_joint.c ├── space.c ├── tracing.c ├── tree.h ├── udata.c ├── udata.h └── utils.c └── thirdparty ├── asciidoctor-styles-license ├── lua-compat-5.3-license ├── openbsd-tree-license └── powered-by-lua-license /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.dylib 3 | *.log 4 | *.so 5 | *.dll 6 | *.o 7 | *.swp 8 | *.symbols 9 | core.* 10 | local/ 11 | src/TODO 12 | src/DIFF 13 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.17) 2 | 3 | project(moonchipmunk) 4 | 5 | find_package(Lua REQUIRED) 6 | 7 | #needs to be manually created until chipmunk provides a chipmunkConfig.cmake 8 | find_package(chipmunk REQUIRED) 9 | 10 | add_library(moonchipmunk SHARED 11 | src/compat-5.3.h 12 | src/constraint.h 13 | src/enums.h 14 | src/internal.h 15 | src/moonchipmunk.h 16 | src/objects.h 17 | src/tree.h 18 | src/udata.h 19 | src/arbiter.c 20 | src/body.c 21 | src/circle.c 22 | src/collision_handler.c 23 | src/compat-5.3.c 24 | src/constraint.c 25 | src/damped_rotary_spring.c 26 | src/damped_spring.c 27 | src/datastructs.c 28 | src/enums.c 29 | src/flags.c 30 | src/gear_joint.c 31 | src/groove_joint.c 32 | src/main.c 33 | src/misc.c 34 | src/objects.c 35 | src/pin_joint.c 36 | src/pivot_joint.c 37 | src/poly.c 38 | src/ratchet_joint.c 39 | src/rotary_limit_joint.c 40 | src/segment.c 41 | src/shape.c 42 | src/simple_motor.c 43 | src/slide_joint.c 44 | src/space.c 45 | src/tracing.c 46 | src/udata.c 47 | src/utils.c 48 | ) 49 | 50 | target_include_directories(moonchipmunk PUBLIC 51 | ${LUA_INCLUDE_DIR} 52 | ${chipmunk_INCLUDE_DIR} 53 | ) 54 | 55 | target_link_libraries(moonchipmunk 56 | ${LUA_LIBRARIES} 57 | ${chipmunk_LIBS} 58 | ) 59 | 60 | install(TARGETS moonchipmunk LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) 61 | install(TARGETS moonchipmunk RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 62 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2020 Stefano Trettel 4 | 5 | Software repository: MoonChipmunk, https://github.com/stetre/moonchipmunk 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | 25 | 26 | (See also the THIRD-PARTY LICENSES contained in the thirdparty/ directory 27 | of the Software repository.) 28 | 29 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | default: build 3 | 4 | build install uninstall where: 5 | @cd src; $(MAKE) $@ 6 | 7 | clean : 8 | @cd src; $(MAKE) $@ 9 | @cd doc; $(MAKE) $@ 10 | 11 | docs: 12 | @cd doc; $(MAKE) 13 | 14 | cleanall: clean 15 | 16 | backup: clean 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## MoonChipmunk: Lua bindings for Chipmunk2D 2 | 3 | MoonChipmunk is a Lua binding library for Scott Lembcke's [Chipmunk2D](http://chipmunk-physics.net/) physics engine. 4 | 5 | It runs on GNU/Linux and on Windows (MSYS2/MinGW) and requires 6 | [Lua](http://www.lua.org/) (>=5.3) and [Chipmunk2D](http://chipmunk-physics.net/downloads.php) (>= 7.0.3). 7 | 8 | _Author:_ _[Stefano Trettel](https://www.linkedin.com/in/stetre)_ 9 | 10 | [![Lua logo](./doc/powered-by-lua.gif)](http://www.lua.org/) 11 | 12 | #### License 13 | 14 | MIT/X11 license (same as Lua). See [LICENSE](./LICENSE). 15 | 16 | #### Documentation 17 | 18 | See the [Reference Manual](https://stetre.github.io/moonchipmunk/doc/index.html). 19 | 20 | #### Getting and installing 21 | 22 | Setup the build environment as described [here](https://github.com/stetre/moonlibs), then: 23 | 24 | ```sh 25 | $ git clone https://github.com/stetre/moonchipmunk/ 26 | $ cd moonchipmunk 27 | moonchipmunk$ make 28 | moonchipmunk$ sudo make install 29 | ``` 30 | 31 | #### Example 32 | 33 | The example below is a port of the ["Hello Chipmunk (World)" example](http://chipmunk-physics.net/release/ChipmunkLatest-Docs/#Intro-HelloChipmunk) from the Chipmunk2D manual. 34 | 35 | Other examples, including a Lua port of the Chipmunk2D demos, can be found in the **examples/** directory. 36 | 37 | ```lua 38 | -- MoonChipmunk example: hello.lua 39 | local cp = require("moonchipmunk") 40 | 41 | -- Create an empty space and set the gravity for it. 42 | local space = cp.space_new() 43 | space:set_gravity({0, -100}) 44 | 45 | -- Add a static line segment shape for the ground. 46 | -- We'll make it slightly tilted so the ball will roll off. 47 | -- We attach it to a static body to tell Chipmunk it shouldn't be movable. 48 | local ground = cp.segment_shape_new(space:get_static_body(), {-20, 5}, {20, -5}, 0) 49 | ground:set_friction(1) 50 | space:add_shape(ground) 51 | 52 | -- Now let's make a ball that falls onto the line and rolls off. 53 | -- First we need to make a body to hold the physical properties of the object. 54 | -- These include the mass, position, velocity, angle, etc. of the object. 55 | -- Then we attach collision shapes to the body to give it a size and shape. 56 | local radius = 5 57 | local mass = 1 58 | -- The moment of inertia is like mass for rotation 59 | -- Use the cp.moment_for*() functions to help you approximate it. 60 | local moment = cp.moment_for_circle(mass, 0, radius, {0, 0}) 61 | 62 | -- The space:add*() methods return the thing that you are adding. 63 | -- It's convenient to create and add an object in one line. 64 | local ballBody = space:add_body(cp.body_new(mass, moment)) 65 | ballBody:set_position({0, 15}) 66 | 67 | -- Now we create the collision shape for the ball. 68 | -- You can create multiple collision shapes that point to the same body. 69 | -- They will all be attached to the body and move around to follow it. 70 | local ballShape = space:add_shape(cp.circle_shape_new(ballBody, radius, {0, 0})) 71 | ballShape:set_friction(0.7) 72 | 73 | -- Now that it's all set up, we simulate all the objects in the space by 74 | -- stepping forward through time in small increments called steps. 75 | -- It is *highly* recommended to use a fixed size time step. 76 | local timeStep = 1.0/60.0 77 | for time = 0, 2, timeStep do 78 | local pos = ballBody:get_position() 79 | local vel = ballBody:get_velocity() 80 | print(string.format( 81 | "Time is %5.2f. ballBody is at (%5.2f, %5.2f). It's velocity is (%5.2f, %5.2f)", 82 | time, pos[1], pos[2], vel[1], vel[2])) 83 | space:step(timeStep) 84 | end 85 | 86 | -- No need to delete objects here (they are are automatically deleted ad exit). 87 | ``` 88 | 89 | The script can be executed at the shell prompt with the standard Lua interpreter: 90 | 91 | ```shell 92 | $ lua hello.lua 93 | ``` 94 | 95 | #### See also 96 | 97 | * [MoonLibs - Graphics and Audio Lua Libraries](https://github.com/stetre/moonlibs). 98 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | TgtAdoc := index 2 | 3 | Stylesdir = ./ 4 | Stylesheet = colony.css 5 | Style = -a stylesheet=$(Stylesheet) -a stylesdir=$(Stylesdir) 6 | Style = 7 | 8 | Src = $(TgtAdoc).adoc 9 | 10 | default: html 11 | 12 | check: 13 | 14 | clean: 15 | @-rm -f *~ 16 | @-rm -f *.html 17 | 18 | install: 19 | 20 | html: clean 21 | @asciidoctor $(Style) $(Src) 22 | 23 | docs: html 24 | -------------------------------------------------------------------------------- /doc/arbiter.adoc: -------------------------------------------------------------------------------- 1 | 2 | [[arbiter]] 3 | === Arbiters 4 | 5 | [small]#Rfr: https://chipmunk-physics.net/release/ChipmunkLatest-API-Reference/group__cp_arbiter.html[cpArbiter].# 6 | 7 | From the point of view of the Lua scripts, an arbiter object is automatically created when it 8 | is received as argument to some callback function, and automatically deleted as soon as the 9 | function returns. 10 | 11 | [[arbiter_set_float]] 12 | * _arbiter_++:++*set_restitution*(_value_) + 13 | _arbiter_++:++*set_friction*(_value_) + 14 | _value_ = _arbiter_++:++*get_restitution*( ) + 15 | _value_ = _arbiter_++:++*get_friction*( ) + 16 | _value_ = _arbiter_++:++*total_ke*( ) + 17 | [small]#_value_: float.# 18 | 19 | [[arbiter_set_vec]] 20 | * _arbiter_++:++*set_surface_velocity*(<>) + 21 | <> = _arbiter_++:++*get_surface_velocity*( ) + 22 | <> = _arbiter_++:++*get_normal*( ) + 23 | <> = _arbiter_++:++*total_impulse*( ) + 24 | 25 | [[arbiter_get_boolean]] 26 | * _boolean_ = _arbiter_++:++*ignore*( ) + 27 | _boolean_ = _arbiter_++:++*is_first_contact*( ) + 28 | _boolean_ = _arbiter_++:++*is_removal*( ) + 29 | 30 | [[arbiter_get_shapes]] 31 | * <>, <> = _arbiter_++:++*get_shapes*( ) + 32 | <>, <> = _arbiter_++:++*get_bodies*( ) + 33 | 34 | [[arbiter_contact_point_set]] 35 | * _arbiter_++:++*set_contact_point_set*(_normal_, _{points}_) + 36 | _normal_, _{points}_ = _arbiter_++:++*get_contact_point_set*( ) + 37 | [small]#_normal_: <>. + 38 | _{points}_: {<>}.# 39 | 40 | [[arbiter_get_points]] 41 | * _npoints_ = _arbiter_++:++*get_count*( ) + 42 | _{point~a~}_, _{point~b~}_, _{depth}_ = _arbiter_++:++*get_points*( ) + 43 | [small]#_{point~a~}_, _{point~b~}_: {<>}. + 44 | _{depth}_: {float}.# 45 | 46 | [[arbiter_call_wildcard]] 47 | * _boolean_ = _arbiter_++:++*call_wildcard_begin_a*(_arbiter_, _space_) + 48 | _boolean_ = _arbiter_++:++*call_wildcard_begin_b*(_arbiter_, _space_) + 49 | _boolean_ = _arbiter_++:++*call_wildcard_pre_solve_a*(_arbiter_, _space_) + 50 | _boolean_ = _arbiter_++:++*call_wildcard_pre_solve_b*(_arbiter_, _space_) + 51 | _arbiter_++:++*call_wildcard_post_solve_a*(_arbiter_, _space_) + 52 | _arbiter_++:++*call_wildcard_post_solve_b*(_arbiter_, _space_) + 53 | _arbiter_++:++*call_wildcard_separate_a*(_arbiter_, _space_) + 54 | _arbiter_++:++*call_wildcard_separate_b*(_arbiter_, _space_) + 55 | 56 | [[arbiter_get_user_data]] 57 | * _value_ = _arbiter_++:++*get_user_index*( ) + 58 | _arbiter_++:++*set_user_index*(_value_) + 59 | [small]#Set/get a user-defined integer index associated with the arbiter. + 60 | This is a limited binding to _cpArbiterSetUserData( )_ and _cpArbiterGetUserData( )_: 61 | it doesn't allow you to directly associate a generic user data value with the arbiter, 62 | but you can store it in a table and associate with the arbiter the corresponding index instead. + 63 | Note that you can't use the _arbiter_ itself to index the user data table, because the arbiter Lua 64 | object is actually a singleton that is reused every time a _cpArbiter_ is passed to a callback. 65 | (From the Chipmunk Manual: _"[...] you should never store a reference to an arbiter as you don’t 66 | know when they will be freed or reused."_).# 67 | 68 | -------------------------------------------------------------------------------- /doc/body.adoc: -------------------------------------------------------------------------------- 1 | 2 | [[body]] 3 | === Rigid bodies 4 | 5 | [small]#Rfr: http://chipmunk-physics.net/release/ChipmunkLatest-API-Reference/group__cp_body.html[cpBody].# 6 | 7 | * _body_ = *body_new*(_mass_, _moment_) + 8 | _body_ = *body_new_kinematic*( ) + 9 | _body_ = *body_new_static*( ) + 10 | _body_++:++*free*( ) + 11 | [small]#Create/delete a rigid body.# 12 | 13 | [[body_get_space]] 14 | * <>|_nil_ = _body_++:++*get_space*( ) + 15 | 16 | [[body_set_type]] 17 | * _body_++:++*set_type*(_type_) + 18 | _type_ = _body_++:++*get_type*( ) + 19 | [small]#_type_: '_dynamic_' |, '_kinematic_' | '_static_'.# 20 | 21 | [[body_set_xxx]] 22 | * _body_++:++*set_mass*(_value_) + 23 | _body_++:++*set_moment*(_value_) + 24 | _body_++:++*set_angle*(_value_) + 25 | _body_++:++*set_angular_velocity*(_value_) + 26 | _body_++:++*set_torque*(_value_) + 27 | _value_ = _body_++:++*get_mass*( ) + 28 | _value_ = _body_++:++*get_moment*( ) + 29 | _value_ = _body_++:++*get_angle*( ) + 30 | _value_ = _body_++:++*get_angular_velocity*( ) + 31 | _value_ = _body_++:++*get_torque*( ) + 32 | _value_ = _body_++:++*kinetic_energy*( ) + 33 | [small]#_value_: float. + 34 | Angles are in radians.# 35 | 36 | [[body_set_vec]] 37 | * _body_++:++*set_position*(<>) + 38 | _body_++:++*set_center_of_gravity*(<>) + 39 | _body_++:++*set_velocity*(<>) + 40 | _body_++:++*set_force*(<>) + 41 | <> = _body_++:++*get_position*( ) + 42 | <> = _body_++:++*get_center_of_gravity*( ) + 43 | <> = _body_++:++*get_velocity*( ) + 44 | <> = _body_++:++*get_force*( ) + 45 | <> = _body_++:++*get_rotation*( ) 46 | 47 | [[body_local_to_world]] 48 | * <> = _body_++:++*local_to_world*(<>) + 49 | <> = _body_++:++*world_to_local*(<>) + 50 | <> = _body_++:++*get_velocity_at_world_point*(<>) + 51 | <> = _body_++:++*get_velocity_at_local_point*(<>) + 52 | 53 | [[body_apply_xxx]] 54 | * _body_++:++*apply_force_at_world_point*(_point_, _value_) + 55 | _body_++:++*apply_force_at_local_point*(_point_, _value_) + 56 | _body_++:++*apply_impulse_at_world_point*(_point_, _value_) + 57 | _body_++:++*apply_impulse_at_local_point*(_point_, _value_) + 58 | [small]#_point_, _value_: <>.# 59 | 60 | [[body_update]] 61 | * _body_++:++*update_position*(_dt_) + 62 | _body_++:++*update_velocity*(_gravity_, _damping_, _dt_) + 63 | _body_++:++*set_position_update_func*(_func_) + 64 | _body_++:++*set_velocity_update_func*(_func_) + 65 | [small]#_dt_, _damping_: float. + 66 | _gravity_: <>. + 67 | The update callbacks are executed as follows: + 68 | pass:[-] position update: *func(body, dt)*. + 69 | pass:[-] velocity update: *func(body, gravity, damping, dt)*.# 70 | 71 | 72 | 73 | [[body_sleep]] 74 | * _body_++:++*sleep*( ) + 75 | _body_++:++*sleep_with_group*([_group_]) + 76 | _body_++:++*activate*( ) + 77 | _body_++:++*activate_static*([_filter_]) + 78 | _boolean_ = _body_++:++*is_sleeping*( ) + 79 | [small]#_group_: <>. + 80 | _filter_: <>.# 81 | 82 | 83 | [[body_each_xxx]] 84 | * _body_++:++*each_shape*(_func_) + 85 | _body_++:++*each_constraint*(_func_) + 86 | _body_++:++*each_arbiter*(_func_) + 87 | [small]#Execute _func_ as *func(body, object)* for each object of the given type.# 88 | 89 | -------------------------------------------------------------------------------- /doc/collisionhandler.adoc: -------------------------------------------------------------------------------- 1 | 2 | [[collision_handler]] 3 | === Collision handlers 4 | 5 | [small]#Rfr: https://chipmunk-physics.net/release/ChipmunkLatest-API-Reference/structcp_collision_handler.html[cpCollisionHandler].# 6 | 7 | [[space_add_collision_handler]] 8 | * _collision_handler_ = _space_++:++*add_default_collision_handler*( ) + 9 | _collision_handler_ = _space_++:++*add_collision_handler*(_type~a~_, _type~b~_) + 10 | _collision_handler_ = _space_++:++*add_wildcard_handler*(_type_) + 11 | [small]#_type_, _type~a~_, _type~b~_: integer (cpCollisionType).# 12 | 13 | [[collision_handler_free]] 14 | * _collision_handler_++:++*free*( ) + 15 | [small]#Delete _collision_handler_.# 16 | 17 | [[collision_handler_xxx]] 18 | * _type~a~_, _type~b~_ = _collision_handler_++:++*get_types*( ) + 19 | _collision_handler_++:++*set_begin_func*(_func_) + 20 | _collision_handler_++:++*set_pre_solve_func*(_func_) + 21 | _collision_handler_++:++*set_post_solve_func*(_func_) + 22 | _collision_handler_++:++*set_separate_func*(_func_) + 23 | [small]#The callbacks are executed as follows: + 24 | pass:[-] begin: *boolean = func(<>, space)*. + 25 | pass:[-] pre solve: *boolean = func(<>, space)*. + 26 | pass:[-] post solve: *func(<>, space)*. + 27 | pass:[-] separate: *func(<>, space)*.# 28 | 29 | -------------------------------------------------------------------------------- /doc/datatypes.adoc: -------------------------------------------------------------------------------- 1 | 2 | [[datatypes]] 3 | == Data types 4 | 5 | In this document, the _float_ and _integer_ types denote Lua numbers, while other types 6 | such as _boolean_, _string_, etc denote standard Lua types. Note that _float_ 7 | here just means 'floating point' as opposed to 'integer', and does not imply 8 | single-precision (all numbers are actually represented internally using double-precision). 9 | 10 | Angles are always expressed in radians. 11 | 12 | Vectors, matrices, bounding boxes, and colors are by default represented as Lua arrays containing 13 | _float_ elements (or arrays of arrays in the case of matrices). The meaning of the elements 14 | thus depends on their position, as detailed below, and there is no syntactic sugar 15 | such as _v.x_ and _v.y_ to access them (unless one enables <>). 16 | 17 | A few other Chipmunk2D structs are represented as string-indexed Lua tables, also described below. 18 | 19 | * [[vec]] 20 | [small]#*vec* = {_x_, _y_} + 21 | All elements are floats. + 22 | (Rfr: http://chipmunk-physics.net/release/ChipmunkLatest-API-Reference/group__cp_vect.html[cpVect])# 23 | 24 | * [[mat]] 25 | [small]#*mat* = {{_a_, _c_, _tx_}, {_b_, _d_, _ty_}} + 26 | All elements are floats. + 27 | (Rfr: http://chipmunk-physics.net/release/ChipmunkLatest-API-Reference/structcp_transform.html[cpTransform])# 28 | 29 | * [[bb]] 30 | [small]#*bb* = {_l_, _r_, _b_, _t_} + 31 | All elements are floats. + 32 | Beware that the order is different than in _cpBB_ (where the order is _l_, _b_, _r_, _t_). + 33 | (Rfr: http://chipmunk-physics.net/release/ChipmunkLatest-API-Reference/structcp_b_b.html[cpBB])# 34 | 35 | * [[color]] 36 | [small]#*color* = {_r_, _g_, _b_, _a_} + 37 | All elements are floats, representing normalized color components (i.e. in the range _[0, 1]_). + 38 | (Rfr: cpSpaceDebugColor)# 39 | 40 | * [[shapefilter]] 41 | [small]#*shapefilter* = { + 42 | _group_: integer, + 43 | _categories_: integer, + 44 | _mask_: integer, + 45 | } (Rfr: http://chipmunk-physics.net/release/ChipmunkLatest-API-Reference/structcp_shape_filter.html[cpShapeFilter])# 46 | 47 | * [[pointqueryinfo]] 48 | [small]#*pointqueryinfo* = { + 49 | _shape_: <>, + 50 | _point_: <>, + 51 | _distance_: float, + 52 | _gradient_: <>, + 53 | } (Rfr: http://chipmunk-physics.net/release/ChipmunkLatest-API-Reference/structcp_point_query_info.html[cpPointQueryInfo])# 54 | 55 | * [[segmentqueryinfo]] 56 | [small]#*segmentqueryinfo* = { + 57 | _shape_: <>, + 58 | _point_: <>, + 59 | _normal_: <>, + 60 | _alpha_: float, + 61 | } (Rfr: http://chipmunk-physics.net/release/ChipmunkLatest-API-Reference/structcp_segment_query_info.html[cpSegmentQueryInfo])# 62 | 63 | * [[contactpoint]] 64 | [small]#*contactpoint* = { + 65 | _a_: <>, + 66 | _b_: <>, + 67 | _distance_: float, + 68 | } (Rfr: http://chipmunk-physics.net/release/ChipmunkLatest-API-Reference/structcp_contact_point_set.html[cpContactPointSet])# 69 | 70 | [[glmath_compat]] 71 | == GLMATH compatibility 72 | 73 | As an option, it is possible to instruct MoonChipmunk to return vectors, matrices, boxes, and colors 74 | as https://github.com/stetre/moonglmath[MoonGLMATH] types, instead of returning them as plain tables 75 | (which is the default). 76 | footnote:[MoonGLMATH types are convenient because they support operators and synctatic sugar, but I 77 | chose not to impose their use because one may want to use an alternative math library, or none at all.] 78 | 79 | In particular, when this functionality is enabled, functions and methods will return values 80 | of the following MoonGLMATH types: *vec2* instead of <>, *mat2x3* instead of <>, *box2* instead of <>, and *vec4* instead of <>. 81 | 82 | (Notice that for function arguments nothing changes, since the above MoonGLMATH types are compatible 83 | with the corresponding plain tables used by default, thus they can be used as function arguments in 84 | any case). 85 | 86 | Use the following functions to control GLMATH compatibility: 87 | 88 | * *glmath_compat*(_boolean_) + 89 | [small]#Enables/disables GLMATH compatibility (which by default is disabled). + 90 | Enabling this functionality requires MoonGLMATH to be installed.# 91 | 92 | * _boolean_ = *is_glmath_compat*( ) + 93 | [small]#Returns _true_ if GLMATH compatibility is enabled.# 94 | 95 | -------------------------------------------------------------------------------- /doc/index.adoc: -------------------------------------------------------------------------------- 1 | = MoonChipmunk Reference Manual 2 | Stefano Trettel 3 | v0.1, 2020-02-25 4 | :toc: left 5 | :toclevels: 3 6 | :stylesdir: ./ 7 | :stylesheet: colony.css 8 | :source-highlighter: pygments 9 | :pygments-style: autumn 10 | :source-language: lua 11 | :exampledir: ../examples 12 | 13 | image::powered-by-lua.gif[Lua logo, link=http://www.lua.org] 14 | 15 | // Macros for trees: {tS} = " ", {tI} = "│  ", {tH} = "├─ ", {tL} = "└─ " 16 | :tS:      17 | :tI: │    18 | :tH: ├─  19 | :tL: └─  20 | 21 | include::preface.adoc[] 22 | include::introduction.adoc[] 23 | 24 | == Objects 25 | 26 | Listed below are the Lua object types in MoonChipmunk, together with the corresponding 27 | original types in Chipmunk2D: 28 | 29 | [small]#Objects: + 30 | <> _(cpSpace, cpHastySpace)_ + 31 | <> _(cpBody)_ + 32 | <> _(cpShape)_ + 33 | {tH}<> _(cpCircleShape)_ + 34 | {tH}<> _(cpSegmentShape)_ + 35 | {tL}<> _(cpPolyShape)_ + 36 | <> _(cpConstraint)_ + 37 | {tH}<> _(cpPinJoint)_ + 38 | {tH}<> _(cpSlideJoint)_ + 39 | {tH}<> _(cpPivotJoint)_ + 40 | {tH}<> _(cpGrooveJoint)_ + 41 | {tH}<> _(cpDampedSpring)_ + 42 | {tH}<> _(cpDampedRotarySpring)_ + 43 | {tH}<> _(cpRotaryLimitJoint)_ + 44 | {tH}<> _(cpRatchetJoint)_ + 45 | {tH}<> _(cpGearJoint)_ + 46 | {tL}<> _(cpSimpleMotor)_ + 47 | <> _(cpCollisionHandler)_ + 48 | <> _(cpArbiter)_# 49 | 50 | 51 | include::space.adoc[] 52 | include::body.adoc[] 53 | include::shape.adoc[] 54 | include::constraint.adoc[] 55 | include::collisionhandler.adoc[] 56 | include::arbiter.adoc[] 57 | 58 | include::miscellanea.adoc[] 59 | include::datatypes.adoc[] 60 | include::toolbox.adoc[] 61 | 62 | 63 | -------------------------------------------------------------------------------- /doc/introduction.adoc: -------------------------------------------------------------------------------- 1 | 2 | == Introduction 3 | 4 | MoonChipmunk is an almost one-to-one Lua binding library to the Chipmunk2D physics engine. 5 | This means that by and large, it is intended to be used as described in the http://chipmunk-physics.net/release/ChipmunkLatest-Docs/[Chipmunk2D Manual] (apart from coding in Lua, of course). 6 | 7 | This section gives a brief overview of the binding library, while the details are given 8 | in the sections that follow. 9 | 10 | MoonChipmunk binds Chipmunk2D *objects* (_space_, _body_, etc.) to Lua userdata, which are 11 | returned by the creating functions (_cp.space_new_( ), _cp.body_new_( ), etc) and are then used to refer to objects in Lua in the same way as one would use Chipmunk2D handles in C. 12 | 13 | As a general rule, Chipmunk2D functions are bound to MoonChipmunk functions or methods 14 | whose names are https://en.wikipedia.org/wiki/Snake_case[snake_case] versions of the original ones. 15 | 16 | The functions related to an object type - with the exception of the creating function - are 17 | bounded to methods of that object (e.g. the C function _cpSpaceSetGravity(space,...)_ becomes the method _space:set_gravity(...)_ in Lua. 18 | 19 | Objects are *garbage collected at exit* (which includes on error), and automatically 20 | deleted at the Chipmunk2D level, so there is no need to explicitly invoke their _free_( ) methods at exit for cleanup. 21 | 22 | Apart from at exit, however, objects are not automatically garbage collected 23 | footnote:[Objects are anchored to the Lua registry at their creation, so even if the script does not 24 | have references to an object, a reference always exists on the registry and this prevents the 25 | GC to collect it.] 26 | and one must release them explicitly when needed, e.g. to release resources when the 27 | application is not exiting and some objects are no longer needed. 28 | 29 | Releasing an object causes the automatic (pre) destruction of all its children 30 | objects, and the invalidation of any reference to the object and to its children. 31 | footnote:[It is good practice to not leave invalid references to objects around, because 32 | they prevent the GC to collect the memory associated with the userdata.] 33 | 34 | If not stated otherwise, *on error* all MoonChipmunk functions raise a 35 | http://www.lua.org/manual/5.3/manual.html#lua_error[Lua error]. 36 | If needed, this behaviour can be overridden by wrapping function calls in the standard Lua 37 | http://www.lua.org/manual/5.3/manual.html#pdf-pcall[pcall]( ). 38 | 39 | -------------------------------------------------------------------------------- /doc/miscellanea.adoc: -------------------------------------------------------------------------------- 1 | 2 | [[miscellanea]] 3 | == Miscellanea 4 | 5 | [[float_utils]] 6 | === Float utilities 7 | 8 | [small]#Rfr: https://chipmunk-physics.net/release/ChipmunkLatest-API-Reference/group__basic_types.html[cp basic types].# 9 | 10 | * _value_ = *fclamp*(_f_, _a_, _b_) + 11 | _value_ = *fclamp01*(_f_) + 12 | _value_ = *flerp*(_f~1~_, _f~2~_, _f_) + 13 | _value_ = *flerpconst*(_f~1~_, _f~2~_, _f_) + 14 | [small]#_value_, _f_, _f~1~_, _f~2~_, _a_, _b_: float.# 15 | 16 | [[vec_utils]] 17 | === Vector utilities 18 | 19 | [small]#Rfr: http://chipmunk-physics.net/release/ChipmunkLatest-API-Reference/group__cp_vect.html[cpVect].# 20 | 21 | * _boolean_ = *veql*(_v~1~_, _v~2~_) + 22 | _v_ = *vadd*(_v~1~_, _v~2~_) + 23 | _v_ = *vsub*(_v~1~_, _v~2~_) + 24 | _v_ = *vneg*(_v~1~_) + 25 | _v_ = *vmult*(_v~1~_, _v~2~_) + 26 | _value_ = *vdot*(_v~1~_, _v~2~_) + 27 | _value_ = *vcross*(_v~1~_, _v~2~_) + 28 | _v_ = *vperp*(_v~1~_) + 29 | _v_ = *vrperp*(_v~1~_) + 30 | _v_ = *vproject*(_v~1~_, _v~2~_) + 31 | _v_ = *vforangle*(_angle_) + 32 | _angle_ = *vtoangle*(_v_) + 33 | _v_ = *vrotate*(_v~1~_, _v~2~_) + 34 | _v_ = *vunrotate*(_v~1~_, _v~2~_) + 35 | _value_ = *vlength*(_v~1~_) + 36 | _value_ = *vlengthsq*(_v~1~_) + 37 | _value_ = *vdist*(_v~1~_, _v~2~_) + 38 | _value_ = *vdistsq*(_v~1~_, _v~2~_) + 39 | _v_ = *vnormalize*(_v~1~_) + 40 | _v_ = *vclamp*(_v~1~_, _len_) + 41 | _boolean_ = *vnear*(_v~1~_, _v~2~_, _d_) + 42 | _v_ = *vlerp*(_v~1~_, _v~2~_, _d_) + 43 | _v_ = *vslerp*(_v~1~_, _v~2~_, _d_) + 44 | _v_ = *vlerpconst*(_v~1~_, _v~2~_, _d_) + 45 | _v_ = *vslerpconst*(_v~1~_, _v~2~_, _d_) + 46 | [small]#_v_, _v~1~_, _v~2~_: <>. + 47 | _value_, _angle_, _len_, _d_: float.# 48 | 49 | 50 | [[mat_utils]] 51 | === Transform utilities 52 | 53 | [small]#Rfr: http://chipmunk-physics.net/release/ChipmunkLatest-API-Reference/structcp_transform.html[cpTransform].# 54 | 55 | * _m_ = *transform_identity*( ) + 56 | _m_ = *transform_new*(_a_, _b_, _c_, _d_, _t~x~_, _t~y~_) + 57 | _m_ = *transform_new_transpose*(_a_, _c_, _t~x~_, _b_, _d_, _t~y~_) + 58 | _m_ = *transform_inverse*(_m~1~_) + 59 | _m_ = *transform_mult*(_m~1~_, _m~2~_) + 60 | _p_ = *transform_point*(_m_, _p_) + 61 | _v_ = *transform_vect*(_m_, _v_) + 62 | _bb_ = *transform_bb*(_m_, _bb_) + 63 | _m_ = *transform_translate*(_v_) + 64 | _m_ = *transform_scale*(_s~x~_, _s~y~_) + 65 | _m_ = *transform_rotate*(_angle_) + 66 | _m_ = *transform_rigid*(_v_, _angle_) + 67 | _m_ = *transform_rigid_inverse*(_m~1~_) + 68 | _m_ = *transform_wrap*(_m~outer~_, _m~inner~_) + 69 | _m_ = *transform_wrap_inverse*(_m~outer~_, _m~inner~_) + 70 | _m_ = *transform_ortho*(_bb_) + 71 | _m_ = *transform_bone_scale*(_v~1~_, _v~2~_) + 72 | _m_ = *transform_axial_scale*(_axis_, _pivot_, _scale_) + 73 | [small]#_m_, _m~1~, _m~2~_, _m~outer~_, _m~inner~_: <>. + 74 | _p_, _v_, _v~1~_, _v~2~_, _axis_, _pivot_: <>. + 75 | _bb_: <>. + 76 | _a_, _b_, _c_, _d_, _t~x~_, _t~y~_, _s~x~_, _s~y~_, _angle_, _scale_: float.# 77 | 78 | [[bb_utils]] 79 | === Bounding box utilities 80 | 81 | [small]#Rfr: https://chipmunk-physics.net/release/ChipmunkLatest-API-Reference/group__cp_b_b_b.html[cpBB].# 82 | 83 | * _bb_ = *bb_new_for_extents*(_center_, _halfwidth_, _halfheight_) + 84 | _bb_ = *bb_new_for_circle*(_center_, _radius_) + 85 | _boolean_ = *bb_intersects*(_bb~1~_, _bb~2~_) + 86 | _boolean_ = *bb_contains_bb*(_bb~1~_, _bb~2~_) + 87 | _boolean_ = *bb_contains_vect*(_bb_, _v_) + 88 | _bb_ = *bb_merge*(_bb~1~_, _bb~2~_) + 89 | _bb_ = *bb_expand*(_bb~1~_, _v_) + 90 | _center_ = *bb_center*(_bb_) + 91 | _area_ = *bb_area*(_bb_) + 92 | _area_ = *bb_merged_area*(_bb~1~_, _bb~2~_) + 93 | _f_ = *bb_segment_query*(_bb_, _a_, _b_) + 94 | _boolean_ = *bb_intersects_segment*(_bb_, _a_, _b_) + 95 | _v_ = *bb_clamp_vect*(_bb_, _v_) + 96 | _v_ = *bb_wrap_vect*(_bb_, _v_) + 97 | _bb_ = *bb_offset*(_bb_, _v_) + 98 | [small]#_bb_, _bb~1~_, _bb~2~_: <>. + 99 | _center_, _v_, _a_, _b_: <>. + 100 | _width_, _height_, _area_, _f_: float.# 101 | 102 | * *march_soft*(_bb_, _xsamples_, _ysamples_, _threshold_, _samplefunc_, _segmentfunc_ ) + 103 | *march_hard*(_bb_, _xsamples_, _ysamples_, _threshold_, _samplefunc_, _segmentfunc_ ) + 104 | [small]#_bb_: <>. + 105 | _xsamples_, _ysamples_: integer. + 106 | _threshold_: float. + 107 | The sample function is executed as *density = func(p)* (_density_: float, _p_: <>). + 108 | The segment function is executed as *func(_a_, _b_)* (_a_, _b_: <>).# 109 | 110 | [[moment]] 111 | === Moments, areas, etc 112 | 113 | [small]#Rfr:https://chipmunk-physics.net/release/ChipmunkLatest-API-Reference/group__misc.html[cp misc].# 114 | 115 | * _moment_ = *moment_for_circle*(_mass_, _r~inner~_, _r~outer~_, _offset_) + 116 | _moment_ = *moment_for_segment*(_mass_, _point~a~_, _point~b~_, _radius_) + 117 | _moment_ = *moment_for_poly*(_mass_, _{verts}_, _offset_, _radius_) + 118 | _moment_ = *moment_for_box*(_mass_, _width_, _height_) + 119 | _moment_ = *moment_for_box*(_mass_, <>) + 120 | _area_ = *area_for_circle*(_r~inner~_, _r~outer~_) + 121 | _area_ = *area_for_segment*(_point~a~_, _point~b~_, _radius_) + 122 | _area_ = *area_for_poly*(_{verts}_, _radius_) + 123 | _centroid_ = *centroid_for_poly*(_{verts}_) + 124 | _{verts}_ = *convex_hull*(_{verts}_, _tol_) + 125 | [small]#_moment_, _area_, _mass_, _r~inner~_, _r~outer~_, _radius_, _width_, _height_, _tol_: float. + 126 | _point~a~_, _point~b~_, _offset_, _centroid_: <>. + 127 | _{verts}_: {<>}.# 128 | 129 | * _p_ = *closest_point_on_segment*(_p_, _a_, _b_) + 130 | [small]#Returns the point on the segment (_a_, _b_) that is closest to the point _p_. + 131 | _p_, _a_, _b_: <>.# 132 | 133 | //// 134 | * _boolean_ = *check_point_greater*(_p_, _a_, _b_) + 135 | [small]#Returns _true_ if the point _p_ is to the left of the segment (_a_, _b_). + 136 | _p_, _a_, _b_: <>.# 137 | 138 | * _boolean_ = *check_axis*(_v~0~_, _v~1~_, _p_, _n_) + 139 | [small]#Returns _true_ if the point _p_ is behind one of _v~0~_ or _v~1~_ on axis _n_. + @@ UH? 140 | _v~0~_, _v~1~_, _p_, _n_: <>.# 141 | //// 142 | 143 | 144 | -------------------------------------------------------------------------------- /doc/powered-by-lua.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stetre/moonchipmunk/0e93b019d43041d5c12c6edb5b2bcfcc39c0155a/doc/powered-by-lua.gif -------------------------------------------------------------------------------- /doc/preface.adoc: -------------------------------------------------------------------------------- 1 | 2 | == Preface 3 | 4 | This is the reference manual of *MoonChipmunk*, which is a 5 | https://www.lua.org[*Lua*] binding library for Scott Lembcke's 6 | http://chipmunk-physics.net/[*Chipmunk2D*] physics engine. 7 | footnote:[ 8 | This manual is written in 9 | http://www.methods.co.nz/asciidoc/[AsciiDoc], rendered with 10 | http://asciidoctor.org/[AsciiDoctor] and a CSS from the 11 | https://github.com/asciidoctor/asciidoctor-stylesheet-factory[AsciiDoctor Stylesheet Factory].] 12 | 13 | It is assumed that the reader is familiar with both Chipmunk2D and the Lua programming language. 14 | 15 | For convenience of reference, this document contains external (deep) links to the 16 | https://www.lua.org/manual/5.3/manual.html[Lua Reference Manual] and the 17 | http://chipmunk-physics.net/documentation.php[Chipmunk2D Documentation]. 18 | 19 | === Getting and installing 20 | 21 | For installation intructions, refer to the README file in the 22 | https://github.com/stetre/moonchipmunk[*MoonChipmunk official repository*] 23 | on GitHub. 24 | 25 | === Module organization 26 | 27 | The MoonChipmunk module is loaded using Lua's 28 | http://www.lua.org/manual/5.3/manual.html#pdf-require[require]() and 29 | returns a table containing the functions it provides 30 | (as usual with Lua modules). This manual assumes that such 31 | table is named *cp*, i.e. that it is loaded with: 32 | 33 | [source,lua,indent=1] 34 | ---- 35 | cp = require("moonchipmunk") 36 | ---- 37 | 38 | but nothing forbids the use of a different name. 39 | 40 | === Examples 41 | 42 | Complete examples can be found in the *examples/* directory of the release package. 43 | 44 | === License 45 | 46 | MoonChipmunk is released under the *MIT/X11 license* (same as 47 | http://www.lua.org/license.html[Lua], and with the same only requirement to give proper 48 | credits to the original author). 49 | The copyright notice is in the LICENSE file in the base directory 50 | of the https://github.com/stetre/moonchipmunk[official repository] on GitHub. 51 | 52 | [[see-also]] 53 | === See also 54 | 55 | MoonChipmunk is part of https://github.com/stetre/moonlibs[MoonLibs], a collection of 56 | Lua libraries for graphics and audio programming. 57 | 58 | -------------------------------------------------------------------------------- /doc/shape.adoc: -------------------------------------------------------------------------------- 1 | 2 | [[shape]] 3 | === Shapes 4 | 5 | [small]#Rfr: http://chipmunk-physics.net/release/ChipmunkLatest-API-Reference/group__cp_shape.html[cpShape].# 6 | 7 | [[shape_new]] 8 | Constructors and specialized methods are available for the following subtypes: 9 | 10 | * <> 11 | * <> 12 | * <> 13 | 14 | Common methods: 15 | 16 | [[shape_free]] 17 | * _shape_++:++*free*( ) + 18 | [small]#Delete _shape_.# 19 | 20 | [[shape_set_body]] 21 | * _shape_++:++*set_body*(<>) + 22 | <> = _shape_++:++*get_body*( ) + 23 | <> = _shape_++:++*get_space*( ) + 24 | 25 | [[shape_update]] 26 | * <> = _shape_++:++*update*(_transform_) + 27 | [small]#_transform_: <>.# 28 | 29 | [[shape_set_float]] 30 | * _shape_++:++*set_mass*(_value_) + 31 | _shape_++:++*set_density*(_value_) + 32 | _shape_++:++*set_elasticity*(_value_) + 33 | _shape_++:++*set_friction*(_value_) + 34 | _value_ = _shape_++:++*get_mass*( ) + 35 | _value_ = _shape_++:++*get_moment*( ) + 36 | _value_ = _shape_++:++*get_area*( ) + 37 | _value_ = _shape_++:++*get_density*( ) + 38 | _value_ = _shape_++:++*get_elasticity*( ) + 39 | _value_ = _shape_++:++*get_friction*( ) + 40 | [small]#_value_: float.# 41 | 42 | [[shape_set_vec]] 43 | * _shape_++:++*set_surface_velocity*(<>) + 44 | <> = _shape_++:++*get_surface_velocity*( ) + 45 | <> = _shape_++:++*get_center_of_gravity*( ) + 46 | 47 | [[shape_get_bb]] 48 | * <> = _shape_++:++*get_bb*( ) + 49 | <> = _shape_++:++*cache_bb*( ) + 50 | 51 | [[shape_set_sensor]] 52 | * _shape_++:++*set_sensor*(_boolean_) + 53 | _boolean_ = _shape_++:++*get_sensor*( ) + 54 | 55 | [[shape_set_filter]] 56 | * _shape_++:++*set_filter*(<>) + 57 | <> = _shape_++:++*get_filter*( ) + 58 | 59 | [[shape_filter_new]] 60 | * <> = *shape_filter_new*(_group_, _categories_, _bitmask_) + 61 | <> = *shape_filter_all*( ) + 62 | <> = *shape_filter_none*( ) + 63 | [small]#Shape filter constructor and built-in shape filters (_CP_SHAPE_FILTER_XXX_). + 64 | Note that a shape filter is a plain Lua table, and thus may also be manually constructed.# 65 | 66 | [[shape_set_collision_type]] 67 | * _shape_++:++*set_collision_type*(value) + 68 | value = _shape_++:++*get_collision_type*( ) + 69 | [small]#_value_: integer.# 70 | 71 | [[shape_collide]] 72 | * _normal_|_nil_, _{points}_ = *shapes_collide*(<>, <>) + 73 | _normal_|_nil_, _{points}_ = _shape_++:++*collide*(<>) + 74 | [small]#Return _nil_ if shape do not collide. + 75 | _normal_ = <>. + 76 | _{points}_ = {<>}.# 77 | 78 | [[shape_query]] 79 | * <> = _shape_++:++*point_query*(_point_) + 80 | <>|_nil_ = _shape_++:++*segment_query*(_a_, _b_, _radius_) + 81 | [small]#_point_, _a_, _b_: <>. 82 | _radius_: float.# 83 | 84 | [[circle]] 85 | ==== circle 86 | 87 | * <> = *circle_shape_new*(<>, _radius_, [_offset_]) + 88 | _shape_++:++*set_radius*(_radius_) _UNSAFE_ + 89 | _shape_++:++*set_offset*(_offset_) _UNSAFE_ + 90 | _radius_ = _shape_++:++*get_radius*( ) + 91 | _offset_ = _shape_++:++*get_offset*( ) + 92 | [small]#_radius_: float. + 93 | _offset_: <> (defaults to _{0, 0}_).# 94 | 95 | 96 | [[segment]] 97 | ==== segment 98 | 99 | * <> = *segment_shape_new*(<>, _a_, _b_, _radius_) + 100 | _shape_++:++*set_radius*(_radius_) _UNSAFE_ + 101 | _shape_++:++*set_endpoints*(_a_, _b_) _UNSAFE_ + 102 | _shape_++:++*set_neighbors*(_prev_, _next_) _UNSAFE_ + 103 | _radius_ = _shape_++:++*get_radius*( ) + 104 | _a_, _b_ = _shape_++:++*get_endpoints*( ) + 105 | _normal_ = _shape_++:++*get_normal*( ) + 106 | [small]#_a_, _b_, _prev_, _next_, _normal_: <>. + 107 | _radius_: float.# 108 | 109 | [[poly]] 110 | ==== poly 111 | 112 | * <> = *poly_shape_new*(<>, _{verts}_, _radius_, [_transform_]) + 113 | <> = *box_shape_new*(<>, _width_, _height_, _radius_) + 114 | <> = *box_shape_new*(<>, <>, _radius_) + 115 | _shape_++:++*set_radius*(_radius_) _UNSAFE_ + 116 | _shape_++:++*set_verts*(_{verts}_, [_transform_]) _UNSAFE_ + 117 | _radius_ = _shape_++:++*get_radius*( ) + 118 | _{verts}_ = _shape_++:++*get_verts*( ) + 119 | _nverts_ = _shape_++:++*get_count*( ) + 120 | [small]#_{verts}_: {<>}. + 121 | _radius_, _width_, _height_: float. + 122 | _transform_: <> (defaults to the identity transform).# 123 | 124 | -------------------------------------------------------------------------------- /doc/space.adoc: -------------------------------------------------------------------------------- 1 | 2 | [[space]] 3 | === Spaces 4 | 5 | [small]#Rfr: http://chipmunk-physics.net/release/ChipmunkLatest-API-Reference/group__cp_space.html[cpSpace].# 6 | 7 | [[space_new]] 8 | * _space_ = *space_new*( ) + 9 | _space_ = *hasty_space_new*( ) + 10 | _space_++:++*free*( ) + 11 | [small]#Create/delete a space.# 12 | 13 | [[space_set_threads]] 14 | * _space_++:++*set_threads*(_n_) + 15 | _n_ = _space_++:++*get_threads*( ) + 16 | [small]#For hasty spaces only.# 17 | 18 | [[space_step]] 19 | * _space_++:++*step*(_dt_) + 20 | _space_++:++*nstep*(_dt_, _n_) 21 | * _dt_ = _space_++:++*get_current_time_step*( ) + 22 | [small]#_dt_: float (seconds). + 23 | _n_: number of steps.# 24 | 25 | [[space_is_locked]] 26 | * _boolean_ = _space_++:++*is_locked*( ) 27 | 28 | [[space_set_gravity]] 29 | * _space_++:++*set_gravity*(_gravity_) + 30 | _space_++:++*set_damping*(_damping_) + 31 | _gravity_ = _space_++:++*get_gravity*( ) + 32 | _damping_ = _space_++:++*get_damping*( ) + 33 | [small]#_gravity_: <> (defaults to _{0, 0}_). + 34 | _damping_: float (defaults to _1.0_).# 35 | 36 | [[space_set_iterations]] 37 | * _space_++:++*set_iterations*(_n_) + 38 | _n_ = _space_++:++*get_iterations*( ) 39 | 40 | [[space_set_thresholds]] 41 | * _space_++:++*set_idle_speed_threshold*(_ist_) + 42 | _space_++:++*set_sleep_time_threshold*(_stt_) + 43 | _ist_ = _space_++:++*get_idle_speed_threshold*( ) + 44 | _stt_ = _space_++:++*get_sleep_time_threshold*( ) + 45 | [small]#_ist_: float (defaults to _0_). + 46 | _stt_: float (defaults to _math.huge_).# 47 | 48 | [[space_set_collision_xxx]] 49 | * _space_++:++*set_collision_slop*(_cs_) + 50 | _space_++:++*set_collision_bias*(_cb_) + 51 | _space_++:++*set_collision_persistence*(_cp_) + 52 | _cs_ = _space_++:++*get_collision_slop*( ) + 53 | _cb_ = _space_++:++*get_collision_bias*( ) + 54 | _cp_ = _space_++:++*get_collision_persistence*( ) + 55 | [small]#_cs_: float (defaults to _0.1_). + 56 | _cb_: float (defaults to _(1 - 0.1)^60^_). + 57 | _cp_: number of frames (defaults to _3_).# 58 | 59 | 60 | [[space_get_static_body]] 61 | * <> = _space_++:++*get_static_body*( ) 62 | 63 | [[space_add_xxx]] 64 | * <> = _space_++:++*add_body*(<>) + 65 | <> = _space_++:++*add_shape*(<>) + 66 | <> = _space_++:++*add_constraint*(<>) + 67 | _space_++:++*remove_body*(<>) + 68 | _space_++:++*remove_shape*(<>) + 69 | _space_++:++*remove_constraint*(<>) + 70 | _boolean_ = _space_++:++*contains_body*(<>) + 71 | _boolean_ = _space_++:++*contains_shape*(<>) + 72 | _boolean_ = _space_++:++*contains_constraint*(<>) 73 | 74 | [[space_reindex]] 75 | * _space_++:++*reindex_static*( ) + 76 | _space_++:++*reindex_shape*(<>) + 77 | _space_++:++*reindex_shapes_for_body*(<>) + 78 | _space_++:++*use_spatial_hash*(_dim_, _count_) 79 | 80 | [[space_each]] 81 | * _space_++:++*each_body*(_func_) + 82 | _space_++:++*each_shape*(_func_) + 83 | _space_++:++*each_constraint*(_func_) + 84 | [small]#Execute _func_ as *func(space, object)* for each object of the given type.# 85 | 86 | * _collision_handler_ = _space_++:++*add_default_collision_handler*( ) + 87 | _collision_handler_ = _space_++:++*add_collision_handler*(_type~a~_, _type~b~_) + 88 | _collision_handler_ = _space_++:++*add_wildcard_handler*(_type_) + 89 | [small]#See <>.# 90 | 91 | [[space_add_post_step_callback]] 92 | * _space_++:++*add_post_step_callback*(_func_) + 93 | [small]#The post-step callback is executed as *func(space)*.# 94 | 95 | [[space_queries]] 96 | * <>|_nil_ = _space_++:++*point_query_nearest*(_point_, _maxdist_, _shapefilter_) + 97 | <>|_nil_ = _space_++:++*segment_query_first*(_p~start~_, _p~end~_, _radius_, _shapefilter_) + 98 | _space_++:++*point_query*(_point_, _maxdist_, _shapefilter_, _func_) + 99 | _space_++:++*segment_query*(_p~start~_, _p~end~_, _radius_, _shapefilter_, _func_) + 100 | _space_++:++*bb_query*(<>, _shapefilter_, _func_) + 101 | _space_++:++*shape_query*(<>, _func_) + 102 | [small]#_point_, _p~start~_, _p~end~_: <>. + 103 | _maxdist_, _radius_: float. + 104 | _shapefilter_: <>. + 105 | The _func_ callbacks are executed for each hit shape, as follows: + 106 | pass:[-] point query: *func(space, shape, _point_, _distance_)* (_point_: <>, _distance_: float). + 107 | pass:[-] segment query: *func(space, shape, point, normal, alpha)* (_point_, _normal_: <>, _alpha_: float). + 108 | pass:[-] bb query: *func(space, shape)*. + 109 | pass:[-] shape query: *func(space, shape, _normal_, {points})* ( _normal_: <>, _{points}_: {<>}).# 110 | 111 | [[space_]] 112 | * _space_++:++*debug_draw*( ) + 113 | _space_++:++*set_debug_draw_options*(_draw_circle_, _draw_segment_, _..._) + 114 | [small]#Arguments for set_debug_draw_options( ): + 115 | arg1: _space_ (implicit argument). + 116 | arg2: _draw_circle_: a function, executed as *func(angle, radius, outlinecolor, fillcolor)*. + 117 | arg3: _draw_segment_: a function, executed as *func(a, b, color)* + 118 | arg4: _draw_fat_segment_: a function, executed as *func(a, b, radius, outlinecolor, fillcolor)*. + 119 | arg5: _draw_polygon_: a function, executed as *func({verts}, radius, outlinecolor, fillcolor)* + 120 | arg6: _draw_dot_: a function, executed as *func(size, pos, color)*. + 121 | arg7: _color_for_shape_: a function, executed as *color = func(shape)* + 122 | arg8: _flags_: integer (_cpSpaceDebugDrawFlags_) + 123 | arg9: _shape_outline_color_: <>, + 124 | arg10: _constraint_color_: <>, + 125 | arg11: _collision_point_color_: <>.# 126 | 127 | -------------------------------------------------------------------------------- /doc/toolbox.adoc: -------------------------------------------------------------------------------- 1 | 2 | [[toolbox]] 3 | == Toolbox 4 | 5 | MoonChipmunk comes with a 'toolbox' submodule, located in `moonchipmunk/toolbox.lua`. 6 | This submodule provides the tools that are used in examples and demos for rendering, input 7 | handling, and more. 8 | 9 | In addition to MoonChipmunk itself, the toolbox uses (and thus requires) the following 10 | libraries from the https://github.com/stetre/moonlibs[MoonLibs collection]: 11 | 12 | * https://github.com/stetre/moongl[MoonGL]: bindings to the OpenGL API, for graphics rendering. 13 | * https://github.com/stetre/moonglfw[MoonGLFW]: bindings to GLFW, for window/surface creation and input handling. 14 | * https://github.com/stetre/moonglmath[MoonGLMATH]: graphics math library. 15 | * https://github.com/stetre/moonfreetype[MoonFreeType]: bindings to FreeType, for loading fonts. 16 | * https://github.com/stetre/moonimage[MoonImage]: bindings to stb_image, for loading images. 17 | * https://github.com/stetre/moonsndfile[MoonSndFile]: bindings to libsndfile, for loading sound samples. 18 | * https://github.com/stetre/moonal[MoonAL]: bindings to OpenAL, for rendering audio. 19 | 20 | (Note that MoonChipmunk itself does not depend on the above libraries. Only the toolbox does, 21 | and its use in an application is optional). 22 | 23 | The examples and demos, together with the comments in the toolbox script, should hopefully 24 | suffice to show how the tools are meant to be used. 25 | 26 | -------------------------------------------------------------------------------- /examples/demo/01-pyramid-stack.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | local glfw = require("moonglfw") 3 | local gl = require("moongl") 4 | local cp = require("moonchipmunk") 5 | local toolbox = require("moonchipmunk.toolbox") 6 | 7 | local infinity = math.huge 8 | local fmt = string.format 9 | 10 | -- Initializations ------------------------------------------------------------ 11 | 12 | local TITLE = "Pyramid Stack" 13 | local FW, FH = 640, 480 -- width and height of the field 14 | local W, H = 1024, 768 -- width and height of the window 15 | local BG_COLOR = {0x07/255, 0x36/255, 0x42/255, 1.0} 16 | 17 | glfw.version_hint(3, 3, 'core') 18 | glfw.window_hint('samples', 32) 19 | local window = glfw.create_window(W, H, TITLE) 20 | glfw.make_context_current(window) 21 | gl.init() 22 | toolbox.init(W, H) 23 | local camera = toolbox.camera() 24 | 25 | local function resize(window, width, height) 26 | W, H = width, height 27 | toolbox.resize(W, H) 28 | toolbox.set_matrices(camera:view(), camera:projection(-FW/2, FW/2, -FH/2, FH/2)) 29 | gl.viewport(0, 0, W, H) 30 | end 31 | 32 | glfw.set_window_size_callback(window, resize) 33 | resize(window, W, H) 34 | 35 | local space = cp.space_new() 36 | space:set_iterations(30) 37 | space:set_gravity({0, -100}) 38 | space:set_sleep_time_threshold(0.5) 39 | space:set_collision_slop(0.5) 40 | local grabber = toolbox.grabber(window, space) 41 | local grabbable, not_grabbable = grabber:filters() 42 | 43 | local static_body = space:get_static_body() 44 | -- Create segments around the edge of the screen. 45 | local shape = space:add_shape(cp.segment_shape_new(static_body, {-320,-240}, {-320,240}, 0.0)) 46 | shape:set_elasticity(1.0) 47 | shape:set_friction(1.0) 48 | shape:set_filter(not_grabbable) 49 | local shape = space:add_shape(cp.segment_shape_new(static_body, {320,-240}, {320,240}, 0.0)) 50 | shape:set_elasticity(1.0) 51 | shape:set_friction(1.0) 52 | shape:set_filter(not_grabbable) 53 | local shape = space:add_shape(cp.segment_shape_new(static_body, {-320,-240}, {320,-240}, 0.0)) 54 | shape:set_elasticity(1.0) 55 | shape:set_friction(1.0) 56 | shape:set_filter(not_grabbable) 57 | -- Add lots of boxes. 58 | for i=0, 13 do 59 | for j=0,i do 60 | local body = space:add_body(cp.body_new(1.0, cp.moment_for_box(1.0, 30.0, 30.0))) 61 | body:set_position({j*32 - i*16, 300 - i*32}) 62 | shape = space:add_shape(cp.box_shape_new(body, 30.0, 30.0, 0.5)) 63 | shape:set_elasticity(0.0) 64 | shape:set_friction(0.8) 65 | end 66 | end 67 | -- Add a ball to make things more interesting 68 | local radius = 15.0 69 | local body = space:add_body(cp.body_new(10.0, cp.moment_for_circle(10.0, 0.0, radius, {0, 0}))) 70 | body:set_position({0, -240 + radius+5}) 71 | local shape = space:add_shape(cp.circle_shape_new(body, radius, {0, 0})) 72 | shape:set_elasticity(0.0) 73 | shape:set_friction(0.9) 74 | 75 | -- Input handling ------------------------------------------------------------- 76 | 77 | local toggle_fullscreen = toolbox.toggle_fullscreen(window) 78 | local keys = {} -- keys[k] = true if key k is pressed 79 | 80 | glfw.set_key_callback(window, function(window, key, scancode, action) 81 | if key == 'escape' and action == 'press' then 82 | glfw.set_window_should_close(window, true) 83 | elseif key == 'f11' and action == 'press' then 84 | toggle_fullscreen() 85 | else 86 | keys[key] = action ~= 'release' 87 | end 88 | end) 89 | 90 | glfw.set_cursor_pos_callback(window, function(window, x, y) 91 | grabber:cursor_pos_callback(x, y) 92 | end) 93 | 94 | glfw.set_mouse_button_callback(window, function(window, button, action, shift, control, alt, super) 95 | grabber:mouse_button_callback(button, action, shift, control, alt, super) 96 | end) 97 | 98 | 99 | -- Game loop ------------------------------------------------------------------ 100 | local timer = toolbox.frame_timer() 101 | local spf = 1/60 -- 1 / desired fps 102 | local fdt = 1/180 -- fixed dt for physics updates 103 | local n_physics_updates = toolbox.fixed_dt_counter(fdt) 104 | local n, dt 105 | 106 | local renderer = toolbox.renderer(space) 107 | 108 | collectgarbage() 109 | collectgarbage('stop') 110 | while not glfw.window_should_close(window) do 111 | glfw.wait_events_timeout(spf) 112 | dt = timer:update() -- duration of the current frame 113 | n = n_physics_updates(dt) -- no. of physics updates to do in this frame 114 | 115 | space:step(fdt, n) 116 | grabber:step(fdt, n) 117 | 118 | glfw.set_window_title(window, fmt("%s - fps=%.0f, n=%d", TITLE, timer:fps(), n)) 119 | gl.clear_color(BG_COLOR) 120 | gl.clear('color') 121 | renderer:begin() 122 | space:debug_draw() 123 | renderer:done() 124 | 125 | glfw.swap_buffers(window) 126 | collectgarbage() 127 | end 128 | 129 | toolbox.cleanup() 130 | 131 | -------------------------------------------------------------------------------- /examples/demo/02-plink.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | local glfw = require("moonglfw") 3 | local gl = require("moongl") 4 | local cp = require("moonchipmunk") 5 | local toolbox = require("moonchipmunk.toolbox") 6 | 7 | local pi, infinity = math.pi, math.huge 8 | local sin, cos, abs = math.sin, math.cos, math.abs 9 | local fmt = string.format 10 | 11 | -- Initializations ------------------------------------------------------------ 12 | 13 | local TITLE = "Pyramid Stack" 14 | local FW, FH = 640, 480 -- width and height of the field 15 | local W, H = 1024, 768 -- width and height of the window 16 | local BG_COLOR = {0x07/255, 0x36/255, 0x42/255, 1.0} 17 | local FONT_COLOR, FONT_SIZE = {0xfd/250, 0xf6/250, 0xe3/250, 1.0}, 12/H 18 | 19 | glfw.version_hint(3, 3, 'core') 20 | glfw.window_hint('samples', 32) 21 | local window = glfw.create_window(W, H, TITLE) 22 | glfw.make_context_current(window) 23 | gl.init() 24 | toolbox.init(W, H) 25 | local camera = toolbox.camera() 26 | 27 | local function resize(window, width, height) 28 | W, H = width, height 29 | toolbox.resize(W, H) 30 | toolbox.set_matrices(camera:view(), camera:projection(-FW/2, FW/2, -FH/2, FH/2)) 31 | gl.viewport(0, 0, W, H) 32 | end 33 | 34 | glfw.set_window_size_callback(window, resize) 35 | resize(window, W, H) 36 | 37 | -- Fonts ---------------------------------------------------------------------- 38 | local font = toolbox.font("../ttf-bitstream-vera-1.10/VeraMoBd.ttf", 40/H) 39 | 40 | -- Demo inits ----------------------------------------------------------------- 41 | local space = cp.space_new() 42 | local grabber = toolbox.grabber(window, space) 43 | local grabbable, not_grabbable = grabber:filters() 44 | space:set_iterations(5) 45 | space:set_gravity({0, -100}) 46 | local static_body = space:get_static_body() 47 | local tris = {{-15,-15}, { 0, 10}, { 15,-15}} -- Vertexes for a triangle shape. 48 | -- Create the static triangles. 49 | for i=0, 8 do 50 | for j=0, 5 do 51 | local stagger = (j%2)*40 52 | local offset = {i*80 - 320 + stagger, j*70 - 240} 53 | local transform = cp.transform_translate(offset) 54 | local shape = cp.poly_shape_new(static_body, tris, 0.0, transform) 55 | space:add_shape(shape) 56 | shape:set_elasticity(1.0) 57 | shape:set_friction(1.0) 58 | shape:set_filter(not_grabbable) 59 | end 60 | end 61 | 62 | -- Add lots of pentagons. 63 | local num_pentagon_verts= 5 64 | local pentagon_mass = 1.0 65 | local pentagon_verts = {} -- vertices for a pentagon shape. 66 | for i=0, num_pentagon_verts-1 do 67 | local angle = -2.0*pi*i/num_pentagon_verts 68 | table.insert(pentagon_verts, {10*cos(angle), 10*sin(angle)}) 69 | end 70 | local pentagon_moment = cp.moment_for_poly(pentagon_mass, pentagon_verts, {0, 0}, 0.0) 71 | local identity = cp.transform_identity() 72 | 73 | math.randomseed(os.time()) 74 | for i=0,299 do 75 | local body = cp.body_new(pentagon_mass, pentagon_moment) 76 | space:add_body(body) 77 | body:set_position({math.random()*640-320, 350}) 78 | local shape = cp.poly_shape_new(body, pentagon_verts, 0.0, identity) 79 | space:add_shape(shape) 80 | shape:set_elasticity(0.0) 81 | shape:set_friction(0.4) 82 | end 83 | 84 | -- Input handling ------------------------------------------------------------- 85 | 86 | local toggle_fullscreen = toolbox.toggle_fullscreen(window) 87 | local keys = {} -- keys[k] = true if key k is pressed 88 | 89 | glfw.set_key_callback(window, function(window, key, scancode, action) 90 | if key == 'escape' and action == 'press' then 91 | glfw.set_window_should_close(window, true) 92 | elseif key == 'f11' and action == 'press' then 93 | toggle_fullscreen() 94 | else 95 | keys[key] = action ~= 'release' 96 | end 97 | end) 98 | 99 | glfw.set_cursor_pos_callback(window, function(window, x, y) 100 | grabber:cursor_pos_callback(x, y) 101 | end) 102 | 103 | glfw.set_mouse_button_callback(window, function(window, button, action, shift, control, alt, super) 104 | if button=='right' and action=='press' then 105 | -- toggle the nearest body (if any) from static to dynamic and viceversa 106 | local nearest = space:point_query_nearest(grabber:get_pos(), 0.0, grabbable) 107 | if nearest then 108 | local body = nearest.shape:get_body() 109 | if body:get_type() == 'static' then 110 | body:set_type('dynamic') 111 | body:set_mass(pentagon_mass) 112 | body:set_moment(pentagon_moment) 113 | elseif body:get_type()=='dynamic' then 114 | body:set_type('static') 115 | end 116 | end 117 | end 118 | grabber:mouse_button_callback(button, action, shift, control, alt, super) 119 | end) 120 | 121 | -- Game loop ------------------------------------------------------------------ 122 | local timer = toolbox.frame_timer() 123 | local spf = 1/60 -- 1 / desired fps 124 | local fdt = 1/60 -- fixed dt for physics updates 125 | local n_physics_updates = toolbox.fixed_dt_counter(fdt) 126 | local n, dt 127 | 128 | local renderer = toolbox.renderer(space) 129 | 130 | collectgarbage() 131 | collectgarbage('stop') 132 | while not glfw.window_should_close(window) do 133 | glfw.wait_events_timeout(spf) 134 | dt = timer:update() -- duration of the current frame 135 | n = n_physics_updates(dt) -- no. of physics updates to do in this frame 136 | 137 | for i = 1, n do 138 | -- Iterate over all of the bodies and reset the ones that have fallen offscreen. 139 | space:each_body(function(space, body) 140 | local x, y = table.unpack(body:get_position()) 141 | if y < -260 or abs(x) > 340 then 142 | body:set_position({math.random()*640-320, 260}) 143 | end 144 | end) 145 | space:step(fdt) 146 | grabber:step(fdt) 147 | end 148 | 149 | glfw.set_window_title(window, fmt("%s - fps=%.0f, n=%d", TITLE, timer:fps(), n)) 150 | gl.clear_color(BG_COLOR) 151 | gl.clear('color') 152 | renderer:begin() 153 | space:debug_draw() 154 | renderer:done() 155 | 156 | font:draw("Right click to make pentagons static/dynamic.", .05, .9, FONT_SIZE, FONT_COLOR) 157 | 158 | glfw.swap_buffers(window) 159 | collectgarbage() 160 | end 161 | 162 | toolbox.cleanup() 163 | 164 | 165 | -------------------------------------------------------------------------------- /examples/demo/04-tumble.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | local glfw = require("moonglfw") 3 | local gl = require("moongl") 4 | local glmath = require("moonglmath") 5 | local cp = require("moonchipmunk") 6 | local toolbox = require("moonchipmunk.toolbox") 7 | 8 | cp.glmath_compat(true) 9 | local pi, infinity = math.pi, math.huge 10 | local sin, cos, abs = math.sin, math.cos, math.abs 11 | local fmt = string.format 12 | local vec2 = glmath.vec2 13 | 14 | -- Initializations ------------------------------------------------------------ 15 | 16 | local TITLE = "Tumble" 17 | local FW, FH = 640, 480 -- width and height of the field 18 | local W, H = 1024, 768 -- window width and height 19 | local BG_COLOR = {0x07/255, 0x36/255, 0x42/255, 1.0} 20 | 21 | glfw.version_hint(3, 3, 'core') 22 | glfw.window_hint('samples', 32) 23 | local window = glfw.create_window(W, H, TITLE) 24 | glfw.make_context_current(window) 25 | gl.init() 26 | toolbox.init(W, H) 27 | local camera = toolbox.camera() 28 | 29 | local function resize(window, width, height) 30 | W, H = width, height 31 | toolbox.resize(W, H) 32 | toolbox.set_matrices(camera:view(), camera:projection(-FW/2, FW/2, -FH/2, FH/2)) 33 | gl.viewport(0, 0, W, H) 34 | end 35 | 36 | glfw.set_window_size_callback(window, resize) 37 | resize(window, W, H) 38 | 39 | -- Demo inits ----------------------------------------------------------------- 40 | 41 | local space = cp.space_new() 42 | local grabber = toolbox.grabber(window, space) 43 | local grabbable, not_grabbable = grabber:filters() 44 | space:set_gravity({0, -600}) 45 | -- We create an infinite mass rogue body to attach the line segments too 46 | -- This way we can control the rotation however we want. 47 | local kinematic_box_body = cp.body_new_kinematic() 48 | space:add_body(kinematic_box_body) 49 | kinematic_box_body:set_angular_velocity(0.4) 50 | -- Set up the static box. 51 | local a, b, c, d = {-200, -200}, {-200, 200}, { 200, 200}, { 200, -200} 52 | local shape = space:add_shape(cp.segment_shape_new(kinematic_box_body, a, b, 0.0)) 53 | shape:set_elasticity(1.0) 54 | shape:set_friction(1.0) 55 | shape:set_filter(not_grabbable) 56 | local shape = space:add_shape(cp.segment_shape_new(kinematic_box_body, b, c, 0.0)) 57 | shape:set_elasticity(1.0) 58 | shape:set_friction(1.0) 59 | shape:set_filter(not_grabbable) 60 | local shape = space:add_shape(cp.segment_shape_new(kinematic_box_body, c, d, 0.0)) 61 | shape:set_elasticity(1.0) 62 | shape:set_friction(1.0) 63 | shape:set_filter(not_grabbable) 64 | local shape = space:add_shape(cp.segment_shape_new(kinematic_box_body, d, a, 0.0)) 65 | shape:set_elasticity(1.0) 66 | shape:set_friction(1.0) 67 | shape:set_filter(not_grabbable) 68 | 69 | -- Add the bricks. 70 | 71 | local function add_box(space, pos, mass, width, height) 72 | local body = space:add_body(cp.body_new(mass, cp.moment_for_box(mass, width, height))) 73 | body:set_position(pos) 74 | local shape = space:add_shape(cp.box_shape_new(body, width, height, 0.0)) 75 | shape:set_elasticity(0.0) 76 | shape:set_friction(0.7) 77 | end 78 | 79 | local function add_segment(space, pos, mass, width, height) 80 | local body = space:add_body(cp.body_new(mass, cp.moment_for_box(mass, width, height))) 81 | body:set_position(pos) 82 | local a, b = {0.0, (height-width)/2.0}, {0.0, (width-height)/2.0} 83 | local shape = space:add_shape(cp.segment_shape_new(body, a, b, width/2.0)) 84 | shape:set_elasticity(0.0) 85 | shape:set_friction(0.7) 86 | end 87 | 88 | local function add_circle(space, pos, mass, radius) 89 | local body = space:add_body(cp.body_new(mass, cp.moment_for_circle(mass, 0.0, radius, {0, 0}))) 90 | body:set_position(pos) 91 | local shape = space:add_shape(cp.circle_shape_new(body, radius, {0, 0})) 92 | shape:set_elasticity(0.0) 93 | shape:set_friction(0.7) 94 | end 95 | 96 | local mass, width, height = 1, 30, 60 97 | math.randomseed(os.time()) 98 | for i=0, 6 do 99 | for j=0, 2 do 100 | local pos = vec2(i*width - 150, j*height - 150) 101 | local dice = math.random(0,2) -- 3-faces dice (0, 1, 2) 102 | if dice==0 then 103 | add_box(space, pos, mass, width, height) 104 | elseif dice == 1 then 105 | add_segment(space, pos, mass, width, height) 106 | else -- dice == 2 107 | add_circle(space, pos + vec2(0.0, (height - width)/2.0), mass, width/2.0) 108 | add_circle(space, pos + vec2(0.0, (width - height)/2.0), mass, width/2.0) 109 | end 110 | end 111 | end 112 | 113 | -- Input handling ------------------------------------------------------------- 114 | 115 | local toggle_fullscreen = toolbox.toggle_fullscreen(window) 116 | local keys = {} -- keys[k] = true if key k is pressed 117 | 118 | glfw.set_key_callback(window, function(window, key, scancode, action) 119 | if key == 'escape' and action == 'press' then 120 | glfw.set_window_should_close(window, true) 121 | elseif key == 'f11' and action == 'press' then 122 | toggle_fullscreen() 123 | else 124 | keys[key] = action ~= 'release' 125 | end 126 | end) 127 | 128 | glfw.set_cursor_pos_callback(window, function(window, x, y) 129 | grabber:cursor_pos_callback(x, y) 130 | end) 131 | 132 | glfw.set_mouse_button_callback(window, function(window, button, action, shift, control, alt, super) 133 | grabber:mouse_button_callback(button, action, shift, control, alt, super) 134 | end) 135 | 136 | -- Game loop ------------------------------------------------------------------ 137 | local timer = toolbox.frame_timer() 138 | local spf = 1/60 -- 1 / desired fps 139 | local fdt = 1/180 -- fixed dt for physics updates 140 | local n_physics_updates = toolbox.fixed_dt_counter(fdt) 141 | local n, dt 142 | 143 | local renderer = toolbox.renderer(space) 144 | 145 | collectgarbage() 146 | collectgarbage('stop') 147 | while not glfw.window_should_close(window) do 148 | glfw.wait_events_timeout(spf) 149 | dt = timer:update() -- duration of the current frame 150 | n = n_physics_updates(dt) -- no. of physics updates to do in this frame 151 | 152 | space:step(fdt, n) 153 | grabber:step(fdt, n) 154 | 155 | glfw.set_window_title(window, fmt("%s - fps=%.0f, n=%d", TITLE, timer:fps(), n)) 156 | gl.clear_color(BG_COLOR) 157 | gl.clear('color') 158 | renderer:begin() 159 | space:debug_draw() 160 | renderer:done() 161 | 162 | glfw.swap_buffers(window) 163 | collectgarbage() 164 | end 165 | 166 | toolbox.cleanup() 167 | 168 | -------------------------------------------------------------------------------- /examples/demo/05-pyramid-topple.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | local glfw = require("moonglfw") 3 | local gl = require("moongl") 4 | local glmath = require("moonglmath") 5 | local cp = require("moonchipmunk") 6 | local toolbox = require("moonchipmunk.toolbox") 7 | 8 | cp.glmath_compat(true) 9 | local pi, infinity = math.pi, math.huge 10 | local sin, cos, abs = math.sin, math.cos, math.abs 11 | local fmt = string.format 12 | local vec2 = glmath.vec2 13 | 14 | -- Initializations ------------------------------------------------------------ 15 | 16 | local TITLE = "Pyramid Topple" 17 | local FW, FH = 640, 480 -- width and height of the field 18 | local W, H = 1024, 768 -- window width and height 19 | local BG_COLOR = {0x07/255, 0x36/255, 0x42/255, 1.0} 20 | 21 | glfw.version_hint(3, 3, 'core') 22 | glfw.window_hint('samples', 32) 23 | local window = glfw.create_window(W, H, TITLE) 24 | glfw.make_context_current(window) 25 | gl.init() 26 | toolbox.init(W, H) 27 | local camera = toolbox.camera() 28 | 29 | local function resize(window, width, height) 30 | W, H = width, height 31 | toolbox.resize(W, H) 32 | toolbox.set_matrices(camera:view(), camera:projection(-FW/2, FW/2, -FH/2, FH/2)) 33 | gl.viewport(0, 0, W, H) 34 | end 35 | 36 | glfw.set_window_size_callback(window, resize) 37 | resize(window, W, H) 38 | 39 | -- Demo inits ----------------------------------------------------------------- 40 | 41 | local space = cp.space_new() 42 | local grabber = toolbox.grabber(window, space) 43 | local grabbable, not_grabbable = grabber:filters() 44 | space:set_iterations(30) 45 | space:set_gravity({0, -300}) 46 | space:set_sleep_time_threshold(0.5) 47 | space:set_collision_slop(0.5) 48 | -- Add a floor. 49 | local shape = cp.segment_shape_new(space:get_static_body(),{-600,-240}, {600,-240}, 0.0) 50 | space:add_shape(shape) 51 | shape:set_elasticity(1.0) 52 | shape:set_friction(1.0) 53 | shape:set_filter(not_grabbable) 54 | 55 | -- Add the dominoes. 56 | local n, width, height = 12, 4.0, 30.0 57 | local n = 12 58 | 59 | local function add_domino(space, pos, flipped) 60 | local mass, radius = 1.0, 0.5 61 | local moment = cp.moment_for_box(mass, width, height) 62 | local body = space:add_body(cp.body_new(mass, moment)) 63 | body:set_position(pos) 64 | local shape 65 | if flipped then 66 | shape = cp.box_shape_new(body, height, width, 0.0) 67 | else 68 | shape = cp.box_shape_new(body, width - radius*2.0, height, radius) 69 | end 70 | space:add_shape(shape) 71 | shape:set_elasticity(0.0) 72 | shape:set_friction(0.6) 73 | end 74 | 75 | for i=0, n-1 do 76 | for j=0, (n-i-1) do 77 | local offset = vec2((j-(n-1-i)*0.5)*1.5*height, (i+0.5)*(height+2*width)-width-240) 78 | add_domino(space, offset, false) 79 | add_domino(space, offset+vec2(0, (height + width)/2.0), true) 80 | if j == 0 then 81 | add_domino(space, offset + vec2(0.5*(width - height), height + width), false) 82 | end 83 | if j ~= (n-i-1) then 84 | add_domino(space, offset + vec2(height*0.75, (height + 3*width)/2.0), true) 85 | else 86 | add_domino(space, offset + vec2(0.5*(height - width), height + width), false) 87 | end 88 | end 89 | end 90 | 91 | -- Input handling ------------------------------------------------------------- 92 | 93 | local toggle_fullscreen = toolbox.toggle_fullscreen(window) 94 | local keys = {} -- keys[k] = true if key k is pressed 95 | 96 | glfw.set_key_callback(window, function(window, key, scancode, action) 97 | if key == 'escape' and action == 'press' then 98 | glfw.set_window_should_close(window, true) 99 | elseif key == 'f11' and action == 'press' then 100 | toggle_fullscreen() 101 | else 102 | keys[key] = action ~= 'release' 103 | end 104 | end) 105 | 106 | glfw.set_cursor_pos_callback(window, function(window, x, y) 107 | grabber:cursor_pos_callback(x, y) 108 | end) 109 | 110 | glfw.set_mouse_button_callback(window, function(window, button, action, shift, control, alt, super) 111 | grabber:mouse_button_callback(button, action, shift, control, alt, super) 112 | end) 113 | 114 | -- Game loop ------------------------------------------------------------------ 115 | local timer = toolbox.frame_timer() 116 | local spf = 1/60 -- 1 / desired fps 117 | local fdt = 1/180 -- fixed dt for physics updates 118 | local n_physics_updates = toolbox.fixed_dt_counter(fdt) 119 | local n, dt 120 | 121 | local renderer = toolbox.renderer(space) 122 | 123 | collectgarbage() 124 | collectgarbage('stop') 125 | while not glfw.window_should_close(window) do 126 | glfw.wait_events_timeout(spf) 127 | dt = timer:update() -- duration of the current frame 128 | n = n_physics_updates(dt) -- no. of physics updates to do in this frame 129 | 130 | space:step(fdt, n) 131 | grabber:step(fdt, n) 132 | 133 | glfw.set_window_title(window, fmt("%s - fps=%.0f, n=%d", TITLE, timer:fps(), n)) 134 | gl.clear_color(BG_COLOR) 135 | gl.clear('color') 136 | renderer:begin() 137 | space:debug_draw() 138 | renderer:done() 139 | 140 | glfw.swap_buffers(window) 141 | collectgarbage() 142 | end 143 | 144 | toolbox.cleanup() 145 | 146 | -------------------------------------------------------------------------------- /examples/demo/06-planet.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | local glfw = require("moonglfw") 3 | local gl = require("moongl") 4 | local glmath = require("moonglmath") 5 | local cp = require("moonchipmunk") 6 | local toolbox = require("moonchipmunk.toolbox") 7 | 8 | cp.glmath_compat(true) 9 | local pi, infinity = math.pi, math.huge 10 | local sin, cos, abs = math.sin, math.cos, math.abs 11 | local fmt = string.format 12 | local vec2 = glmath.vec2 13 | local identity = cp.transform_identity() 14 | 15 | -- Initializations ------------------------------------------------------------ 16 | 17 | local TITLE = "Planet" 18 | local FW, FH = 640, 480 -- width and height of the field 19 | local W, H = 1024, 768 -- window width and height 20 | local BG_COLOR = {0x07/255, 0x36/255, 0x42/255, 1.0} 21 | 22 | glfw.version_hint(3, 3, 'core') 23 | glfw.window_hint('samples', 32) 24 | local window = glfw.create_window(W, H, TITLE) 25 | glfw.make_context_current(window) 26 | gl.init() 27 | toolbox.init(W, H) 28 | local camera = toolbox.camera() 29 | 30 | local function resize(window, width, height) 31 | W, H = width, height 32 | toolbox.resize(W, H) 33 | toolbox.set_matrices(camera:view(), camera:projection(-FW/2, FW/2, -FH/2, FH/2)) 34 | gl.viewport(0, 0, W, H) 35 | end 36 | 37 | glfw.set_window_size_callback(window, resize) 38 | resize(window, W, H) 39 | 40 | -- Demo inits ----------------------------------------------------------------- 41 | 42 | local gravity_strength = 5.0e6 43 | 44 | local function planet_gravity_velocity_func(body, gravity, damping, dt) 45 | -- Gravitational acceleration is proportional to the inverse square of 46 | -- distance, and directed toward the origin. The central planet is assumed 47 | -- to be massive enough that it affects the satellites but not vice versa. 48 | local pos = body:get_position() 49 | local r = pos:norm() 50 | local g = (-gravity_strength/(r^3))*pos 51 | body:update_velocity(g, damping, dt) 52 | end 53 | 54 | local function rand_pos(radius) 55 | while true do 56 | local v = vec2(math.random()*(FW-2*radius)-(FW/2-radius), math.random()*(FH-2*radius)-(FH/2-radius)) 57 | if v:norm() >= 85.0 then return v end 58 | end 59 | end 60 | 61 | local function add_box(space) 62 | local size, mass = 10.0, 1.0 63 | local verts = {{-size,-size}, {-size, size}, { size, size}, { size,-size}} 64 | local radius = vec2(size, size):norm() 65 | local pos = rand_pos(radius) 66 | local body = cp.body_new(mass, cp.moment_for_poly(mass, verts, {0, 0}, 0.0)) 67 | space:add_body(body) 68 | body:set_velocity_update_func(planet_gravity_velocity_func) 69 | body:set_position(pos) 70 | -- Set the box's velocity to put it into a circular orbit from its starting position. 71 | local r = pos:norm() 72 | local v = math.sqrt(gravity_strength/r)/r 73 | body:set_velocity(v*vec2(-pos.y, pos.x)) -- perp 74 | -- Set the box's angular velocity to match its orbital period and 75 | -- align its initial angle with its position. 76 | body:set_angular_velocity(v) 77 | body:set_angle(math.atan(pos.y, pos.x)) 78 | local shape = cp.poly_shape_new(body, verts, 0.0, identity) 79 | space:add_shape(shape) 80 | shape:set_elasticity(0.0) 81 | shape:set_friction(0.7) 82 | end 83 | 84 | -- Create a rouge body to control the planet manually. 85 | local space = cp.space_new() 86 | local grabber = toolbox.grabber(window, space) 87 | local grabbable, not_grabbable = grabber:filters() 88 | space:set_iterations(20) 89 | local planetBody = space:add_body(cp.body_new_kinematic()) 90 | planetBody:set_angular_velocity(0.2) 91 | for i=1, 30 do add_box(space) end 92 | local shape = space:add_shape(cp.circle_shape_new(planetBody, 70.0, {0, 0})) 93 | shape:set_elasticity(1.0) 94 | shape:set_friction(1.0) 95 | shape:set_filter(not_grabbable) 96 | 97 | -- Input handling ------------------------------------------------------------- 98 | 99 | local toggle_fullscreen = toolbox.toggle_fullscreen(window) 100 | local keys = {} -- keys[k] = true if key k is pressed 101 | 102 | glfw.set_key_callback(window, function(window, key, scancode, action) 103 | if key == 'escape' and action == 'press' then 104 | glfw.set_window_should_close(window, true) 105 | elseif key == 'f11' and action == 'press' then 106 | toggle_fullscreen() 107 | else 108 | keys[key] = action ~= 'release' 109 | end 110 | end) 111 | 112 | glfw.set_cursor_pos_callback(window, function(window, x, y) 113 | grabber:cursor_pos_callback(x, y) 114 | end) 115 | 116 | glfw.set_mouse_button_callback(window, function(window, button, action, shift, control, alt, super) 117 | grabber:mouse_button_callback(button, action, shift, control, alt, super) 118 | end) 119 | 120 | -- Game loop ------------------------------------------------------------------ 121 | local timer = toolbox.frame_timer() 122 | local spf = 1/60 -- 1 / desired fps 123 | local fdt = 1/180 -- fixed dt for physics updates 124 | local n_physics_updates = toolbox.fixed_dt_counter(fdt) 125 | local n, dt 126 | 127 | local renderer = toolbox.renderer(space) 128 | 129 | collectgarbage() 130 | collectgarbage('stop') 131 | while not glfw.window_should_close(window) do 132 | glfw.wait_events_timeout(spf) 133 | dt = timer:update() -- duration of the current frame 134 | n = n_physics_updates(dt) -- no. of physics updates to do in this frame 135 | 136 | space:step(fdt, n) 137 | grabber:step(fdt, n) 138 | 139 | glfw.set_window_title(window, fmt("%s - fps=%.0f, n=%d", TITLE, timer:fps(), n)) 140 | gl.clear_color(BG_COLOR) 141 | gl.clear('color') 142 | renderer:begin() 143 | space:debug_draw() 144 | renderer:done() 145 | 146 | glfw.swap_buffers(window) 147 | collectgarbage() 148 | end 149 | 150 | toolbox.cleanup() 151 | 152 | -------------------------------------------------------------------------------- /examples/demo/10-query.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | local glfw = require("moonglfw") 3 | local gl = require("moongl") 4 | local glmath = require("moonglmath") 5 | local cp = require("moonchipmunk") 6 | local toolbox = require("moonchipmunk.toolbox") 7 | 8 | cp.glmath_compat(true) 9 | local pi, infinity = math.pi, math.huge 10 | local sin, cos, abs = math.sin, math.cos, math.abs 11 | local fmt = string.format 12 | local vec2 = glmath.vec2 13 | local clamp, mix = glmath.clamp, glmath.mix 14 | local identity = cp.transform_identity() 15 | 16 | -- Initializations ------------------------------------------------------------ 17 | 18 | local TITLE = "Segment Query" 19 | local FW, FH = 640, 480 -- width and height of the field 20 | local W, H = 1024, 768 -- window width and height 21 | local BG_COLOR = {0x07/255, 0x36/255, 0x42/255, 1.0} 22 | local FONT_COLOR, FONT_SIZE = {0xfd/250, 0xf6/250, 0xe3/250, 1.0}, 12/H 23 | 24 | local NO_COLOR = {0, 0, 0, 0} 25 | local RED = {1, 0, 0, 1} 26 | local GREEN = {0, 1, 0, 1} 27 | local BLUE = {0, 0, 1, 1} 28 | local GREY = {.5, .5, .5, 1} 29 | 30 | glfw.version_hint(3, 3, 'core') 31 | glfw.window_hint('samples', 32) 32 | local window = glfw.create_window(W, H, TITLE) 33 | glfw.make_context_current(window) 34 | gl.init() 35 | toolbox.init(W, H) 36 | local camera = toolbox.camera() 37 | 38 | local function resize(window, width, height) 39 | W, H = width, height 40 | toolbox.resize(W, H) 41 | toolbox.set_matrices(camera:view(), camera:projection(-FW/2, FW/2, -FH/2, FH/2)) 42 | gl.viewport(0, 0, W, H) 43 | end 44 | 45 | glfw.set_window_size_callback(window, resize) 46 | resize(window, W, H) 47 | 48 | -- Fonts ---------------------------------------------------------------------- 49 | local font = toolbox.font("../ttf-bitstream-vera-1.10/VeraMoBd.ttf", 40/H) 50 | 51 | -- Demo inits ----------------------------------------------------------------- 52 | local space = cp.space_new() 53 | local grabber = toolbox.grabber(window, space) 54 | local grabbable, not_grabbable = grabber:filters() 55 | local filter_all = {group=0, categories=-1, mask=-1 } 56 | local filter_none = {group=0, categories=0, mask=0 } 57 | space:set_iterations(5) 58 | 59 | -- add a fat segment 60 | local mass, length = 1.0, 100.0 61 | local a, b = {-length/2.0, 0.0}, {length/2.0, 0.0} 62 | local body = space:add_body(cp.body_new(mass, cp.moment_for_segment(mass, a, b, 0.0))) 63 | body:set_position({0.0, 100.0}) 64 | space:add_shape(cp.segment_shape_new(body, a, b, 20.0)) 65 | -- add a static segment 66 | space:add_shape(cp.segment_shape_new(space:get_static_body(), {0, 300}, {300, 0}, 0.0)) 67 | -- add a pentagon 68 | local mass, verts = 1.0, {} 69 | for i=0, 5 do 70 | local angle = -2.0*pi*i/5 71 | table.insert(verts, {30*cos(angle), 30*sin(angle)}) 72 | end 73 | local body = space:add_body(cp.body_new(mass, cp.moment_for_poly(mass, verts, {0, 0}, 0.0))) 74 | body:set_position({50.0, 30.0}) 75 | space:add_shape(cp.poly_shape_new(body, verts, 10.0, identity)) 76 | -- add a circle 77 | local mass, r = 1.0, 20.0 78 | local body = space:add_body(cp.body_new(mass, cp.moment_for_circle(mass, 0.0, r, {0, 0}))) 79 | body:set_position({100.0, 100.0}) 80 | space:add_shape(cp.circle_shape_new(body, r, {0, 0})) 81 | 82 | -- Input handling ------------------------------------------------------------- 83 | 84 | local toggle_fullscreen = toolbox.toggle_fullscreen(window) 85 | local keys = {} -- keys[k] = true if key k is pressed 86 | 87 | local right_click = false 88 | local query_start = vec2() 89 | 90 | glfw.set_key_callback(window, function(window, key, scancode, action) 91 | if key == 'escape' and action == 'press' then 92 | glfw.set_window_should_close(window, true) 93 | elseif key == 'f11' and action == 'press' then 94 | toggle_fullscreen() 95 | elseif key == 'right' then right_click = action~='release' 96 | else 97 | keys[key] = action ~= 'release' 98 | end 99 | end) 100 | 101 | glfw.set_cursor_pos_callback(window, function(window, x, y) 102 | grabber:cursor_pos_callback(x, y) 103 | end) 104 | 105 | glfw.set_mouse_button_callback(window, function(window, button, action, shift, control, alt, super) 106 | grabber:mouse_button_callback(button, action, shift, control, alt, super) 107 | end) 108 | 109 | -- Game loop ------------------------------------------------------------------ 110 | local timer = toolbox.frame_timer() 111 | local spf = 1/60 -- 1 / desired fps 112 | local fdt = 1/60 -- fixed dt for physics updates 113 | local n_physics_updates = toolbox.fixed_dt_counter(fdt) 114 | local n, dt 115 | 116 | local renderer = toolbox.renderer(space) 117 | local message1, message2 118 | 119 | collectgarbage() 120 | collectgarbage('stop') 121 | while not glfw.window_should_close(window) do 122 | glfw.wait_events_timeout(spf) 123 | dt = timer:update() -- duration of the current frame 124 | n = n_physics_updates(dt) -- no. of physics updates to do in this frame 125 | space:step(fdt, n) 126 | grabber:step(fdt, n) 127 | 128 | glfw.set_window_title(window, fmt("%s - fps=%.0f, n=%d", TITLE, timer:fps(), n)) 129 | gl.clear_color(BG_COLOR) 130 | gl.clear('color') 131 | 132 | renderer:begin() 133 | space:debug_draw() 134 | 135 | local mouse_pos = grabber:get_pos() 136 | if right_click then query_start = mouse_pos end 137 | local p_start = query_start 138 | local p_end = mouse_pos 139 | local dist = (p_end - p_start):norm() 140 | local radius = 10.0 141 | 142 | renderer:draw_segment(p_start, p_end, GREEN) 143 | message1 = fmt("Query: Dist(%f) Point(%5.2f, %5.2f), ", dist, p_end.x, p_end.y) 144 | local info = space:segment_query_first(p_start, p_end, radius, filter_all) 145 | local alpha = info and info.alpha or 0 146 | if info then 147 | local point, normal = info.point, info.normal 148 | -- Draw blue over the occluded part of the query 149 | renderer:draw_segment(mix(p_start, p_end, alpha), p_end, BLUE) 150 | -- Draw a little red surface normal 151 | renderer:draw_segment(point, point + 16*normal, RED) 152 | -- Draw a little red dot on the hit point. 153 | renderer:draw_dot(3, point, RED) 154 | message2 = fmt("Segment Query: Dist(%f) Normal(%5.2f, %5.2f)", alpha*dist, normal.x, normal.y) 155 | else 156 | message2 = "Segment Query (None)" 157 | end 158 | -- Draw a fat green line over the unoccluded part of the query 159 | renderer:draw_fat_segment(p_start, mix(p_start,p_end, alpha), radius, GREEN, NO_COLOR) 160 | local nearest_info = space:point_query_nearest(mouse_pos, 100.0, filter_all) 161 | if nearest_info then 162 | -- Draw a grey line to the closest shape. 163 | renderer:draw_dot(3, mouse_pos, GREY) 164 | renderer:draw_segment(mouse_pos, nearest_info.point, GREY) 165 | -- Draw a red bounding box around the shape under the mouse. 166 | if nearest_info.distance < 0 then 167 | renderer:draw_box(nearest_info.shape:get_bb(), RED) 168 | end 169 | end 170 | 171 | renderer:done() 172 | 173 | font:draw(message1..message2, .05, .9, FONT_SIZE, FONT_COLOR) 174 | 175 | glfw.swap_buffers(window) 176 | collectgarbage() 177 | end 178 | 179 | toolbox.cleanup() 180 | 181 | -------------------------------------------------------------------------------- /examples/demo/11-one-way.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | local glfw = require("moonglfw") 3 | local gl = require("moongl") 4 | local glmath = require("moonglmath") 5 | local cp = require("moonchipmunk") 6 | local toolbox = require("moonchipmunk.toolbox") 7 | 8 | cp.glmath_compat(true) 9 | local pi, infinity = math.pi, math.huge 10 | local sin, cos, abs = math.sin, math.cos, math.abs 11 | local fmt = string.format 12 | local vec2 = glmath.vec2 13 | local clamp, mix = glmath.clamp, glmath.mix 14 | local identity = cp.transform_identity() 15 | 16 | -- Initializations ------------------------------------------------------------ 17 | 18 | local TITLE = "One Way Platforms" 19 | local FW, FH = 640, 480 -- width and height of the field 20 | local W, H = 1024, 768 -- window width and height 21 | local BG_COLOR = {0x07/255, 0x36/255, 0x42/255, 1.0} 22 | local FONT_COLOR, FONT_SIZE = {0xfd/250, 0xf6/250, 0xe3/250, 1.0}, 12/H 23 | 24 | glfw.version_hint(3, 3, 'core') 25 | glfw.window_hint('samples', 32) 26 | local window = glfw.create_window(W, H, TITLE) 27 | glfw.make_context_current(window) 28 | gl.init() 29 | toolbox.init(W, H) 30 | local camera = toolbox.camera() 31 | 32 | local function resize(window, width, height) 33 | W, H = width, height 34 | toolbox.resize(W, H) 35 | toolbox.set_matrices(camera:view(), camera:projection(-FW/2, FW/2, -FH/2, FH/2)) 36 | gl.viewport(0, 0, W, H) 37 | end 38 | 39 | glfw.set_window_size_callback(window, resize) 40 | resize(window, W, H) 41 | 42 | -- Fonts ---------------------------------------------------------------------- 43 | local font = toolbox.font("../ttf-bitstream-vera-1.10/VeraMoBd.ttf", 40/H) 44 | 45 | -- Demo inits ----------------------------------------------------------------- 46 | 47 | local collision_type = { ONE_WAY=1, STANDARD=2 } 48 | 49 | local platforms = {} -- indexed by shape 50 | local function new_platform(normal, shape) 51 | local platform = { 52 | normal=normal, -- direction objects may pass through 53 | shape=shape, -- the platform's shape 54 | } 55 | platforms[shape] = platform 56 | return platform 57 | end 58 | 59 | local function pre_solve(arbiter, space) 60 | local a, b = arbiter:get_shapes() 61 | local platform = platforms[a] 62 | if arbiter:get_normal()*platform.normal < 0 then return arbiter:ignore() end 63 | return true 64 | end 65 | 66 | local space = cp.space_new() 67 | local grabber = toolbox.grabber(window, space) 68 | local grabbable, not_grabbable = grabber:filters() 69 | space:set_iterations(10) 70 | space:set_gravity({0, -100}) 71 | local static_body = space:get_static_body() 72 | -- Create segments around the edge of the screen. 73 | local shape = space:add_shape(cp.segment_shape_new(static_body, {-320,-240}, {-320,240}, 0.0)) 74 | shape:set_elasticity(1.0) 75 | shape:set_friction(1.0) 76 | shape:set_filter(not_grabbable) 77 | local shape = space:add_shape(cp.segment_shape_new(static_body, {320,-240}, {320,240}, 0.0)) 78 | shape:set_elasticity(1.0) 79 | shape:set_friction(1.0) 80 | shape:set_filter(not_grabbable) 81 | local shape = space:add_shape(cp.segment_shape_new(static_body, {-320,-240}, {320,-240}, 0.0)) 82 | shape:set_elasticity(1.0) 83 | shape:set_friction(1.0) 84 | shape:set_filter(not_grabbable) 85 | -- Add our one way segment 86 | local shape = space:add_shape(cp.segment_shape_new(static_body, {-160,-100}, {160,-100}, 10.0)) 87 | shape:set_elasticity(1.0) 88 | shape:set_friction(1.0) 89 | shape:set_collision_type(collision_type.ONE_WAY) 90 | shape:set_filter(not_grabbable) 91 | local platform = new_platform(vec2(0,1), shape) 92 | -- Add a ball to test it out 93 | local radius = 15.0 94 | local body = space:add_body(cp.body_new(10.0, cp.moment_for_circle(10.0, 0.0, radius, {0, 0}))) 95 | body:set_position({0, -200}) 96 | body:set_velocity({0, 170}) 97 | local shape = space:add_shape(cp.circle_shape_new(body, radius, {0, 0})) 98 | shape:set_elasticity(0.0) 99 | shape:set_friction(0.9) 100 | shape:set_collision_type(collision_type.STANDARD) 101 | local handler = space:add_wildcard_handler(collision_type.ONE_WAY) 102 | handler:set_pre_solve_func(pre_solve) 103 | 104 | -- Input handling ------------------------------------------------------------- 105 | 106 | local toggle_fullscreen = toolbox.toggle_fullscreen(window) 107 | local keys = {} -- keys[k] = true if key k is pressed 108 | 109 | glfw.set_key_callback(window, function(window, key, scancode, action) 110 | if key == 'escape' and action == 'press' then 111 | glfw.set_window_should_close(window, true) 112 | elseif key == 'f11' and action == 'press' then 113 | toggle_fullscreen() 114 | else 115 | keys[key] = action ~= 'release' 116 | end 117 | end) 118 | 119 | glfw.set_cursor_pos_callback(window, function(window, x, y) 120 | grabber:cursor_pos_callback(x, y) 121 | end) 122 | 123 | glfw.set_mouse_button_callback(window, function(window, button, action, shift, control, alt, super) 124 | grabber:mouse_button_callback(button, action, shift, control, alt, super) 125 | end) 126 | 127 | -- Game loop ------------------------------------------------------------------ 128 | local timer = toolbox.frame_timer() 129 | local spf = 1/60 -- 1 / desired fps 130 | local fdt = 1/60 -- fixed dt for physics updates 131 | local n_physics_updates = toolbox.fixed_dt_counter(fdt) 132 | local n, dt 133 | 134 | local message = "One way platforms are trivial in Chipmunk using a very simple collision callback." 135 | local renderer = toolbox.renderer(space) 136 | 137 | collectgarbage() 138 | collectgarbage('stop') 139 | while not glfw.window_should_close(window) do 140 | glfw.wait_events_timeout(spf) 141 | dt = timer:update() -- duration of the current frame 142 | n = n_physics_updates(dt) -- no. of physics updates to do in this frame 143 | space:step(fdt, n) 144 | grabber:step(fdt, n) 145 | 146 | glfw.set_window_title(window, fmt("%s - fps=%.0f, n=%d", TITLE, timer:fps(), n)) 147 | gl.clear_color(BG_COLOR) 148 | gl.clear('color') 149 | 150 | renderer:begin() 151 | space:debug_draw() 152 | renderer:done() 153 | 154 | font:draw(message, .05, .9, FONT_SIZE, FONT_COLOR) 155 | 156 | glfw.swap_buffers(window) 157 | collectgarbage() 158 | end 159 | 160 | toolbox.cleanup() 161 | 162 | -------------------------------------------------------------------------------- /examples/demo/14-chains.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | local glfw = require("moonglfw") 3 | local gl = require("moongl") 4 | local glmath = require("moonglmath") 5 | local cp = require("moonchipmunk") 6 | local toolbox = require("moonchipmunk.toolbox") 7 | 8 | cp.glmath_compat(true) 9 | local pi, infinity = math.pi, math.huge 10 | local sin, cos, abs = math.sin, math.cos, math.abs 11 | local fmt = string.format 12 | local vec2 = glmath.vec2 13 | local clamp, mix = glmath.clamp, glmath.mix 14 | local identity = cp.transform_identity() 15 | 16 | -- Initializations ------------------------------------------------------------ 17 | 18 | local TITLE = "Breakable Chains" 19 | local FW, FH = 640, 480 -- width and height of the field 20 | local W, H = 1024, 768 -- window width and height 21 | local BG_COLOR = {0x07/255, 0x36/255, 0x42/255, 1.0} 22 | local FONT_COLOR, FONT_SIZE = {0xfd/250, 0xf6/250, 0xe3/250, 1.0}, 12/H 23 | 24 | glfw.version_hint(3, 3, 'core') 25 | glfw.window_hint('samples', 32) 26 | local window = glfw.create_window(W, H, TITLE) 27 | glfw.make_context_current(window) 28 | gl.init() 29 | toolbox.init(W, H) 30 | local camera = toolbox.camera() 31 | 32 | local function resize(window, width, height) 33 | W, H = width, height 34 | toolbox.resize(W, H) 35 | toolbox.set_matrices(camera:view(), camera:projection(-FW/2, FW/2, -FH/2, FH/2)) 36 | gl.viewport(0, 0, W, H) 37 | end 38 | 39 | glfw.set_window_size_callback(window, resize) 40 | resize(window, W, H) 41 | 42 | -- Fonts ---------------------------------------------------------------------- 43 | local font = toolbox.font("../ttf-bitstream-vera-1.10/VeraMoBd.ttf", 40/H) 44 | 45 | -- Demo inits ----------------------------------------------------------------- 46 | 47 | local chain_count, link_count = 8, 10 48 | local breaking_force = 80000 49 | 50 | local function breakable_joint_post_solve(joint, space) 51 | local joint = joint 52 | local dt = space:get_current_time_step() 53 | -- Convert the impulse to a force by dividing it by the timestep. 54 | local force = joint:get_impulse()/dt 55 | local maxForce = joint:get_max_force() 56 | -- If the force is almost as big as the joint's max force, break it. 57 | if force > 0.9*maxForce then 58 | space:add_post_step_callback(function(space) 59 | space:remove_constraint(joint) 60 | joint:free() 61 | end) 62 | end 63 | end 64 | 65 | local space = cp.space_new() 66 | local grabber = toolbox.grabber(window, space) 67 | local grabbable, not_grabbable = grabber:filters() 68 | space:set_iterations(30) 69 | space:set_gravity({0, -100}) 70 | space:set_sleep_time_threshold(0.5) 71 | local static_body = space:get_static_body() 72 | -- Create segments around the edge of the screen. 73 | local shape = space:add_shape(cp.segment_shape_new(static_body, {-320,-240}, {-320,240}, 0.0)) 74 | shape:set_elasticity(1.0) 75 | shape:set_friction(1.0) 76 | shape:set_filter(not_grabbable) 77 | local shape = space:add_shape(cp.segment_shape_new(static_body, {320,-240}, {320,240}, 0.0)) 78 | shape:set_elasticity(1.0) 79 | shape:set_friction(1.0) 80 | shape:set_filter(not_grabbable) 81 | local shape = space:add_shape(cp.segment_shape_new(static_body, {-320,-240}, {320,-240}, 0.0)) 82 | shape:set_elasticity(1.0) 83 | shape:set_friction(1.0) 84 | shape:set_filter(not_grabbable) 85 | local shape = space:add_shape(cp.segment_shape_new(static_body, {-320,240}, {320,240}, 0.0)) 86 | shape:set_elasticity(1.0) 87 | shape:set_friction(1.0) 88 | shape:set_filter(not_grabbable) 89 | local mass, width, height = 1, 20, 30 90 | local spacing = width*0.3 91 | -- Add lots of boxes. 92 | for i=0, chain_count-1 do 93 | local prev = nil 94 | for j= 0, link_count-1 do 95 | local pos = vec2(40*(i-(chain_count-1)/2.0), 240-(j+0.5)*height-(j+1)*spacing) 96 | local body = space:add_body(cp.body_new(mass, cp.moment_for_box(mass, width, height))) 97 | body:set_position(pos) 98 | local shape = cp.segment_shape_new(body, 99 | {0, (height-width)/2.0}, {0, (width-height)/2.0}, width/2.0) 100 | space:add_shape(shape) 101 | shape:set_friction(0.8) 102 | local constraint 103 | if not prev then 104 | constraint = cp.slide_joint_new(body, static_body, {0, height/2}, {pos.x, 240}, 0, spacing) 105 | else 106 | constraint = cp.slide_joint_new(body, prev, {0, height/2}, {0, -height/2}, 0, spacing) 107 | end 108 | space:add_constraint(constraint) 109 | constraint:set_max_force(breaking_force) 110 | constraint:set_post_solve_func(breakable_joint_post_solve) 111 | constraint:set_collide_bodies(false) 112 | prev = body 113 | end 114 | end 115 | local radius = 15.0 116 | local body = space:add_body(cp.body_new(10.0, cp.moment_for_circle(10.0, 0.0, radius, {0, 0}))) 117 | body:set_position({0, -240 + radius+5}) 118 | body:set_velocity({0, 300}) 119 | local shape = space:add_shape(cp.circle_shape_new(body, radius, {0, 0})) 120 | shape:set_elasticity(0.0) 121 | shape:set_friction(0.9) 122 | 123 | -- Input handling ------------------------------------------------------------- 124 | 125 | local toggle_fullscreen = toolbox.toggle_fullscreen(window) 126 | local keys = {} -- keys[k] = true if key k is pressed 127 | 128 | glfw.set_key_callback(window, function(window, key, scancode, action) 129 | if key == 'escape' and action == 'press' then 130 | glfw.set_window_should_close(window, true) 131 | elseif key == 'f11' and action == 'press' then 132 | toggle_fullscreen() 133 | else 134 | keys[key] = action ~= 'release' 135 | end 136 | end) 137 | 138 | glfw.set_cursor_pos_callback(window, function(window, x, y) 139 | grabber:cursor_pos_callback(x, y) 140 | end) 141 | 142 | glfw.set_mouse_button_callback(window, function(window, button, action, shift, control, alt, super) 143 | grabber:mouse_button_callback(button, action, shift, control, alt, super) 144 | end) 145 | 146 | -- Game loop ------------------------------------------------------------------ 147 | local timer = toolbox.frame_timer() 148 | local spf = 1/60 -- 1 / desired fps 149 | local fdt = 1/180 -- fixed dt for physics updates 150 | local n_physics_updates = toolbox.fixed_dt_counter(fdt) 151 | local n, dt 152 | 153 | local renderer = toolbox.renderer(space) 154 | 155 | collectgarbage() 156 | collectgarbage('stop') 157 | while not glfw.window_should_close(window) do 158 | glfw.wait_events_timeout(spf) 159 | dt = timer:update() -- duration of the current frame 160 | n = n_physics_updates(dt) -- no. of physics updates to do in this frame 161 | space:step(fdt, n) 162 | grabber:step(fdt, n) 163 | 164 | glfw.set_window_title(window, fmt("%s - fps=%.0f, n=%d", TITLE, timer:fps(), n)) 165 | gl.clear_color(BG_COLOR) 166 | gl.clear('color') 167 | 168 | renderer:begin() 169 | space:debug_draw() 170 | renderer:done() 171 | 172 | -- font:draw(message, .05, .9, FONT_SIZE, FONT_COLOR) 173 | 174 | glfw.swap_buffers(window) 175 | collectgarbage() 176 | end 177 | 178 | toolbox.cleanup() 179 | 180 | -------------------------------------------------------------------------------- /examples/demo/20-convex.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | local glfw = require("moonglfw") 3 | local gl = require("moongl") 4 | local glmath = require("moonglmath") 5 | local cp = require("moonchipmunk") 6 | local toolbox = require("moonchipmunk.toolbox") 7 | 8 | cp.glmath_compat(true) 9 | local pi, infinity = math.pi, math.huge 10 | local sin, cos, abs, exp, sqrt = math.sin, math.cos, math.abs, math.exp, math.sqrt 11 | local fmt = string.format 12 | local vec2 = glmath.vec2 13 | local clamp, mix = glmath.clamp, glmath.mix 14 | local identity = cp.transform_identity() 15 | 16 | -- Initializations ------------------------------------------------------------ 17 | 18 | local TITLE = "Convex" 19 | local FW, FH = 640, 480 -- width and height of the field 20 | local W, H = 1024, 768 -- window width and height 21 | local BG_COLOR = {0x07/255, 0x36/255, 0x42/255, 1.0} 22 | local FONT_COLOR, FONT_SIZE = {0xfd/250, 0xf6/250, 0xe3/250, 1.0}, 12/H 23 | 24 | glfw.version_hint(3, 3, 'core') 25 | glfw.window_hint('samples', 32) 26 | local window = glfw.create_window(W, H, TITLE) 27 | glfw.make_context_current(window) 28 | gl.init() 29 | toolbox.init(W, H) 30 | local camera = toolbox.camera() 31 | 32 | local function resize(window, width, height) 33 | W, H = width, height 34 | toolbox.resize(W, H) 35 | toolbox.set_matrices(camera:view(), camera:projection(-FW/2, FW/2, -FH/2, FH/2)) 36 | gl.viewport(0, 0, W, H) 37 | end 38 | 39 | glfw.set_window_size_callback(window, resize) 40 | resize(window, W, H) 41 | 42 | -- Fonts ---------------------------------------------------------------------- 43 | local font = toolbox.font("../ttf-bitstream-vera-1.10/VeraMoBd.ttf", 40/H) 44 | 45 | -- Demo inits ----------------------------------------------------------------- 46 | 47 | local density = 1/10000 48 | local tolerance = 2.0 49 | 50 | local space = cp.space_new() 51 | local grabber = toolbox.grabber(window, space) 52 | local grabbable, not_grabbable = grabber:filters() 53 | space:set_iterations(30) 54 | space:set_gravity({0, -500}) 55 | space:set_sleep_time_threshold(0.5) 56 | space:set_collision_slop(0.5) 57 | local static_body = space:get_static_body(space) 58 | -- Create segments around the edge of the screen. 59 | local shape = space:add_shape(cp.segment_shape_new(static_body, {-320,-240}, {320,-240}, 0.0)) 60 | shape:set_elasticity(1.0) 61 | shape:set_friction(1.0) 62 | shape:set_filter(not_grabbable) 63 | local width, height = 50.0, 70.0 64 | local mass = width*height*density 65 | local moment = cp.moment_for_box(mass, width, height) 66 | local body = space:add_body(cp.body_new(mass, moment)) 67 | local shape = space:add_shape(cp.box_shape_new(body, width, height, 0.0)) 68 | shape:set_friction(0.6) 69 | 70 | -- Input handling ------------------------------------------------------------- 71 | 72 | local toggle_fullscreen = toolbox.toggle_fullscreen(window) 73 | local keys = {} -- keys[k] = true if key k is pressed 74 | local right_click, last_right_click_state = false, false 75 | 76 | glfw.set_key_callback(window, function(window, key, scancode, action) 77 | if key == 'escape' and action == 'press' then glfw.set_window_should_close(window, true) 78 | elseif key == 'f11' and action == 'press' then toggle_fullscreen() 79 | else 80 | keys[key] = action ~= 'release' 81 | end 82 | end) 83 | 84 | glfw.set_cursor_pos_callback(window, function(window, x, y) 85 | grabber:cursor_pos_callback(x, y) 86 | end) 87 | 88 | glfw.set_mouse_button_callback(window, function(window, button, action, shift, control, alt, super) 89 | grabber:mouse_button_callback(button, action, shift, control, alt, super) 90 | if button == 'right' then right_click = action ~= 'release' end 91 | end) 92 | 93 | -- Game loop ------------------------------------------------------------------ 94 | local timer = toolbox.frame_timer() 95 | local spf = 1/60 -- 1 / desired fps 96 | local fdt = 1/60 -- fixed dt for physics updates 97 | local n_physics_updates = toolbox.fixed_dt_counter(fdt) 98 | local n, dt 99 | 100 | local renderer = toolbox.renderer(space) 101 | 102 | collectgarbage() 103 | collectgarbage('stop') 104 | while not glfw.window_should_close(window) do 105 | glfw.wait_events_timeout(spf) 106 | dt = timer:update() -- duration of the current frame 107 | n = n_physics_updates(dt) -- no. of physics updates to do in this frame 108 | 109 | if right_click then 110 | local mouse_pos = grabber:get_pos() 111 | local info = shape:point_query(mouse_pos) 112 | if info.distance > tolerance then 113 | local body = shape:get_body() 114 | local verts = shape:get_verts() 115 | verts[#verts+1] = body:world_to_local(mouse_pos) 116 | -- This function builds a convex hull for the vertexes. 117 | local verts = cp.convex_hull(verts, tolerance) 118 | -- Figure out how much to shift the body by. 119 | local centroid = cp.centroid_for_poly(verts) 120 | -- Recalculate the body properties to match the updated shape. 121 | local mass = cp.area_for_poly(verts, 0.0)*density 122 | body:set_mass(mass) 123 | body:set_moment(cp.moment_for_poly(mass, verts, -centroid, 0.0)) 124 | body:set_position(body:local_to_world(centroid)) 125 | -- Use the setter function from chipmunk_unsafe.h. 126 | -- You could also remove and recreate the shape if you wanted. 127 | shape:set_verts(verts, cp.transform_translate(-centroid)) 128 | end 129 | end 130 | space:step(fdt, n) 131 | grabber:step(fdt, n) 132 | 133 | glfw.set_window_title(window, fmt("%s - fps=%.0f, n=%d", TITLE, timer:fps(), n)) 134 | gl.clear_color(BG_COLOR) 135 | gl.clear('color') 136 | 137 | renderer:begin() 138 | space:debug_draw() 139 | renderer:done() 140 | 141 | font:draw("Right click and drag to change the blocks's shape.", .05, .9, FONT_SIZE, FONT_COLOR) 142 | 143 | glfw.swap_buffers(window) 144 | collectgarbage() 145 | end 146 | 147 | toolbox.cleanup() 148 | 149 | -------------------------------------------------------------------------------- /examples/enumsandflags.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | -- MoonChipmunk example: enumsandflags.lua 3 | local cp = require("moonchipmunk") 4 | 5 | -- Enums 6 | print(table.unpack(cp.enum('bodytype'))) 7 | 8 | -- Flags 9 | print(cp.debugdrawflags(-1)) 10 | print(string.format("0x%.8x", cp.debugdrawflags('shapes', 'constraints', 'points'))) 11 | 12 | print(string.format("SPACE_DEBUG_DRAW_SHAPES 0x%x", cp.SPACE_DEBUG_DRAW_SHAPES)) 13 | print(string.format("SPACE_DEBUG_DRAW_CONSTRAINTS 0x%x", cp.SPACE_DEBUG_DRAW_CONSTRAINTS)) 14 | print(string.format("SPACE_DEBUG_DRAW_COLLISION_POINTS 0x%x", cp.SPACE_DEBUG_DRAW_COLLISION_POINTS)) 15 | local flags = cp.SPACE_DEBUG_DRAW_SHAPES|cp.SPACE_DEBUG_DRAW_CONSTRAINTS|cp.SPACE_DEBUG_DRAW_COLLISION_POINTS 16 | print(string.format("0x%.8x", flags)) 17 | 18 | -- Constants 19 | print(string.format("NO_GROUP 0x%x", cp.NO_GROUP)) 20 | print(string.format("ALL_CATEGORIES 0x%x", cp.ALL_CATEGORIES)) 21 | print(string.format("WILDCARD_COLLISION_TYPE 0x%x", cp.WILDCARD_COLLISION_TYPE)) 22 | 23 | 24 | print(string.format("~ALL_CATEGORIES 0x%x", ~cp.ALL_CATEGORIES)) 25 | print(string.format("~WILDCARD_COLLISION_TYPE 0x%x", ~cp.WILDCARD_COLLISION_TYPE)) 26 | -------------------------------------------------------------------------------- /examples/hello.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | -- MoonChipmunk example: hello.lua 3 | -- This is a port of the "Hello Chipmunk (World)" example from the Chipmunk manual: 4 | -- (see http://chipmunk-physics.net/release/ChipmunkLatest-Docs/#Intro-HelloChipmunk ) 5 | 6 | local cp = require("moonchipmunk") 7 | 8 | -- Create an empty space and set the gravity for it. 9 | local space = cp.space_new() 10 | space:set_gravity({0, -100}) 11 | 12 | -- Add a static line segment shape for the ground. 13 | -- We'll make it slightly tilted so the ball will roll off. 14 | -- We attach it to a static body to tell Chipmunk it shouldn't be movable. 15 | local ground = cp.segment_shape_new(space:get_static_body(), {-20, 5}, {20, -5}, 0) 16 | ground:set_friction(1) 17 | space:add_shape(ground) 18 | 19 | -- Now let's make a ball that falls onto the line and rolls off. 20 | -- First we need to make a body to hold the physical properties of the object. 21 | -- These include the mass, position, velocity, angle, etc. of the object. 22 | -- Then we attach collision shapes to the body to give it a size and shape. 23 | local radius = 5 24 | local mass = 1 25 | -- The moment of inertia is like mass for rotation 26 | -- Use the cp.moment_for*() functions to help you approximate it. 27 | local moment = cp.moment_for_circle(mass, 0, radius, {0, 0}) 28 | 29 | -- The space:add*() methods return the thing that you are adding. 30 | -- It's convenient to create and add an object in one line. 31 | local ballBody = space:add_body(cp.body_new(mass, moment)) 32 | ballBody:set_position({0, 15}) 33 | 34 | -- Now we create the collision shape for the ball. 35 | -- You can create multiple collision shapes that point to the same body. 36 | -- They will all be attached to the body and move around to follow it. 37 | local ballShape = space:add_shape(cp.circle_shape_new(ballBody, radius, {0, 0})) 38 | ballShape:set_friction(0.7) 39 | 40 | -- Now that it's all set up, we simulate all the objects in the space by 41 | -- stepping forward through time in small increments called steps. 42 | -- It is *highly* recommended to use a fixed size time step. 43 | local timeStep = 1.0/60.0 44 | for time = 0, 2, timeStep do 45 | local pos = ballBody:get_position() 46 | local vel = ballBody:get_velocity() 47 | print(string.format( 48 | "Time is %5.2f. ballBody is at (%5.2f, %5.2f). It's velocity is (%5.2f, %5.2f)", 49 | time, pos[1], pos[2], vel[1], vel[2])) 50 | space:step(timeStep) 51 | end 52 | 53 | -- No need to delete objects here (they are are automatically deleted ad exit). 54 | -------------------------------------------------------------------------------- /examples/sounds/Explosion_00.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stetre/moonchipmunk/0e93b019d43041d5c12c6edb5b2bcfcc39c0155a/examples/sounds/Explosion_00.wav -------------------------------------------------------------------------------- /examples/sounds/Jingle_Win_00.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stetre/moonchipmunk/0e93b019d43041d5c12c6edb5b2bcfcc39c0155a/examples/sounds/Jingle_Win_00.wav -------------------------------------------------------------------------------- /examples/sounds/LICENSE: -------------------------------------------------------------------------------- 1 | 2 | The sound samples contained in this directory are taken from the 3 | '8 Bit Sound Effects Library', by Little Robot Sound Factory: 4 | https://opengameart.org/content/8-bit-sound-effects-library 5 | 6 | License: CC-BY 3.0 (https://creativecommons.org/licenses/by/3.0/). 7 | 8 | -------------------------------------------------------------------------------- /examples/sounds/Shoot_00.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stetre/moonchipmunk/0e93b019d43041d5c12c6edb5b2bcfcc39c0155a/examples/sounds/Shoot_00.wav -------------------------------------------------------------------------------- /examples/sprites/LICENSE: -------------------------------------------------------------------------------- 1 | 2 | The sprite renderer in moonchipmunk/toolbox.lua is based on the 3 | Learn OpenGL tutorial by Joey de Vries, at: 4 | https://learnopengl.com/#!In-Practice/2D-Game/Rendering-Sprites 5 | 6 | The texture images contained in this directory are taken from the 7 | same source, and are covered by the CC-BY 4.0 license 8 | (https://creativecommons.org/licenses/by/4.0/) 9 | 10 | 11 | -------------------------------------------------------------------------------- /examples/sprites/awesomeface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stetre/moonchipmunk/0e93b019d43041d5c12c6edb5b2bcfcc39c0155a/examples/sprites/awesomeface.png -------------------------------------------------------------------------------- /examples/sprites/block.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stetre/moonchipmunk/0e93b019d43041d5c12c6edb5b2bcfcc39c0155a/examples/sprites/block.png -------------------------------------------------------------------------------- /examples/toolboxtest.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | local glfw = require("moonglfw") 3 | local gl = require("moongl") 4 | local glmath = require("moonglmath") 5 | local cp = require("moonchipmunk") 6 | local toolbox = require("moonchipmunk.toolbox") 7 | --local game = require("game") 8 | 9 | local vec2, vec3, vec4 = glmath.vec2, glmath.vec3, glmath.vec4 10 | local fmt = string.format 11 | 12 | -- Initializations ------------------------------------------------------------ 13 | 14 | local TITLE = "Prova!" 15 | local FW, FH = 640, 480 -- width and height of the field 16 | local W, H = 1024, 768 -- window width and height 17 | 18 | local WHITE = {1, 1, 1, 1} 19 | local RED = {1, 0, 0, 1} 20 | local GREEN = {0, 1, 0, 1} 21 | local BLUE = {0, 0, 1, 1} 22 | 23 | glfw.version_hint(3, 3, 'core') 24 | glfw.window_hint('samples', 32) 25 | local window = glfw.create_window(W, H, TITLE) 26 | glfw.make_context_current(window) 27 | gl.init() 28 | toolbox.init(W, H, true) 29 | local camera = toolbox.camera(vec3(0, 0, 0)) 30 | --game.init(W, H) 31 | 32 | local view, projection 33 | local function set_matrices() 34 | toolbox.set_matrices(camera:view(), camera:projection(-FW/2, FW/2, -FH/2, FH/2)) 35 | toolbox.resize(W, H) 36 | end 37 | 38 | local function resize(window, w, h) 39 | W, H = w, h 40 | set_matrices() 41 | --game.resize(W, H) 42 | gl.viewport(0, 0, W, H) 43 | end 44 | 45 | glfw.set_window_size_callback(window, resize) 46 | resize(window, W, H) 47 | 48 | local space = cp.space_new() 49 | local renderer = toolbox.renderer(space) 50 | 51 | -- Fonts ---------------------------------------------------------------------- 52 | local font = toolbox.font("ttf-bitstream-vera-1.10/VeraMoBd.ttf", .3) 53 | 54 | -- Sprites -------------------------------------------------------------------- 55 | local face = toolbox.sprite("sprites/awesomeface.png", 'rgba') 56 | local block = toolbox.sprite("sprites/block.png", 'rgb') 57 | 58 | -- Sounds --------------------------------------------------------------------- 59 | local shoot = toolbox.sound_sample("sounds/Shoot_00.wav") 60 | local explosion = toolbox.sound_sample("sounds/Explosion_00.wav") 61 | local jinglewin = toolbox.sound_sample("sounds/Jingle_Win_00.wav") 62 | 63 | local function playsoundevery(sample, interval) 64 | local sample = sample 65 | local interval = interval 66 | local t = 0 67 | return function(dt) 68 | t = t+dt 69 | if t >= interval then sample:play() t = 0 end 70 | end 71 | end 72 | 73 | local playshoot = playsoundevery(shoot, 1) 74 | local playexplosion = playsoundevery(explosion, 2.3) 75 | local playjinglewin = playsoundevery(jinglewin, 2.7) 76 | 77 | -- Input handling ------------------------------------------------------------- 78 | 79 | local toggle_fullscreen = toolbox.toggle_fullscreen(window) 80 | local keys = {} -- keys[k] = true if key k is pressed 81 | 82 | glfw.set_key_callback(window, function(window, key, scancode, action) 83 | if key == 'escape' and action == 'press' then 84 | glfw.set_window_should_close(window, true) 85 | elseif key == 'f11' and action == 'press' then 86 | toggle_fullscreen() 87 | else 88 | keys[key] = action ~= 'release' 89 | end 90 | end) 91 | 92 | -- Game loop ------------------------------------------------------------------ 93 | 94 | local timer = toolbox.frame_timer() 95 | 96 | local rot = 0 97 | local fdt = 1/180 -- fixed dt for physics updates 98 | local n_physics_updates = toolbox.fixed_dt_counter(fdt) 99 | local dt = timer:update() 100 | 101 | 102 | local ang_speed = math.pi/10 -- rad/s 103 | collectgarbage() 104 | collectgarbage('stop') 105 | while not glfw.window_should_close(window) do 106 | glfw.wait_events_timeout(1/60) 107 | dt = timer:update() 108 | local n = n_physics_updates(dt) 109 | space:step(fdt, n) -- do n update steps with time interval = fdt 110 | 111 | glfw.set_window_title(window, tostring(timer)) 112 | 113 | playshoot(dt) 114 | playexplosion(dt) 115 | playjinglewin(dt) 116 | 117 | if keys['up'] then camera:move('up', 200, dt) end 118 | if keys['down'] then camera:move('down', 200, dt) end 119 | if keys['left'] then camera:move('left', 200, dt) end 120 | if keys['right'] then camera:move('right', 200, dt) end 121 | if keys['w'] then camera:zoom('in', 1, dt) end 122 | if keys['s'] then camera:zoom('out', 1, dt) end 123 | if keys['a'] then camera:rotate('ccw', ang_speed, dt) end 124 | if keys['d'] then camera:rotate('cw', ang_speed, dt) end 125 | set_matrices() 126 | 127 | --game.input(keys) 128 | --game.update(dt, keys) 129 | --game.draw(dt, keys) 130 | 131 | gl.clear_color(0.3, 0.3, 0.3, 1.0) 132 | gl.clear('color') 133 | renderer:begin() 134 | renderer:draw_dot(40, {0, 0}, {1, 0, 0, 1}) 135 | renderer:draw_dot(40, {FW/2, FH/2}, {0, 0, 1, 1}) 136 | 137 | rot = rot + dt 138 | face:draw({0,100}, {100,100}, rot) 139 | block:draw({0, -200}, {100, 30}, 0, RED) 140 | block:draw({100, -200}, {100, 30}, 0, GREEN) 141 | block:draw({200, -200}, {100, 30}, math.pi/4, BLUE) 142 | block:draw({300, -200}, {100, 30}, 0, WHITE) 143 | 144 | font:draw(string.format("Physics intervals = %d", n), 0, 0, .05, WHITE) 145 | 146 | renderer:draw_box({-FW/4, 0, FH/8, FH/4}, {1, 0, 0, 1}) 147 | renderer:draw_fat_segment({0, 0}, vec2(FW/4, FH/4)*math.cos(rot), 10, {0, 1, 0, 1}, {0, 0, 0, 0}) 148 | renderer:done() 149 | 150 | glfw.swap_buffers(window) 151 | collectgarbage() 152 | end 153 | 154 | toolbox.cleanup() 155 | 156 | -------------------------------------------------------------------------------- /examples/ttf-bitstream-vera-1.10/COPYRIGHT.TXT: -------------------------------------------------------------------------------- 1 | Bitstream Vera Fonts Copyright 2 | 3 | The fonts have a generous copyright, allowing derivative works (as 4 | long as "Bitstream" or "Vera" are not in the names), and full 5 | redistribution (so long as they are not *sold* by themselves). They 6 | can be be bundled, redistributed and sold with any software. 7 | 8 | The fonts are distributed under the following copyright: 9 | 10 | Copyright 11 | ========= 12 | 13 | Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream 14 | Vera is a trademark of Bitstream, Inc. 15 | 16 | Permission is hereby granted, free of charge, to any person obtaining 17 | a copy of the fonts accompanying this license ("Fonts") and associated 18 | documentation files (the "Font Software"), to reproduce and distribute 19 | the Font Software, including without limitation the rights to use, 20 | copy, merge, publish, distribute, and/or sell copies of the Font 21 | Software, and to permit persons to whom the Font Software is furnished 22 | to do so, subject to the following conditions: 23 | 24 | The above copyright and trademark notices and this permission notice 25 | shall be included in all copies of one or more of the Font Software 26 | typefaces. 27 | 28 | The Font Software may be modified, altered, or added to, and in 29 | particular the designs of glyphs or characters in the Fonts may be 30 | modified and additional glyphs or characters may be added to the 31 | Fonts, only if the fonts are renamed to names not containing either 32 | the words "Bitstream" or the word "Vera". 33 | 34 | This License becomes null and void to the extent applicable to Fonts 35 | or Font Software that has been modified and is distributed under the 36 | "Bitstream Vera" names. 37 | 38 | The Font Software may be sold as part of a larger software package but 39 | no copy of one or more of the Font Software typefaces may be sold by 40 | itself. 41 | 42 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 43 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 44 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 45 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL 46 | BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR 47 | OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, 48 | OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR 49 | OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT 50 | SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. 51 | 52 | Except as contained in this notice, the names of Gnome, the Gnome 53 | Foundation, and Bitstream Inc., shall not be used in advertising or 54 | otherwise to promote the sale, use or other dealings in this Font 55 | Software without prior written authorization from the Gnome Foundation 56 | or Bitstream Inc., respectively. For further information, contact: 57 | fonts at gnome dot org. 58 | 59 | Copyright FAQ 60 | ============= 61 | 62 | 1. I don't understand the resale restriction... What gives? 63 | 64 | Bitstream is giving away these fonts, but wishes to ensure its 65 | competitors can't just drop the fonts as is into a font sale system 66 | and sell them as is. It seems fair that if Bitstream can't make money 67 | from the Bitstream Vera fonts, their competitors should not be able to 68 | do so either. You can sell the fonts as part of any software package, 69 | however. 70 | 71 | 2. I want to package these fonts separately for distribution and 72 | sale as part of a larger software package or system. Can I do so? 73 | 74 | Yes. A RPM or Debian package is a "larger software package" to begin 75 | with, and you aren't selling them independently by themselves. 76 | See 1. above. 77 | 78 | 3. Are derivative works allowed? 79 | Yes! 80 | 81 | 4. Can I change or add to the font(s)? 82 | Yes, but you must change the name(s) of the font(s). 83 | 84 | 5. Under what terms are derivative works allowed? 85 | 86 | You must change the name(s) of the fonts. This is to ensure the 87 | quality of the fonts, both to protect Bitstream and Gnome. We want to 88 | ensure that if an application has opened a font specifically of these 89 | names, it gets what it expects (though of course, using fontconfig, 90 | substitutions could still could have occurred during font 91 | opening). You must include the Bitstream copyright. Additional 92 | copyrights can be added, as per copyright law. Happy Font Hacking! 93 | 94 | 6. If I have improvements for Bitstream Vera, is it possible they might get 95 | adopted in future versions? 96 | 97 | Yes. The contract between the Gnome Foundation and Bitstream has 98 | provisions for working with Bitstream to ensure quality additions to 99 | the Bitstream Vera font family. Please contact us if you have such 100 | additions. Note, that in general, we will want such additions for the 101 | entire family, not just a single font, and that you'll have to keep 102 | both Gnome and Jim Lyles, Vera's designer, happy! To make sense to add 103 | glyphs to the font, they must be stylistically in keeping with Vera's 104 | design. Vera cannot become a "ransom note" font. Jim Lyles will be 105 | providing a document describing the design elements used in Vera, as a 106 | guide and aid for people interested in contributing to Vera. 107 | 108 | 7. I want to sell a software package that uses these fonts: Can I do so? 109 | 110 | Sure. Bundle the fonts with your software and sell your software 111 | with the fonts. That is the intent of the copyright. 112 | 113 | 8. If applications have built the names "Bitstream Vera" into them, 114 | can I override this somehow to use fonts of my choosing? 115 | 116 | This depends on exact details of the software. Most open source 117 | systems and software (e.g., Gnome, KDE, etc.) are now converting to 118 | use fontconfig (see www.fontconfig.org) to handle font configuration, 119 | selection and substitution; it has provisions for overriding font 120 | names and subsituting alternatives. An example is provided by the 121 | supplied local.conf file, which chooses the family Bitstream Vera for 122 | "sans", "serif" and "monospace". Other software (e.g., the XFree86 123 | core server) has other mechanisms for font substitution. 124 | 125 | -------------------------------------------------------------------------------- /examples/ttf-bitstream-vera-1.10/README.TXT: -------------------------------------------------------------------------------- 1 | Contained herin is the Bitstream Vera font family. 2 | 3 | The Copyright information is found in the COPYRIGHT.TXT file (along 4 | with being incoporated into the fonts themselves). 5 | 6 | The releases notes are found in the file "RELEASENOTES.TXT". 7 | 8 | We hope you enjoy Vera! 9 | 10 | Bitstream, Inc. 11 | The Gnome Project 12 | -------------------------------------------------------------------------------- /examples/ttf-bitstream-vera-1.10/Vera.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stetre/moonchipmunk/0e93b019d43041d5c12c6edb5b2bcfcc39c0155a/examples/ttf-bitstream-vera-1.10/Vera.ttf -------------------------------------------------------------------------------- /examples/ttf-bitstream-vera-1.10/VeraBI.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stetre/moonchipmunk/0e93b019d43041d5c12c6edb5b2bcfcc39c0155a/examples/ttf-bitstream-vera-1.10/VeraBI.ttf -------------------------------------------------------------------------------- /examples/ttf-bitstream-vera-1.10/VeraBd.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stetre/moonchipmunk/0e93b019d43041d5c12c6edb5b2bcfcc39c0155a/examples/ttf-bitstream-vera-1.10/VeraBd.ttf -------------------------------------------------------------------------------- /examples/ttf-bitstream-vera-1.10/VeraIt.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stetre/moonchipmunk/0e93b019d43041d5c12c6edb5b2bcfcc39c0155a/examples/ttf-bitstream-vera-1.10/VeraIt.ttf -------------------------------------------------------------------------------- /examples/ttf-bitstream-vera-1.10/VeraMoBI.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stetre/moonchipmunk/0e93b019d43041d5c12c6edb5b2bcfcc39c0155a/examples/ttf-bitstream-vera-1.10/VeraMoBI.ttf -------------------------------------------------------------------------------- /examples/ttf-bitstream-vera-1.10/VeraMoBd.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stetre/moonchipmunk/0e93b019d43041d5c12c6edb5b2bcfcc39c0155a/examples/ttf-bitstream-vera-1.10/VeraMoBd.ttf -------------------------------------------------------------------------------- /examples/ttf-bitstream-vera-1.10/VeraMoIt.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stetre/moonchipmunk/0e93b019d43041d5c12c6edb5b2bcfcc39c0155a/examples/ttf-bitstream-vera-1.10/VeraMoIt.ttf -------------------------------------------------------------------------------- /examples/ttf-bitstream-vera-1.10/VeraMono.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stetre/moonchipmunk/0e93b019d43041d5c12c6edb5b2bcfcc39c0155a/examples/ttf-bitstream-vera-1.10/VeraMono.ttf -------------------------------------------------------------------------------- /examples/ttf-bitstream-vera-1.10/VeraSe.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stetre/moonchipmunk/0e93b019d43041d5c12c6edb5b2bcfcc39c0155a/examples/ttf-bitstream-vera-1.10/VeraSe.ttf -------------------------------------------------------------------------------- /examples/ttf-bitstream-vera-1.10/VeraSeBd.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stetre/moonchipmunk/0e93b019d43041d5c12c6edb5b2bcfcc39c0155a/examples/ttf-bitstream-vera-1.10/VeraSeBd.ttf -------------------------------------------------------------------------------- /examples/ttf-bitstream-vera-1.10/local.conf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 13 | 14 | 15 | serif 16 | 17 | Bitstream Vera Serif 18 | 19 | 20 | 21 | sans-serif 22 | 23 | Bitstream Vera Sans 24 | 25 | 26 | 27 | monospace 28 | 29 | Bitstream Vera Sans Mono 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /examples/version.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | -- MoonChipmunk example: version.lua 3 | local cp = require("moonchipmunk") 4 | 5 | print(cp._VERSION) 6 | print(cp._CHIPMUNK_VERSION) 7 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | 2 | ifdef MINGW_PREFIX 3 | MINGW=1 4 | else 5 | LINUX=1 6 | endif 7 | 8 | # Lua version 9 | LUAVER?=$(shell lua -e 'print(string.match(_VERSION, "%d+%.%d+") or "5.3")') 10 | ifeq ($(LUAVER),) 11 | # lua-interpreter not found 12 | LUAVER=5.3 13 | endif 14 | 15 | # Base install directory 16 | ifdef LINUX 17 | PREFIX?=/usr/local 18 | endif 19 | ifdef MINGW 20 | PREFIX?=$(MINGW_PREFIX) 21 | endif 22 | 23 | # Directory where to install Lua modules 24 | L_DIR=$(PREFIX)/share/lua/$(LUAVER) 25 | # Directory where to install Lua C modules 26 | C_DIR=$(PREFIX)/lib/lua/$(LUAVER) 27 | # Directory where to install C headers 28 | H_DIR=$(PREFIX)/include 29 | # Directory where to install C libraries 30 | S_DIR=$(PREFIX)/lib 31 | 32 | ifeq ($(D),1) 33 | DEBUG=1 34 | endif 35 | 36 | ifdef LINUX 37 | LIBS = -lchipmunk -lpthread 38 | endif 39 | ifdef MINGW 40 | LIBS = -lchipmunk -llua 41 | endif 42 | 43 | Tgt := moonchipmunk 44 | Src := $(wildcard *.c) 45 | Objs := $(Src:.c=.o) 46 | 47 | INCDIR = -I. -I/usr/include/lua$(LUAVER) 48 | 49 | COPT += -O2 50 | #COPT += -O0 -g 51 | #COPT += -m32 52 | COPT += -Wfatal-errors 53 | COPT += -Wall -Wextra -Wpedantic 54 | COPT += -DCOMPAT53_PREFIX=moonchipmunk_compat_ 55 | COPT += -std=gnu99 56 | COPT += -DLUAVER=$(LUAVER) 57 | ifdef LINUX 58 | COPT += -fpic 59 | COPT += -DLINUX 60 | endif 61 | ifdef MINGW 62 | COPT += -DMINGW 63 | endif 64 | ifdef DEBUG 65 | COPT += -DDEBUG 66 | COPT += -Wshadow -Wsign-compare -Wundef -Wwrite-strings 67 | COPT += -Wdisabled-optimization -Wdeclaration-after-statement 68 | COPT += -Wmissing-prototypes -Wstrict-prototypes -Wnested-externs 69 | COPT += -Wold-style-definition 70 | #COPT += -Wc++-compat 71 | endif 72 | 73 | override CFLAGS = $(COPT) $(INCDIR) 74 | 75 | default: build 76 | 77 | where: 78 | @echo "PREFIX="$(PREFIX) 79 | @echo "LUAVER="$(LUAVER) 80 | @echo $(L_DIR) 81 | @echo $(C_DIR) 82 | @echo $(H_DIR) 83 | @echo $(S_DIR) 84 | 85 | clean: 86 | @-rm -f *.so *.dll *.o *.err *.map *.S *~ *.log 87 | @-rm -f $(Tgt).symbols 88 | 89 | install: 90 | @-mkdir -pv $(H_DIR) 91 | @-mkdir -pv $(C_DIR) 92 | @-mkdir -pv $(S_DIR) 93 | @-mkdir -pv $(L_DIR) 94 | @-cp -fpv $(Tgt).h $(H_DIR) 95 | @-cp -fpvr ../$(Tgt) $(L_DIR) 96 | ifdef LINUX 97 | @-cp -fpv $(Tgt).so $(C_DIR) 98 | @-ln -fsv $(C_DIR)/$(Tgt).so $(S_DIR)/lib$(Tgt).so 99 | endif 100 | ifdef MINGW 101 | @-cp -fpv $(Tgt).dll $(C_DIR) 102 | endif 103 | 104 | uninstall: 105 | @-rm -f $(H_DIR)/$(Tgt).h 106 | @-rm -f $(C_DIR)/$(Tgt).so 107 | @-rm -f $(S_DIR)/lib$(Tgt).so 108 | @-rm -fr $(L_DIR)/$(Tgt) 109 | @-rm -f $(C_DIR)/$(Tgt).dll 110 | 111 | build: clean $(Tgt) 112 | 113 | symbols: build 114 | @objdump -T $(Tgt).so > $(Tgt).symbols 115 | 116 | $(Tgt): $(Objs) 117 | ifdef LINUX 118 | @$(CXX) -shared -o $(Tgt).so $(Objs) $(LIBDIR) $(LIBS) 119 | endif 120 | ifdef MINGW 121 | @-$(CXX) -shared -o $(Tgt).dll $(Objs) $(LIBDIR) $(LIBS) 122 | endif 123 | @-rm -f $(Objs) 124 | @echo 125 | 126 | -------------------------------------------------------------------------------- /src/_make: -------------------------------------------------------------------------------- 1 | sudo make LUAVER=5.4 uninstall && make LUAVER=5.4 D=$1 && sudo make LUAVER=5.4 install 2 | -------------------------------------------------------------------------------- /src/circle.c: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2020 Stefano Trettel 4 | * 5 | * Software repository: MoonChipmunk, https://github.com/stetre/moonchipmunk 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include "internal.h" 27 | 28 | static int freecircle(lua_State *L, ud_t *ud) 29 | { 30 | shape_t *shape = (shape_t*)ud->handle; 31 | if(!candestroyshape(shape, ud)) return 0; 32 | if(!freeuserdata(L, ud, "circle")) return 0; 33 | shapedestroy(L, (shape_t*)shape); 34 | return 0; 35 | } 36 | 37 | static int newcircle(lua_State *L, shape_t *circle) 38 | { 39 | ud_t *ud; 40 | ud = newuserdata(L, circle, CIRCLE_MT, "circle"); 41 | ud->parent_ud = NULL; 42 | ud->destructor = freecircle; 43 | return 1; 44 | } 45 | 46 | static int Create(lua_State *L) 47 | { 48 | shape_t *circle; 49 | vec_t offset; 50 | body_t *body = checkbody(L, 1, NULL); 51 | double radius = luaL_checknumber(L, 2); 52 | offset.x = offset.y = 0.0; 53 | optvec(L, 3, &offset); 54 | circle = cpCircleShapeNew(body, radius, offset); 55 | return newcircle(L, circle); 56 | } 57 | 58 | static int GetOffset(lua_State *L) 59 | { 60 | shape_t *circle = checkcircle(L, 1, NULL); 61 | vec_t offset = cpCircleShapeGetOffset(circle); 62 | pushvec(L, &offset); 63 | return 1; 64 | } 65 | 66 | static int SetOffset(lua_State *L) 67 | { 68 | vec_t offset; 69 | shape_t *circle = checkcircle(L, 1, NULL); 70 | checkvec(L, 2, &offset); 71 | cpCircleShapeSetOffset(circle, offset); 72 | return 0; 73 | } 74 | 75 | static int GetRadius(lua_State *L) 76 | { 77 | shape_t *circle = checkcircle(L, 1, NULL); 78 | double radius = cpCircleShapeGetRadius(circle); 79 | lua_pushnumber(L, radius); 80 | return 1; 81 | } 82 | 83 | static int SetRadius(lua_State *L) 84 | { 85 | shape_t *circle = checkcircle(L, 1, NULL); 86 | double radius = luaL_checknumber(L, 2); 87 | cpCircleShapeSetRadius(circle, radius); 88 | return 0; 89 | } 90 | 91 | 92 | DESTROY_FUNC(circle) 93 | 94 | static const struct luaL_Reg Methods[] = 95 | { 96 | { "free", Destroy }, 97 | { "get_offset", GetOffset }, 98 | { "get_radius", GetRadius }, 99 | { "set_offset", SetOffset }, /* chipmunk_unsafe.h */ 100 | { "set_radius", SetRadius }, /* chipmunk_unsafe.h */ 101 | { NULL, NULL } /* sentinel */ 102 | }; 103 | 104 | static const struct luaL_Reg MetaMethods[] = 105 | { 106 | { "__gc", Destroy }, 107 | { NULL, NULL } /* sentinel */ 108 | }; 109 | 110 | static const struct luaL_Reg Functions[] = 111 | { 112 | { "circle_shape_new", Create }, 113 | { NULL, NULL } /* sentinel */ 114 | }; 115 | 116 | void moonchipmunk_open_circle(lua_State *L) 117 | { 118 | udata_define(L, CIRCLE_MT, Methods, MetaMethods); 119 | udata_inherit(L, CIRCLE_MT, SHAPE_MT); 120 | luaL_setfuncs(L, Functions, 0); 121 | } 122 | 123 | -------------------------------------------------------------------------------- /src/collision_handler.c: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2020 Stefano Trettel 4 | * 5 | * Software repository: MoonChipmunk, https://github.com/stetre/moonchipmunk 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include "internal.h" 27 | 28 | static int freecollision_handler(lua_State *L, ud_t *ud) 29 | { 30 | //collision_handler_t *handler = (collision_handler_t*)ud->handle; 31 | if(!freeuserdata(L, ud, "collision_handler")) return 0; 32 | return 0; 33 | } 34 | 35 | int newcollision_handler(lua_State *L, collision_handler_t *handler, space_t *space) 36 | { 37 | ud_t *ud; 38 | if(userdata(handler)) /* already in */ 39 | return pushcollision_handler(L, handler); 40 | ud = newuserdata(L, handler, COLLISION_HANDLER_MT, "collision_handler"); 41 | ud->parent_ud = userdata(space); 42 | ud->destructor = freecollision_handler; 43 | handler->userData = ud; 44 | return 1; 45 | } 46 | 47 | static int GetTypes(lua_State *L) 48 | { 49 | collision_handler_t *handler = checkcollision_handler(L, 1, NULL); 50 | lua_pushinteger(L, handler->typeA); 51 | lua_pushinteger(L, handler->typeB); 52 | return 2; 53 | } 54 | 55 | static cpBool BeginFunc(cpArbiter *arbiter, space_t *space, cpDataPointer userData) 56 | { 57 | int rc; 58 | cpBool res; 59 | lua_State *L = moonchipmunk_L; 60 | ud_t *ud = (ud_t*)userData; 61 | int top = lua_gettop(L); 62 | lua_rawgeti(L, LUA_REGISTRYINDEX, ud->ref1); 63 | pusharbiter(L, arbiter); 64 | pushspace(L, space); 65 | rc = lua_pcall(L, 2, 1, 0); 66 | invalidatearbiter(L, arbiter); 67 | if(rc != LUA_OK) { lua_error(L); return 0; } 68 | res = lua_toboolean(L, -1); 69 | lua_settop(L, top); 70 | return res; 71 | } 72 | 73 | static cpBool PreSolveFunc(cpArbiter *arbiter, space_t *space, cpDataPointer userData) 74 | { 75 | int rc; 76 | cpBool res; 77 | lua_State *L = moonchipmunk_L; 78 | ud_t *ud = (ud_t*)userData; 79 | int top = lua_gettop(L); 80 | lua_rawgeti(L, LUA_REGISTRYINDEX, ud->ref2); 81 | pusharbiter(L, arbiter); 82 | pushspace(L, space); 83 | rc = lua_pcall(L, 2, 1, 0); 84 | invalidatearbiter(L, arbiter); 85 | if(rc != LUA_OK) { lua_error(L); return 0; } 86 | res = lua_toboolean(L, -1); 87 | lua_settop(L, top); 88 | return res; 89 | } 90 | 91 | static void PostSolveFunc(cpArbiter *arbiter, space_t *space, cpDataPointer userData) 92 | { 93 | int rc; 94 | lua_State *L = moonchipmunk_L; 95 | ud_t *ud = (ud_t*)userData; 96 | int top = lua_gettop(L); 97 | lua_rawgeti(L, LUA_REGISTRYINDEX, ud->ref3); 98 | pusharbiter(L, arbiter); 99 | pushspace(L, space); 100 | rc = lua_pcall(L, 2, 0, 0); 101 | invalidatearbiter(L, arbiter); 102 | if(rc != LUA_OK) { lua_error(L); return; } 103 | lua_settop(L, top); 104 | return; 105 | } 106 | 107 | static void SeparateFunc(cpArbiter *arbiter, space_t *space, cpDataPointer userData) 108 | { 109 | int rc; 110 | lua_State *L = moonchipmunk_L; 111 | ud_t *ud = (ud_t*)userData; 112 | int top = lua_gettop(L); 113 | lua_rawgeti(L, LUA_REGISTRYINDEX, ud->ref4); 114 | pusharbiter(L, arbiter); 115 | pushspace(L, space); 116 | rc = lua_pcall(L, 2, 0, 0); 117 | invalidatearbiter(L, arbiter); 118 | if(rc != LUA_OK) 119 | { lua_error(L); return; } 120 | lua_settop(L, top); 121 | return; 122 | } 123 | 124 | static int SetBeginFunc(lua_State *L) 125 | { 126 | ud_t *ud; 127 | collision_handler_t *handler = checkcollision_handler(L, 1, &ud); 128 | if(!lua_isfunction(L, 2)) return argerror(L, 2, ERR_FUNCTION); 129 | Reference(L, 2, ud->ref1); 130 | handler->beginFunc = BeginFunc; 131 | return 0; 132 | } 133 | 134 | static int SetPreSolveFunc(lua_State *L) 135 | { 136 | ud_t *ud; 137 | collision_handler_t *handler = checkcollision_handler(L, 1, &ud); 138 | if(!lua_isfunction(L, 2)) return argerror(L, 2, ERR_FUNCTION); 139 | Reference(L, 2, ud->ref2); 140 | handler->preSolveFunc = PreSolveFunc; 141 | return 0; 142 | } 143 | 144 | static int SetPostSolveFunc(lua_State *L) 145 | { 146 | ud_t *ud; 147 | collision_handler_t *handler = checkcollision_handler(L, 1, &ud); 148 | if(!lua_isfunction(L, 2)) return argerror(L, 2, ERR_FUNCTION); 149 | Reference(L, 2, ud->ref3); 150 | handler->postSolveFunc = PostSolveFunc; 151 | return 0; 152 | } 153 | 154 | static int SetSeparateFunc(lua_State *L) 155 | { 156 | ud_t *ud; 157 | collision_handler_t *handler = checkcollision_handler(L, 1, &ud); 158 | if(!lua_isfunction(L, 2)) return argerror(L, 2, ERR_FUNCTION); 159 | Reference(L, 2, ud->ref4); 160 | handler->separateFunc = SeparateFunc; 161 | return 0; 162 | } 163 | 164 | 165 | RAW_FUNC(collision_handler) 166 | PARENT_FUNC(collision_handler) 167 | DESTROY_FUNC(collision_handler) 168 | 169 | static const struct luaL_Reg Methods[] = 170 | { 171 | { "raw", Raw }, 172 | { "parent", Parent }, 173 | { "free", Destroy }, 174 | { "get_types", GetTypes }, 175 | { "set_begin_func", SetBeginFunc }, 176 | { "set_pre_solve_func", SetPreSolveFunc }, 177 | { "set_post_solve_func", SetPostSolveFunc }, 178 | { "set_separate_func", SetSeparateFunc }, 179 | { NULL, NULL } /* sentinel */ 180 | }; 181 | 182 | static const struct luaL_Reg MetaMethods[] = 183 | { 184 | { "__gc", Destroy }, 185 | { NULL, NULL } /* sentinel */ 186 | }; 187 | 188 | static const struct luaL_Reg Functions[] = 189 | { 190 | { NULL, NULL } /* sentinel */ 191 | }; 192 | 193 | 194 | void moonchipmunk_open_collision_handler(lua_State *L) 195 | { 196 | udata_define(L, COLLISION_HANDLER_MT, Methods, MetaMethods); 197 | luaL_setfuncs(L, Functions, 0); 198 | } 199 | 200 | -------------------------------------------------------------------------------- /src/constraint.h: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2020 Stefano Trettel 4 | * 5 | * Software repository: MoonChipmunk, https://github.com/stetre/moonchipmunk 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef constraintDEFINED 27 | #define constraintDEFINED 28 | 29 | /* Common functions for constraints */ 30 | 31 | #define SETDOUBLE(Func, func, what) /* void func(what, double) */ \ 32 | static int Func(lua_State *L) \ 33 | { \ 34 | constraint_t *constraint = check##what(L, 1, NULL); \ 35 | double val = luaL_checknumber(L, 2); \ 36 | func(constraint, val); \ 37 | return 0; \ 38 | } 39 | 40 | #define SETBOOLEAN(Func, func, what) /* void func(what, bool) */ \ 41 | static int Func(lua_State *L) \ 42 | { \ 43 | constraint_t *constraint = check##what(L, 1, NULL); \ 44 | int val = checkboolean(L, 2); \ 45 | func(constraint, val); \ 46 | return 0; \ 47 | } 48 | 49 | #define SETVEC(Func, func, what) /* void func(what, vec_t) */ \ 50 | static int Func(lua_State *L) \ 51 | { \ 52 | vec_t val; \ 53 | constraint_t *constraint = check##what(L, 1, NULL); \ 54 | checkvec(L, 2, &val); \ 55 | func(constraint, val); \ 56 | return 0; \ 57 | } 58 | 59 | #define GETDOUBLE(Func, func, what) /* double func(what) */ \ 60 | static int Func(lua_State *L) \ 61 | { \ 62 | constraint_t *constraint = check##what(L, 1, NULL); \ 63 | double val = func(constraint); \ 64 | lua_pushnumber(L, val); \ 65 | return 1; \ 66 | } 67 | 68 | #define GETBOOLEAN(Func, func, what) /* bool func(what) */ \ 69 | static int Func(lua_State *L) \ 70 | { \ 71 | constraint_t *constraint = check##what(L, 1, NULL); \ 72 | int val = func(constraint); \ 73 | lua_pushboolean(L, val); \ 74 | return 1; \ 75 | } 76 | 77 | #define GETVEC(Func, func, what) /* vec_t func(what) */ \ 78 | static int Func(lua_State *L) \ 79 | { \ 80 | constraint_t *constraint = check##what(L, 1, NULL); \ 81 | vec_t val = func(constraint); \ 82 | pushvec(L, &val); \ 83 | return 1; \ 84 | } 85 | 86 | #endif /* constraintDEFINED */ 87 | -------------------------------------------------------------------------------- /src/damped_rotary_spring.c: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2020 Stefano Trettel 4 | * 5 | * Software repository: MoonChipmunk, https://github.com/stetre/moonchipmunk 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include "internal.h" 27 | #include "constraint.h" 28 | 29 | static int freedamped_rotary_spring(lua_State *L, ud_t *ud) 30 | { 31 | constraint_t *constraint = (constraint_t*)ud->handle; 32 | if(!candestroyconstraint(constraint, ud)) return 0; 33 | if(!freeuserdata(L, ud, "damped_rotary_spring")) return 0; 34 | constraintdestroy(L, constraint); 35 | return 0; 36 | } 37 | 38 | static int newdamped_rotary_spring(lua_State *L, constraint_t *constraint) 39 | { 40 | ud_t *ud; 41 | ud = newuserdata(L, constraint, DAMPED_ROTARY_SPRING_MT, "damped_rotary_spring"); 42 | ud->parent_ud = NULL; 43 | ud->destructor = freedamped_rotary_spring; 44 | return 1; 45 | } 46 | 47 | static int Create(lua_State *L) 48 | { 49 | body_t *a = checkbody(L, 1, NULL); 50 | body_t *b = checkbody(L, 2, NULL); 51 | double restAngle = luaL_checknumber(L, 3); 52 | double stiffness = luaL_checknumber(L, 4); 53 | double damping = luaL_checknumber(L, 5); 54 | constraint_t *constraint = cpDampedRotarySpringNew(a, b, restAngle, stiffness, damping); 55 | return newdamped_rotary_spring(L, constraint); 56 | } 57 | 58 | SETDOUBLE(SetRestAngle, cpDampedRotarySpringSetRestAngle, damped_rotary_spring) 59 | SETDOUBLE(SetStiffness, cpDampedRotarySpringSetStiffness, damped_rotary_spring) 60 | SETDOUBLE(SetDamping, cpDampedRotarySpringSetDamping, damped_rotary_spring) 61 | GETDOUBLE(GetRestAngle, cpDampedRotarySpringGetRestAngle, damped_rotary_spring) 62 | GETDOUBLE(GetStiffness, cpDampedRotarySpringGetStiffness, damped_rotary_spring) 63 | GETDOUBLE(GetDamping, cpDampedRotarySpringGetDamping, damped_rotary_spring) 64 | 65 | static double TorqueCallback(struct constraint_t *constraint, double relativeAngle) /* ud->ref3 */ 66 | { 67 | #define L moonchipmunk_L 68 | double result; 69 | int top = lua_gettop(L); 70 | ud_t *ud = userdata(constraint); 71 | if(!ud) { unexpected(L); return 0.0f; } 72 | lua_rawgeti(L, LUA_REGISTRYINDEX, ud->ref3); 73 | pushconstraint(L, constraint); 74 | lua_pushnumber(L, relativeAngle); 75 | if(lua_pcall(L, 2, 1, 0) != LUA_OK) 76 | { lua_error(L); return 0.0f; } 77 | result = luaL_checknumber(L, -1); 78 | lua_settop(L, top); 79 | return result; 80 | #undef L 81 | } 82 | 83 | static int SetTorqueFunc(lua_State *L) 84 | { 85 | ud_t *ud; 86 | constraint_t *constraint = checkdamped_rotary_spring(L, 1, &ud); 87 | if(lua_isnoneornil(L, 2)) /* remove callback */ 88 | { 89 | if(ud->ref3!=LUA_NOREF) 90 | { cpDampedRotarySpringSetSpringTorqueFunc(constraint, NULL); Unreference(L, ud->ref3); } 91 | return 0; 92 | } 93 | if(!lua_isfunction(L, 2)) 94 | return argerror(L, 2, ERR_FUNCTION); 95 | Reference(L, 2, ud->ref3); 96 | cpDampedRotarySpringSetSpringTorqueFunc(constraint, TorqueCallback); 97 | return 0; 98 | } 99 | 100 | static int GetTorqueFunc(lua_State *L) 101 | { 102 | ud_t *ud; 103 | (void)checkdamped_rotary_spring(L, 1, &ud); 104 | lua_rawgeti(L, LUA_REGISTRYINDEX, ud->ref3); 105 | return 1; 106 | } 107 | 108 | DESTROY_FUNC(damped_rotary_spring) 109 | 110 | static const struct luaL_Reg Methods[] = 111 | { 112 | { "free", Destroy }, 113 | { "set_rest_angle", SetRestAngle }, 114 | { "set_stiffness", SetStiffness }, 115 | { "set_damping", SetDamping }, 116 | { "get_rest_angle", GetRestAngle }, 117 | { "get_stiffness", GetStiffness }, 118 | { "get_damping", GetDamping }, 119 | { "set_spring_torque_func", SetTorqueFunc }, 120 | { "get_spring_torque_func", GetTorqueFunc }, 121 | { NULL, NULL } /* sentinel */ 122 | }; 123 | 124 | static const struct luaL_Reg MetaMethods[] = 125 | { 126 | { "__gc", Destroy }, 127 | { NULL, NULL } /* sentinel */ 128 | }; 129 | 130 | static const struct luaL_Reg Functions[] = 131 | { 132 | { "damped_rotary_spring_new", Create }, 133 | { NULL, NULL } /* sentinel */ 134 | }; 135 | 136 | void moonchipmunk_open_damped_rotary_spring(lua_State *L) 137 | { 138 | udata_define(L, DAMPED_ROTARY_SPRING_MT, Methods, MetaMethods); 139 | udata_inherit(L, DAMPED_ROTARY_SPRING_MT, CONSTRAINT_MT); 140 | luaL_setfuncs(L, Functions, 0); 141 | } 142 | 143 | -------------------------------------------------------------------------------- /src/damped_spring.c: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2020 Stefano Trettel 4 | * 5 | * Software repository: MoonChipmunk, https://github.com/stetre/moonchipmunk 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include "internal.h" 27 | #include "constraint.h" 28 | 29 | static int freedamped_spring(lua_State *L, ud_t *ud) 30 | { 31 | constraint_t *constraint = (constraint_t*)ud->handle; 32 | if(!candestroyconstraint(constraint, ud)) return 0; 33 | if(!freeuserdata(L, ud, "damped_spring")) return 0; 34 | constraintdestroy(L, constraint); 35 | return 0; 36 | } 37 | 38 | static int newdamped_spring(lua_State *L, constraint_t *constraint) 39 | { 40 | ud_t *ud; 41 | ud = newuserdata(L, constraint, DAMPED_SPRING_MT, "damped_spring"); 42 | ud->parent_ud = NULL; 43 | ud->destructor = freedamped_spring; 44 | return 1; 45 | } 46 | 47 | static int Create(lua_State *L) 48 | { 49 | vec_t anchorA, anchorB; 50 | double restLength, stiffness, damping; 51 | constraint_t *constraint; 52 | body_t *a = checkbody(L, 1, NULL); 53 | body_t *b = checkbody(L, 2, NULL); 54 | checkvec(L, 3, &anchorA); 55 | checkvec(L, 4, &anchorB); 56 | restLength = luaL_checknumber(L, 5); 57 | stiffness = luaL_checknumber(L, 6); 58 | damping = luaL_checknumber(L, 7); 59 | constraint = cpDampedSpringNew(a, b, anchorA, anchorB, restLength, stiffness, damping); 60 | return newdamped_spring(L, constraint); 61 | } 62 | 63 | SETVEC(SetAnchorA, cpDampedSpringSetAnchorA, damped_spring) 64 | SETVEC(SetAnchorB, cpDampedSpringSetAnchorB, damped_spring) 65 | GETVEC(GetAnchorA, cpDampedSpringGetAnchorA, damped_spring) 66 | GETVEC(GetAnchorB, cpDampedSpringGetAnchorB, damped_spring) 67 | SETDOUBLE(SetRestLength, cpDampedSpringSetRestLength, damped_spring) 68 | SETDOUBLE(SetStiffness, cpDampedSpringSetStiffness, damped_spring) 69 | SETDOUBLE(SetDamping, cpDampedSpringSetDamping, damped_spring) 70 | GETDOUBLE(GetRestLength, cpDampedSpringGetRestLength, damped_spring) 71 | GETDOUBLE(GetStiffness, cpDampedSpringGetStiffness, damped_spring) 72 | GETDOUBLE(GetDamping, cpDampedSpringGetDamping, damped_spring) 73 | 74 | static double ForceCallback(constraint_t *constraint, double dist) /* ud->ref3 */ 75 | { 76 | #define L moonchipmunk_L 77 | double result; 78 | int top = lua_gettop(L); 79 | ud_t *ud = userdata(constraint); 80 | if(!ud) { unexpected(L); return 0.0f; } 81 | lua_rawgeti(L, LUA_REGISTRYINDEX, ud->ref3); 82 | pushconstraint(L, constraint); 83 | lua_pushnumber(L, dist); 84 | if(lua_pcall(L, 2, 1, 0) != LUA_OK) 85 | { lua_error(L); return 0.0f; } 86 | result = luaL_checknumber(L, -1); 87 | lua_settop(L, top); 88 | return result; 89 | #undef L 90 | } 91 | 92 | static int SetSpringForceFunc(lua_State *L) 93 | { 94 | ud_t *ud; 95 | constraint_t *constraint = checkdamped_spring(L, 1, &ud); 96 | if(lua_isnoneornil(L, 2)) /* remove callback */ 97 | { 98 | if(ud->ref3!=LUA_NOREF) 99 | { cpDampedSpringSetSpringForceFunc(constraint, NULL); Unreference(L, ud->ref3); } 100 | return 0; 101 | } 102 | if(!lua_isfunction(L, 2)) 103 | return argerror(L, 2, ERR_FUNCTION); 104 | Reference(L, 2, ud->ref3); 105 | cpDampedSpringSetSpringForceFunc(constraint, ForceCallback); 106 | return 0; 107 | } 108 | 109 | static int GetSpringForceFunc(lua_State *L) 110 | { 111 | ud_t *ud; 112 | (void)checkdamped_spring(L, 1, &ud); 113 | lua_rawgeti(L, LUA_REGISTRYINDEX, ud->ref3); 114 | return 1; 115 | } 116 | 117 | DESTROY_FUNC(damped_spring) 118 | 119 | static const struct luaL_Reg Methods[] = 120 | { 121 | { "free", Destroy }, 122 | { "set_anchor_a", SetAnchorA }, 123 | { "set_anchor_b", SetAnchorB }, 124 | { "get_anchor_a", GetAnchorA }, 125 | { "get_anchor_b", GetAnchorB }, 126 | { "set_rest_length", SetRestLength }, 127 | { "set_stiffness", SetStiffness }, 128 | { "set_damping", SetDamping }, 129 | { "get_rest_length", GetRestLength }, 130 | { "get_stiffness", GetStiffness }, 131 | { "get_damping", GetDamping }, 132 | { "set_spring_force_func", SetSpringForceFunc }, 133 | { "get_spring_force_func", GetSpringForceFunc }, 134 | { NULL, NULL } /* sentinel */ 135 | }; 136 | 137 | static const struct luaL_Reg MetaMethods[] = 138 | { 139 | { "__gc", Destroy }, 140 | { NULL, NULL } /* sentinel */ 141 | }; 142 | 143 | static const struct luaL_Reg Functions[] = 144 | { 145 | { "damped_spring_new", Create }, 146 | { NULL, NULL } /* sentinel */ 147 | }; 148 | 149 | void moonchipmunk_open_damped_spring(lua_State *L) 150 | { 151 | udata_define(L, DAMPED_SPRING_MT, Methods, MetaMethods); 152 | udata_inherit(L, DAMPED_SPRING_MT, CONSTRAINT_MT); 153 | luaL_setfuncs(L, Functions, 0); 154 | } 155 | 156 | -------------------------------------------------------------------------------- /src/enums.h: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2020 Stefano Trettel 4 | * 5 | * Software repository: MoonChipmunk, https://github.com/stetre/moonchipmunk 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef enumsDEFINED 27 | #define enumsDEFINED 28 | 29 | /* enums.c */ 30 | #define enums_free_all moonchipmunk_enums_free_all 31 | void enums_free_all(lua_State *L); 32 | #define enums_test moonchipmunk_enums_test 33 | int enums_test(lua_State *L, int domain, int arg, int *err); 34 | #define enums_opt moonchipmunk_enums_opt 35 | int enums_opt(lua_State *L, int domain, int arg, int defval); 36 | #define enums_check moonchipmunk_enums_check 37 | int enums_check(lua_State *L, int domain, int arg); 38 | #define enums_push moonchipmunk_enums_push 39 | int enums_push(lua_State *L, int domain, int code); 40 | #define enums_values moonchipmunk_enums_values 41 | int enums_values(lua_State *L, int domain); 42 | #define enums_checklist moonchipmunk_enums_checklist 43 | int* enums_checklist(lua_State *L, int domain, int arg, int *count, int *err); 44 | #define enums_freelist moonchipmunk_enums_freelist 45 | void enums_freelist(lua_State *L, int *list); 46 | 47 | 48 | /* Enum domains */ 49 | #define DOMAIN_ 0 50 | #define DOMAIN_BODY_TYPE 1 51 | 52 | #define testbodytype(L, arg, err) enums_test((L), DOMAIN_BODY_TYPE, (arg), (err)) 53 | #define optbodytype(L, arg, defval) enums_opt((L), DOMAIN_BODY_TYPE, (arg), (defval)) 54 | #define checkbodytype(L, arg) enums_check((L), DOMAIN_BODY_TYPE, (arg)) 55 | #define pushbodytype(L, val) enums_push((L), DOMAIN_BODY_TYPE, (int)(val)) 56 | #define valuesbodytype(L) enums_values((L), DOMAIN_BODY_TYPE) 57 | 58 | #if 0 /* scaffolding 7yy */ 59 | #define testxxx(L, arg, err) enums_test((L), DOMAIN_XXX, (arg), (err)) 60 | #define optxxx(L, arg, defval) enums_opt((L), DOMAIN_XXX, (arg), (defval)) 61 | #define checkxxx(L, arg) enums_check((L), DOMAIN_XXX, (arg)) 62 | #define pushxxx(L, val) enums_push((L), DOMAIN_XXX, (int)(val)) 63 | #define valuesxxx(L) enums_values((L), DOMAIN_XXX) 64 | CASE(xxx); 65 | 66 | #endif 67 | 68 | #endif /* enumsDEFINED */ 69 | 70 | 71 | -------------------------------------------------------------------------------- /src/flags.c: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2020 Stefano Trettel 4 | * 5 | * Software repository: MoonChipmunk, https://github.com/stetre/moonchipmunk 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include "internal.h" 27 | 28 | #define ADD(c) do { lua_pushinteger(L, CP_##c); lua_setfield(L, -2, #c); } while(0) 29 | 30 | /* checkkkflags: accepts a list of strings starting from index=arg 31 | * pushxxxflags -> pushes a list of strings 32 | */ 33 | 34 | /*----------------------------------------------------------------------* 35 | | cpSpaceDebugDrawFlags 36 | *----------------------------------------------------------------------*/ 37 | 38 | static int checkdebugdrawflags(lua_State *L, int arg) 39 | { 40 | const char *s; 41 | int flags = 0; 42 | 43 | while(lua_isstring(L, arg)) 44 | { 45 | s = lua_tostring(L, arg++); 46 | #define CASE(CODE,str) if((strcmp(s, str)==0)) do { flags |= CODE; goto done; } while(0) 47 | CASE(CP_SPACE_DEBUG_DRAW_SHAPES, "shapes"); 48 | CASE(CP_SPACE_DEBUG_DRAW_CONSTRAINTS, "constraints"); 49 | CASE(CP_SPACE_DEBUG_DRAW_COLLISION_POINTS, "points"); 50 | #undef CASE 51 | return luaL_argerror(L, --arg, badvalue(L,s)); 52 | done: ; 53 | } 54 | 55 | return flags; 56 | } 57 | 58 | static int pushdebugdrawflags(lua_State *L, int flags) 59 | { 60 | int n = 0; 61 | 62 | #define CASE(CODE,str) do { if( flags & CODE) { lua_pushstring(L, str); n++; } } while(0) 63 | CASE(CP_SPACE_DEBUG_DRAW_SHAPES, "shapes"); 64 | CASE(CP_SPACE_DEBUG_DRAW_CONSTRAINTS, "constraints"); 65 | CASE(CP_SPACE_DEBUG_DRAW_COLLISION_POINTS, "points"); 66 | #undef CASE 67 | 68 | return n; 69 | } 70 | 71 | static int DebugDrawFlags(lua_State *L) 72 | { 73 | if(lua_type(L, 1) == LUA_TNUMBER) 74 | return pushdebugdrawflags(L, luaL_checkinteger(L, 1)); 75 | lua_pushinteger(L, checkdebugdrawflags(L, 1)); 76 | return 1; 77 | } 78 | 79 | #define Add_DebugDrawFlags(L) \ 80 | ADD(SPACE_DEBUG_DRAW_SHAPES);\ 81 | ADD(SPACE_DEBUG_DRAW_CONSTRAINTS);\ 82 | ADD(SPACE_DEBUG_DRAW_COLLISION_POINTS);\ 83 | 84 | /*----------------------------------------------------------------------*/ 85 | 86 | static int AddConstants(lua_State *L) /* cp.XXX constants for CP_XXX values */ 87 | { 88 | Add_DebugDrawFlags(L); 89 | return 0; 90 | } 91 | 92 | static const struct luaL_Reg Functions[] = 93 | { 94 | { "debugdrawflags", DebugDrawFlags }, 95 | { NULL, NULL } /* sentinel */ 96 | }; 97 | 98 | 99 | void moonchipmunk_open_flags(lua_State *L) 100 | { 101 | AddConstants(L); 102 | luaL_setfuncs(L, Functions, 0); 103 | } 104 | 105 | 106 | #if 0 // scaffolding 107 | 108 | /*----------------------------------------------------------------------* 109 | | 110 | *----------------------------------------------------------------------*/ 111 | 112 | static int checkzzz(lua_State *L, int arg) 113 | { 114 | const char *s; 115 | int flags = 0; 116 | 117 | while(lua_isstring(L, arg)) 118 | { 119 | s = lua_tostring(L, arg++); 120 | #define CASE(CODE,str) if((strcmp(s, str)==0)) do { flags |= CODE; goto done; } while(0) 121 | CASE(ZZZ_, ""); 122 | #undef CASE 123 | return luaL_argerror(L, --arg, badvalue(L,s)); 124 | done: ; 125 | } 126 | 127 | return flags; 128 | } 129 | 130 | static int pushzzz(lua_State *L, int flags) 131 | { 132 | int n = 0; 133 | 134 | #define CASE(CODE,str) do { if( flags & CODE) { lua_pushstring(L, str); n++; } } while(0) 135 | CASE(ZZZ_, ""); 136 | #undef CASE 137 | 138 | return n; 139 | } 140 | 141 | static int Zzz(lua_State *L) 142 | { 143 | if(lua_type(L, 1) == LUA_TNUMBER) 144 | return pushzzz(L, luaL_checkinteger(L, 1)); 145 | lua_pushinteger(L, checkzzz(L, 1)); 146 | return 1; 147 | } 148 | 149 | Add_Zzz(L); 150 | { "zzz", Zzz }, 151 | #define Add_Zzz(L) \ 152 | ADD(ZZZ_);\ 153 | 154 | #endif 155 | 156 | -------------------------------------------------------------------------------- /src/gear_joint.c: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2020 Stefano Trettel 4 | * 5 | * Software repository: MoonChipmunk, https://github.com/stetre/moonchipmunk 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include "internal.h" 27 | #include "constraint.h" 28 | 29 | static int freegear_joint(lua_State *L, ud_t *ud) 30 | { 31 | constraint_t *constraint = (constraint_t*)ud->handle; 32 | if(!candestroyconstraint(constraint, ud)) return 0; 33 | if(!freeuserdata(L, ud, "gear_joint")) return 0; 34 | constraintdestroy(L, constraint); 35 | return 0; 36 | } 37 | 38 | static int newgear_joint(lua_State *L, constraint_t *constraint) 39 | { 40 | ud_t *ud; 41 | ud = newuserdata(L, constraint, GEAR_JOINT_MT, "gear_joint"); 42 | ud->parent_ud = NULL; 43 | ud->destructor = freegear_joint; 44 | return 1; 45 | } 46 | 47 | static int Create(lua_State *L) 48 | { 49 | body_t *a = checkbody(L, 1, NULL); 50 | body_t *b = checkbody(L, 2, NULL); 51 | double phase = luaL_checknumber(L, 3); 52 | double ratio = luaL_checknumber(L, 4); 53 | constraint_t *constraint = cpGearJointNew(a, b, phase, ratio); 54 | return newgear_joint(L, constraint); 55 | } 56 | 57 | SETDOUBLE(SetPhase, cpGearJointSetPhase, gear_joint) 58 | SETDOUBLE(SetRatio, cpGearJointSetRatio, gear_joint) 59 | GETDOUBLE(GetPhase, cpGearJointGetPhase, gear_joint) 60 | GETDOUBLE(GetRatio, cpGearJointGetRatio, gear_joint) 61 | 62 | DESTROY_FUNC(gear_joint) 63 | 64 | static const struct luaL_Reg Methods[] = 65 | { 66 | { "free", Destroy }, 67 | { "set_phase", SetPhase }, 68 | { "set_ratio", SetRatio }, 69 | { "get_phase", GetPhase }, 70 | { "get_ratio", GetRatio }, 71 | { NULL, NULL } /* sentinel */ 72 | }; 73 | 74 | static const struct luaL_Reg MetaMethods[] = 75 | { 76 | { "__gc", Destroy }, 77 | { NULL, NULL } /* sentinel */ 78 | }; 79 | 80 | static const struct luaL_Reg Functions[] = 81 | { 82 | { "gear_joint_new", Create }, 83 | { NULL, NULL } /* sentinel */ 84 | }; 85 | 86 | void moonchipmunk_open_gear_joint(lua_State *L) 87 | { 88 | udata_define(L, GEAR_JOINT_MT, Methods, MetaMethods); 89 | udata_inherit(L, GEAR_JOINT_MT, CONSTRAINT_MT); 90 | luaL_setfuncs(L, Functions, 0); 91 | } 92 | 93 | -------------------------------------------------------------------------------- /src/groove_joint.c: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2020 Stefano Trettel 4 | * 5 | * Software repository: MoonChipmunk, https://github.com/stetre/moonchipmunk 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include "internal.h" 27 | #include "constraint.h" 28 | 29 | static int freegroove_joint(lua_State *L, ud_t *ud) 30 | { 31 | constraint_t *constraint = (constraint_t*)ud->handle; 32 | if(!candestroyconstraint(constraint, ud)) return 0; 33 | if(!freeuserdata(L, ud, "groove_joint")) return 0; 34 | constraintdestroy(L, constraint); 35 | return 0; 36 | } 37 | 38 | static int newgroove_joint(lua_State *L, constraint_t *constraint) 39 | { 40 | ud_t *ud; 41 | ud = newuserdata(L, constraint, GROOVE_JOINT_MT, "groove_joint"); 42 | ud->parent_ud = NULL; 43 | ud->destructor = freegroove_joint; 44 | return 1; 45 | } 46 | 47 | static int Create(lua_State *L) 48 | { 49 | vec_t grooveA, grooveB, anchorB; 50 | constraint_t *constraint; 51 | body_t *a = checkbody(L, 1, NULL); 52 | body_t *b = checkbody(L, 2, NULL); 53 | checkvec(L, 3, &grooveA); 54 | checkvec(L, 4, &grooveB); 55 | checkvec(L, 5, &anchorB); 56 | constraint = cpGrooveJointNew(a, b, grooveA, grooveB, anchorB); 57 | return newgroove_joint(L, constraint); 58 | } 59 | 60 | SETVEC(SetGrooveA, cpGrooveJointSetGrooveA, groove_joint) 61 | SETVEC(SetGrooveB, cpGrooveJointSetGrooveB, groove_joint) 62 | SETVEC(SetAnchorB, cpGrooveJointSetAnchorB, groove_joint) 63 | GETVEC(GetGrooveA, cpGrooveJointGetGrooveA, groove_joint) 64 | GETVEC(GetGrooveB, cpGrooveJointGetGrooveB, groove_joint) 65 | GETVEC(GetAnchorB, cpGrooveJointGetAnchorB, groove_joint) 66 | 67 | DESTROY_FUNC(groove_joint) 68 | 69 | static const struct luaL_Reg Methods[] = 70 | { 71 | { "free", Destroy }, 72 | { "set_groove_a", SetGrooveA }, 73 | { "set_groove_b", SetGrooveB }, 74 | { "set_anchor_b", SetAnchorB }, 75 | { "get_groove_a", GetGrooveA }, 76 | { "get_groove_b", GetGrooveB }, 77 | { "get_anchor_b", GetAnchorB }, 78 | { NULL, NULL } /* sentinel */ 79 | }; 80 | 81 | static const struct luaL_Reg MetaMethods[] = 82 | { 83 | { "__gc", Destroy }, 84 | { NULL, NULL } /* sentinel */ 85 | }; 86 | 87 | static const struct luaL_Reg Functions[] = 88 | { 89 | { "groove_joint_new", Create }, 90 | { NULL, NULL } /* sentinel */ 91 | }; 92 | 93 | void moonchipmunk_open_groove_joint(lua_State *L) 94 | { 95 | udata_define(L, GROOVE_JOINT_MT, Methods, MetaMethods); 96 | udata_inherit(L, GROOVE_JOINT_MT, CONSTRAINT_MT); 97 | luaL_setfuncs(L, Functions, 0); 98 | } 99 | 100 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2020 Stefano Trettel 4 | * 5 | * Software repository: MoonChipmunk, https://github.com/stetre/moonchipmunk 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include "internal.h" 27 | 28 | lua_State *moonchipmunk_L; 29 | 30 | static void AtExit(void) 31 | { 32 | if(moonchipmunk_L) 33 | { 34 | enums_free_all(moonchipmunk_L); 35 | moonchipmunk_L = NULL; 36 | } 37 | } 38 | 39 | static int AddVersions(lua_State *L) 40 | { 41 | lua_pushstring(L, "_VERSION"); 42 | lua_pushstring(L, "MoonChipmunk "MOONCHIPMUNK_VERSION); 43 | lua_settable(L, -3); 44 | 45 | 46 | lua_pushstring(L, "_CHIPMUNK_VERSION"); 47 | // lua_pushfstring(L, "Chipmunk %d.%d.%d", 48 | // CP_VERSION_MAJOR, CP_VERSION_MINOR, CP_VERSION_RELEASE); 49 | lua_pushfstring(L, "Chipmunk %s", cpVersionString); 50 | lua_settable(L, -3); 51 | 52 | return 0; 53 | } 54 | 55 | static int AddConstants(lua_State *L) 56 | { 57 | lua_pushinteger(L, CP_NO_GROUP); 58 | lua_setfield(L, -2, "NO_GROUP"); 59 | 60 | lua_pushinteger(L, CP_ALL_CATEGORIES); 61 | lua_setfield(L, -2, "ALL_CATEGORIES"); 62 | 63 | lua_pushinteger(L, CP_WILDCARD_COLLISION_TYPE); 64 | lua_setfield(L, -2, "WILDCARD_COLLISION_TYPE"); 65 | return 0; 66 | } 67 | 68 | 69 | 70 | static int IsGlmathCompat(lua_State *L) 71 | { 72 | lua_pushboolean(L, isglmathcompat()); 73 | return 1; 74 | } 75 | 76 | static int GlmathCompat(lua_State *L) 77 | { 78 | int on = checkboolean(L, 1); 79 | glmathcompat(L, on); 80 | return 0; 81 | } 82 | 83 | static const struct luaL_Reg Functions[] = 84 | { 85 | { "is_glmath_compat", IsGlmathCompat }, 86 | { "glmath_compat", GlmathCompat }, 87 | { NULL, NULL } /* sentinel */ 88 | }; 89 | 90 | int luaopen_moonchipmunk(lua_State *L) 91 | /* Lua calls this function to load the module */ 92 | { 93 | moonchipmunk_L = L; 94 | 95 | moonchipmunk_utils_init(L); 96 | atexit(AtExit); 97 | 98 | lua_newtable(L); /* the module table */ 99 | moonchipmunk_open_enums(L); 100 | moonchipmunk_open_flags(L); 101 | AddVersions(L); 102 | AddConstants(L); 103 | luaL_setfuncs(L, Functions, 0); 104 | moonchipmunk_open_tracing(L); 105 | moonchipmunk_open_misc(L); 106 | moonchipmunk_open_space(L); 107 | moonchipmunk_open_body(L); 108 | moonchipmunk_open_shape(L); 109 | moonchipmunk_open_circle(L); 110 | moonchipmunk_open_segment(L); 111 | moonchipmunk_open_poly(L); 112 | moonchipmunk_open_constraint(L); 113 | moonchipmunk_open_pin_joint(L); 114 | moonchipmunk_open_slide_joint(L); 115 | moonchipmunk_open_pivot_joint(L); 116 | moonchipmunk_open_groove_joint(L); 117 | moonchipmunk_open_damped_spring(L); 118 | moonchipmunk_open_damped_rotary_spring(L); 119 | moonchipmunk_open_rotary_limit_joint(L); 120 | moonchipmunk_open_ratchet_joint(L); 121 | moonchipmunk_open_gear_joint(L); 122 | moonchipmunk_open_simple_motor(L); 123 | moonchipmunk_open_arbiter(L); 124 | moonchipmunk_open_collision_handler(L); 125 | 126 | #if 0 //@@ 127 | /* Add functions implemented in Lua */ 128 | lua_pushvalue(L, -1); lua_setglobal(L, "moonchipmunk"); 129 | if(luaL_dostring(L, "require('moonchipmunk.datastructs')") != 0) lua_error(L); 130 | lua_pushnil(L); lua_setglobal(L, "moonchipmunk"); 131 | #endif 132 | 133 | return 1; 134 | } 135 | 136 | -------------------------------------------------------------------------------- /src/moonchipmunk.h: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2020 Stefano Trettel 4 | * 5 | * Software repository: MoonChipmunk, https://github.com/stetre/moonchipmunk 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef moonchipmunkDEFINED 27 | #define moonchipmunkDEFINED 28 | 29 | #include 30 | #include "lualib.h" 31 | #include "lauxlib.h" 32 | #include "compat-5.3.h" 33 | 34 | #undef CP_SPACE_DISABLE_DEBUG_API 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | #define MOONCHIPMUNK_VERSION "0.1" 44 | 45 | #endif /* moonchipmunkDEFINED */ 46 | 47 | -------------------------------------------------------------------------------- /src/objects.c: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2020 Stefano Trettel 4 | * 5 | * Software repository: MoonChipmunk, https://github.com/stetre/moonchipmunk 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include "internal.h" 27 | 28 | ud_t *newuserdata(lua_State *L, void *handle, const char *mt, const char *tracename) 29 | { 30 | ud_t *ud; 31 | /* we use handle as search key */ 32 | ud = (ud_t*)udata_new(L, sizeof(ud_t), (uint64_t)(uintptr_t)handle, mt); 33 | memset(ud, 0, sizeof(ud_t)); 34 | ud->handle = handle; 35 | MarkValid(ud); 36 | if(trace_objects) 37 | printf("create %s %p (%p)\n", tracename, (void*)ud, handle); 38 | return ud; 39 | } 40 | 41 | int freeuserdata(lua_State *L, ud_t *ud, const char *tracename) 42 | { 43 | /* The 'Valid' mark prevents double calls when an object is explicitly destroyed, 44 | * and subsequently deleted also by the GC (the ud sticks around until the GC 45 | * collects it, so we mark it as invalid when the object is explicitly destroyed 46 | * by the script, or implicitly destroyed because child of a destroyed object). */ 47 | if(!IsValid(ud)) return 0; 48 | CancelValid(ud); 49 | if(ud->info) 50 | Free(L, ud->info); 51 | if(ud->ref1!=LUA_NOREF) luaL_unref(L, LUA_REGISTRYINDEX, ud->ref1); 52 | if(ud->ref2!=LUA_NOREF) luaL_unref(L, LUA_REGISTRYINDEX, ud->ref2); 53 | if(ud->ref3!=LUA_NOREF) luaL_unref(L, LUA_REGISTRYINDEX, ud->ref3); 54 | if(trace_objects) 55 | printf("delete %s %p (%p)\n", tracename, (void*)ud, ud->handle); 56 | udata_free(L, (uint64_t)(uintptr_t)ud->handle); 57 | return 1; 58 | } 59 | 60 | static int freeifchild(lua_State *L, const void *mem, const char *mt, const void *parent_ud) 61 | /* callback for udata_scan */ 62 | { 63 | ud_t *ud = (ud_t*)mem; 64 | (void)mt; 65 | if(IsValid(ud) && (ud->parent_ud == parent_ud)) 66 | ud->destructor(L, ud); 67 | return 0; 68 | } 69 | 70 | int freechildren(lua_State *L, const char *mt, ud_t *parent_ud) 71 | /* calls the self destructor for all 'mt' objects that are children of the given parent_ud */ 72 | { 73 | return udata_scan(L, mt, parent_ud, freeifchild); 74 | } 75 | 76 | int pushuserdata(lua_State *L, ud_t *ud) 77 | { 78 | if(!IsValid(ud)) return unexpected(L); 79 | return udata_push(L, (uint64_t)(uintptr_t)ud->handle); 80 | } 81 | 82 | ud_t *userdata(const void *handle) 83 | { 84 | ud_t *ud = (ud_t*)udata_mem((uint64_t)(uintptr_t)handle); 85 | if(ud && IsValid(ud)) return ud; 86 | return NULL; 87 | } 88 | 89 | void *testxxx(lua_State *L, int arg, ud_t **udp, const char *mt) 90 | { 91 | ud_t *ud = (ud_t*)udata_test(L, arg, mt); 92 | if(ud && IsValid(ud)) { if(udp) *udp=ud; return ud->handle; } 93 | if(udp) *udp = NULL; 94 | return 0; 95 | } 96 | 97 | #if 0 98 | void *testoneofxxx(lua_State *L, int arg, ud_t **udp, char **mtp) 99 | { 100 | void *handle = NULL; 101 | int i = 0; 102 | char *mt = NULL; 103 | while((mt = mtp[i++]) != NULL) 104 | { 105 | handle = testxxx(L, arg, udp, mt); 106 | if(handle) return handle; 107 | } 108 | if(udp) *udp = NULL; 109 | return 0; 110 | } 111 | #endif 112 | 113 | 114 | void *checkxxx(lua_State *L, int arg, ud_t **udp, const char *mt) 115 | { 116 | ud_t *ud = (ud_t*)udata_test(L, arg, mt); 117 | if(ud && IsValid(ud)) 118 | { if(udp) *udp = ud; return ud->handle; } 119 | lua_pushfstring(L, "not a %s", mt); 120 | luaL_argerror(L, arg, lua_tostring(L, -1)); 121 | return 0; 122 | } 123 | 124 | void *optxxx(lua_State *L, int arg, ud_t **udp, const char *mt) 125 | /* This differs from testxxx in that it fails in case the argument is 126 | * something different than either none/nil or the expected userdata type 127 | */ 128 | { 129 | if(lua_isnoneornil(L, arg)) 130 | { if(udp) *udp = NULL; return 0; } 131 | return checkxxx(L, arg, udp, mt); 132 | } 133 | 134 | int pushxxx(lua_State *L, void *handle) 135 | { return udata_push(L, (uint64_t)(uintptr_t)handle); } 136 | 137 | 138 | void** checkxxxlist(lua_State *L, int arg, int *count, int *err, const char *mt) 139 | /* xxx* checkxxxlist(lua_State *L, int arg, int *count, int *err) 140 | * Checks if the variable at arg on the Lua stack is a list of xxx objects. 141 | * On success, returns an array of xxx handles and sets its length in *count. 142 | * The array s Malloc'd and must be released by the caller using Free(L, ...). 143 | * On error, sets *err to ERR_XXX, *count to 0, and returns NULL. 144 | */ 145 | { 146 | void** list; 147 | int i; 148 | 149 | *count = 0; 150 | *err = 0; 151 | if(lua_isnoneornil(L, arg)) 152 | { *err = ERR_NOTPRESENT; return NULL; } 153 | if(lua_type(L, arg) != LUA_TTABLE) 154 | { *err = ERR_TABLE; return NULL; } 155 | *count = luaL_len(L, arg); 156 | if(*count == 0) 157 | { *err = ERR_EMPTY; return NULL; } 158 | list = (void**)MallocNoErr(L, sizeof(void*) * (*count)); 159 | 160 | if(!list) 161 | { *count = 0; *err = ERR_MEMORY; return NULL; } 162 | 163 | for(i=0; i<*count; i++) 164 | { 165 | lua_rawgeti(L, arg, i+1); 166 | list[i] = (void*)(uintptr_t)testxxx(L, -1, NULL, mt); 167 | if(!list[i]) 168 | { Free(L, list); *count = 0; *err = ERR_TYPE; return NULL; } 169 | lua_pop(L, 1); 170 | } 171 | return list; 172 | } 173 | 174 | 175 | int setmetatable(lua_State *L, const char *mt) 176 | /* Sets the metatable of the table on top of the stack */ 177 | { 178 | luaL_getmetatable(L, mt); 179 | lua_setmetatable(L, -2); 180 | return 0; 181 | } 182 | 183 | -------------------------------------------------------------------------------- /src/pin_joint.c: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2020 Stefano Trettel 4 | * 5 | * Software repository: MoonChipmunk, https://github.com/stetre/moonchipmunk 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include "internal.h" 27 | #include "constraint.h" 28 | 29 | static int freepin_joint(lua_State *L, ud_t *ud) 30 | { 31 | constraint_t *constraint = (constraint_t*)ud->handle; 32 | if(!candestroyconstraint(constraint, ud)) return 0; 33 | if(!freeuserdata(L, ud, "pin_joint")) return 0; 34 | constraintdestroy(L, constraint); 35 | return 0; 36 | } 37 | 38 | static int newpin_joint(lua_State *L, constraint_t *constraint) 39 | { 40 | ud_t *ud; 41 | ud = newuserdata(L, constraint, PIN_JOINT_MT, "pin_joint"); 42 | ud->parent_ud = NULL; 43 | ud->destructor = freepin_joint; 44 | return 1; 45 | } 46 | 47 | static int Create(lua_State *L) 48 | { 49 | vec_t anchorA, anchorB; 50 | constraint_t *constraint; 51 | body_t *a = checkbody(L, 1, NULL); 52 | body_t *b = checkbody(L, 2, NULL); 53 | checkvec(L, 3, &anchorA); 54 | checkvec(L, 4, &anchorB); 55 | constraint = cpPinJointNew(a, b, anchorA, anchorB); 56 | return newpin_joint(L, constraint); 57 | } 58 | 59 | SETVEC(SetAnchorA, cpPinJointSetAnchorA, pin_joint) 60 | SETVEC(SetAnchorB, cpPinJointSetAnchorB, pin_joint) 61 | GETVEC(GetAnchorA, cpPinJointGetAnchorA, pin_joint) 62 | GETVEC(GetAnchorB, cpPinJointGetAnchorB, pin_joint) 63 | SETDOUBLE(SetDist, cpPinJointSetDist, pin_joint) 64 | GETDOUBLE(GetDist, cpPinJointGetDist, pin_joint) 65 | 66 | DESTROY_FUNC(pin_joint) 67 | 68 | static const struct luaL_Reg Methods[] = 69 | { 70 | { "free", Destroy }, 71 | { "set_anchor_a", SetAnchorA }, 72 | { "set_anchor_b", SetAnchorB }, 73 | { "get_anchor_a", GetAnchorA }, 74 | { "get_anchor_b", GetAnchorB }, 75 | { "set_dist", SetDist }, 76 | { "get_dist", GetDist }, 77 | { NULL, NULL } /* sentinel */ 78 | }; 79 | 80 | static const struct luaL_Reg MetaMethods[] = 81 | { 82 | { "__gc", Destroy }, 83 | { NULL, NULL } /* sentinel */ 84 | }; 85 | 86 | static const struct luaL_Reg Functions[] = 87 | { 88 | { "pin_joint_new", Create }, 89 | { NULL, NULL } /* sentinel */ 90 | }; 91 | 92 | void moonchipmunk_open_pin_joint(lua_State *L) 93 | { 94 | udata_define(L, PIN_JOINT_MT, Methods, MetaMethods); 95 | udata_inherit(L, PIN_JOINT_MT, CONSTRAINT_MT); 96 | luaL_setfuncs(L, Functions, 0); 97 | } 98 | 99 | 100 | -------------------------------------------------------------------------------- /src/pivot_joint.c: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2020 Stefano Trettel 4 | * 5 | * Software repository: MoonChipmunk, https://github.com/stetre/moonchipmunk 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include "internal.h" 27 | #include "constraint.h" 28 | 29 | static int freepivot_joint(lua_State *L, ud_t *ud) 30 | { 31 | constraint_t *constraint = (constraint_t*)ud->handle; 32 | if(!candestroyconstraint(constraint, ud)) return 0; 33 | if(!freeuserdata(L, ud, "pivot_joint")) return 0; 34 | constraintdestroy(L, constraint); 35 | return 0; 36 | } 37 | 38 | static int newpivot_joint(lua_State *L, constraint_t *constraint) 39 | { 40 | ud_t *ud; 41 | ud = newuserdata(L, constraint, PIVOT_JOINT_MT, "pivot_joint"); 42 | ud->parent_ud = NULL; 43 | ud->destructor = freepivot_joint; 44 | return 1; 45 | } 46 | 47 | static int Create(lua_State *L) 48 | { 49 | vec_t pivot, anchorA, anchorB; 50 | constraint_t *constraint; 51 | body_t *a = checkbody(L, 1, NULL); 52 | body_t *b = checkbody(L, 2, NULL); 53 | if(lua_isnoneornil(L, 4)) 54 | { 55 | checkvec(L, 3, &pivot); 56 | constraint = cpPivotJointNew(a, b, pivot); 57 | } 58 | else 59 | { 60 | checkvec(L, 3, &anchorA); 61 | checkvec(L, 4, &anchorB); 62 | constraint = cpPivotJointNew2(a, b, anchorA, anchorB); 63 | } 64 | return newpivot_joint(L, constraint); 65 | } 66 | 67 | SETVEC(SetAnchorA, cpPivotJointSetAnchorA, pivot_joint) 68 | SETVEC(SetAnchorB, cpPivotJointSetAnchorB, pivot_joint) 69 | GETVEC(GetAnchorA, cpPivotJointGetAnchorA, pivot_joint) 70 | GETVEC(GetAnchorB, cpPivotJointGetAnchorB, pivot_joint) 71 | 72 | DESTROY_FUNC(pivot_joint) 73 | 74 | static const struct luaL_Reg Methods[] = 75 | { 76 | { "free", Destroy }, 77 | { "set_anchor_a", SetAnchorA }, 78 | { "set_anchor_b", SetAnchorB }, 79 | { "get_anchor_a", GetAnchorA }, 80 | { "get_anchor_b", GetAnchorB }, 81 | { NULL, NULL } /* sentinel */ 82 | }; 83 | 84 | static const struct luaL_Reg MetaMethods[] = 85 | { 86 | { "__gc", Destroy }, 87 | { NULL, NULL } /* sentinel */ 88 | }; 89 | 90 | static const struct luaL_Reg Functions[] = 91 | { 92 | { "pivot_joint_new", Create }, 93 | { NULL, NULL } /* sentinel */ 94 | }; 95 | 96 | void moonchipmunk_open_pivot_joint(lua_State *L) 97 | { 98 | udata_define(L, PIVOT_JOINT_MT, Methods, MetaMethods); 99 | udata_inherit(L, PIVOT_JOINT_MT, CONSTRAINT_MT); 100 | luaL_setfuncs(L, Functions, 0); 101 | } 102 | 103 | -------------------------------------------------------------------------------- /src/poly.c: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2020 Stefano Trettel 4 | * 5 | * Software repository: MoonChipmunk, https://github.com/stetre/moonchipmunk 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include "internal.h" 27 | 28 | static int freepoly(lua_State *L, ud_t *ud) 29 | { 30 | shape_t *shape = (shape_t*)ud->handle; 31 | if(!candestroyshape(shape, ud)) return 0; 32 | if(!freeuserdata(L, ud, "poly")) return 0; 33 | shapedestroy(L, (shape_t*)shape); 34 | return 0; 35 | } 36 | 37 | static int newpoly(lua_State *L, shape_t *poly) 38 | { 39 | ud_t *ud; 40 | ud = newuserdata(L, poly, POLY_MT, "poly"); 41 | ud->parent_ud = NULL; 42 | ud->destructor = freepoly; 43 | return 1; 44 | } 45 | 46 | static int PolyShapeNew(lua_State *L) 47 | { 48 | int count, raw=0; 49 | double radius; 50 | mat_t transform; 51 | vec_t *verts; 52 | shape_t *poly; 53 | body_t *body = checkbody(L, 1, NULL); 54 | if(lua_isnoneornil(L, 4)) raw=1; else checkmat(L, 4, &transform); 55 | radius = luaL_checknumber(L, 3); 56 | verts = checkveclist(L, 2, &count, NULL); 57 | poly = raw ? cpPolyShapeNewRaw(body, count, verts, radius) : 58 | cpPolyShapeNew(body, count, verts, transform, radius); 59 | Free(L, verts); 60 | return newpoly(L, poly); 61 | } 62 | 63 | static int BoxShapeNew(lua_State *L) 64 | { 65 | shape_t *poly; 66 | bb_t box; 67 | double width, height, radius; 68 | body_t *body = checkbody(L, 1, NULL); 69 | if(lua_isnumber(L, 2)) 70 | { 71 | width = luaL_checknumber(L, 2); 72 | height = luaL_checknumber(L, 3); 73 | radius = luaL_checknumber(L, 4); 74 | poly = cpBoxShapeNew(body, width, height, radius); 75 | } 76 | else 77 | { 78 | checkbb(L, 2, &box); 79 | radius = luaL_checknumber(L, 3); 80 | poly = cpBoxShapeNew2(body, box, radius); 81 | } 82 | return newpoly(L, poly); 83 | } 84 | 85 | static int GetCount(lua_State *L) 86 | { 87 | shape_t *poly = checkpoly(L, 1, NULL); 88 | int count = cpPolyShapeGetCount(poly); 89 | lua_pushnumber(L, count); 90 | return 1; 91 | } 92 | 93 | static int GetVerts(lua_State *L) 94 | { 95 | int i; 96 | vec_t vert; 97 | shape_t *poly = checkpoly(L, 1, NULL); 98 | int count = cpPolyShapeGetCount(poly); 99 | lua_newtable(L); 100 | for(i=0; ihandle; 32 | if(!candestroyconstraint(constraint, ud)) return 0; 33 | if(!freeuserdata(L, ud, "ratchet_joint")) return 0; 34 | constraintdestroy(L, constraint); 35 | return 0; 36 | } 37 | 38 | static int newratchet_joint(lua_State *L, constraint_t *constraint) 39 | { 40 | ud_t *ud; 41 | ud = newuserdata(L, constraint, RATCHET_JOINT_MT, "ratchet_joint"); 42 | ud->parent_ud = NULL; 43 | ud->destructor = freeratchet_joint; 44 | return 1; 45 | } 46 | 47 | static int Create(lua_State *L) 48 | { 49 | body_t *a = checkbody(L, 1, NULL); 50 | body_t *b = checkbody(L, 2, NULL); 51 | double phase = luaL_checknumber(L, 3); 52 | double ratchet = luaL_checknumber(L, 4); 53 | constraint_t *constraint = cpRatchetJointNew(a, b, phase, ratchet); 54 | return newratchet_joint(L, constraint); 55 | } 56 | 57 | SETDOUBLE(SetAngle, cpRatchetJointSetAngle, ratchet_joint) 58 | SETDOUBLE(SetPhase, cpRatchetJointSetPhase, ratchet_joint) 59 | SETDOUBLE(SetRatchet, cpRatchetJointSetRatchet, ratchet_joint) 60 | GETDOUBLE(GetAngle, cpRatchetJointGetAngle, ratchet_joint) 61 | GETDOUBLE(GetPhase, cpRatchetJointGetPhase, ratchet_joint) 62 | GETDOUBLE(GetRatchet, cpRatchetJointGetRatchet, ratchet_joint) 63 | 64 | DESTROY_FUNC(ratchet_joint) 65 | 66 | static const struct luaL_Reg Methods[] = 67 | { 68 | { "free", Destroy }, 69 | { "set_angle", SetAngle }, 70 | { "set_phase", SetPhase }, 71 | { "set_ratchet", SetRatchet }, 72 | { "get_angle", GetAngle }, 73 | { "get_phase", GetPhase }, 74 | { "get_ratchet", GetRatchet }, 75 | { NULL, NULL } /* sentinel */ 76 | }; 77 | 78 | static const struct luaL_Reg MetaMethods[] = 79 | { 80 | { "__gc", Destroy }, 81 | { NULL, NULL } /* sentinel */ 82 | }; 83 | 84 | static const struct luaL_Reg Functions[] = 85 | { 86 | { "ratchet_joint_new", Create }, 87 | { NULL, NULL } /* sentinel */ 88 | }; 89 | 90 | void moonchipmunk_open_ratchet_joint(lua_State *L) 91 | { 92 | udata_define(L, RATCHET_JOINT_MT, Methods, MetaMethods); 93 | udata_inherit(L, RATCHET_JOINT_MT, CONSTRAINT_MT); 94 | luaL_setfuncs(L, Functions, 0); 95 | } 96 | 97 | -------------------------------------------------------------------------------- /src/rotary_limit_joint.c: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2020 Stefano Trettel 4 | * 5 | * Software repository: MoonChipmunk, https://github.com/stetre/moonchipmunk 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include "internal.h" 27 | #include "constraint.h" 28 | 29 | static int freerotary_limit_joint(lua_State *L, ud_t *ud) 30 | { 31 | constraint_t *constraint = (constraint_t*)ud->handle; 32 | if(!candestroyconstraint(constraint, ud)) return 0; 33 | if(!freeuserdata(L, ud, "rotary_limit_joint")) return 0; 34 | constraintdestroy(L, constraint); 35 | return 0; 36 | } 37 | 38 | static int newrotary_limit_joint(lua_State *L, constraint_t *constraint) 39 | { 40 | ud_t *ud; 41 | ud = newuserdata(L, constraint, ROTARY_LIMIT_JOINT_MT, "rotary_limit_joint"); 42 | ud->parent_ud = NULL; 43 | ud->destructor = freerotary_limit_joint; 44 | return 1; 45 | } 46 | 47 | static int Create(lua_State *L) 48 | { 49 | body_t *a = checkbody(L, 1, NULL); 50 | body_t *b = checkbody(L, 2, NULL); 51 | double min = luaL_checknumber(L, 3); 52 | double max = luaL_checknumber(L, 4); 53 | constraint_t *constraint = cpRotaryLimitJointNew(a, b, min, max); 54 | return newrotary_limit_joint(L, constraint); 55 | } 56 | 57 | SETDOUBLE(SetMin, cpRotaryLimitJointSetMin, rotary_limit_joint) 58 | SETDOUBLE(SetMax, cpRotaryLimitJointSetMax, rotary_limit_joint) 59 | GETDOUBLE(GetMin, cpRotaryLimitJointGetMin, rotary_limit_joint) 60 | GETDOUBLE(GetMax, cpRotaryLimitJointGetMax, rotary_limit_joint) 61 | 62 | DESTROY_FUNC(rotary_limit_joint) 63 | 64 | static const struct luaL_Reg Methods[] = 65 | { 66 | { "free", Destroy }, 67 | { "set_min", SetMin }, 68 | { "set_max", SetMax }, 69 | { "get_min", GetMin }, 70 | { "get_max", GetMax }, 71 | { NULL, NULL } /* sentinel */ 72 | }; 73 | 74 | static const struct luaL_Reg MetaMethods[] = 75 | { 76 | { "__gc", Destroy }, 77 | { NULL, NULL } /* sentinel */ 78 | }; 79 | 80 | static const struct luaL_Reg Functions[] = 81 | { 82 | { "rotary_limit_joint_new", Create }, 83 | { NULL, NULL } /* sentinel */ 84 | }; 85 | 86 | void moonchipmunk_open_rotary_limit_joint(lua_State *L) 87 | { 88 | udata_define(L, ROTARY_LIMIT_JOINT_MT, Methods, MetaMethods); 89 | udata_inherit(L, ROTARY_LIMIT_JOINT_MT, CONSTRAINT_MT); 90 | luaL_setfuncs(L, Functions, 0); 91 | } 92 | 93 | -------------------------------------------------------------------------------- /src/segment.c: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2020 Stefano Trettel 4 | * 5 | * Software repository: MoonChipmunk, https://github.com/stetre/moonchipmunk 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include "internal.h" 27 | 28 | static int freesegment(lua_State *L, ud_t *ud) 29 | { 30 | shape_t *shape = (shape_t*)ud->handle; 31 | if(!candestroyshape(shape, ud)) return 0; 32 | if(!freeuserdata(L, ud, "segment")) return 0; 33 | shapedestroy(L, (shape_t*)shape); 34 | return 0; 35 | } 36 | 37 | static int newsegment(lua_State *L, shape_t *segment) 38 | { 39 | ud_t *ud; 40 | ud = newuserdata(L, segment, SEGMENT_MT, "segment"); 41 | ud->parent_ud = NULL; 42 | ud->destructor = freesegment; 43 | return 1; 44 | } 45 | 46 | static int Create(lua_State *L) 47 | { 48 | shape_t *segment; 49 | vec_t a, b; 50 | double radius; 51 | body_t *body = checkbody(L, 1, NULL); 52 | checkvec(L, 2, &a); 53 | checkvec(L, 3, &b); 54 | radius = luaL_checknumber(L, 4); 55 | segment = cpSegmentShapeNew(body, a, b, radius); 56 | return newsegment(L, segment); 57 | } 58 | 59 | static int SetNeighbors(lua_State *L) 60 | { 61 | vec_t prev, next; 62 | shape_t *segment = checksegment(L, 1, NULL); 63 | checkvec(L, 2, &prev); 64 | checkvec(L, 3, &next); 65 | cpSegmentShapeSetNeighbors(segment, prev, next); 66 | return 0; 67 | } 68 | 69 | #if 0 70 | static int GetA(lua_State *L) 71 | { 72 | shape_t *segment = checksegment(L, 1, NULL); 73 | vec_t a = cpSegmentShapeGetA(segment); 74 | pushvec(L, &a); 75 | return 1; 76 | } 77 | 78 | static int GetB(lua_State *L) 79 | { 80 | shape_t *segment = checksegment(L, 1, NULL); 81 | vec_t b = cpSegmentShapeGetB(segment); 82 | pushvec(L, &b); 83 | return 1; 84 | } 85 | #endif 86 | 87 | static int GetEndpoints(lua_State *L) 88 | { 89 | shape_t *segment = checksegment(L, 1, NULL); 90 | vec_t a = cpSegmentShapeGetA(segment); 91 | vec_t b = cpSegmentShapeGetB(segment); 92 | pushvec(L, &a); 93 | pushvec(L, &b); 94 | return 2; 95 | } 96 | 97 | static int SetEndpoints(lua_State *L) 98 | { 99 | vec_t a, b; 100 | shape_t *segment = checksegment(L, 1, NULL); 101 | checkvec(L, 2, &a); 102 | checkvec(L, 3, &b); 103 | cpSegmentShapeSetEndpoints(segment, a, b); 104 | return 0; 105 | } 106 | 107 | static int GetNormal(lua_State *L) 108 | { 109 | shape_t *segment = checksegment(L, 1, NULL); 110 | vec_t n = cpSegmentShapeGetNormal(segment); 111 | pushvec(L, &n); 112 | return 1; 113 | } 114 | 115 | static int GetRadius(lua_State *L) 116 | { 117 | shape_t *segment = checksegment(L, 1, NULL); 118 | double radius = cpSegmentShapeGetRadius(segment); 119 | lua_pushnumber(L, radius); 120 | return 1; 121 | } 122 | 123 | static int SetRadius(lua_State *L) 124 | { 125 | shape_t *segment = checksegment(L, 1, NULL); 126 | double radius = luaL_checknumber(L, 2); 127 | cpSegmentShapeSetRadius(segment, radius); 128 | return 0; 129 | } 130 | 131 | DESTROY_FUNC(segment) 132 | 133 | static const struct luaL_Reg Methods[] = 134 | { 135 | { "free", Destroy }, 136 | { "set_neighbors", SetNeighbors }, 137 | // { "get_a", GetA }, 138 | // { "get_b", GetB }, 139 | { "get_normal", GetNormal }, 140 | { "get_endpoints", GetEndpoints }, 141 | { "set_endpoints", SetEndpoints }, /* chipmunk_unsafe.h */ 142 | { "get_radius", GetRadius }, 143 | { "set_radius", SetRadius }, /* chipmunk_unsafe.h */ 144 | { NULL, NULL } /* sentinel */ 145 | }; 146 | 147 | static const struct luaL_Reg MetaMethods[] = 148 | { 149 | { "__gc", Destroy }, 150 | { NULL, NULL } /* sentinel */ 151 | }; 152 | 153 | static const struct luaL_Reg Functions[] = 154 | { 155 | { "segment_shape_new", Create }, 156 | { NULL, NULL } /* sentinel */ 157 | }; 158 | 159 | void moonchipmunk_open_segment(lua_State *L) 160 | { 161 | udata_define(L, SEGMENT_MT, Methods, MetaMethods); 162 | udata_inherit(L, SEGMENT_MT, SHAPE_MT); 163 | luaL_setfuncs(L, Functions, 0); 164 | } 165 | 166 | -------------------------------------------------------------------------------- /src/simple_motor.c: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2020 Stefano Trettel 4 | * 5 | * Software repository: MoonChipmunk, https://github.com/stetre/moonchipmunk 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include "internal.h" 27 | #include "constraint.h" 28 | 29 | static int freesimple_motor(lua_State *L, ud_t *ud) 30 | { 31 | constraint_t *constraint = (constraint_t*)ud->handle; 32 | if(!candestroyconstraint(constraint, ud)) return 0; 33 | if(!freeuserdata(L, ud, "simple_motor")) return 0; 34 | constraintdestroy(L, constraint); 35 | return 0; 36 | } 37 | 38 | static int newsimple_motor(lua_State *L, constraint_t *constraint) 39 | { 40 | ud_t *ud; 41 | ud = newuserdata(L, constraint, SIMPLE_MOTOR_MT, "simple_motor"); 42 | ud->parent_ud = NULL; 43 | ud->destructor = freesimple_motor; 44 | return 1; 45 | } 46 | 47 | static int Create(lua_State *L) 48 | { 49 | body_t *a = checkbody(L, 1, NULL); 50 | body_t *b = checkbody(L, 2, NULL); 51 | double rate = luaL_checknumber(L, 3); 52 | constraint_t *constraint = cpSimpleMotorNew(a, b, rate); 53 | return newsimple_motor(L, constraint); 54 | } 55 | 56 | SETDOUBLE(SetRate, cpSimpleMotorSetRate, simple_motor) 57 | GETDOUBLE(GetRate, cpSimpleMotorGetRate, simple_motor) 58 | 59 | DESTROY_FUNC(simple_motor) 60 | 61 | static const struct luaL_Reg Methods[] = 62 | { 63 | { "free", Destroy }, 64 | { "set_rate", SetRate }, 65 | { "get_rate", GetRate }, 66 | { NULL, NULL } /* sentinel */ 67 | }; 68 | 69 | static const struct luaL_Reg MetaMethods[] = 70 | { 71 | { "__gc", Destroy }, 72 | { NULL, NULL } /* sentinel */ 73 | }; 74 | 75 | static const struct luaL_Reg Functions[] = 76 | { 77 | { "simple_motor_new", Create }, 78 | { NULL, NULL } /* sentinel */ 79 | }; 80 | 81 | void moonchipmunk_open_simple_motor(lua_State *L) 82 | { 83 | udata_define(L, SIMPLE_MOTOR_MT, Methods, MetaMethods); 84 | udata_inherit(L, SIMPLE_MOTOR_MT, CONSTRAINT_MT); 85 | luaL_setfuncs(L, Functions, 0); 86 | } 87 | 88 | -------------------------------------------------------------------------------- /src/slide_joint.c: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2020 Stefano Trettel 4 | * 5 | * Software repository: MoonChipmunk, https://github.com/stetre/moonchipmunk 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include "internal.h" 27 | #include "constraint.h" 28 | 29 | static int freeslide_joint(lua_State *L, ud_t *ud) 30 | { 31 | constraint_t *constraint = (constraint_t*)ud->handle; 32 | if(!candestroyconstraint(constraint, ud)) return 0; 33 | if(!freeuserdata(L, ud, "slide_joint")) return 0; 34 | constraintdestroy(L, constraint); 35 | return 0; 36 | } 37 | 38 | static int newslide_joint(lua_State *L, constraint_t *constraint) 39 | { 40 | ud_t *ud; 41 | ud = newuserdata(L, constraint, SLIDE_JOINT_MT, "slide_joint"); 42 | ud->parent_ud = NULL; 43 | ud->destructor = freeslide_joint; 44 | return 1; 45 | } 46 | 47 | static int Create(lua_State *L) 48 | { 49 | double min, max; 50 | vec_t anchorA, anchorB; 51 | constraint_t *constraint; 52 | body_t *a = checkbody(L, 1, NULL); 53 | body_t *b = checkbody(L, 2, NULL); 54 | checkvec(L, 3, &anchorA); 55 | checkvec(L, 4, &anchorB); 56 | min = luaL_checknumber(L, 5); 57 | max = luaL_checknumber(L, 6); 58 | constraint = cpSlideJointNew(a, b, anchorA, anchorB, min, max); 59 | return newslide_joint(L, constraint); 60 | } 61 | 62 | SETVEC(SetAnchorA, cpSlideJointSetAnchorA, slide_joint) 63 | SETVEC(SetAnchorB, cpSlideJointSetAnchorB, slide_joint) 64 | GETVEC(GetAnchorA, cpSlideJointGetAnchorA, slide_joint) 65 | GETVEC(GetAnchorB, cpSlideJointGetAnchorB, slide_joint) 66 | SETDOUBLE(SetMin, cpSlideJointSetMin, slide_joint) 67 | SETDOUBLE(SetMax, cpSlideJointSetMax, slide_joint) 68 | GETDOUBLE(GetMin, cpSlideJointGetMin, slide_joint) 69 | GETDOUBLE(GetMax, cpSlideJointGetMax, slide_joint) 70 | 71 | DESTROY_FUNC(slide_joint) 72 | 73 | static const struct luaL_Reg Methods[] = 74 | { 75 | { "free", Destroy }, 76 | { "set_anchor_a", SetAnchorA }, 77 | { "set_anchor_b", SetAnchorB }, 78 | { "get_anchor_a", GetAnchorA }, 79 | { "get_anchor_b", GetAnchorB }, 80 | { "set_min", SetMin }, 81 | { "set_max", SetMax }, 82 | { "get_min", GetMin }, 83 | { "get_max", GetMax }, 84 | { NULL, NULL } /* sentinel */ 85 | }; 86 | 87 | static const struct luaL_Reg MetaMethods[] = 88 | { 89 | { "__gc", Destroy }, 90 | { NULL, NULL } /* sentinel */ 91 | }; 92 | 93 | static const struct luaL_Reg Functions[] = 94 | { 95 | { "slide_joint_new", Create }, 96 | { NULL, NULL } /* sentinel */ 97 | }; 98 | 99 | void moonchipmunk_open_slide_joint(lua_State *L) 100 | { 101 | udata_define(L, SLIDE_JOINT_MT, Methods, MetaMethods); 102 | udata_inherit(L, SLIDE_JOINT_MT, CONSTRAINT_MT); 103 | luaL_setfuncs(L, Functions, 0); 104 | } 105 | 106 | -------------------------------------------------------------------------------- /src/tracing.c: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2020 Stefano Trettel 4 | * 5 | * Software repository: MoonChipmunk, https://github.com/stetre/moonchipmunk 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include "internal.h" 27 | 28 | int trace_objects = 0; 29 | 30 | static int TraceObjects(lua_State *L) 31 | { 32 | trace_objects = checkboolean(L, 1); 33 | return 0; 34 | } 35 | 36 | static int Now(lua_State *L) 37 | { 38 | lua_pushnumber(L, now()); 39 | return 1; 40 | } 41 | 42 | static int Since(lua_State *L) 43 | { 44 | double t = luaL_checknumber(L, 1); 45 | lua_pushnumber(L, since(t)); 46 | return 1; 47 | } 48 | 49 | /* ----------------------------------------------------------------------- */ 50 | 51 | static const struct luaL_Reg Functions[] = 52 | { 53 | { "trace_objects", TraceObjects }, 54 | { "now", Now }, 55 | { "since", Since }, 56 | { NULL, NULL } /* sentinel */ 57 | }; 58 | 59 | void moonchipmunk_open_tracing(lua_State *L) 60 | { 61 | luaL_setfuncs(L, Functions, 0); 62 | } 63 | 64 | 65 | -------------------------------------------------------------------------------- /src/udata.h: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2020 Stefano Trettel 4 | * 5 | * Software repository: MoonChipmunk, https://github.com/stetre/moonchipmunk 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | #include 32 | #include "lua.h" 33 | #include "lauxlib.h" 34 | #include "compat-5.3.h" 35 | 36 | #ifndef Malloc 37 | #define Malloc moonchipmunk_Malloc 38 | void *Malloc(lua_State *L, size_t size); 39 | #define Free moonchipmunk_Free 40 | void Free(lua_State *L, void *ptr); 41 | #endif 42 | 43 | #define udata_t moonchipmunk_udata_t 44 | #define udata_s moonchipmunk_udata_s 45 | #define moonchipmunk_udata_t struct moonchipmunk_udata_s 46 | 47 | #define udata_new moonchipmunk_udata_new 48 | void *udata_new(lua_State*, size_t, uint64_t, const char*); 49 | #define udata_unref moonchipmunk_udata_unref 50 | int udata_unref(lua_State *L, uint64_t); 51 | #define udata_free moonchipmunk_udata_free 52 | int udata_free(lua_State*, uint64_t); 53 | #define udata_mem moonchipmunk_udata_mem 54 | void *udata_mem(uint64_t); 55 | #define udata_push moonchipmunk_udata_push 56 | int udata_push(lua_State*, uint64_t); 57 | #define udata_free_all moonchipmunk_udata_free_all 58 | void udata_free_all(lua_State *L); 59 | #define udata_scan moonchipmunk_udata_scan 60 | int udata_scan(lua_State *L, const char *mt, 61 | void *info, int (*func)(lua_State *L, const void *mem, const char* mt, const void *info)); 62 | #define udata_define moonchipmunk_udata_define 63 | int udata_define(lua_State*, const char*, const luaL_Reg*, const luaL_Reg*); 64 | #define udata_inherit moonchipmunk_udata_inherit 65 | int udata_inherit(lua_State*, const char*, const char*); 66 | #define udata_test moonchipmunk_udata_test 67 | void *udata_test(lua_State*, int, const char*); 68 | #define udata_addmethods moonchipmunk_udata_addmethods 69 | int udata_addmethods(lua_State*, const char*, const luaL_Reg*); 70 | 71 | #ifdef __cplusplus 72 | } 73 | #endif 74 | 75 | -------------------------------------------------------------------------------- /thirdparty/asciidoctor-styles-license: -------------------------------------------------------------------------------- 1 | The CSS used for the Reference Manual is taken from the 2 | Asciidoctor styles project 3 | (https://github.com/asciidoctor/asciidoctor-stylesheet-factory ). 4 | 5 | Below is a copy of the Asciidoctor styles copyright notice. 6 | 7 | Stefano Trettel 8 | 9 | ======================================================================== 10 | 11 | Asciidoctor styles 12 | ------------------ 13 | 14 | Copyright (c) 2013 Dan Allen 15 | 16 | MIT License 17 | 18 | Permission is hereby granted, free of charge, to any person obtaining 19 | a copy of this software and associated documentation files (the 20 | "Software"), to deal in the Software without restriction, including 21 | without limitation the rights to use, copy, modify, merge, publish, 22 | distribute, sublicense, and/or sell copies of the Software, and to 23 | permit persons to whom the Software is furnished to do so, subject to 24 | the following conditions: 25 | 26 | The above copyright notice and this permission notice shall be 27 | included in all copies or substantial portions of the Software. 28 | 29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 30 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 31 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 32 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 33 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 34 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 35 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 36 | 37 | 38 | Other licensed work 39 | ------------------- 40 | 41 | - Foundation 4 by Zurb, on which the themes are built, is licensed under the 42 | Apache License, v2.0: 43 | 44 | http://apache.org/licenses/LICENSE-2.0 45 | http://foundation.zurb.com 46 | 47 | - The riak theme is derived from the Riak documentation theme by Basho, 48 | licensed under the Creative Commons Attribution 3.0 Unported License: 49 | 50 | http://creativecommons.org/licenses/by/3.0/us 51 | http://docs.basho.org 52 | 53 | - The iconic theme is inspired by O'Reilly typography and Atlas manual. 54 | 55 | http://oreilly.com 56 | -------------------------------------------------------------------------------- /thirdparty/lua-compat-5.3-license: -------------------------------------------------------------------------------- 1 | The src/compat-5.3.h and src/compat-5.3.c files are taken from: 2 | https://github.com/keplerproject/lua-compat-5.3 3 | 4 | Below is a copy of the original copyright notice, from the same source. 5 | 6 | Stefano Trettel 7 | 8 | =========================================================================== 9 | 10 | The MIT License (MIT) 11 | 12 | Copyright (c) 2015 Kepler Project. 13 | 14 | Permission is hereby granted, free of charge, to any person obtaining a copy of 15 | this software and associated documentation files (the "Software"), to deal in 16 | the Software without restriction, including without limitation the rights to 17 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 18 | the Software, and to permit persons to whom the Software is furnished to do so, 19 | subject to the following conditions: 20 | 21 | The above copyright notice and this permission notice shall be included in all 22 | copies or substantial portions of the Software. 23 | 24 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 26 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 27 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 28 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | 31 | -------------------------------------------------------------------------------- /thirdparty/openbsd-tree-license: -------------------------------------------------------------------------------- 1 | The src/tree.h module is taken from: 2 | http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/sys/tree.h 3 | 4 | Below is a copy of the copyright notice included in the module. 5 | 6 | Stefano Trettel 7 | 8 | =========================================================================== 9 | /* 10 | * Copyright 2002 Niels Provos 11 | * All rights reserved. 12 | * 13 | * Redistribution and use in source and binary forms, with or without 14 | * modification, are permitted provided that the following conditions 15 | * are met: 16 | * 1. Redistributions of source code must retain the above copyright 17 | * notice, this list of conditions and the following disclaimer. 18 | * 2. Redistributions in binary form must reproduce the above copyright 19 | * notice, this list of conditions and the following disclaimer in the 20 | * documentation and/or other materials provided with the distribution. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | -------------------------------------------------------------------------------- /thirdparty/powered-by-lua-license: -------------------------------------------------------------------------------- 1 | The 'powered by Lua' logo (doc/powered-by-lua.gif ) is taken from: 2 | http://www.lua.org/images . 3 | 4 | Below is a copy of the copyright notice from the same web-page. 5 | 6 | Stefano Trettel 7 | 8 | =========================================================================== 9 | Copyright © 1998 Lua.org. Graphic design by Alexandre Nakonechnyj. 10 | 11 | Permission is hereby granted, without written agreement and without license 12 | or royalty fees, to use, copy, and distribute this logo for any purpose, 13 | including commercial applications, subject to the following conditions: 14 | 15 | - The origin of this logo must not be misrepresented; you must not claim that 16 | you drew the original logo. 17 | - The only modification you can make is to adapt the orbiting text to your 18 | product name. 19 | - The logo can be used in any scale as long as the relative proportions of its 20 | elements are maintained. 21 | --------------------------------------------------------------------------------