![](/img/trans.png)
[英]Collision detection between two rectangles without using a sprite in pygame
[英]How can i create an effective way for collision detection between rectangles in a dictionary in python, (using pygame to emmulate)?
我知道這個問題很長,但是請幫助我,您的時間將不勝感激,與寫作相比,這個問題不是很復雜,我只是不確定如何處理,請幫助我。 (您只需要閱讀我嘗試鏈接的詞典中的代碼,其余的就在您需要時)
I have been working tirelessly on this game which i am making for a project,
it has all been running relatively smoothly until just recently i have found
a rather large issue and i am not sure how to overcome it.
I have been working tirelessly on this game which i am making for a project,
it has all been running relatively smoothly until just recently i have found
a rather large issue and i am not sure how to overcome it.
我的問題如下:
當我為對象創建字典時,它將在屏幕上做某事。
(在這種情況下,玩家的子彈):
我能夠將所有詞典對象放置在屏幕上,並使其執行所有必要的操作,例如向上移動,在某個點處將其自身刪除並使其顯示。 當我嘗試將某些鏈接彼此時,會發生問題。 例如。 我能夠正確地將播放器的矩形鏈接到“ yummy
”字典,如果我的播放器觸摸了該矩形,則'score'
得到了更多的分數,並且刪除了“ yummy
”。 當我嘗試在“ bullet
”和氣泡之間進行碰撞檢測時,也是如此,它會刪除氣泡,子彈並給出更多點,這正是我想要的。 雖然如果我嘗試使用與其他方法相同的方法'z.colliderect(x,y)'
,則它不起作用。 例如,如果我嘗試鏈接“ bigbullet
”和“ yummy
”字典矩形以檢測'bigbullet'
是否命中了“ yummy
”並在發生這種情況時采取措施,我會收到一條消息,說:
'File "E:\Bubble Dash\practice\bubbledashworking1.py", line 347, in play
if u['rect'].colliderect(u['rect']):
UnboundLocalError: local variable 'u' referenced before assignment'
我真的為此感到無比興奮,因為我不太擅長編程,我真的很想知道如何做到這一點,這樣我就可以 以我控制的相同方式控制所有詞典
從
'bubble'
到“ bullet'
詞典,在這里我可以刪除'bigbullet'
,如果碰到“ bubble
”,則給我40分。
#Additional Information: ###########################################################
enemyImage = pygame.image.load('enemy2.png')
yummyImage = pygame.image.load('bubble.png')
bulletImage = pygame.image.load('Haduoken.png')
playerImage = pygame.image.load('player.png')
playerImage2 = pygame.image.load('sadplayer.png')
playerStretchedImage = pygame.transform.scale(playerImage, (40, 40))
def play(PLAY, playing, highscore):
baddie = []
yummy = []
bullet = []
bigbullet = []
movex,movey = 0,0
charx, chary= WindowWidth /2 - 20, 800
enemyy, enemyx = 10, 10
moveright = False
moveleft = False
spawn = False
direction = 'down'
score = 0
level1min = 2
level1max = 7
level2min = 3
level2max = 9
level3min = 5
level3max = 15
level1 = False
level2 = False
level3 = False
boom = False
cheat = False
#for i in range(20):
#baddie.append(pygame.Rect(random.randint(0, WindowWidth - 40), random.randint(0, WindowHeight - 40), 40, 80))
#enemycounter = 0
#newenemy = 40
while True:
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == ord('m'):
pygame.mixer.music.pause()
music = False
if event.key == ord('n'):
pygame.mixer.music.unpause()
music = True
if event.key == ord('a'):
moveleft = True
if event.key == ord('d'):
moveright = True
if event.key == ord('w'):
movey = -5
if score > 100:
movey = -7
if score > 500:
movey = -10
if score > 1000:
movey = -12
if event.key == ord('s'):
movey = 5
if score > 100:
movey = 7
if score > 500:
movey = 10
if score > 1000:
movey = 12
if event.key == ord('p'):
time.sleep(5)
if event.type ==KEYUP:
if event.key == ord('a'):
moveleft = False
if moveleft == False:
movex = 0
if event.key == ord('c'):
cheat = True
if event.key == ord('x'):
cheat = False
if event.key == ord('d'):
moveright = False
if moveright == False:
movex = 0
if event.key == ord('w'):
movey = 0
if event.key == ord('s'):
movey = 0
if event.type == QUIT:
pygame.quit()
sys.exit()
screen.blit(playscreenStretchImage,(0,0))
player = pygame.Rect(charx, chary, 40, 40)
if direction == 'down':
enemyy += 0.5
if moveright ==True:
movex = 5
if score > 100:
movex = 7
if score > 500:
movex = 10
if score > 1000:
movex = 12
if moveleft ==True:
movex = -5
if score > 100:
movex = -7
if score > 500:
movex = -10
if score > 1000:
movex = -12
#for bad in baddie[:]:
#if player.colliderect(bad):
# print('COLLISION')
if player.bottom > WindowHeight:
chary = WindowHeight - 40
movey = 0
print'bottom'
if player.top < 0:
chary = 1
movey = 0
print'top'
if player.left < 0:
charx = -1
movex = 0
if event.type == KEYDOWN:
if event.key == ord('d'):
movex = 5
print 'left'
if player.right > WindowWidth:
charx = WindowWidth - 39
movex = 0
if event.type == KEYDOWN:
if event.key == ord('a'):
movex = -5
print'right'
if playing != False:
score +=1
score_render = font.render("score: %.0f"%score, True, (255,255,255))
time_passed = clock.tick(60)
time_passed_seconds = time_passed*1000
if score in range(40, 60):
screen.blit(countdown3, (WindowWidth / 2, WindowHeight / 2))
if score in range(61, 80):
screen.blit(countdown2, (WindowWidth / 2, WindowHeight / 2))
if score in range(81, 100):
screen.blit(countdown1, (WindowWidth / 2, WindowHeight / 2))
if score in range(440, 460):
screen.blit(countdown3, (WindowWidth / 2, WindowHeight / 2))
if score in range(461, 480):
screen.blit(countdown2, (WindowWidth / 2, WindowHeight / 2))
if score in range(481, 500):
screen.blit(countdown1, (WindowWidth / 2, WindowHeight / 2))
if score in range(940, 960):
screen.blit(countdown3, (WindowWidth / 2, WindowHeight / 2))
if score in range(961, 980):
screen.blit(countdown2, (WindowWidth / 2, WindowHeight / 2))
if score in range(981, 1000):
screen.blit(countdown1, (WindowWidth / 2, WindowHeight / 2))
screen.blit(score_render, (0,0))
if score > highscore:
highscore = score
finalscore = score
score_render = font.render("%0.f"%score, True, (255,255,255))
highscore_render = font.render("Highscore:%.0f"%highscore, True, (255,255,255))
maxscore_render = font.render("%.0f"%highscore, True, (255,255,255))
screen.blit(highscore_render, (200,0))
#Here is the dictionaries i am trying to link:#########################################
#BULLETS
if len(bullet) <1:
bulletSize = 30
newBullet = {'rect': pygame.Rect(charx, chary, bulletSize, bulletSize),
'speed': -20,
'surface': pygame.transform.scale(bulletImage, (bulletSize, bulletSize))}
bullet.append(newBullet)
for l in bullet[:]:
l['rect'].move_ip(0, l['speed'])
for l in bullet[:]:
if l['rect'].top < 0:
bullet.remove(l)
for l in bullet[:]:
screen.blit(l['surface'], l['rect'])
#BIGBULLETS
if len(bigbullet) < 1:
bigbulletSize = 200
newBigBullet = {'rect': pygame.Rect(0, WindowHeight - bigbulletSize, bigbulletSize, bigbulletSize),
'speed': -5,
'surface': pygame.transform.scale(bulletImage, (bigbulletSize,bigbulletSize))}
if score in range(100, 200):
bigbullet.append(newBigBullet)
for u in bigbullet[:]:
u['rect'].move_ip(0, u['speed'])
boom = False
for u in bigbullet[:]:
screen.blit(u['surface'], u['rect'])
#YUMMYYY
if len(yummy)<5:
if score < 100:
yummySize = 100
for y in yummy[:]:
if score == 100:
yummy.remove(y)
if score > 100:
yummySize = 75
for y in yummy[:]:
if score == 500:
yummy.remove(y)
if score >= 500:
yummySize = 50
for y in yummy[:]:
if score == 1000:
yummy.remove(y)
if score >= 1000:
yummySize = 25
newYummy = {'rect': pygame.Rect(random.randint(0, WindowWidth - yummySize), random.randint(0, WindowHeight-yummySize), yummySize-yummySize/2.2 , yummySize-yummySize/2.2),
'speed': random.randint(eminspeed, emaxspeed),
'surface': pygame.transform.scale(yummyImage, (yummySize, yummySize)),}
yummy.append(newYummy)
for y in yummy[:]:
y['rect'].move_ip(0, y['speed'])
for y in yummy[:]:
if y['rect'].top > WindowHeight:
yummy.remove(y)
for y in yummy[:]:
if player.colliderect(y['rect']):
yummy.remove(y)
score += 20
for y in yummy[:]:
if l['rect'].colliderect(y['rect']):
yummy.remove(y)
bullet.remove(l)
score +=40
## for y in yummy[:]:
## if u['rect'].colliderect(y['rect']):
## yummy.remove(y)
## score +=200
##
for y in yummy:
screen.blit(y['surface'], y['rect'])
#BADDDIESS
if len(baddie)<30:
eminsize = 10
emaxsize = 40
if score >= 900:
eminsize = 30
emaxsize = 60
enemySize = random.randint(eminsize, emaxsize)
newEnemy = {'rect': pygame.Rect(random.randint(0, WindowWidth- enemySize),0-enemySize, enemySize, enemySize),
'speed': random.randint(eminspeed, emaxspeed),
'level1':random.randint(level1min, level1max),
'level2': random.randint(level2min, level2max),
'level3': random.randint(level3min, level3max),
'surface': pygame.transform.scale(enemyImage, (enemySize, enemySize)),}
baddie.append(newEnemy)
for b in baddie:
if not level1 and not level2 and not level3 and not cheat:
b['rect'].move_ip(0, b['speed'])
if score >= 100:
level1 = True
if level1 and not cheat == True:
b['rect'].move_ip(0, b['level1'])
if cheat and level1 == True:
b['rect'].move_ip(0, 0)
if score >= 500:
level1 = False
level2 = True
if level2 and not cheat == True:
b['rect'].move_ip(0, b['level2'])
elif cheat == True:
b['rect'].move_ip(0, 0)
if cheat and level2 == True:
b['rect'].move_ip(0, 0)
if score >= 1000:
level2 = False
level3 = True
if level3 and not cheat == True:
b['rect'].move_ip(0, b['level3'])
if cheat and level3 == True:
b['rect'].move_ip(0, 0)
if cheat == True:
b['rect'].move_ip(0,0)
for b in baddie[:]:
if level1 == True:
screen.blit(level1text, (400, 0))
elif level2 == True:
screen.blit(level2text, (400, 0))
elif level3 == True:
screen.blit(level3text, (400, 0))
for b in baddie[:]:
if b['rect'].top > WindowHeight:
baddie.remove(b)
for b in baddie[:]:
if player.colliderect(b['rect']):
baddie.remove(b)
charx, chary= WindowWidth /2 - 50, 340
playing = False
for b in baddie:
#Additional Information:#############################################################
while playing == False:
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == ord('m'):
pygame.mixer.music.pause()
if event.key == ord('n'):
pygame.mixer.music.play()
if event.key == K_ESCAPE:
pygame.quit()
sys.exit()
if event.key == ord('r'):
playing = True
play(PLAY, playing, highscore)
if event.key == ord('b'):
presskey(instrtomenu, highscore)
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == MOUSEBUTTONDOWN:
x, y = event.pos
if (x in range (28, 598)) and (y in range(570, 642)):
playing = True
play(PLAY, playing, highscore)
if (x in range (24, 712)) and (y in range(688, 760)):
presskey(instrtomenu, highscore)
score += 0
screen.blit(gameoverscreenStretchImage, (0,0))
screen.blit(score_render, (494, 14))
screen.blit(maxscore_render, (506 ,66))
screen.blit(playerStretchedImage3, (0,227))
if finalscore in range(1100, 1199):
screen.blit(gunterLabel, (450, 408))
screen.blit(gunterLabel2, (450, 463))
screen.blit(gunterStretchImage, (500, 519))
pygame.display.update()
screen.blit(playerStretchedImage, player)
charx+=movex
chary+=movey
clock.tick(FPS)
pygame.display.update()
恐怕您可能需要對程序的結構進行較大的檢查。 字典確實不能做到這一點,您應該使用類,尤其是精靈。 此代碼是包含內置沖突檢測器的sprite的示例。
class collidable(pygame.sprite.Sprite):
def __init__(self,coordinates,image): #this method is called on an instance of a class upon creation. it is always nescessary to pass in "self" as the first argument to a def that is part of a class
pygame.sprite.Sprite.__init__(self)
self.image = image
self.rect = self.image.get_rect()
self.rect.center = coordinates
def collide(self,other): #pass in the other sprite to check for a collision, this will return a True/False value of whether or not you are colliding with the other sprite
mycollisions = pygame.sprite.spritecollide(self,other,False)
for collision in mycollisions:
if collision != self:
return True
return False
您可能對類和對象不是很了解,並且由於主題太寬,我無法解釋,所以我建議您查看關於該主題的python文檔,該文檔相當廣泛。 這是鏈接: http : //docs.python.org/2/tutorial/classes.html
另外,這可能沒有多大意義,所以我將嘗試介紹基礎知識。 Python是一種面向對象的語言。 python中幾乎所有的東西都是一個對象,包括數字,字符串等(當您添加數字時,實際上是在第一個數字上調用def以將其添加到幕后的另一個對象中)。 類是用戶可以用來創建新對象的一種特定類型的對象。 您可以定義一個類並為其創建多個實例。 一個類在其中包含一個變量和函數的列表,因此它將管理與其自身有關的所有其他對象。 這在pygame中是必需的,因為:
a:pygame提供了一個為您做很多工作的sprite類,您應該使用它。b:類是更好的組織數據的方法,即使它們乍一看似乎令人困惑。 您當前使用的字典可以提供類似的功能,但是構建了類來填補這一位置,並且做得更好。 諸如在屏幕上移動實體之類的事物需要管理某些事物,如位置。 字典可以做到這一點,但是類可以做到這一點。
將屬性分配給一個類后,您可以使用
<classname>.<attributename>
例如,要調用我們在可碰撞類的兩個實例之間創建的碰撞函數,我們可以這樣做:
mysprite = collidable((200,200),pygame.image.load("image_path.png").convert_alpha())
myothersprite = collidable((300,300),pygame.image.load("image_path.png").convert_alpha())
if mysprite.collide(myothersprite):
print "sprites are colliding"
我傾向於同意某人或某人的觀點,您在程序上的編碼更少了,這將使調試和編寫變得非常困難。
剛開始編碼時,我以程序編寫了30頁的游戲,並告訴您,使用類/函數將極大地幫助您。
無論如何,進行碰撞檢測的一種非常簡單的方法是在精靈上放置一個圓圈,然后當對象A的坐標在圓圈內時(使用半徑來確定),然后為此設置一個觸發器。
您也可以使用正方形甚至更復雜的形狀。 例如,在正方形的情況下,您只需確定對象a的坐標何時大於包含正方形的“西北”點且小於“東南”點。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.