Programming with fruit Games through Python Development

Source: Internet
Author: User

Programming with fruit Games through Python Development

The Python game engine I developed has been updated to 1.4. Now let's use it to complete an extremely simple little game: Pick up the fruit. The following are games:

Game operation instructions: click on the left and right sides of the screen or use the keyboard direction key to control the movement of the character, so that the character and the fruit contact score, when encountering non-fruit items, such as broken glass, the game will be over.

The following is a detailed development process with a long length. Please read it with patience.

Pylash Project address

Since pylash is used in this development, you can go to Github to learn about the engine.
Https://github.com/yuehaowang/pylash_engine

Create a project

First, createget_fruitsDirectory. Then download Pylash from Github. The engine is built based on Python3 and PyQt4, so before using it, make sure you are using Python3 and installed with PyQt4. If not, you can find their webpage link in the above project address for download and installation. The installation and configuration steps are very simple. I will not go into details here.

After downloading Pylash, we get the directory structure as follows:

+- pylash_engine/    |    +- pylash/    |    +- demo/    |    +- examples/

You candemo/Andexamples/View examples in two directories.The source code of this article can be found inexamples/get_fruits.

pylashThe directory is the source code of the engine. Next, copy the directory to the one we createdget_fruitsDirectory, and thenget_fruitsCreateimagesDirectory used to store images. Last createdMain.pyFile. At this time, ourget_fruitsThe directory structure is as follows:

+- get_fruits/    |    +- pylash/    |    +- images/    |    +- Main.py

Then, set the Engine Directoryplash_engine/examples/get_fruits/images/Copy to project directoryget_fruits/images/Used as game materials.

In this way, our project has been created, and we will only useMain.pyEnter the code, and then run it.

Write a Hello World Applet

Use the Code Editor (Sublime Text is recommended) to openMain.pyFile, write the following code:

#! /Usr/bin/env python3 #-*-coding: UTF-8-*-from pylash. utils import init, addChildfrom pylash. text import TextFielddef main (): # create a text display object txt = TextField () # Set the text content txt. text = "Hello World" # Set the text color txt. textColor = "red" # Set the Text Location txt. x = 50 txt. y = 100 # Set the text font size. txt. size = 50 # Add a Text object to the bottom layer addChild (txt) # initialize the window. parameters: interface refresh time (unit: milliseconds), window title, window width, and window height, after initialization, the callback function init (1000/60, "Hello World", 800,600, main)

RunMain.pyIf the interface shown in is displayed, the program runs properly.

You can start to understand Pylash with comments. If you are familiar with flash, it is not difficult to find that,TextFieldIs the class for displaying text in flash, and its usage is very similar.
We can see from line 1 of the Code that we have introduced some functions and classes in pylash. Pylash provides many modules. You can view their introduction here.
Next, we will find that pylash provides a class for displaying text and sets the text style by setting different attributes of the class. Last useaddChildAdd the text display object to the interface. We can think of games as divided into many layers: map layer, character layer, UI Layer ......, You can achieve hierarchical display by layering. For example, if a character is always displayed on the top of the map, the character layer is on the top of the map layer.addChildA function adds a display object to the bottom layer.
Finally, we useinitFunction initialization window.

Pylash provides many basic display objects,TextFieldText display class, andBitmapImage Display class,SpriteGenie class. It will be mentioned below.

Compile a game

With the above general understanding of pylash, we can start to write a game. First, delete all code after the fourth line.

Import required

First, introduce all the classes and functions we need and modify them.Main.py:

from pylash.utils import stage, init, addChild, KeyCodefrom pylash.system import LoadManagefrom pylash.display import Sprite, BitmapData, Bitmap, FPSfrom pylash.text import TextField, TextFormatWeightfrom pylash.events import MouseEvent, Event, KeyboardEventfrom pylash.ui import LoadingSample1

These classes and functions are used in the following code. Because I wrote the game in advance, I posted this part of the code here. When you use it, you can introduce one for each use.

Global Variables

Some global variables need to be used in the game. You can view them first and know what they are doing differently. They will be used later:

dataList = {}stageLayer = Noneplayer = NoneitemLayer = NonescoreTxt = NoneaddItemSpeed = 40addItemSpeedIndex = 0score = 0keyboardEnabled = False
Load Resources

