Physix.go is simple, easy to use , fast , physics engine written in GoLang With functions to perform physics calculations faster...
- Vector Calculations
- Physics Calculations
- Easy to use with Ebiten.go
GoLang must be installed And Ebiten
Install
To start , Clone this project
git clone https://github.com/rudransh61/Physix.go
Then Run the example files from ./examples
folder
for example :
go run ./examples/ex4.go //which is simple circular motion
Vectors are a datatype to store vectors.
Import the following file to use vectors
package main
import (
//...other imports
"github.com/rudransh61/Physix-go/pkg/vector"
)
var MyVector := vector.Vector{X: 30, Y: 20}
// X is x component and Y is y component of Vector
Using Function
var NewVec := vector.NewVector(x,y)
var NewVector = Vec1.Add(Vec2)
var NewVector = Vec1.Sub(Vec2)
var DotProduct := Vec1.InnerProduct(Vec2)
var ScaledVector := Vec1.Scale(num)
var Magnitude := Vec1.Magnitude()
var NormalizeVector = Vec1.Normalize()
var distance = vector.Distance(Vec1,Vec2)
vector.Vector Orthogonal_Vector = vector.Orthogonal(Vec1)
In this Physics Engine , we call every physical entity a : RigidBody
There are 2 types of RigidBody According to their Shape
- Rectangle
- Circle
Every RigidBody have following properties :-
- Position : Vector # Required while initializing - Velocity : Vector - Force : Vector - Mass : float64 # Required while initializing for Collision and Forces - Shape : string # Required while initializing for Collision - Width : float64 # Required while initializing only for Shape :- "Rectangle" - Height : float64 # Required while initializing only for Shape :- "Rectangle" - Radius : float64 # Required while initializing only for Shape :- "Circle" - IsMovable : bool # Required while initializing for Collision and Forces
To create an instance of RigidBody you need to provide all the required fields .
First Import these files,
import (
"github.com/rudransh61/Physix-go/dynamics/physics"
"github.com/rudransh61/Physix-go/pkg/rigidbody"
)
Example :-
ball = &rigidbody.RigidBody{
Position: vector.Vector{X: 400, Y: 100},
Velocity: vector.Vector{X: 0, Y: 2},
Mass: 1,
Force: vector.Vector{X: 0, Y: 5},
IsMovable: true,
Shape: "Rectangle",
Width: 50,
Height: 50,
}
To update position of a RigidBody, Use ApplyForce in a loop , Example :-
for i := 0; i < 100; i++ {
github.com/rudransh61/Physix-go.ApplyForce(ball1, vector.Vector{X: 10, Y: 0}, dt) // Make the vector (0,0) to apply no force
// .. other code
}
To access or change the Force , Velocity , Position,
ball.Velocity // Get the velocity of ball as a vector.Vector
ball.Position.X += 5 // Increase the position of ball in X direction by 5
There are 2 types of collision systems for different shapes.
- Rectangle-Rectangle collision
- Circle-Circle collision
For example you have 2 Rectangles, Like this :-
rect = &rigidbody.RigidBody{
Position: vector.Vector{X: 100, Y: 200},
Velocity: vector.Vector{X: 50, Y: -50},
Mass: 1.0,
Shape : "Rectangle",
Width : 100,
Height : 90,
IsMovable : true,
}
rect2 = &rigidbody.RigidBody{
Position: vector.Vector{X: 400, Y: 300},
Velocity: vector.Vector{X: 60, Y: 50},
Mass: 2.0,
Shape : "Rectangle",
Width : 70,
Height : 70,
IsMovable : true,
}
Now you want to detect collision between them ,
if(collision.RectangleCollided(rect,rect2)){
fmt.Println("Collided!")
}
And if you want to add a bounce effect in this collision according to the Momentum Conservation and Energy Conservation,
if(collision.RectangleCollided(rect,rect2)){
float64 e = 0.9999999999; // e is coefficient of restitution in collision
collision.BounceOnCollision(ball,ball2,e)// NOTE :- e<1 is bit glitchy and goes wild, use it on your own risk :)
}
==NOTE :- e<1 is bit glitchy and goes wild, use it on your own risk :) ==
Now if you want to detect collisions between a circle and a circle,
if(collision.CircleCollided(rect,rect2)){
fmt.Println("Collided!")
}
And same BounceOnCollision function for Bouncing ...
Check examples in ./example
folder
To create a polygon , we made a new entity Polygon which inherits all Properties of RigidBody with some additional features.
- Position : Vector # Required while initializing - Velocity : Vector - Force : Vector - Mass : float64 # Required while initializing for Collision and Forces - IsMovable : bool # Required while initializing for Collision and Forces - Vertices : [] Vector # Required while initializing only for Shape :- "Polygon"
To initialize a polygon , use NewPolygon function
import (
...
"github.com/rudransh61/Physix-go/pkg/polygon"
...
)
...
vertices := []vector.Vector{
{X: 250, Y: 50},
{X: 200, Y: 100},
{X: 200, Y: 50},
{X: 350, Y: 200}
}
ball = polygon.NewPolygon(vertices, 50, true)
To update our 'entity' , We have 2 functions which are ApplyForce and ApplyForcePolygon , as the name suggests one is for Rigidbody and one for polygons.
This function will move one frame forward or 'dt' time forward (which is time between 2 frames).
NOTE: Define dt(0.1 mostly) at top globally for good code
polygonA := polygon.NewPolygon(vertices, 50, true) # Example
# Define dt
dt := 0.1
physix.ApplyForcePolygon(
polygonA,
vector.Vector{X: 10, Y: 0},
dt,
)
# To applyForce on polygon and update its position and everything
Similarly for RigidBody :
rigid := &rigidbody.Rigidbody{...}
physix.ApplyForce(rigid, vector.Vector{X:10,Y:0}, dt)
To get both the utilities in the code import this file:
import(
...
"github.com/rudransh61/Physix-go/dynamics/physics"
...
)
New contributors are welcome!! If you have any doubt related to its working you can ask to us by opening an issue
LICENSE.md
file
Inspired from Coding Train - Daniel Shiffman