คลาสและอ๊อปเจกต์

ตัวแปรและการสร้างอ๊อปเจกต์

  1. pygame.display.set_mode([1200, 800]) เป็นคำสั่งสร้าง object ของคลาส pygame.Surface เพื่อการแสดงหน้าต่างขนาด กว้าง 1200 พิกเซล สูง 800 พิกเซล

  1. pygame.time.Clock() เป็นคำสั่งสร้าง object ของคลาสสำหรับจัดการเรื่องเวลาของเกม

  1. pygame.image.load('BG.png') เป็นคำสั่งสร้าง object ของคลาส pygame.Surface จากการโหลดไฟล์ภาพชื่อ BG.png

  1. bg.get_rect() ส่งกับ object ของคลาส pygame.Rect() เป็นสี่เหลี่ยมที่มีข้อมูล topleft และ size ของ pygame.Surface ที่อ้างอิงถึงด้วยตัวแปร bg

ข้อความ

Pygame มีคลาส pygame.font.Font เพื่อช่วยในการนำเข้าและแสดงข้อความ

  1. download font

  1. เปลี่ยนชื่อไฟล์เป็น NotoSerifThai.ttf เก็บไว้ใน folder ชื่อ fonts

../../../_images/pygame02.png
 1import sys
 2import pygame
 3from pygame.locals import QUIT
 4
 5pygame.init()
 6
 7screen = pygame.display.set_mode([1200, 800])
 8clock = pygame.time.Clock()
 9bg = pygame.image.load('deserttileset/png/BG.png')
10bg_rect = bg.get_rect()
11font = pygame.font.Font('fonts/NotoSerifThai.ttf', size=50)
12game_over = False
13
14while not game_over:
15
16    for event in pygame.event.get():              
17        if event.type == QUIT:
18            pygame.quit()
19            sys.exit()
20
21    screen.blit(bg, bg_rect)
22    text = f'{clock.get_fps():.0f} เฟรมต่อวินาที'
23    msg = font.render(text, True, (0,150,0))
24    screen.blit(msg, msg.get_rect())
25    pygame.display.update()
26    clock.tick(60)
27    

เสียง

เสียงในเกมจะมีอยู่สองแบบได้แก่เสียงที่เกิดจาก action และเสียงเพลง background โดยจะใช้ pygame.mixer ในการจัดการเรื่องเสียงในเกม

  • download เสียงเพลง mp3

https://opengameart.org/sites/default/files/desert_theme.zip

 1import sys
 2import pygame
 3from pygame.locals import QUIT
 4
 5pygame.init()
 6
 7screen = pygame.display.set_mode([1200, 800])
 8clock = pygame.time.Clock()
 9bg = pygame.image.load('deserttileset/png/BG.png')
10bg_rect = bg.get_rect()
11font = pygame.font.Font('fonts/NotoSerifThai.ttf', size=50)
12pygame.mixer.music.load('Desert Theme/Desert Theme.mp3')
13pygame.mixer.music.play(0)
14game_over = False
15
16while not game_over:
17
18    for event in pygame.event.get():              
19        if event.type == QUIT:
20            pygame.quit()
21            sys.exit()
22
23    screen.blit(bg, bg_rect)
24    text = f'{clock.get_fps():.2f} เฟรมต่อวินาที'
25    msg = font.render(text, True, (0,150,0))
26    screen.blit(msg, msg.get_rect())
27    pygame.display.update()
28    clock.tick(60)
29    

ตัวละคร

เนื่องจากตัวละครจำเป็นต้องใช้หลายภาพเพื่อเปลี่ยนท่าทางการแสดงผลไปเรื่อย ๆ ตามจำนวนเฟรมที่ผ่านไปของเกม ดังนั้น pygame จึงสร้างคลาส pygame.sprite.Sprite มาเพื่อจัดการการแสดงผลตัวละครโดยเฉพาะ

  1. download character

  1. เนื่องจากตัวละครมีความซับซ้อน เพื่อให้สะดวกต่อการเรียกใช้งาน จึงจำเป็นต้องเขียนเป็นคลาสเพื่อจัดการข้อมูลท่าทาง(action) ตำแหน่งบนหน้าจอ(x, y) เฟรม(frame) และเวลาสะสม(deltatime) ของตัวละครดังนี้

 1import sys
 2import pygame
 3from pygame.locals import QUIT
 4
 5pygame.init()
 6
 7class Character(pygame.sprite.Sprite):
 8
 9    ACTIONS = [
10         'Idle', 'Dead', 'Jump', 'Run', 'Slide'
11     ]
12
13    def __init__(self, action='Dead', x=400, y=100, frame=0):
14        super().__init__() # pygame.sprite.Sprite.__init__(self)
15        #self.image = pygame.Surface([588, 600])
16        self.rect = pygame.Rect((0, 0), (588, 600))
17        self.action = action
18        self.x = x
19        self.y = y
20        self.frame = frame
21        self.deltatime = 0
22
23    def update(self, deltatime):
24        self.deltatime += deltatime
25        if self.deltatime >= 30:
26            self.deltatime -= 30
27            self.frame = (self.frame+1)%10
28
29    def blit(self, screen):
30        image = pygame.image.load(f'templerun/{self.action}__{self.frame:03d}.png')
31        self.rect.topleft = self.x, self.y
32        screen.blit(image, self.rect)
33
34screen = pygame.display.set_mode([1200, 800])
35clock = pygame.time.Clock()
36bg = pygame.image.load('deserttileset/png/BG.png')
37bg_rect = bg.get_rect()
38font = pygame.font.Font('fonts/NotoSerifThai.ttf', size=50)
39pygame.mixer.music.load('Desert Theme/Desert Theme.mp3')
40pygame.mixer.music.play(0)
41game_over = False
42player = Character()
43
44while not game_over:
45
46    for event in pygame.event.get():              
47        if event.type == QUIT:
48            pygame.quit()
49            sys.exit()
50
51    screen.blit(bg, bg_rect)
52    text = f'{clock.get_fps():.2f} เฟรมต่อวินาที'
53    msg = font.render(text, True, (0,150,0))
54    screen.blit(msg, msg.get_rect())
55    player.blit(screen)
56    pygame.display.update()
57    deltatime = clock.tick(60)
58    player.update(deltatime)
59    

