ผลต่างระหว่างรุ่นของ "Oop lab/pygame1"
Jittat (คุย | มีส่วนร่วม) |
Jittat (คุย | มีส่วนร่วม) |
||
แถว 110: | แถว 110: | ||
คลาสเกมที่ได้ เราต้องการให้เมื่อสร้างแล้วเรียกทำงานโดยเมท็อด run ได้เลย | คลาสเกมที่ได้ เราต้องการให้เมื่อสร้างแล้วเรียกทำงานโดยเมท็อด run ได้เลย | ||
− | เราจะเริ่มทยอยเขียนจากส่วนสามเมท็อดแรกก่อน เราจะเขียนคลาสดังกล่าวไว้ในไฟล์ <tt>gamelib.py</tt> ซึ่งจะเป็นโมดูลย่อยของเกมของเรา โครงของคลาสเราเป็นดังนี้ | + | เราจะเริ่มทยอยเขียนจากส่วนสามเมท็อดแรกก่อน เราจะเขียนคลาสดังกล่าวไว้ในไฟล์ '''<tt>gamelib.py</tt>''' ซึ่งจะเป็นโมดูลย่อยของเกมของเรา โครงของคลาสเราเป็นดังนี้ |
<syntaxhighlight lang="python"> | <syntaxhighlight lang="python"> | ||
แถว 132: | แถว 132: | ||
def render(self): | def render(self): | ||
pass | pass | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | เราจะเขียนโปรแกรมหลักขึ้นมาทดสอบพร้อม ๆ กัน | ||
+ | |||
+ | <syntaxhighlight lang="python"> | ||
+ | import pygame | ||
+ | from pygame.locals import * | ||
+ | from gamelib import SimpleGame | ||
+ | |||
+ | class SquashGame(SimpleGame): | ||
+ | pass | ||
+ | |||
+ | def main(): | ||
+ | game = SquashGame() | ||
+ | game.run() | ||
+ | |||
+ | if __name__ == '__main__': | ||
+ | main() | ||
</syntaxhighlight> | </syntaxhighlight> |
รุ่นแก้ไขเมื่อ 15:31, 16 พฤศจิกายน 2557
- หน้านี้เป็นส่วนหนึ่งของ oop lab
ไลบรารีที่เราจะใช้ในการพัฒนาเกมบน Python คือ PyGame อย่างไรก็ตาม ตัว Pygame นั้นไม่ได้มีโครงสร้างที่เป็นเชิงวัตถุมากนัก ใน Tutorial นี้เราจะสร้างกรอบงานเชิงวัตถุครอบ Pygame อีกครั้ง โดยจะพยายามอ้างอิงโครงสร้างจาก Slick2D เพื่อความคุ้นเคย
โค้ดเริ่มต้น
เราจะเริ่มจากโค้ด squash.py จากหน้า สร้างเกมด้วย Pygame โดยเราจะเริ่มจากการแกะส่วนแก่นของเกมในฟังก์ชัน main แยกออกมาเป็นคลาส
โค้ดที่เราสนใจอยู่ในส่วนต่อไปนี้
def main():
global game_over,font,score,score_image
pygame.init()
clock = pygame.time.Clock()
display = pygame.display.set_mode(WINDOW_SIZE)
pygame.display.set_caption('Squash')
game_over = False
font = pygame.font.SysFont("monospace", 20)
score = 0
score_image = None
render_score()
ball = Ball(speed=(200,50))
player = Player(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.draw(display) # draw player
ball.move(1./FPS, display, player) # move ball
ball.draw(display) # draw ball
pygame.display.update() # redraw the screen
clock.tick(FPS) # wait to limit FPS requirement
if __name__=='__main__':
main()
print "Game Over! Total score is %d." % score
pygame.quit()
หน้าที่หลักของฟังก์ชัน main ถ้ามองในแง่ของเกมแล้ว มีดังนี้
- ตั้งค่าเริ่มต้น (init)
- ทำงานใน update/render ลูป
- จัดการกับ event
ถ้าเราพิจารณาจากโค้ด จะแบ่งเป็นส่วน ๆ ได้ตามด้านล่างนี้
def main():
# ------------------------ init -------------------------------------
pygame.init()
clock = pygame.time.Clock()
# ...
player = Player(color=pygame.Color('green'),pos=100)
# ------------------ event loop ------------------------------------
while not game_over:
# ----------------------- event processing -------------------------
for event in pygame.event.get(): # process events
# ...
if pygame.key.get_pressed()[K_UP]:
player.pos -= 5
elif pygame.key.get_pressed()[K_DOWN]:
player.pos += 5
# ---------------------------- render & update ---------------------------------------
display.fill(BLACK) # clear screen
display.blit(score_image, (10,10)) # draw score
player.draw(display) # draw player
ball.move(1./FPS, display, player) # move ball
ball.draw(display) # draw ball
pygame.display.update() # redraw the screen
# ---------------------------- wait inside loop ----------------------------
clock.tick(FPS) # wait to limit FPS requirement
เราจะเริ่มจากส่วน init และ update/render ลูปก่อน
คลาส SimpleGame
มาวางแผนกันก่อน... เราจะเขียนคลาส SimpleGame ที่ทำหน้าที่จัดการแกนหลักของเกม ตามที่นำมาข้างต้น เราต้องการให้คนที่เขียนเกม นำคลาสเราไปใช้เพื่อสร้างเกมขึ้นมา
เรามีทางเลือกในการออกแบบคลาสดังกล่าวสองทางคือ การใช้ inheritance กับการใช้ composition (อ่านรายละเอียดคร่าว ๆ ที่ แบบฝึกหัด 44, หนังสือ Learn Python the Hard Way) อย่างไรก็ตาม เราพยายามจะคงโครงสร้างของ Slick2D เอาไว้ ดังนั้นเราจะเลือกแบบแรก กล่าวคือ เราจะให้คนที่เขียนเกม inherit SimpleGame เพื่อสร้างเป็นคลาสใหม่ของเกมขึ้นมา ดังนั้นเราต้องวางแผนคร่าว ๆ ว่า SimpleGame ของเราจะทำอะไรบ้าง และอะไรจะเหลือให้คลาสที่ inherit ไปเอาไปเขียนเอง และจะเขียนเองอย่างไร
เราต้องการให้คน inherit คลาส SimpleGame เขียนเมท็อดเหล่านี้ที่เฉพาะเจาะจงกับเกมของตัวเอง:
- init
- render
- update
- on_key_up
- on_key_down
คลาสเกมที่ได้ เราต้องการให้เมื่อสร้างแล้วเรียกทำงานโดยเมท็อด run ได้เลย
เราจะเริ่มทยอยเขียนจากส่วนสามเมท็อดแรกก่อน เราจะเขียนคลาสดังกล่าวไว้ในไฟล์ gamelib.py ซึ่งจะเป็นโมดูลย่อยของเกมของเรา โครงของคลาสเราเป็นดังนี้
import pygame
from pygame.locals import *
class SimpleGame:
def __init__(self):
pass
def run(self):
pass
def init(self):
pass
def update(self):
pass
def render(self):
pass
เราจะเขียนโปรแกรมหลักขึ้นมาทดสอบพร้อม ๆ กัน
import pygame
from pygame.locals import *
from gamelib import SimpleGame
class SquashGame(SimpleGame):
pass
def main():
game = SquashGame()
game.run()
if __name__ == '__main__':
main()