如何在 pygame 中制作咀嚼效果
How to make a chomping effect in pygame
这是我的代码:
import pygame
pygame.init()
pygame.display.set_caption("Pac-Man")
# Sets the size of the screen via (WIDTH, HEIGHT)
SCREEN_WIDTH = 478
SCREEN_HEIGHT = 608
# Speed of Characters
SPEED = 1
# Frames per second, how fast the game runs
FPS = 50
# Colors (RED,GREEN,BLUE)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
YELLOW = (255, 255, 0)
BLUE = (0, 0, 255)
HIGH_SCORE = 0
# Sets the WIDTH and HEIGHT of the window
WINDOW = (SCREEN_WIDTH, SCREEN_HEIGHT)
# Displays the screen
SCREEN = pygame.display.set_mode(WINDOW)
CLOCK = pygame.time.Clock()
PacManStartSurface = pygame.transform.scale(pygame.image.load
("PacManStart.png"), (24, 24))
PacManStartSurface.convert()
PacManStartRect = PacManStartSurface.get_rect(topleft =
(((SCREEN_WIDTH - 25) // 2),
(SCREEN_HEIGHT + 144) // 2))
PacManSurface = pygame.transform.scale(pygame.image.load
("PacManRight.png"), (24, 24))
PacManSurface.convert()
PacManRect = PacManStartSurface.get_rect(topleft =
(((SCREEN_WIDTH - 125) // 2),
(SCREEN_HEIGHT + 144) // 2))
CurrentSurface = PacManStartSurface
CurrentRect = PacManStartRect
BackgroundSurface = pygame.image.load("Background.png").convert()
class PacMan():
def __init__(self):
self.LIVES = 3
class PowerUp(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.transform.scale(pygame.image.load("PowerUp.png")
.convert(), (23, 23))
self.mask = pygame.mask.from_surface(self.image)
class YellowGhost(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.transform.scale(pygame.image.load
("YellowGhost.png")
.convert(), (23, 23))
self.rect = self.image.get_rect(topleft = (235, 347))
self.mask = pygame.mask.from_surface(self.image)
class RedGhost(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.transform.scale(pygame.image.load("RedGhost.png")
.convert(), (23, 23))
self.rect = self.image.get_rect(topleft = (235, 347))
self.mask = pygame.mask.from_surface(self.image)
class BlueGhost(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.transform.scale(pygame.image.load("BlueGhost.png")
.convert(), (23, 23))
self.rect = self.image.get_rect(topleft = (235, 347))
self.mask = pygame.mask.from_surface(self.image)
class PinkGhost(pygame.sprite.Sprite):
def __init__(self):
self.image = pygame.transform.scale(pygame.image.load("PinkGhost.png")
.convert(), (23, 23))
self.rect = self.image.get_rect(topleft = (235, 347))
self.mask = pygame.mask.from_surface(self.image)
class Maze():
def __init__(self):
self.DOTS = []
self.WALLS = []
self.BLOCK_WIDTH = 25
self.BLOCK_HEIGHT = 25
self.MAZE_OFFSET_X = 0
self.MAZE_OFFSET_Y = 50
self.MARGIN = 3
# 0 - Dots
# 1 - Walls
# 2 - Power Up
# 3 - Empty Space
# 4 - Ghosts
self.MATRIX = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], \
[1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1], \
[1,2,1,1,0,1,1,1,0,1,0,1,1,1,0,1,1,2,1], \
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], \
[1,0,1,1,0,1,0,1,1,1,1,1,0,1,0,1,1,0,1], \
[1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1], \
[1,1,1,1,0,1,1,1,3,1,3,1,1,1,0,1,1,1,1], \
[3,3,3,1,0,1,3,3,3,3,3,3,3,1,0,1,3,3,3], \
[1,1,1,1,0,1,3,1,1,1,1,1,3,1,0,1,1,1,1], \
[0,0,0,0,0,3,3,1,4,4,4,1,3,3,0,0,0,0,0], \
[1,1,1,1,0,1,3,1,1,1,1,1,3,1,0,1,1,1,1], \
[3,3,3,1,0,1,3,3,3,3,3,3,3,1,0,1,3,3,3], \
[1,1,1,1,0,1,3,1,1,1,1,1,3,1,0,1,1,1,1], \
[1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1], \
[1,2,1,1,0,1,1,1,0,1,0,1,1,1,0,1,1,2,1], \
[1,0,0,1,0,0,0,0,0,3,0,0,0,0,0,1,0,0,1], \
[1,1,0,1,0,1,0,1,1,1,1,1,0,1,0,1,0,1,1], \
[1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1], \
[1,0,1,1,1,1,1,1,0,1,0,1,1,1,1,1,1,0,1], \
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], \
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
# BackgroundImage(X, Y, WIDTH, HEIGHT)
self.MAZE_X = self.BLOCK_WIDTH * (len(self.MATRIX[0])
+ self.MAZE_OFFSET_X)
self.MAZE_Y = self.BLOCK_HEIGHT * (len(self.MATRIX)
+ self.MAZE_OFFSET_Y)
self.MAZE_WIDTH = self.BLOCK_WIDTH * len(self.MATRIX[0])
self.MAZE_HEIGHT = self.BLOCK_HEIGHT * len(self.MATRIX)
def DrawMaze(self, MazeSurface):
for ROW in range(len(self.MATRIX)):
for COLUMN in range(len(self.MATRIX[0])):
# Only saves the position of each dot
if self.MATRIX[ROW][COLUMN] == 0:
self.DOTS.append([(self.BLOCK_WIDTH * COLUMN),
(self.BLOCK_HEIGHT * ROW), 4, 4])
if self.MATRIX[ROW][COLUMN] == 1:
self.WALLS.append(pygame.draw.rect(MazeSurface, WHITE,
[((self.BLOCK_WIDTH) * COLUMN),
((self.BLOCK_HEIGHT) * ROW),
self.BLOCK_WIDTH, self.BLOCK_HEIGHT]))
class Main(Maze):
def __init__(self):
# Inherits Maze class
Maze.__init__(self)
self.DIRECTION = ""
self.SCORE = 0
def Movement(self):
key = pygame.key.get_pressed()
if key[pygame.K_LEFT] and not key[pygame.K_UP] \
and not key[pygame.K_DOWN]:
self.DIRECTION = "LEFT"
elif key[pygame.K_RIGHT] and not key[pygame.K_UP] \
and not key[pygame.K_DOWN]:
self.DIRECTION = "RIGHT"
elif key[pygame.K_UP] and not key[pygame.K_LEFT] \
and not key[pygame.K_RIGHT]:
self.DIRECTION = "UP"
elif key[pygame.K_DOWN] and not key[pygame.K_LEFT] \
and not key[pygame.K_RIGHT]:
self.DIRECTION = "DOWN"
def ContinueMovement(self):
if self.DIRECTION == "LEFT":
CurrentRect.x -= SPEED
self.WallDetection(-1, 0, CurrentRect)
if self.DIRECTION == "RIGHT":
CurrentRect.x += SPEED
self.WallDetection(1, 0, CurrentRect)
if self.DIRECTION == "UP":
CurrentRect.y -= SPEED
self.WallDetection(0, -1, CurrentRect)
if self.DIRECTION == "DOWN":
CurrentRect.y += SPEED
self.WallDetection(0, 1, CurrentRect)
def ChangeImage(self):
global CurrentSurface
if self.DIRECTION == "LEFT":
CurrentSurface = pygame.transform.rotate(PacManSurface, 180)
if self.DIRECTION == "RIGHT":
CurrentSurface = PacManSurface
if self.DIRECTION == "UP":
CurrentSurface = pygame.transform.rotate(PacManSurface, 90)
if self.DIRECTION == "DOWN":
CurrentSurface = pygame.transform.rotate(PacManSurface, 270)
def Teleport(self):
if CurrentRect.right < 0:
CurrentRect.right = SCREEN_WIDTH + 20
if CurrentRect.left > SCREEN_WIDTH:
CurrentRect.right = 0
def WallDetection(self, x, y, CurrentRect):
CurrentRect.right += x
for WALL in self.WALLS:
COLLIDE = CurrentRect.colliderect(WALL)
if COLLIDE:
if x < 0:
CurrentRect.left = WALL.right
elif x > 0:
CurrentRect.right = WALL.left
break
CurrentRect.top += y
for WALL in self.WALLS:
COLLIDE = CurrentRect.colliderect(WALL)
if COLLIDE:
if y < 0:
CurrentRect.top = WALL.bottom
if y > 0:
CurrentRect.bottom = WALL.top
break
def EatDots(self):
for ROW in range(len(self.MATRIX)):
for COLUMN in range(len(self.MATRIX[0])):
for DOT in self.DOTS:
CHOMP = CurrentRect.colliderect(DOT)
if CHOMP:
self.DOTS.remove(DOT)
self.MATRIX[ROW][COLUMN] = 3
self.SCORE += 10
return str(self.SCORE)
def DrawDots(self):
for POSITION in self.DOTS:
X = POSITION[0] + 13
Y = POSITION[1] + 13
WIDTH = POSITION[2]
HEIGHT = POSITION[3]
pygame.draw.circle(MazeSurface, YELLOW, (X, Y),
WIDTH // 2, HEIGHT // 2)
def EatGhosts(self):
pass
def EatPowerUp(self):
pass
def ShowText(self):
Font = pygame.font.Font("emulogic.ttf", 15)
OneUpText = Font.render("1UP", True, WHITE)
OneUpTextRect = OneUpText.get_rect(center = (70, 10))
OneUpScoreText = Font.render("00", True, WHITE)
UpdateScore = Main.EatDots(self)
if int(self.SCORE) > 0:
OneUpScoreText = Font.render(UpdateScore, True, WHITE)
OneUpScoreRect = OneUpScoreText.get_rect(center =
((SCREEN_WIDTH - 290)
// 2, 26))
HighScoreText = Font.render("High Score", True, WHITE)
HighScoreTextRect = HighScoreText.get_rect(center =
(SCREEN_WIDTH // 2, 10))
HighScoreNumber = Font.render("00", True, WHITE)
HighScoreNumberRect = HighScoreNumber.get_rect(center =
((SCREEN_WIDTH + 90)
// 2, 26))
SCREEN.blit(OneUpText, OneUpTextRect)
SCREEN.blit(OneUpScoreText, OneUpScoreRect)
SCREEN.blit(HighScoreText, HighScoreTextRect)
SCREEN.blit(HighScoreNumber, HighScoreNumberRect)
def PacManBite(self):
SCREEN.blit(PacManStartSurface, PacManStartRect)
pygame.display.update()
Player = Main()
BackgroundSurface = pygame.transform.scale(BackgroundSurface,
(Player.MAZE_WIDTH,
Player.MAZE_HEIGHT))
BackgroundRect = BackgroundSurface.get_rect()
MazeSurface = pygame.Surface((Player.MAZE_WIDTH, Player.MAZE_HEIGHT))
MazeRect = MazeSurface.get_rect(topleft = (Player.MAZE_OFFSET_X,
Player.MAZE_OFFSET_Y))
Player.DrawMaze(MazeSurface)
'''
pregame = True
while pregame:
if key button pressed:
pregame = False
run = True
'''
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
Player.Movement()
Player.ChangeImage()
Player.Teleport()
Player.ContinueMovement()
MazeSurface.blit(BackgroundSurface, BackgroundRect)
Player.DrawDots()
MazeSurface.blit(CurrentSurface, CurrentRect)
Player.PacManBite()
SCREEN.blit(MazeSurface, MazeRect)
#SCREEN.fill(BLACK)
Player.ShowText()
pygame.display.update()
CLOCK.tick(FPS)
pygame.quit()
所以我基本上有两个表面,主屏幕和 MazeSurface,我将迷宫、圆点、pacman 和背景 blit,然后将它们 blit 到主屏幕。所以出于某种原因,只有一个 pacman 图像被 blitted,这意味着我有 PacManStartSurface,它是闭着嘴的 PacMan,所以只有一个圆圈和 PacManSurface,它是 PacMan 面向右侧或我进入的任何方向,基本上我想重叠它们,以便 PacMan 图像重叠并产生咬住或咬住点的效果
因此您可以像这样更改背景图片的比例:
backgroundImage = pygame.transform.scale(backgroundImage, (width, height))
为了运动。你会加速,因为正在调用 Movement
函数和 ContinueMovement
函数并且它们都在移动你所以我让 Movement
函数不移动你。
def Movement(self):
key = pygame.key.get_pressed()
if key[pygame.K_LEFT]:
self.DIRECTION = "LEFT"
elif key[pygame.K_RIGHT]:
self.DIRECTION = "RIGHT"
elif key[pygame.K_UP]:
self.DIRECTION = "UP"
elif key[pygame.K_DOWN]:
self.DIRECTION = "DOWN"
def ContinueMovement(self):
if self.DIRECTION == "LEFT":
CurrentRect.x -= SPEED
self.WallDetection(-1, 0, CurrentRect)
if self.DIRECTION == "RIGHT":
CurrentRect.x += SPEED
self.WallDetection(1, 0, CurrentRect)
if self.DIRECTION == "UP":
CurrentRect.y -= SPEED
self.WallDetection(0, -1, CurrentRect)
if self.DIRECTION == "DOWN":
CurrentRect.y += SPEED
self.WallDetection(0, 1, CurrentRect)
你可以在这里看到我用 elif
语句
替换了长 if
语句
我还用这个替换了 Main.WallDetection(self, 0, 1, CurrentRect)
:self.WallDetection(0, 1, CurrentRect)
因为它更清晰,更容易理解
您还应该考虑让 Movement 函数接受这样的事件:def Movement(self, event):
并使用事件来检查按钮按下,而不是像这样:if event.button == PYGAME.K_LEFT
.
要绘制背景使其与迷宫的大小完全相同,您需要执行以下操作:
mazeHeight = (maze.BLOCK_HEIGHT + maze.MARGIN) * len(maze.MATRIX)
mazeWidth = (maze.BLOCK_WIDTH + maze.MARGIN) * len(maze.MATRIX[0])
backgroundImage = pygame.transform.scale(backgroundImage, (mazeWidth, mazeHeight))
首先你得到 mazeHeight
,这是通过将行数乘以每个块的高度来完成的
然后你得到 mazeWidth
通过将其中一行中的列数(哪一行无关紧要)乘以每个块的宽度
最后,您将背景图像的大小设置为 mazeWidth
和 mazeHeight
请注意,变量 maze
是 class Maze
的一个实例,它是这样构成的:maze = Maze()
Maze
class应该是这样的:
class Maze:
def __init__(self):
self.DOTS = []
self.WALLS = []
self.BLOCK_SIZE = 22
self.ROWS = 21
self.COLUMNS = 20
self.MARGIN = 3
self.OFFSET_Y = 40
# 0 - Dots
# 1 - Walls
# 2 - Power Up
# 3 - Empty Space
# 4 - Ghosts
self.MATRIX = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], \
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1], \
[1, 2, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 2, 1], \
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], \
[1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1], \
[1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1], \
[1, 1, 1, 1, 0, 1, 1, 1, 3, 1, 3, 1, 1, 1, 0, 1, 1, 1, 1], \
[3, 3, 3, 1, 0, 1, 3, 3, 3, 3, 3, 3, 3, 1, 0, 1, 3, 3, 3], \
[1, 1, 1, 1, 0, 1, 3, 1, 1, 1, 1, 1, 3, 1, 0, 1, 1, 1, 1], \
[0, 0, 0, 0, 0, 3, 3, 1, 4, 4, 4, 1, 3, 3, 0, 0, 0, 0, 0], \
[1, 1, 1, 1, 0, 1, 3, 1, 1, 1, 1, 1, 3, 1, 0, 1, 1, 1, 1], \
[3, 3, 3, 1, 0, 1, 3, 3, 3, 3, 3, 3, 3, 1, 0, 1, 3, 3, 3], \
[1, 1, 1, 1, 0, 1, 3, 1, 1, 1, 1, 1, 3, 1, 0, 1, 1, 1, 1], \
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1], \
[1, 2, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 2, 1], \
[1, 0, 0, 1, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 1, 0, 0, 1], \
[1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1], \
[1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1], \
[1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1], \
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], \
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
def DrawGrid(self):
for ROW in range(self.ROWS):
for COLUMN in range(self.COLUMNS - 1):
if self.MATRIX[ROW][COLUMN] == 0:
self.DOTS.append(pygame.draw.circle(SCREEN, YELLOW,
(((self.MARGIN + self.BLOCK_SIZE) * COLUMN) + self.BLOCK_SIZE/2,
((self.MARGIN + self.BLOCK_SIZE) * ROW) + self.OFFSET_Y + self.BLOCK_SIZE/2),
2))
if self.MATRIX[ROW][COLUMN] == 1:
self.WALLS.append(pygame.draw.rect(SCREEN, WHITE,
(((self.MARGIN + self.BLOCK_SIZE) * COLUMN),
((self.MARGIN + self.BLOCK_SIZE) * ROW) + self.OFFSET_Y,
self.BLOCK_SIZE, self.BLOCK_SIZE)))
我创建了一个 self.OFFSET_Y
变量,并添加了 self.BLOCK_SIZE/2
以使点位于块的中间
然后我像这样更改了 BackgroundSurface
的比例:
BackgroundSurface = pygame.transform.scale(BackgroundSurface, ((Player.BLOCK_SIZE + Player.MARGIN) * len(Player.MATRIX[0]), (Player.BLOCK_SIZE + Player.MARGIN) * len(Player.MATRIX)))
我将块大小与每个块之间的距离相加,然后将它们乘以块的数量以获得所有块的总大小
编辑:
所以我把 import time
放在脚本的顶部,因为我用它来制作 pacman bite
并且我在Main
class中的__init__
中添加了三个变量,像这样:
def __init__(self):
# Inherits Maze class
Maze.__init__(self)
self.timeBetweenBites = 0.2
self.lastBiteTime = time.time()
self.mouthOpen = False
self.DIRECTION = ""
self.SCORE = 0
我添加了 timeBetweenBites
,您可以更改它以使 Pacman
咬得更慢或更快
我添加了 lastBitTime
每次 Pacman
咬时都设置为当前时间(更改其外观)
然后我添加了mouthOpen
来知道Pacman's
嘴巴是张着还是闭着
我也像这样更改了 changeImage
函数:
def ChangeImage(self):
global CurrentSurface
if self.DIRECTION == "LEFT":
CurrentSurface = pygame.transform.rotate(CurrentSurface, 180)
if self.DIRECTION == "RIGHT":
CurrentSurface = CurrentSurface
if self.DIRECTION == "UP":
CurrentSurface = pygame.transform.rotate(CurrentSurface, 90)
if self.DIRECTION == "DOWN":
CurrentSurface = pygame.transform.rotate(CurrentSurface, 270)
我所做的只是将 PacManSurface 替换为 CurrentSurface
我把 PacManBite
函数改成这样:
def PacManBite(self):
global CurrentSurface
if time.time() - self.lastBiteTime >= self.timeBetweenBites:
self.lastBiteTime = time.time()
if self.mouthOpen:
CurrentSurface = PacManStartSurface
else:
CurrentSurface = PacManSurface
self.mouthOpen = not self.mouthOpen
if self.DIRECTION == "LEFT":
CurrentSurface = pygame.transform.rotate(CurrentSurface, 180)
if self.DIRECTION == "RIGHT":
CurrentSurface = CurrentSurface
if self.DIRECTION == "UP":
CurrentSurface = pygame.transform.rotate(CurrentSurface, 90)
if self.DIRECTION == "DOWN":
CurrentSurface = pygame.transform.rotate(CurrentSurface, 270)
我在这里做的是检查当前时间减去我上次更改 Pacman 表面的时间是否大于或等于我想在更改 Pacman 表面之前花费的时间。如果那是真的。
我将上次更改 Pacman's Surface 的时间设置为当前时间,因为我现在将更改它
然后我检查吃豆人的嘴是否张开。如果是我关闭它,如果不是我打开它。然后我切换 Pacman 的 mouthOpen 变量,因为我刚刚切换了 Pacman 的表面
然后我将精灵的旋转设置为吃豆人的旋转,就这样。
我注意到您忘记将 pygame.sprite.Sprite.__init__(self)
放在 PinkGhost
class 中并且脚本末尾的 pygame.quit
行几乎没有用
那应该有用,谢谢
这是我的代码:
import pygame
pygame.init()
pygame.display.set_caption("Pac-Man")
# Sets the size of the screen via (WIDTH, HEIGHT)
SCREEN_WIDTH = 478
SCREEN_HEIGHT = 608
# Speed of Characters
SPEED = 1
# Frames per second, how fast the game runs
FPS = 50
# Colors (RED,GREEN,BLUE)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
YELLOW = (255, 255, 0)
BLUE = (0, 0, 255)
HIGH_SCORE = 0
# Sets the WIDTH and HEIGHT of the window
WINDOW = (SCREEN_WIDTH, SCREEN_HEIGHT)
# Displays the screen
SCREEN = pygame.display.set_mode(WINDOW)
CLOCK = pygame.time.Clock()
PacManStartSurface = pygame.transform.scale(pygame.image.load
("PacManStart.png"), (24, 24))
PacManStartSurface.convert()
PacManStartRect = PacManStartSurface.get_rect(topleft =
(((SCREEN_WIDTH - 25) // 2),
(SCREEN_HEIGHT + 144) // 2))
PacManSurface = pygame.transform.scale(pygame.image.load
("PacManRight.png"), (24, 24))
PacManSurface.convert()
PacManRect = PacManStartSurface.get_rect(topleft =
(((SCREEN_WIDTH - 125) // 2),
(SCREEN_HEIGHT + 144) // 2))
CurrentSurface = PacManStartSurface
CurrentRect = PacManStartRect
BackgroundSurface = pygame.image.load("Background.png").convert()
class PacMan():
def __init__(self):
self.LIVES = 3
class PowerUp(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.transform.scale(pygame.image.load("PowerUp.png")
.convert(), (23, 23))
self.mask = pygame.mask.from_surface(self.image)
class YellowGhost(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.transform.scale(pygame.image.load
("YellowGhost.png")
.convert(), (23, 23))
self.rect = self.image.get_rect(topleft = (235, 347))
self.mask = pygame.mask.from_surface(self.image)
class RedGhost(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.transform.scale(pygame.image.load("RedGhost.png")
.convert(), (23, 23))
self.rect = self.image.get_rect(topleft = (235, 347))
self.mask = pygame.mask.from_surface(self.image)
class BlueGhost(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.transform.scale(pygame.image.load("BlueGhost.png")
.convert(), (23, 23))
self.rect = self.image.get_rect(topleft = (235, 347))
self.mask = pygame.mask.from_surface(self.image)
class PinkGhost(pygame.sprite.Sprite):
def __init__(self):
self.image = pygame.transform.scale(pygame.image.load("PinkGhost.png")
.convert(), (23, 23))
self.rect = self.image.get_rect(topleft = (235, 347))
self.mask = pygame.mask.from_surface(self.image)
class Maze():
def __init__(self):
self.DOTS = []
self.WALLS = []
self.BLOCK_WIDTH = 25
self.BLOCK_HEIGHT = 25
self.MAZE_OFFSET_X = 0
self.MAZE_OFFSET_Y = 50
self.MARGIN = 3
# 0 - Dots
# 1 - Walls
# 2 - Power Up
# 3 - Empty Space
# 4 - Ghosts
self.MATRIX = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], \
[1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1], \
[1,2,1,1,0,1,1,1,0,1,0,1,1,1,0,1,1,2,1], \
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], \
[1,0,1,1,0,1,0,1,1,1,1,1,0,1,0,1,1,0,1], \
[1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1], \
[1,1,1,1,0,1,1,1,3,1,3,1,1,1,0,1,1,1,1], \
[3,3,3,1,0,1,3,3,3,3,3,3,3,1,0,1,3,3,3], \
[1,1,1,1,0,1,3,1,1,1,1,1,3,1,0,1,1,1,1], \
[0,0,0,0,0,3,3,1,4,4,4,1,3,3,0,0,0,0,0], \
[1,1,1,1,0,1,3,1,1,1,1,1,3,1,0,1,1,1,1], \
[3,3,3,1,0,1,3,3,3,3,3,3,3,1,0,1,3,3,3], \
[1,1,1,1,0,1,3,1,1,1,1,1,3,1,0,1,1,1,1], \
[1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1], \
[1,2,1,1,0,1,1,1,0,1,0,1,1,1,0,1,1,2,1], \
[1,0,0,1,0,0,0,0,0,3,0,0,0,0,0,1,0,0,1], \
[1,1,0,1,0,1,0,1,1,1,1,1,0,1,0,1,0,1,1], \
[1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1], \
[1,0,1,1,1,1,1,1,0,1,0,1,1,1,1,1,1,0,1], \
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], \
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
# BackgroundImage(X, Y, WIDTH, HEIGHT)
self.MAZE_X = self.BLOCK_WIDTH * (len(self.MATRIX[0])
+ self.MAZE_OFFSET_X)
self.MAZE_Y = self.BLOCK_HEIGHT * (len(self.MATRIX)
+ self.MAZE_OFFSET_Y)
self.MAZE_WIDTH = self.BLOCK_WIDTH * len(self.MATRIX[0])
self.MAZE_HEIGHT = self.BLOCK_HEIGHT * len(self.MATRIX)
def DrawMaze(self, MazeSurface):
for ROW in range(len(self.MATRIX)):
for COLUMN in range(len(self.MATRIX[0])):
# Only saves the position of each dot
if self.MATRIX[ROW][COLUMN] == 0:
self.DOTS.append([(self.BLOCK_WIDTH * COLUMN),
(self.BLOCK_HEIGHT * ROW), 4, 4])
if self.MATRIX[ROW][COLUMN] == 1:
self.WALLS.append(pygame.draw.rect(MazeSurface, WHITE,
[((self.BLOCK_WIDTH) * COLUMN),
((self.BLOCK_HEIGHT) * ROW),
self.BLOCK_WIDTH, self.BLOCK_HEIGHT]))
class Main(Maze):
def __init__(self):
# Inherits Maze class
Maze.__init__(self)
self.DIRECTION = ""
self.SCORE = 0
def Movement(self):
key = pygame.key.get_pressed()
if key[pygame.K_LEFT] and not key[pygame.K_UP] \
and not key[pygame.K_DOWN]:
self.DIRECTION = "LEFT"
elif key[pygame.K_RIGHT] and not key[pygame.K_UP] \
and not key[pygame.K_DOWN]:
self.DIRECTION = "RIGHT"
elif key[pygame.K_UP] and not key[pygame.K_LEFT] \
and not key[pygame.K_RIGHT]:
self.DIRECTION = "UP"
elif key[pygame.K_DOWN] and not key[pygame.K_LEFT] \
and not key[pygame.K_RIGHT]:
self.DIRECTION = "DOWN"
def ContinueMovement(self):
if self.DIRECTION == "LEFT":
CurrentRect.x -= SPEED
self.WallDetection(-1, 0, CurrentRect)
if self.DIRECTION == "RIGHT":
CurrentRect.x += SPEED
self.WallDetection(1, 0, CurrentRect)
if self.DIRECTION == "UP":
CurrentRect.y -= SPEED
self.WallDetection(0, -1, CurrentRect)
if self.DIRECTION == "DOWN":
CurrentRect.y += SPEED
self.WallDetection(0, 1, CurrentRect)
def ChangeImage(self):
global CurrentSurface
if self.DIRECTION == "LEFT":
CurrentSurface = pygame.transform.rotate(PacManSurface, 180)
if self.DIRECTION == "RIGHT":
CurrentSurface = PacManSurface
if self.DIRECTION == "UP":
CurrentSurface = pygame.transform.rotate(PacManSurface, 90)
if self.DIRECTION == "DOWN":
CurrentSurface = pygame.transform.rotate(PacManSurface, 270)
def Teleport(self):
if CurrentRect.right < 0:
CurrentRect.right = SCREEN_WIDTH + 20
if CurrentRect.left > SCREEN_WIDTH:
CurrentRect.right = 0
def WallDetection(self, x, y, CurrentRect):
CurrentRect.right += x
for WALL in self.WALLS:
COLLIDE = CurrentRect.colliderect(WALL)
if COLLIDE:
if x < 0:
CurrentRect.left = WALL.right
elif x > 0:
CurrentRect.right = WALL.left
break
CurrentRect.top += y
for WALL in self.WALLS:
COLLIDE = CurrentRect.colliderect(WALL)
if COLLIDE:
if y < 0:
CurrentRect.top = WALL.bottom
if y > 0:
CurrentRect.bottom = WALL.top
break
def EatDots(self):
for ROW in range(len(self.MATRIX)):
for COLUMN in range(len(self.MATRIX[0])):
for DOT in self.DOTS:
CHOMP = CurrentRect.colliderect(DOT)
if CHOMP:
self.DOTS.remove(DOT)
self.MATRIX[ROW][COLUMN] = 3
self.SCORE += 10
return str(self.SCORE)
def DrawDots(self):
for POSITION in self.DOTS:
X = POSITION[0] + 13
Y = POSITION[1] + 13
WIDTH = POSITION[2]
HEIGHT = POSITION[3]
pygame.draw.circle(MazeSurface, YELLOW, (X, Y),
WIDTH // 2, HEIGHT // 2)
def EatGhosts(self):
pass
def EatPowerUp(self):
pass
def ShowText(self):
Font = pygame.font.Font("emulogic.ttf", 15)
OneUpText = Font.render("1UP", True, WHITE)
OneUpTextRect = OneUpText.get_rect(center = (70, 10))
OneUpScoreText = Font.render("00", True, WHITE)
UpdateScore = Main.EatDots(self)
if int(self.SCORE) > 0:
OneUpScoreText = Font.render(UpdateScore, True, WHITE)
OneUpScoreRect = OneUpScoreText.get_rect(center =
((SCREEN_WIDTH - 290)
// 2, 26))
HighScoreText = Font.render("High Score", True, WHITE)
HighScoreTextRect = HighScoreText.get_rect(center =
(SCREEN_WIDTH // 2, 10))
HighScoreNumber = Font.render("00", True, WHITE)
HighScoreNumberRect = HighScoreNumber.get_rect(center =
((SCREEN_WIDTH + 90)
// 2, 26))
SCREEN.blit(OneUpText, OneUpTextRect)
SCREEN.blit(OneUpScoreText, OneUpScoreRect)
SCREEN.blit(HighScoreText, HighScoreTextRect)
SCREEN.blit(HighScoreNumber, HighScoreNumberRect)
def PacManBite(self):
SCREEN.blit(PacManStartSurface, PacManStartRect)
pygame.display.update()
Player = Main()
BackgroundSurface = pygame.transform.scale(BackgroundSurface,
(Player.MAZE_WIDTH,
Player.MAZE_HEIGHT))
BackgroundRect = BackgroundSurface.get_rect()
MazeSurface = pygame.Surface((Player.MAZE_WIDTH, Player.MAZE_HEIGHT))
MazeRect = MazeSurface.get_rect(topleft = (Player.MAZE_OFFSET_X,
Player.MAZE_OFFSET_Y))
Player.DrawMaze(MazeSurface)
'''
pregame = True
while pregame:
if key button pressed:
pregame = False
run = True
'''
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
Player.Movement()
Player.ChangeImage()
Player.Teleport()
Player.ContinueMovement()
MazeSurface.blit(BackgroundSurface, BackgroundRect)
Player.DrawDots()
MazeSurface.blit(CurrentSurface, CurrentRect)
Player.PacManBite()
SCREEN.blit(MazeSurface, MazeRect)
#SCREEN.fill(BLACK)
Player.ShowText()
pygame.display.update()
CLOCK.tick(FPS)
pygame.quit()
所以我基本上有两个表面,主屏幕和 MazeSurface,我将迷宫、圆点、pacman 和背景 blit,然后将它们 blit 到主屏幕。所以出于某种原因,只有一个 pacman 图像被 blitted,这意味着我有 PacManStartSurface,它是闭着嘴的 PacMan,所以只有一个圆圈和 PacManSurface,它是 PacMan 面向右侧或我进入的任何方向,基本上我想重叠它们,以便 PacMan 图像重叠并产生咬住或咬住点的效果
因此您可以像这样更改背景图片的比例:
backgroundImage = pygame.transform.scale(backgroundImage, (width, height))
为了运动。你会加速,因为正在调用 Movement
函数和 ContinueMovement
函数并且它们都在移动你所以我让 Movement
函数不移动你。
def Movement(self):
key = pygame.key.get_pressed()
if key[pygame.K_LEFT]:
self.DIRECTION = "LEFT"
elif key[pygame.K_RIGHT]:
self.DIRECTION = "RIGHT"
elif key[pygame.K_UP]:
self.DIRECTION = "UP"
elif key[pygame.K_DOWN]:
self.DIRECTION = "DOWN"
def ContinueMovement(self):
if self.DIRECTION == "LEFT":
CurrentRect.x -= SPEED
self.WallDetection(-1, 0, CurrentRect)
if self.DIRECTION == "RIGHT":
CurrentRect.x += SPEED
self.WallDetection(1, 0, CurrentRect)
if self.DIRECTION == "UP":
CurrentRect.y -= SPEED
self.WallDetection(0, -1, CurrentRect)
if self.DIRECTION == "DOWN":
CurrentRect.y += SPEED
self.WallDetection(0, 1, CurrentRect)
你可以在这里看到我用 elif
语句
if
语句
我还用这个替换了 Main.WallDetection(self, 0, 1, CurrentRect)
:self.WallDetection(0, 1, CurrentRect)
因为它更清晰,更容易理解
您还应该考虑让 Movement 函数接受这样的事件:def Movement(self, event):
并使用事件来检查按钮按下,而不是像这样:if event.button == PYGAME.K_LEFT
.
要绘制背景使其与迷宫的大小完全相同,您需要执行以下操作:
mazeHeight = (maze.BLOCK_HEIGHT + maze.MARGIN) * len(maze.MATRIX)
mazeWidth = (maze.BLOCK_WIDTH + maze.MARGIN) * len(maze.MATRIX[0])
backgroundImage = pygame.transform.scale(backgroundImage, (mazeWidth, mazeHeight))
首先你得到 mazeHeight
,这是通过将行数乘以每个块的高度来完成的
然后你得到 mazeWidth
通过将其中一行中的列数(哪一行无关紧要)乘以每个块的宽度
最后,您将背景图像的大小设置为 mazeWidth
和 mazeHeight
请注意,变量 maze
是 class Maze
的一个实例,它是这样构成的:maze = Maze()
Maze
class应该是这样的:
class Maze:
def __init__(self):
self.DOTS = []
self.WALLS = []
self.BLOCK_SIZE = 22
self.ROWS = 21
self.COLUMNS = 20
self.MARGIN = 3
self.OFFSET_Y = 40
# 0 - Dots
# 1 - Walls
# 2 - Power Up
# 3 - Empty Space
# 4 - Ghosts
self.MATRIX = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], \
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1], \
[1, 2, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 2, 1], \
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], \
[1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1], \
[1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1], \
[1, 1, 1, 1, 0, 1, 1, 1, 3, 1, 3, 1, 1, 1, 0, 1, 1, 1, 1], \
[3, 3, 3, 1, 0, 1, 3, 3, 3, 3, 3, 3, 3, 1, 0, 1, 3, 3, 3], \
[1, 1, 1, 1, 0, 1, 3, 1, 1, 1, 1, 1, 3, 1, 0, 1, 1, 1, 1], \
[0, 0, 0, 0, 0, 3, 3, 1, 4, 4, 4, 1, 3, 3, 0, 0, 0, 0, 0], \
[1, 1, 1, 1, 0, 1, 3, 1, 1, 1, 1, 1, 3, 1, 0, 1, 1, 1, 1], \
[3, 3, 3, 1, 0, 1, 3, 3, 3, 3, 3, 3, 3, 1, 0, 1, 3, 3, 3], \
[1, 1, 1, 1, 0, 1, 3, 1, 1, 1, 1, 1, 3, 1, 0, 1, 1, 1, 1], \
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1], \
[1, 2, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 2, 1], \
[1, 0, 0, 1, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 1, 0, 0, 1], \
[1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1], \
[1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1], \
[1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1], \
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], \
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
def DrawGrid(self):
for ROW in range(self.ROWS):
for COLUMN in range(self.COLUMNS - 1):
if self.MATRIX[ROW][COLUMN] == 0:
self.DOTS.append(pygame.draw.circle(SCREEN, YELLOW,
(((self.MARGIN + self.BLOCK_SIZE) * COLUMN) + self.BLOCK_SIZE/2,
((self.MARGIN + self.BLOCK_SIZE) * ROW) + self.OFFSET_Y + self.BLOCK_SIZE/2),
2))
if self.MATRIX[ROW][COLUMN] == 1:
self.WALLS.append(pygame.draw.rect(SCREEN, WHITE,
(((self.MARGIN + self.BLOCK_SIZE) * COLUMN),
((self.MARGIN + self.BLOCK_SIZE) * ROW) + self.OFFSET_Y,
self.BLOCK_SIZE, self.BLOCK_SIZE)))
我创建了一个 self.OFFSET_Y
变量,并添加了 self.BLOCK_SIZE/2
以使点位于块的中间
然后我像这样更改了 BackgroundSurface
的比例:
BackgroundSurface = pygame.transform.scale(BackgroundSurface, ((Player.BLOCK_SIZE + Player.MARGIN) * len(Player.MATRIX[0]), (Player.BLOCK_SIZE + Player.MARGIN) * len(Player.MATRIX)))
我将块大小与每个块之间的距离相加,然后将它们乘以块的数量以获得所有块的总大小
编辑:
所以我把 import time
放在脚本的顶部,因为我用它来制作 pacman bite
并且我在Main
class中的__init__
中添加了三个变量,像这样:
def __init__(self):
# Inherits Maze class
Maze.__init__(self)
self.timeBetweenBites = 0.2
self.lastBiteTime = time.time()
self.mouthOpen = False
self.DIRECTION = ""
self.SCORE = 0
我添加了 timeBetweenBites
,您可以更改它以使 Pacman
咬得更慢或更快
我添加了 lastBitTime
每次 Pacman
咬时都设置为当前时间(更改其外观)
然后我添加了mouthOpen
来知道Pacman's
嘴巴是张着还是闭着
我也像这样更改了 changeImage
函数:
def ChangeImage(self):
global CurrentSurface
if self.DIRECTION == "LEFT":
CurrentSurface = pygame.transform.rotate(CurrentSurface, 180)
if self.DIRECTION == "RIGHT":
CurrentSurface = CurrentSurface
if self.DIRECTION == "UP":
CurrentSurface = pygame.transform.rotate(CurrentSurface, 90)
if self.DIRECTION == "DOWN":
CurrentSurface = pygame.transform.rotate(CurrentSurface, 270)
我所做的只是将 PacManSurface 替换为 CurrentSurface
我把 PacManBite
函数改成这样:
def PacManBite(self):
global CurrentSurface
if time.time() - self.lastBiteTime >= self.timeBetweenBites:
self.lastBiteTime = time.time()
if self.mouthOpen:
CurrentSurface = PacManStartSurface
else:
CurrentSurface = PacManSurface
self.mouthOpen = not self.mouthOpen
if self.DIRECTION == "LEFT":
CurrentSurface = pygame.transform.rotate(CurrentSurface, 180)
if self.DIRECTION == "RIGHT":
CurrentSurface = CurrentSurface
if self.DIRECTION == "UP":
CurrentSurface = pygame.transform.rotate(CurrentSurface, 90)
if self.DIRECTION == "DOWN":
CurrentSurface = pygame.transform.rotate(CurrentSurface, 270)
我在这里做的是检查当前时间减去我上次更改 Pacman 表面的时间是否大于或等于我想在更改 Pacman 表面之前花费的时间。如果那是真的。
我将上次更改 Pacman's Surface 的时间设置为当前时间,因为我现在将更改它
然后我检查吃豆人的嘴是否张开。如果是我关闭它,如果不是我打开它。然后我切换 Pacman 的 mouthOpen 变量,因为我刚刚切换了 Pacman 的表面
然后我将精灵的旋转设置为吃豆人的旋转,就这样。
我注意到您忘记将 pygame.sprite.Sprite.__init__(self)
放在 PinkGhost
class 中并且脚本末尾的 pygame.quit
行几乎没有用
那应该有用,谢谢