Today we will study the animation, in fact, this animation is a Sprite
+ Bitmap
of the combination of the body. What is not to be made Sprite
and Bitmap
? =__= #看来你是半路杀进来的, go and see the first few chapters:
Python Game engine Development (i): Preface
Python Game Engine Development (II): Creating a window and redrawing the interface
Python Game engine Development (iii): Show pictures
Python Game engine Development (iv): TextField text class
Python Game Engine Development (v): Sprite Elf class and mouse events
The principle of animation
In general, our animations are used in such a picture:
When playing an animation, like playing a movie, this picture is film. We can get a projector, the size of the projector is the size of each action small map. If our film keeps moving, it will be animated, such as:
How do you achieve this effect? We learned in chapter three how to display pictures, which refer to the BitmapData
class (do not understand?). You are advised to read the first few chapters), there are two methods in this class: setCoordinate
and setProperty
for setting the position and size of the picture display:
bmpd.setCoordinate(x, y)bmpd.setProperty(x, y, width, height)
The parameters are illustrated as follows:
When playing the animation, our "film" is a Bitmap
picture display object, which contains an BitmapData
object, we can call this object by the above two methods, we will be able to achieve animation playback.
But there seems to be something missing. Perhaps you will ask, animation is a continuous process, and each frame will need a little time between animation, is not a timer? Yes, yes, yes, the important thing to say three times, we did have a timer analogue missing. But don't worry. Do you remember the method of displaying objects mentioned in the third chapter _show
? This method is called in the window paintEvent
, and is paintEvent
also called in a timer (involving the second chapter of the content). Wait a minute...... Timers ... So we've actually got a timer, and we're getting an interface to the timer.
Time Axis Events
Since there is a lack of interface, then the addition of a will be finished. DisplayObject
How to change _show
:
def _show(self, c): ifnot self.visible: return # 加入时间轴事件入口 self._loopFrame() c.save() c.translate(self.x, self.y) c.setOpacity(self.alpha * c.opacity()) c.rotate(self.rotation) c.scale(self.scaleX, self.scaleY) self._loopDraw(c) c.restore()
Added a line of code for the Timeline event entry. This method is Sprite
specifically implemented in subclasses:
def _loopFrame(self): e = object() e.currentTarget = self s.__enterFrameListener(e)
__enterFrameListener
This is the newly added Sprite
property, which is the listener for the timeline event. As with mouse events, we pass a parameter to the listener to get the event information.
Changed Sprite
to addEventListener
allow it to join a timeline event:
def addEventListener(self, eventType, listener): if eventType == Event.ENTER_FRAME: self.__enterFrameListener = listener else: self.mouseList.append({ "eventType" : eventType, "listener" : listener })
Then Event
define the timeline event in the class ENTER_FRAME
:
class Event(Object): "enter_frame" # more code ...
When used, it is OK to write this:
layer = Sprite()layer.addEventListener(Event.ENTER_FRAME, onframe)def onframe(e): print("enter frame")
A simple animation class
Animation class:
class Animation(Sprite): def __init__(self, bitmapData = BitmapData(), frameList = [[AnimationFrame()]]): super(Animation, self).__init__()
This class requires an object BitmapData
as a parameter, and an list
object, which list
is the list of frames used to mount the AnimationFrame
object, as the AnimationFrame
name implies, a class that holds the data for each frame. The code is implemented as follows:
class AnimationFrame(object): def __init__(self, x = 0, y = 0, width = 0, height = 0): super(AnimationFrame, self).__init__() self.x = x self.y = y self.width = width self.height = height
where x
the y
attribute stores the position of each frame on the picture, width
and height
stores the width height of each frame.
For the general animated picture (the example picture above), each frame is evenly distributed on the picture, so we can add a function to the uniform clipping of the frame, so we get the frame list is much more convenient. Animation
Add the following code for the class:
def divideUniformSizeFrames(width = 0, height = 0, col = 1, row = 1): result = [] frameWidth = width / col frameHeight = height / row forin range(row): rowList = [] forin range(col): frame = AnimationFrame(j * frameWidth, i * frameHeight, frameWidth, frameHeight) rowList.append(frame) result.append(rowList) return result
Next, we call this function, passing in the corresponding parameters can be cut out of the frame list. As follows:
L = animation.divideuniformsizeframes ( the, the,4,4)# Get the following list:[[Animationframe (0,0, +, +), Animationframe ( +,0, +, +), Animationframe ( the,0, +, +), Animationframe ( -,0, +, +)],[animationframe (0, +, +, +), Animationframe ( +, +, +, +), Animationframe ( the, +, +, +), Animationframe ( -, +, +, +)],[animationframe (0, the, +, +), Animationframe ( +, the, +, +), Animationframe ( the, the, +, +), Animationframe ( -, the, +, +)],[animationframe (0, -, +, +), Animationframe ( +, -, +, +), Animationframe ( the, -, +, +), Animationframe ( -, -, +, +)]]
The next step is to implement the play animation, modify the Animation
class:
class Animation(Sprite): def __init__(self, bitmapData = BitmapData(), framelist = [[Animationframe()] ]]):Super (Animation, self). __init__ () Self.bitmapdata = BitmapData Self.framelist = framelist Self.bitmap = Bitmap (bitmapData) Self.currentrow =0Self.currentcolumn =0Self.addeventlistener (Event.enter_frame, Self.__onframe) def __onframe(self, e):Currentframe = Self.framelist[self.currentrow][self.currentcolumn] Self.bitmap.bitmapData.setProperty ( Currentframe.x, Currentframe.y, Currentframe.width, currentframe.height) Self.currentcolumn + =1 ifSelf.currentcolumn >= Len (Self.framelist[self.currentrow]): Self.currentcolumn =0
Because this class inherits from it Sprite
, it inherits the method of joining the event addEventListener
. The above code is to play a row of animation, you can expand to play a column of animation or play a whole group of animation.
In this way, the following code is written to play the animation:
# 加载图片loader = Loader()loader.load("./player.png")# 动画数据bmpd = BitmapData(loader.content)l = Animation.divideUniformSizeFrames(16016044)# 加入动画anim = Animation(bmpd, l)addChild(anim)
Trailer: Next we'll draw a vector graphic.
You are welcome to follow my blog
Reprint Please specify source: Yorhom's Game box
Http://blog.csdn.net/yorhomwang
Python Game engine Development (VI): A small study of animation