Pygame 教學 (一)

共筆:https://hackmd.io/LuheTD_SQwWYa2wMwiv65g
匿名提問

前情提要

我們今天要來做打磚塊!

在這之前 我們來把遊戲的流程釐清一下

我們會用到的物件

  • 磚塊

    生成 / 消失 / 反彈
  • 反彈 (物理碰撞)
  • 反彈球ㄉ板子

    反彈 (物理碰撞)

遊戲的基本流程

CODING 邏輯

  • pygame 初始化
  • 把物件做出來

init

  • 球的生成 位置 及 速度
  • 反射板的生成 位置
  • 遊戲初始化 ( ) 將該歸位的的東西歸位 參數重設

loop start

  • 判斷遊戲狀態(按下右鍵開始) ( ) bool 開始參數

  • 球給我動起來 - 球的碰撞>變更移動方向


第一步 - Pygame 及 遊戲參數的初始化

import sys import pygame from pygame.locals import QUIT SCREEN_SIZEX = 800 SCREEN_SIZEY = 600 SCREEN_COLOR = (0,0,0) clock = pygame.time.Clock() pygame.init() window_surface = pygame.display.set_mode((SCREEN_SIZEX,SCREEN_SIZEY)) window_surface.fill(SCREEN_COLOR) pygame.display.update() # 鼠標 鎖定 和 隱藏 pygame.event.set_grab(True) pygame.mouse.set_visible(False) while True: for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit() elif event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: pygame.quit() sys.exit() window_surface.fill(SCREEN_COLOR) pygame.display.update() #設定畫面貞數 clock.tick(60)

第二步 物件的製作

我們的目標是 把物件包好 然後我們只要 call 他就可以生成了
今天的進度 我們會需要用到 "球" 和 "發射板" 這兩個物件

Object.py

import pygame # 球 class Ball(object): def __init__(self,canvas,pos, radius): #一個pygame物件 self.pygame = pygame #畫布(物件繪製在哪邊) self.canvas = canvas #設置圓心位置 self.pos = pos #球的半徑 self.radius = radius #球的顏色 self.color = (100,200,200) #實/空 心 self.visible = True self.rect = self.pygame.draw.circle(self.canvas, self.color, self.pos, self.radius) def update(self): if(self.visible): self.rect = self.pygame.draw.circle(self.canvas, self.color, self.pos, self.radius) # 發射板 class Paddle(object): def __init__(self,canvas, rect): self.pygame = pygame self.canvas = canvas self.rect = rect self.color = (255, 255, 255) self.visible = True def update(self): if(self.visible): self.pygame.draw.rect(self.canvas, self.color, self.rect)

寫完之後 我們把它匯入主程式吧!
我們只要在主程式前面加上 from Object import * 就可以把他們匯進去了

然後我們就可以在主程式裡面呼叫他們測試看看 - 像這樣

# Paddle(要繪製的圖層,[繪製位置,長跟寬]) paddle = Paddle(window_surface, [SCREEN_SIZEX/2 - 50, SCREEN_SIZEY - 48, 100, 24]) # Ball(要繪製的圖層,[繪製位置],半徑) ball = Ball(window_surface, [int(paddle.rect[0] + ((paddle.rect[2] - 10)//2)), paddle.rect[1] - 10], 10)

然後記得在 while 裡面更新 讓他一直繪圖

paddle.update() ball.update()

第三步 物件的生成和設定

一些常數

BALL_SPEED = 8 dx = BALL_SPEED dy = -BALL_SPEED

生成物件

這邊只是生成而已 一樣要記得在 loop 裡面 update 喔!

paddle_x = 0 paddle_y = (SCREEN_SIZEY - 48) paddle = Paddle(window_surface, [paddle_x, paddle_y, 100, 24]) ball_x = paddle_x ball_y = paddle_y ball = Ball(window_surface, [ball_x, ball_y], 8)

遊戲重設

def resetGame(): global game_mode,dx, dy game_mode = 0 dx = BALL_SPEED dy = -BALL_SPEED

第四步 - 遊戲狀態設定 及 初始化

我們要在loop 一開始的 for event 裡面加上條件 判斷是否按下右鍵

