Столкновения в Pygame помогают и как не дать ему столкнуться со стенами, когда вы используете угол и скорость для перемещения - PullRequest
1 голос
/ 19 февраля 2020

Скорее всего, я неправильно инициализирую прямоугольники, поэтому игрок постоянно «прыгает через стену», что не предназначено. Скорее всего, я неправильно инициализирую прямоугольники, поэтому игрок постоянно «прыгает через стену», что не предназначено. Скорее всего, я неправильно инициализирую прямоугольники, поэтому игрок постоянно «прыгает через стену», что не предназначено.

Это основной:

import pygame
import wall
import Player
import math

pygame.init()
pygame.display.set_caption("Tanki")
pygame.display.set_icon(pygame.image.load("mainIcon.png"))

running = True
screen = pygame.display.set_mode((300, 500))

WALLS = pygame.sprite.Group()
fence = \
    [wall.Wall(0, 0, 300, 10, pygame.Color(255, 255, 255), screen),
     wall.Wall(290, 0, 10, 500, pygame.Color(255, 255, 255), screen),
     wall.Wall(0, 0, 10, 500, pygame.Color(255, 255, 255), screen),
     wall.Wall(0, 490, 300, 10, pygame.Color(255, 255, 255), screen),
     # boundry
     wall.Wall(10 + 60, 235, 50, 10, pygame.Color(255, 255, 255), screen),
     wall.Wall(10 + 60 + 50 + 60, 235, 50, 10, pygame.Color(255, 255, 255), screen),
     # middle blocks
     wall.Wall(100, ((245 + 500 - 60) / 2) - 5, 100, 10, pygame.Color(255, 255, 255), screen),
     wall.Wall(100, ((235 + 60) / 2) - 5, 100, 10, pygame.Color(255, 255, 255), screen),
     wall.Wall(10 + 66.666, 440, 66.666 + 80, 10, pygame.Color(255, 255, 255), screen),
     wall.Wall(10 + 66.666, 430, 10, 10, pygame.Color(255, 255, 255), screen),
     wall.Wall(10 + 66.666 * 2 + 80 - 11, 430, 10, 10, pygame.Color(255, 255, 255), screen),
     # everythin around the goal
     wall.Wall(10 + 66.666 + 10, 430, 66.666 + 80 - 11 - 9, 10, pygame.Color(0, 0, 200), screen),
     # the bottom goal MAKE A CLASS FOR THIS
     wall.Wall(10 + 66.666, 50, 66.666 + 80, 10, pygame.Color(255, 255, 255), screen),
     wall.Wall(10 + 66.666, 60, 10, 10, pygame.Color(255, 255, 255), screen),
     wall.Wall(10 + 66.666 * 2 + 80 - 11, 60, 10, 10, pygame.Color(255, 255, 255), screen),
     # everythin around the goal
     wall.Wall(10 + 66.666 + 10, 60, 66.666 + 80 - 11 - 9, 10, pygame.Color(200, 0, 0), screen)
     # the top goal

     ]

tmp = Player.Player(pygame.Color(0, 255, 0), 20, 20, 140, 455, 0.05, 180, 0)
pro = Player.Player(pygame.Color(0, 255, 0), 20, 20, 140, 455, 0.05, 180, tmp)
for eachwall in fence:
    WALLS.add(eachwall)
count = 1
while running:
    count += 1
    print(pro.getAngle() % 360)
    if (count % 10 == 0):
        tmp.updatetmp(pro)
    screen.fill(pygame.Color(0, 0, 0))
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                pro.setAngle(pro.getAngle() - 10)
            if event.key == pygame.K_RIGHT:
                pro.setAngle(pro.getAngle() + 10)
            if event.key == pygame.K_UP:
                pro.setVel(0.05)
            if event.key == pygame.K_DOWN:
                pro.setVel(-0.05)
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
                pro.setVel(0)
    b = True
    for block in WALLS:
        if (pygame.sprite.collide_rect(pro, block)):
            b = False
            print("A")

    a = pro.update(WALLS, screen,b)

    for awall in WALLS:
        awall.draw()
    pygame.display.update()

Это игрок

import pygame
import math