Exercise

  • เพิ่มข้อมูล scale ในคลาส Character เพื่อให้สามารถลดพื้นที่การแสดงผลเป็นร้อยละได้เช่น scale = .5 หมายถึง ร้อยละ 50 ของขนาดเดิม โดยใช้คำสั่ง pygame.transform.scale

  • ทำให้เปลี่ยนท่าทางไปเรื่อย? Idle - Dead - Jump - Run - Slide

การตอบสนองต่อผู้เล่น

ผู้เล่น pygame สามารถโต้ตอบผ่าน Mouse, Keyboard, touch screen, Joystick หรือ Controller ได้ โดยข้อมูลการโต้ตอบจะอยู่เก็บไว้เป็น object ของคลาส pygame.event.Event

กดปุ่มย้ำ ๆ

import sys
import pygame
from pygame.locals import QUIT, KEYDOWN, K_a, K_d

pygame.init()

class Character(pygame.sprite.Sprite):

    ACTIONS = [
         'Idle', 'Dead', 'Jump', 'Run', 'Slide'
     ]

    def __init__(self, action='Idle', x=400, y=100, frame=0):
        super().__init__() # pygame.sprite.Sprite.__init__(self)
        #self.image = pygame.Surface([588, 600])
        self.rect = pygame.Rect((0, 0), (588, 600))
        self.action = action
        self.x = x
        self.y = y
        self.frame = frame
        self.deltatime = 0

    def left(self):
        self.x -= 2

    def right(self):
        self.x += 2

    def update(self, deltatime):
        self.deltatime += deltatime
        if self.deltatime >= 30:
            self.deltatime -= 30
            self.frame = (self.frame+1)%10

    def blit(self, screen):
        image = pygame.image.load(f'templerun/{self.action}__{self.frame:03d}.png')
        self.rect.topleft = self.x, self.y
        screen.blit(image, self.rect)

screen = pygame.display.set_mode([1200, 800])
clock = pygame.time.Clock()
bg = pygame.image.load('deserttileset/png/BG.png')
bg_rect = bg.get_rect()
font = pygame.font.Font('fonts/NotoSerifThai.ttf', size=50)
pygame.mixer.music.load('Desert Theme/Desert Theme.mp3')
pygame.mixer.music.play(0)
game_over = False
player = Character()

while not game_over:

    for event in pygame.event.get():              
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
        if event.type == KEYDOWN:
            if event.key == K_a:
                player.left()
            if event.key == K_d:
                player.right()

    screen.blit(bg, bg_rect)
    text = f'{clock.get_fps():.2f} เฟรมต่อวินาที'
    msg = font.render(text, True, (0,150,0))
    screen.blit(msg, msg.get_rect())
    player.blit(screen)
    pygame.display.update()
    deltatime = clock.tick(60)
    player.update(deltatime)
    

กดปุ่มค้างไว้

import sys
import pygame
from pygame.locals import QUIT

pygame.init()

class Character(pygame.sprite.Sprite):

    ACTIONS = [
         'Idle', 'Dead', 'Jump', 'Run', 'Slide'
     ]

    def __init__(self, action='Idle', x=400, y=100, frame=0):
        super().__init__() # pygame.sprite.Sprite.__init__(self)
        #self.image = pygame.Surface([588, 600])
        self.rect = pygame.Rect((0, 0), (588, 600))
        self.action = action
        self.x = x
        self.y = y
        self.frame = frame
        self.deltatime = 0

    def left(self):
        self.x -= 2

    def right(self):
        self.x += 2

    def update(self, deltatime):
        self.deltatime += deltatime
        if self.deltatime >= 30:
            self.deltatime -= 30
            self.frame = (self.frame+1)%10

    def blit(self, screen):
        image = pygame.image.load(f'templerun/{self.action}__{self.frame:03d}.png')
        self.rect.topleft = self.x, self.y
        screen.blit(image, self.rect)

