แนะให้รู้จัก Farseer Physics Engine สำหรับสร้างงานประยุกต์สนุกๆในโลก 2D

แนะนำให้รู้จัก

Farseer Physics Engine เป็นเครื่องมือที่ใช้ง่ายมากในการทำกลไกลทาง  physics แบบ 2 มิติ มันยังสนับสนุนหลาย platform เช่น Microsoft’s XNA, Silverlight, WPF, และ Vanilla .NET Farseer Physics Engine เน้นที่ความเรียบง่าย, คุณลักษณะที่มีประโยชน์, และทำให้การสร้างเกมแบบไดนามิก เป็นเรื่องสนุกมาก(จริงๆ)

ภาพรวม

จริงๆแล้ว Farseer Physics Engine ถูกออกแบบมาเพื่อควบคุมตำแหน่งและการหมุนของ game model ในระยะเวลาใดๆ ในโลกจริง(real world) สิ่งที่เคลื่อนย้ายและหมุน อันเนื่องมาจากแรง(forces)และแรงบิด(torques) ซึ่งใน Farseer ก็ทำเช่นเดียวกัน Objects จะถูกเรียกว่า “Body” ใช้แสดงแทนทุกสรรพสิ่งใน real world แรงและแรงบิดจะมีผลกับ body เพื่อตอบสนองให้เป็นไปตามกฎทางฟิสิกส์ 2D ตำแหน่งและการหมุนของ body เหล่านี้ถูกนำมาใช้ในการปรับปรุง game model
สำหรับ game loop ที่ง่ายที่สุด มันจะมีขั้นตอนการทำงานแบบนี้

1. เพิ่ม Body object ไปยัง simulator

2. เริ่มต้น Game Loop

1. กระทำแรงและแรงบิดกับ Body

2. ปรับปุง simulator

3. จบ Game Loop

Body โดยการออกแบบใดๆที่ไม่ใช่ geometry ในโลกของ 2D  แล้วมันจึงไม่มีแนวคิดของการชนกัน(collisions) เกิดขึ้น
สำหรับการชนกันใน Farseer เป็นวัตถุ “Geometry”  วัตถุ geometric สามารถใช้เป็น 2D polygon  และสามารถเป็นได้ทั้งเว้า(concave )หรือนูน(convex)ได้ โดยจะกำหนดด้วย  set ของจุด(vertices) หนึ่งหรือมากกว่าของรูปทรงเรขาคณิต(geometries) ที่จะแนบมากับ body เพื่อที่จะให้ body รับรู้ได้เชิงเรขาคณิต(geometrical) นี้จะช่วยให้ Body มีส่วนร่วมในการชนกันกับ body อื่นๆได้

Body

Body เป็น physics object หลักใน Farseer กฏ physics เรื่องของแรง, แรงบิด และแรงกระตุ้นนำไปใช้กับ body และ body ตอบสนองโดยการเคลื่อนย้ายอย่างสอดคล้องกัน
Body ไม่ได้มีรูปแบบของการรับรู้การปะทะกันใด ๆ ได้ด้วยตัวเอง เมื่อต้องการสร้าง body คุณมักจะใช้ Body Factory ช่วยสร้าง แต่ในการสร้างครั้งแรกนี้ ผมจะแสดงให้คุณดูการสร้าง body ด้วยตัวเอง

World theMatrix = new World(Vector2.Zero);//สร้างโลก theMatrix  กำหนดให้แรงดึงดูด(gravity)เท่ากับ 0
Body myBody = new Body(theMatrix);//สร้าง myBody และกำหนดให้ myBody อยู่ในโลก theMatrix
myBody.Mass = mass;//มีมวลเท่ากับ 1
myBody.Position = new Vector2(100, 200);//กำหนด location ที่พิกัด 100, 200

สิ่งหนึ่งที่ต้องรู้เกี่ยวกับ Body ก็คือว่าตำแหน่งของ body เป็นจะสัมพันธ์กับศูนย์กลางของร่างกาย ดูภาพประกอบ

มันมีความเกี่ยวข้องกับการวางตำแหน่งและ code การวาดรูปของคุณ เมื่อคุณกำหนดต่ำแหน่งให้ Body ของคุณ คุณจะต้องไปยังตำแหน่งที่มันเทียบกับตรงจุดศูนย์กลางของ body นอกจากนี้เมื่อคุณต้องการวาด body เข้าสู่หน้าจอ, ให้แน่ใจว่าคุณวาดมันให้สัมพันธ์กับศูนย์กลางแล้ว

Body Factory

คุณสร้าง body ด้วย factory แบบนี้

