2017-01-29 1 views
0

Ich versuche, ein kleines Spiel zu bauen, das darauf basiert, das Kabel nicht zu berühren (Sie müssen einen Kreis um einen Draht/eine Linie manövrieren). Ich bin mir nicht sicher, wo ich anfangen soll, die Kollision zwischen dem Draht und der Kante des Kreises zu programmieren, weil sich der Draht zufällig von selbst bewegt. Muss ich eine Liste erstellen, in der alle Koordinaten der Linie gespeichert sind? Hier ist der Code für sie:PyGame Collsion Problem

import pygame 
from random import randint 

pygame.init() 

white = (255, 255, 255) 
black = (0, 0, 0) 
red = (255, 0, 0) 
green = (0, 255, 0) 
blue = (0, 0, 255) 

display_width = 600 
display_height = 600 

gameDisplay = pygame.display.set_mode((display_width, display_height)) 
pygame.display.set_caption("Wire") 
font = pygame.font.SysFont("aerial", 20) 
clock = pygame.time.Clock() 
pygame.display.update() 


def text_objects(text, colour): 
    textSurface = font.render(text, True, colour) 
    return textSurface, textSurface.get_rect() 

def message_to_screen(msg, colour, xpos, ypos): 
    textSurf, textRect = text_objects(msg, colour) 
    textRect.center = (xpos), (ypos) 
    gameDisplay.blit(textSurf, textRect) 

def gameLoop(FPS): 
    start = 0 
    from math import pi 
    gameExit = False 
    gameOver = False 
    num_top = 300 
    num_bot = 300 
    pygame.mouse.set_pos(display_width/2, display_height/2) 
    line_array =[] 
    line_thickness = 8 

    while not gameExit: 
     mouse = pygame.mouse.get_pos() 
     # print(mouse) 
     if (start == 0): 
      print("Game Started") 
     elif(mouse[0] <= 48) or (mouse[0] >= 547) or (mouse[1] <= 25) or (mouse[1] >=585): 
      gameOver = True 
     start += 1 
     if gameOver == True: 
      gameDisplay.fill(white) 
      message_to_screen("You Lost", red, 300, 300) 
     for event in pygame.event.get(): 
      if event.type == pygame.QUIT: 
       gameExit = True 
      if event.type == pygame.KEYDOWN: 
       if event.key == pygame.K_q: 
        gameExit = True 

     rand_nums = [randint(-3, 3), randint(-3, 3)] 
     num_top += rand_nums[0] 
     num_bot += rand_nums[1] 
     message_to_screen("Press q or the x button to quit", blue, 100, 40) 
     pygame.display.update() 
     gameDisplay.fill(white) 
     pygame.draw.arc(gameDisplay, red, [mouse[0]-48, mouse[1]-25, 100, 40], 0, pi, 3) 
     pygame.draw.line(gameDisplay, black, [num_top, 0], [num_bot, 600], line_thickness) 
     pygame.draw.arc(gameDisplay, red, [mouse[0]-48, mouse[1]-25, 100, 40], 3 * pi, 2 * pi, 3) 

     clock.tick(FPS) 

    pygame.quit() 
    quit() 
gameLoop(100) 
+0

Sie haben nur zwei Punkte von Kreis zu überprüfen, ob sie auf schwarze Linie ar - und es gibt eine mathematische Methode, um zu prüfen, ob ein Punkt online ist. Sie brauchen nur Start- und Endpunkt der Linie. Sie müssen nicht alle Punkte online auflisten. – furas

+0

Wie mache ich das, wenn ich nur den Anfangs- und Endpunkt der Linie angegeben habe? Muss ich eine Liste der Pixel erstellen? –

+0

http://gamedev.stackexchange.com/questions/26004/how-to-detect-2d-line-on-line-collision – Viney

Antwort

0

I berechnen Winkel (siehe roten und grünen Winkel auf dem Bild) und sie vergleichen. Wenn sie fast identisch sind, dann ist der Punkt auf der Linie - also gibt es eine Kollision.

Weil float nicht ideale Ergebnisse gibt, also muss ich vergleichen, ob die Winkel fast identisch sind.

if -0.01 < tanges_angle - tanges_angle_p1 < 0.01: 

