首页 > 编程语言 >python实现赛博宠物(纯代码无需素材)

python实现赛博宠物(纯代码无需素材)

时间:2024-11-13 16:47:56浏览次数:3  
标签:draw python 赛博 self 宠物 current action ellipse fill

1、创作背景

        今天如往常一样来上班,一进公司就看见财务小姐姐闷闷不乐,就走过去跟她聊天,她说她很想养一只小狗,但是家里面不同意,怕把家里弄得乱七八糟。看着小姐姐悲伤的样子,我恏大力最舍不得小姐姐不开熏,所以我恏大力就要出来帮助美丽的财务小姐姐咯。

2、技术选择

        Python             (对于目前的打工人来说,学会python真的是可以提高大部分的工作效率)

3、程序设计

        1.对于一个桌面小宠物来说,首先得有这只宠物的样式,但是如果用素材的话那可玩性就很低了,我这边的方法就是可以无素材独立创作宠物样式!!!

        首先先来写一个创建宠物样式的程序。【create_folders.py】

代码直接付给大家,注释都在代码中,各位可随意修改。

import os
from PIL import Image, ImageDraw

def create_folder_structure():
    # 创建主文件夹
    os.makedirs("images", exist_ok=True)
    
    def create_dog_image(filename, is_sleeping=False, is_walking=False, is_happy=False, is_eating=False, frame=1):
        # 创建一个128x128的图片(加大尺寸以容纳更多细节)
        img = Image.new('RGBA', (128, 128), (0, 0, 0, 0))
        draw = ImageDraw.Draw(img)
        
        # 颜色定义
        white = (255, 255, 255)  # 主体颜色
        pink = (255, 218, 233)   # 耳朵内部
        black = (0, 0, 0)        # 眼睛和鼻子
        
        if is_sleeping:
            # 睡觉状态:趴着的狗
            # 身体
            draw.ellipse([40, 70, 90, 95], fill=white)  # 身体
            
            # 尾巴(趴着)
            draw.ellipse([85, 65, 95, 75], fill=white)
            
            # 头
            draw.ellipse([25, 60, 60, 90], fill=white)   # 头部
            
            # 耳朵(趴下)
            draw.ellipse([30, 55, 45, 70], fill=white)    # 左耳外部
            draw.ellipse([35, 58, 42, 67], fill=pink)     # 左耳内部
            draw.ellipse([40, 55, 55, 70], fill=white)    # 右耳外部
            draw.ellipse([45, 58, 52, 67], fill=pink)     # 右耳内部
            
            # 闭着的眼睛
            draw.line([35, 75, 40, 75], fill=black, width=2)  # 左眼
            draw.line([45, 75, 50, 75], fill=black, width=2)  # 右眼
            
            # 鼻子
            draw.ellipse([40, 78, 45, 83], fill=black)
            
            # 腿(趴着)
            draw.ellipse([45, 90, 55, 98], fill=white)    # 前腿
            draw.ellipse([75, 90, 85, 98], fill=white)    # 后腿
            
        else:
            # 正常状态:站着的狗
            # 身体
            draw.ellipse([45, 60, 85, 90], fill=white)  # 身体
            
            # 尾巴(摇动效果)
            if frame == 1:
                draw.arc([75, 45, 95, 65], 0, 180, fill=white, width=4)
            else:
                draw.arc([75, 45, 95, 65], -30, 150, fill=white, width=4)
            
            # 腿
            if is_walking:
                # 走路状态:交替抬腿
                if frame == 1:
                    draw.ellipse([50, 85, 60, 100], fill=white)    # 左前腿
                    draw.ellipse([70, 88, 80, 103], fill=white)    # 右前腿
                else:
                    draw.ellipse([50, 88, 60, 103], fill=white)    # 左前腿
                    draw.ellipse([70, 85, 80, 100], fill=white)    # 右前腿
            else:
                # 站立状态
                draw.ellipse([50, 85, 60, 100], fill=white)    # 左前腿
                draw.ellipse([70, 85, 80, 100], fill=white)    # 右前腿
            
            # 头
            draw.ellipse([30, 45, 65, 75], fill=white)   # 头部
            
            # 耳朵
            draw.ellipse([35, 35, 50, 50], fill=white)    # 左耳外部
            draw.ellipse([38, 38, 47, 47], fill=pink)     # 左耳内部
            draw.ellipse([45, 35, 60, 50], fill=white)    # 右耳外部
            draw.ellipse([48, 38, 57, 47], fill=pink)     # 右耳内部
            
            # 眼睛
            draw.ellipse([38, 55, 43, 60], fill=black)    # 左眼
            draw.ellipse([52, 55, 57, 60], fill=black)    # 右眼
            
            # 鼻子和嘴
            draw.ellipse([45, 62, 50, 67], fill=black)    # 鼻子
            draw.arc([40, 62, 55, 72], 0, 180, fill=black, width=1)  # 微笑
        
        if is_happy:
            # 开心状态:尾巴摇动幅度更大,眼睛变成月牙形
            # 基本形态与正常状态相同,但有以下变化:
            
            # 身体
            draw.ellipse([45, 60, 85, 90], fill=white)
            
            # 摇动的尾巴(幅度更大)
            if frame == 1:
                draw.arc([75, 40, 95, 65], -30, 150, fill=white, width=4)
            else:
                draw.arc([75, 45, 95, 70], 30, 210, fill=white, width=4)
            
            # 月牙形眼睛
            draw.arc([38, 55, 43, 60], 0, 180, fill=black, width=2)
            draw.arc([52, 55, 57, 60], 0, 180, fill=black, width=2)
            
            # 微笑
            draw.arc([40, 62, 55, 72], 0, 180, fill=black, width=2)
        
        elif is_eating:
            # 吃东西状态:低头,嘴巴张开
            # 身体
            draw.ellipse([45, 60, 85, 90], fill=white)
            
            # 低头的姿势
            draw.ellipse([30, 55, 65, 85], fill=white)
            
            # 张开的嘴
            if frame == 1:
                draw.arc([40, 70, 55, 80], 0, 180, fill=black, width=2)
            else:
                draw.arc([40, 70, 55, 80], 30, 150, fill=black, width=2)
        
        img.save(f"images/{filename}")
    
    # 创建各种状态的小狗图片
    # 正常状态
    create_dog_image("normal_1.png", frame=1)
    create_dog_image("normal_2.png", frame=2)
    
    # 睡觉状态
    create_dog_image("sleep_1.png", is_sleeping=True, frame=1)
    create_dog_image("sleep_2.png", is_sleeping=True, frame=2)
    
    # 走路状态
    create_dog_image("walk_1.png", is_walking=True, frame=1)
    create_dog_image("walk_2.png", is_walking=True, frame=2)
    
    # 开心状态
    create_dog_image("happy_1.png", is_happy=True, frame=1)
    create_dog_image("happy_2.png", is_happy=True, frame=2)
    
    # 吃东西状态
    create_dog_image("eat_1.png", is_eating=True, frame=1)
    create_dog_image("eat_2.png", is_eating=True, frame=2)

