Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FRect.clipline not working properly #3047

Open
bigwhoopgames opened this issue Aug 9, 2024 · 4 comments
Open

FRect.clipline not working properly #3047

bigwhoopgames opened this issue Aug 9, 2024 · 4 comments
Labels
bug Not working as intended

Comments

@bigwhoopgames
Copy link

pygame-ce 2.5.0 (SDL 2.30.3, Python 3.12.0)

Current behavior:

When using FRects there are instances when clipline does not return the correct line clip

Expected behavior:

Clipline to clip using floats correctly

The below code is an example where a player and an enemy should not be able to see each other through the obstacle rects but they can. The line should be red to indicate that the clipline returned a clip and therefore the player and enemy are out of line of sight.

import pygame

player_pos = [21.015, 41.359]
enemy_pos = [17.321, 90.1746]

obstacles = [pygame.FRect(18, 82, 4, 4),
             pygame.FRect(14, 82, 4, 4),]


# Main function
def main():
    # Set up the display
    display_width = 480
    display_height = 270
    
    screen = pygame.display.set_mode((display_width, display_height), flags = pygame.SCALED)
    pygame.display.set_caption("clipline test")

    player_rect = pygame.FRect(0, 0, 6, 6)
    player_rect.center = player_pos
    
    enemy_rect = pygame.FRect(0, 0, 6, 6)
    enemy_rect.center = enemy_pos

    running = True
    
    # Main loop
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
                
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESC:
                    running = False


        screen.fill((0, 0, 0))

        pygame.draw.rect(screen, 'blue', player_rect)
        pygame.draw.rect(screen, 'purple', enemy_rect)

        for obstacle in obstacles:
            pygame.draw.rect(screen, 'white', obstacle)
            
        color = 'green'

        for obstacle in obstacles:
            if obstacle.clipline(enemy_rect.center, player_rect.center):
                color = 'red'
                
        pygame.draw.line(screen, color, enemy_rect.center, player_rect.center)

        pygame.display.flip()

    pygame.quit()

if __name__ == "__main__":
    main()
@bigwhoopgames bigwhoopgames added the bug Not working as intended label Aug 9, 2024
@itzpr3d4t0r
Copy link
Member

I've checked on this and I believe this one is on SDL.

@bigwhoopgames
Copy link
Author

I ended up just doing a workaround with this code:

def collide_line_line(p1, p2, p3, p4):
    return ((p4[1] - p1[1]) * (p2[0] - p1[0]) > (p2[1] - p1[1]) * (p4[0] - p1[0])) != \
           ((p4[1] - p2[1]) * (p2[0] - p1[0]) > (p2[1] - p2[1]) * (p4[0] - p2[0])) and \
           ((p3[1] - p1[1]) * (p2[0] - p1[0]) > (p2[1] - p1[1]) * (p3[0] - p1[0])) != \
           ((p4[1] - p1[1]) * (p2[0] - p1[0]) > (p2[1] - p1[1]) * (p4[0] - p1[0]))
    
def collide_line_rect(p1, p2, rect):

    # check line collision
    if (collide_line_line(p1, p2, rect.topleft, rect.topright) or
        collide_line_line(p1, p2, rect.topright, rect.bottomright) or
        collide_line_line(p1, p2, rect.bottomright, rect.bottomleft) or
        collide_line_line(p1, p2, rect.bottomleft, rect.topleft)):
        return True

    # check if both points are inside the rectangle
    if (rect.x <= p1[0] <= rect.x + rect.w and
        rect.x <= p2[0] <= rect.x + rect.w and
        rect.y <= p1[1] <= rect.y + rect.h and
        rect.y <= p2[1] <= rect.y + rect.h):
        return True

    return False

@itzpr3d4t0r
Copy link
Member

Oh ok so what you really wanted was checking for collision, kinda like Line.colliderect(). Luckily, that's coming in the geometry module with the Line class.

@bigwhoopgames
Copy link
Author

Ultimately yes, but clipline should still be returning a line segment where it overlaps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Not working as intended
Projects
None yet
Development

No branches or pull requests

2 participants