一个简单的火柴人移动程序

闲着编写了一个火柴人的走路程序,让电脑更加丰富多彩。

#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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值