写一个linux平台的桌面宠物
阅读原文时间:2023年07月11日阅读:1

效果图


前言

我一直在用python 写一下有趣的东西,让编程不那么无聊,之前一直有写一个桌面宠物的想法,无奈这些都是依赖资源文件,没有图片资源没办法写里面的逻辑,直到我看见了 shimiji手机桌面宠物软件


这个软件提供了很多宠物的图片资源,这样就简单了,用 charles 对手机简单抓包,抓取到这些资源链接
http://pepeswap.com/mascot/78
另外示例图片链接
http://pepeswap.com/thumb/78
这里是78,其实号码从 3 到90 都是有资源的,就是没有1,2(1,2是软件内置的)
所以这里一共有 90-3+1=88个资源,这下子图片资源就解决了
然后编写代码

代码

先写一个管理这些资源的软件

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import requests
import threading
import os
import zipfile
from PIL import Image

class Workchange(QThread):
    """docstring for WorkThread"""
    change_done = pyqtSignal()

    def __init__(self):
        super(Workchange, self).__init__()

    def run(self):
        url = self.url
        name = url.split('/')[-1] + '.zip'
        print('正在下载资源',name)
        data = requests.get(url).content
        with open(name,'wb') as f:
            f.write(data)
        print('下载完成!')

        path = os.environ['HOME']+'/shimeji/'
        if not os.path.exists(path):
            os.makedirs(path)
        print('正在解压资源...')
        z = zipfile.ZipFile(name, 'r')
        z.extractall(path=path)
        z.close()

        for i in range(1,47):
            os.rename(path + 'shime%s.png'% str(i),path+str(i)+'.png')
            pri_image = Image.open(path+'%s.png' %str(i))
            pri_image.transpose(Image.FLIP_LEFT_RIGHT).save(path+'-%s.png'%str(i))

        for i in os.listdir(path):
            os.system('convert %s %s'%(path+i,path+i))
        print('解压完成')
        os.remove(name)
        self.change_done.emit()

class Workinit(QThread):
    """docstring for WorkThread"""
    init_done = pyqtSignal(dict)

    def __init__(self):
        super(Workinit, self).__init__()

    def run(self):
        for i in range(3,90):
            threading.Thread(target=self.load,args=(i,)).start()

    def load(self,i):
            url = ''' http://pepeswap.com/thumb/%s''' %str(i)
            data  = requests.get(url).content
            name = str(i)
            dict_data = dict(data=data,name=name)
            self.init_done.emit(dict_data)

class DQListWidget(QListWidget):
    def __init__(self):
        super(DQListWidget, self).__init__()
        self.workinit = Workinit()
        self.workchange = Workchange()
        self.workchange.change_done.connect(self.change_done)
        self.workinit.init_done.connect(self.load_picture)
        self.workinit.start()
        self.itemDoubleClicked.connect(self.change)

    def change_done(self):
        QMessageBox.about(self,'提示','更换完成!(*>﹏<*)')

    def change(self,item):
        self.workchange.url = 'http://pepeswap.com/mascot/' + item.text()
        self.workchange.start()

    def load_picture(self,dict_data):
        item = QListWidgetItem(dict_data['name'])
        item.setSizeHint(QSize(10, 128))
        self.addItem(item)
        pixmap = QPixmap()
        label = QLabel()
        pixmap.loadFromData(dict_data['data'])
        label.setPixmap(pixmap)
        self.setItemWidget(item,label)

class Mywin(QWidget):
    def __init__(self):
        super(Mywin, self).__init__()
        list_ = DQListWidget()
        layout = QVBoxLayout(self)
        layout.addWidget(list_)
        self.setLayout(layout) 

app = QApplication(sys.argv)
mywin = Mywin() # 实例化一个窗口小部件
mywin.setWindowTitle('Hello world!') # 设置窗口标题
mywin.show() #显示窗口
sys.exit(app.exec())

这个程序双击列表中的条目即可下载并更换对应的宠物图片资源

主程序

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import time
import random
import os

def random_probability(r):
    s = random.randint(1,100)
    if r >= s:
        return True
    else:
        return False