for event in pygame.event.get(): ...... 以上省略 ..... if event.type == pygame.MOUSEBUTTONDOWN: if(game_mode == 0): game_mode = 1

背景塗滿

window_surface.fill(SCREEN_COLOR)

反射板 歸位

paddle.rect[0] = paddle_x

第五步 - 遊戲開始!

if(game_mode == 0): ball.pos[0] = ball_x = paddle.rect[0] + ((paddle.rect[2] - ball.radius)//2) ball.pos[1] = ball_y = paddle.rect[1] - ball.radius else: ball_x += dx ball_y += dy #判斷死亡. if(ball_y + dy > SCREEN_SIZEY - ball.radius): resetGame() # 右牆或左牆碰撞. if(ball_x + dx > SCREEN_SIZEX - ball.radius or ball_x + dx < ball.radius): dx = -dx # 上牆碰撞 if(ball_y + dy < -ball.radius): dy = -dy ball.pos[0] = ball_x ball.pos[1] = ball_y

完整程式碼

main.py

import sys import pygame from pygame.locals import QUIT from Object import * SCREEN_SIZEX = 800 SCREEN_SIZEY = 600 SCREEN_COLOR = (0,0,0) BALL_SPEED = 8 dx = BALL_SPEED dy = -BALL_SPEED clock = pygame.time.Clock() def Update(): ball.update() paddle.update() pygame.display.update() def isCollision(Rect1, Rect2): if(pygame.Rect.colliderect(Rect1, Rect2)): return True return False def resetGame(): global game_mode, dx, dy game_mode = 0 dx = BALL_SPEED dy = -BALL_SPEED pygame.init() window_surface = pygame.display.set_mode((SCREEN_SIZEX,SCREEN_SIZEY)) window_surface.fill(SCREEN_COLOR) paddle_x = 0 paddle_y = (SCREEN_SIZEY - 48) paddle = Paddle(window_surface, [paddle_x, paddle_y, 100, 24]) ball_x = paddle_x ball_y = paddle_y ball = Ball(window_surface, [ball_x, ball_y], 8) resetGame() pygame.display.update() # 鼠標 鎖定 和 隱藏 pygame.event.set_grab(True) pygame.mouse.set_visible(False) while True: for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit() elif event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: pygame.quit() sys.exit() if event.type == pygame.MOUSEMOTION: paddle_x = pygame.mouse.get_pos()[0] - 50= pygame.MO if event.type == pygame.MOUSEMOTION: paddle_x = pygame.mouse.get_pos()[0] - 50 if event.type == pygame.MOUSEBUTTONDOWN: if(game_mode == 0): game_mode = 1 window_surface.fill(SCREEN_COLOR) paddle.rect[0] = paddle_x if(isCollision(ball.rect, paddle.rect)): dy = -dy # 遊戲流程控制 if(game_mode == 0): ball.pos[0] = ball_x = paddle.rect[0] + ((paddle.rect[2] - ball.radius) // 2) ball.pos[1] = ball_y = paddle.rect[1] - ball.radius else: ball_x += dx ball_y += dy #判斷死亡. if(ball_y + dy > SCREEN_SIZEY - ball.radius): game_mode = 0 # 右牆或左牆碰撞. if(ball_x + dx > SCREEN_SIZEX - ball.radius or ball_x + dx < ball.radius): dx = -dx # 上牆碰撞 if(ball_y + dy < -ball.radius): dy = -dy ball.pos[0] = ball_x ball.pos[1] = ball_y Update() clock.tick(60)

Object.py

import pygame class Ball(object): def __init__(self,canvas,pos, radius): self.pygame = pygame self.canvas = canvas self.pos = pos self.radius = radius self.color = (100,200,200) self.visible = True self.rect = self.pygame.draw.circle(self.canvas, self.color, self.pos, self.radius) def update(self): if(self.visible): self.rect = self.pygame.draw.circle(self.canvas, self.color, self.pos, self.radius) class Paddle(object): def __init__(self,canvas, rect): self.pygame = pygame self.canvas = canvas self.rect = rect self.color = (255, 255, 255) self.visible = True def update(self): if(self.visible): self.pygame.draw.rect(self.canvas, self.color, self.rect)

Git && GitHub 教學操作筆記
https://hackmd.io/@andy010629/BJB6pdg5w

Select a repo