Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
149 views
in Technique[技术] by (71.8m points)

python - Why does the "move 5 - if touching wall - move back 5" logic not work when scrolling is implemented?

I know that this sort of wall detection logic works fine in most games, but I wanted some more pizzaz. So, I implemented scrolling, where the player is always in the middle and instead, the background moves.

keys=pygame.key.get_pressed()
if keys[pygame.K_w]:
    y-=5
    if rect.colliderect(wall):
        y+=5

The way my scrolling works is all the objects are drawn relative to the variable scrollx and scrolly. When keys are pressed, scrollx or scrolly changes. When the collision actually happens though, the player seems to get stuck in the objects. Here's the full code.

import pygame
import random
pygame.init()
win_height=600
win_width=600
win=pygame.display.set_mode((win_width,win_height))
pygame.display.set_caption("YourCraft")
white=(255,255,255)
black=(0,0,0)
green=(0,255,0)
clock=pygame.time.Clock()
debris_list=[]

player=pygame.Rect(win_width/2,win_height/2,20,20)
scrolly=0
scrollx=0

size=1000
speed=5

class debris_class():
    def __init__(self):
        self.x=random.randrange(0,size-20)
        self.y=random.randrange(0,size-20)
        self.rect=pygame.Rect(self.x,self.y,20,20)
    def update(self):
        pygame.draw.rect(win,white,self.rect)
        self.rect.y=scrolly+self.y
        self.rect.x=scrollx+self.x

for i in range(10):
    debris=debris_class()
    debris_list.append(debris)

def collision():
    for i in debris_list:
        if i.rect.colliderect(player):
            return 1
    return 0

while True:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type==pygame.QUIT:
            pygame.quit()

    key=pygame.key.get_pressed()
    if key[pygame.K_s]:
        scrolly-=speed
        collide=collision()
        if collide==1:
            scrolly+=speed

    if key[pygame.K_w]:
        scrolly+=speed
        collide=collision()
        if collide==1:
            scrolly-=speed

    if key[pygame.K_d]:
        scrollx-=speed
        collide=collision()
        if collide==1:
            scrollx+=speed

    if key[pygame.K_a]:
        scrollx+=speed
        collide=collision()
        if collide==1:
            scrollx-=speed


    win.fill(black)
    pygame.draw.rect(win,green,(scrollx,scrolly,size,size)) #background
    pygame.draw.rect(win,white,player)

    for i in debris_list:
        i.update()

    pygame.display.update()

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You are performing the collision test too early. When the collision test is run, the object and map have not yet been scrolled.

Separate update and draw in the class debris_class:

class debris_class():
    def __init__(self):
        self.x=random.randrange(0,size-20)
        self.y=random.randrange(0,size-20)
        self.rect=pygame.Rect(self.x,self.y,20,20)
    def update(self):
        self.rect.y=scrolly+self.y
        self.rect.x=scrollx+self.x
    def draw(self):
        pygame.draw.rect(win,white,self.rect)

Get the movement depending on the keys pressed and the speed:

key=pygame.key.get_pressed()
move_x = (key[pygame.K_d] - key[pygame.K_a]) * speed
move_y = (key[pygame.K_s] - key[pygame.K_w]) * speed

Copy the plyer and move the player:

player_copy = player.copy()
player.x += move_x
player.y += move_y

Perform the collision test and undo the movement of the player:

collide = collision()
player = player_copy

If no collision is detected, scroll the map and the objects:

if collide == 0:
    scrollx -= move_x
    scrolly -= move_y
    for i in debris_list:
        i.update()     

Draw the objects in a loop:

for i in debris_list:
    i.draw()

Complete code:

import pygame
import random

pygame.init()
win_height=600
win_width=600
win=pygame.display.set_mode((win_width,win_height))
pygame.display.set_caption("YourCraft")
white=(255,255,255)
black=(0,0,0)
green=(0,255,0)
clock=pygame.time.Clock()
debris_list=[]

player=pygame.Rect(win_width/2,win_height/2,20,20)
scrolly=0
scrollx=0

size=1000
speed=5

class debris_class():
    def __init__(self):
        self.x=random.randrange(0,size-20)
        self.y=random.randrange(0,size-20)
        self.rect=pygame.Rect(self.x,self.y,20,20)
    def update(self):
        self.rect.y=scrolly+self.y
        self.rect.x=scrollx+self.x
    def draw(self):
        pygame.draw.rect(win,white,self.rect)

for i in range(10):
    debris=debris_class()
    debris_list.append(debris)

def collision():
    for i in debris_list:
        if i.rect.colliderect(player):
            return 1
    return 0

while True:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type==pygame.QUIT:
            pygame.quit()

    key=pygame.key.get_pressed()
    move_x = (key[pygame.K_d] - key[pygame.K_a]) * speed
    move_y = (key[pygame.K_s] - key[pygame.K_w]) * speed
    
    player_copy = player.copy()
    player.x += move_x
    player.y += move_y

    collide = collision()
    player = player_copy
    if collide == 0:
        scrollx -= move_x
        scrolly -= move_y
        for i in debris_list:
            i.update()
           
    win.fill(black)
    pygame.draw.rect(win,green,(scrollx,scrolly,size,size)) #background
    pygame.draw.rect(win,white,player)
    for i in debris_list:
        i.draw()
    pygame.display.update()

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...