亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何在 pygame 平臺游戲中重寫碰撞邏輯?

如何在 pygame 平臺游戲中重寫碰撞邏輯?

侃侃無極 2023-06-27 16:36:29
我似乎不知道如何為我的平臺游戲編寫碰撞邏輯。項目文件:https ://github.com/1NilusNilus/Pygame-Platformer玩家移動代碼:def move(self):        print(self.POS)        if self.POS[1] > SCREEN_SIZE[1]:            self.POS[1] = SCREEN_SIZE[1] - self.SIZE[1]        self.RECT.x = self.POS[0]        self.RECT.y = self.POS[1]        self.VEL[0] = 0        if self.DIR["left"]:            self.VEL[0] = -5        if self.DIR["right"]:            self.VEL[0] = 5        self.POS[0] += self.VEL[0]                self.VEL[1] += self.GRAVITY瓷磚碰撞測試代碼:def testCollision(self, rect):        self.RECT.x = self.POS[0]        self.RECT.y = self.POS[1]        for tile in self.TILES:            if rect.colliderect(tile):                self.hitlist.append(self.RECT)        return self.hitlist
查看完整描述

1 回答

?
狐的傳說

TA貢獻1804條經驗 獲得超3個贊

您沒有描述您希望碰撞如何進行。所以我會一邊做一邊彌補。

進行碰撞的最簡單方法之一是在嘗試移動期間進行測試。也就是說,在更改玩家的坐標之前確定提議的移動是否合法。這很有效,因為代碼知道玩家的原始位置和行進方向。因此,一個優雅的解決方案將玩家部分地移動到所需的方向直到碰撞點。

所以對于初學者來說,你似乎保留了一個玩家POS和一個玩家RECT。為什么要保留兩個位置?讓我們只使用RECT.?但請記住 Python 風格指南PEP8,我們將其稱為rect.

查看您現有的功能,將move()玩家左右移動,增加重力,并處理屏幕上的情況。恕我直言,玩家移動功能不應該知道重力,因此應該在其他地方處理。它可以簡單地作為 y-change 的一部分傳遞。我將把屏幕測試留給讀者作為練習。

關于碰撞 - 我對你的地圖一無所知,但一次移動可能會與超過 1 個物體發生碰撞。想象一下dx像素的單跳,用例:

http://img2.sycdn.imooc.com/649a9fab0001766605640216.jpg

我們知道這個提議的單跳向右會與 3 個物體發生碰撞。在這個移動實現中,我們只能移動到接觸最左側地形元素“T2”的左側。

你能看出知道擬議的運動是“正確的”對這有什么幫助嗎?它允許我們說:“向右移動dx像素,我們會碰到 3 個東西。所以停在最左邊的那個”。如果你的玩家已經移動,然后你的碰撞報告顯示:“呃-哦,3 次碰撞,老大”,你該如何修復它?你不能。

所以我們采取理論上的移動方式,如果沒有碰撞,那么玩家就可以移動所有的物體。但如果發生碰撞,我們會查看行進方向,并找到距離我們最近的碰撞點。這成為該方向的移動限制。但我們可以像獨立運動一樣簡單地處理dxdy 。

參考代碼:


import pygame

import random


WINDOW_WIDTH? = 500

WINDOW_HEIGHT = 500


WHITE = ( 200, 200, 200 )

GREEN = (? 30, 240,? 80 )

BLUE? = (? ?3,? ?5,? 54 )


class DummyMap:

? ? """ A random map of blockable terrain objects.

? ? ? ? Being random, it sometimes unhelpfully puts blocks over the?

? ? ? ? initial player position.? """


? ? def __init__( self, point_count, x_size=32, y_size=32 ):

? ? ? ? self.blockers = []

? ? ? ? for i in range( point_count ):

? ? ? ? ? ? random_x = random.randint( 0, WINDOW_WIDTH )

? ? ? ? ? ? random_y = random.randint( 0, WINDOW_HEIGHT )

? ? ? ? ? ? self.blockers.append( pygame.Rect( random_x, random_y, x_size, y_size ) )


? ? def draw( self, surface ):

? ? ? ? for tile in self.blockers:

? ? ? ? ? ? pygame.draw.rect( surface, GREEN, tile )

? ? ? ? ? ??

? ? def testCollision( self, rect ):

? ? ? ? """ This function is very much NOT efficeient for large lists.

? ? ? ? ? ? Consider using a quad-tree, etc. for faster collisions """

? ? ? ? colliders = []

? ? ? ? for tile in self.blockers:

? ? ? ? ? ? if ( tile.colliderect( rect ) ):

? ? ? ? ? ? ? ? colliders.append( tile )

? ? ? ? return colliders



class Player:

? ? """ Simple moveable player block, which collides with map elements """


? ? def __init__( self, x, y ):

? ? ? ? self.image? = pygame.Surface( ( 32, 32 ) )

? ? ? ? self.rect? ?= self.image.get_rect()

? ? ? ? self.rect.x = x

? ? ? ? self.rect.y = y

? ? ? ? self.image.fill( WHITE )


? ? def draw( self, surface ):

? ? ? ? surface.blit( self.image, self.rect )


? ? def move( self, dx, dy, game_map ):

? ? ? ? """ Move the player, handling collisions """


? ? ? ? # calculate the target position of any x-move

? ? ? ? if ( dx != 0 ):

