तो मैं pygame के साथ हमारे बीच टाइप गेम बनाने की कोशिश कर रहा हूं। मैंने अभी शुरुआत की है, इसलिए मेरे पास बहुत कुछ नहीं है और मैं अभी मानचित्र पर काम कर रहा हूं। हालाँकि, एक चीज जिससे मैं जूझ रहा हूं, वह है टकराव का तर्क। मानचित्र में अभी के लिए एक लम्बी अष्टकोणीय आकृति है, लेकिन मुझे लगता है कि आकार से कोई फर्क नहीं पड़ता कि मैं एक पायगम बहुभुज की तरह कुछ उपयोग करूंगा। जब मैंने अब मेरे पास कोड चलाया, जो मेरे खिलाड़ी (पायगम आयत) और दीवारों (पायगम बहुभुज) के बीच टकराव की जांच करता है तो यह कहता है:

TypeError: Argument must be rect style object

मुझे पता चला है कि यह एक आयत लौटने वाले पायगम बहुभुज की वजह से है, लेकिन टकराव चेकर में इस तरह वर्गीकृत नहीं किया जा रहा है। मैंने टकराव नामक एक पुस्तकालय की कोशिश की है, और एक महान प्रयास देने के लिए टक्कर का पता लगाने के लिए श्रेय दिया है, लेकिन खिलाड़ी अभी भी दीवारों के माध्यम से गड़बड़ करने में सक्षम था। सिडेनोट: मैंने उस कोड को सहेजा है जहां मैंने इस पुस्तकालय का उपयोग किया है यदि कोई इसे देखना चाहता है और शायद मेरे दोषों में सुधार कर सकता है।

वैसे भी, यह सब उबालने के लिए:

मुझे बहुभुज और आयतों के बीच टकराव (वास्तव में, वास्तव में अधिमानतः pygame में) का पता लगाने का एक तरीका चाहिए

किसी भी मदद के लिए धन्यवाद जो आप दे सकते हैं और यदि आपका कोई प्रश्न/अनुरोध है तो कृपया एक टिप्पणी छोड़ दें।

यहाँ मेरा कोड है:

import pygame
pygame.init()
W, H=500, 500
screen = pygame.display.set_mode([500, 500])
running = True

bcg=(200, 200, 200)
red=(255, 0 ,0)
purp=(255, 0, 255)
wall=(100, 100, 100)

class player:
    def bg(self):        
        screen.fill(bcg)
        x,y=self.x,self.y

        self.outer=(
                (x,y),
                (x+800, y),
                (x+1200, y+200),
                (x+1200, y+600),
                (x+800, y+800),
                (x, y+800),
                (x-400, y+600),
                (x-400, y+200),
                
                (x,y),
                
                (x, y+50),
                (x-350, y+225),
                (x-350, y+575),
                (x, y+750),
                (x+800, y+750),
                (x+1150, y+575),
                (x+1150, y+225),
                (x+800, y+50),
                (x, y+50)
            )
        
        pygame.draw.polygon(screen, wall, self.outer)
        
    
    def __init__(self, color, size=20, speed=0.25):
        self.x=0
        self.y=0
        self.col=color
        self.size=size
        self.speed=speed


    def draw(self):
        s=self.size
        self.rect=pygame.Rect(W/2-s/2, H/2-s/2, self.size, self.size)
        pygame.draw.rect(screen, self.col, self.rect)

    def move(self, x, y):
        x*=self.speed
        y*=self.speed
        if not self.rect.colliderect(self.outer):
            self.x+=x
            self.y+=y
        

        

p=player(red)

while running:
    for event in pygame.event.get():
        
        if event.type == pygame.QUIT:
            running = False

    p.bg()

    keys=pygame.key.get_pressed()
    
    if keys[pygame.K_a]: p.move(1, 0)
    if keys[pygame.K_d]: p.move(-1, 0)
    if keys[pygame.K_w]: p.move(0, 1)
    if keys[pygame.K_s]: p.move(0, -1)

    p.draw()

    pygame.display.update()

pygame.quit()
2
Python boi 28 सितंबर 2020, 06:01

1 उत्तर

सबसे बढ़िया उत्तर

एक फ़ंक्शन collideLineLine लिखें जो परीक्षण करता है कि क्या रेखा खंड प्रतिच्छेद कर रहे हैं। इस फ़ंक्शन के एल्गोरिदम को प्रश्न के उत्तर में विस्तार से समझाया गया है pygame, एक घूर्णन आयत की टक्कर का पता लगाना:

def collideLineLine(l1_p1, l1_p2, l2_p1, l2_p2):

    # normalized direction of the lines and start of the lines
    P  = pygame.math.Vector2(*l1_p1)
    line1_vec = pygame.math.Vector2(*l1_p2) - P
    R = line1_vec.normalize()
    Q  = pygame.math.Vector2(*l2_p1)
    line2_vec = pygame.math.Vector2(*l2_p2) - Q
    S = line2_vec.normalize()

    # normal vectors to the lines
    RNV = pygame.math.Vector2(R[1], -R[0])
    SNV = pygame.math.Vector2(S[1], -S[0])
    RdotSVN = R.dot(SNV)
    if RdotSVN == 0:
        return False

    # distance to the intersection point
    QP  = Q - P
    t = QP.dot(SNV) / RdotSVN
    u = QP.dot(RNV) / RdotSVN

    return t > 0 and u > 0 and t*t < line1_vec.magnitude_squared() and u*u < line2_vec.magnitude_squared()

फ़ंक्शन colideRectLine लिखें जो परीक्षण करता है कि क्या एक आयत और एक रेखा खंड प्रतिच्छेद कर रहा है। यह जांचने के लिए कि क्या एक रेखा खंड एक आयत को काटता है, आपको यह परीक्षण करना होगा कि क्या यह आयत के 4 पक्षों में से किसी एक को काटता है:

def colideRectLine(rect, p1, p2):
    return (collideLineLine(p1, p2, rect.topleft, rect.bottomleft) or
            collideLineLine(p1, p2, rect.bottomleft, rect.bottomright) or
            collideLineLine(p1, p2, rect.bottomright, rect.topright) or
            collideLineLine(p1, p2, rect.topright, rect.topleft))

अगला फ़ंक्शन collideRectPolygon परीक्षण करता है कि क्या एक बहुभुज और एक आयत प्रतिच्छेद कर रहे हैं। यह एक लूप में आयत के विरुद्ध बहुभुज पर प्रत्येक पंक्ति खंड का परीक्षण करके प्राप्त किया जा सकता है:

def collideRectPolygon(rect, polygon):
    for i in range(len(polygon)-1):
        if colideRectLine(rect, polygon[i], polygon[i+1]):
            return True
    return False

अंत में आप टकराव परीक्षण के लिए collideRectPolygon का उपयोग कर सकते हैं। ध्यान दें, हालांकि, परीक्षण के लिए आपको बहुभुज का उपयोग करने की आवश्यकता है जैसे कि खिलाड़ी आगे बढ़ रहा था:

class player:
    def bg(self):        
        screen.fill(bcg)
        self.outer = self.createPolygon(self.x, self.y)
        pygame.draw.polygon(screen, wall, self.outer)
  
    def createPolygon(self, x, y):
        return [
            (x,y), (x+800, y), (x+1200, y+200), (x+1200, y+600), 
            (x+800, y+800), (x, y+800), (x-400, y+600), (x-400, y+200),           
            (x,y), (x, y+50), (x-350, y+225), (x-350, y+575), 
            (x, y+750), (x+800, y+750), (x+1150, y+575), (x+1150, y+225),
            (x+800, y+50),(x, y+50)]
    
    # [...]

    def move(self, x, y):
        
        x *= self.speed
        y *= self.speed
        polygon = self.createPolygon(self.x + x, self.y + y)
        if not collideRectPolygon(self.rect, polygon):
            self.x += x
            self.y += y

पूरा उदाहरण:

import pygame
pygame.init()
W, H=500, 500
screen = pygame.display.set_mode([500, 500])
running = True

bcg=(200, 200, 200)
red=(255, 0 ,0)
purp=(255, 0, 255)
wall=(100, 100, 100)

def collideLineLine(l1_p1, l1_p2, l2_p1, l2_p2):

    # normalized direction of the lines and start of the lines
    P  = pygame.math.Vector2(*l1_p1)
    line1_vec = pygame.math.Vector2(*l1_p2) - P
    R = line1_vec.normalize()
    Q  = pygame.math.Vector2(*l2_p1)
    line2_vec = pygame.math.Vector2(*l2_p2) - Q
    S = line2_vec.normalize()

    # normal vectors to the lines
    RNV = pygame.math.Vector2(R[1], -R[0])
    SNV = pygame.math.Vector2(S[1], -S[0])
    RdotSVN = R.dot(SNV)
    if RdotSVN == 0:
        return False

    # distance to the intersection point
    QP  = Q - P
    t = QP.dot(SNV) / RdotSVN
    u = QP.dot(RNV) / RdotSVN

    return t > 0 and u > 0 and t*t < line1_vec.magnitude_squared() and u*u < line2_vec.magnitude_squared()

def colideRectLine(rect, p1, p2):
    return (collideLineLine(p1, p2, rect.topleft, rect.bottomleft) or
            collideLineLine(p1, p2, rect.bottomleft, rect.bottomright) or
            collideLineLine(p1, p2, rect.bottomright, rect.topright) or
            collideLineLine(p1, p2, rect.topright, rect.topleft))

def collideRectPolygon(rect, polygon):
    for i in range(len(polygon)-1):
        if colideRectLine(rect, polygon[i], polygon[i+1]):
            return True
    return False

class player:
    def bg(self):        
        screen.fill(bcg)
        self.outer = self.createPolygon(self.x, self.y)
        pygame.draw.polygon(screen, wall, self.outer)
  
    def createPolygon(self, x, y):
        return [
            (x,y), (x+800, y), (x+1200, y+200), (x+1200, y+600), 
            (x+800, y+800), (x, y+800), (x-400, y+600), (x-400, y+200),           
            (x,y), (x, y+50), (x-350, y+225), (x-350, y+575), 
            (x, y+750), (x+800, y+750), (x+1150, y+575), (x+1150, y+225),
            (x+800, y+50),(x, y+50)]
    
    def __init__(self, color, size=20, speed=0.25):
        self.x=0
        self.y=0
        self.col=color
        self.size=size
        self.speed=speed

    def draw(self):
        s=self.size
        self.rect=pygame.Rect(W/2-s/2, H/2-s/2, self.size, self.size)
        pygame.draw.rect(screen, self.col, self.rect)

    def move(self, x, y):
        
        x *= self.speed
        y *= self.speed
        polygon = self.createPolygon(self.x + x, self.y + y)
        if not collideRectPolygon(self.rect, polygon):
            self.x += x
            self.y += y
            
p=player(red)
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    p.bg()

    keys=pygame.key.get_pressed()
    
    if keys[pygame.K_a]: p.move(1, 0)
    if keys[pygame.K_d]: p.move(-1, 0)
    if keys[pygame.K_w]: p.move(0, 1)
    if keys[pygame.K_s]: p.move(0, -1)

    p.draw()
    pygame.display.update()

pygame.quit()
2
Rabbid76 28 सितंबर 2020, 20:08