class Player(pygame.sprite.Sprite):
    direction = 'right'

    def __init__(self, color, width, height, x, y, velocity, angle, past):
        # Pygame constructor
        pygame.sprite.Sprite.__init__(self)
        self.past = past
        # Init. variables
        self.angle = angle
        self.velocity = velocity
        self.color = color
        self.width = width
        self.height = height
        self.x = x
        self.y = y
        # Create sprite
        self.image = pygame.Surface([width, height])
        self.image.fill(self.color)
        self.rect = self.image.get_rect(topleft = (self.x, self.y))

        #############################
    def setColor(self, color):
        self.color = color
    def setX(self, X):
        self.x = X
    def setY(self, Y):
        self.y = Y
    def setVel(self, vel):
        self.velocity = vel
    def setAngle(self, ANGLE):
        self.angle = ANGLE
    ##############################
    def getColor(self):
        return self.color

    def getX(self):
        return self.x

    def getY(self):
        return self.y

    def getVel(self):
        return self.velocity

    def getAngle(self):
        return self.angle
#################################
    def draw(self, screen):
        # Draw player on the screen
        pygame.draw.rect(screen, self.color, [self.x, self.y, self.width, self.height], 0)

    def deg_to_rad(self):
        return int(self.angle * math.pi) / 180

    def rad_to_offset(self, offset):  # insert better func name.
        radians = self.deg_to_rad()
        x = math.cos(radians) * offset
        y = math.sin(radians) * offset
        return [x, y]

    def move(self, walls, go):

        if go:
            forward = self.rad_to_offset(self.velocity)
            self.x += forward[0]
            self.y += forward[1]
        else:
            print("collided")


    def update(self, walls, screen, go):
        if(self.angle>=360):
            self.angle = self.angle%360
        hit = self.move(walls, go)
        self.draw(screen)
        return hit
    def updatetmp(self, Player):
        self.angle = Player.getAngle()
        self.velocity = Player.getVel()
        self.color = Player.getColor()
        self.x = Player.getX()
        self.y = Player.getY()

Это класс Стены

import pygame

class Wall(pygame.sprite.Sprite):
    def __init__(self, x, y, width, height, color, screen):
        pygame.sprite.Sprite.__init__(self)
        self.x = x
        self.y = y
        self.height = height
        self.width = width
        self.color = color
        self.screen = screen
        self.image = pygame.Surface((width, height))
        self.image.fill(color)
        self.rect = self.image.get_rect(topleft = (self.x, self.y))

    def get_rectangle(self):
        return pygame.Rect(self.x, self.y, self.width, self.height)

    def draw(self):
        pygame.draw.rect(self.screen, self.color, (self.x, self.y, self.width, self.height), 0)

1 Ответ

0 голосов
/ 19 февраля 2020

Операции типа pygame.sprite.collide_rect() или pygame.sprite.spritecollide() используют атрибут .rect объекта Sprite для выполнения теста на столкновение.
Объект игрока расположен по атрибутам с плавающей точкой .x и .y. Вы должны синхронизировать это местоположение с (целым) атрибутом .rect в обновлении, чтобы заставить тест на столкновение работать:

class Player(pygame.sprite.Sprite):
    # [...]

    def update(self, walls, screen, go):
        if(self.angle>=360):
            self.angle = self.angle%360
        hit = self.move(walls, go)

        self.rect.topleft = (round(self.x), round(self.y)) # <-----
        self.draw(screen)
        return hit

Более того, нет необходимости повторять все WALLS:

for block in WALLS:
   if pygame.sprite.collide_rect(pro, block):
       b = False
       print("A")

Используйте pygame.sprite.spritecollide() вместо `` pygame.sprite.collide_rect () `

if pygame.sprite.spritecollide(pro, WALLS, False):
    b = False
    print("A")

Обратите внимание, что нет необходимости внедрять draw() методы в Player и Wall. Вы можете использовать draw() метод Group. Этот удобный метод использует атрибуты .rect и .image содержащихся объектов Sprite для их рисования.

Удалите метод draw из Player и Wall. Добавьте игроков и стены в группы и вызовите draw() для групп:

fence = \
    [wall.Wall(0, 0, 300, 10, pygame.Color(255, 255, 255), screen),
     # [...]
    ]

tmp = Player.Player(pygame.Color(0, 255, 0), 20, 20, 140, 455, 0.05, 180, 0)
pro = Player.Player(pygame.Color(0, 255, 0), 20, 20, 140, 455, 0.05, 180, tmp)

WALLS = pygame.sprite.Group(fence)
players = pygame.sprite.Group([tmp, pro])

count = 1
while running:
    count += 1

    # [...]

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