pygame學習教程(五)用exec優化上一個例子
阿新 • • 發佈:2018-12-17
前一篇
在C,C++程式碼重複工作用巨集表示。舉例。我用Msp430程式設計寫的巨集。
巨集可以理解為文字替換。它的好處在於可以靈活地替換變數,舉個例子。
#define SETOUT(IONAME,IONUMBER) \
P##IONAME##DIR|=BIT##IONUMBER;
這個解釋##,##之間就是變數文字連結 具體SETOUT(1,3) 展開巨集就是IONAME=1,
IONUMBER=3
P##IONAME##DIR|=BIT##IONUMBER;
相當於 “P”+IONAME+“DIR|=BIT”+IONUMBER+";"
結果是P1DIR|=BIT3
這樣寫的好處可以自己體會,至少每次置位不用費腦計算,也不用特意寫一個函式,幾個Msp430系列底層很實用的巨集,其它微控制器可以依據這個思路修改。
#define DIM(a,b) \ int a,b; #define SETOUT(IONAME,IONUMBER) \ P##IONAME##DIR|=BIT##IONUMBER; #define SETB(IONAME,IONUMBER) \ P##IONAME##OUT|=BIT##IONUMBER; #define SETIN(IONAME,IONUMBER) \ P##IONAME##DIR&=~BIT##IONUMBER; #define CLRB(IONAME,IONUMBER) \ P##IONAME##OUT&=~BIT##IONUMBER; #define SET_XOR(IONAME,IONUMBER) \ P##IONAME##OUT ^= (1<<IONUMBER); #define SETONEBITH(NAME,NUMER)\ NAME|=(128>>NUMER) #define SETONEBITL(NAME,NUMER)\ NAME &=~(128>>NUMER) #define CHECK_IO(IONAME,IONUMBER) \ (P##IONAME##IN & (1<<IONUMBER)) #define CHECK_IOOUT(IONAME,IONUMBER) \ (P##IONAME##OUT & (1<<IONUMBER))
在python裡使用exec可以達到巨集的效果,上一個例子。設想一下,我們放置兩個按鈕可以butto1.SetPo(); butto2.SetPo()。如果多個,多個例項化,就會顯得很臃腫。所以這裡我們需要編輯一個新增,簡化程式。這裡希望吧所有的按鈕作為Dict儲存起來。這樣設定:
ButtonDict["butto1"] = [(12, 13), 'feid1.png'] #全域性變數,判定
ButtonDict["butto2"] = [(52, 73), 'feid1.png']
ButtonDict["butto3"] = [(102, 203), 'feid1.png']
在這裡為了讓自己省心,第一段需要優化。可以編寫一個新增函式(這是因為我精力不行,容易出錯。不過程式設計師應該根據自己的習慣調整程式碼)很簡單,自己按照自己的習慣編寫吧。
butto1 = Jbutton((12, 13), 'feid1.png')
butto2 = Jbutton((52, 73), 'feid1.png')
butto3 = Jbutton((102, 203), 'feid1.png')
#這裡的意思是初始化完成根據字典判斷按鈕的位置,實際上可以用按鈕的屬性高判斷
ButtonDict["butto1"] = [ButtonDict["butto1"][0], (butto1.BoPo[0], butto1.BoPo[1])]
ButtonDict["butto2"] = [ButtonDict["butto2"][0], (butto2.BoPo[0], butto2.BoPo[1])]
ButtonDict["butto3"] = [ButtonDict["butto3"][0], (butto3.BoPo[0], butto3.BoPo[1])]
注意到共性,除了文字有變化,其它變化不大,正是使用exec的時機
這段程式碼也是一樣
butto1.SetPo()
butto2.SetPo()
butto3.SetPo()
思路就是把這些變成有規律的指令用exec迴圈執行,如果你新增或刪除一個按鈕就不需要改動太多了。修改這兩個函式,就是把 ButtonDict所有與按鈕有關的程式碼抽象出來自動處理(format一下)
def CreateButton():
# global ButtonDict
mylist=[]
for exi in ButtonDict.keys():
mylist.append("{}=Jbutton({},'{}')".format(exi,ButtonDict[exi][0],ButtonDict[exi][1]))
for exi in ButtonDict.keys():
mylist.append('ButtonDict["{0}"] = [ButtonDict["{0}"][0],({0}.BoPo[0],{0}.BoPo[1])]'.format(exi))
return mylist
def showButton():
mylist = [] #butto1.SetPo()
for exi in ButtonDict.keys():
mylist.append ("{}.SetPo()".format(exi))
return mylist
修正後的程式碼,下一節準備新增滑鼠移動事件
# coding: utf8
import pygame
#匯入pygame庫
from pygame.locals import *
#匯入一些常用的函式和常量
from sys import exit
import pickle
from PIL import Image
import DVerctor
# coding: utf8
import pygame
#匯入pygame庫
from pygame.locals import *
#匯入一些常用的函式和常量
from sys import exit
import pickle
import DVerctor
ButtonDict={}
class JCon():
def __init__(self,vertex,mouse_image_filename):
self.vertex=vertex #設定按鈕頂點 set button vertex (left,top)格式
self.mouse_cursor = pygame.image.load(mouse_image_filename).convert_alpha()
self.count=0 #用於計數
self.BoPo =DVerctor.Vec2d(vertex)+DVerctor.Vec2d(self.mouse_cursor.get_width(),self.mouse_cursor.get_height())
#獲得範圍left+width,top+height (x,y)+(x1,y1)
def SetPo(self): #設定位置 set position #
screen.blit(self.mouse_cursor,self.vertex)
def Mouse_Click(self):
pass
class Jbutton(JCon):
pass
def TextPygame(): #測試模組是否存在和版本號
print(pygame.ver)
pgname = ['pygame.cdrom', 'pygame.cursors', 'pygame.display', 'pygame.draw',
'pygame.event', 'pygame.font', 'pygame.image', 'pygame.joystick',
'pygame.key', 'pygame.mixer', 'pygame.mouse', 'pygame.movie', 'pygame.music',
'pygame.overlay', 'pygame', 'pygame.rect', 'pygame.sndarray', 'pygame.sprite',
'pygame.surface', 'pygame.surfarray', 'pygame.time']
for i in pgname:
if i is None:
print(i+" is None")
else:
print(i + " at this computer")
def storeTree(filename,*args):
with open(filename,'wb') as fw: #開啟需要用'wb'
for i in args:
pickle.dump(i, fw,-1) #為了保護資料protocol=-1,設為0可以看到資料
def grabTree(filename):
Mylist=[] #返回變數的列表
with open(filename,'rb') as fr:
while True: #這裡用try最簡單,不用定義迴圈次數
try:
Mylist.append(pickle.load(fr))
except:
break
return Mylist
def CreateButton():
# global ButtonDict
mylist=[]
for exi in ButtonDict.keys():
mylist.append("{}=Jbutton({},'{}')".format(exi,ButtonDict[exi][0],ButtonDict[exi][1]))
for exi in ButtonDict.keys():
mylist.append('ButtonDict["{0}"] = [ButtonDict["{0}"][0],({0}.BoPo[0],{0}.BoPo[1])]'.format(exi))
return mylist
def showButton():
mylist = [] #butto1.SetPo()
for exi in ButtonDict.keys():
mylist.append ("{}.SetPo()".format(exi))
return mylist
if __name__ == "__main__":
background_image_filename = 'sushiplate.jpg'
# 指定影象檔名稱
pygame.init()
# 初始化pygame,為使用硬體做準備
screen = pygame.display.set_mode((640, 480), 0, 32)
# 建立了一個視窗
pygame.display.set_caption("Hello, World!") # 設定視窗標題
background = pygame.image.load(background_image_filename).convert()
#在這裡新增按鈕
ButtonDict["butto1"] = [(12, 13), 'feid1.png'] #全域性變數,判定
ButtonDict["butto2"] = [(52, 73), 'feid1.png']
ButtonDict["butto3"] = [(102, 203), 'feid1.png']
# ButtonDict = {"butto1": [(12, 13), 'feid1.png'], "butto2": [(52, 73), 'feid1.png'], "butto3": [(102, 203), 'feid1.png']}
s=CreateButton()
# RunStr(s) 這裡不能呼叫函式
for i in s:
exec(i)
print("ButtonDict=",ButtonDict)
#修改ButtonDict
while True:
# 遊戲主迴圈
for event in pygame.event.get():
if event.type == QUIT:
# 接收到退出事件後退出程式
exit()
screen.blit(background, (0, 0))
# 將背景圖畫上去
x, y = pygame.mouse.get_pos()
# 獲得滑鼠位置
# 計算游標的左上角位置
#screen.blit(mouse_cursor, (x, y))
# 把游標畫上去
# butto1.SetPo()
# butto2.SetPo()
# butto3.SetPo()
for i in showButton():
exec(i)
#screen.blit(mouse_cursor, butto1.vertex)
pygame.display.update()
# 重新整理一下畫面