สร้างเกมด้วย Pygame

จาก Theory Wiki
ไปยังการนำทาง ไปยังการค้นหา
วิกินี้เป็นส่วนหนึ่งของรายวิชา 01204223

Pygame เป็นโมดูลภาษาไพทอนที่ออกแบบมาเพื่อความสะดวกในการพัฒนาเกม วิกินี้ยกตัวอย่างการสร้างเกมอย่างง่ายที่อาศัยบอร์ดไมโครคอนโทรลเลอร์ในการควบคุมผู้เล่น

การเตรียมตัว

ติดตั้งไลบรารี Pygame

สำหรับระบบปฏิบัติการ Ubuntu Linux ใช้คำสั่ง apt-get ติดตั้งได้โดยตรง

sudo apt-get install python-pygame

ส่วนระบบปฏิบัตการ Mac OS X หรือระบบปฏิบัติการอื่น ๆ ให้ดาวน์โหลดตัวติดตั้งจากเว็บไซท์ http://pygame.org/download.shtml

เตรียมบอร์ดไมโครคอนโทรลเลอร์

บอร์ดไมโครคอนโทรลเลอร์ที่นำมาใช้เป็นตัวควบคุมผู้เล่นในวิกินี้ต้องถูกโปรแกรมเฟิร์มแวร์ให้สามารถอ่านค่าแสงผ่านพอร์ท USB ได้แล้ว ให้แน่ใจว่า

เกมตัวอย่าง: สควอช

เกมที่เราจะใช้เป็นตัวอย่างเรียกว่า Squash ดัดแปลงมาจากเกม Pong ที่เป็นคลาสสิคสุดฮิต ลักษณะการเล่นจะเป็นผู้เล่นตั้งแต่หนึ่งคนขึ้นไปตีลูกกระทบกำแพง และพยายามรับลูกที่สะท้อนกลับมาให้ได้

สนามแข่งสควอช
หน้าจอเกมสควอชต้นแบบที่สร้างด้วย Pygame

โค้ดต้นแบบ

ดาวน์โหลดโค้ดต้นแบบจากลิ้งค์ http://www.cpe.ku.ac.th/~cpj/204223/squash.py แล้วนำมาบันทึกไว้ในไดเรคตอรีเดียวกันกับโมดูล practicum.py และ peri.py ที่ได้มาจากการปฏิบัติตามขั้นตอนในวิกิ การติดต่อกับบอร์ด MCU ผ่าน USB ด้วย Arduino ทดลองรันโปรแกรมด้วยไพทอน

python squash.py

ควรปรากฏผลลัพธ์ดังรูปตัวอย่างข้างต้น เกมต้นแบบมีกติกาและการควบคุมดังนี้

  • มีผู้เล่นคนเดียว
  • ใช้ปุ่มลูกศรขึ้น/ลงเลื่อนไม้ตีของผู้เล่นเพื่อรับลูก
  • ทุกครั้งที่รับลูกได้จะได้คะแนนเพิ่ม 1 คะแนน
  • หากรับลูกพลาดและลูกกระทบกำแพงด้านซ้ายมือถือเป็นการจบเกม
  • กดปุ่ม ESC เพื่อออกจากเกมได้ตลอดเวลา

โครงสร้างคลาสของเกม

class diagram

ควบคุมผู้เล่นด้วยบอร์ดไมโครคอนโทรลเลอร์

import pygame
from pygame.locals import *
from practicum import findDevices
from peri import PeriBoard


class Player(object):

    THICKNESS = 10

    def __init__(self, board, pos=WINDOW_SIZE[1]/2, width=100, color=WHITE):
        self.width = width
        self.pos = pos
        self.color = color
        self.board = board

    def move(self):
        try:
            self.pos = self.board.getLight()
        except:
            pass


def main():
    :
    ball = Ball(speed=(200,50))
    board = PeriBoard(findDevices()[0])
    player = Player(board, color=pygame.Color('green'),pos=100)

    while not game_over:
        for event in pygame.event.get(): # process events
            if (event.type == QUIT) or \
               (event.type == KEYDOWN and event.key == K_ESCAPE):
                game_over = True

        if pygame.key.get_pressed()[K_UP]:
            player.pos -= 5
        elif pygame.key.get_pressed()[K_DOWN]:
            player.pos += 5

        display.fill(BLACK)  # clear screen
        display.blit(score_image, (10,10))  # draw score
        player.move()  # move player
        player.draw(display)  # draw player

โค้ดข้างต้นถือว่าต้องมีบอร์ดไมโครคอนโทรลเลอร์เสียบอยู่อย่างน้อยหนึ่งบอร์ดเสมอ

ลดการส่ายของไม้ตี

class Player(object):
    :
    def move(self):
        try:
            self.pos = self.board.getLight()
            self.pos = 0.9*self.pos + 0.1*self.board.getLight()
        except:
            pass

รองรับผู้เล่นหลายคน

FPS = 50
WINDOW_SIZE = (500,500)
BLACK = pygame.Color('black')
WHITE = pygame.Color('white')
GREY  = pygame.Color('grey')
PLAYER_COLORS = ('green','yellow','red','cyan')


def main():
    :
    ball = Ball(speed=(200,50))
    board = PeriBoard(findDevices()[0])
    player = Player(board, color=pygame.Color('green'),pos=100)
    players = []
    for i,dev in enumerate(findDevices()):
        color = PLAYER_COLORS[i % len(PLAYER_COLORS)]
        board = PeriBoard(dev)
        players.append(Player(board,color=pygame.Color(color),pos=100,width=150))

    while not game_over:
        :
        display.fill(BLACK)  # clear screen
        display.blit(score_image, (10,10))  # draw score

        player.move()
        player.draw(display)  # draw player
        for p in players:
            p.move()  # move player
            p.draw(display)  # draw player

        ball.move(1./FPS, display, player players)  # move ball
        ball.draw(display)  # draw ball
$ python
>>> data = ['a','b','c']
>>> list(enumerate(data))
[(0, 'a'), (1, 'b'), (2, 'c')]
>>> for i,x in enumerate(data):
...     print i,x
... 
0 a
1 b
2 c
>>>
class Ball(object):
    :
    def move(self, delta_t, display, player players):
        global score, game_over
        self.x += self.vx*delta_t
        self.y += self.vy*delta_t

        # player-hitting check
        if player.can_hit(self):
            score += 1
            render_score()
            self.vx = abs(self.vx) # bounce ball back
        for p in players:
            if p.can_hit(self):
                score += 1
                render_score()
                self.vx = abs(self.vx) # bounce ball back

เพิ่มจำนวนลูก

เพิ่มความเร็วเมื่อตีลูกโดน

สุ่มปรับความเร็วในแนวตั้งเมื่อลูกกระทบไม้ตี

เพิ่มแรงโน้มถ่วง