if __name__ == "__main__":
    create_folder_structure()
    print("文件夹和小狗图片创建完成!")

        好的,这段程序运行后就会在当前目录下生成一个images文件夹来存放生成的素材。 

        我设置的小狗样式就是这个样子的,大家可以发挥自己的想法设计自己的宠物,可以在评论区分享各位的宠物样式。

4、主程序

        2.然后现在开始实现主程序设计,主要是包括宠物自身的动作,然后活动的范围,以及与人的互动过程。

        代码依旧附下:(注释都在代码中)

import sys
import random
from PyQt5.QtWidgets import (QApplication, QMainWindow, QLabel, QMenu, 
                            QSystemTrayIcon, QAction, QMessageBox)
from PyQt5.QtCore import Qt, QTimer, QPoint
from PyQt5.QtGui import QPixmap, QIcon

class DesktopPet(QMainWindow):
    def __init__(self):
        super().__init__()
        # 初始化状态
        self.is_following_mouse = False
        self.is_sleeping = False
        self.current_action = "normal"
        
        # 加载动画帧并验证
        self.animations = {}
        try:
            self.animations = {
                "normal": [
                    self.load_and_verify_image("images/normal_1.png"),
                    self.load_and_verify_image("images/normal_2.png")
                ],
                "sleeping": [
                    self.load_and_verify_image("images/sleep_1.png"),
                    self.load_and_verify_image("images/sleep_2.png")
                ],
                "walking": [
                    self.load_and_verify_image("images/walk_1.png"),
                    self.load_and_verify_image("images/walk_2.png")
                ],
                "happy": [
                    self.load_and_verify_image("images/happy_1.png"),
                    self.load_and_verify_image("images/happy_2.png")
                ],
                "eating": [
                    self.load_and_verify_image("images/eat_1.png"),
                    self.load_and_verify_image("images/eat_2.png")
                ]
            }
        except Exception as e:
            print(f"加载图片时出错: {e}")
            sys.exit(1)
            
        self.current_frame = 0
        self.initUI()
        self.setupTimers()
        
        # 获取屏幕尺寸
        self.screen = QApplication.primaryScreen().geometry()
        
        # 设置活动范围(默认为整个屏幕)
        self.movement_area = {
            'left': self.screen.width() // 2,  # 从屏幕中间开始
            'top': 0,  # 从顶部开始
            'right': self.screen.width(),  # 到屏幕右边
            'bottom': self.screen.height() // 2  # 到屏幕中间
        }
        
        # 添加自动移动定时器
        self.movement_timer = QTimer(self)
        self.movement_timer.timeout.connect(self.auto_move)
        self.movement_timer.start(3000)  # 每3秒移动一次
        
        # 移动目标点
        self.target_pos = None
        
        # 添加新的状态和计数器
        self.is_dragging = False
        self.is_happy = False
        self.pet_mood = 100  # 心情值(最大100)
        self.energy = 100    # 能量值(最大100)
        
        # 添加状态计时器
        self.status_timer = QTimer(self)
        self.status_timer.timeout.connect(self.update_status)
        self.status_timer.start(10000)  # 每10秒更新一次状态
    
    def initUI(self):
        # 设置窗口属性
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.SubWindow)
        self.setAttribute(Qt.WA_TranslucentBackground)
        
        # 创建标签用于显示图片
        self.pet_label = QLabel(self)
        self.pet_label.setPixmap(self.animations["normal"][0])
        # 设置标签大小为图片大小
        self.pet_label.setFixedSize(128, 128)
        # 确保标签从窗口左上角开始
        self.pet_label.move(0, 0)
        
        # 设置窗口大小为图片大小
        self.resize(self.pet_label.size())
        
        # 创建系统托盘图标
        self.create_tray_icon()
        
        # 显示在屏幕上
        self.show()
        
    def setupTimers(self):
        # 动画计时器
        self.animation_timer = QTimer(self)
        self.animation_timer.timeout.connect(self.update_animation)
        self.animation_timer.start(16)  # 设置为16毫秒以达到60帧每秒
        
        # 随机行为计时器
        self.action_timer = QTimer(self)
        self.action_timer.timeout.connect(self.random_action)
        self.action_timer.start(5000)  # 5秒执行一次随机行为
    
    def create_tray_icon(self):
        # 创建托盘图标
        self.tray_icon = QSystemTrayIcon(self)
        self.tray_icon.setIcon(QIcon(self.animations["normal"][0]))
        
        # 创建托盘菜单
        tray_menu = QMenu()
        
        # 添加菜单项
        action_wake = QAction("唤醒", self)
        action_wake.triggered.connect(self.wake_up)
        
        action_sleep = QAction("睡觉", self)
        action_sleep.triggered.connect(self.sleep)
        
        action_quit = QAction("退出", self)
        action_quit.triggered.connect(QApplication.quit)
        
        action_feed = QAction("喂食", self)
        action_feed.triggered.connect(self.feed)
        
        action_pat = QAction("摸摸头", self)
        action_pat.triggered.connect(self.pat)
        
        action_status = QAction("查看状态", self)
        action_status.triggered.connect(self.show_status)
        
        tray_menu.addAction(action_wake)
        tray_menu.addAction(action_sleep)
        tray_menu.addAction(action_quit)
        tray_menu.addAction(action_feed)
        tray_menu.addAction(action_pat)
        tray_menu.addAction(action_status)
        tray_menu.addSeparator()  # 添加分隔线
        
        self.tray_icon.setContextMenu(tray_menu)
        self.tray_icon.show()
        
    def update_animation(self):
        """更新动画帧"""
        print(f"当前动作: {self.current_action}, 当前帧: {self.current_frame}")  # 调试信息
        if not self.is_sleeping:
            animations = self.animations[self.current_action]
            self.current_frame = (self.current_frame + 1) % len(animations)
            pixmap = animations[self.current_frame]
            # 确保图片大小正确
            if pixmap.width() != 128 or pixmap.height() != 128:
                pixmap = pixmap.scaled(128, 128, Qt.KeepAspectRatio, Qt.SmoothTransformation)
            self.pet_label.setPixmap(pixmap)
        else:
            # 如果是睡觉状态,确保显示睡觉的第一帧
            self.pet_label.setPixmap(self.animations["sleeping"][0])
    
    def random_action(self):
        if not self.is_sleeping and not self.is_following_mouse:
            # 根据心情和能量值决定行为
            if self.energy < 30:
                self.sleep()
            elif self.pet_mood < 30:
                # 心情不好时更容易睡觉
                if random.random() < 0.3:
                    self.sleep()
            else:
                actions = ["normal", "walking"]
                self.current_action = random.choice(actions)
                
                if self.current_action == "walking":
                    self.random_walk()
    
    def random_walk(self):
        if self.current_action == "walking":
            current_pos = self.pos()
            # 在当前位置周围小范围随机移动
            random_x = max(self.movement_area['left'], 
                         min(self.movement_area['right'] - self.width(),
                             current_pos.x() + random.randint(-30, 30)))
            random_y = max(self.movement_area['top'],
                         min(self.movement_area['bottom'] - self.height(),
                             current_pos.y() + random.randint(-30, 30)))
            self.move(random_x, random_y)
            
    def sleep(self):
        print("进入睡觉状态")  # 调试信息
        self.is_sleeping = True
        self.current_action = "sleeping"
        self.update_animation()
        
    def wake_up(self):
        self.is_sleeping = False
        self.current_action = "normal"
        
    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.is_dragging = True
            self.dragPosition = event.globalPos() - self.frameGeometry().topLeft()
            if self.energy > 30:  # 只有在能量充足时才会开心
                self.current_action = "happy"
            event.accept()
        elif event.button() == Qt.RightButton:
            self.tray_icon.contextMenu().exec_(event.globalPos())
            
    def mouseMoveEvent(self, event):
        if event.buttons() == Qt.LeftButton:
            self.move(event.globalPos() - self.dragPosition)
            self.current_action = "walking"
            event.accept()
            
    def mouseDoubleClickEvent(self, event):
        if event.button() == Qt.LeftButton:
            if self.is_sleeping:
                self.wake_up()
            else:
                self.sleep()
    
    def auto_move(self):
        """自动在区域内移动"""
        if not self.is_sleeping and self.current_action != "walking":
            # 设置随机目标点
            target_x = random.randint(
                self.movement_area['left'], 
                self.movement_area['right'] - self.width()
            )
            target_y = random.randint(
                self.movement_area['top'], 
                self.movement_area['bottom'] - self.height()
            )
            
            self.target_pos = QPoint(target_x, target_y)
            self.current_action = "walking"
            
            # 开始移动动画
            self.start_movement_animation()
    
    def start_movement_animation(self):
        """创建平滑移动动画"""
        if self.target_pos:
            # 计算当前位置到目标位置的向量
            current_pos = self.pos()
            dx = self.target_pos.x() - current_pos.x()
            dy = self.target_pos.y() - current_pos.y()
            
            # 计算移动步长(每次移动的距离)
            step = 5
            distance = (dx**2 + dy**2)**0.5
            
            if distance > step:
                # 计算规范化的方向向量
                dx = dx / distance * step
                dy = dy / distance * step
                
                # 移动一步
                new_x = current_pos.x() + dx
                new_y = current_pos.y() + dy
                self.move(int(new_x), int(new_y))
                
                # 继续移动
                QTimer.singleShot(50, self.start_movement_animation)
            else:
                # 到达目标点
                self.move(self.target_pos)
                self.target_pos = None
                self.current_action = "normal"
    
    def set_movement_area(self, left, top, right, bottom):
        """设置活动范围"""
        self.movement_area = {
            'left': max(0, left),
            'top': max(0, top),
            'right': min(self.screen.width(), right),
            'bottom': min(self.screen.height(), bottom)
        }
    
    def load_and_verify_image(self, path):
        """加载并验证图片"""
        pixmap = QPixmap(path)
        if pixmap.isNull():
            raise Exception(f"无法加载图片: {path}")
        return pixmap
    
    def update_status(self):
        """定期更新宠物状态"""
        if not self.is_sleeping:
            self.energy -= 1
            if self.energy < 30:
                self.pet_mood -= 2
            
        if self.pet_mood < 0:
            self.pet_mood = 0
        if self.energy < 0:
            self.energy = 0
            self.sleep()
    
    def feed(self):
        """喂食"""
        if not self.is_sleeping:
            self.current_action = "eating"
            self.energy = min(100, self.energy + 30)
            self.pet_mood = min(100, self.pet_mood + 10)
            QTimer.singleShot(2000, self.back_to_normal)  # 2秒后恢复正常
    
    def pat(self):
        """摸头"""
        if not self.is_sleeping:
            self.current_action = "happy"
            self.pet_mood = min(100, self.pet_mood + 15)
            QTimer.singleShot(2000, self.back_to_normal)  # 2秒后恢复正常
    
    def back_to_normal(self):
        """恢复正常状态"""
        if not self.is_sleeping:
            self.current_action = "normal"
    
    def show_status(self):
        """显示状态信息"""
        status = f"心情值: {self.pet_mood}%\n能量值: {self.energy}%"
        QMessageBox.information(self, "宠物状态", status)
    
    def mouseReleaseEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.is_dragging = False
            if not self.is_sleeping:
                self.current_action = "normal"
    
