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個(gè)球在窗口上移動(dòng)的最基礎(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)這三個(gè)球有一個(gè)缺點(diǎn),一旦移動(dòng)到窗口外,就移不回來了,因此,我們要在移動(dòng)時(shí),進(jìn)行窗口邊沿的判斷
2、增加上下左右邊框的判斷
這樣當(dāng)球試圖超出邊界時(shí),將對(duì)應(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)小球碰到一起時(shí)沒有發(fā)生碰撞事件,即碰到一起的小球沒有互相撤退,這時(shí)碰撞檢測就使用起來了:
通過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)針對(duì)小球兩兩組合進(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]])這樣小球互相碰到就會(huì)向相反的方向彈去。
三、畫出球桿并擊打小球
我們可以設(shè)想當(dāng)小球停止下來后才好進(jìn)行擊打小球的動(dòng)作,因此,可以針對(duì)小球做一個(gè)減速處理
然后當(dāng)小球的x,y方向的速度都低于1時(shí)即認(rèn)為小球靜止了
1、減速邏輯
def dec_speed(self):
"""減速"""
self.speed[0] *= 0.995
self.speed[1] *= 0.9952、畫出球桿
當(dāng)小球靜時(shí)后,我們需要畫出一個(gè)球桿,畫法為小球中心點(diǎn)到當(dāng)前鼠標(biāo)的位置畫一條線段:
def wait_hit(self):
if abs(self.speed[0]) > 1 or abs(self.speed[1]) > 1: # 在運(yùn)動(dòng)狀態(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號(hào)小球靜止時(shí)畫出球桿
balls[i].move()
balls[i].dec_speed() # 減速,使得小球最終靜止下來至此,一開始3個(gè)小球都會(huì)運(yùn)動(dòng),運(yùn)動(dòng)過程中碰到一起也會(huì)發(fā)生碰撞反彈,隨著時(shí)間推移,小球越來越慢,最終停下來,然后在0號(hào)球處畫出了紅線,點(diǎn)擊鼠標(biāo)左鍵,小球會(huì)向紅線的相反方向移動(dòng),就是存在一個(gè)問題,當(dāng)小球碰到靜止的小球時(shí),靜止的小球不會(huì)動(dòng)
3、碰撞發(fā)生后,當(dāng)發(fā)現(xiàn)自身沒有速度,使用對(duì)方的速度
def crash(self, groups):
groups.remove(self) # 將自身從碰撞組中刪除
if pygame.sprite.spritecollide(self, groups, False): # 檢測碰撞發(fā)生,將自身的速度取反
if abs(self.speed[0]) > 1: # 運(yùn)動(dòng)狀態(tài)用自身的反速度
self.speed[0] = -self.speed[0]
else:
self.speed[0] = -groups[0].speed[0] # 靜止?fàn)顟B(tài),用對(duì)方的反速度
if abs(self.speed[1]) > 1:
self.speed[1] = -self.speed[1]
else:
self.speed[1] = -groups[0].speed[1]至此一個(gè)簡單的彈球游戲就結(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)動(dòng)狀態(tài)用自身的反速度
self.speed[0] = -self.speed[0]
else:
self.speed[0] = -groups[0].speed[0] # 靜止?fàn)顟B(tài),用對(duì)方的反速度
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)動(dòng)狀態(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號(hào)小球靜止時(shí)畫出球桿
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)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python中網(wǎng)絡(luò)請(qǐng)求的12種方式
今天,我們要用一行簡潔的Python代碼來揭開網(wǎng)絡(luò)請(qǐng)求的神秘面紗,別看這行代碼短小,它背后的魔法可強(qiáng)大了,能幫你輕松獲取網(wǎng)頁數(shù)據(jù)、實(shí)現(xiàn)API調(diào)用,甚至更多,無論你是想做數(shù)據(jù)分析、網(wǎng)站爬蟲還是簡單的信息查詢,這12種方式都是你的得力助手,需要的朋友可以參考下2024-07-07
Python中用append()連接后多出一列Unnamed的解決
Python中用append()連接后多出一列Unnamed的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-01-01
pandas篩選某列出現(xiàn)編碼錯(cuò)誤的解決方法
今天小編就為大家分享一篇pandas篩選某列出現(xiàn)編碼錯(cuò)誤的解決方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-11-11
OpenCV實(shí)現(xiàn)機(jī)器人對(duì)物體進(jìn)行移動(dòng)跟隨的方法實(shí)例
這篇文章主要給大家介紹了關(guān)于OpenCV實(shí)現(xiàn)機(jī)器人對(duì)物體進(jìn)行移動(dòng)跟隨的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11
python關(guān)于os.walk函數(shù)查找windows文件方式
這篇文章主要介紹了python關(guān)于os.walk函數(shù)查找windows文件方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08
python實(shí)戰(zhàn)之Scrapy框架爬蟲爬取微博熱搜
前面講解了Scrapy中各個(gè)模塊基本使用方法以及代理池、Cookies池。接下來我們以一個(gè)反爬比較強(qiáng)的網(wǎng)站新浪微博為例,來實(shí)現(xiàn)一下Scrapy的大規(guī)模爬取。2021-09-09
Python報(bào)錯(cuò)TypeError: tuple indices must be
在Python編程過程中,我們經(jīng)常會(huì)遇到各種各樣的報(bào)錯(cuò)信息,其中,“TypeError: tuple indices must be integers or slices, not str”這個(gè)報(bào)錯(cuò),對(duì)于很多開發(fā)者來說,可能既熟悉又陌生,今天,我們就來深入探討一下這個(gè)報(bào)錯(cuò),看看它是如何產(chǎn)生的,以及如何快速有效地解決它2025-01-01

