418383/418587 ภาคปลาย 2553/การบ้าน 2

จาก Theory Wiki
ไปยังการนำทาง ไปยังการค้นหา

ให้ไว้ ณ วันพุธที่ 13 ม.ค. 2554 ส่งวันศุกร์ที่ 11 ก.พ. 2554 เวลา 23.59 น. โดย zip ไฟล์ในไดเรกทอรี Breakout ส่งมาที่ pramook at gmail dot com

เริ่มต้น

งานของคุณ

1. เพิ่มไอเทมที่เก็บแล้วมีลูกบอลเพิ่มขึ้นสองลูก (20 คะแนน)

ในตอนนี้เกม Breakout ในโค้ดตั้งต้นมีไอเทมเพียงสองชนิด คือ ไอเทมที่เก็บแล้วแป้นสามารถจับและปล่อยลูกบอลได้ (ไิอเทม A) กับไอเทมที่เก็บแล้วแป้นมีความยาวมากขึ้น (ไอเทม B)

ในข้อนี้ให้คุณสร้างไอเทมชนิดใหม่ ซึ่ีงเมื่อเก็บแล้วแป้นจะปล่อยลูกบอลออกมาสองลูก ลูกหนึ่งพุ่งออกทางด้านซ้าน อีกลูกพุ่งออกทางด้านขวา ลูกบอลนี้จะต้องมีสมบัติเหมือนลูกบอลที่มีอยู่แล้วทุกประการ และเมื่อแป้นยิงลูกบอลใหม่มาแล้ว ลูกบอลเดิมสามารถที่จะหล่นออกจากฉากไปได้โดยที่ผู้เล่นจะยังไม่ตาย (กล่าวคือผู้เล่นจะตายก็ต่อเมื่อไม่มีลูกบอลเหลือในฉากแล้วเท่านั้น)

วิธีการที่ง่ายที่สุดในการทำโจทย์ข้อนี้คือการเขียน subclass ของ Item แล้ว implement เมธอด CollideWithBar ของมันให้เพิ่มลูกบอลเข้าไปสองลูกใส่ GameState

อนิเมชันของไอเทม

เ้ราได้สร้างอนิเมชันของไอเทมชนิดนี้เอาไว้ให้คุณแล้ว มันอยู่ในไฟล์ extra_balls_item.anim ใน Content ของโปรเจค BreakoutContent

แก้ไข Content Pipeline ให้อ่านไอเทมชนิดที่สามได้

Map ที่ให้ไปในเกม (ไฟล์ map-01.txt ใน BreakoutContent) สามารถใส่ไอเทมได้ 4 ชนิด (แทนด้วยตัวอักษร 1, 2, 3, 4 ตามลำดับ) แต่ในตอนนี้เกมสามารถอ่านไอเทมได้แค่ชนิด 1 กับ 2 เท่านั้น เนื่องจากใน MapReader.cs ในโปรเจค BreakoutLib มีการกำหนดเงื่อนไขดังต่ีอไปนี้

<geshi lang="csharp"> if (brickType >= 0) {

   Item item = null;
   if (itemType == 0)
       item = new LongBarItem();
   else if (itemType == 1)
       item = new MagnetBarItem();
   Brick brick = new Brick((BrickColor)brickType, x, y, item);
   map.Bricks.Add(brick);

} </geshi>

เมื่อคุณสร้างคลาสสำหรับไอเทมชนิดนี้เสร็จแล้ว ให้ไปเพิ่ม case 3 หรือ case 4 ในคำสั่ง switch ข้างบน แล้วเกมก็จะอ่านไอเทมที่คุณสร้างขึ้นมาใหม่ได้

2. เพิ่มไอเทมที่เก็บแล้วผู้เล่นสามารถยิงลูกกระสุนปืนออกจากแป้นได้ (30 คะแนน)

จงสร้างไอเทมชนิดใหม่ ซึ่ีงเมื่อเก็บแล้วลูกแป้นจะเปลี่ยนรูปร่างให้ปลายทั้งสองข้างเป็นสีเขียว เมื่อแป้นอยู่ในสภาพนี้ หากผู้ใช้กดปุ่ม spacebar แล้วแป้นจะยิงลูกกระสุนสีแดงสองลูกออกทางข้างแป้น เมื่อลูกกระสุนกระทบบล็อก "เลือด" (HP) ของบล็อกจะลดลงหนึ่ง เหมือนกับโดนลูกบอลกระทบหนึ่งครั้ง (กล่าวคือถ้าเลือกเหลือ 0 แป้นก็จะถูกทำลายได้) และเมื่อเป็นอยู่ในสถานะนี้ไปสักระยะหนึ่งมันจะกลับคือสู่สภาพเดิม