Images are used in our games, so we need to attach images in advance (stored inimages/Directory ). We useLoadManageStatic class andLoadingSample1Progress bar (andLoadingSample2,LoadingSample3The two different style progress bars. Or you can write a progress bar class by yourself ). ModifymainFunction:

Def main (): # resource list, a list object. Format: {"name": Resource name, "path": Resource path} loadList = [{"name ": "player", "path ":". /images/player.png "},{" name ":" bg "," path ":". /images/bg.jpg "},{" name ":" item0 "," path ":". /images/item0.png "},{" name ":" item1 "," path ":". /images/item1.png "},{" name ":" item2 "," path ":". /images/item2.png "},{" name ":" item3 "," path ":". /images/item3.png "},{" name ":" item4 "," path ":". /images/item4.png "},{" name ":" item5 "," path ":". /images/item5.png "},{" name ":" item6 "," path ":". /images/item6.png "},{" name ":" item7 "," path ":". /images/item7.png "}] # create a progress bar loadingPage = LoadingSample1 () addChild (loadingPage) # The function called after loading. A parameter is accepted, which is a dict object, use result [Resource Name] to obtain the loaded resource def loadComplete (result): # Call the remove method to remove its own loadingPage from the interface. remove () # Call the initialization game function gameInit (result) # load the file, parameter: resource list, each time a resource callback function is loaded (mostly used to display the progress ), loadManage, the callback function for all resources, is loaded. load (loadList, loadingPage. setProgress, loadComplete)

The above Code contains detailed comments, which should not be difficult to understand. We can see that we useLoadManage.loadLoad.LoadingSample1.setProgressUsed to set the display progress.

Create start Interface

InmainFunction calledgameInitFunction, so add the function:

Def gameInit (result): global dataList, stageLayer # Save the loaded resource, you can use dataList [Resource Name] to obtain the loaded resource dataList = result # create a stage layer stageLayer = Sprite () addChild (stageLayer) # Add FPS, easy to view game efficiency fps = FPS () addChild (fps) # Add background image bg = Bitmap (BitmapData (dataList ["bg"]) stageLayer. addChild (bg) # Add text titleTxt = TextField () titleTxt. text = "Get Furit" titleTxt. size = 70 titleTxt. textColor = "red" titleTxt. x = (s Tage. width-titleTxt. width)/2 titleTxt. y = 100 stageLayer. addChild (titleTxt) hintTxt = TextField () hintTxt. text = "Tap to Start the Game !~ "HintTxt. textColor = "red" hintTxt. size = 40 hintTxt. x = (stage. width-hintTxt. width)/2 hintTxt. y = 300 stageLayer. addChild (hintTxt) engineTxt = TextField () engineTxt. text = "-Powered by Pylash-" engineTxt. textColor = "red" engineTxt. size = 20 engineTxt. weight = TextFormatWeight. BOLD engineTxt. italic = True engineTxt. x = (stage. width-engineTxt. width)/2 engineTxt. y = 500 stageLayer. addChild (engineTxt) # Add the mouse click event: Click the stage layer to start the game stageLayer. addEventListener (MouseEvent. MOUSE_UP, startGame) # Add a keyboard event: used to control the character stage in the game. addEventListener (KeyboardEvent. KEY_DOWN, keyDown) stage. addEventListener (KeyboardEvent. KEY_UP, keyUp) def startGame (e): print ("start game") def keyDown (e): print ("key down") def keyUp (e ): print ("key up ")

In the above Code, we need to break through the following difficulties:

SpriteGenie class.SpriteIs a genie class. But what is genie? You can actually think of it as a layer. It ownsaddChildMethod, used to add the Display object to its own layer (and globaladdChildFunction ). Of courseSpriteIt is not just a layer function, but you should regard it as a layer.

BitmapAndBitmapDataClass usage.BitmapThis is a class used to display images. AndTextFieldSame, useaddChildAdd it to the interface.BitmapDataClass is used to store image data, and the parameters it receives are loaded image resources. Pass it as a parameterBitmapClass constructor to create an image.BitmapDataPixel operations can also be performed, but this is a more advanced feature that you do not need to know.