screen = pygame.display.set_mode([1200, 800])
clock = pygame.time.Clock()
bg = pygame.image.load('deserttileset/png/BG.png')
bg_rect = bg.get_rect()
font = pygame.font.Font('fonts/NotoSerifThai.ttf', size=50)
pygame.mixer.music.load('Desert Theme/Desert Theme.mp3')
pygame.mixer.music.play(0)
game_over = False
player = Character()

while not game_over:

    for event in pygame.event.get():              
        if event.type == QUIT:
            pygame.quit()
            sys.exit()

    keys = pygame.key.get_pressed()
    if keys[pygame.K_a]:
        player.left()
    if keys[pygame.K_d]:
        player.right()

    screen.blit(bg, bg_rect)
    text = f'{clock.get_fps():.2f} เฟรมต่อวินาที'
    msg = font.render(text, True, (0,150,0))
    screen.blit(msg, msg.get_rect())
    player.blit(screen)
    pygame.display.update()
    deltatime = clock.tick(60)
    player.update(deltatime)
    

mouse click

การสร้าง effect สำหรับยิงปืนลูกซองในเกม

  1. download sprite สำหรับ effect

  1. download เสียงยิงปืนลูกซอง

import sys
import pygame
from pygame.locals import QUIT, MOUSEBUTTONDOWN

pygame.init()

class ShootAnimation(pygame.sprite.Sprite):

    SHEET = pygame.image.load('alotofimpacts/Impact001.png')
    SOUND = pygame.mixer.Sound('shots/pistol.wav')

    def __init__(self, x, y):
        self.frame = 0
        self.width = 768/4
        self.height = 192
        self.x = x - self.width/2
        self.y = y - self.height/2
        #self.image = pygame.Surface([768/4, 192])
        self.rect = pygame.Rect((0,0), (self.width, self.height))
        self.deltatime = 0
        ShootAnimation.SOUND.play()

    def update(self, screen, deltatime):
        if self.frame < 4:
            self.deltatime += deltatime
            if self.deltatime >= 30:
                self.deltatime -= 30
                self.frame += 1
                self.rect.topleft = self.x, self.y
                screen.blit(
                        ShootAnimation.SHEET, 
                        self.rect,
                        (self.frame*self.width,0,self.width,self.height)
                    )


class Character(pygame.sprite.Sprite):

    ACTIONS = [
         'Idle', 'Dead', 'Jump', 'Run', 'Slide'
     ]

    def __init__(self, action='Idle', x=400, y=100, frame=0):
        super().__init__() # pygame.sprite.Sprite.__init__(self)
        #self.image = pygame.Surface([588, 600])
        self.rect = pygame.Rect((0, 0), (588, 600))
        self.action = action
        self.x = x
        self.y = y
        self.frame = frame
        self.deltatime = 0

    def left(self):
        self.x -= 2

    def right(self):
        self.x += 2

    def update(self, deltatime):
        self.deltatime += deltatime
        if self.deltatime >= 30:
            self.deltatime -= 30
            self.frame = (self.frame+1)%10

    def blit(self, screen):
        image = pygame.image.load(f'templerun/{self.action}__{self.frame:03d}.png')
        self.rect.topleft = self.x, self.y
        screen.blit(image, self.rect)

screen = pygame.display.set_mode([1200, 800])
clock = pygame.time.Clock()
bg = pygame.image.load('deserttileset/png/BG.png')
bg_rect = bg.get_rect()
font = pygame.font.Font('fonts/NotoSerifThai.ttf', size=50)
pygame.mixer.music.load('Desert Theme/Desert Theme.mp3')
pygame.mixer.music.play(0)
game_over = False
player = Character()
animation = None

while not game_over:

    for event in pygame.event.get():              
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
        if event.type == MOUSEBUTTONDOWN:
            x, y = pygame.mouse.get_pos()
            left, wheel, right = pygame.mouse.get_pressed()
            if left:
                animation = ShootAnimation(x, y)

    keys = pygame.key.get_pressed()
    if keys[pygame.K_a]:
        player.left()
    if keys[pygame.K_d]:
        player.right()

    screen.blit(bg, bg_rect)
    text = f'{clock.get_fps():.2f} เฟรมต่อวินาที'
    msg = font.render(text, True, (0,150,0))
    screen.blit(msg, msg.get_rect())
    player.blit(screen)
    deltatime = clock.tick(60)
    player.update(deltatime)
    if animation: 
        animation.update(screen, deltatime)
    pygame.display.update()
    

Exercise

  • สร้างโครงงานเกมด้วย pygame