ผลต่างระหว่างรุ่นของ "01204223/kivy"

จาก Theory Wiki
ไปยังการนำทาง ไปยังการค้นหา
 
(ไม่แสดง 25 รุ่นระหว่างกลางโดยผู้ใช้คนเดียวกัน)
แถว 1: แถว 1:
 +
เอกสารส่วนนี้ดัดแปลงมาจาก [http://kivy.org/docs/tutorials/pong.html Pong Game Tutorial]
 +
 
== ติดตั้ง kivy ==
 
== ติดตั้ง kivy ==
 
การติดตั้ง สั่งคำสั่งต่อไปนี้ใน shell (อย่าลืม login เครือข่ายนนทรีก่อน)
 
การติดตั้ง สั่งคำสั่งต่อไปนี้ใน shell (อย่าลืม login เครือข่ายนนทรีก่อน)
  
 +
sudo apt-get update
 
  sudo apt-get install python-setuptools python-pygame python-opengl \
 
  sudo apt-get install python-setuptools python-pygame python-opengl \
 
   python-gst0.10 python-enchant gstreamer0.10-plugins-good python-dev \
 
   python-gst0.10 python-enchant gstreamer0.10-plugins-good python-dev \
แถว 8: แถว 11:
 
จากนั้นสั่ง  
 
จากนั้นสั่ง  
  
 +
sudo pip install --upgrade cython
 
  sudo easy_install kivy
 
  sudo easy_install kivy
  
แถว 45: แถว 49:
 
         text: "hello"
 
         text: "hello"
 
</pre>
 
</pre>
 +
 +
ทดลองเรียก python main.py  จะเห็นหน้าจอที่มีคำว่า hello
 +
 +
แฟ้ม <tt>pong.kv</tt> จะถูกอ่านโดยอัตโนมัติโดย App ที่ชื่อ <tt>PongApp</tt>
 +
 +
=== เพิ่มลูกบอล ===
 +
 +
เราจะเพิ่มคลาส <tt>PongBall</tt> ลงใน main.py
 +
 +
class PongBall(Widget):
 +
    pass
 +
 +
จากนั้นแก้ไข <tt>pong.kv</tt> โดยเพิ่มข้อมูลเกี่ยวกับการวาดวัตถุของคลาส <tt>PongBall</tt> และเพิ่มลูกบอลลงใน widget <tt>PongGame</tt>
 +
 +
<pre>
 +
#:kivy 1.7.1
 +
 +
<PongBall>:
 +
    size: 50, 50
 +
    canvas:
 +
        Ellipse:
 +
            pos: self.pos
 +
            size: self.size
 +
 +
<PongGame>:   
 +
    Label:
 +
        font_size: 70 
 +
        center_x: (root.width * 3) / 4
 +
        top: root.top - 50
 +
        text: "hello"
 +
 +
    PongBall:
 +
        center: self.parent.center
 +
</pre>
 +
 +
จากนั้นทดลองรัน
 +
 +
== ลูกบอลเคลื่อนที่: Clock, properties ==
 +
 +
ในส่วนนี้เราจะทำให้ลูกบอลเคลื่อนที่ได้ มีกิจกรรมที่เราต้องทำ 3 ขั้นตอน
 +
 +
=== 1. การปรับสถานะเกม ===
 +
เกมทั่วไปที่มีการเคลื่อนไหวจะมีการเปลี่ยนตำแหน่งวัตถุต่าง ๆ ตลอดเวลา ในการเขียนโปรแกรมจริง ๆ นั้น เราไม่สามารถปรับตำแหน่งตลอดเวลาได้ แต่เราจะใช้การตั้งเวลาให้ระบบเรียกฟังก์ชันในการปรับตำแหน่งของเราเป็นระยะ
 +
 +
เราจะสร้างเมท็อด <tt>update</tt> ในคลาส <tt>PongGame</tt> เพื่อปรับตำแหน่งลูกบอล
 +
 +
<pre>
 +
class PongGame(Widget):
 +
 +
    def update(self, dt):
 +
        pass
 +
</pre>
 +
 +
จากนั้นแก้ไขคลาส <tt>PongApp</tt> ให้ตั้งเวลาเรียกฟังก์ชันดังกล่าวทุก ๆ 1/60 วินาที
 +
 +
<pre>
 +
class PongApp(App):
 +
    def build(self):
 +
        game = PongGame()
 +
        Clock.schedule_interval(game.update, 1.0/60.0)
 +
        return game
 +
</pre>
 +
 +
สังเกตว่าเราใช้ <tt>Clock</tt> ด้วย เราจะต้อง import ชื่อดังกล่าว โดยเพิ่ม
 +
 +
from kivy.clock import Clock
 +
 +
ไว้ที่ต้นโปรแกรม
 +
 +
โปรแกรมดังกล่าวเมื่อเรียกให้ทำงาน จะไม่เห็นผลลัพธ์เปลี่ยนแปลงใด ๆ เพราะว่าเรายังไม่ได้ทำงานอะไรเลยในเมท็อด update
 +
 +
=== 2. ทำให้ PongGame รู้จักวัตถุ PongBall: properties และการกำหนด id ===
 +
การที่เมท็อด <tt>update</tt> จะปรับตำแหน่งของลูกบอลได้นั้น เมท็อดดังกล่าวจะต้องอ้างถึงวัตถุที่แทนลูกบอลให้ได้เสียก่อน
 +
 +
เราสามารถ "ร้อย" วัตถุที่สร้างขึ้นในแฟ้ม kv ให้ "มองเห็น" กันได้
 +
 +
ขั้นแรกเราจะเพิ่ม property <tt>ball</tt> ในคลาส <tt>PongGame</tt>
 +
 +
<pre>
 +
class PongGame(Widget):
 +
    ball = ObjectProperty(None)
 +
 +
    # ... (ละไว้) ...
 +
</pre>
 +
 +
ให้เพิ่มการ import ObjectProperty ที่หัวแฟ้มด้วย: <tt>from kivy.properties import ObjectProperty</tt>
 +
 +
จากนั้นปรับกฎในแฟ้ม kv ดังนี้
 +
 +
<pre>
 +
<PongGame>:   
 +
    ball: pong_ball
 +
 +
    # ...
 +
 +
    PongBall:
 +
        id: pong_ball
 +
        center: self.parent.center
 +
</pre>
 +
 +
สังเกตว่าเราให้ชื่อกับวัตถุคลาส PongBall ที่เราสร้างภายใน PongGame ว่า <tt>pong_ball</tt> จากนั้นเรากำหนด property <tt>ball</tt> ให้อ้างถึงวัตถุดังกล่าวด้วยชื่อ <tt>pong_ball</tt>
 +
 +
เพื่อทดลองว่าเราสามารถอ้างถึง <tt>pong_ball</tt> ได้จริง ๆ ให้แก้เมท็อด <tt>update</tt> ในคลาส <tt>PongGame</tt> เป็น
 +
 +
    def update(self, dt):
 +
        self.ball.x += 1
 +
 +
แล้วทดลองเรียกให้โปรแกรมทำงาน
 +
 +
=== 3.เพิ่ม property เกี่ยวกับความเร็วให้ลูกบอลและปรับทิศทางเมื่อชนขอบ ===
 +
 +
สังเกตว่าถ้าเราต้องการให้ลูกบอลเด้งไปมาได้ ลูกบอลจะต้องมีข้อมูลเกี่ยวกับความเร็ว เราจะเพิ่ม property <tt>vx</tt> และ <tt>vy</tt> ให้กับลูกบอล และเขียนเมท็อด <tt>move</tt> ที่ <tt>PongBall</tt> เพื่อปรับตำแหน่งตามความเร็วนั้น
 +
 +
<pre>
 +
class PongBall(Widget):
 +
    vx = NumericProperty(1)
 +
    vy = NumericProperty(1)
 +
 +
    def move(self):
 +
        self.x += self.vx
 +
        self.y += self.vy
 +
</pre>
 +
 +
เรากำหนดค่าเริ่มต้นของ property ทั้งสองเป็น 1
 +
 +
สังเกตว่าเราใช้ <tt>NumericProperty</tt> ดังนั้นต้องไป import ด้วย โดยแก้หัวโปรแกรมเป็น
 +
 +
from kivy.properties import ObjectProperty, NumericProperty
 +
 +
จากนั้นแก้เมท็อด <tt>update</tt> ให้เป็น
 +
 +
    def update(self, dt):
 +
        self.ball.move()
 +
 +
ทดลองเรียกให้โปรแกรมทำงาน
 +
 +
เราจะปรับทิศทางของลูกบอลเมื่อชนขอบ  ก่อนอื่นเราลองพิจารณาว่าเราควรจะเขียนเมท็อดดังกล่าวที่คลาสใด?
 +
 +
สังเกตว่าลูกบอลไม่มีข้อมูลของกรอบขอบมัน ดังนั้นถ้าเราไม่คิดจะเปลี่ยนโครงสร้างของการสร้างวัตถุเราก็ควรจะเขียนการปรับค่าดังกล่าวที่คลาสแม่ (นั่นคือ <tt>PongGame</tt>)
 +
 +
แก้คลาด <tt>PongGame</tt> โดยเพิ่มเมท็อด <tt>bounce_ball</tt> และแก้ <tt>update</tt> ดังนี้
 +
 +
<pre>
 +
class PongGame(Widget):
 +
    ball = ObjectProperty(None)
 +
 +
    def bounce_ball(self):
 +
        if self.ball.y < 0 or self.ball.y > self.height:
 +
            self.ball.vy *= -1
 +
 +
        if self.ball.x < 0 or self.ball.x > self.width:
 +
            self.ball.vx *= -1
 +
 +
    def update(self, dt):
 +
        self.ball.move()
 +
        self.bounce_ball()
 +
</pre>
 +
 +
ทดลองเรียกให้โปรแกรมทำงาน (ถ้าลูกบอลเคลื่อนที่ช้าเกินไป ให้ลองปรับความเร็วเริ่มต้นดู) สังเกตการเด้งของลูกบอลว่ามีอะไรผิดปกติหรือไม่?
 +
 +
== Observers ==
 +
เราจะแก้ปัญหาลูกบอลเด้งนอกกรอบ  แต่ก่อนที่เราจะแก้ปัญหาอะไรได้ เราจะต้องลองหาสาเหตุเสียก่อน
 +
 +
บรรดา property ที่เรากำหนดค่าใน kv rules นั้น จะมีลักษณะพิเศษ  เราจะปรับ property ของ <tt>Label</tt> (ที่ตอนแรกเป็นคำว่า hello) ที่เราระบุในตลาส <tt>PongGame</tt> 
 +
 +
แก้แฟ้ม <tt>pong.kv</tt> ดังด้านล่างแล้วทดลองเรียกให้โปรแกรมทำงาน
 +
 +
<pre>
 +
<PongGame>:   
 +
    # ...
 +
    Label:
 +
        # ...
 +
        text: str(self.parent.ball.y)
 +
    # ...
 +
</pre>
 +
 +
สังเกตว่าข้อความที่แสดงเปลี่ยนไปตาม property <tt>self.parent.ball.y</tt>  สาเหตุที่การทำงานมีลักษณะดังกล่าวเป็นเพราะว่า property ต่าง ๆ ที่เรากำหนดได้ implement [http://en.wikipedia.org/wiki/Observer_pattern Observer pattern] เอาไว้  เมื่อมันมีการเปลี่ยนค่า มันจะแจ้ง property อื่น ๆ ที่ใช้ค่าจากมันให้ปรับค่าตามโดยอัตโนมัติ
 +
 +
พยายามตอบคำถามว่าทำไมลูกบอลจึงเด้งเลยขอบด้านบน  และแก้โปรแกรมให้ลูกบอลเด้งภายในขอบเขต
 +
 +
หมายเหตุ: ทุก ๆ widget จะมี property <tt>height</tt> และ <tt>width</tt> ที่สามารถอ่านขนาดได้
 +
 +
== Events ==
 +
ในส่วนนี้เราจะทดลองปรับโปรแกรมให้รับเหตุการณ์ที่เกิดขึ้นจากผู้ใช้
 +
 +
การตอบสนองต่อเหตุการณ์ทำได้โดยเขียนฟังก์ชันที่เกี่ยวกับการแตะทำได้โดยเขียนฟังก์ชัน on_touch_down, on_touch_move, หรือ on_touch_up ([http://kivy.org/docs/api-kivy.uix.widget.html#kivy.uix.widget.Widget.on_touch_down]) 
 +
 +
เราจะย้ายลูกบอลมาที่ตำแหน่งที่มีการแตะโดยเขียนเมท็อด <tt>on_touch_down</tt> ในคลาส <tt>PongGame</tt>
 +
 +
<pre>
 +
class PongGame(Widget):
 +
    # ...
 +
    def on_touch_down(self, touch):
 +
        self.ball.center_x = touch.x
 +
        self.ball.center_y = touch.y
 +
</pre>
 +
 +
โดยปกติแล้ว สำหรับเหตุการณ์ต่าง ๆ ถ้าเราไม่ได้เขียนเมท็อดเพื่อรองรับเอาไว้ สิ่งที่ widget จะทำคือส่งต่อเหตุการณ์นั้นไปยัง widget ลูก ๆ เรื่อย ๆ จนกระทั่งมีบาง widget คืนค่า True (ถ้าไม่มี ก็จะส่งต่อจนครบ)
 +
 +
ดังนั้นบางครั้งที่เรารับเหตุการณ์เมื่อเป็น widget ลูก เราอาจจะจำเป็นต้องตรวจสอบว่าตำแหน่งที่ได้รับมานั้นอยู่ในขอบเขตหรือไม่  เราสามารถใช้เมท็อด <tt>collide_point</tt> เพื่อตรวจสอบได้
 +
 +
เราจะปรับให้ลูกบอลใหญ่ขึ้นถ้ามีการกดภายในขอบเขตของลูกบอล (ในขอบเขตกล่องสี่เหลี่ยมของลูกบอล) โดยแก้เมท็อด on_touch_move ดังนี้
 +
 +
<pre>
 +
    def on_touch_down(self, touch):
 +
        self.ball.center_x = touch.x
 +
        self.ball.center_y = touch.y
 +
 +
        if self.ball.collide_point(touch.x,touch.y):
 +
            self.ball.width += 10
 +
            self.ball.height += 10
 +
</pre>
 +
 +
สังเกตว่า ถ้าเรากดที่จุดที่ไม่อยู่ในลูกบอล แต่อยู่ในขอบเขตสี่เหลี่ยม ลูกบอลก็ยังขยายขนาด  ให้เขียนเมท็อด <tt>is_inside(self,x,y)</tt> ในคลาส <tt>PongBall</tt> เพื่อตรวจสอบว่าจุดที่กดอยู่ในวงกลมของลูกบอลหรือไม่  จากนั้นแก้เมท็อด <tt>on_touch_down</tt> ให้ใช้เมท็อดดังกล่าวแทน <tt>self.ball.collide_point(touch.x,touch.y)</tt>
 +
 +
== การติดต่อที่ซับซ้อนขึ้น ==
 +
ในส่วนนี้เราจะเรียนวิธีการ grab

รุ่นแก้ไขปัจจุบันเมื่อ 03:08, 15 กรกฎาคม 2556

เอกสารส่วนนี้ดัดแปลงมาจาก Pong Game Tutorial

ติดตั้ง kivy

การติดตั้ง สั่งคำสั่งต่อไปนี้ใน shell (อย่าลืม login เครือข่ายนนทรีก่อน)

sudo apt-get update
sudo apt-get install python-setuptools python-pygame python-opengl \
  python-gst0.10 python-enchant gstreamer0.10-plugins-good python-dev \
  build-essential libgl1-mesa-dev libgles2-mesa-dev cython python-pip

จากนั้นสั่ง

sudo pip install --upgrade cython
sudo easy_install kivy

ทดลองโปรแกรมด้านล่าง

ให้สร้างไดเร็กทอรีย่อย จากนั้นป้อนโปรแกรมด้านล่างลงในแฟ้ม main.py

from kivy.app import App
from kivy.uix.widget import Widget

class PongGame(Widget):
    pass

class PongApp(App):
    def build(self):
        return PongGame()

if __name__ == '__main__':
    PongApp().run()

Kv Language และการสร้าง widget

Kivy แยกส่วนออกแบบหน้าจอออกมาเป็นแฟ้มนามสกุล kv ในส่วนนี้เราจะทดลองการใช้แฟ้มดังกล่าว และแนวคิดพื้นฐานเกี่ยวกับการตอบสนอง event และ observer patterns

เพิ่มแฟ้มชื่อ pong.kv ในไดเร็กทอรี

#:kivy 1.7.1

<PongGame>:    
    Label:
        font_size: 70  
        center_x: (root.width * 3) / 4
        top: root.top - 50
        text: "hello"

ทดลองเรียก python main.py จะเห็นหน้าจอที่มีคำว่า hello

แฟ้ม pong.kv จะถูกอ่านโดยอัตโนมัติโดย App ที่ชื่อ PongApp

เพิ่มลูกบอล

เราจะเพิ่มคลาส PongBall ลงใน main.py

class PongBall(Widget):
    pass

จากนั้นแก้ไข pong.kv โดยเพิ่มข้อมูลเกี่ยวกับการวาดวัตถุของคลาส PongBall และเพิ่มลูกบอลลงใน widget PongGame

#:kivy 1.7.1

<PongBall>:
    size: 50, 50
    canvas:
        Ellipse:
            pos: self.pos
            size: self.size

<PongGame>:    
    Label:
        font_size: 70  
        center_x: (root.width * 3) / 4
        top: root.top - 50
        text: "hello"

    PongBall:
        center: self.parent.center

จากนั้นทดลองรัน

ลูกบอลเคลื่อนที่: Clock, properties

ในส่วนนี้เราจะทำให้ลูกบอลเคลื่อนที่ได้ มีกิจกรรมที่เราต้องทำ 3 ขั้นตอน

1. การปรับสถานะเกม

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

เราจะสร้างเมท็อด update ในคลาส PongGame เพื่อปรับตำแหน่งลูกบอล

class PongGame(Widget):

    def update(self, dt):
        pass

จากนั้นแก้ไขคลาส PongApp ให้ตั้งเวลาเรียกฟังก์ชันดังกล่าวทุก ๆ 1/60 วินาที

class PongApp(App):
    def build(self):
        game = PongGame()
        Clock.schedule_interval(game.update, 1.0/60.0)
        return game

สังเกตว่าเราใช้ Clock ด้วย เราจะต้อง import ชื่อดังกล่าว โดยเพิ่ม

from kivy.clock import Clock

ไว้ที่ต้นโปรแกรม

โปรแกรมดังกล่าวเมื่อเรียกให้ทำงาน จะไม่เห็นผลลัพธ์เปลี่ยนแปลงใด ๆ เพราะว่าเรายังไม่ได้ทำงานอะไรเลยในเมท็อด update

2. ทำให้ PongGame รู้จักวัตถุ PongBall: properties และการกำหนด id

การที่เมท็อด update จะปรับตำแหน่งของลูกบอลได้นั้น เมท็อดดังกล่าวจะต้องอ้างถึงวัตถุที่แทนลูกบอลให้ได้เสียก่อน

เราสามารถ "ร้อย" วัตถุที่สร้างขึ้นในแฟ้ม kv ให้ "มองเห็น" กันได้

ขั้นแรกเราจะเพิ่ม property ball ในคลาส PongGame

class PongGame(Widget):
    ball = ObjectProperty(None)

    # ... (ละไว้) ...

ให้เพิ่มการ import ObjectProperty ที่หัวแฟ้มด้วย: from kivy.properties import ObjectProperty

จากนั้นปรับกฎในแฟ้ม kv ดังนี้

<PongGame>:    
    ball: pong_ball

    # ...

    PongBall:
        id: pong_ball
        center: self.parent.center

สังเกตว่าเราให้ชื่อกับวัตถุคลาส PongBall ที่เราสร้างภายใน PongGame ว่า pong_ball จากนั้นเรากำหนด property ball ให้อ้างถึงวัตถุดังกล่าวด้วยชื่อ pong_ball

เพื่อทดลองว่าเราสามารถอ้างถึง pong_ball ได้จริง ๆ ให้แก้เมท็อด update ในคลาส PongGame เป็น

    def update(self, dt):
        self.ball.x += 1

แล้วทดลองเรียกให้โปรแกรมทำงาน

3.เพิ่ม property เกี่ยวกับความเร็วให้ลูกบอลและปรับทิศทางเมื่อชนขอบ

สังเกตว่าถ้าเราต้องการให้ลูกบอลเด้งไปมาได้ ลูกบอลจะต้องมีข้อมูลเกี่ยวกับความเร็ว เราจะเพิ่ม property vx และ vy ให้กับลูกบอล และเขียนเมท็อด move ที่ PongBall เพื่อปรับตำแหน่งตามความเร็วนั้น

class PongBall(Widget):
    vx = NumericProperty(1)
    vy = NumericProperty(1)

    def move(self):
        self.x += self.vx
        self.y += self.vy

เรากำหนดค่าเริ่มต้นของ property ทั้งสองเป็น 1

สังเกตว่าเราใช้ NumericProperty ดังนั้นต้องไป import ด้วย โดยแก้หัวโปรแกรมเป็น

from kivy.properties import ObjectProperty, NumericProperty

จากนั้นแก้เมท็อด update ให้เป็น

    def update(self, dt):
        self.ball.move()

ทดลองเรียกให้โปรแกรมทำงาน

เราจะปรับทิศทางของลูกบอลเมื่อชนขอบ ก่อนอื่นเราลองพิจารณาว่าเราควรจะเขียนเมท็อดดังกล่าวที่คลาสใด?

สังเกตว่าลูกบอลไม่มีข้อมูลของกรอบขอบมัน ดังนั้นถ้าเราไม่คิดจะเปลี่ยนโครงสร้างของการสร้างวัตถุเราก็ควรจะเขียนการปรับค่าดังกล่าวที่คลาสแม่ (นั่นคือ PongGame)

แก้คลาด PongGame โดยเพิ่มเมท็อด bounce_ball และแก้ update ดังนี้

class PongGame(Widget):
    ball = ObjectProperty(None)

    def bounce_ball(self):
        if self.ball.y < 0 or self.ball.y > self.height:
            self.ball.vy *= -1

        if self.ball.x < 0 or self.ball.x > self.width:
            self.ball.vx *= -1

    def update(self, dt):
        self.ball.move()
        self.bounce_ball()

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

Observers

เราจะแก้ปัญหาลูกบอลเด้งนอกกรอบ แต่ก่อนที่เราจะแก้ปัญหาอะไรได้ เราจะต้องลองหาสาเหตุเสียก่อน

บรรดา property ที่เรากำหนดค่าใน kv rules นั้น จะมีลักษณะพิเศษ เราจะปรับ property ของ Label (ที่ตอนแรกเป็นคำว่า hello) ที่เราระบุในตลาส PongGame

แก้แฟ้ม pong.kv ดังด้านล่างแล้วทดลองเรียกให้โปรแกรมทำงาน

<PongGame>:    
    # ...
    Label:
        # ...
        text: str(self.parent.ball.y)
    # ...

สังเกตว่าข้อความที่แสดงเปลี่ยนไปตาม property self.parent.ball.y สาเหตุที่การทำงานมีลักษณะดังกล่าวเป็นเพราะว่า property ต่าง ๆ ที่เรากำหนดได้ implement Observer pattern เอาไว้ เมื่อมันมีการเปลี่ยนค่า มันจะแจ้ง property อื่น ๆ ที่ใช้ค่าจากมันให้ปรับค่าตามโดยอัตโนมัติ

พยายามตอบคำถามว่าทำไมลูกบอลจึงเด้งเลยขอบด้านบน และแก้โปรแกรมให้ลูกบอลเด้งภายในขอบเขต

หมายเหตุ: ทุก ๆ widget จะมี property height และ width ที่สามารถอ่านขนาดได้

Events

ในส่วนนี้เราจะทดลองปรับโปรแกรมให้รับเหตุการณ์ที่เกิดขึ้นจากผู้ใช้

การตอบสนองต่อเหตุการณ์ทำได้โดยเขียนฟังก์ชันที่เกี่ยวกับการแตะทำได้โดยเขียนฟังก์ชัน on_touch_down, on_touch_move, หรือ on_touch_up ([1])

เราจะย้ายลูกบอลมาที่ตำแหน่งที่มีการแตะโดยเขียนเมท็อด on_touch_down ในคลาส PongGame

class PongGame(Widget):
    # ...
    def on_touch_down(self, touch):
        self.ball.center_x = touch.x
        self.ball.center_y = touch.y

โดยปกติแล้ว สำหรับเหตุการณ์ต่าง ๆ ถ้าเราไม่ได้เขียนเมท็อดเพื่อรองรับเอาไว้ สิ่งที่ widget จะทำคือส่งต่อเหตุการณ์นั้นไปยัง widget ลูก ๆ เรื่อย ๆ จนกระทั่งมีบาง widget คืนค่า True (ถ้าไม่มี ก็จะส่งต่อจนครบ)

ดังนั้นบางครั้งที่เรารับเหตุการณ์เมื่อเป็น widget ลูก เราอาจจะจำเป็นต้องตรวจสอบว่าตำแหน่งที่ได้รับมานั้นอยู่ในขอบเขตหรือไม่ เราสามารถใช้เมท็อด collide_point เพื่อตรวจสอบได้

เราจะปรับให้ลูกบอลใหญ่ขึ้นถ้ามีการกดภายในขอบเขตของลูกบอล (ในขอบเขตกล่องสี่เหลี่ยมของลูกบอล) โดยแก้เมท็อด on_touch_move ดังนี้

    def on_touch_down(self, touch):
        self.ball.center_x = touch.x
        self.ball.center_y = touch.y

        if self.ball.collide_point(touch.x,touch.y):
            self.ball.width += 10
            self.ball.height += 10

สังเกตว่า ถ้าเรากดที่จุดที่ไม่อยู่ในลูกบอล แต่อยู่ในขอบเขตสี่เหลี่ยม ลูกบอลก็ยังขยายขนาด ให้เขียนเมท็อด is_inside(self,x,y) ในคลาส PongBall เพื่อตรวจสอบว่าจุดที่กดอยู่ในวงกลมของลูกบอลหรือไม่ จากนั้นแก้เมท็อด on_touch_down ให้ใช้เมท็อดดังกล่าวแทน self.ball.collide_point(touch.x,touch.y)

การติดต่อที่ซับซ้อนขึ้น

ในส่วนนี้เราจะเรียนวิธีการ grab