Event.In pylash, useaddEventListenerAn event is added to a unified interface. This method parameter is an event type and an event listener (that is, an event callback function ). What is an event? Similar to a signal, a specified signal listener is triggered after a signal is sent in some cases. Add the mouse eventaddEventListenerYesEventDispatcher,DisplayObjectClass inherited fromEventDispatcher, So it inherits fromDisplayObjectAll classes can be added to the event. However, onlySpriteTo trigger a mouse event. So we givestageLayer(Stage layer,SpriteObject) added the mouse click event (MouseEvent.MOUSE_UP). CorrespondingaddEventListenerMethods include:removeEventListener(Remove the event with the same parameters ). In additionMouseEvent.MOUSE_UP(With the mouse on it), andMouseEvent.MOUSE_DOWN(Press the mouse ),MouseEvent.MOUSE_MOVE(Move the mouse ),MouseEvent.MOUSE_OUT(Move the mouse) and other events. Later I will use some. The event listener is a function,startGame,keyDown,keyUpThey are all event listeners. The listener is called when an event is triggered and receives an event data parameter (usually writteneYou can use this parameter to obtain information about the event. For example, the mouse event listener can use this parameter to obtain the mouse position.

stageGlobal class.HerestageIs a global class used to manage the entire window, such as setting the Window refresh speed and obtaining the window size (stage. width, stage. height ).window. Keyboard Events cannot be added to an object, sostageYou can also add Keyboard Events. Add a keyboard event for the same purposeaddEventListenerThis unified interface.

Last joininitFunction initialization window:

init(1000 / 60, "Get Fruits", 800, 600, main)

initIn the function, it is worth noting that the first parameter. The comment in the code above explains "interface refresh time", which means that our interface is constantly refresh and re-painting. This parameter is used to determine the refresh time. The smaller the parameter value, the faster the refresh, the smoother the game, but you do not need to set it too small. If it is too small, the refresh speed is too fast and the device will not be able to keep up with this pace. A friend who has played a game can understand this parameter. divide it by 1000 to get FPS.

Run Main. py to obtain the following interface:

We can see that there are images and texts on our interface. Click "start game" on the page, press the keyboard to output "key down", and release the keyboard to output "key up ". In this way, we have successfully added display objects and mouse & Keyboard Events.

Start the game

The listener for the stage layer mouse click event isstartGameFunction, that is, we click the start interface to start the game. ModifystartGameFunction:

Def startGame (e): global player, itemLayer, scoreTxt, addItemSpeedIndex, score, keyboardEnabled # initial global variables addItemSpeedIndex = 0 score = 0 keyboardEnabled = True # clear stage layer and stage event stageLayer. removeAllChildren () stageLayer. removeAllEventListeners () # Add background bg = Bitmap (BitmapData (dataList ["bg"]) stageLayer. addChild (bg) # create a role player = Player (dataList ["player"]) player. x = (stage. width-player. width)/2 player. y = 450 stageLayer. addChild (player) # create a falling item layer itemLayer = Sprite () stageLayer. addChild (itemLayer) # saves the character object to itemLayer to detect collision itemLayer. hitTarget = player # Add score text scoreTxt = TextField () scoreTxt. text = "Score: 0" scoreTxt. textColor = "red" scoreTxt. size = 30 scoreTxt. x = scoreTxt. y = 30 scoreTxt. weight = TextFormatWeight. BOLDER stageLayer. addChild (scoreTxt) # adds the event stageLayer. addEventListener (MouseEvent. MOUSE_DOWN, onMouseDown) stageLayer. addEventListener (MouseEvent. MOUSE_UP, onMouseUp) stageLayer. addEventListener (Event. ENTER_FRAME, loop) def onMouseDown (e): print ("mouse down") def onMouseUp (e): print ("mouse up") def loop (e ): print ("loop ")

CorrespondingaddChild,SpriteProvidedremoveChildTo remove a display object. In additionremoveAllChildrenRemove all object methods.removeAllEventListenersAs the name implies, all events are removed. The above code is confusing. Similarly, we need to overcome the following challenges:

Global variable.addItemSpeedIndexIs used to control the interval of adding falling items, which will be mentioned later.scoreIs the variable that saves the score. Since these variables need to return to the initial value after the game startsstartGameThe code is added to the function to complete this task.keyboardEnabled = TrueThis line of code is used to open a keyboard event, and the keyboard event is addedstageObject (see the previous section), but it is used to operate the main character in the game, so it is only useful after the game starts, So joinkeyboardEnabledVariables can be used as the keyboard switch, which will be used to modify the keyboard event listener later.

Player class.This class is the sequence class we want to create, and its code will be displayed later.

Timeline event ENTER_FRAME.We have learned about mouse events.MouseEvent.MOUSE_DOWN,MouseEvent.MOUSE_UP,Event.ENTER_FRAMEWhat is it -_-#? This event is a timeline event. A timeline event is similar to a timer. The listener of this event is triggered at intervals. The interval of event triggering depends oninitThe first parameter of the function.

Run the code and click the start interface to start the game. You can find that the console continuously outputs "loop", which indicates that the timeline event is running.

Player role class

As mentioned above, before writing this classget_fruits/Create a directory namedPlayer.pyPython file. After the file is created, open the file and add the following code:

From pylash. utils import stagefrom pylash. display import Sprite, Animation, BitmapData # create a Player class and inherit it from the Sprite class Player (Sprite): def _ init _ (self, playerImage ): super (Player, self ). _ init _ () # Move direction, [right to the right, left to the left, None not move] self. direction = None # moving speed self. step = 5 # Create Image Data BMP = BitmapData (playerImage) # create an Animation frame list frames = Animation. divideUniformSizeFrames (bmp d. width, bmp d. height, 4, 4) # create an animation self. animation = Animation (bmp d, frames) # sets the animation playback speed self. animation. speed = 5 # play the animation self. animation. play () # Add the animation to the interface self. addChild (self. animation) def loop (self): # Move it to the right if self. direction = "right": self. x + = self. step # play the animation self when moving to the right. animation. currentRow = 2 # Move elif self to the left. direction = "left": self. x-= self. step # play the animation self when moving to the left. animation. currentRow = 1 # Do not move else: # play the animation self when it is not moved. animation. currentRow = 0 # Restrict the character position if self. x <0: self. x = 0 elif self. x> stage. width-self. width: self. x = stage. width-self. width

ThisPlayerClass must inherit fromSpriteTo make it a display object. That is to say, inherited fromSpriteYou can beaddChildGo to the interface and display it. In addition, you can also usePlayerObjectaddChildTo add display elements to the category class.PlayerClass constructor receives a character image parameter.
Used in the codeAnimationClass. It is provided by pylash to create simple image-based animations.AnimationThe constructor receives two parameters: animation bitmap data and animation frame list.

In general, the images used for animation are like this:

Therefore, when playing an animation, you only need to control the size and position of the area displayed in the bitmap to play the animation. It is similar to a projector to show movies. As shown in the following two images, the display area is the blank area, and the area that is not displayed is the area that is covered by a translucent black backdrop. Each small image in the animation is called a frame. When the display area is moved, frames are switched to play the animation.

In the codeAnimation.divideUniformSizeFrames(bmpd.width, bmpd.height, 4, 4)Is used to obtain the position and size of each frame.divideUniformSizeFramesThe static method receives four parameters: animation image width, animation Image Height, number of animation columns, and number of animation lines. This method is only suitable for obtaining a list of frames with a uniform distribution and size.

AnimationThere isspeedAttribute, used to control the animation playback speed. If this attribute is not set, the switching speed of each frame in the animation is equalinitThe refresh speed set in is the same. After setting, the switching speed is changed to speed * refresh speed.

AnimationBy default, only the first row of the animation is played. to specify the position of the animation, you must setcurrentRowAndcurrentColumnAttribute to control the row and column of the video.

Falling Item: Item

This class has never been used before, but we should first write it here, which will be used later. Similarly, create a newItem.pyOpen it and write the code:

From pylash. utils import stagefrom pylash. display import Sprite, Bitmap, BitmapDataclass Item (Sprite): # define a Custom Event EVENT_ADD_SCORE = "event_add_score" EVENT_GAME_OVER = "event_game_over" def _ init _ (self, image ): super (Item, self ). _ init _ () bmp = Bitmap (BitmapData (image) self. addChild (bmp) self. index = 0 self. y =-bmp. height/2 def loop (self): player = None # obtain the object if self. parent: player = self. parent. hitTarget if player is None: return # Move self down. y + = 5 # Collision Detection if (abs (self. x + self. width/2-player. x-player. width/2) <= (self. width + player. width)/2) and (abs (self. y + self. height/2-player. y-player. height/2) <= (self. height + player. height)/2): # if index <= 3, it indicates that the item is fruit if self. index <= 3: # trigger a Custom Event: Add event self. dispatchEvent (Item. EVENT_ADD_SCORE) self. remove () # if an item is not a fruit else: # trigger a Custom Event: Game end self. dispatchEvent (Item. EVENT_GAME_OVER) # remove itself. if self is removed from the screen. y> = stage. height: self. remove ()

ItemClass constructor andPlayerThe constructor accepts an image parameter.
Here we use a relatively advanced feature: Custom events. A custom event can be a string used as the identifier of the event. UsedispatchEventMethod trigger event.dispatchEventMethod inEventDispatcherDefined in.ItemYou can also use this method.
The collision detection section is worth noting. Currently, we can handle simple rectangular collisions. First, let's look at the figure:

If the collision is to be judged horizontally, determine whether the absolute value of (x1-x2) is smaller than or equal to w1/2 + w2/2, if yes, there is a collision. Vertical judgment is the same, to determine whether the absolute value of (y1-y2) is smaller than or equal to h1/2 + h2/2 can be.

Modify event listener

Although we have added events in the code above, there is no valid event listener added, So modify these functions:

Def keyDown (e): global player if not keyboardEnabled or not player: return if e. keyCode = KeyCode. KEY_RIGHT: player. direction = "right" elif e. keyCode = KeyCode. KEY_LEFT: player. direction = "left" def keyUp (e): global player if not keyboardEnabled or not player: return player. direction = Nonedef onMouseDown (e): global player if e. offsetX> (stage. width/2): player. direction = "right" else: player. direction = "left" def onMouseUp (e): global player. direction = Nonedef loop (e): global player, itemLayer, addItemSpeed, addItemSpeedIndex player. loop () for o in itemLayer. childList: o. loop () # control the interval between adding a falling item if addItemSpeedIndex <addItemSpeed: addItemSpeedIndex + = 1 return addItemSpeedIndex = 0 # obtain a random falling item randomNum = random. randint (0, 7) # Add the falling item Item = item (dataList ["item" + str (randomNum)]) item. index = randomNum item. x = int (random. randint (30, stage. width-100) itemLayer. addChild (item) # Add Custom Event item. addEventListener (Item. EVENT_ADD_SCORE, addScore) item. addEventListener (Item. EVENT_GAME_OVER, gameOver)

keyDown,keyUp,onMouseDown,onMouseUpThese four listeners are used by the operator (player).

Next let's look at the listener.loop. In this function,loopMethod (seePlayerClassloop). As defined aboveitemLayerIsSpriteObject,SpriteThe object haschildListAttribute, islistObject. All Sub-objects are saved. So we can traverseitemLayerTo obtain the list of items that fall, and call theirloopMethod. Next, useaddItemSpeedIndexAndaddItemSpeedTwo global variables are used to control the speed of adding a falling item. The following code is used to constructItemClass to create a falling item.

Extra points and Game Over

We giveItemCustom events are added to the object, which are triggered separately.addScoreAndgameOverListener, add these two listeners:

Def addScore (e): global score, scoreTxt score + = 1 scoreTxt. text = "Score: % s" % scoredef gameOver (e): global player, scoreTxt, stageLayer, keyboardEnabled = False stageLayer. removeAllEventListeners () scoreTxt. remove () player. animation. stop () resultTxt = TextField () resultTxt. text = "Final Score: % s" % score resultTxt. size = 40 resultTxt. weight = TextFormatWeight. BOLD resultTxt. textColor = "orangered" resultTxt. x = (stage. width-resultTxt. width)/2 resultTxt. y = 250 stageLayer. addChild (resultTxt) hintTxt = TextField () hintTxt. text = "Double Click to Restart" hintTxt. size = 35 hintTxt. textColor = "red" hintTxt. x = (stage. width-hintTxt. width)/2 hintTxt. y = 320 stageLayer. addChild (hintTxt) # Add the double-click event and click it to start the game stageLayer again. addEventListener (MouseEvent. DOUBLE_CLICK, startGame)

RunMain.py. Move a person to get in touch with the falling item. If you encounter non-fruit items such as broken glass, the game will be over:

OK, we have completed the fruit game. It can be seen that using python + pylash to develop small games is very convenient.

Source code

The source code of this article can be found inexamples/get_fruits. Or you can view it online.

 

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.