382 lines
14 KiB
Python
382 lines
14 KiB
Python
import sys
|
|
import os
|
|
import random
|
|
import datetime
|
|
from PyQt5.QtGui import QIcon, QMovie, QCursor, QPixmap
|
|
from PyQt5.QtWidgets import (QWidget, QApplication, QSystemTrayIcon,
|
|
QMenu, QAction, QLabel, QDesktopWidget,
|
|
QProgressBar, QVBoxLayout, QHBoxLayout)
|
|
from PyQt5.QtCore import Qt, QSize, QTimer
|
|
|
|
class DesktopPet(QWidget):
|
|
def __init__(self, parent=None, **kwargs):
|
|
super(DesktopPet, self).__init__(parent)
|
|
self.init()
|
|
self.initPall()
|
|
self.action_timer = QTimer(self)
|
|
self.action_timer.setSingleShot(True)
|
|
self.action_timer.timeout.connect(self.checkInitialGif)
|
|
self.status_timer = QTimer(self)
|
|
self.status_timer.timeout.connect(self.statusTimer)
|
|
self.happiness_accumulated = 0
|
|
self.energy_accumulated = 0
|
|
self.working_timer = QTimer(self)
|
|
self.working_timer.timeout.connect(self.updateWorking)
|
|
self.boring_timer = QTimer(self)
|
|
self.boring_timer.setSingleShot(True)
|
|
self.boring_timer.timeout.connect(self.setBoring)
|
|
self.is_boring = False
|
|
self.resetBoringTimer()
|
|
self.resurrect_timer = QTimer(self)
|
|
self.resurrect_timer.setSingleShot(True)
|
|
self.resurrect_timer.timeout.connect(self.resurrectPet)
|
|
self.is_dead = False
|
|
self.initPetImage()
|
|
|
|
def init(self):
|
|
self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.Tool | Qt.NoDropShadowWindowHint)
|
|
self.setAutoFillBackground(False)
|
|
self.setAttribute(Qt.WA_TranslucentBackground, True)
|
|
self.repaint()
|
|
|
|
def initPall(self):
|
|
icons = os.path.join('Image/MenuIcon.jpg')
|
|
self.quit_action = QAction(u'退出', self, triggered=self.quit)
|
|
self.showing = QAction(u'显示', self, triggered=self.showup)
|
|
self.hideup = QAction(u'隐藏', self, triggered=self.hide)
|
|
self.hidestats = QAction(u'显示/隐藏状态栏', self, triggered=self.hideStatsBar)
|
|
self.tray_icon_menu = QMenu(self)
|
|
self.tray_icon_menu.addAction(self.quit_action)
|
|
self.tray_icon_menu.addAction(self.showing)
|
|
self.tray_icon_menu.addAction(self.hideup)
|
|
self.tray_icon_menu.addAction(self.hidestats)
|
|
self.tray_icon = QSystemTrayIcon(self)
|
|
self.tray_icon.setIcon(QIcon(icons))
|
|
self.tray_icon.setContextMenu(self.tray_icon_menu)
|
|
self.tray_icon.show()
|
|
|
|
def initPetImage(self):
|
|
self.main_layout = QVBoxLayout(self)
|
|
self.main_layout.setContentsMargins(0, 0, 0, 0)
|
|
self.main_layout.setSpacing(0)
|
|
|
|
self.stats_visible = True
|
|
self.happiness_layout = QHBoxLayout()
|
|
self.happiness_layout.setContentsMargins(0, 0, 0, 0)
|
|
self.happiness_layout.setSpacing(0)
|
|
self.happiness_icon = QLabel()
|
|
self.happiness_icon.setContentsMargins(0, 0, 0, 0)
|
|
self.happiness_icon_pixmap = QPixmap("Image/Happiness.svg")
|
|
self.happiness_icon_pixmap = self.happiness_icon_pixmap.scaled(QSize(20, 20), Qt.KeepAspectRatio, Qt.SmoothTransformation)
|
|
self.happiness_icon.setPixmap(self.happiness_icon_pixmap)
|
|
self.happiness_layout.addWidget(self.happiness_icon, alignment=Qt.AlignCenter)
|
|
self.happiness_bar = QProgressBar()
|
|
self.happiness_bar.setRange(0, 100)
|
|
self.happiness_bar.setValue(80)
|
|
self.happiness_bar.setFixedHeight(12)
|
|
self.happiness_bar.setFixedWidth(150)
|
|
self.happiness_bar.setStyleSheet("""
|
|
QProgressBar {
|
|
border: 1px solid #ccc;
|
|
border-radius: 5px;
|
|
text-align: center;
|
|
}
|
|
QProgressBar::chunk {
|
|
background-color: #FF69B4;
|
|
}
|
|
""")
|
|
self.happiness_layout.addWidget(self.happiness_bar, alignment=Qt.AlignCenter)
|
|
|
|
self.energy_layout = QHBoxLayout()
|
|
self.energy_layout.setContentsMargins(0, 0, 0, 0)
|
|
self.energy_layout.setSpacing(0)
|
|
self.energy_label = QLabel()
|
|
self.energy_label.setContentsMargins(0, 0, 0, 0)
|
|
self.energy_icon_pixmap = QPixmap("Image/Energy.svg")
|
|
self.energy_icon_pixmap = self.energy_icon_pixmap.scaled(QSize(20, 20), Qt.KeepAspectRatio, Qt.SmoothTransformation)
|
|
self.energy_label.setPixmap(self.energy_icon_pixmap)
|
|
self.energy_layout.addWidget(self.energy_label, alignment=Qt.AlignCenter)
|
|
self.energy_bar = QProgressBar()
|
|
self.energy_bar.setRange(0, 100)
|
|
self.energy_bar.setValue(80)
|
|
self.energy_bar.setFixedHeight(12)
|
|
self.energy_bar.setFixedWidth(150)
|
|
self.energy_bar.setStyleSheet("""
|
|
QProgressBar {
|
|
border: 1px solid #ccc;
|
|
border-radius: 5px;
|
|
text-align: center;
|
|
}
|
|
QProgressBar::chunk {
|
|
background-color: #1E90FF;
|
|
}
|
|
""")
|
|
self.energy_layout.addWidget(self.energy_bar, alignment=Qt.AlignCenter)
|
|
|
|
self.image = QLabel(self)
|
|
self.image.setContentsMargins(0, 0, 0, 0)
|
|
self.checkInitialGif()
|
|
|
|
self.main_layout.addWidget(self.image)
|
|
self.main_layout.addLayout(self.happiness_layout)
|
|
self.main_layout.addLayout(self.energy_layout)
|
|
|
|
self.resize(200, 240)
|
|
self.randomPosition()
|
|
self.show()
|
|
self.pet1 = []
|
|
for filename in os.listdir("GIF"):
|
|
self.pet1.append(os.path.join("GIF", filename))
|
|
|
|
def showMenu(self):
|
|
menu = QMenu()
|
|
menu.addAction(u"贴贴", self.stick)
|
|
menu.addAction(u"拍一拍", self.call)
|
|
menu.addAction(u"锻炼", self.exercise)
|
|
menu.addAction(u"充电", self.charge)
|
|
menu.addAction(u"投喂小白", self.cake)
|
|
menu.addAction(u"吧唧", self.baji)
|
|
menu.addAction(u"随机出现", self.appear)
|
|
menu.addAction(u"遛小鸡毛", self.walkDog)
|
|
right_pos = self.mapToGlobal(self.rect().topRight())
|
|
menu.exec_(right_pos)
|
|
|
|
def stick(self):
|
|
if self.is_dead:
|
|
return
|
|
self.resetBoringTimer()
|
|
self.working_timer.stop()
|
|
self.changeGif("GIF/stick.gif")
|
|
self.action_timer.start(10 * 60 * 1000)
|
|
self.updateStatus(15, -5, 10 * 60 * 1000)
|
|
|
|
def call(self):
|
|
if self.is_dead:
|
|
return
|
|
self.resetBoringTimer()
|
|
self.working_timer.stop()
|
|
self.changeGif("GIF/call.gif")
|
|
self.action_timer.start(2000)
|
|
|
|
def exercise(self):
|
|
if self.is_dead:
|
|
return
|
|
self.resetBoringTimer()
|
|
self.working_timer.stop()
|
|
self.changeGif("GIF/exercise.gif")
|
|
self.action_timer.start(10 * 60 * 1000)
|
|
self.updateStatus(5, -10, 10 * 60 * 1000)
|
|
|
|
def charge(self):
|
|
if self.is_dead:
|
|
return
|
|
self.resetBoringTimer()
|
|
self.working_timer.stop()
|
|
self.changeGif("GIF/charge.gif")
|
|
self.action_timer.start(45 * 60 * 1000)
|
|
self.updateStatus(30, 30, 30 * 60 * 1000)
|
|
|
|
def cake(self):
|
|
if self.is_dead:
|
|
return
|
|
self.resetBoringTimer()
|
|
self.working_timer.stop()
|
|
self.changeGif("GIF/cake.gif")
|
|
self.action_timer.start(5 * 60 * 1000)
|
|
self.updateStatus(10, 5, 5 * 60 * 1000)
|
|
|
|
def baji(self):
|
|
if self.is_dead:
|
|
return
|
|
self.resetBoringTimer()
|
|
self.working_timer.stop()
|
|
self.changeGif("GIF/baji.gif")
|
|
self.action_timer.start(5 * 60 * 1000)
|
|
self.updateStatus(10, 10, 5 * 60 * 1000)
|
|
|
|
def appear(self):
|
|
if self.is_dead:
|
|
return
|
|
self.resetBoringTimer()
|
|
self.working_timer.stop()
|
|
self.changeGif("GIF/appear.gif")
|
|
self.action_timer.start(3500)
|
|
self.randomPosition()
|
|
|
|
def walkDog(self):
|
|
if self.is_dead:
|
|
return
|
|
self.resetBoringTimer()
|
|
self.working_timer.stop()
|
|
self.changeGif("GIF/walkdog.gif")
|
|
self.action_timer.start(10 * 60 * 1000)
|
|
self.updateStatus(15, -10, 10 * 60 * 1000)
|
|
|
|
def checkInitialGif(self):
|
|
current_time = datetime.datetime.now()
|
|
current_hour = current_time.hour
|
|
weekday = current_time.weekday()
|
|
self.is_working_time = (0 <= weekday <= 4) and (10 <= current_hour < 18)
|
|
happiness = self.happiness_bar.value()
|
|
energy = self.energy_bar.value()
|
|
|
|
if happiness == 0 and energy == 0:
|
|
self.petDied()
|
|
elif happiness < 20 and energy < 20:
|
|
if self.is_working_time:
|
|
self.working_timer.stop()
|
|
self.working_timer.start(60 * 1000)
|
|
return self.changeGif("GIF/angry.gif")
|
|
elif happiness < 20:
|
|
if self.is_working_time:
|
|
self.working_timer.stop()
|
|
self.working_timer.start(2 * 60 * 1000)
|
|
return self.changeGif("GIF/crying2.gif")
|
|
elif energy < 20:
|
|
if self.is_working_time:
|
|
self.working_timer.stop()
|
|
self.working_timer.start(2 * 10 * 1000)
|
|
return self.changeGif("GIF/crying.gif")
|
|
|
|
if self.is_working_time:
|
|
self.working_timer.start(3 * 60 * 1000)
|
|
return self.changeGif("GIF/working2.gif")
|
|
else:
|
|
self.working_timer.stop()
|
|
return self.changeGif("GIF/normal.gif")
|
|
|
|
def updateWorking(self):
|
|
self.updateHappiness(-1)
|
|
self.updateEnergy(-1)
|
|
if self.happiness_bar.value() <= 20 or self.energy_bar.value() <= 20:
|
|
self.checkInitialGif()
|
|
|
|
def updateStatus(self, happinesschange, energychange, duration):
|
|
self.total_happiness_change = happinesschange
|
|
self.total_energy_change = energychange
|
|
interval = 100
|
|
self.remaining = duration / interval
|
|
self.happiness_change_step = happinesschange / self.remaining
|
|
self.energy_change_step = energychange / self.remaining
|
|
self.status_timer.start(interval)
|
|
|
|
def statusTimer(self):
|
|
if self.remaining <= 0:
|
|
self.status_timer.stop()
|
|
return
|
|
self.happiness_accumulated += self.happiness_change_step
|
|
self.energy_accumulated += self.energy_change_step
|
|
if self.happiness_accumulated >= 1 or self.happiness_accumulated <= -1:
|
|
self.updateHappiness(int(self.happiness_accumulated))
|
|
self.happiness_accumulated = 0
|
|
if self.energy_accumulated >= 1 or self.energy_accumulated <= -1:
|
|
self.updateEnergy(int(self.energy_accumulated))
|
|
self.energy_accumulated = 0
|
|
self.remaining -= 1
|
|
|
|
def setBoring(self):
|
|
if not self.is_boring and not self.is_working_time:
|
|
self.is_boring = True
|
|
self.changeGif("GIF/boring.gif")
|
|
self.updateHappiness(-5)
|
|
|
|
def resetBoringTimer(self):
|
|
if self.is_boring:
|
|
self.is_boring = False
|
|
self.checkInitialGif()
|
|
self.boring_timer.stop()
|
|
self.boring_timer.start(60 * 60 * 1000)
|
|
|
|
def petDied(self):
|
|
if self.is_dead:
|
|
return
|
|
self.is_dead = True
|
|
self.working_timer.stop()
|
|
self.boring_timer.stop()
|
|
self.action_timer.stop()
|
|
self.status_timer.stop()
|
|
self.showing.setEnabled(False)
|
|
self.hidestats.setEnabled(False)
|
|
self.hideup.setEnabled(False)
|
|
self.hide()
|
|
self.resurrect_timer.start(5000)
|
|
|
|
def resurrectPet(self):
|
|
self.is_dead = False
|
|
self.happiness_bar.setValue(50)
|
|
self.energy_bar.setValue(50)
|
|
self.showing.setEnabled(True)
|
|
self.hidestats.setEnabled(True)
|
|
self.hideup.setEnabled(True)
|
|
self.showup()
|
|
self.resetBoringTimer()
|
|
self.checkInitialGif()
|
|
|
|
def randomPosition(self):
|
|
screen_geometry = QDesktopWidget().screenGeometry()
|
|
pet_geometry = self.geometry()
|
|
width = int((screen_geometry.width() - pet_geometry.width()) * random.random())
|
|
height = int((screen_geometry.height() - pet_geometry.height()) * random.random())
|
|
self.move(width, height)
|
|
|
|
def changeGif(self, path):
|
|
self.movie = QMovie(path)
|
|
self.movie.setScaledSize(QSize(200, 200))
|
|
self.image.setMovie(self.movie)
|
|
self.movie.start()
|
|
|
|
def mousePressEvent(self, event):
|
|
self.condition = 1
|
|
if event.button() == Qt.LeftButton:
|
|
self.is_follow_mouse = True
|
|
self.mouse_drag_pos = event.globalPos() - self.pos()
|
|
self.setCursor(QCursor(Qt.OpenHandCursor))
|
|
elif event.button() == Qt.RightButton:
|
|
self.showMenu()
|
|
event.accept()
|
|
|
|
def mouseMoveEvent(self, event):
|
|
if Qt.LeftButton and self.is_follow_mouse:
|
|
self.move(event.globalPos() - self.mouse_drag_pos)
|
|
event.accept()
|
|
|
|
def mouseReleaseEvent(self, event):
|
|
self.is_follow_mouse = False
|
|
self.setCursor(QCursor(Qt.ArrowCursor))
|
|
|
|
def enterEvent(self, event):
|
|
self.setCursor(Qt.ClosedHandCursor)
|
|
|
|
def updateHappiness(self, value):
|
|
current_value = self.happiness_bar.value()
|
|
new_value = max(0, min(100, current_value + value))
|
|
self.happiness_bar.setValue(new_value)
|
|
|
|
def updateEnergy(self, value):
|
|
current_value = self.energy_bar.value()
|
|
new_value = max(0, min(100, current_value + value))
|
|
self.energy_bar.setValue(new_value)
|
|
|
|
def hideStatsBar(self):
|
|
if self.is_dead:
|
|
return
|
|
self.stats_visible = not self.stats_visible
|
|
self.happiness_icon.setVisible(self.stats_visible)
|
|
self.happiness_bar.setVisible(self.stats_visible)
|
|
self.energy_label.setVisible(self.stats_visible)
|
|
self.energy_bar.setVisible(self.stats_visible)
|
|
|
|
def quit(self):
|
|
self.close()
|
|
sys.exit()
|
|
|
|
def showup(self):
|
|
self.setWindowOpacity(1)
|
|
|
|
def hide(self):
|
|
self.setWindowOpacity(0)
|
|
|
|
if __name__ == '__main__':
|
|
app = QApplication(sys.argv)
|
|
pet = DesktopPet()
|
|
sys.exit(app.exec_()) |