Oop lab/objects co-ordination
- หน้านี้เป็นส่วนหนึ่งของ oop lab
มีสองแนวทางหลัก ๆ ในการจัดการประสานงานระหว่าง object ในเกม
- Game เป็นตัวประสานงานจัดการทั้งหมด
- ให้ object ต่าง ๆ จัดการกันเอง และแจ้ง Game เฉพาะเมื่อเกิดเหตุการณ์สำคัญ
อย่างไรก็ตาม ไม่ใช่ว่าแต่ละเกมจะต้องมีรูปแบบในการติดต่อแบบเดียว ในเกมหนึ่ง ๆ อาจจะมีทั้งส่วนที่ Game เป็นคนจัดการและส่วนที่ object จัดการกันเองด้วยก็ได้
เนื้อหา
Game เป็นตัวประสานงานทั้งหมด
เกมที่เราเขียนมาทั้งหมด โดยมากจากอยู่ในรูปแบบนี้ ทั้ง Ship game และ Flappy dot
Object ติดต่อกันเอง
การที่ object จะจัดการกิจกรรมอื่น ๆ ได้เองนั้น object จะต้องอ้างถึง object อื่น ๆ ที่เกี่ยวข้องได้ด้วย นอกจากนี้ ในบางครั้งที่เกิดเหตุการณ์ที่สำคัญ เช่น game over แล้ว object จะต้องสามารถแจ้งผลต่าง ๆ ให้กับ Game ได้ด้วย
การอ้างถึงวัตถุอื่น ๆ ในเกม
สามารถดำเนินการได้หลายแบบ
1. เก็บไว้เป็น field
ในกรณีที่ object ของคุณมีจำนวนไม่มาก คุณอาจจะเก็บ field ของวัตถุอื่นไว้ใน object ก็ได้ ยกตัวอย่างเช่น ถ้าคุณมีผู้เล่นสองคน อาจจะเก็บผู้เล่นอีกฝ่ายเป็น field ได้
class Player {
private Player otherPlayer = null;
//...
public setOtherPlayer(player) {
otherPlayer = player;
}
//...
public isHit() {
//... now you can access the other player with otherPlayer field.
}
}
ในส่วน init ใน Game อาจเป็นดังนี้
public init() {
player1 = new Player();
player2 = new Player();
player1.setOtherPlayer(player2);
player2.setOtherPlayer(player1);
}
2. อ้างผ่านทาง Game
ถ้าเราต้องการอ้าง object ในเกมที่เปลี่ยนไปมา เช่น monster เพิ่มขึ้นเรื่อย ๆ หรือกระสุนที่เปลี่ยนไปมา ตัว object เอง จะไม่สามารถเก็บวัตถุพวกนี้ได้ (เพราะว่ามีการแก้ไขตลอด) อีกทางที่เราทำได้คืออ้างถึงผ่านทาง Game
อย่างไรก็ตามถ้าเราต้องการใช้วิธีนี้ เราจะต้องให้ object อ้างถึง Game ได้ด้วย โดยทำได้สองแบบหลัก ๆ คือ
2.1 เพิ่ม field game ในวัตถุ
class Player {
private Game game;
public Player(Game game) {
//...
this.game = game;
}
}
และกำหนดค่าให้เมื่อสร้าง object เหล่านี้
public void init() {
//...
player1 = new Player(this);
}
2.2 อ้างผ่านคลาส Game
ในคลาส game ของเรา เราอาจจะมี static method เพื่ออ้างถึง instance ของคลาสได้
class MySampleGame extends BasicGame {
private static MySampleGame currentGame = null;
//...
public static getCurrentGame() {
return MySampleGame.currentGame;
}
public static void main(String[] args) {
try {
MySampleGame.currentGame = new MySampleGame("Super Ship Game");
AppGameContainer appgc = new AppGameContainer(MySampleGame.currentGame);
appgc.setDisplayMode(640, 480, false);
appgc.start();
} catch (SlickException e) {
e.printStackTrace();
}
}
}
โดยคลาส Player จะสามารถอ้างถึง game ได้ โดยสั่งเช่น
game = MySampleGame.getCurrentGame();
ลักษณะการเขียนแบบนี้ ถ้าเขียนให้รัดกุมขึ้นสามารถอ่านรายละเอียดเพิ่มได้ที่ Singleton Pattern จาก wikipedia
เมื่อเราอ้างถึง game ได้แล้ว เราอาจจะเพิ่มเมท็อดในการอ้างถึงวัตถุต่าง ๆ ในเกม เช่น
class MySampleGame extends BasicGame {
private LinkedList<Monster> monsters;
public List<Monster> getMonsters() {
return monsters;
}
}
โค้ด Player อาจเป็นดังนี้
public boolean isHit() {
//--------------------------------------
// approach 1: keep field
List<Monster> monsters = game.getMonsters();
//--------------------------------------
// approach 2: get it from class Game
List<Monster> monsters = MySampleGamge.getMonsters();
for (Monster monster : monsters) {
// doSomething....
}
}
การแจ้งเหตุการณ์
เมื่อมีเหตุการณ์ที่เราจำเป็นต้องแจ้งกับ game วิธีที่ทำได้ง่าย ๆ ถ้าเราสามารถอ้างถึงคลาส game ได้ คือการให้ object เรียกเมท็อดที่ต้องการในคลาส game
ยกตัวอย่างเช่น เราอาจจะสร้างเมท็อด monsterHit ในคลาส MySampleGame
class MySampleGame externs BasicGame {
public void monsterHit(Monster monster) {
//....
}
}
จากนั้นในเมท็อดที่ object เราก็สามารถเรียกเมท็อดดังกล่าวได้า