If you want to learn Python, I don't know where to start, let's see my colleagues and I learn Python through game development

Learning python? make sense. It has a large and stable library of machine learning and data manipulation. In this article, take your Python research to the next level.

My colleague and I decided to make a little game together to help us learn the language. This post presents our initial experience, putting it all together.

If you want to learn Python, I don't know where to start, let's see my colleagues and I learn Python through game development

This plan

Like any other language I've learned, I usually like to develop an application that involves some functionality like reading files, networking, user input, and visualization. This forced me to become familiar with the capabilities of the library and language, which allowed me to speed up reimplementing algorithms and completing tutorial projects. It also forced me to understand Python's environment in order to install dependencies and create distributions.

We looked at some game creation and networking related libraries and decided to use pygame as it seems to provide a feature that removes a lot of the tedious stuff from development. It also looks like there are a bunch of networking libraries in Python, so we decided to figure it out while using it.

Install Python

Python itself is relatively easy to install. We just downloaded the auto-installer from the website and had the runtime ready in a minute.

Install Pygame

Installing Pygame proved to be a bit frustrating. We tried several times before we managed to download the script and install it the right way. We have to find the correct version of this library (which matches the version of Python we have installed) on a list of dependencies that is not easy to find, and then use the Python package installation utility pip3.exe to extract it. This looks a lot harder than it really is, especially due to the number of different versions of the library and what we need to do if we have different versions of Python installed.

Eventually we built something and looked for a tutorial on how to get the basics of the game.

Here I would like to recommend the Python development and learning group I built myself: 483546416. The group is all developed by learning Python. If you are learning Python, the editor welcomes you to join. Everyone is a software development party and shares dry goods from time to time ( Only related to Python software development), including a copy of the latest Python advanced materials and advanced development tutorials in 2018 compiled by myself. Welcome to advanced and advanced partners who want to go deeper into Python

Drawing a Sprite

The first thing to do when starting out with any graphics is to render something (or anything) on ​​the screen. We found a bunch of complicated tutorials on this and came up with a basic rendering loop based on their examples:

import pygame, sys

from pygame.locals import *

WIDTH = 400

HEIGHT = 400

screen = pygame.display.set_mode((WIDTH, HEIGHT))

pygame.display.set_caption('Hello World!')

clock = pygame.time.Clock()

thing = pygame.image.load('images/TrashPanda/TrashPanda_front.png')

x = 0

y = 0

whileTrue:

for event in pygame.event.get():

if event.type == QUIT:

pygame.quit()

sys.exit()

clock.tick(30)

screen.fill((0,0,0))

screen.blit(thing, (x, y))

pygame.display.flip()

This code produces:

If you want to learn Python, I don't know where to start, let's see my colleagues and I learn Python through game development

After that, we focus on capturing user input to move characters. We also created a class for the player character to internalize its logic:

classMinion:

def__init__(self, x, y):

self.x = x

self.y = y

self.vx = 0

self.vy = 0

defupdate(self):

self.x += self.vx

self.y += self.vy

#this keeps the player character within the bounds of the screen

ifself.x > WIDTH - 50:

self.x = WIDTH - 50

ifself.x < 0:

self.x = 0

ifself.y > HEIGHT - 50:

self.y = HEIGHT - 50

ifself.y < 0:

self.y = 0

defrender(self):

screen.blit(thing, (self.x, self.y))

用户输入在游戏循环中被捕获:

for event in pygame.event.get():

if event.type == QUIT:

pygame.quit()

sys.exit()

if event.type == KEYDOWN:

if event.key == K_LEFT: cc.vx = -10

if event.key == K_RIGHT: cc.vx = 10

if event.key == K_UP: cc.vy = -10

if event.key == K_DOWN: cc.vy = 10

if event.type == KEYUP:

if event.key == K_LEFT and cc.vx == -10: cc.vx = 0

if event.key == K_RIGHT and cc.vx == 10: cc.vx = 0

if event.key == K_UP and cc.vy == -10: cc.vy = 0

if event.key == K_DOWN and cc.vy == 10: cc.vy = 0

角色的位置被更新和渲染(同样在游戏中):

cc.update()

cc.render()

现在我们有了基本的字符移动工作,我们想开始构建一些简单的多人游戏功能。

我们决定采用一个非常简单的数据传输模型:

· 客户端连接到服务器,然后不断广播自己的字符的位置

服务器将所有字符的位置广播给所有的客户