Es muß kleinere oder größere Werte als 0.01

ersten Engel berechnen (grün) Ich brauche nur Fußpunkt und oberen Punkt der schwarzen Linie. Um den zweiten Winkel zu berechnen, brauche ich den unteren Punkt der schwarzen Linie und zeige auf den Kreis.

enter image description here

#!/usr/bin/env python3 

import pygame 
from random import randint 
from math import pi 

# --- constants --- (UPPER_CASE names) 

WHITE = (255, 255, 255) 
BLACK = ( 0, 0, 0) 
RED = (255, 0, 0) 
GREEN = ( 0, 255, 0) 
BLUE = ( 0, 0, 255) 

DISPLAY_WIDTH = 600 
DISPLAY_HEIGHT = 600 
CENTER_X = DISPLAY_WIDTH//2 
CENTER_Y = DISPLAY_HEIGHT//2 

FPS = 30 

LINE_THICKNESS = 8 

PI_2 = 2*pi 
PI_3 = 3*pi 

# --- functions --- (lower_cas names) 

def render_text(text, colour): 
    image = font.render(text, True, colour) 
    rect = image.get_rect() 
    return image, rect 

def message(screen, msg, colour, x, y): 
    image, rect = render_text(msg, colour) 
    rect.center = (x, y) 
    screen.blit(image, rect) 

def gameloop(): 

    num_top = 300 
    num_bot = 300 

    pygame.mouse.set_pos(CENTER_X, CENTER_Y) 

    start = True 
    game_exit = False 
    game_over = False 

    while not game_exit: 

     # - events - 

     for event in pygame.event.get(): 
      if event.type == pygame.QUIT: 
       game_exit = True 
      if event.type == pygame.KEYDOWN: 
       if event.key == pygame.K_q: 
        game_exit = True 

     # - updates - 

     m_x, m_y = pygame.mouse.get_pos() 

     if start: 
      print("Game Started") 
      start = False 
     elif (m_x <= 48) or (m_x >= 547) or (m_y <= 25) or (m_y >= 585): 
      game_over = True 

     if game_over == True: 
      screen.fill(WHITE) 
      message(screen, "You Lost", RED, 300, 300) 

     num_top += randint(-3, 3) 
     num_bot += randint(-3, 3) 

     # proportion 

     dx = num_bot - num_top 
     dy = DISPLAY_HEIGHT 
     tanges_angle = dx/dy 

     dx_p1 = num_bot - (m_x-48) # or smaller ie. m_x-46 
     dy_p1 = DISPLAY_HEIGHT - m_y 
     tanges_angle_p1 = dx_p1/dy_p1 

     if -0.01 < tanges_angle - tanges_angle_p1 < 0.01: 
      print('Collide left') 

     dx_p2 = num_bot - (m_x+48) # or smaller ie. m_x+46 
     dy_p2 = DISPLAY_HEIGHT - m_y 
     tanges_angle_p2 = dx_p2/dy_p2 

     if -0.01 < tanges_angle - tanges_angle_p2 < 0.01: 
      print('Collide right') 

     # - draws - 

     screen.fill(WHITE) 

     pygame.draw.arc(screen, RED, (m_x-48, m_y-25, 100, 40), 0, pi, 3) 
     pygame.draw.line(screen, BLACK, (num_top, 0), (num_bot, 600), LINE_THICKNESS) 
     pygame.draw.arc(screen, RED, (m_x-48, m_y-25, 100, 40), PI_3, PI_2, 3) 

     message(screen, "Press q or the x button to quit", BLUE, 100, 40) 

     pygame.display.update() 

     # - FPS - 

     clock.tick(FPS) 

    # - end - 

    pygame.quit() 
    quit() 

# --- main --- 

pygame.init() 

screen = pygame.display.set_mode((DISPLAY_WIDTH, DISPLAY_HEIGHT)) 
pygame.display.set_caption("Wire") 

font = pygame.font.SysFont("aerial", 20) 
clock = pygame.time.Clock() 

gameloop() 

Es nutzt comparition dx/dy == dx_p1/dy_p1 die od Strahlensatz basiert, auch bekannt als Thales' theorem