每日一贴,今天的内容关键字为动画实现
蛇年到,贪吃蛇还是要出马下的,不准备写整完的程序,就让蛇跑起来,尾巴的长起来吧,蛇头有点动画得了。
先讲讲一些道理,蛇的袋脑应用键盘制控,因此写重他的keyPressEvent
是势在必行的;
蛇身可以长增,动运,本来我划计是蛇身的每一块的坐标都市动移,可看见一个老哥说每次只要把尾巴动移的蛇袋脑那里,蛇袋脑再往前跑跑,蛇就动了,想想也是。蛇身是一块块构成的,很对的块成形一个组,酿成蛇的身子,每次蛇要长长,只要在这个组里加增新的块可即。
因为应用了大批的图形,因此应用PyQt里头的带Graphics的那一堆类,写重QGraphicsItem
的类或者子类,成完特定的能功,作为基本的元素;应用QGraphicsScene
加增元素;QGraphicsView
表现。
想应用动画Animation,看了看里头要需QObject
来初始化,而QGraphicsItem
居然不是继承自QObject
的。因此我择选了QGraphicsObject
作为类基来完善求需,他继承自QGraphicsItem
和QObject
,可以应用动画的西东。
面下是整完的代码,先贴上:
1 import sys 2 import random 3 from Queue import deque 4 from PyQt4.QtCore import (QObject,QRectF,QRect,QPointF, 5 QTimer,SIGNAL,Qt,pyqtProperty, 6 QPropertyAnimation,QEasingCurve ) 7 from PyQt4.QtGui import (QMainWindow,QGraphicsScene,QGraphicsView, 8 QGraphicsPixmapItem,QGraphicsItem, 9 QFont,QPainter,QPixmap, 10 QPainter,QGraphicsItemGroup, 11 QApplication,QGraphicsObject) 12 import qrc_resources 13 14 class Segment(QGraphicsObject): 15 width = 50 16 def __init__(self,pos,parent=None): 17 super(Segment,self).__init__(parent) 18 self.setPixmap(QPixmap(":/img/book.jpg")) 19 self.setFlags(QGraphicsItem.ItemIsSelectable| 20 QGraphicsItem.ItemIsMovable) 21 self.setPos(pos) 22 # def setPos(self,pos): 23 # super(Segment,self).setPos(pos) 24 def pixmap(self): 25 return self.pix 26 def setPixmap(self,pix): 27 self.pix = pix 28 def paint(self,painter,option,widget): 29 painter.drawPixmap(QRect(0,0,self.width,self.width), 30 self.pixmap()) 31 def boundingRect (self): 32 return QRectF(0,0,self.width,self.width) 33 class Head(Segment): 34 speed = Segment.width 35 UP = 0 36 DOWN = 1 37 LEFT = 2 38 RIGHT = 3 39 TimeGap = 500 40 CURVE_TYPES = [(n, c) for n, c in QEasingCurve.__dict__.items() 41 if isinstance(c, QEasingCurve.Type) and c != QEasingCurve.Custom] 42 def _set_pos(self,pos): 43 self.setPos(pos) 44 def _get_pos(self): 45 return self.pos() 46 47 position = pyqtProperty(QPointF,fset = _set_pos, 48 fget = _get_pos) 49 def __init__(self,pos,parent=None): 50 super(Head,self).__init__(pos,parent) 51 self.setPixmap(QPixmap(":/img/person.jpg")) 52 self.setFlags(QGraphicsItem.ItemIsSelectable| 53 QGraphicsItem.ItemIsMovable| 54 QGraphicsItem.ItemIsFocusable) 55 self.curveType = QEasingCurve.OutBounce 56 self.setPos(pos) 57 self.setFocus(Qt.OtherFocusReason) 58 self.direction = self.RIGHT 59 self.timer = QTimer() 60 self.timer.start(self.TimeGap) 61 QObject.connect(self.timer, SIGNAL("timeout()"), 62 self.move) 63 def move(self): 64 pos = self.pos() 65 # add animation,i dont know why must do this 66 # else it wont be move 67 if self.direction == self.LEFT: 68 position = pos + QPointF(-self.speed,0) 69 elif self.direction == self.RIGHT: 70 position = pos + QPointF(self.speed,0) 71 elif self.direction == self.UP: 72 position = pos + QPointF(0,-self.speed) 73 elif self.direction == self.DOWN: 74 position = pos + QPointF(0,self.speed) 75 76 pre = pos = position 77 78 rect = QRectF(self.boundingRect()) 79 if self.direction == self.LEFT: 80 self.setPos(pos+QPointF(-self.speed,0)) 81 elif self.direction == self.RIGHT: 82 self.setPos(pos+QPointF(self.speed,0)) 83 elif self.direction == self.UP: 84 self.setPos(pos+QPointF(0,-self.speed)) 85 elif self.direction == self.DOWN: 86 self.setPos(pos+QPointF(0,self.speed)) 87 current = self.pos() 88 self.animationChanged(pre, current) 89 90 def animationChanged(self,pre,current): 91 self.anim= QPropertyAnimation(self,'position') 92 self.anim.setStartValue(pre) 93 self.anim.setEndValue(current) 94 95 self.anim.setEasingCurve(self.curveType) 96 self.anim.setDirection(self.TimeGap-200) 97 self.anim.start() 98 def keyPressEvent (self,event): 99 key = event.key() 100 if key == Qt.Key_Left: 101 self.direction = self.LEFT 102 return 103 if key == Qt.Key_Right: 104 self.direction = self.RIGHT 105 return 106 if key == Qt.Key_Up: 107 self.direction = self.UP 108 return 109 if key == Qt.Key_Down: 110 self.direction = self.DOWN 111 return 112 class SegmentGroup(QObject): 113 def __init__(self,scene,parent = None): 114 super(SegmentGroup,self).__init__(parent) 115 self.scene = scene 116 self.items = deque() 117 118 def addSegment(self,segment): 119 self.scene.addItem(segment) 120 self.items.append(segment) 121 122 def move(self,headPos): 123 if not self.items:return 124 tail = self.items.pop() 125 tail.setPos(headPos) 126 self.items.appendleft(tail) 127 128 def tail(self): 129 if not self.items:return 130 return self.items[-1] 131 132 class SnackScene(QGraphicsScene): 133 def __init__(self,parent=None): 134 super(SnackScene,self).__init__(parent) 135 self.setSceneRect(0,0,400,300) 136 self.segmentGroup = SegmentGroup(self) 137 self.segmentGroup.addSegment(Segment(QPointF(0,0))) 138 139 self.head = Head(QPointF(Segment.width,0)) 140 self.addItem(self.head) 141 142 self.setFocusItem(self.head) 143 self.timer = QTimer() 144 self.timer.start(Head.TimeGap) 145 146 self.connect(self.timer, SIGNAL("timeout()"), 147 self.segmentMove) 148 def segmentMove(self): 149 self.segmentGroup.move(self.head.pos()) 150 def mousePressEvent (self, event): 151 if event.button() == Qt.LeftButton: 152 tail = self.segmentGroup.tail() 153 self.segmentGroup.addSegment( 154 Segment(tail.pos()) 155 ) 156 elif event.button() == Qt.RightButton: 157 curveType = random.choice(Head.CURVE_TYPES) 158 self.head.curveType = QEasingCurve(curveType[1]) 159 160 class Form(QMainWindow): 161 def __init__(self,parent=None): 162 super(Form,self).__init__(parent) 163 self.fileMenu = self.menuBar().addMenu("&File") 164 self.statusBar().showMessage("Ready", 5000) 165 self.scene = SnackScene() 166 167 self.view = QGraphicsView(self.scene) 168 self.view.setRenderHint(QPainter.SmoothPixmapTransform) 169 self.view.setDragMode(QGraphicsView.RubberBandDrag) 170 self.setCentralWidget(self.view) 171 172 app = QApplication(sys.argv) 173 174 form = Form() 175 form.show() 176 app.exec_()
资源文件:
1 <RCC> 2 <qresource prefix="/"> 3 <file>img/book.jpg</file> 4 <file>img/person.jpg</file> 5 <file>img/cat.jpg</file> 6 </qresource> 7 </RCC>
开始讲授:
蛇的体身:
1 class Segment(QGraphicsObject): 2 width = 50 3 def __init__(self,pos,parent=None): 4 super(Segment,self).__init__(parent) 5 self.setPixmap(QPixmap(":/img/book.jpg")) 6 self.setFlags(QGraphicsItem.ItemIsSelectable| 7 QGraphicsItem.ItemIsMovable) 8 self.setPos(pos) 9 # def setPos(self,pos): 10 # super(Segment,self).setPos(pos) 11 def pixmap(self): 12 return self.pix 13 def setPixmap(self,pix): 14 self.pix = pix 15 def paint(self,painter,option,widget): 16 painter.drawPixmap(QRect(0,0,self.width,self.width), 17 self.pixmap()) 18 def boundingRect (self): 19 return QRectF(0,0,self.width,self.width)
boundingRect
是指明这个对象所占的矩形空间巨细,因为有的时候你可以用鼠标择选图片,那么到底哪个区域呢,就是这个区域。
为了让蛇身蛇头的巨细分歧,设置了一个width作为蛇身的静态成员变量,并且在paint
法方中重绘了图片,这样,不管图片多么大,画出来都市酿成指定的巨细,保障了蛇身蛇头雷同的巨细。
蛇头
1 class Head(Segment): 2 speed = Segment.width 3 UP = 0 4 DOWN = 1 5 LEFT = 2 6 RIGHT = 3 7 TimeGap = 500 8 CURVE_TYPES = [(n, c) for n, c in QEasingCurve.__dict__.items() 9 if isinstance(c, QEasingCurve.Type) and c != QEasingCurve.Custom] 10 def _set_pos(self,pos): 11 self.setPos(pos) 12 def _get_pos(self): 13 return self.pos() 14 15 position = pyqtProperty(QPointF,fset = _set_pos, 16 fget = _get_pos) 17 def __init__(self,pos,parent=None): 18 super(Head,self).__init__(pos,parent) 19 self.setPixmap(QPixmap(":/img/person.jpg")) 20 self.setFlags(QGraphicsItem.ItemIsSelectable| 21 QGraphicsItem.ItemIsMovable| 22 QGraphicsItem.ItemIsFocusable) 23 self.curveType = QEasingCurve.OutBounce 24 self.setPos(pos) 25 self.setFocus(Qt.OtherFocusReason) 26 self.direction = self.RIGHT 27 self.timer = QTimer() 28 self.timer.start(self.TimeGap) 29 QObject.connect(self.timer, SIGNAL("timeout()"), 30 self.move) 31 def move(self): 32 pos = self.pos() 33 # add animation,i dont know why must do this 34 # else it wont be move 35 if self.direction == self.LEFT: 36 position = pos + QPointF(-self.speed,0) 37 elif self.direction == self.RIGHT: 38 position = pos + QPointF(self.speed,0) 39 elif self.direction == self.UP: 40 position = pos + QPointF(0,-self.speed) 41 elif self.direction == self.DOWN: 42 position = pos + QPointF(0,self.speed) 43 44 pre = pos = position 45 46 rect = QRectF(self.boundingRect()) 47 if self.direction == self.LEFT: 48 self.setPos(pos+QPointF(-self.speed,0)) 49 elif self.direction == self.RIGHT: 50 self.setPos(pos+QPointF(self.speed,0)) 51 elif self.direction == self.UP: 52 self.setPos(pos+QPointF(0,-self.speed)) 53 elif self.direction == self.DOWN: 54 self.setPos(pos+QPointF(0,self.speed)) 55 current = self.pos() 56 self.animationChanged(pre, current) 57 58 def animationChanged(self,pre,current): 59 self.anim= QPropertyAnimation(self,'position') 60 self.anim.setStartValue(pre) 61 self.anim.setEndValue(current) 62 63 self.anim.setEasingCurve(self.curveType) 64 self.anim.setDirection(self.TimeGap-200) 65 self.anim.start() 66 def keyPressEvent (self,event): 67 key = event.key() 68 if key == Qt.Key_Left: 69 self.direction = self.LEFT 70 return 71 if key == Qt.Key_Right: 72 self.direction = self.RIGHT 73 return 74 if key == Qt.Key_Up: 75 self.direction = self.UP 76 return 77 if key == Qt.Key_Down: 78 self.direction = self.DOWN 79 return
设置了四个向方,并且写重了keyPressEvent
法方,键盘按下的时候,转变self.direction
的向方。
CURVE_TYPES是动画的全部可能取值,有40多种,可查阅QEasingCurve的文档。
蛇头的动运,是在move
法方中实现的,如果不加添动画的话,第一段if else语句并不要需加,程序运行常正,可加添动画后,不知道为什么,每次运行到这里,pos的值与上一次运行move的值雷同,不得已加了一段if else使得程序能常正运行。
animationChanged
法方实现了蛇头的动画,self.anim.setEasingCurve(self.curveType)
设置动画效果,为了让动画效果可以转变,因此保留了一个self.curveType
变量。另外在造构时self.anim= QPropertyAnimation(self,'position')
,第一个数参要需是QObject
对象,而第二个数参要需时Qt的属性,因此在上面我命生了一个position
属性,代码如下:
1 def _set_pos(self,pos): 2 self.setPos(pos) 3 def _get_pos(self): 4 return self.pos() 5 6 position = pyqtProperty(QPointF,fset = _set_pos, 7 fget = _get_pos)
造构法方的定时器让蛇身连续动移,这个在我之前的博客中有分析,不在啰嗦。
蛇身Group
1 class SegmentGroup(QObject): 2 def __init__(self,scene,parent = None): 3 super(SegmentGroup,self).__init__(parent) 4 self.scene = scene 5 self.items = deque() 6 7 def addSegment(self,segment): 8 self.scene.addItem(segment) 9 self.items.append(segment) 10 11 def move(self,headPos): 12 if not self.items:return 13 tail = self.items.pop() 14 tail.setPos(headPos) 15 self.items.appendleft(tail) 16 17 def tail(self): 18 if not self.items:return 19 return self.items[-1]
这是为了便利理管,将蛇头和整段体身分离而做的一个器容,因为重要在实第一节蛇身和蛇尾之间行进插入删除操纵,所以应用python的deque()来实现这个器容,并且这个器容直接将蛇身加添到scene中去。代码木有神马别特要需明说的。
Scene
1 class SnackScene(QGraphicsScene): 2 def __init__(self,parent=None): 3 super(SnackScene,self).__init__(parent) 4 self.setSceneRect(0,0,400,300) 5 self.segmentGroup = SegmentGroup(self) 6 self.segmentGroup.addSegment(Segment(QPointF(0,0))) 7 8 self.head = Head(QPointF(Segment.width,0)) 9 self.addItem(self.head) 10 11 self.setFocusItem(self.head) 12 self.timer = QTimer() 13 self.timer.start(Head.TimeGap) 14 15 self.connect(self.timer, SIGNAL("timeout()"), 16 self.segmentMove) 17 def segmentMove(self): 18 self.segmentGroup.move(self.head.pos()) 19 def mousePressEvent (self, event): 20 if event.button() == Qt.LeftButton: 21 tail = self.segmentGroup.tail() 22 self.segmentGroup.addSegment( 23 Segment(tail.pos()) 24 ) 25 elif event.button() == Qt.RightButton: 26 curveType = random.choice(Head.CURVE_TYPES) 27 self.head.curveType = QEasingCurve(curveType[1])
在这个类中加添据数,蛇头,蛇身理管器,设置了简略的长增蛇身的事件——按下鼠标左键;而按下键右则是改更蛇头的动画效果。将蛇身的动移与蛇头的动移对应起来,用一个与蛇头定时器间时雷同的定时器来实现。
最后的form则是应用mainwindow在实现的应用程序。
1 class Form(QMainWindow): 2 def __init__(self,parent=None): 3 super(Form,self).__init__(parent) 4 self.fileMenu = self.menuBar().addMenu("&File") 5 self.statusBar().showMessage("Ready", 5000) 6 self.scene = SnackScene() 7 8 self.view = QGraphicsView(self.scene) 9 self.view.setRenderHint(QPainter.SmoothPixmapTransform) 10 self.view.setDragMode(QGraphicsView.RubberBandDrag) 11 self.setCentralWidget(self.view)
跋文:做这个然依是为了练熟qt,本来是想用图形界面做设计模式的,但是有些模式想不好写神马好,就像装饰者模式,用神马例子捏?
文章结束给大家分享下程序员的一些笑话语录: AdobeFlash拖垮Windows拖垮IE!又拖垮Linux拖垮Ubuntu拖垮FirxEox!还拖垮BSD拖垮MacOS拖垮Safri!简直无所不拖!AdobeFlash滚出网路世界!不要以为市占有率高就可以持续出烂货产品!以后替代品多得是!
相关推荐
游戏玩法: 点击"开始游戏"按钮开始 使用键盘方向键控制蛇的移动 吃到红色食物可以得分 撞到墙壁或自己会结束游戏
【标题】"蛇年吉祥2013新年片头动画.rar"揭示了这是一个与2013年中国农历新年相关的多媒体资源,特别设计用于制作新年庆祝活动的开场动画。"rar"是流行的压缩文件格式,意味着这个文件包含了多个可能用于创建片头...
蛇年的祝福前奏,以及JAVA贪吃蛇的一个项目讲解 是不是人机合一? 就是缺少一个蛇变贪吃蛇的AE特效
蛇年祝福 和蛇年祝福的代码
这是一个使用Python的turtle图形库开发的新年祝福动画程序。程序以优雅的动画方式展示"龙年吉祥"四个大字,并配以...程序通过面向对象编程方式组织代码,包含多个功能模块,实现了文字绘制、装饰效果和动画控制等功能。
用Python画一个蛇年吉祥物源代码,超漂亮超萌的蛇年吉祥物源代码,含详细代码解释,基于turtle实现
诸葛蛇年运程软件2025,点击试用,可以全功能体验2次
【标题】"蛇年连写字"所对应的资源可能是一组Photoshop笔刷,特别设计用于在图像编辑中创作中国新年或生肖蛇相关的艺术作品。在 Photoshop 中,笔刷(abr)文件是一种预设工具,可以方便用户快速地绘制出特定风格的...
在2013年这个特殊的蛇年,人们开始寻找各种方式来庆祝这一年份的特别之处。而在这其中,一个名为“蛇年大吉——2013蛇年剪纸ppt模板.rar”的PPT模板成为了人们的首选,它不仅蕴含了深厚的文化内涵,还以中国传统剪纸...
【标题】"贺新年——蛇年动态ppt模板.rar"是一个压缩文件,内含一个用于庆祝新年的蛇年动态PowerPoint模板。这个模板可能是为2013年设计的,因为中国的生肖纪年中,蛇年每12年轮回一次,而2013年恰好是农历的癸巳...
豆包MarsCode 蛇年编程大作战 | 蛇年运势预测
2025跨年倒计时html代码
标题中的“2013蛇年ppt模板下载”表明了这是一个与PPT设计相关的资源,具体是2013年以“蛇年”为主题的PowerPoint模板。在中国文化中,蛇年是中国农历十二生肖中的一种,每十二年轮回一次,2013年对应的生肖就是蛇。...
通过分析源码,开发者可以了解编程逻辑、页面布局以及动画效果的实现方法。 【压缩包子文件的文件名称列表】中的“2013蛇年新年祝福贺卡”可能包含以下文件: 1. HTML文件:构成网页结构的基础,可能包含了贺卡的...
"蛇年大吉PPT模板.ppt"显然是一款针对中国农历蛇年的特别设计,它融合了传统元素和节日氛围,旨在为新年相关的演讲或展示增添喜庆色彩。 1. **模板选择与设计原则** - **主题统一**:优秀的PPT模板应有明确的主题...
标题“蛇年PPT拜年模板PPT模板.ppt”表明这是一个设计用于农历新年(蛇年)的PowerPoint演示文稿模板,主要用于制作拜年或新年祝福的幻灯片。蛇年是中国十二生肖中的一个年份,通常会与特定的生肖元素和吉祥寓意相...
在"XXXX蛇年春节工作总结计划模版.pptx"这个文件中,我们可以看到一个全面的财务管理类的工作总结和计划的演示文稿框架。这个模版适用于年度总结、商务科技以及工作汇报,旨在帮助用户高效地整理和展示其在2013年的...
【标题】:“蛇年素材”通常指的是与农历蛇年相关的设计元素、图片、图形或模板,这些素材可以用于创建贺卡、海报、宣传品、网页设计等,为庆祝蛇年的到来增添节日气氛。 【描述】:“蛇年素材”这个描述简洁明了,...
蛇年祝福语中当然少不了与自然和谐共处的意象。比如,我们可以用“金蛇献瑞”、“祥龙送福”等成语,借助自然界的蛇和龙的形象,来增添祝福语的文化内涵和美好寓意。 当然,财富与幸福是每个个体所追求的。在祝福语...
【标题】"HAPPY NEW YEAR 新年快乐蛇年ppt模板.rar"是一个压缩包文件,主要包含用于庆祝新年,特别是蛇年的PowerPoint演示文稿模板。这类模板通常是为了帮助用户在新的一年到来时创建富有创意和视觉吸引力的幻灯片...