ผลต่างระหว่างรุ่นของ "Oop lab/oop in python"

จาก Theory Wiki
ไปยังการนำทาง ไปยังการค้นหา
แถว 184: แถว 184:
  
 
เราจะบังคับให้วงกลมเคลื่อนที่ โดยปรับค่าตำแหน่งตามความเร็วสองแกนคือ vx แทนความเร็วในแนวแกน x และ vy แทนความเร็วในแกน y
 
เราจะบังคับให้วงกลมเคลื่อนที่ โดยปรับค่าตำแหน่งตามความเร็วสองแกนคือ vx แทนความเร็วในแนวแกน x และ vy แทนความเร็วในแกน y
 +
 +
เนื่องจากเราต้องการเปลี่ยนค่าตำแหน่งวงกลมอย่างต่อเนื่อง เราจึงต้องมีตัวแปรโกลบอลเก็บค่าตำแหน่ง คือ x และ y  ในฟังก์ชัน on_draw เราจะระบุว่าจะแก้ค่าตัวแปรดังกล่าวด้วย keyword '''global''' เราใส่ vx และ vy เผื่อไว้ด้วยเลย (เพราะว่าเราต้องการให้สะท้อนขอบจอ)
 +
 +
โค้ดของ on_draw เป็นดังนี้ บรรทัดที่ประกาศ x,y,vx,vy เป็นการกำหนดค่าให้กับตัวแปรโกลบอล
  
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">

รุ่นแก้ไขเมื่อ 22:04, 31 สิงหาคม 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 ด้วย

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()

แบบฝึกหัด: วงกลมที่มีหลายขนาด

ชนและเด้ง