class Donghua(QWidget):
    def __init__(self):
        super(Donghua, self).__init__()
        self.desktop = QApplication.desktop()
        self.screenRect = self.desktop.screenGeometry()
        self.HEIGHT = self.screenRect.height()
        self.WIDTH = self.screenRect.width()
        self.setWindowFlags(Qt.FramelessWindowHint)
        # self.setWindowFlags(Qt.SplashScreen)
        self.setAttribute(Qt.WA_TranslucentBackground)
        self.timer = QTimer()
        self.timer.timeout.connect(self.update)
        self.img_timer = QTimer()
        self.img_timer.timeout.connect(self.update_img)
        self.label = QLabel(self)
        self.label.setScaledContents(True)
        layout = QVBoxLayout(self)
        layout.addWidget(self.label)
        self.setLayout(layout)
        self.index = 0
        self.x = 0
        self.is_right = True
        self.m_flag = False
        self.action_dcit = {
        'left_go':(1,3),
        'right_go':(-3,-1),
        'left_hold':(5,7),
        'right_hold':(-7,-5),
        'left_release':(4,4),
        'right_release':(-4,-4),
        'left_down':(18,19),
        'right_down':(-19,-18),
        'left_crawl':(12,14),
        'right_crawl':(-14,-12),
        # 'left_rest':(15,17),
        # 'right_rest':(-17,-15),
        'left_rest':(26,27),
        'right_rest':(-27,-26),
        'left_rest2':(27,29),
        'right_rest2':(-29,-27),
        }
        self.action = 'right_release'
        self.pre_action = ''
        # 控制窗体移动及各种动作切换计时器
        self.timer.start(100)
        # 控制图片切换计时器
        self.img_timer.start(200)

    #监听鼠标动作
    def mousePressEvent(self, event):
        x = (event.globalPos()-self.pos()).x()
        y = (event.globalPos()-self.pos()).y()
        if event.button() == Qt.LeftButton and x < 128 and y < 128:
            self.m_flag = True
            self.m_Position = event.globalPos()-self.pos()  # 获取鼠标相对窗口的位置
            event.accept()

            if self.is_right:
                self.action='right_hold'
            else:
                self.action='left_hold'
            self.setCursor(QCursor(Qt.OpenHandCursor))

    def mouseMoveEvent(self, QMouseEvent):
        if Qt.LeftButton and self.m_flag:
            self.move(QMouseEvent.globalPos()-self.m_Position)  # 更改窗口位置
            QMouseEvent.accept()

    #鼠标左键释放
    def mouseReleaseEvent(self, QMouseEvent):
        self.m_flag = False
        if self.is_right:
            self.action = 'right_release'
        else:
            self.action = 'left_release'

        #手动将其放入屏幕边缘
        if self.x <= 0 and self.y > 0:
            self.action = 'left_crawl'
        elif self.x + self.width >= self.WIDTH and self.y > 0:
            self.action = 'right_crawl'

        self.setCursor(QCursor(Qt.ArrowCursor))

    #动作更新
    def update(self):
        self.width = self.geometry().width()
        self.height = self.geometry().height()
        self.x = self.geometry().x()
        self.y = self.geometry().y()
        # print(self.x,self.y)
        exec('self.%s()'% self.action)

    def right_crawl(self):
        if self.y > 0:
            self.y -= 10
            self.setGeometry(self.x,self.y,100,100)
        else:
            self.action = 'right_release'

    def left_crawl(self):
        if self.y > 0:
            self.y -= 10
            self.setGeometry(self.x,self.y,100,100)
        else:
            self.action = 'left_release'

    def right_down(self):
        if self.index+1 == self.action_dcit[self.action][1]:
            self.action = 'right_go'

    def left_down(self):
        if self.index+1 == self.action_dcit[self.action][1]:
            self.action = 'left_go'

    def right_release(self):
        if self.y + self.height > self.HEIGHT:
            self.action = 'right_down'

        else:
            self.action = 'right_release'
            self.y += 100
            self.setGeometry(self.x,self.y,100,100)

    def left_release(self):

        if self.y + self.height > self.HEIGHT:
            self.action = 'left_down'

        else:
            self.action = 'left_release'
            self.y += 100
            self.setGeometry(self.x,self.y,100,100)

    def right_go(self):
        self.x += 5
        self.action = 'right_go'
        if self.x + self.width> self.WIDTH:
            if random_probability(30):
                self.action = 'right_crawl'
            else:
                self.is_right = False
                self.action = 'left_go'

        if random_probability(1):
            self.action = 'right_rest'

        self.setGeometry(self.x,self.y,100,100)

    def left_go(self):
        self.x -= 5
        self.action = 'left_go'
        if self.x < 0:
            if random_probability(30):
                self.action = 'left_crawl'
            else:
                self.is_right = True
                self.action = 'right_go'

        if random_probability(1):
            self.action = 'left_rest'

        self.setGeometry(self.x,self.y,100,100)

    def right_rest(self):
        if random_probability(1):
            self.action = 'right_go'

    def left_rest(self):
        if random_probability(1):
            self.action = 'left_go'

    def right_hold(self):
        pass

    def left_hold(self):
        pass

    #更新图片
    def update_img(self):
        start_index,end_index = self.action_dcit[self.action]
        if self.pre_action != self.action:
            self.index = start_index
            self.pre_action = self.action

        if self.index == end_index:
            self.index = start_index
        else:
            self.index += 1
        q = QPixmap(path +'%s.png' % self.index)
        self.label.setPixmap(q)

if __name__ == '__main__':
    path = os.environ['HOME']+'/shimeji/'
    app = QApplication(sys.argv)
    mywin = Donghua()
    mywin.show()
    sys.exit(app.exec())