Pygame Notebook 1 Puzzle 连连看

2017/10/21

《Making Games with Python and Pygame》


Notebook <1>

在半敲半复制了第三章 Memory Puzzle 和第四章 Slide Puzzle 的源码之后,结合前两章节所讲的东西算是对如何使用 Pygame 编写一个带有界面和操作的小游戏有了基本的认识和了解。这两章的代码主要功能都是在 原始的 Surface 上面绘制带有颜色和文字内容的矩形块,并能对鼠标键盘等操作进行响应。抛开其中简单的数学图形计算不谈,先把其中 Pygame 编写的思路和 API 的调用方式记录下。

Memory Puzzle & Slide Puzzle

像素坐标系和矩形坐标系的转化

  • 两个源码都始终用的是矩形左上角的像素坐标值进行选择和计算
def leftTopCoordsOfBox(boxx , boxy):
	# Convert board coordinates to pixel coordinates
	left = boxx * (BOXSIZE + GAPSIZE ) + XMARGIN
	top  = boxy * (BOXSIZE + GAPSIZE ) + YMARGIN
	return (left , top)

def getLeftTopOfTile(tileX, tileY):
	left = XMARGIN + (tileX * TILESIZE) + (tileX - 1)
	top = YMARGIN + (tileY * TILESIZE) + (tileY - 1)
	return (left, top)

获取光标像素位置,获取键盘值

  • 获取光标像素位置,检查光标位于哪一个方块上
for event in pygame.event.get():
	event.type == MOUSEMOTION:#or other types
		mousex , mousey = event.pos

# 遍历所有的矩形,检查鼠标与哪一个矩形碰撞了
# 返回矩形所在的行列值,注意坐标系的规定
def getSpotClicked(board, x, y):
    # from the x & y pixel coordinates, get the x & y board coordinates
	for tileX in range(len(board)):
		for tileY in range(len(board[0])):
			left, top = getLeftTopOfTile(tileX, tileY)
			tileRect = pygame.Rect(left, top, TILESIZE, TILESIZE)
			if tileRect.collidepoint(x, y):
				return (tileX, tileY)
	return (None, None)
  • 获取键盘值
for event in pygame.event.get():
	if event.type == KEYUP:
		if event.key in (K_LEFT, K_a) and isValidMove(mainBoard, LEFT):
			slideTo = LEFT
		elif event.key in (K_RIGHT, K_d) and isValidMove(mainBoard, RIGHT):
			slideTo = RIGHT
		elif event.key in (K_UP, K_w) and isValidMove(mainBoard, UP):
			slideTo = UP
		elif event.key in (K_DOWN, K_s) and isValidMove(mainBoard, DOWN):
			slideTo = DOWN 
  • 使用 assert 语句检查
assert (BOARDWIDTH * BOARDHEIGHT) %2 == 0

import random

  • 截取列表前 numIconsUsed 个, 打乱列表
icons = icons[:numIconsUsed] * 2
random.shuffle(icons)

Pygame 绘制思路

  • 导入模块
import pygame,sys
from pygame.locals import *
  • 启动,设置全部变量,窗口大小,标题,字体
global FPSCLOCK , DISPLAYSURF , BASICFONT
pygame.init()
FPSCLOCK = pygame.time.Clock()
DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH , WINDOWHEIGHT))
pygame.display.set_caption('NAME')
BASICFONT = pygame.font.Font('freesansbold.ttf' , BASICFONTSIZE)

# 设置字体抗锯齿,颜色,背景颜色
def makeText(text, color, bgcolor, top, left):
	# create the Surface and Rect objects for some text.
	textSurf = BASICFONT.render(text, True, color, bgcolor) #返回的是字体的 Surface
	textRect = textSurf.get_rect()
	textRect.topleft = (top, left)
	return (textSurf, textRect)
  • 更新绘图,帧数
pygame.display.update()
FPSCLOCK.tick(FPS)
  • 在 Slide Puzzle 中通过不断地重设背景颜色,不断地重复绘制,层叠Surface整体 从而实现效果。
  • 矩形方块的打开覆盖,贴片的滑动是通过绘制大小不一的矩形图案实现的。
	drawBoard(board, message)  #每次都重新绘制整个图
	baseSurf = DISPLAYSURF.copy() # 深度拷贝
	# draw a blank space over the moving tile on the baseSurf Surface.
	moveLeft, moveTop = getLeftTopOfTile(movex, movey)
	pygame.draw.rect(baseSurf, BGCOLOR, (moveLeft, moveTop, TILESIZE, TILESIZE)) #用背景色方块替换原来的

	for i in range(0, TILESIZE, animationSpeed):
	# animate the tile sliding over
		checkForQuit()
		DISPLAYSURF.blit(baseSurf, (0, 0)) # 覆盖空白方块后继续画图,显示移动
		if direction == UP:
			drawTile(movex, movey, board[movex][movey], 0, -i)
		if direction == DOWN:
			drawTile(movex, movey, board[movex][movey], 0, i)
		if direction == LEFT:
			drawTile(movex, movey, board[movex][movey], -i, 0)
		if direction == RIGHT:
			drawTile(movex, movey, board[movex][movey], i, 0)
	
		pygame.display.update()
		FPSCLOCK.tick(FPS)
  • Start , Reset 等按键是通过检测相同位置的矩形范围是否与光标碰撞实现的。
#画矩形
pygame.draw.rect(baseSurf, BGCOLOR, (moveLeft, moveTop, TILESIZE, TILESIZE))
#利用矩形所在位置进行检测
boxRect = pygame.Rect(left , top , BOXSIZE , BOXSIZE)
if boxRect.collidepoint(event.pos):
	fun_def()

Search

    Post Directory