闲着编写了一个火柴人的走路程序,让电脑更加丰富多彩。
#classes.py文件
import random
import pygame
import win32con
import win32api
import win32gui
import pyautogui
pygame.init()
pyautogui.FAILSAFE = False # 网上某位同志分享的内容,他说加了这句就能解决问题。
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
# 不同状态的编号
XMOVERIGHT = 2
XMOVELEFT = -2
YMOVEUP = 1
YMOVEDOWN = -1
YJUMPDOWN = -4
STOP = 0
SHOWING = 0.5
XRUNNINGRIGHT = 3
XRUNNINGLEFT = -3
FLYING = 7
WHAT = 8
LEFT_STEPPED__MOVE_RIGHT = -10 # 用于踩完后的移动
RIGHT_STEPPED__MOVE_LEFT = 10
STEPINGLEFT = -9
STEPINGRIGHT = 9
# 造型编号
TSCMIN = 2 # 走路编号(1)
TSCNUM = 6 # 走路编号(最后)
RUNMIN = 10 # 跑步编号(1)
RUNMAX = 15 # 跑步编号(最后)
TSCGOING = 1 # 手挥开
TSCRETURN = 0 # 手合拢
LEFTSTEP1 = -18
LEFTSTEP2 = -19
# 以下是用于踩任务栏后的等待,否则看不到效果
STEP_WAIT = 5
STEPPED_WAIT = 15
# 以下是屏幕宽高
# 不能直接FULLSCREEN,不然会影响到正常使用电脑
# WIDTH = 1440
# HEIGHT = 900
WIDTH, HEIGHT = pyautogui.size()
# 以下是火柴人移动范围边界值
YMIN = -100
YMAX = HEIGHT * (770 / 900)
XMIN = -70
XMAX = WIDTH
# 以下是真正的屏幕边界值
SMALLYMIN = 0
SMALLXMIN = 0
SMALLXMAX = WIDTH
class Screen: # 窗口类
def __init__(self, window_position=(0, 0)): # window_position是一个元组/列表
self.screen = pygame.display.set_mode((WIDTH, HEIGHT),
pygame.RESIZABLE | pygame.NOFRAME | pygame.HWSURFACE)
# pygame.display.set_icon(icon)
# pygame.display.set_caption(name + "Moving")
self.hwnd = pygame.display.get_wm_info()["window"] # 获取句柄
# SetWindowLong()设置窗口属性
# WS_EX_LAYED与SetLayeredWindowAttributes()连用控制透明度
win32gui.SetWindowLong(self.hwnd, win32con.GWL_EXSTYLE,
win32gui.SetWindowLong(self.hwnd, win32con.GWL_EXSTYLE,
win32con.WS_EX_LAYERED) | win32con.WS_EX_LAYERED | win32con.WS_EX_TOOLWINDOW)
# SetLayeredWindowAttributes()这个函数是一个控制窗口透明度的函数
# (hwnd,crKey(COLORREF类型,指定了用于分层窗口透明度的颜色键,这种颜色会变得透明),bAlpha(不透明度),dwFlags(特定操作))
win32gui.SetLayeredWindowAttributes(self.hwnd, win32api.RGB(0, 0, 0), 0, win32con.LWA_COLORKEY)
# 坐标
self.x = window_position[0]
self.y = window_position[1]
# 设置窗口位置
win32gui.SetWindowPos(self.hwnd, win32con.HWND_TOP | win32con.HWND_TOPMOST, self.x, self.y,
WIDTH, HEIGHT,
win32con.SWP_SHOWWINDOW)
screen = Screen() # 游戏所需的screen
def screen_blit(peoples, screen=screen):
screen.screen.fill(BLACK)
for i in peoples:
screen.screen.blit(i.people, (i.x, i.y))
pygame.display.flip()
class People: # 人类
def show(self):
self.showing = SHOWING
xx = random.randint(0, 10)
if xx < 2:
self.x = 1500
self.y = 785
self.control = XMOVELEFT
elif xx < 4:
self.x = -50
self.y = 785
self.control = XMOVERIGHT
else:
self.x = random.randint(0, 1400)
self.y = -80
self.control = YJUMPDOWN
def __init__(self, name="Blue", shortName="Blue", ChineseName="小蓝", small=3.7):
self.name = name
self.shortName = shortName # 简称
self.control = STOP # control控制状态,往哪里走
self.go = TSCGOING # go表示手张开还是关上
self.now = TSCMIN # now是现在的图片
self.ChineseName = ChineseName # 中文名
self.xmin = XMIN
self.xmax = XMAX
self.ymin = YMIN
self.ymax = YMAX
self.small = small
self.people = pygame.image.load(self.shortName + str(self.now) + ".png") # 现在显示的图片
# 大小调整 宽高各缩小small倍
width = int(self.people.get_width() // self.small)
height = int(self.people.get_height() // self.small)
self.people = pygame.transform.scale(self.people, (width, height))
self.show()
def edge_control(self):
# 以下是边界控制,防止人走远
# 会走出屏幕一点
if self.x < self.xmin:
if not self.showing:
self.x += 10
elif self.x > self.xmax:
if not self.showing:
self.x -= 10
if self.y < self.ymin:
if not self.showing:
self.y += 20
elif self.y > self.ymax:
self.y = YMAX
else:
if self.x > SMALLXMIN and self.x < SMALLXMAX and self.y > SMALLYMIN:
self.showing = STOP
def blit(self, draw_screen=screen):
self.people = pygame.image.load(self.shortName + str(self.now) + ".png") # 现在显示的图片
# 大小调整 宽高各缩小small倍
width = int(self.people.get_width() // self.small)
height = int(self.people.get_height() // self.small)
self.people = pygame.transform.scale(self.people, (width, height))
draw_screen.screen.blit(self.people, (self.x, self.y)) # 绘制人物
def change_control(self):
to_control = random.randint(-30, 50)
if to_control >= -30 and to_control < -20: # 10
self.control = XRUNNINGLEFT # 10
elif to_control < -5: # 15
self.control = XMOVELEFT
elif to_control < 0: # 5
self.control = YMOVEDOWN
elif to_control <= 13: # 14
self.control = STOP
elif to_control < 20: # 6
self.control = YMOVEUP
elif to_control < 35: # 15
self.control = XMOVERIGHT
elif to_control < 45: # 10
self.control = XRUNNINGRIGHT
elif to_control <= 50: # 1
self.control = YJUMPDOWN
if self.control == XMOVELEFT: # 走路的初始造型
self.now = -TSCMIN
self.go = TSCGOING
elif self.control == XMOVERIGHT: # 走路的初始造型
self.now = TSCMIN
self.go = TSCGOING
elif self.control == XRUNNINGLEFT:
self.now = -RUNMIN
elif self.control == XRUNNINGRIGHT:
self.now = RUNMIN
def move(self):
self.blit()
if random.randint(1, 100) == 1 and not self.showing: # 100分之1的概率会调整状态
self.change_control()
if not self.control: # STOP状态(STOP=0)
self.now = WHAT
return
if self.control == XMOVERIGHT or self.control == LEFT_STEPPED__MOVE_RIGHT: # 向右状态
self.x += XMOVERIGHT # x+=4
# 走路时,手先张开再合上
if self.go: # 手张开
if self.now == TSCNUM: # TSCNUM是最大值
self.go = TSCRETURN # go改成“手关上”
self.now -= 1
else:
self.now += 1
else: # 手关上
if self.now == TSCMIN: # TSCMIN是最小值
self.go = TSCGOING
self.now += 1
else:
self.now -= 1
elif self.control == XMOVELEFT: # 向左走,方向就是反过来的,图片号是向右的相反数
self.x += XMOVELEFT # x-=4
if self.go:
if self.now == -TSCNUM:
self.now += 1
self.go = TSCRETURN
else:
self.now -= 1
else:
if self.now == -TSCMIN:
self.now -= 1
self.go = TSCGOING
else:
self.now += 1
elif self.control == YMOVEUP: # 向上
self.now = FLYING
self.go = TSCGOING
self.y -= YMOVEUP * 2
elif self.control == YJUMPDOWN: # 向下
self.now = FLYING
self.go = TSCGOING
self.y -= YJUMPDOWN * 20 # 跳下来!
elif self.control == XRUNNINGRIGHT:
# 跑步时,无需分手张开还是合上的情况
if self.now < RUNMAX:
self.now += 1
else:
self.now = RUNMIN
self.x += XRUNNINGRIGHT * 2
elif self.control == XRUNNINGLEFT:
if self.now > -RUNMAX:
self.now -= 1
else:
self.now = -RUNMIN
self.x += XRUNNINGLEFT * 2
elif self.control == YMOVEDOWN: # 向下
self.now = FLYING
self.go = TSCGOING
self.y += YMOVEUP * 2
self.edge_control()
def key_to_control(self, event, left=pygame.K_LEFT, right=pygame.K_RIGHT, up=pygame.K_UP, down=pygame.K_DOWN,
stop=pygame.K_SPACE): # 为方便,有时用键盘控制移动
if event.type == pygame.KEYDOWN:
if event.key == left:
self.control = XMOVELEFT
self.now = -TSCMIN
self.go = TSCGOING
self.x -= 200
elif event.key == right:
self.control = XMOVERIGHT
self.now = TSCMIN
self.go = TSCGOING
self.x += 200
if event.key == up:
self.y -= 150
elif event.key == down:
self.y += 150
if event.key == stop:
self.control = STOP
def __str__(self): # 返回直观信息
return self.name + ' ' + self.ChineseName
class TheSecondComing(People):
def __init__(self):
self.steps = 0
People.__init__(self, "TheSecondComing", "TSC", "再临", 4.4)
def move(self):
self.blit()
# 再临者的踩任务栏功能!
if self.x > 0 and self.x <= 50 and self.y == YMAX:
if self.control != LEFT_STEPPED__MOVE_RIGHT:
if self.control != LEFT_STEPPED__MOVE_RIGHT and self.now != LEFTSTEP1 and self.now != LEFTSTEP2:
self.control = STEPINGLEFT
self.now = LEFTSTEP1
return
elif self.now == LEFTSTEP1 or self.now == LEFTSTEP2:
if self.steps < STEP_WAIT:
self.steps += 1
return
elif self.steps == STEP_WAIT:
self.now = LEFTSTEP2
# 踩任务栏操作
self.y += 10
mouse_position = pyautogui.position()
pyautogui.click(0, HEIGHT)
pyautogui.moveTo(x=mouse_position[0], y=mouse_position[1])
self.steps += 1
elif self.steps < STEPPED_WAIT:
self.now = LEFTSTEP2
self.steps += 1
return
else:
self.control = LEFT_STEPPED__MOVE_RIGHT
self.now = TSCMIN
self.steps = 0
People.move(self)
#main.py文件
import time
import sys
import threading
from classes import *
#设置定时器
CLOCK = pygame.time.Clock()
def game_quit():
time.sleep(0.2)
pygame.quit()
sys.exit()
def main():
theSecondComing = TheSecondComing()
Blue = People() # small默认值为3.7
Red = People("Red", "Red", "小红")
Green = People("Green", "Green", "小绿")
Yellow = People("Yellow", "Ye", "小黄")
Purple = People("Purple", "p", "小紫")
PEOPLES = {theSecondComing, Blue, Red, Green, Yellow, Purple}
while True: # 游戏循环
tscThread = threading.Thread(target=theSecondComing.move(), args=())
blueThread = threading.Thread(target=Blue.move(), args=())
redThread = threading.Thread(target=Red.move(), args=())
greenThread = threading.Thread(target=Green.move(), args=())
yellowThread = threading.Thread(target=Yellow.move(), args=())
PurpleThread = threading.Thread(target=Purple.move(), args=())
THREADS = (tscThread, blueThread, redThread, greenThread, yellowThread, PurpleThread)
for i in THREADS: # 线程一起开始执行
i.start()
screen_blit(PEOPLES)
for e in pygame.event.get():
if e.type == pygame.QUIT:
game_quit()
if e.type == pygame.KEYDOWN:
if e.key == pygame.K_q:
game_quit()
theSecondComing.key_to_control(e)
Blue.key_to_control(e, pygame.K_a, pygame.K_d, pygame.K_w, pygame.K_s)
Red.key_to_control(e, pygame.K_j, pygame.K_l, pygame.K_i, pygame.K_k)
Green.key_to_control(e)
Yellow.key_to_control(e, pygame.K_a, pygame.K_d, pygame.K_w, pygame.K_s)
screen_blit(PEOPLES)
for i in THREADS:
i.join()
CLOCK.tick(24)
if __name__ == "__main__":
main()
(鸣谢:角色原型来自AlanBecker)