Pygame - Как правильно применить прокрутку камеры к стенам - PullRequest
0 голосов
/ 06 августа 2020

Итак, я работаю над прокруткой камеры для моей платформерной игры. Проблема в том, что положение стен не обновляется в соответствии с перемещениями объектов правильно.

Способ, которым я подошел к прокрутке, находит разницу, когда объект переместился из своего исходного положения, и забирает это значение из координат стен ( объект, который я выбрал, был средней точкой расстояния между двумя персонажами)

В результате стены могли двигаться, но не поспевали за объектом и казались слишком медленными

Вот как Я вычислил изменение расстояния

scroll[0] += (middle_x - scroll[0])
scroll[1] += (middle_y - scroll[1])

Вот как я обновляю положение стен из значения прокрутки (пока работаю только со значениями x)

def make_map(level):
    x = y = 0
    for row in level:
        for col in row:
            if col == 'W':
                Wall(x - scroll[0],y)
            x += 30
        y += 15
        x = 0

Это все мои код

import os
import pygame
import time
import random
vec = pygame.math.Vector2

#Rectmo
class player1(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.image.load("Characters Sprites\\rectmo.png").convert_alpha()
        self.image = pygame.transform.scale(self.image, (25,90))
        self.rect = self.image.get_rect()
        self.rect.center = (self.rect.width/2,self.rect.height/2)
        self.pos = vec(WIDTH/2,HEIGHT/2)
        self.vel = vec(0,0)
        self.acc = vec(0,0)
        self.testbottom = self.rect.inflate(-6,-90)
        self.testtop = self.rect.inflate(-6,-91)
        self.testright = self.rect.inflate(-20,-33)
        self.testleft = self.rect.inflate(-20,-33)
        self.aftershadow = self.rect.inflate(0,0)
        self.middle = self.rect.inflate(-20,-85)
        self.thing = self.rect.inflate(-20,-85)

    def update(self):
        #just a cool effect for the character
        self.aftershadow.center = self.pos

        #controls
        user_input = pygame.key.get_pressed()

        self.acc.x = 0
        if user_input[pygame.K_d]:
            self.acc.x = player_acc
        if user_input[pygame.K_a]:
            self.acc.x = -player_acc

        #adds Friction    
        self.acc.x += self.vel.x * -0.03
        #applying accelerating equation
        self.vel.x = self.vel.x * 0.95 + self.acc.x
        self.vel.y += self.acc.y
        self.pos += self.vel
        self.rect.center = self.pos

        #stops sprite from moving through other sprites
        if self.rect.colliderect(squarey.rect) == True:
                if squarey.rect.colliderect(self.testright):
                    self.rect.right = squarey.rect.left
                    self.vel.x = 0
                    self.pos = vec(self.rect.center)
                if squarey.rect.colliderect(self.testleft):
                    self.rect.left = squarey.rect.right
                    self.vel.x = 0
                    self.pos = vec(self.rect.center)
                if squarey.rect.colliderect(self.testtop):
                    self.rect.top = squarey.rect.bottom
                    self.vel.y = 0
                    self.pos = vec(self.rect.center)
                        
        #stops sprite from moving through walls
        on_ground = False
        for wall in walls:
            if self.rect.colliderect(wall.rect) == True:
                if wall.rect.colliderect(self.testright):
                    self.rect.right = wall.rect.left
                    self.vel.x = 0
                    self.pos = vec(self.rect.center)
                if wall.rect.colliderect(self.testleft):
                    self.rect.left = wall.rect.right
                    self.vel.x = 0
                    self.pos = vec(self.rect.center)
                if wall.rect.colliderect(self.testtop):
                    self.rect.top = wall.rect.bottom
                    self.vel.y = 0
                    self.pos = vec(self.rect.center)
                        
            #test rectangles x and y positioning correction
            if self.vel.y > 0:
                self.testbottom.y = self.rect.y+99
            else:
                self.testbottom.y = self.rect.y+90
            self.testbottom.x = self.rect.x+3
            self.testtop.y = self.rect.top-1
            self.testtop.x = self.rect.x+3
            self.testright.y = self.rect.y+20
            self.testright.x = self.rect.x+21
            self.testleft.y = self.rect.y+20
            self.testleft.x = self.rect.x-1
            self.middle.x = middle_x
            self.middle.y = middle_y
            self.thing.x = scroll[0]
            self.thing.y = scroll[1]
            

        
        #testing if a pixel below is a wall or a sprite and applying gravity   
            if self.testbottom.colliderect(wall.rect):
                on_ground = True
                if self.vel.y > 0:
                    self.rect.bottom = wall.rect.top
                    self.vel.y = 0
                    self.pos = vec(self.rect.center)
                    
            if self.testbottom.colliderect(squarey.rect):
                on_ground = True
                if self.vel.y > 0:
                    self.rect.bottom = squarey.rect.top
                    self.vel.y = 0
                    self.pos = vec(self.rect.center)
                
        if on_ground:
            self.acc.y = 0
            if not self.testtop.colliderect(squarey.rect):
                if user_input[pygame.K_w]:
                    self.vel.y = -19
                    
        else:
            self.acc.y = player_grav
        
#Squarey
class player2(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.image.load("Characters Sprites\\squal.png").convert_alpha()
        self.image = pygame.transform.scale(self.image, (35,40))
        self.rect = self.image.get_rect()
        self.rect.center = (self.rect.width/2,self.rect.height/2)
        self.pos = vec(WIDTH/2,HEIGHT/2)
        self.vel = vec(0,0)
        self.acc = vec(0,0)
        self.testbottom = self.rect.inflate(-6,-39)
        self.testtop = self.rect.inflate(-6,-39)
        self.testright = self.rect.inflate(-30,-22)
        self.testleft = self.rect.inflate(-30,-22)
        self.aftershadow=self.rect.inflate(0,0)

    def update(self):
        #just a cool effect for the character
        self.aftershadow.center = self.pos

        #controls
        user_input = pygame.key.get_pressed()

        self.acc.x = 0
        if user_input[pygame.K_RIGHT]:
            self.acc.x = player_acc
        if user_input[pygame.K_LEFT]:
            self.acc.x = -player_acc

        #adds Friction    
        self.acc.x += self.vel.x * -0.05
        #applying accelerating equation
        self.vel.x = self.vel.x * 0.95 + self.acc.x
        self.vel.y += self.acc.y
        self.pos += self.vel
        self.rect.center = self.pos
        
        #stops sprite from moving through other sprites
        if self.rect.colliderect(rectmo.rect) == True:
                if rectmo.rect.colliderect(self.testright):
                    #if self.vel.x > 0:
                    self.rect.right = rectmo.rect.left
                    self.vel.x = 0
                    self.pos = vec(self.rect.center)
                if rectmo.rect.colliderect(self.testleft):
                    #if self.vel.x < 0:
                    self.rect.left = rectmo.rect.right
                    self.vel.x = 0
                    self.pos = vec(self.rect.center)
                if rectmo.rect.colliderect(self.testtop):
                    #if self.vel.y < 0:
                    self.rect.top = rectmo.rect.bottom
                    self.vel.y = 0
                    self.pos = vec(self.rect.center)        
                        
        #stops sprite from moving through walls
        on_ground = False
        for wall in walls:
            if self.rect.colliderect(wall.rect) == True:
                if wall.rect.colliderect(self.testright):
                    #if self.vel.x > 0:
                    self.rect.right = wall.rect.left
                    self.vel.x = 0
                    self.pos = vec(self.rect.center)
                if wall.rect.colliderect(self.testleft):
                    #if self.vel.x < 0:
                    self.rect.left = wall.rect.right
                    self.vel.x = 0
                    self.pos = vec(self.rect.center)
                if wall.rect.colliderect(self.testtop):
                    #if self.vel.y < 0:
                    self.rect.top = wall.rect.bottom
                    self.vel.y = 0
                    self.pos = vec(self.rect.center)
                    
                        
            #test square x and y positioning correction
            if self.vel.y > 0:
                self.testbottom.y = self.rect.y+45
            else:
                self.testbottom.y = self.rect.y+40
            self.testbottom.x = self.rect.x+3
            self.testtop.y = self.rect.top-1
            self.testtop.x = self.rect.x+3
            self.testright.y = self.rect.y+15
            self.testright.x = self.rect.x+31
            self.testleft.y = self.rect.y+15
            self.testleft.x = self.rect.x-1

        
        #testing if a pixel below is a wall or a sprite and applying gravity     
            if self.testbottom.colliderect(wall.rect):
                on_ground = True
                if self.vel.y > 0:
                    self.rect.bottom = wall.rect.top
                    self.vel.y = 0
                    self.pos = vec(self.rect.center)

            if self.testbottom.colliderect(rectmo.rect):
                on_ground = True
                if self.vel.y > 0:
                    self.rect.bottom = rectmo.rect.top
                    self.vel.y = 0
                    self.pos = vec(self.rect.center)
                
        if on_ground:
            self.acc.y = 0
            if not self.testtop.colliderect(rectmo.rect):
                if user_input[pygame.K_UP]:
                    self.vel.y = -14
        else:
            self.acc.y = player_grav
            
class Wall(object):
    def __init__(self,wx,wy):
        walls.append(self)
        self.rect = pygame.Rect(wx,wy,30,30)
    def reset_wall(self):
        self.active = False

def load_map(name):
    f = open('Levels\\' + name + '.txt','r')
    data = f.readlines()
    levels=[]
    for row in data:
        levels.append(row)
    return (levels)

def make_map(level):
    x = y = 0
    for row in level:
        for col in row:
            if col == 'W':
                Wall(x - scroll[0],y)
            x += 30
        y += 15
        x = 0
        
        
    
os.environ['SDL_VIDEO_CENTERED'] = '1'
pygame.init()

pygame.display.set_caption('Shapeful')
WIDTH = 1366
HEIGHT= 768
screen = pygame.display.set_mode((WIDTH,HEIGHT))

clock = pygame.time.Clock()
walls = []
player_grav = 0.98
player_acc = 0.5
player_friction = -0.02
rectmo = player1()
squarey = player2()
main_colour = (0,0,0)
colour = main_colour
wall_colour = (255,255,255)
rectmo.pos = (813,500)
squarey.pos = (813,470)
scroll = [0,0]

running = True

#Main loop
while running == True:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
            
    middle_x = ((squarey.rect.center[0] + rectmo.rect.center[0]) / 2)  
    middle_y = ((squarey.rect.center[1] + rectmo.rect.center[1]) / 2)
    scroll[0] += (middle_x - scroll[0])
    #scroll[1] += (middle_y - scroll[1])
    walls = []
    level_T = load_map('Test level')
    make_map(level_T)
    rectmo.update()
    squarey.update()

    

    
    
    
    #Drawing things
    if running == True:
        screen.fill(wall_colour)
        for wall in walls:
            pygame.draw.rect(screen, main_colour,wall.rect)
        #pygame.draw.rect(screen,(255,0,0),rectmo.testbottom)
        #pygame.draw.rect(screen,(255,255,0),rectmo.testtop)
        #pygame.draw.rect(screen,(0,255,0),rectmo.testright)
        #pygame.draw.rect(screen,(255,143,204),rectmo.testleft)
        #pygame.draw.rect(screen,(0,0,255),squarey.testbottom)
        #pygame.draw.rect(screen,(255,255,0),squarey.testtop)
        #pygame.draw.rect(screen,(0,255,0),squarey.testright)
        #pygame.draw.rect(screen,(255,143,204),squarey.testleft)
        pygame.draw.rect(screen,(255,0,0),rectmo.middle)
        pygame.draw.rect(screen,(0,156,255),rectmo.thing)
        pygame.draw.rect(screen,(153,153,255),rectmo.aftershadow)
        pygame.draw.rect(screen,(255,204,204),squarey.aftershadow)
        
        all_sprites_list = pygame.sprite.Group()
        all_sprites_list.add(rectmo,squarey)
        all_sprites_list.draw(screen)

        pygame.display.flip()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...