ก่อนอธิบายนะครับ ขอบอกนิดนึงว่า
โค้ดที่พี่แอนเขียน.. มีจุดที่ยังไม่ดีอยู่ครับ (คือมันไม่เหมาะสมน่ะครับ)
โค้ดเก่า
onClipEvent (enterFrame) {
with (_root.player) {
//
// บังคับ
if (Key.isDown(Key.DOWN)) {
_y += 3;
}
if (Key.isDown(Key.UP)) {
_y -= 3;
}
if (Key.isDown(Key.LEFT)) {
_x -= 3;
}
if (Key.isDown(Key.RIGHT)) {
_x += 3;
}
//
// เช็กขอบ
trace(this._name);
if (this.hitTest(getBounds(_root).xMax, _y, true)) {
_x -= 2;
}
if (this.hitTest(getBounds(_root).xMin, _y, true)) {
_x += 2;
}
if (this.hitTest(_x, getBounds(_root).yMax, true)) {
_y -= 2;
}
if (this.hitTest(_x, getBounds(_root).yMin, true)) {
_y += 2;
}
}
}
ตรงไหน มาดูัโค้ดกันก่อนครับ
if (this.hitTest(getBounds(_root).xMax, _y, true)) {
_x -= 2;
}
จากโค้ดเราจะได้ว่า
- this หมายถึงตัว "อ" และ
- คำสั่งที่ไม่ได้ขึ้นต้นด้วย this จะมหายถึง "ลูกบอล"
เพราะ มีการคร่อมด้วย
with(_root.player){
//
}
ดังนั้น
Property ที่อยู่ข้างใน with และไม่ได้ขึ้นด้วย this หรือ _root จะหมายถึง Property ของ player ทั้งหมดส่วนตรงโค้ด แปลเอาตรงๆ เลยนะครับ
ถ้า ตัว "อ" (this) ไปชนกับ
- พิกัด y ของลูกบอล และ พิกัดจุด xMax ของ ลูกบอล บนพิกัดของ _root (เลื่อนไปดูแผนภาพที่ผมทำไว้ก่อนหน้านี้ครับ ว่าพิกัดของ _root หรือ Stage เป็นยังไง)
- โดยดูรูปร่างของวัตถุด้วย (ลูกบอลเป็นวงกลม)
แล้ว.. ให้ลดพิกัด x ของลูกบอลลง 2
โดย
xMax เนี่ยคืออะไร?
xMax คือขอบขวาของ ลูกบอล ครับ (ในกรณีนี้) แต่ปกติถ้าไม่ใส่ _root และลุกบอลอยู่ใต้ MovieClip อื่น
มันจะอ้างตำแหน่งจาก MovieClip ตัวนั้นแทนครับ
ดังนั้น ถ้าเราใส่
_root ลงไปด้วย ก็จะเป็นการบอกว่า ให้แปลงพิกัดของลูกบอล เป็นพิกัดที่วัดจาก 0,0 ของ _root ครับ
(ไปดูแผนภาพประกอบนะครับ)
(อันอื่นๆ ก็ใกล้เคียงกัน)
แต่!! (อีกที) เขียนแบบนี้
ไม่ดีครับ (ผมไม่ได้บอกว่า
ผิด นะครับ) เพราะ
1. สิ่งที่ควรเขียนบนลูกบอล เอาไปใส่บน "อ"- แบบนี้ถือว่าเป็นการเขียนสคริปต์ที่ "ผิดจุดประสงค์" ครับผม เพราะฉะนั้น ถ้าจะสั่งลูกบอล ก็ควรเขียนสคริปต์ที่ลูกบอลครับ
- เอาให้ลึกกว่านี้ เค้าจะเรียกว่า การ Delegate งานครับ หรือก็คือ การแจกแจงงานที่ถูกต้อง ให้คนที่รับงานที่ถูกต้อง หรือ The right job to the right man ประมาณนี้ครับ
2. ไม่ควรเขียน getBounds ซ้ำหลายรอบ - เพราะอะไร? เพราะว่า ในทางทฤษฎีแล้ว ตัวโปรแกรม จะต้องทำการ getBounds ใหม่ทุกครั้งที่มีการเรียก ดังนั้นใน 1 รอบ enterFrame มันจะต้องทำคำสั่ง getBounds ถึง 4 รอบเลยทีเดียว!!
- คำนวณเอาง่ายๆ ครับ ถ้าเล่นสคริปต์นี้ไป 3 วินาที จะทำงาน getBounds ทั้งหมด
3 x 30 x 4 = 270 ครั้ง!!!
และถ้า getBounds 1 คำสั่ง ใช้เวลาทำงาน 10 มิลลิวินาที ก็จะหมายความว่า เราใช้เวลารันสคริปต์นี้
270 x 10 = 2700 มิลลิวินาที!! = 2.7 วินาที นี่นับเฉพาะ getBounds นะครับ ถ้ามีคำสั่งอื่นอีก ก็จะเกิดการ "หน่วง"
- แต่นี่เป็นการเทียบง่ายๆ ครับ จริงๆ อาจทำงานเร็วกว่านี้เยอะมากๆ

- เพราะฉะนั้น อะไรที่คงที่ ก็เรียกครั้งเดียวพอครับ
- ขั้นนี้เรียกว่าการ Optimize ครับ ปรับแต่งโค้ด อะไรที่คิดว่าทำให้โปรแกรมหน่วง ก็พยายามลดลงๆ เป็นต้น
หลังจากปรับโค้ดพี่แอนแล้ว จะได้แบบนี้ครับ
onClipEvent(load){
//สั่งใช้ getBounds ที่เดียว ตอนที่โหลดโปรแกรมเสร็จ
var ballBounds = this.getBounds(_root);
}
onClipEvent (enterFrame) {
//
// บังคับ
if (Key.isDown(Key.DOWN)) {
_y += 3;
}
if (Key.isDown(Key.UP)) {
_y -= 3;
}
if (Key.isDown(Key.LEFT)) {
_x -= 3;
}
if (Key.isDown(Key.RIGHT)) {
_x += 3;
}
//
// เช็กขอบ
//เช็คว่า่ "อ" ชนกับลูกยอบตรงไหน โดยเรียกผ่าน ballBounds วึ่ง ballBounds จะเก็บค่า xMin, xMax, yMin, yMax ทั้งหมด
//และในการเรียก ballBounds แต่ละรอบ จะไม่ได้มีการเรียก getBounds ใหม่ แต่จะเอาค่าที่เก็บไว้มาใช้ only
if (_root.อ.hitTest(ballBounds.xMax, _y, true)) {
trace("xMax");
_x -= 2;
}
if (_root.อ.hitTest(ballBounds.xMin, _y, true)) {
trace("xMin");
_x += 2;
}
if (_root.อ.hitTest(_x, ballBounds.yMax, true)) {
_y -= 2;
}
if (_root.อ.hitTest(_x, ballBounds.yMin, true)) {
_y += 2;
}
}
โค้ดนี้เอาไปใส่ที่
player ที่เดียว ส่วนตัว "อ" ก็ใส่ Instance Name ว่า
อ ครับ