sairate 5488a216f2 feat(第7讲 字母卡牌): 实现记忆游戏并添加开始界面
- 新增 jiyi.py 文件,实现字母翻牌记忆游戏功能
- 添加 youxijiemian.py 文件,创建游戏开始界面
- 使用 turtle 和 tkinter 模块分别实现游戏和界面
- 支持选择不同难度的游戏模式
2025-11-16 13:29:06 +08:00

316 lines
7.4 KiB
Python

import math
import pygame
from pgzero.actor import Actor, POS_TOPLEFT, ANCHOR_CENTER, transform_anchor
from pgzero import game, loaders
import types
import sys
import time
mod = sys.modules['__main__']
_fullscreen = False
def set_fullscreen():
global _fullscreen
mod.screen.surface = pygame.display.set_mode((mod.WIDTH, mod.HEIGHT), pygame.FULLSCREEN)
_fullscreen = True
def set_windowed():
global _fullscreen
mod.screen.surface = pygame.display.set_mode((mod.WIDTH, mod.HEIGHT))
_fullscreen = False
def toggle_fullscreen():
if _fullscreen:
set_windowed()
else:
set_fullscreen()
def hide_mouse():
pygame.mouse.set_visible(False)
def show_mouse():
pygame.mouse.set_visible(True)
class Actor(Actor):
def __init__(self, image, pos=POS_TOPLEFT, anchor=ANCHOR_CENTER, **kwargs):
self._flip_x = False
self._flip_y = False
self._scale = 1
self._mask = None
self._animate_counter = 0
self.fps = 5
self.direction = 0
super().__init__(image, pos, anchor, **kwargs)
def distance_to(self, actor):
dx = actor.x - self.x
dy = actor.y - self.y
return math.sqrt(dx**2 + dy**2)
def direction_to(self, actor):
dx = actor.x - self.x
dy = self.y - actor.y
angle = math.degrees(math.atan2(dy, dx))
if angle > 0:
return angle
return 360 + angle
def move_towards(self, actor, dist):
angle = math.radians(self.direction_to(actor))
dx = dist * math.cos(angle)
dy = dist * math.sin(angle)
self.x += dx
self.y -= dy
def point_towards(self, actor):
print(self.direction_to(actor))
self.angle = self.direction_to(actor)
def move_in_direction(self, dist):
angle = math.radians(self.direction)
dx = dist * math.cos(angle)
dy = dist * math.sin(angle)
self.x += dx
self.y -= dy
def move_forward(self, dist):
angle = math.radians(self.angle)
dx = dist * math.cos(angle)
dy = dist * math.sin(angle)
self.x += dx
self.y -= dy
def move_left(self, dist):
angle = math.radians(self.angle + 90)
dx = dist * math.cos(angle)
dy = dist * math.sin(angle)
self.x += dx
self.y -= dy
def move_right(self, dist):
angle = math.radians(self.angle - 90)
dx = dist * math.cos(angle)
dy = dist * math.sin(angle)
self.x += dx
self.y -= dy
def move_back(self, dist):
angle = math.radians(self.angle)
dx = -dist * math.cos(angle)
dy = -dist * math.sin(angle)
self.x += dx
self.y -= dy
@property
def images(self):
return self._images
@images.setter
def images(self, images):
self._images = images
if len(self._images) != 0:
self.image = self._images[0]
def next_image(self):
if self.image in self._images:
current = self._images.index(self.image)
if current == len(self._images) - 1:
self.image = self._images[0]
else:
self.image = self._images[current + 1]
else:
self.image = self._images[0]
def animate(self):
now = int(time.time() * self.fps)
if now != self._animate_counter:
self._animate_counter = now
self.next_image()
@property
def angle(self):
return self._angle
@angle.setter
def angle(self, angle):
self._angle = angle
self._transform_surf()
@property
def scale(self):
return self._scale
@scale.setter
def scale(self, scale):
self._scale = scale
self._transform_surf()
@property
def flip_x(self):
return self._flip_x
@flip_x.setter
def flip_x(self, flip_x):
self._flip_x = flip_x
self._transform_surf()
@property
def flip_y(self):
return self._flip_y
@flip_y.setter
def flip_y(self, flip_y):
self._flip_y = flip_y
self._transform_surf()
@property
def image(self):
return self._image_name
@image.setter
def image(self, image):
self._image_name = image
self._orig_surf = self._surf = loaders.images.load(image)
self._update_pos()
self._transform_surf()
def _transform_surf(self):
self._surf = self._orig_surf
p = self.pos
if self._scale != 1:
size = self._orig_surf.get_size()
self._surf = pygame.transform.scale(self._surf, (int(size[0] * self.scale), int(size[1] * self.scale)))
if self._flip_x:
self._surf = pygame.transform.flip(self._surf, True, False)
if self._flip_y:
self._surf = pygame.transform.flip(self._surf, False, True)
self._surf = pygame.transform.rotate(self._surf, self._angle)
self.width, self.height = self._surf.get_size()
w, h = self._orig_surf.get_size()
ax, ay = self._untransformed_anchor
anchor = transform_anchor(ax, ay, w, h, self._angle)
self._anchor = (anchor[0] * self.scale, anchor[1] * self.scale)
self.pos = p
self._mask = None
def collidepoint_pixel(self, x, y=0):
if isinstance(x, tuple):
y = x[1]
x = x[0]
if self._mask == None:
self._mask = pygame.mask.from_surface(self._surf)
xoffset = int(x - self.left)
yoffset = int(y - self.top)
if xoffset < 0 or yoffset < 0:
return 0
width, height = self._mask.get_size()
if xoffset > width or yoffset > height:
return 0
return self._mask.get_at((xoffset, yoffset))
def collide_pixel(self, actor):
for a in [self, actor]:
if a._mask == None:
a._mask = pygame.mask.from_surface(a._surf)
xoffset = int(actor.left - self.left)
yoffset = int(actor.top - self.top)
return self._mask.overlap(actor._mask, (xoffset, yoffset))
def collidelist_pixel(self, actors):
for i in range(len(actors)):
if self.collide_pixel(actors[i]):
return i
return -1
def collidelistall_pixel(self, actors):
collided = []
for i in range(len(actors)):
if self.collide_pixel(actors[i]):
collided.append(i)
return collided
def obb_collidepoints(self, actors):
angle = math.radians(self._angle)
costheta = math.cos(angle)
sintheta = math.sin(angle)
width, height = self._orig_surf.get_size()
half_width = width / 2
half_height = height / 2
i = 0
for actor in actors:
tx = actor.x - self.x
ty = actor.y - self.y
rx = tx * costheta - ty * sintheta
ry = ty * costheta + tx * sintheta
if rx > -half_width and rx < half_width and ry > -half_height and ry < half_height:
return i
i += 1
return -1
def obb_collidepoint(self, x, y=0):
if isinstance(x, tuple):
y = x[1]
x = x[0]
angle = math.radians(self._angle)
costheta = math.cos(angle)
sintheta = math.sin(angle)
width, height = self._orig_surf.get_size()
half_width = width / 2
half_height = height / 2
tx = x - self.x
ty = y - self.y
rx = tx * costheta - ty * sintheta
ry = ty * costheta + tx * sintheta
if rx > -half_width and rx < half_width and ry > -half_height and ry < half_height:
return True
return False
def circle_collidepoints(self, radius, actors):
rSquare = radius ** 2
i = 0
for actor in actors:
dSquare = (actor.x - self.x)**2 + (actor.y - self.y)**2
if dSquare < rSquare:
return i
i += 1
return -1
def circle_collidepoint(self, radius, x, y=0):
if isinstance(x, tuple):
y = x[1]
x = x[0]
rSquare = radius ** 2
dSquare = (x - self.x)**2 + (y - self.y)**2
if dSquare < rSquare:
return True
return False
def draw(self):
game.screen.blit(self._surf, self.topleft)
def get_rect(self):
return self._rect