Python Game Engine Development (II): Creating a window and redrawing the interface

Source: Internet
Author: User
Tags addchild event listener getcolor

Before we develop a local application, we have to have a window to display the interface. Second, we also have to implement the redrawing mechanism, so that the game constantly refreshed, to achieve the purpose of dynamic. So the first stage of our engine development is to create windows and redraw the interface.

Here are the previous articles:
Python Game engine Development (i): Preface

The rendering mechanism of QT

In the previous chapter "Preface" We talked about this development using the PYQT, which is the Python version of Qt. Before we begin to implement the engine features, we need to know about QT First, here we understand the rendering mechanism.
In Qt, the class that the painting uses is called, as the QPainter name implies, is a painter class bar. In this class, there are a lot of ways to manipulate the "painter", such as asking him to draw a circle, to measure the size of the text, Mr Painter certainly will not refuse.
When used QPainter , it is necessary to give a painting device, which is similar to the painter's artboard. This painting equipment is one QWidget , part class. This class also provides a number of methods, such as setting part size. In Qt, if there is only one QWidget , then this QWidget becomes the Window object.

Events in QT and signals and slots

QT events and JavaScript DOM events are a little different, not by registering an event type and the corresponding listener for the event callback, but QT directly in the class to write the listener, by overriding the listener method to execute their own code, that is, JS event is added to the call , and Qt is automatically added to the event by modifying the listener to execute the custom code. But Qt added the function of JS to add a kind of argument-signal and slot. This is the same as the Count of Monte Cristo Fairline betrayed the king of Ali the same paragraph-sent is the dagger detonated bombs blew up all the property and family, sent the ring is safe. Here the "dagger" is the signal, "detonate bombs" is the slot; "Send the Ring" is the signal, "safe" for the slot. You can also interpret the signal as the event name and the slot as a callback function.
The painting mentioned above needs to be QWidget paintEvent carried out in the middle.

Qapplication

Qapplication is the portal for the entire application. This class is a bit special, specifically where is it? Take a look at the following code:

app = QtGui.QApplication(sys.argv)# ...app.exec_()

In other words, if you want to use a series of functions in Qt, QApplication after instantiating it, exec_ use these functions before invoking the method, that is, where the entry of the program is in the code # ... . Also, QApplication accept a parameter, which is the code sys.argv , so you need to introduce the SYS module before using it.
Here, incidentally, some of the QT modules. Qt as a powerful engine, inevitably have a lot of modules, but we basically use only QtGui , QtCore QtWebKit these modules. Development of the game, the QtGui QtCore two modules are enough.

Library base class

The basic part is roughly finished, begin encapsulation, the first package is the Stage class. This class is basically to manage some of the global things, such as the size of the window, set the window refresh frequency, to the lowest level to add display objects and so on. But before we implement the stage, we have to create the lowest class in the library Object :

class Object(object):    0    def __init__(self):        1        self.objectIndex = Object.latestObjectIndex

This class is used as the base class for all classes in a library, so that it is easy to extend functionality to all classes later. Then there is the constructor part of the stage class:

class  stage   (Object) :  def  __init__  :  super (Stage, self). __init__ () self.parent = " root " self.width = 0  self.height = 0  self.speed = 0  self.app = none self.canvaswidget = none  Self.canvas = None<  /span> Self.timer = none  self.childlist = [] Self.backgroundcolor = none   

The

can see that the class contains many global properties. For example, width and height are used to get the height of the game interface, and backgroundcolor is used to set the background.
Next is the Setcanvas method, which is used to finish creating the painting device and Qpainter and redraw the timer:

def  _setcanvas   (self, speed, title, width, height) :  self.speed = Speed Self.width = width self.height = Height Self.canvas = Qtgui . Qpainter () Self.canvaswidget = Canvaswidget () self.canvasWidget.setWindowTitle (title) SELF.CANVASWIDG Et.setfixedsize (width, height) self.canvasWidget.show () Self.timer = Qtcore.qtimer () self.timer.setIn        Terval (Speed) self.timer.start (); QtCore.QObject.connect (Self.timer, qtcore.signal ( "timeout ()" ), Self.canvaswidget, Qtcore.slot ( "update ()" ))  

QT QTimer is a timer class that invokes setInterval methods to set the timing time and cycle the timings. startmethod to turn on the timer. The method is then used to connect connect the signal and slot, the signal is "timed out" and the slot is "Refresh window". In this way, we can use this signal slot device to achieve the function of the timed refresh interface.

In the code above, we have also saved the drawing class QPainter , which calls the brush in a later code.

The above code also has a class, derived from the class, CanvasWidget in which QWidget we will also add other functions, such as rewriting the Paint event listener, keyboard event listener, and so on. The constructor code is as follows:

class CanvasWidget(QtGui.QWidget):    def __init__(self):        super(CanvasWidget, self).__init__()

Of course, QT provides us with more than just this kind of basic parts, as QWidget well as input boxes, buttons, Windows and other advanced components, but we temporarily do not use these parts, let alone qt in the absence of other widgets, will default to the first QWidget set as a Window object, so here is CanvasWidget inherited from QWidget, when instantiated, is the Window object.
The above setWindowTitle and setFixedSize methods are used to set the window title, window fixed size. Then use show the method to display the part.

Because there can only be one object in the whole game, in Stage order to facilitate the use of the global public, we instantiate this class directly in the library, as the only stage object:

stage = Stage()

