pygame實(shí)現(xiàn)彈球游戲流程
一、事件
鼠標(biāo)事件:
pygame.mouse.get_pos():獲取鼠標(biāo)當(dāng)前點(diǎn)的坐標(biāo)
pygame.mouse.get_pressed()[0]:獲取鼠標(biāo)左鍵是否為點(diǎn)擊
二、復(fù)習(xí)碰撞精靈
1、首先是3個球在窗口上移動的最基礎(chǔ)的版本:
import pygame, sys
class MyBall(pygame.sprite.Sprite):
def __init__(self, point, speed):
self.image = pygame.image.load("beach_ball.png")
self.rect = self.image.get_rect()
self.rect.left = point[0]
self.rect.top = point[1]
self.speed = speed
def move(self):
self.rect = self.rect.move(self.speed)
screen.blit(self.image, self.rect)
pygame.init()
size = width, height = 640, 480
screen = pygame.display.set_mode(size)
screen.fill([255, 255, 255])
balls = []
for i in range(3):
ball = MyBall([180+i*180, 200], [8, 8])
balls.append(ball)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
screen.fill([255, 255, 255])
for i in range(len(balls)):
balls[i].move()
pygame.display.flip()
pygame.time.delay(20)這三個球有一個缺點(diǎn),一旦移動到窗口外,就移不回來了,因此,我們要在移動時,進(jìn)行窗口邊沿的判斷
2、增加上下左右邊框的判斷
這樣當(dāng)球試圖超出邊界時,將對應(yīng)方向的速度取反,使得重新回到窗口中來:
def move(self):
self.rect = self.rect.move(self.speed)
if self.rect.right > width: # 新增右邊框判斷
self.speed[0] = -abs(self.speed[0])
if self.rect.left < 0: # 新增左邊框判斷
self.speed[0] = abs(self.speed[0])
if self.rect.bottom > height: # 新增下邊框判斷
self.speed[1] = -abs(self.speed[1])
if self.rect.top < 0: # 新增上邊框判斷
self.speed[1] = abs(self.speed[1])
screen.blit(self.image, self.rect)進(jìn)行到這一步,我們發(fā)現(xiàn)小球碰到一起時沒有發(fā)生碰撞事件,即碰到一起的小球沒有互相撤退,這時碰撞檢測就使用起來了:
通過pygame.sprite.spritecollide我們可以檢測當(dāng)前小球與別的小球是否發(fā)生碰撞,如果發(fā)生碰撞,就將小球當(dāng)前速度取反
3、碰撞處理
1)碰撞后的處理
def crash(self, balls):
balls.remove(self) # 將自身從碰撞組中刪除
if pygame.sprite.spritecollide(self, balls, False): # 檢測碰撞發(fā)生,將自身的速度取反
self.speed[0] = -self.speed[0]
self.speed[1] = -self.speed[1]2)針對小球兩兩組合進(jìn)行碰撞處理:
for i in range(len(balls)):
for j in range(len(balls)):
if i == j:
continue
balls[i].crash([balls[i], balls[j]])這樣小球互相碰到就會向相反的方向彈去。
三、畫出球桿并擊打小球
我們可以設(shè)想當(dāng)小球停止下來后才好進(jìn)行擊打小球的動作,因此,可以針對小球做一個減速處理
然后當(dāng)小球的x,y方向的速度都低于1時即認(rèn)為小球靜止了
1、減速邏輯
def dec_speed(self):
"""減速"""
self.speed[0] *= 0.995
self.speed[1] *= 0.9952、畫出球桿
當(dāng)小球靜時后,我們需要畫出一個球桿,畫法為小球中心點(diǎn)到當(dāng)前鼠標(biāo)的位置畫一條線段:
def wait_hit(self):
if abs(self.speed[0]) > 1 or abs(self.speed[1]) > 1: # 在運(yùn)動狀態(tài),退出,注意需要用abs,原因是速度有正和負(fù)
pass
else:
pos = pygame.mouse.get_pos() # 獲取鼠標(biāo)坐標(biāo)
pygame.draw.line(screen, [255, 0, 0], self.rect.center, pos, 5) # 畫出小球到鼠標(biāo)的紅線
if pygame.mouse.get_pressed()[0]: # 按下鼠標(biāo)左鍵
self.speed[0] = 0.1 * (self.rect.center[0] - pos[0]) # 給小球初始速度
self.speed[1] = 0.1 * (self.rect.center[1] - pos[1])然后加上調(diào)用:
for i in range(len(balls)):
if i == 0:
balls[i].wait_hit() # 只有0號小球靜止時畫出球桿
balls[i].move()
balls[i].dec_speed() # 減速,使得小球最終靜止下來至此,一開始3個小球都會運(yùn)動,運(yùn)動過程中碰到一起也會發(fā)生碰撞反彈,隨著時間推移,小球越來越慢,最終停下來,然后在0號球處畫出了紅線,點(diǎn)擊鼠標(biāo)左鍵,小球會向紅線的相反方向移動,就是存在一個問題,當(dāng)小球碰到靜止的小球時,靜止的小球不會動
3、碰撞發(fā)生后,當(dāng)發(fā)現(xiàn)自身沒有速度,使用對方的速度
def crash(self, groups):
groups.remove(self) # 將自身從碰撞組中刪除
if pygame.sprite.spritecollide(self, groups, False): # 檢測碰撞發(fā)生,將自身的速度取反
if abs(self.speed[0]) > 1: # 運(yùn)動狀態(tài)用自身的反速度
self.speed[0] = -self.speed[0]
else:
self.speed[0] = -groups[0].speed[0] # 靜止?fàn)顟B(tài),用對方的反速度
if abs(self.speed[1]) > 1:
self.speed[1] = -self.speed[1]
else:
self.speed[1] = -groups[0].speed[1]至此一個簡單的彈球游戲就結(jié)束了
附完整源代碼:
import pygame, sys
class MyBall(pygame.sprite.Sprite):
def __init__(self, point, speed):
self.image = pygame.image.load("beach_ball.png")
self.rect = self.image.get_rect()
self.rect.left = point[0]
self.rect.top = point[1]
self.speed = speed
def move(self):
self.rect = self.rect.move(self.speed)
if self.rect.right > width: # 新增右邊框判斷
self.speed[0] = -abs(self.speed[0])
if self.rect.left < 0: # 新增左邊框判斷
self.speed[0] = abs(self.speed[0])
if self.rect.bottom > height: # 新增下邊框判斷
self.speed[1] = -abs(self.speed[1])
if self.rect.top < 0: # 新增上邊框判斷
self.speed[1] = abs(self.speed[1])
screen.blit(self.image, self.rect)
def crash(self, groups):
groups.remove(self) # 將自身從碰撞組中刪除
if pygame.sprite.spritecollide(self, groups, False): # 檢測碰撞發(fā)生,將自身的速度取反
if abs(self.speed[0]) > 1: # 運(yùn)動狀態(tài)用自身的反速度
self.speed[0] = -self.speed[0]
else:
self.speed[0] = -groups[0].speed[0] # 靜止?fàn)顟B(tài),用對方的反速度
if abs(self.speed[1]) > 1:
self.speed[1] = -self.speed[1]
else:
self.speed[1] = -groups[0].speed[1]
def dec_speed(self):
"""減速"""
self.speed[0] *= 0.995
self.speed[1] *= 0.995
def wait_hit(self):
if abs(self.speed[0]) > 1 or abs(self.speed[1]) > 1: # 在運(yùn)動狀態(tài),退出,注意需要用abs,原因是速度有正和負(fù)
pass
else:
pos = pygame.mouse.get_pos() # 獲取鼠標(biāo)坐標(biāo)
pygame.draw.line(screen, [255, 0, 0], self.rect.center, pos, 5) # 畫出小球到鼠標(biāo)的紅線
if pygame.mouse.get_pressed()[0]: # 按下鼠標(biāo)左鍵
self.speed[0] = 0.1 * (self.rect.center[0] - pos[0]) # 給小球初始速度
self.speed[1] = 0.1 * (self.rect.center[1] - pos[1])
pygame.init()
size = width, height = 640, 480
screen = pygame.display.set_mode(size)
screen.fill([255, 255, 255])
balls = []
for i in range(3):
ball = MyBall([180 + i * 180, 200], [8, 8])
balls.append(ball)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
screen.fill([255, 255, 255])
for i in range(len(balls)):
if i == 0:
balls[i].wait_hit() # 只有0號小球靜止時畫出球桿
balls[i].move()
balls[i].dec_speed() # 減速,使得小球最終靜止下來
for i in range(len(balls)):
for j in range(len(balls)):
if i == j:
continue
balls[i].crash([balls[i], balls[j]])
pygame.display.flip()
pygame.time.delay(10)到此這篇關(guān)于pygame實(shí)現(xiàn)彈球游戲流程的文章就介紹到這了,更多相關(guān)pygame彈球游戲內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python中用append()連接后多出一列Unnamed的解決
Python中用append()連接后多出一列Unnamed的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-01-01
OpenCV實(shí)現(xiàn)機(jī)器人對物體進(jìn)行移動跟隨的方法實(shí)例
這篇文章主要給大家介紹了關(guān)于OpenCV實(shí)現(xiàn)機(jī)器人對物體進(jìn)行移動跟隨的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11
python關(guān)于os.walk函數(shù)查找windows文件方式
這篇文章主要介紹了python關(guān)于os.walk函數(shù)查找windows文件方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-08-08
python實(shí)戰(zhàn)之Scrapy框架爬蟲爬取微博熱搜
前面講解了Scrapy中各個模塊基本使用方法以及代理池、Cookies池。接下來我們以一個反爬比較強(qiáng)的網(wǎng)站新浪微博為例,來實(shí)現(xiàn)一下Scrapy的大規(guī)模爬取。2021-09-09
Python報錯TypeError: tuple indices must be
在Python編程過程中,我們經(jīng)常會遇到各種各樣的報錯信息,其中,“TypeError: tuple indices must be integers or slices, not str”這個報錯,對于很多開發(fā)者來說,可能既熟悉又陌生,今天,我們就來深入探討一下這個報錯,看看它是如何產(chǎn)生的,以及如何快速有效地解決它2025-01-01

