Farseer Physic Engine merupakan engine fisika yang open source untuk .NET.
Pada tulisan ini saya akan mencoba membuat contoh implementasi dari sebuah kotak dan lingkaran. Kotak dan lingkaran tersebut dapat digerakkan dan bertabrakan satu sama lain.
Program yang diperlukan :
- Microsoft Visual Studio 2008 SP 1
- XNAGS 31
Packages atau project yang dibutuhkan :
- Farseer Physics 2.1.3 XNA
- DemoBaseXNA
Langkah-langkah :
Buat project baru XNA Game Studio 3.1 -> Windows Game 3.1
Add Packages Farseer Physics 2.1.3 XNA & DemoBaseXNA
Add Reference Farseer Physics 2.1.3 XNA & DemoBaseXNA
Buat Class yang diturunkan dari class DemoBaseXNA.ScreenSystem.GameScreen
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DemoBaseXNA;
using DemoBaseXNA.DrawingSystem;
using DemoBaseXNA.ScreenSystem;
using FarseerGames.FarseerPhysics;
using FarseerGames.FarseerPhysics.Dynamics;
using FarseerGames.FarseerPhysics.Factories;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace WindowsGame2.Contoh1
{
class contoh1:GameScreen
{
//inisialisasi awal gamescreen
public override void Initialize()
{
}
//load object, digunakan untuk load lingkaran dan kotak
public override void LoadContent()
{
}
//digunakan untuk menggambar objek ke layar
public override void Draw(GameTime gameTime)
{
}
//handle input state dari gamescreen
public override void HandleInput(InputState input)
{
}
//handle input dari keyboard
private void HandleKeyboardInput(InputState input)
{
}
//text detail saat dilayar pause
private static string GetDetails()
{
}
}
}
Inisialisasi Class GameScreen
public override void Initialize()
{
//inisialisasi physic simulator
PhysicsSimulator = new PhysicsSimulator(new Vector2(0, 0));
//add physic simulator ke view
PhysicsSimulatorView = new hysicsSimulatorView(PhysicsSimulator);
base.Initialize();
}
Load objek gambar geometry yang akan diload
public override void LoadContent()
{
//membuat brush untuk draw lingkaran
//radius, fill color, border color
_circleBrush = new CircleBrush(64, Color.White, Color.Black);
_circleBrush.Load(ScreenManager.GraphicsDevice);
//membuat body dari lingkaran untuk simulasi gaya dan impuls
//radius, masa
_circleBody = BodyFactory.Instance.CreateCircleBody(PhysicsSimulator, 64, 1);
_circleBody.Position = new Vector2(500, 384);
//mmebuat geometri untuk deteksi tabrakan dari lingkaran
//body, radius, jumlah edge/garis
GeomFactory.Instance.CreateCircleGeom(PhysicsSimulator, _circleBody, 64, 20);
//membuat body kotak untuk simulasi gaya dan impuls
//width, height, mass
_rectangleBody = BodyFactory.Instance.CreateRectangleBody(PhysicsSimulator, 128, 128, 1);
_rectangleBody.Position = new Vector2(256, 384);
//membuat geometri untuk deteksi tabrakan dari kotak
//width, height
GeomFactory.Instance.CreateRectangleGeom(PhysicsSimulator, _rectangleBody, 128, 128);
//membuat brush untuk draw kotak
//width, height, fill color, border color
_rectangleBrush = new RectangleBrush(128, 128, Color.Gold, Color.Black);
_rectangleBrush.Load(ScreenManager.GraphicsDevice);
base.LoadContent();
}
Draw brush model sesuai dengan bodynya
public override void Draw(GameTime gameTime)
{
//memulai proses drawing pada SpriteBatch
ScreenManager.SpriteBatch.Begin(SpriteBlendMode.AlphaBlend);
//menggambar brush lingkaran sesuai dengan body lingkaran
_circleBrush.Draw(ScreenManager.SpriteBatch, _circleBody.Position);
//menggambar brush kotak sesuai dengan body kotak
_rectangleBrush.Draw(ScreenManager.SpriteBatch, _rectangleBody.Position, _rectangleBody.Rotation);
//menutup SpriteBatch
ScreenManager.SpriteBatch.End();
base.Draw(gameTime);
}
Mengatur handle input
public override void HandleInput(InputState input)
{
//jika gamescreen pertama kali dijalankan
if (firstRun)
{
//tambah pause screen ke screen manager
ScreenManager.AddScreen(new PauseScreen(GetTitle(), GetDetails()));
firstRun = false;
}
//jika screen dalam keadaan pause/ berhentei sejenak
if (input.PauseGame)
{
ScreenManager.AddScreen(new PauseScreen(GetTitle(), GetDetails()));
}
//handle input keyboard
HandleKeyboardInput(input);
base.HandleInput(input);
}
private void HandleKeyboardInput(InputState input)
{
//set besarnya penambahan gaya jika user menekan A/S/D/W
const float forceAmount = 50;
//set gaya awal sebesar 0/ diam
Vector2 force = Vector2.Zero;
//set Y negatif/ ke bawah
force.Y = -force.Y;
//user menekan tombol A
if (input.CurrentKeyboardState.IsKeyDown(Keys.A)) { force += new Vector2(-forceAmount, 0); }
//user menekan tombol S
if (input.CurrentKeyboardState.IsKeyDown(Keys.S)) { force += new Vector2(0, forceAmount); }
//user menekan tombol D
if (input.CurrentKeyboardState.IsKeyDown(Keys.D)) { force += new Vector2(forceAmount, 0); }
//user menekan tombol W
if (input.CurrentKeyboardState.IsKeyDown(Keys.W)) { force += new Vector2(0, -forceAmount); }
//berikan gaya pada body kotak
_rectangleBody.ApplyForce(force);
//set besarnya pertambahan torsi pada kotak
const float torqueAmount = 1000;
//set torsi awal menjadi 0/ tidak berputar
float torque = 0;
//user menekan tombol left
if (input.CurrentKeyboardState.IsKeyDown(Keys.Left)) { torque -= torqueAmount; }
//user menekan tombol right
if (input.CurrentKeyboardState.IsKeyDown(Keys.Right)) { torque += torqueAmount; }
//berikan torsi pada kotak
_rectangleBody.ApplyTorque(torque);
}
Set atribut lain dalam GameSreen
//judul dari GameScreen
public static string GetTitle()
{
return "Contoh 1 : kotak dan lingkaran";
}
//Deskripsi dari GameScreen (akan dipasang di pause screen)
private static string GetDetails()
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("Contoh isi dari layar pause/menu");
sb.AppendLine("object attached.");
sb.AppendLine(string.Empty);
sb.AppendLine("Keyboard:");
sb.AppendLine(" -Rotasi : panah kanan atau kiri");
sb.AppendLine(" -Gerak: A,S,D,W");
sb.AppendLine(string.Empty);
sb.AppendLine("Mouse");
sb.AppendLine(" -Tahan mouse kiri lalu drag mouse");
return sb.ToString();
}
Set constructor Game, add GameScreen ke Game
public Game1()
{
graphics = new GraphicsDeviceManager(this);
//set judul game
Window.Title = "Contoh Farseer Physics Engine XNA";
graphics.SynchronizeWithVerticalRetrace = false;
TargetElapsedTime = new TimeSpan(0, 0, 0, 0, 10);
IsFixedTimeStep = true;
//set ukuran jendela game
graphics.PreferredBackBufferWidth = 800;
graphics.PreferredBackBufferHeight = 600;
graphics.IsFullScreen = false;
//set apakah mouse di draw atau tidak
IsMouseVisible = true;
//Set window defaults. Parent game can override in constructor
Window.AllowUserResizing = false;
//new-up components and add to Game.Components
ScreenManager screenmanager= new ScreenManager(this);
Components.Add(screenmanager);
//set frame counter
FrameRateCounter frameRateCounter = new FrameRateCounter(screenmanager);
frameRateCounter.DrawOrder = 101;
Components.Add(frameRateCounter);
//tambah GameScreen yang sudah Anda buat(contoh1)
screenmanager.MainMenuScreen.AddMainMenuItem(contoh1.GetTitle(), new contoh1());
screenmanager.MainMenuScreen.AddMainMenuItem("Keluar", null, true);
//arahkan game ke main menu
screenmanager.GoToMainMenu();
}
Dan berikut adalah hasil akhir dari program diatas