This time to implementSpriteclass and mouse events.
Speaking of whichSprite, crossing, who has been involved in the field of 2D game research, should have heard about it. Its Chinese original meaning is "elf", but in the eyes of different people, it means different meanings. For example, in cocos2d, it can be a picture. But in Flash,Spriteit's a guy like "layer." Of course, you define it as a layer is not very accurate, in fact it is a display list with the display object. What do you mean? Crossing if you read the previous chapters, you are not unfamiliar with the display list. It is plainly a container that contains other display objects.
Then maybe you think, why do you have this class? Let me give you an example. In an RPG game (e.g. Pokemon), our map has a series of map elements, such as trees and streams. The students who have played this kind of game know that if our characters go to the center of the map and move on, the map will scroll and show the next part of the map. At this point, if we want to move each map element, it can be quite cumbersome to operate. So flash provides us with aSpriteuniform processing of a series of display objects.
After the introduction, you may still not understand such an abstract class. Let's think of it as a layer, which we can useSpritetoaddChildadd a display object to this layer. The actions that are added to the object are relative, such as moving, rotating.
The following is a list of previous 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
The implementation of the Sprite
Here is the implementation code:
class Sprite(DisplayObject):
def __init__(self):
super(Sprite, self).__init__()
self.childList = []
def addChild(self, child):
self.childList.append(child)
def removeChild(self, child):
self.childList.remove(child)
child.parent = None
def _loopDraw(self, c):
stage._showDisplayList(self.childList)
As you can see, the implementation code for this class is simple, adding a way to display list properties and Add/delete objects. In fact, in Flash, this class has many features, such as vector drawings that will be mentioned later. Students who have read the second chapter should notice thatstage._showDisplayListthis method is responsible for traversing the display list and displaying the traversed objects (and sub-objects). Since this method isQPaintercalled after the transformation (translation, rotation, stretching), it is calledQPainter.restore()again to the sub-object display method, and the transformation in the display methodQPainteris relative to the previousQPaintertransformation. Therefore, we implement the effect of the child object transformation relative to the parent object.
Mouse events
We're going to implement the function of the mouse event. The first thing to understand is that since we cannot add events directly to the display object we write, we can onlyQWidgetdetermine whether the event is triggered by adding a mouse event and then making further calculations. For this we need to change theCanvasWidgetclass:
class CanvasWidget(QtGui.QWidget):
def __init__(self):
super(CanvasWidget, self).__init__()
self.setMouseTracking(True)
def paintEvent(self, event):
stage._onShow()
def mousePressEvent(self, event):
self.__enterMouseEvent(event, "mouse_down")
def mouseMoveEvent(self, event):
self.__enterMouseEvent(event, "mouse_move")
def mouseReleaseEvent(self, event):
self.__enterMouseEvent(event, "mouse_up")
def __enterMouseEvent(self, event, eventType):
e = {"offsetX" : event.x(), "offsetY" : event.y(), "eventType" : eventType, "target" : None}
stage._enterMouseEvent(e, {"x" : 0, "y" : 0, "scaleX" : 1, "scaleY" : 1})
The main thing is to rewriteQWidgetseveral of the event callbacks (mouseReleaseEvent,mouseMoveEvent,mousePressEvent) and add events into the Display object's entry__enterMouseEvent.
It is worth noting that thesetMouseTrackingmethod is used to constantly trigger a move event.
Stage._enterMouseEventThe code is as follows:
def _enterMouseEvent(self, event, cd):
childList = self.childList[:: -1]
currentCd = {"x" : cd["x"], "y" : cd["y"], "scaleX" : cd["scaleX"], "scaleY" : cd["scaleY"]}
for o in childList:
if hasattr(o, "_enterMouseEvent") and hasattr(o._enterMouseEvent, "__call__") and o._enterMouseEvent(event, currentCd):
break
In which, we traverse all the underlying sub-objects and determine whether the mouse event can be entered into the sub-object loop, if possible (and determine if there is no_enterMouseEventmethod), then proceed. In addition, in order to achieve the effect of mouse event occlusion, we specifically to traverse the display list, that is, the first traversal of the objects displayed in the upper layer, call the methods of these objects,_enterMouseEventthe method returns the value of theTruemouse on the display object, bybreakinterrupting the traversal.
In general, there are more than_enterMouseEventhalf of theSpriteobjects. So weSpriteadd this method for:
def _enterMouseEvent(self, e, cd):
if not self.visible:
return
currentCd = self.__getVisualCoordinate(cd, self)
isOn = self._isMouseOn(e, currentCd)
if isOn:
for o in self.childList[::-1]:
if (hasattr(o, "_enterMouseEvent") and hasattr(o._enterMouseEvent, "__call__") and o._enterMouseEvent(e, currentCd)):
break
self.__dispatchMouseEvent(e, currentCd)
return False
and_entermouseeventin the stage are very similar. The_ismouseonmethod of the child object is used to determine whether to click on the object.__dispatchmouseeventis used to trigger mouse events.__getvisualcoordinateis used to get a display coordinate, which is like looking at a three-dimensional graphical visualization, and the actual size is not the same as what we see. So we use this method to achieve the size and position we see.__getvisualcoordinateCode:
def __getVisualCoordinate(self, origin, obj):
return {
"x" : origin["x"] + obj.x * origin["scaleX"],
"y" : origin["y"] + obj.y * origin["scaleY"],
"scaleX" : origin["scaleX"] * obj.scaleX,
"scaleY" : origin["scaleY"] * obj.scaleY
}
Since the implementation of the_isMouseOn__dispatchMouseEventtwo methods is not very good, but also with optimization, so the code is not given first. When the library is released, it will give the corresponding perfect plan.
Finally, add the event functionaddEventListenerandremoveEventListeneryou can. As the name implies, they are used to add events and remove events, primarily usinglistanddictto complete the event store.
At this point, we haveSpriteroughly implemented the mouse events. Because it is more complex and not well-developed, I speak very rough. The complete code is given when the library is released.
Trailer: Next we implement animation class.
You are welcome to follow my blog
Reprint Please specify source: Yorhom's Game box
Http://blog.csdn.net/yorhomwang
Python Game Engine Development (v): Sprite Elf class and mouse events