In the above setCanvas method, we use the signal slot to complete the interface refresh, then exactly how to refresh it? When our timer is timed to the specified time, the slot of the part is called, and in update this slot it is called into paintEvent , as we mentioned in "events in QT and Signals and slots", this event is QWidget already written in, we just need CanvasWidget to You can override this function in:

def paintEvent(self, event):        stage._onShow()

Call into Stage the method of the object _onShow :

def  _onshow   (self) :  self.canvas.begin (self.canvaswidget) if  self.backgroundcolor is  not  none : Self.canvas.fillRect (
    
     0 , 
     0 , Self.width, Self.height, GetColor ( Self.backgroundcolor)) 
     else : Self.canvas.eraseRect (
     0 , 
     0 , Self.width, Self.height) self._showdisplaylist (self.childlist ) self.canvas.end () 
     

In this function, we first use QPainter the begin method to bind the painting device. The erase interface is then re-painted by means of the _showDisplayList method, and finally the painting is finished. It is noteworthy that the _showDisplayList method, which iterates through the display list, will iterate over the object to be redrawn:

def _showDisplayList(self, childList):        forin childList:            if"_show"and"__call__"):                o._show(self.canvas)

We can finish drawing the object by invoking the method of displaying the object _show . In subsequent development, we just need to add a method to an object and _show then join the display list to redraw the object. If you add the function of the picture in the picture, _show then get the image class, add the function of painting text, it becomes the text class.

In the _onShow method we also use getColor this global function, used to convert the color name string or 16 binary value into QColor , after all, QT this illiterate, recognize the color is only recognized QColor :

def getColor(color):    if isinstance(color, QtGui.QColor):        return color    elifnot color:        return QtCore.Qt.transparent    else:        colorObj = QtGui.QColor()        colorObj.setNamedColor(color)        return colorObj

Because the Stage class is used as the lowest-level display list, the Join addChild method is removeChild used to complete the addition and deletion of the display object:

 def addChild(self, Child):        ifChild is  not None: Child.parent = self self.childList.append (child)Else:RaiseValueError ("parameter ' child ' must is a display object.") def removechild(self, Child):        ifChild is  not None: Self.childList.remove (child) Child.parent =None        Else:RaiseValueError ("parameter ' child ' must is a display object.")

Finally, add the init global function to initialize the interface:

def init(speed, title, width, height, callback):    stage.app = QtGui.QApplication(sys.argv)    stage._setCanvas(speed, title, width, height)    ifnot"__call__"):        raise ValueError("parameter ‘callback‘ must be a function.")    callback()    stage.app.exec_()

One of the QApplication above has been described in detail.
Call the init function and pass in the corresponding parameter to see the empty window.

All the code in this article:

 class object(object):Latestobjectindex =0     def __init__(self):Object.latestobjectindex + =1Self.objectindex = Object.latestobjectindex class canvaswidget(qtgui.qwidget):     def __init__(self):Super (Canvaswidget, self). __init__ () self.setmousetracking (True) def paintevent(self, event):Stage._onshow () class Stage(Object):     def __init__(self):Super (Stage, self). __init__ () Self.parent ="Root"Self.width =0Self.height =0Self.speed =0Self.app =NoneSelf.canvaswidget =NoneSelf.canvas =NoneSelf.timer =NoneSelf.childlist = [] Self.backgroundcolor =None     def _setcanvas(self, speed, title, width, height):Self.speed = Speed Self.width = width self.height = Height Self.canvas = qtgui.qpainter () Self  . Canvaswidget = Canvaswidget () self.canvasWidget.setWindowTitle (title) self.canvasWidget.setFixedSize (width, Height) self.canvasWidget.show () Self.timer = Qtcore.qtimer () self.timer.setInterval (speed) s        Elf.timer.start (); QtCore.QObject.connect (Self.timer, Qtcore.signal ("timeout ()"), Self.canvaswidget, Qtcore.slot ("Update ()")) def _onshow(self):Self.canvas.begin (Self.canvaswidget)ifSelf.backgroundcolor is  not None: Self.canvas.fillRect (0,0, Self.width, Self.height, GetColor (Self.backgroundcolor))Else: Self.canvas.eraseRect (0,0, Self.width, Self.height) self._showdisplaylist (self.childlist) self.canvas.end () def _showdisplaylist(self, childlist):         forOinchChildlist:ifHasattr (O,"_show") andHasattr (O._show,"__call__"): O._show (Self.canvas) def addChild(self, Child):        ifChild is  not None: Child.parent = self self.childList.append (child)Else:RaiseValueError ("parameter ' child ' must is a display object.") def removechild(self, Child):        ifChild is  not None: Self.childList.remove (child) Child.parent =None        Else:RaiseValueError ("parameter ' child ' must is a display object.") def init(speed, title, width, height, callback):Stage.app = Qtgui.qapplication (SYS.ARGV) Stage._setcanvas (speed, title, width, height)if  notHasattr (Callback,"__call__"):RaiseValueError ("parameter ' callback ' must be a function.") Callback () Stage.app.exec_ () def getColor(color):    ifIsinstance (color, Qtgui.qcolor):returnColorelif  notColorreturnQtCore.Qt.transparentElse: Colorobj = Qtgui.qcolor () colorobj.setnamedcolor (color)returnColorobj

preview: Next we implement the display picture.

You are welcome to follow my blog

Reprint Please specify source: Yorhom's Game box

Http://blog.csdn.net/yorhomwang

Python Game Engine Development (II): Creating a window and redrawing the interface

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.