ผู้เขียนบทความ : นายมานุสน นะหวัง COE#12
1. ความเป็นมา
ความเป็นมาของโปรเจคนี้คือ ตัวผู้ศึกษานั้นเป็นคนชอบเล่นเกมแนวไขปริศนา (Puzzel) และต้องการที่จะศึกษาวิธีการสร้างเกมเป็นของตัวเองอีกด้วย จึงเริ่มทำการศึกษา หาวิธีที่จะสร้างเกมขึ้นมา จึงไปเจอกับเกม Tetris ซึ่งเป็นเกมที่ตัวผู้ศึกษาชอบเป็นการส่วนตัวอยู่แล้ว จึงนำลองมาทำเป็นเกมของตัวเอง ทำให้เกิดเป็นโปรเจคตัวนี้
2. วัตถุประสงค์
- เพิ่อศึกษาความรู้ในการใช้งานภาษา Python
- เพื่อศึกษาสร้างเกมโดยใช้ Python
- ทำให้ตัวเกมสามารถนำมาเล่นได้จริงและสนุกเพลิดเพลินไปกับเกม
3.ขอบเขตของงาน
- สามารถเล่นได้จริงอย่างอิสระ
- มีการนับคะแนนเมื่อบล็อกเต็มทั้งแถวแนวราบ
- มีฟังก์ชั่นพื้นฐานของเกม Tetris
4.ประโยชน์ที่คาดว่าจะได้รับ
- สามารถนำความรู้เรื่องภาษา Python มาประยุกต์ใช้
- ตัวเกมสามารถทำให้เกิดความสนุกสนาน
- สามารถต่อยอดหรือพัฒนาตัวเกมหรือโปรเจคอื่นๆได้
5.ความรู้ที่เกี่ยวข้อง
5.1 PyGame คืออะไร
PyGame เป็นไลบรารีของภาษา Python ใช้ในการพัฒนาเกม 2 มิติและเป็นแพลตฟอร์มที่สามารถใช้ชุดโมดูล Python เพื่อพัฒนาเกมได้ เป็นแพลตฟอร์มที่เข้าใจง่ายและเป็นมิตรกับผู้เริ่มต้นซึ่งสามารถช่วยให้คุณพัฒนาเกมได้อย่างรวดเร็ว
ตัวอย่างตัวเกมจาก PyGame
วิธีการติดตั้ง Pygame
1.ทำการโหลดตัว Pygame จาก http://www.pygame.org/download.shtml
2. เข้าไปที่ Command Prompt แล้วใส่โค้ด “pip install pygame “ แล้วกด Enter
pip install pygame
3. รอจนติดตั้งเสร็จ
6.ผลการดำเนินงาน
ระยะที่ 1 ทำการหาข้อมูลเกี่ยวกับการทำงาน ระบบต่างๆของเกม Tetris เเละตัวช่วยในการ run ออกมาให้เป็นตัวเกมอย่างโปรเเกรม PyGame ระยะที่ 2 ทำการเขียนอัลกอริทึ่มหรือหาโค้ดจากเเหล่งที่มาอื่น เพื่อสร้างเป็นตัวเกม
เริ่มจากการเรียกตัว Pygame มาก่อนเเละทำการกำหนดขนาดของตัวเกมว่าจะให้มีความกว้างเเละความสูงเท่าไหร่
from random import randrange as rand
import pygame, sys
#The configuration
cell_size = 18
cols = 10
rows = 22
maxfps = 30
กำหนดสีพื้นหลังของตัวเกม
colors = [
(0, 0, 0 ),
(255, 85, 85),
(100, 200, 115),
(120, 108, 245),
(255, 140, 50 ),
(50, 120, 52 ),
(146, 202, 73 ),
(150, 161, 218 ),
(35, 35, 35) ] # Helper color for background grid
กำหนดรูปร่างของบล็อกในเกม
tetris_shapes = [
[[1, 1, 1],
[0, 1, 0]],
[[0, 2, 2],
[2, 2, 0]],
[[3, 3, 0],
[0, 3, 3]],
[[4, 0, 0],
[4, 4, 4]],
[[0, 0, 5],
[5, 5, 5]],
[[6, 6, 6, 6]],
[[7, 7],
[7, 7]]
]
กำหนดการหมุนของบล็อก
def rotate_clockwise(shape):
return [
[ shape[y][x] for y in range(len(shape)) ]
for x in range(len(shape[0]) - 1, -1, -1)
]
ส่วนของการตรวจสอบการชนกันของบล็อกเมื่อลงทับต่อๆกัน
def check_collision(board, shape, offset):
off_x, off_y = offset
for cy, row in enumerate(shape):
for cx, cell in enumerate(row):
try:
if cell and board[ cy + off_y ][ cx + off_x ]:
return True
except IndexError:
return True
return False
ส่วนนี้คือทำให้เเถวหายเมื่อเเถวเเนวนอนเต็มทั้งเเถว
def remove_row(board, row):
del board[row]
return [[0 for i in range(cols)]] + board
def join_matrixes(mat1, mat2, mat2_off):
off_x, off_y = mat2_off
for cy, row in enumerate(mat2):
for cx, val in enumerate(row):
mat1[cy+off_y-1 ][cx+off_x] += val
return mat1
สร้างบอร์ดใหม่เมื่อเริ่มเกม
def new_board():
board = [
[ 0 for x in range(cols) ]
for y in range(rows)
]
board += [[ 1 for x in range(cols)]]
return board
ส่วนนี้คือการกำหนดขนาดของตัวเกมให้สามารถเเสดงผลได้ในตัว PyGame
class TetrisApp(object):
def __init__(self):
pygame.init()
pygame.key.set_repeat(250,25)
self.width = cell_size*(cols+6)
self.height = cell_size*rows
self.rlim = cell_size*cols
self.bground_grid = [[ 8 if x%2==y%2 else 0 for x in range(cols)] for y in range(rows)]
self.default_font = pygame.font.Font(
pygame.font.get_default_font(), 12)
self.screen = pygame.display.set_mode((self.width, self.height))
pygame.event.set_blocked(pygame.MOUSEMOTION) # We do not need
# mouse movement
# events, so we
# block them.
self.next_stone = tetris_shapes[rand(len(tetris_shapes))]
self.init_game()
ส่วนนี้คือการสร้างบล็อกขึ้นมาตัวเกม
def new_stone(self):
self.stone = self.next_stone[:]
self.next_stone = tetris_shapes[rand(len(tetris_shapes))]
self.stone_x = int(cols / 2 - len(self.stone[0])/2)
self.stone_y = 0
if check_collision(self.board,
self.stone,
(self.stone_x, self.stone_y)):
self.gameover = True
ส่วนนี้คือสวนของการเเสดงคะเเนนเเละเลเวลเมื่อเล่น
def init_game(self):
self.board = new_board()
self.new_stone()
self.level = 1
self.score = 0
self.lines = 0
pygame.time.set_timer(pygame.USEREVENT+1, 1000)
การเเสดงผลของหน้าจอบนPyGame
def disp_msg(self, msg, topleft):
x,y = topleft
for line in msg.splitlines():
self.screen.blit(
self.default_font.render(
line,
False,
(255,255,255),
(0,0,0)),
(x,y))
y+=14
def center_msg(self, msg):
for i, line in enumerate(msg.splitlines()):
msg_image = self.default_font.render(line, False,
(255,255,255), (0,0,0))
msgim_center_x, msgim_center_y = msg_image.get_size()
msgim_center_x //= 2
msgim_center_y //= 2
self.screen.blit(msg_image, (
self.width // 2-msgim_center_x,
self.height // 2-msgim_center_y+i*22))
ส่วนนี้คือส่วนของการสุ่มบล็อก
def draw_matrix(self, matrix, offset):
off_x, off_y = offset
for y, row in enumerate(matrix):
for x, val in enumerate(row):
if val:
pygame.draw.rect(
self.screen,
colors[val],
pygame.Rect(
(off_x+x) *
cell_size,
(off_y+y) *
cell_size,
cell_size,
cell_size),0)
ส่วนของการขยับบล็อก
def move(self, delta_x):
if not self.gameover and not self.paused:
new_x = self.stone_x + delta_x
if new_x < 0:
new_x = 0
if new_x > cols - len(self.stone[0]):
new_x = cols - len(self.stone[0])
if not check_collision(self.board,
self.stone,
(new_x, self.stone_y)):
self.stone_x = new_x
ส่วนของการใช้คำสั่งออกจากโปรเเกรม
def quit(self):
self.center_msg("Exiting...")
pygame.display.update()
sys.exit()
ส่วนของการกำหนดการตกของบล็อกลงมา
def drop(self, manual):
if not self.gameover and not self.paused:
self.score += 1 if manual else 0
self.stone_y += 1
if check_collision(self.board,
self.stone,
(self.stone_x, self.stone_y)):
self.board = join_matrixes(
self.board,
self.stone,
(self.stone_x, self.stone_y))
self.new_stone()
cleared_rows = 0
while True:
for i, row in enumerate(self.board[:-1]):
if 0 not in row:
self.board = remove_row(
self.board, i)
cleared_rows += 1
break
else:
break
self.add_cl_lines(cleared_rows)
return True
return False
def insta_drop(self):
if not self.gameover and not self.paused:
while(not self.drop(True)):
pass
ส่วนของการเรียกใช้การหมุนของบล็อก
def rotate_stone(self):
if not self.gameover and not self.paused:
new_stone = rotate_clockwise(self.stone)
if not check_collision(self.board,
new_stone,
(self.stone_x, self.stone_y)):
self.stone = new_stone
ส่วนของการสั่งการทำงานของโปรเเกรมให้หยุดชั่วคราว
def toggle_pause(self):
self.paused = not self.paused
เรียกการใช้งานการสร้างบอร์ดใหม่เมื่อเริ่มเกม
def start_game(self):
if self.gameover:
self.init_game()
self.gameover = False
ส่วนนี้คือการ run โปรเเกรม เเละกำหนดปุ่มการทำงานของฟังค์ชั่นต่างๆ
def run(self):
key_actions = {
'ESCAPE': self.quit,
'LEFT': lambda:self.move(-1),
'RIGHT': lambda:self.move(+1),
'DOWN': lambda:self.drop(True),
'UP': self.rotate_stone,
'p': self.toggle_pause,
'SPACE': self.start_game,
'RETURN': self.insta_drop
}
self.gameover = False
self.paused = False
dont_burn_my_cpu = pygame.time.Clock()
while 1:
self.screen.fill((0,0,0))
if self.gameover:
self.center_msg("""Game Over!\nYour score: %d Press space to continue""" % self.score)
else:
if self.paused:
self.center_msg("Paused")
else:
pygame.draw.line(self.screen,
(255,255,255),
(self.rlim+1, 0),
(self.rlim+1, self.height-1))
self.disp_msg("Next:", (self.rlim+cell_size,2))
self.disp_msg("Score: %d\n\nLevel: %d\\nLines: %d" % (self.score, self.level, self.lines),
(self.rlim+cell_size, cell_size*5))
self.draw_matrix(self.bground_grid, (0,0))
self.draw_matrix(self.board, (0,0))
self.draw_matrix(self.stone,
(self.stone_x, self.stone_y))
self.draw_matrix(self.next_stone,
(cols+1,2))
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.USEREVENT+1:
self.drop(False)
elif event.type == pygame.QUIT:
self.quit()
elif event.type == pygame.KEYDOWN:
for key in key_actions:
if event.key == eval("pygame.K_"+key):
key_actions[key]()
dont_burn_my_cpu.tick(maxfps)
if __name__ == '__main__':
App = TetrisApp()
App.run()
7. สรุปผลและข้อเสนอแนะ
สรุป ตัวโปรเเกรมนั้นสามารถทำงานได้ดี ตัวบล็อกสามารถร่วงลงมาได้เมื่อถึงจุดล่างสุดหรือเมื่อชนกับบล็อกที่ทับการทำให้บล็อกนั้นหยุด เเละทำการสร้างบล็อกใหม่ขึ้นมาใหม่เเละร่วงมาต่อเรื่อยๆ สามารถเเสดงคะเเนนได้เมื่อบล็อกเต็มหมดจะทำให้ GAME OVER เเละสามารถเริ่มใหม่ได้
ข้อเสนอเเนะ
- สามารถทำให้โปรเเกรมนั้นเเชร์คะเเนนลงสื่อโซเชียลเพื่อเเบ่งปันกันคนอื่นได้
- สามารถทำให้ตัวเกมนั้นมีสีสันเเละหน้าต่างนั้นสวยเเละน่ารัก ทำให้น่าเล่นได้มากกว่านี้