ผลต่างระหว่างรุ่นของ "Oop lab/oop in python"
Jittat (คุย | มีส่วนร่วม) |
Jittat (คุย | มีส่วนร่วม) |
||
แถว 207: | แถว 207: | ||
=== แบบฝึกหัด: ชนและสะท้อนที่ขอบ === | === แบบฝึกหัด: ชนและสะท้อนที่ขอบ === | ||
+ | |||
+ | ตอนนี้ลูกบอลเมื่อวิ่งทะลุขอบจอแล้วจะหายไปเลย ให้เพิ่มการตรวจสอบว่าลูกบอลทะลุจอไปแล้วแล้วปรับให้ลูกบอลเสมือนเด้งกลับมา | ||
<syntaxhighlight lang="python"> | <syntaxhighlight lang="python"> |
รุ่นแก้ไขเมื่อ 02:04, 1 กันยายน 2560
- หน้านี้เป็นส่วนหนึ่งของวิชา Oop lab
เราจะหัดเขียน OOP กันผ่านทางตัวอย่าง โดยเราจะเขียนโปรแกรมแสดงผลเป็นกราฟิกส์โดยใช้ไลบรารีชื่อ Arcade ซึ่งต้องการ Python 3.6 เป็นอย่างน้อย
เนื้อหา
ติดตั้ง Arcade
เราจะใช้ game library ชื่อ arcade ในการพัฒนาเกม
Python 3.6
ทดลองเรียก
python --version
ถ้าระบบตอบว่าเป็นเวอร์ชั่นสูงกว่าหรือเท่ากับ 3.6 ก็ไปทำขั้นตอนการติดตั้ง pip ได้เลย ไม่เช่นนั้นให้ไปติดตั้ง Python 3.6 ตามวิธีต่อไปนี้
ติดตั้ง Python 3.6 บน Windows
ให้ทำตามขั้นตอนในนี้ได้เลย การติดตั้ง arcade อย่าลืมเลือกให้ลง python ใน path ด้วย
ติดตั้ง Python 3.6 บน Ubuntu (รุ่นตั้งแต่ 16.10 ขึ้นไป)
สั่ง
sudo apt-get update sudo apt-get install python3.6
เวลาเรียกใช้ให้เรียก python3.6
ติดตั้ง Python 3.6 บน Ubuntu เก่า
sudo add-apt-repository ppa:jonathonf/python-3.6 sudo apt-get update sudo apt-get install python3.6
ติดตั้ง pip/pip3
pip เป็นโปรแกรมสำหรับติดตั้ง library บน Python ในระบบที่มี python3 พร้อม ๆ กับ python2 เราจะเรียก pip3 เพื่อให้ติดตั้ง library ลงในส่วนของ python3
ให้ลองเรียก
pip
หรือ
pip3
ถ้ามีโปรแกรมแล้วก็ข้ามส่วนติดตั้ง pip ได้เลย
1. ติดตั้ง pip บน Windows
pip จะมาพร้อมกับการติดตั้ง python ให้เลือก option ดังกล่าวด้วย ถ้าเปิด command แล้วเรียก pip ขึ้นก็แสดงว่าได้ติดตั้งเรียบร้อย ถ้าไม่มี ให้ลองติดตั้ง python3 อีกครั้ง และให้เลือก pip ในหน้า Optional Features ด้วย
- ดูรายละเอียดการติดตั้งที่นี่ arcade installation บน windows
2. ติดตั้ง pip3 บน Linux
ให้ติดตั้ง pip3 และโปรแกรมประกอบอื่น ๆ โดยสั่ง
sudo apt install -y python3-dev python3-pip libjpeg-dev zlib1g-dev
3. ติดตั้ง pip3 บน Mac
ถ้าติดตั้ง python3 แล้ว น่าจะมี pip3 มาแล้ว ทดลองเรียกดูใน terminal
บน Mac จะต้องติดตั้ง libjpg ด้วย ถ้ายังไม่มี ถ้าคุณมี homebrew อยู่แล้ว ให้สั่ง
brew install libjpeg
ถ้าไม่ได้ ให้ไปดาวน์โหลดและ install จาก [1] (เลือก libjpg)
ใช้ pip ติดตั้ง arcade
ถ้าในการติดตั้ง python เราได้ลง pip มาแล้ว เราจะสามารถติดตั้ง arcade ผ่านทาง pip ได้โดยสั่ง
sudo pip3 install arcade
ถ้าเป็น windows ให้สั่ง
pip install arcade
virtualenv
เราติดตั้ง arcade ลงใน library ของระบบเลย ซึ่งทำแบบนี้บ่อย ๆ อาจจะทำให้ library เละและตีกันได้ Python มีระบบสำหรับติดตั้ง library แยกกัน เรียกว่า virtualenv
- ยังเขียนส่วนนี้ไม่เสร็จ: to do - how to install with virtualenv
ทดสอบการติดตั้ง
ให้ copy code ด้านล่างนี้ ในไฟล์ชื่อ cirtest.py แล้วทดลองรัน
import arcade
from random import randint
SCREEN_WIDTH = 600
SCREEN_HEIGHT = 600
circle_size = 1
size_direction = 1
circle_xs = []
circle_ys = []
num_circles = 100
def random_locations():
for i in range(num_circles):
circle_xs.append(randint(10,SCREEN_WIDTH-10))
circle_ys.append(randint(10,SCREEN_HEIGHT-10))
def on_draw(delta_time):
global circle_size, size_direction
circle_size += size_direction
if circle_size > 50:
size_direction = -1
elif circle_size == 1:
size_direction = 1
arcade.start_render()
for x,y in zip(circle_xs, circle_ys):
arcade.draw_circle_outline(x, y, circle_size, arcade.color.BLACK)
def main():
random_locations()
arcade.open_window(SCREEN_WIDTH, SCREEN_HEIGHT,
"Circles")
arcade.set_background_color(arcade.color.WHITE)
arcade.schedule(on_draw, 1 / 80)
arcade.run()
if __name__ == '__main__':
main()
อธิบายบางประเด็น
- randint -- สุ่มเลขระหว่างเลขที่ระบุ ต้อง import random ก่อน
- global -- ใน Python ฟังก์ชันจะสามารถอ้างถึงตัวแปรโกลบอลได้ถ้าอ่านค่าอย่างเดียว แต่ถ้าต้องการเปลี่ยนแปลงตัวแปรโกลบอลจะต้องประกาศให้ชัดเจนว่าจะมีการใช้ตัวแปรโกลบอลนั้น ในฟังก์ชัน on_draw เราต้องการเปลี่ยนค่าขนาดวงกลมและทิศทางการเปลี่ยนค่า เราจึงต้องประกาศ
- zip -- ฟังก์ชัน zip นำลิสต์สองลิสต์มารวมเข้าด้วยกัน เช่น zip([1,2,3],['a','b','c']) ได้ผลลัพธ์เทียบเท่ากับ [(1, 'a'), (2, 'b'), (3, 'c')] มักใช้เวลาต้องการ for ไปในรายการหลายอันพร้อม ๆ กัน
- ฟังก์ชันจาก arcade
- arcade.start_render ให้เรียกก่อนจะวาดหน้าจอ จะลบหน้าจอเดิม (มีทดลองในส่วนถัดไป)
- arcade.draw_circle_outline วาดวงกลม
- arcade.open_window
- arcade.set_background_color
- arcade.schedule
- arcade.run
วงกลมขยับ
วาดวงกลม
เราจะเริ่มเขียนจากโปรแกรมที่ทำอะไรไม่ค่อยได้ ไปหาโปรแกรมที่ซับซ้อนขึ้น โปรแกรมด้านล่างวาดรูปวงกลมที่กลางหน้าจอ เขียนและเซฟไว้ในไฟล์ชื่อ cir1.py
import arcade
SCREEN_WIDTH = 600
SCREEN_HEIGHT = 600
def on_draw(delta_time):
arcade.start_render()
x = 300
y = 300
arcade.draw_circle_outline(x, y, 20, arcade.color.BLACK)
def main():
arcade.open_window(SCREEN_WIDTH, SCREEN_HEIGHT,
"Circles")
arcade.set_background_color(arcade.color.WHITE)
arcade.schedule(on_draw, 1 / 80)
arcade.run()
if __name__ == '__main__':
main()
ทดลอง: ให้ทดลองลบบรรทัด arcade.start_render() ออก ผลเป็นอย่างไร?
เคลื่อนที่
เราจะบังคับให้วงกลมเคลื่อนที่ โดยปรับค่าตำแหน่งตามความเร็วสองแกนคือ vx แทนความเร็วในแนวแกน x และ vy แทนความเร็วในแกน y
เนื่องจากเราต้องการเปลี่ยนค่าตำแหน่งวงกลมอย่างต่อเนื่อง เราจึงต้องมีตัวแปรโกลบอลเก็บค่าตำแหน่ง คือ x และ y ในฟังก์ชัน on_draw เราจะระบุว่าจะแก้ค่าตัวแปรดังกล่าวด้วย keyword global เราใส่ vx และ vy เผื่อไว้ด้วยเลย (เพราะว่าเราต้องการให้สะท้อนขอบจอ)
โค้ดของ on_draw เป็นดังนี้ บรรทัดที่ประกาศ x,y,vx,vy เป็นการกำหนดค่าให้กับตัวแปรโกลบอล
vx = 2
vy = 1
x = 300
y = 300
def on_draw(delta_time):
arcade.start_render()
global x, y, vx, vy
x += vx
y += vy
arcade.draw_circle_outline(x, y, 20, arcade.color.BLACK)
แบบฝึกหัด: ชนและสะท้อนที่ขอบ
ตอนนี้ลูกบอลเมื่อวิ่งทะลุขอบจอแล้วจะหายไปเลย ให้เพิ่มการตรวจสอบว่าลูกบอลทะลุจอไปแล้วแล้วปรับให้ลูกบอลเสมือนเด้งกลับมา
def on_draw(delta_time):
arcade.start_render()
global x, y, vx, vy
x += vx
y += vy
# ตรวจสอบตำแหน่ง ถ้าตกขอบให้เปลี่ยนทิศทาง
# hint: ให้ทำทีละแกน จะง่ายกว่า
arcade.draw_circle_outline(x, y, 20, arcade.color.BLACK)
วงกลมหลาย ๆ วง
import arcade
from random import randint
vxs = []
vys = []
xs = []
ys = []
n = 10
def initialize():
for i in range(n):
xs.append(randint(100, SCREEN_WIDTH-100))
ys.append(randint(100, SCREEN_HEIGHT-100))
vxs.append(randint(-5,5))
vys.append(randint(-5,5))
def draw_and_move_circle(i):
xs[i] += vxs[i]
ys[i] += vys[i]
arcade.draw_circle_outline(xs[i], ys[i], 20, arcade.color.BLACK)
def on_draw(delta_time):
arcade.start_render()
for i in range(n):
draw_and_move_circle(i)
def main():
initialize()
arcade.open_window(SCREEN_WIDTH, SCREEN_HEIGHT,
"Circles")
arcade.set_background_color(arcade.color.WHITE)
arcade.schedule(on_draw, 1 / 80)
arcade.run()
แยกฟังก์ชัน
def move_circle(i):
# ....
def draw_circle(i):
# ....
def on_draw(delta_time):
arcade.start_render()
for i in range(n):
move_circle(i)
draw_circle(i)
แบบฝึกหัด: ชนและสะท้อนที่ขอบ
สร้างคลาส
class Circle:
def __init__(self, x, y, vx, vy):
self.x = x
self.y = y
self.vx = vx
self.vy = vy
def move(self):
self.x += self.vx
self.y += self.vy
# เพิ่มโค้ดส่วนจัดการการชนขอบจอที่นี่ด้วย
def draw(self):
arcade.draw_circle_outline(self.x, self.y,
20, arcade.color.BLACK)
circles = []
n = 10
def initialize():
for i in range(n):
circle = Circle(randint(100, SCREEN_WIDTH-100),
randint(100, SCREEN_HEIGHT-100),
randint(-5,5),
randint(-5,5))
circles.append(circle)
def on_draw(delta_time):
arcade.start_render()
for c in circles:
c.move()
c.draw()