if __name__ == '__main__':
    app = QApplication(sys.argv)
    pet = DesktopPet()
    
    # 示例:设置活动范围(比如限制在屏幕右下角区域)
    screen = app.primaryScreen().geometry()
    pet.set_movement_area(
        screen.width() // 2,    # 左边界:屏幕中间
        screen.height() // 2,   # 上边界:屏幕中间
        screen.width(),         # 右边界:屏幕右边
        screen.height()         # 下边界:屏幕底部
    )
    
    sys.exit(app.exec_())

        在运行代码前一定先安装一下代码中所需的库文件,然后将文件路径设置好,直接运行即可。无素材纯代码。

        各位也可以做完之后打包起来发给你的小姐姐们,也算是你们共同创造的一个小生命哦!

标签:draw,python,赛博,self,宠物,current,action,ellipse,fill
From: https://blog.csdn.net/m0_73747952/article/details/143705456

相关文章

  • 忽悠财务小姐姐神器(python实现3D爱心)
    1、设计背景        最近在网上看到了很多粒子爱心的python源码,所以就突发奇想也做一个爱心,但是粒子爱心这么多人做了就没什么意思了,那我就来做一个3D粉嫩旋转爱心,要的就是别出心裁,出人意料。这发给财务小姐姐,我恏大力的春天不就来了!!2、使用技术        这......
  • [开题报告]基于javaweb的宠物医院平台dz56j9计算机毕业设计源码、研究背景、意义、目
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着人们生活水平的提高和城市化进程的加速,宠物已成为许多家庭的重要成员。宠物数量的增加带动了宠物相关产业的发展,其中宠物医院作为宠物健康保障的......
  • Python 桌面应用开发:使用 Tkinter 创建 GUI 应用程序
    Python桌面应用开发:使用Tkinter创建GUI应用程序引言随着计算机技术的飞速发展,桌面应用程序依然在许多领域中发挥着重要作用。Python作为一种强大的编程语言,提供了多种工具和库来创建桌面应用程序。其中,Tkinter是Python的标准GUI(图形用户界面)库,易于使用且功能强......
  • python毕设毕业设计管理系统程序+论文
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容一、选题背景关于毕业设计管理系统的研究,现有研究主要以传统的管理模式为主,专门针对使用Python开发的毕业设计管理系统的研究较少。在当前教育环境......
  • Python Web 应用开发基础知识
    PythonWeb应用开发基础知识引言随着互联网的快速发展,Web应用程序的需求日益增加。Python作为一种简单易学且功能强大的编程语言,已经成为Web开发中广受欢迎的选择之一。本文将深入探讨PythonWeb开发的基础知识,包括常用框架、基本概念、数据库交互以及前后端分离等......
  • 2024 同一个网段,反弹shell四种方法【linux版本】bash、python、nc、villian反弹shell
    实验环境准备(同一个网段下,我是桥接的虚拟机)一、bash反弹shell二、python反弹shell三、nc反弹shell四、villain反弹shell实验环境准备(同一个网段下,我是桥接的虚拟机)      一台kali的linux(攻击者)        一台centos7/debian[另一个linux](受害者)一、b......
  • 免费送源码:Java+python+django+MySQL 小区疫情订菜系统 计算机毕业设计原创定制
    摘 要随着科学技术的飞速发展,各行各业都在努力与现代先进技术接轨,通过科技手段提高自身的优势;对于小区疫情订菜系统当然也不能排除在外,随着网络技术的不断成熟,带动了小区疫情订菜系统,它彻底改变了过去传统的管理方式,不仅使服务管理难度变低了,还提升了管理的灵活性。这种......
  • Windows 下安装miniconda 虚拟python环境,搭配 VS Code
    miniconda下载地址https://docs.anaconda.com/miniconda/miniconda-install/miniconda仓库:https://repo.anaconda.com/miniconda/可以按照官方文档校验哈希值,本次在Windows安装,不设置环境变量。从Anacondaprompt启动。2.配置国内源查看源设置condaconfig--show-so......
  • 宠物寄养服务系统springboot-java毕设源码论文
        博主介绍:......
  • python装饰器decorator的应用
    python中的装饰器类似于java中的AOP切面编程的思想,下面通过demo教大家如何实现(1)一个最简单的装饰器demo1 #一个最简单的装饰器defmy_decorator(func):defwrapper():print("Somethingishappeningbeforethefunctioniscalled.")func()......