ในการทำโจทย์ข้อนี้เราแนะนำให้คุณแบ่งการทำงานเป็นสามขั้นตอน ดังนี้

  1. สร้าง GameObject สำหรับแทนลูกกระสูน
    • สร้าง subclass ของ GameObject ขึ้นมาใหม่ ชื่อ Bullet สำหรับแทนลูกกระสุน
    • เพิ่มเมธอด void CheckCollisionWithBullet(Bullet bullet) เข้่าใน GameObject แล้ว implement เมธอดนี้ให้ subclass ของ GameObject ทุกคลาส
    • สร้าง event ชื่อ BrickHitBullet เพื่อแทนเหตุการณ์ลูกกระสุนกระทบบล็อก
    • สร้างเมธอด void Visit(BrickHitBullet ev) ใน EventVisitor แล้วเขียนเมธอดนี้ให้ subclass ทุกตัวของ EventVisitor (ในตอนนี้มีสองตัวคือ GameState และ ScoreManager)
  2. สร้าง BarType ใหม่
    • BarType เป็นคลาสที่ใช้กำหนดพฤติกรรมของแป้นเมื่อมันได้รับไอเทมแบบต่างๆ
    • ให้สร้าง BarType ใหม่ที่ใช้แทนแป้นเมื่อมันสามารถยิงลูกกระสุนได้
    • เขียนเมธอด void Control (KeySensor keySensor, GameState gameState) ซึ่งรับข้อมูลเข้าทางคีย์บอร์ดจาก KeySensor แล้วควบคุมแป้นตามนั้น ในการเขียนเมธอดนี้คุณจะต้องทำให้
      • ถ้ามีลูกบอลติดอยู่กับแป้นอยู่ เมื่อกด spacebar (KeyMapping.LaunchKey ให้ยิงลูกบอลออกไปก่อน ให้ดูตัวอย่างวิธีการยิงลูกบอลจากคลาส MagnetBarType
      • ถ้าไม่มีลูกบอลติดอยู่กับแป้นเลย ให้ยิงลูกกระสุนออกสองลูก
  3. สร้าง Item ชนิดใหม่
    • สร้าง subclass ของ Item สำหรับแทนไอเทมชนิดใหม่ แล้วเขียนเมธอด PutPowerupEffectToBar เพื่อเปลี่ยนรูปแบบของแป้นไปเป็นรูปแบบที่ียิงกระสนุได้ แล้วจึงเขียนเมธอด CancelPowerupEffectToBar เพื่อคืน BarType ใ้ห้เป็น NormalBarType เมื่อหมดเวลา (ดูวิธีจับเวลาได้ที่ MagnetBarType)

ท้ายสุด อย่าลืมแก้ content pipeline ให้อ่านไอเทมชนิดใหม่ีนี้เข้ามาได้ด้วย

อนิเมชันของส่วนประกอบต่างๆ

  • ลูกกระสุน อยู่ที่ไฟล์ Breakout/BreakoutContent/bullet.anim
  • แป้นเมื่อยิงปืนได้ อยู่ืที่ไฟล์ Breakout/BreakoutContent/gun_bar_type.anim
  • ไอเทม อยู่ที่ไฟล์ Breakout/BreakoutContent/gun_item.anim

3. เพิ่มด่าน (20 คะแนน)

สร้างด่านเพิ่มขึ้นอีกสองด่าน โดยทำการสร้าง map ใหม่ 2 map โดยใช้โปรแกรมสร้าง map ที่ให้ข้างบน

แก้ไข PlayScreen และส่วนประกอบอื่นๆ ของเกมตามที่จำเป็น เพื่อให้หลังจากจบด่านแรกในเกมแล้ว เกมจะไปเริ่มต้นที่ด่านที่สองโดยอัตโนมัติ และทำเช่นเดียวกันกับด่านที่สาม และเมื่อผู้เล่นผ่านด่านที่สามแล้ว ให้แสดงฉากว่าผู้เล่นได้เคลียร์เกมแล้ว

โจทย์ข้อนี้มีวิธีทำสองวิธี

  • ให้สร้าง PlayScreen ขึ้นมาอีก 2 instance โดยให้แต่ละอันใช้ map ที่แตกต่างไป เพื่อให้ PlayScreen หนึ่งตัวแทนด่านหนึ่งด่าน (ในวิธีการนี้คุณอาจจะต้องสร้าง screen อื่นๆ เพิ่มเติมเพื่อช่วยในการเปลี่ยนฉากด้วย)
  • ให้มี PlayScreen แค่ instance เดียว แต่สร้างคลาสขึ้นมาอีกคลาสหนึ่งที่เก็บลำดับของ map ของทั้งเกมเอาไว้ แล้วให้คลาสนี้ไปเปลี่ยน map ที่ PlayScreen ใช้

4. เพิ่มเสียง (20 คะแนน)

เพิ่มเสียงเข้าไปในเกม โดยให้มีเสียงต่อไปนี้ (เสียงละ 2 คะแนน)

  • เพลงแบคกราวนด์
  • เสียงบอลชนแป้น
  • เสียงบอลชนกำแพง
  • เสียงบอลชนบล็อก
  • เสียงบล็อกโดนทำลาย
  • เสียงไอเทมชนแป้น
  • เสียงเวลาแป้นตาย
  • เสียงเวลายิงลูกกระสุน
  • เสียงเวลาลูกกระสุนกระทบแป้น
  • เพลงสั้นๆ ที่เล่นเวลาผู้เล่นผ่านด่าน

วิธีการที่ง่ายที่สุดในการทำโจทย์ข้อนี้คือเวลาจัดการ event ให้ทำการเล่นเสียง โดยถ้าคุณอยากให้เหตุำการณ์ใดมีเสียงก็ให้สร้าง subclass ของ Event สำหรับเหตุการณ์นั้นมา แล้วเขียนเมธอด HandleSpecificEvent ของ GameState ให้เล่นเสียงที่คุณต้องการ

5. ทำให้เกมสวยงาม (10 คะแนน)

เปลี่ยนหน้า Title, หน้า Game Over, หน้าจอระหว่างเล่นเกม, ฯลฯ ให้เป็นไปตามที่คุณชอบ