我们决定使用TCP套接字,因为它们处理诸如连接和断开连接比UDP更容易。另外,这并不是一个性能关键的应用程序。

我们成功地找到了一篇关于在Python中使用Python编写异步服务器的好文章。

基本的服务器代码是这样开始的:

import socket

import asyncore

import random

import pickle

import time

BUFFERSIZE = 512

outgoing = []

#additional logic here...

classMainServer(asyncore.dispatcher):

def__init__(self, port):

asyncore.dispatcher.__init__(self)

self.create_socket(socket.AF_INET, socket.SOCK_STREAM)

self.bind(('', port))

self.listen(10)

defhandle_accept(self):

conn, addr = self.accept()

print ('Connection address:' + addr[0] + " " + str(addr[1]))

outgoing.append(conn)

playerid = random.randint(1000, 1000000)

playerminion = Minion(playerid)

minionmap[playerid] = playerminion

conn.send(pickle.dumps(['id update', playerid]))

SecondaryServer(conn)

classSecondaryServer(asyncore.dispatcher_with_send):

defhandle_read(self):

recievedData = self.recv(BUFFERSIZE)

if recievedData:

updateWorld(recievedData)

else: self.close()

MainServer(4321)

asyncore.loop()

这定义了一个负责接受新的TCP连接的主服务器,然后它创建一个二级服务器。辅助服务器处理来自每个客户机的所有传入数据。接收到传入的数据包时,将数据传递给updateWorld。这是定义如下:

classMinion:

def__init__(self, ownerid):

self.x = 50

self.y = 50

self.ownerid = ownerid

minionmap = {}

defupdateWorld(message):

arr = pickle.loads(message)

playerid = arr[1]

x = arr[2]

y = arr[3]

if playerid == 0: return

minionmap[playerid].x = x

minionmap[playerid].y = y

remove = []

for i in outgoing:

update = ['player locations']

for key, value in minionmap.items():

update.append([value.ownerid, value.x, value.y])

try:

i.send(pickle.dumps(update))

except Exception:

remove.append(i)

continue

for r in remove:

outgoing.remove(r)

updateWorld只是负责更新包含每个玩家角色位置的字典。然后,它通过将它们的位置序列化为数组的数组,向每个播放器广播这些位置。

现在客户端已经构建好了,我们可以实现客户端发送和接收更新的逻辑。当游戏开始时,我们添加了一些逻辑来启动一个简单的套接字并连接到一个服务器地址。这可选地获取命令行指定的IP地址,但其他方式连接到本地主机:

serverAddr = '127.0.0.1'

iflen(sys.argv) == 2:

serverAddr = sys.argv[1]

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

s.connect((serverAddr, 4321))

然后,我们在游戏循环的开始部分添加了一些逻辑,以便从套接字读取。我们使用“select”包只在有数据的情况下从套接字读取传入的包。如果我们使用了插座。如果套接字没有读取的包,则游戏程序将停止。使用“select”允许gameloop继续执行,即使没有什么可读的:

ins, outs, ex = select.select([s], [], [], 0)

for inm in ins:

gameEvent = pickle.loads(inm.recv(BUFFERSIZE))

if gameEvent[0] == 'id update':

playerid = gameEvent[1]

print(playerid)

if gameEvent[0] == 'player locations':

gameEvent.pop(0)

minions = []

for minion in gameEvent:

if minion[0] != playerid:

minions.append(Minion(minion[1], minion[2], minion[0]))

上面的代码处理了服务器可能生成的两个序列化的有效负载。

1. 包含玩家服务器分配标识符的初始包。

客户端使用此方法在所有位置更新中标识自己到服务器。它还用于忽略服务器广播的自己的播放器数据,因此没有一个带有阴影版本的玩家角色。

2. 球员的位置有效载荷

这包含一组包含玩家标识符和字符位置的数组。当检索到现有的Minion对象时,将为每个传输的对象创建新的Minion对象。

其他的小黄人则在游戏循环中呈现:

for m in minions:

m.render()

The last thing we want to do is add some code to the client that tells the server where the player is. This is done by adding a broadcast at the end of the gameloop to serialize the current player's position, then using "pickle", and then sending this bytestream to the server:

ge = ['position update', playerid, cc.x, cc.y]

s.send(pickle.dumps(ge))

Once this is complete the player connects to the same server and can see other players move.

Some additional updates such as showing different avatars based on playerid were implemented.

When completed, the current iteration has two actors like this:


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324685557&siteId=291194637