Body rectBody = BodyFactory.CreateRectangle(theMatrix, 100, 100, 1);//ใช้ BodyFactory สร้าง body แบบ สี่เหลี่ยมขนาด 100 x 100 และมีความหนาแน่น เท่ากับ 1

เรามาดูค่า ความเฉื่อย (inertia) โดย Farseer ได้คำนวณให้เราเรียบร้อยแล้วคือ

Console.WriteLine(rectBody.Inertia);//16666667.0 หรือ I = m(h*h + w*w)/12

Shape

Shape คือสิ่งที่ขยายจุดในพื้นที่ที่เป็นรูปร่าง 2d ชุดของจุดที่อยู่บน shape แล้วลากตัดกันกลายเป็นจุดกึ่งกลางของ shape(centroid) และสิ่งที่ต้องการพื้นที่, ความเฉื่อย และ มวลจะถูกคำนวณสำหรับ shape

Fixture

Fixture จะ attaches (fix) shape เข้ากับ body เพื่อให้ centroid ของ shape กลายเป็นตำแหน่งของ body เมื่อใดก็ตามที่คุณย้าย body shape ก็ย้ายตามไปด้วย เมื่อการปะทะกันเกิดขึ้นกับ shape แรงจะถูกคำนวณและนำไปใช้ใน body
Code ข้างล่างนี้เป็นขั้นตอนการสร้าง Body, Shape และ Fixture ง่ายๆ

World theMatrix = new World(Vector2.Zero);//ระบุแรงดึงดูด(gravity)เท่ากับ 0
Body myBody = BodyFactory.CreateBody(theMatrix);
myBody.BodyType = BodyType.Dynamic;//ให้มันเป็นแบบ dynamic (สามารถเครื่อนที่ได้)
CircleShape circleShape = new CircleShape(0.5f, 1f);//สร้างรูปร่างวงกลม
Fixture fixture = myBody.CreateFixture(circleShape);//Fix body และ shape เข้าด้วยกันโดยใช้ function CreateFixture

ปฏิกิริยาโต้กลับเมื่อมีวัตถุชนกัน(Reacting to a collision)

เราสามารถรู้หรือได้รับการแจ้งเตือนกลับ(callback)การชนกันของวัตถุใดๆได้สองวิธี

1. OnBroadphaseCollision คือ มันจะตรวสอบทุกๆจุดบน body ของวัตถุว่าเกิดการชนกันมั้ยตามรูปแบบของ tree  AABB ซึ่งบางจุดคุณก็ต้องการที่จะรู้ว่าร่างกายของวัตถุบนตัวเกมส์ของคุณนั้นอยู่ใกล้กัน หรือชนกันรึยัง คุณสามารถเขียน code ใน event OnBroadphaseCollision  ได้เลยเพื่อตรวจสอบสิ่งเหล่านี้ code วิธีใช้ bind event ก็ประมาณข้างล่างนี้ครับ

protected override void LoadContent()
{

 mWorld.ContactManager.OnBroadphaseCollision += MyOnBroadphaseCollision;

}

public void MyOnBroadphaseCollision(ref FixtureProxy fp1, ref FixtureProxy fp2)
{

}

2 OnCollision event นี้มันจะแจ้งเตือนเมื่อวัตถุชนกันแล้วเท่านั้น ซึ่งเจ้าตัวนี้จะคำนวนได้ถูกต้องกว่า OnBroadphaseCollision แต่ก็ต้องจ่ายเพิ่ม เพื่อคำนวณมากขึ้น นอกจากที่เราตรวจสอบการชนกัน เรายังสามารถยกเลิกการชนกันได้ด้วย code ตัวอย่าง bind event ก็ตามข้างล่างนี้ครับ

protected override void LoadContent()
{

Fixture myFixture = FixtureFactory.CreateCircle(_world, 0.5f, 1);
myFixture.OnCollision += MyOnCollision;

}

public bool MyOnCollision(Fixture f1, Fixture f2, Contact contact)
{

//ส่วนนี้ผมต้องการให้การชนกันนั้นเกิดขึ้นจึง return เป็น true
return true;

}

ครับผมก็ขอแนะนำเพียงเท่านี้ละกันครับ สำหรับตัวอย่างอื่นๆ และวิธีใช้งาน Farseer Physics Engine อีกมากมายคุณไปดูเพิ่มเติมได้ที่ http://farseerphysics.codeplex.com/ ขอให้สนุกกับการสร้างเกมส์ครับ

ขอบคุณครับ

#:P 

“จงลงมือทำทันทีเพราะ แรงบันดาลใจมีวันหมดอายุ”

REWORK

Advertisements

#2d, #game