Skip to content

rudransh61/Physix-go

Repository files navigation

Physix.go

A simple Physics Engine in GoLang☻

Introduction

Physix.go is simple, easy to use , fast , physics engine written in GoLang With functions to perform physics calculations faster...

Features

  • Vector Calculations
  • Physics Calculations
  • Easy to use with Ebiten.go

Getting Started

Prerequisites

GoLang must be installed And Ebiten

Installation

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

Documentation

Vectors

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"
)

To make a 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)
Add Vector
var NewVector = Vec1.Add(Vec2)
Subtract Vector
var NewVector = Vec1.Sub(Vec2)
Inner Product of 2 Vectors
var DotProduct := Vec1.InnerProduct(Vec2)
Scale a Vector by a scalar
var ScaledVector := Vec1.Scale(num)
Magnitude of a Vector
var Magnitude := Vec1.Magnitude()
Normalize a Vector
var NormalizeVector = Vec1.Normalize()
Distance between Head of 2 Vectors
var distance = vector.Distance(Vec1,Vec2)
Perpendicular Vector of a given Vector
vector.Vector Orthogonal_Vector = vector.Orthogonal(Vec1)

Basics

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

RigidBody

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

Collision Detection

There are 2 types of collision systems for different shapes.

  • Rectangle-Rectangle collision
  • Circle-Circle collision

Rectangle 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 :) ==

Circle Collision

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 ...

Examples

Check examples in ./example folder

Polygon

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

Example

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)

Some Dynamics

Physics

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"
 	...
)

Contributing

New contributors are welcome!! If you have any doubt related to its working you can ask to us by opening an issue

License

LICENSE.md file

Acknowledgments

Inspired from Coding Train - Daniel Shiffman