- 新增 jiyi.py 文件,实现字母翻牌记忆游戏功能 - 添加 youxijiemian.py 文件,创建游戏开始界面 - 使用 turtle 和 tkinter 模块分别实现游戏和界面 - 支持选择不同难度的游戏模式
316 lines
7.4 KiB
Python
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
|