2017-06-23 24 views
1

現在、私はこのスクリプトをよりうまく実装する方法を理解しようと30分ほどかかりました。私はいくつかの方法を試みましたが、うまく機能しませんでした。 スクリプトを実行しているときに、プレーヤーはちょっと違和感を覚えます。プレーヤーは、接触したときにのみブロック内を移動することができます。壁のpygame衝突検出

x = 64*3 
y = 0 
xvel = 0 
yvel = 0 
grounded = True 

playerRect = pygame.Rect ((x, y, 64, 64)) 

collidelist = [] 

level = ["#=======##=========================", 
     "#=======#==========================", 
     "#==###############=========###=====", 
     "#===============#####==============", 
     "#==================================", 
     "###################################"] 

def makelevel (level): 
    x = y = 0 
    def checkline (line, x, y): 
     for character in line: 
      if character == "#": 
       block = pygame.draw.rect (screen, (50, 50, 255), (x * 64, y * 64, 64, 64)) 
       collidelist.append (block) 
      x += 1 
    for line in level: 
     checkline (line, x, y) 
     y += 1 
def move (xvel, yvel): 
    global x 
    global y 
    global playerRect 
    global collideList 
    x += xvel 
    y += yvel 
    for block in collidelist: 
     if playerRect.colliderect(block): 
      x += -xvel * 2 
      y += -yvel * 2 
      break 
makelevel (level) 

while True: 
    screen.fill ([0, 0, 0]) 
    makelevel (level) 
    playerRect = pygame.Rect ((x, y, 64, 64)) 
    pygame.draw.rect (screen, (255, 255, 255), playerRect) 
    for event in pygame.event.get(): 
     if event.type == pygame.QUIT: 
      pygame.quit() 
      sys.exit() 
      exit() 
    pressed = pygame.key.get_pressed() 
    if pressed [pygame.K_RIGHT]: 
     move (5, 0) 
    if pressed [pygame.K_LEFT]: 
     move (-5, 0) 
    if pressed [pygame.K_UP]: 
     move (0, -5) 
    if pressed [pygame.K_DOWN]: 
     move (0, 5) 
    pygame.display.update() 
+0

青いブロックは壁であると思われます。壁の衝突を検出して処理する最も簡単な方法は、最初にx軸に沿ってrectを移動させ、壁のrectと衝突しているかどうかを確認し、 'playerRect.right'を' block.left'に設定します。方向。次に、y軸で同じことを行い、衝突した場合は 'playerRect.bottom'を' block.top'に設定します。それは、あなたが 'collidelist'を二度反復しなければならないことを意味します。 – skrx

+0

私はそれがうまくいかず、あるいは多分何かが間違ってしまったのではないかと心配しています。 –

+0

多分私は何か間違ったことをしましたか? 'X + =ブロックのxvel collidelistで: playerRect.colliderect(ブロック)場合: playerDirection場合== "右": playerRect.left: playerRect.right = block.left playerDirection == "左" であればcollidelistに= block.right Yブロックの+ = yvel : playerRect.colliderect(ブロック)場合: playerDirection == "UP" の場合: playerRect.top = block.bottom playerDirectionが== "DOWN" の場合: playerRect.bottom = block.top' –

答えて

0

壁との衝突を処理するための、最も簡単な解決策は、最初のx軸に沿ってプレイヤーRECTまたはスプライトを移動し、それが壁に衝突したかどうかを確認してから、我々はに移動している場合はそのrect.right = block.leftを設定することです右の場合はrect.left = block.rightとなります。その後、y軸と同じことを行います。私たちはそれを別にしなければなりません。さもなければ、方向と、rectの位置をリセットする方法を知らないでしょう。

ここでは例です:

import sys 
import pygame 


def makelevel(level): 
    collidelist = [] 
    for y, line in enumerate(level): 
     for x, character in enumerate(line): 
      if character == "#": 
       block = pygame.Rect(x*64, y*64, 64, 64) 
       collidelist.append(block) 
    return collidelist 


def move(xvel, yvel, player_rect, collideList): 
    # Move the rect along the x-axis first. 
    player_rect.x += xvel 
    # Check if it collides with a block. 
    for block in collidelist: 
     if player_rect.colliderect(block): 
      if xvel < 0: # We're moving to the left. 
       # Move the player out of the block. 
       player_rect.left = block.right 
      elif xvel > 0: # We're moving to the right. 
       player_rect.right = block.left 
      break 

    # Now do the same for the y-axis. 
    player_rect.y += yvel 
    for block in collidelist: 
     if player_rect.colliderect(block): 
      if yvel < 0: 
       player_rect.top = block.bottom 
      elif yvel > 0: 
       player_rect.bottom = block.top 
      break 


pygame.init() 
screen = pygame.display.set_mode((800, 600)) 
BLOCK_COLOR = (50, 50, 255) 
BG_COLOR = (0, 0, 0) 

level = ["#=======##=========================", 
     "#=======#==========================", 
     "#==###############=========###=====", 
     "#===============#####==============", 
     "#==================================", 
     "###################################",] 

collidelist = makelevel(level) 
player_rect = pygame.Rect((64*3, 0, 64, 64)) 
# A clock to limit the frame rate. 
clock = pygame.time.Clock() 

while True: 
    for event in pygame.event.get(): 
     if event.type == pygame.QUIT: 
      pygame.quit() 
      sys.exit() 

    pressed = pygame.key.get_pressed() 
    if pressed[pygame.K_RIGHT]: 
     move(5, 0, player_rect, collidelist) 
    if pressed[pygame.K_LEFT]: 
     move(-5, 0, player_rect, collidelist) 
    if pressed[pygame.K_UP]: 
     move(0, -5, player_rect, collidelist) 
    if pressed[pygame.K_DOWN]: 
     move(0, 5, player_rect, collidelist) 

    # Draw everything. 
    screen.fill(BG_COLOR) 

    for rect in collidelist: 
     pygame.draw.rect(screen, BLOCK_COLOR, rect) 

    pygame.draw.rect(screen, (255, 255, 255), player_rect) 

    pygame.display.update() 
    clock.tick(30) # Limit frame rate to 30 fps. 

私は(コードレビューは、(http://codereview.stackexchange.com/をチェックアウト)offtopicであっても)に対処する必要がありますあなたのコードといくつかの他の問題がありました:

  • はほとんどが重大な問題は、メインループでmakelevelと呼ぶことです。メモリが足りなくなるまで、collidelistにますます多くの矩形を追加します。この関数内でリストを作成し、それを返してwhileループの上にある変数に代入して再利用します。

  • checklineの機能をmakelevelの内部に定義する必要もありません。

  • グローバル変数は、コードの理解度と保守性に悪影響を及ぼします。むしろ必要な変数を必要な関数に渡して結果を返します。

  • yxを1だけ増やしてmakelevelにする代わりに、enumerateを使用してください。

+0

あなたは伝説です!私はこれを試したことはありません、休日のために、それは動作するように見えます! –