? ? ? ? ? ? move_rect = player.rect.copy()

? ? ? ? ? ? move_rect.move_ip( dx, 0 )


? ? ? ? ? ? print( "DEBUG: proposed x-move to (%d, %d)" % ( move_rect.x, move_rect.y ) )


? ? ? ? ? ? # Does this new position collide with the map elements?

? ? ? ? ? ? collide_rects = game_map.testCollision( move_rect )


? ? ? ? ? ? if ( len( collide_rects ) > 0 ):

? ? ? ? ? ? ? ? # yes collided, determine which object is the nearest

? ? ? ? ? ? ? ? if ( dx > 0 ):

? ? ? ? ? ? ? ? ? ? # Going right, get the left-most x out of everything we hit

? ? ? ? ? ? ? ? ? ? lowest_left_side = min( [ r.left for r in collide_rects ] )

? ? ? ? ? ? ? ? ? ? # We can only move right as far as this lowest left-side, minus our width

? ? ? ? ? ? ? ? ? ? final_dx = lowest_left_side - self.rect.right

? ? ? ? ? ? ? ? else:

? ? ? ? ? ? ? ? ? ? # Going left, get the right-most x out of everything we hit

? ? ? ? ? ? ? ? ? ? highest_right_side = max( [ r.right for r in collide_rects ] )

? ? ? ? ? ? ? ? ? ? # We can only move left as far as the highest right-side

? ? ? ? ? ? ? ? ? ? final_dx = highest_right_side - self.rect.left # (this is a negative value)

? ? ? ? ? ? else:

? ? ? ? ? ? ? ? final_dx = dx? # no collsiions, no worries


? ? ? ? ? ? # Do the x-movement

? ? ? ? ? ? self.rect.x += final_dx

? ? ? ? ? ? print( "DEBUG: final x-move to (%d, %d)" % ( self.rect.x, self.rect.y ) )


? ? ? ? if ( dy != 0 ):

? ? ? ? ? ? move_rect = player.rect.copy()

? ? ? ? ? ? move_rect.move_ip( 0, dy )


? ? ? ? ? ? print( "DEBUG: proposed y-move to (%d, %d)" % ( move_rect.x, move_rect.y ) )


? ? ? ? ? ? # Does this new position collide with the map elements?

? ? ? ? ? ? collide_rects = game_map.testCollision( move_rect )


? ? ? ? ? ? if ( len( collide_rects ) > 0 ):

? ? ? ? ? ? ? ? # yes collided, determine which object is the nearest

? ? ? ? ? ? ? ? if ( dy < 0 ):

? ? ? ? ? ? ? ? ? ? # Going up, get the bottom-most y out of everything we hit

? ? ? ? ? ? ? ? ? ? lowest_bottom_side = min( [ r.bottom for r in collide_rects ] )

? ? ? ? ? ? ? ? ? ? # We can only move up as far as this lowest bottom

? ? ? ? ? ? ? ? ? ? final_dy = lowest_bottom_side - self.rect.top

? ? ? ? ? ? ? ? else:

? ? ? ? ? ? ? ? ? ? # Going down, get the top-most y out of everything we hit

? ? ? ? ? ? ? ? ? ? highest_top_side = max( [ r.top for r in collide_rects ] )

? ? ? ? ? ? ? ? ? ? # We can only move down as far as the highest top-side, minus our height

? ? ? ? ? ? ? ? ? ? final_dy = highest_top_side - self.rect.bottom # (this is a negative value)

? ? ? ? ? ? else:

? ? ? ? ? ? ? ? final_dy = dy? # no collsiions, no worries


? ? ? ? ? ? # Do the y-movement

? ? ? ? ? ? self.rect.y += final_dy

? ? ? ? ? ? print( "DEBUG: final x-move to (%d, %d)" % ( self.rect.x, self.rect.y ) )



? ? ? ? ? ? ? ??



### initialisation

pygame.init()

window = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ) )

pygame.display.set_caption("Collision Demo")


# Game elements

player? ?= Player( WINDOW_WIDTH//2, WINDOW_HEIGHT//2 )

game_map = DummyMap( 37 )


### Main Loop

clock = pygame.time.Clock()

done = False

while not done:


? ? # Handle user-input

? ? for event in pygame.event.get():

? ? ? ? if ( event.type == pygame.QUIT ):

? ? ? ? ? ? done = True


? ? # Movement keys

? ? keys = pygame.key.get_pressed()

? ? dx = 0

? ? dy = 0 # 2 # gravity sucks

? ? if ( keys[pygame.K_UP] ):

? ? ? ? dy -= 5

? ? if ( keys[pygame.K_DOWN] ):

? ? ? ? dy += 5

? ? if ( keys[pygame.K_LEFT] ):

? ? ? ? dx -= 5

? ? if ( keys[pygame.K_RIGHT] ):

? ? ? ? dx += 5

? ? # Try to move the player according to the human's wishes

? ? player.move( dx, dy, game_map )



? ? # Update the window, but not more than 60fps

? ? window.fill( BLUE )

? ? game_map.draw( window )

? ? player.draw( window )

? ? pygame.display.flip()


? ? # Clamp FPS

? ? clock.tick_busy_loop(60)


pygame.quit()




查看完整回答
反對 回復 2023-06-27
  • 1 回答
  • 0 關注
  • 181 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號