想學習Python不知從哪開始,來看我和同事通過遊戲開發學習Python
學習python?說得通。它擁有大量穩定的機器學習和資料操作庫。在本文中,將您的Python研究帶到下一個層次。
我的同事和我決定一起做一個小遊戲來幫助我們學習語言。這篇文章介紹了我們最初的經驗,把一切都放在一起。
這個計劃
就像我學過的其他語言一樣,我通常喜歡開發一個應用程式,它涉及到一些功能,比如讀取檔案、網路、使用者輸入和視覺化。這迫使我熟悉了庫和語言的功能,這讓我加快了重新實現演算法和完成教程專案的速度。它還迫使我瞭解Python的環境,以安裝依賴關係和建立發行版。
我們查閱了一些與遊戲建立和網路相關的庫,並決定使用pygame,因為它似乎提供了一種功能,可以從開發中刪除許多單調乏味的內容。它看起來也像Python裡有一系列的網路庫,所以我們決定在使用它的時候把它弄清楚。
安裝Python
Python本身相對容易安裝。我們剛剛從網站上下載了自動安裝程式,並在一分鐘內將執行時準備好。
安裝Pygame
事實證明,安裝Pygame有點令人沮喪。在我們設法下載指令碼並以正確的方式安裝它之前,我們嘗試了好幾次。我們必須找到這個庫的正確版本(它與我們安裝的Python版本相匹配)在一個不容易找到的依賴項列表上,然後用Python包安裝實用程式pip3.exe來提取它。這看起來比實際要困難得多,特別是由於庫的不同版本的數量,以及如果我們安裝了不同版本的Python,我們需要做些什麼。
最終,我們建立了一些東西,並尋找了一個關於如何獲得遊戲基礎的教程。
在這裡還是要推薦下我自己建的Python開發學習群:483546416,群裡都是學Python開發的,如果你正在學習Python ,小編歡迎你加入,大家都是軟體開發黨,不定期分享乾貨(只有Python軟體開發相關的),包括我自己整理的一份2018最新的Python進階資料和高階開發教程,歡迎進階中和進想深入Python的小夥伴
Drawing a Sprite
在開始使用任何圖形的時候,首先要做的事情就是將某些東西(或任何東西)呈現在螢幕上。我們發現了一大堆關於這方面的複雜的教程,並基於他們的例子提出了一個基本的渲染迴圈:
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()
這段程式碼產生:
在那之後,我們將重點放在捕獲使用者輸入以移動字元。我們還為玩家角色建立了一個類來將其邏輯內部化:
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()
我們要做的最後一件事是向客戶端新增一些程式碼,告訴伺服器玩家的位置。這是通過在gameloop的結尾新增一個廣播來序列化當前播放器的位置,然後使用“pickle”,然後將這個bytestream傳送到伺服器:
ge = ['position update', playerid, cc.x, cc.y]
s.send(pickle.dumps(ge))
一旦這是完整的玩家連線到同一個伺服器可以看到其他玩家移動。
一些額外的更新,例如顯示基於playerid的不同的化身被實現。
當完成時,當前的迭代有兩個參與者是這樣的:
相關文章
- [譯] 我想學習程式設計, 但不知道從哪裡開始程式設計
- 開始學習Python!Python
- 《Python深度學習從零開始學》簡介Python深度學習
- Python從零開始——學習Python的個人方法Python
- 今天開始學習PYTHONPython
- AI 學習路線:從Python開始機器學習AIPython機器學習
- 想比較全面地學習 SAP XXX,能指導下從哪兒開始學習嗎?
- 我想開始學習javaJava
- python Scrapy 從零開始學習筆記(二)Python筆記
- python Scrapy 從零開始學習筆記(一)Python筆記
- Python爬蟲學習之旅-從基礎開始Python爬蟲
- 我該從哪裡開始學習精益?
- Access和Python學哪個好?學習分享!Python
- 從Python開始——圖靈圖書學習路線Python圖靈
- 從零開始的Python學習Episode 6——字串操作Python字串
- python和Java學哪個好找工作?Python學習教程!PythonJava
- C++和Python學哪個好?Python學習難嗎?C++Python
- 從零開始學PythonPython
- Python和Java發展前景哪個好?Python開發學習PythonJava
- PHP和Python哪個更適合Web開發?Python學習!PHPPythonWeb
- 通過示例學習Python列表推導Python
- 學Python不知道從何入手?來看看這一份Python學習任務清單!Python
- 從零開始的Python學習 知識補充sortedPython
- 從零開始的Python學習Episode 11——裝飾器Python
- 從零開始的Python學習Episode 14——日誌操作Python
- VB和Python哪個速度快?Python學習!Python
- 13歲如何開始學習Python? - RedditPython
- 從頭開始學習VuexVue
- 從零開始學習KafkaKafka
- 從零開始學習機器學習機器學習
- 從零開始學習laravelLaravel
- 從頭開始在Python中開發深度學習字幕生成模型Python深度學習模型
- 從零開始的Python學習Episode 18——物件導向(1)Python物件
- 從零開始的Python學習Episode 19——物件導向(2)Python物件
- 從零開始的Python學習Episode 7——檔案基本操作Python
- 從零開始的Python學習Episode 15——正規表示式Python
- python 學習筆記(一)通過做題來熟悉python 的基本語法Python筆記
- 學習哪個程式語言呢?Python和C#哪個好學?PythonC#