import pygame, sys
from pygame.locals import *
from functools import wraps
from collections import defaultdict
import win32gui, win32api
from win32.lib import win32con
from itertools import repeat, cycle
# Constants
SCREEN_WIDTH, SCREEN_HEIGHT = 400, 300
DEFAULT_SPEED = (1, 1)
KEY_DIRECTIONS = {
K_LEFT: ("左", (-3, 0)),
K_RIGHT: ("右", (3, 0)),
K_UP: ("上", (0, -3)),
K_DOWN: ("下", (0, 3))
}
def make_window_transparent(hwnd):
win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE) | win32con.WS_EX_LAYERED)
win32gui.SetLayeredWindowAttributes(hwnd, win32api.RGB(0, 0, 0), 0, win32con.LWA_COLORKEY)
class Route:
def __init__(self):
self.lib = defaultdict(lambda: lambda e: ...)
def __call__(self, routepath):
def warpper(func):
self.lib[routepath] = func
@wraps(func)
def inner_wrapped(*args):
return func(*args)
return inner_wrapped
return warpper
class Game:
def __init__(self):
pygame.init()
self.route = Route()
self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.NOFRAME)
self.rect = self.screen.get_rect()
self._make_window_transparent()
self.clock = pygame.time.Clock()
self.heros = pygame.sprite.Group()
def _make_window_transparent(self):
hwnd = pygame.display.get_wm_info()["window"]
make_window_transparent(hwnd)
def run(self):
while True:
for event in pygame.event.get():
self.route.lib[event.type](event)
self.screen.fill((0, 0, 0, 0))
self.heros.update()
self.heros.draw(self.screen)
pygame.display.flip()
self.clock.tick(60)
game = Game()
class Hero(pygame.sprite.Sprite):
def __init__(self, image_path, position=(100, 100), speed=DEFAULT_SPEED, image_direction="下左右上", image_scale=1):
super().__init__()
self.image_ = pygame.image.load(image_path)
self.image_ = pygame.transform.scale(self.image_, (self.image_.get_width() * image_scale, self.image_.get_height() * image_scale))
self.state = "下"
self.speed = speed
self.width, self.height = self.image_.get_size()
self.tile_width = self.width // 4
self.tile_height = self.height // 4
self.image_dict = self._create_animation_frames(image_direction)
self.rect = self.image_dict[self.state][0].get_rect()
self.image_dict = {key: cycle(value) for key, value in self.image_dict.items()}
self.rect.center = position
game.heros.add(self)
def _create_animation_frames(self, image_direction):
image_dict = {direct: [] for direct in image_direction}
for row, key in enumerate(image_dict.keys()):
for col in range(4):
x = col * self.tile_width
y = row * self.tile_height
tile = self.image_.subsurface((x, y, self.tile_width, self.tile_height))
image_dict[key].extend([tile] * 10)
return image_dict
@property
def image(self):
return self.image_dict[self.state].__next__()
def update(self):
self.rect.move_ip(self.speed)
if self.rect.top < 0:
self.speed = (self.speed[0], -self.speed[1])
self.state = "下"
elif self.rect.bottom > game.rect.height:
self.speed = (self.speed[0], -self.speed[1])
self.state = "上"
if self.rect.left < 0:
self.speed = (-self.speed[0], self.speed[1])
self.state = "右"
elif self.rect.right > game.rect.width:
self.speed = (-self.speed[0], self.speed[1])
self.state = "左"
shero = Hero("girl.png", (100, 100), DEFAULT_SPEED, "下左右上", image_scale=1.5)
hero = Hero("man.png", (200, 200), DEFAULT_SPEED, "下左上右", image_scale=2)
@game.route(KEYDOWN)
def keydown(e):
if e.key == K_ESCAPE:
pygame.quit()
sys.exit()
elif e.key in KEY_DIRECTIONS:
state, speed = KEY_DIRECTIONS[e.key]
for character in [hero, shero]:
character.state, character.speed = state, speed
@game.route(MOUSEMOTION)
def mousemotion(e):
pass
@game.route(MOUSEBUTTONDOWN)
def mousebuttondown(e):
pass
game.run()
精灵图:

girl.png

man.png
运行后:

桌面精灵