圖形用戶界面和游戲開發(fā)
主要介紹下
tkinter
和Pygame
兩個模塊, 真搞gui
有用專業(yè)點的票摇,比如wxPython
亥揖、PyQt
、PyGTK
之類的杈湾,學(xué)習(xí)pygame
好好理解面向?qū)ο笞兂山馐嫦敫阌螒蛞彩强梢缘模偷猛氈铝搜芯?/p>
wxpython 可以看這一篇https://www.cnblogs.com/morries123/p/8568666.html
1. 基于tkinter模塊的GUI
GUI是圖形用戶界面的縮寫漆撞,圖形化的用戶界面對使用過計算機的人來說應(yīng)該都不陌生殴泰,在此也無需進行贅述。Python默認的GUI開發(fā)模塊是tkinter(在Python 3以前的版本中名為Tkinter)浮驳,從這個名字就可以看出它是基于Tk的悍汛,Tk是一個工具包,最初是為Tcl設(shè)計的至会,后來被移植到很多其他的腳本語言中离咐,它提供了跨平臺的GUI控件。
基本上使用tkinter來開發(fā)GUI應(yīng)用需要以下5個步驟:
- 導(dǎo)入tkinter模塊中我們需要的東西奉件。
- 創(chuàng)建一個頂層窗口對象并用它來承載整個GUI應(yīng)用宵蛀。
- 在頂層窗口對象上添加GUI組件。
- 通過代碼將這些GUI組件的功能組織起來县貌。
- 進入主事件循環(huán)(main loop)术陶。
大概看下,后面再專門搞個獨立分支研究gui:
import tkinter
import tkinter.messagebox
def main():
flag = True
# 修改標(biāo)簽上的文字
def change_label_text():
nonlocal flag
flag = not flag
color, msg = ('red', 'Hello, world!')\
if flag else ('blue', 'Goodbye, world!')
label.config(text=msg, fg=color)
# 確認退出
def confirm_to_quit():
if tkinter.messagebox.askokcancel('溫馨提示', '確定要退出嗎?'):
top.quit()
# 創(chuàng)建頂層窗口
top = tkinter.Tk()
# 設(shè)置窗口大小
top.geometry('240x160')
# 設(shè)置窗口標(biāo)題
top.title('小游戲')
# 創(chuàng)建標(biāo)簽對象并添加到頂層窗口
label = tkinter.Label(top, text='Hello, world!', font='Arial -32', fg='red')
label.pack(expand=1)
# 創(chuàng)建一個裝按鈕的容器
panel = tkinter.Frame(top)
# 創(chuàng)建按鈕對象 指定添加到哪個容器中 通過command參數(shù)綁定事件回調(diào)函數(shù)
button1 = tkinter.Button(panel, text='修改', command=change_label_text)
button1.pack(side='left')
button2 = tkinter.Button(panel, text='退出', command=confirm_to_quit)
button2.pack(side='right')
panel.pack(side='bottom')
# 開啟主事件循環(huán)
tkinter.mainloop()
if __name__ == '__main__':
main()
效果:
2.使用Pygame進行游戲開發(fā)
這段直接搬作者的了煤痕,主要學(xué)習(xí)思想
Pygame是一個開源的Python模塊梧宫,專門用于多媒體應(yīng)用(如電子游戲)的開發(fā),其中包含對圖像杭攻、聲音祟敛、視頻、事件兆解、碰撞等的支持。Pygame建立在SDL的基礎(chǔ)上跑揉,SDL是一套跨平臺的多媒體開發(fā)庫锅睛,用C語言實現(xiàn),被廣泛的應(yīng)用于游戲历谍、模擬器现拒、播放器等的開發(fā)。而Pygame讓游戲開發(fā)者不再被底層語言束縛望侈,可以更多的關(guān)注游戲的功能和邏輯印蔬。
大神給的例子是大球吃小球,我改了部分bug脱衙,加了點東西進去侥猬,
from enum import Enum, unique
from math import sqrt,cos,sin,pi
from random import randint
import easygui as g
import pygame
class BallType:
normal,diminish,split,hero = range(4)
class Direction:
left, ltop, top, rtop,right, rbottom, bottom, lbottom, nothing = range(9)
dict_direct = {
left: [(10, 170),False],
ltop: [(10, 80), True],
top: [(10, 170), True],
rtop: [(100, 170),True],
right: [(190, 350), False],
rbottom: [(170, 260), True],
bottom: [(190, 350), True],
lbottom: [(280, 350), True],
nothing: [(0, 360), True]
}
def random_ball(balltype,x,y,radius):
sx, sy = randint(-10, 10), randint(-10, 10)
color = Color.random_color()
# 在點擊鼠標(biāo)的位置創(chuàng)建一個球(大小例驹、速度和顏色隨機)
if balltype is BallType.hero:
global hero_ball
hero_ball = Ball(balltype, x, y, radius, sx, sy, color)
balls.append(hero_ball)
else:
ball = Ball(balltype, x, y, radius, sx, sy, color)
balls.append(ball)
# 將球添加到列表容器中
# balls.append(ball)
@unique
class Color(Enum):
"""顏色"""
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GRAY = (242, 242, 242)
@staticmethod
def random_color():
"""獲得隨機顏色"""
r = randint(0, 255)
g = randint(0, 255)
b = randint(0, 255)
return (r, g, b)
class Ball(object):
"""球"""
dirchange = True
direction = 8;
go_direction = 8;
direction_x = 0
direction_y = 0
def __init__(self, balltype, x, y, radius, sx, sy, color=Color.RED):
"""初始化方法"""
self.x = x
self.y = y
self.radius = radius
self.sx = sx
self.sy = sy
self.color = color
self.alive = True
self.balltype = balltype
def do_direction(self,screen):
degree = randint(Direction.dict_direct[self.direction][0][0],Direction.dict_direct[self.direction][0][1])
if Direction.dict_direct[self.direction][1]:
degree = (degree / 180 * pi)
self.direction_x = cos(degree)
self.direction_y = sin(degree)
else:
degree = (degree / 180 * pi)
self.direction_x = sin(degree)
self.direction_y = cos(degree)
self.go_direction = self.direction
def move(self, screen):
"""移動"""
if self.dirchange:
self.dirchange = False
self.do_direction(screen)
maxspeed = 900/self.radius
if maxspeed > 30:
maxspeed = 30
self.x += int(maxspeed * self.direction_x)
self.y += int(maxspeed * self.direction_y)
if self.x - self.radius <= 0 and self.y - self.radius <= 0: # ltop
if self.go_direction is not Direction.ltop:
self.dirchange = True
self.direction = Direction.ltop
elif self.x - self.radius > 0 >= self.y - self.radius and self.x + self.radius < screen.get_width(): # top
if self.go_direction is not Direction.top:
self.dirchange = True
self.direction = Direction.top
elif self.x + self.radius >= screen.get_width() and self.y - self.radius <= 0: # rtop
if self.go_direction is not Direction.rtop:
self.dirchange = True
self.direction = Direction.rtop
elif self.x + self.radius >= screen.get_width() and self.y+self.radius < screen.get_height() and self.y - self.radius > 0: # right
if self.go_direction is not Direction.right:
self.dirchange = True
self.direction = Direction.right
elif self.x + self.radius >= screen.get_width() and self.y + self.radius >= screen.get_height(): # rbottom
if self.go_direction is not Direction.rbottom:
self.dirchange = True
self.direction = Direction.rbottom
elif self.x - self.radius > 0 and self.x + self.radius < screen.get_width() and self.y + self.radius >= screen.get_height(): # bottom
if self.go_direction is not Direction.bottom:
self.dirchange = True
self.direction = Direction.bottom
elif self.x - self.radius <= 0 and self.y + self.radius >= screen.get_height(): # lbottom
if self.go_direction is not Direction.lbottom:
self.dirchange = True
self.direction = Direction.lbottom
elif self.x - self.radius <= 0 < self.y - self.radius and self.y + self.radius < screen.get_height(): # left
if self.go_direction is not Direction.left:
self.dirchange = True
self.direction = Direction.left
def eat(self, other):
"""吃其他球"""
if self.alive and other.alive and self != other:
dx, dy = self.x - other.x, self.y - other.y
distance = sqrt(dx ** 2 + dy ** 2)
if distance < max(self.radius, other.radius )\
and self.radius > other.radius:
if other.balltype is BallType.normal or other.balltype is BallType.hero:
self.radius = self.radius + int(other.radius * 0.146)
if self.radius > 300:
self.radius = 300
elif other.balltype is BallType.diminish:
self.diminish()
elif other.balltype is BallType.split:
self.split()
other.alive = False
def draw(self, screen):
"""在窗口上繪制球"""
# 不能讓hero 出屏
if self.balltype is BallType.hero:
if self.x <= 0:
self.x = 0
if self.y <= 0:
self.y = 0
if self.x >= screen.get_width():
self.x = screen.get_width()
if self.y >= screen.get_height():
self.y = screen.get_height()
if self.balltype is BallType.normal or self.balltype is BallType.hero:
pygame.draw.circle(screen, self.color,
(self.x, self.y), int(self.radius), 0)
elif self.balltype is BallType.diminish:
pygame.draw.rect(screen,self.color,[self.x, self.y, 20,20])
elif self.balltype is BallType.split:
pygame.draw.ellipse(screen,self.color,[self.x, self.y, 20, 10])
def diminish(self):
if self.radius > 30:
self.radius = int(self.radius/2)
def split(self):
if self.radius > 50:
radius_tmp = self.radius
if self.balltype is BallType.hero:
self.radius = int(self.radius/2)
if self.radius < 30:
self.radius = 30
else:
self.radius = int(self.radius/5)
self.alive = False
for index in range(0,20):
degree = 18*index/180*pi
x = self.radius*cos(degree) + self.x
y = self.radius*sin(degree) + self.y
random_ball(BallType.normal,int(x),int(y),self.radius)
# radius = self.radius
# color = self.color
# sx = x
# sy = y
# ball = Ball(x, y, radius, sx, sy, color)
# balls.append(ball)
if self.balltype is not BallType.hero:
balls.remove(self)
def main():
# 定義用來裝所有球的容器
global balls
balls = []
# global hero_ball
ishavehero = False
ishavehero_old = False
# hero_ball = Ball()
# global hero_ball_x
# global hero_ball_y
# 初始化導(dǎo)入的pygame中的模塊
pygame.init()
# 初始化用于顯示的窗口并設(shè)置窗口尺寸
screen = pygame.display.set_mode((1800, 900))
# print(screen.get_height())
# 設(shè)置當(dāng)前窗口的標(biāo)題
pygame.display.set_caption('大球吃小球')
running = True
sum_palce = 0
auto_out_cnt = 0
msg = ''
bFail = False
# 開啟一個事件循環(huán)處理發(fā)生的事件
# random_ball(BallType.hero, randint(100, 500), randint(100, 500), randint(10, 100))
while running:
# 從消息隊列中獲取事件并對事件進行處理
auto_out_cnt += 1
if bFail :
bFail = False
button_choices = g.buttonbox(msg, '游客', choices=('繼續(xù)', '退出'))
if button_choices == '繼續(xù)':
balls.clear()
ishavehero = False
msg = ''
ishavehero_old = False
continue
elif button_choices == '退出':
return 0
if auto_out_cnt >= 20:
if len(balls) < 30:
random_ball(BallType.normal, randint(100, 500, ), randint(100, 500), randint(10, 100))
auto_out_cnt = 0
if ishavehero:
if sum_palce > screen.get_height() * screen.get_width() / 4 \
or hero_ball.radius * hero_ball.radius * pi > screen.get_height() * screen.get_width() / 4:
if sum_palce < hero_ball.radius * hero_ball.radius * pi:
msg = '你贏了'
else:
msg = '你輸了'
ishavehero = False
bFail = True
elif ishavehero is False and ishavehero_old is True:
msg = '你輸了'
bFail = True
if ishavehero_old is True:
if hero_ball.alive is False:
msg = '你輸了'
bFail = True
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# 處理鼠標(biāo)事件的代碼
if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
# 獲得點擊鼠標(biāo)的位置
x,y = event.pos
# hero_ball.
# random_ball(BallType.normal, x, y,randint(10, 100))
if ishavehero is False:
random_ball(BallType.hero, x, y, randint(50, 100))
random_ball(BallType.split, randint(100, 500), randint(100, 500), randint(10, 100))
random_ball(BallType.diminish, randint(100, 500), randint(100, 500), randint(10, 100))
ishavehero = True
ishavehero_old = True
if ishavehero :
hero_ball.x,hero_ball.y = pygame.mouse.get_pos()
screen.fill((255, 255, 255))
# 取出容器中的球 如果沒被吃掉就繪制 被吃掉了就移除
sum_palce = 0
for ball in balls:
if ball.balltype is BallType.normal:
sum_palce += ball.radius*ball.radius*pi
if ball.alive:
ball.draw(screen)
else:
if ball.balltype is not BallType.normal:
random_ball(ball.balltype,randint(100, 500,), randint(100, 500),randint(10, 100))
balls.remove(ball)
pygame.display.flip()
# 每隔50毫秒就改變球的位置再刷新窗口
pygame.time.delay(50)
for ball in balls:
if ball.balltype is BallType.normal:
ball.move(screen)
# 檢查球有沒有吃到其他的球
for other in balls:
if ball.balltype is BallType.normal or ball.balltype is BallType.hero:
ball.eat(other)
for ball in balls:
if ball.alive:
ball.draw(screen)
else:
if ball.balltype is not BallType.normal and ball.balltype is not BallType.hero:
random_ball(ball.balltype, randint(100, 500, ), randint(100, 500), randint(10, 100))
balls.remove(ball)
def printsin(degree):
print('sin(',degree,') = ',sin(degree/180*pi))
def printcos(degree):
print('cos(', degree, ') = ', cos(degree / 180 * pi))
def printsc(degree):
printcos(degree)
printsin(degree)
if __name__ == '__main__':
while True:
ret = main()
if ret is 0:
exit(0)
效果:
目前是點擊之后可以出一個hero角色,然后又矩形吃了會變小退唠,橢圓吃了會分裂鹃锈,達到北京四分之一就結(jié)束了,回去重新搞一下瞧预,加點分裂之后還是跟著主體屎债,然后讓這東東智能點,變成策略游戲
文集傳送門 學(xué)習(xí)python100天
整個學(xué)習(xí)python100天的目錄傳送門
無敵分割線
再最后面附上大神的鏈接
傳送門