ผลต่างระหว่างรุ่นของ "Oop lab/objects co-ordination"
Jittat (คุย | มีส่วนร่วม) |
Jittat (คุย | มีส่วนร่วม) |
||
(ไม่แสดง 6 รุ่นระหว่างกลางโดยผู้ใช้คนเดียวกัน) | |||
แถว 77: | แถว 77: | ||
'''2.2 อ้างผ่านคลาส Game''' | '''2.2 อ้างผ่านคลาส Game''' | ||
+ | |||
ในคลาส game ของเรา เราอาจจะมี static method เพื่ออ้างถึง instance ของคลาสได้ | ในคลาส game ของเรา เราอาจจะมี static method เพื่ออ้างถึง instance ของคลาสได้ | ||
แถว 101: | แถว 102: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
+ | โดยคลาส Player จะสามารถอ้างถึง game ได้ โดยสั่งเช่น | ||
+ | |||
+ | game = MySampleGame.getCurrentGame(); | ||
+ | |||
+ | ลักษณะการเขียนแบบนี้ ถ้าเขียนให้รัดกุมขึ้นสามารถอ่านรายละเอียดเพิ่มได้ที่ [http://en.wikipedia.org/wiki/Singleton_pattern Singleton Pattern] จาก wikipedia | ||
− | + | {{กล่องเทา|'''ข้อควรระวัง''' เราควรจะใช้ static เท่าที่จำเป็น ไม่ควรเก็บทุกสิ่งทุกอย่างเป็น static public หมดเพื่อความง่ายในการอ้างถึง เพราะว่าการใช้ตัวแปรแบบ static คือการสร้างการขึ้นต่อกันกับคลาส ซึ่งจะทำให้เราทดสอบโปรแกรมยากมากในอนาคต ตัวแปรแบบ static ก็เปรียบเสมอตัวแปร global ในรูปแบบหนึ่งนั่นเอง}} | |
เมื่อเราอ้างถึง game ได้แล้ว เราอาจจะเพิ่มเมท็อดในการอ้างถึงวัตถุต่าง ๆ ในเกม เช่น | เมื่อเราอ้างถึง game ได้แล้ว เราอาจจะเพิ่มเมท็อดในการอ้างถึงวัตถุต่าง ๆ ในเกม เช่น | ||
แถว 114: | แถว 120: | ||
} | } | ||
} | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | โค้ด Player อาจเป็นดังนี้ | ||
+ | |||
+ | <syntaxhighlight lang="java"> | ||
+ | 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.... | ||
+ | } | ||
+ | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== การแจ้งเหตุการณ์ === | === การแจ้งเหตุการณ์ === | ||
+ | เมื่อมีเหตุการณ์ที่เราจำเป็นต้องแจ้งกับ game วิธีที่ทำได้ง่าย ๆ ถ้าเราสามารถอ้างถึงคลาส game ได้ คือการให้ object เรียกเมท็อดที่ต้องการในคลาส game | ||
+ | |||
+ | ยกตัวอย่างเช่น เราอาจจะสร้างเมท็อด monsterHit ในคลาส MySampleGame | ||
+ | |||
+ | <syntaxhighlight lang="java"> | ||
+ | class MySampleGame externs BasicGame { | ||
+ | public void monsterHit(Monster monster) { | ||
+ | //.... | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | จากนั้นในเมท็อดที่ object เราก็สามารถเรียกเมท็อดดังกล่าวได้ | ||
+ | |||
+ | <syntaxhighlight lang="java"> | ||
+ | public boolean isHit() { | ||
+ | //... | ||
+ | for (Monster monster : monsters) { | ||
+ | if (monster.closeTo(this)) { //... any condition you like. | ||
+ | game.monsterHit(monster) | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> |
รุ่นแก้ไขปัจจุบันเมื่อ 09:33, 22 กันยายน 2557
- หน้านี้เป็นส่วนหนึ่งของ 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
ข้อควรระวัง เราควรจะใช้ static เท่าที่จำเป็น ไม่ควรเก็บทุกสิ่งทุกอย่างเป็น static public หมดเพื่อความง่ายในการอ้างถึง เพราะว่าการใช้ตัวแปรแบบ static คือการสร้างการขึ้นต่อกันกับคลาส ซึ่งจะทำให้เราทดสอบโปรแกรมยากมากในอนาคต ตัวแปรแบบ static ก็เปรียบเสมอตัวแปร global ในรูปแบบหนึ่งนั่นเอง
เมื่อเราอ้างถึง 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 เราก็สามารถเรียกเมท็อดดังกล่าวได้
public boolean isHit() {
//...
for (Monster monster : monsters) {
if (monster.closeTo(this)) { //... any condition you like.
game.monsterHit(monster)
}
}
}