Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/joomla/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 乒乓克隆碰撞检测_Python_Pygame_Collision Detection_Pong - Fatal编程技术网

Python 乒乓克隆碰撞检测

Python 乒乓克隆碰撞检测,python,pygame,collision-detection,pong,Python,Pygame,Collision Detection,Pong,这是我第一次真正尝试比赛。我知道代码可能会更好 使用类或函数,但我试图使代码更简单(更短) 我对球和杆/桨的碰撞检测有问题。球粘在杆上,然后向同一方向继续运动。 我尝试了一些pygame碰撞函数,但它们不起作用,因为我使用的是surface方法,而不是rect方法。我的问题是: 如何使球从杆/桨上反弹?和/或我应该使用哪种方法或功能 #!\user\bin\ env python import pygame, sys from pygame.locals import * from sys im

这是我第一次真正尝试比赛。我知道代码可能会更好 使用类或函数,但我试图使代码更简单(更短)

我对球和杆/桨的碰撞检测有问题。球粘在杆上,然后向同一方向继续运动。 我尝试了一些pygame碰撞函数,但它们不起作用,因为我使用的是surface方法,而不是rect方法。我的问题是:

如何使球从杆/桨上反弹?和/或我应该使用哪种方法或功能

#!\user\bin\ env python
import pygame, sys
from pygame.locals import *
from sys import exit
pygame.init()
#game constants
fps = 60
clock = pygame.time.Clock()
#Colors
BLACK = (  0,   0,   0)
WHITE =  (255, 255, 255)
BLUE =    (  0,   0, 255)
GREEN = (  0, 255,   0)
RED =      (255,   0,   0)

size = window_WIDTH, window_HEIGHT = 800,600
window = pygame.display.set_mode( size , pygame.RESIZABLE)
window.fill(BLACK)
ball = pygame.Surface((25, 25))
ball = ball.convert()
ball.fill(WHITE)
ball_x, ball_y = (window_WIDTH/2 -12), (window_HEIGHT/2 -12 )
ball_speed_x = 7  #ball speed = 20
ball_speed_y = 7

bar = pygame.Surface((15, 90))
bar.fill(WHITE)
bar1 = bar.convert()
bar2 = bar.convert()

bar_speed = 0
bar1_x,bar1_y = (50), (window_HEIGHT/2-60)

bar2_x,bar2_y = (window_WIDTH - 50), (window_HEIGHT/2-60)

middle_line = pygame.Surface((2,window_HEIGHT))
middle_line.fill(WHITE)
middle_line = middle_line.convert()

running = True
while running:
    for event in pygame.event.get():
        if ( event.type == pygame.QUIT ) or ( event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
            running = False
        if event.type == pygame.KEYDOWN:
            if event.key == K_UP:
                bar_speed -= 20
            if event.key == K_DOWN:
                bar_speed += 20
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_UP:
                bar_speed = 0
            if event.key == pygame.K_DOWN:
                bar_speed = 0

#since i don't know anything about collision, ball hitting bars goes like this.
    #colisions with the walls (veritical walls for bars)
    if bar1_y >= (window_HEIGHT - 90) or bar1_y <= 0:
        bar_speed = 0
    if bar2_y >= (window_HEIGHT - 90) or bar2_y <= 0:
        bar_speed = 0

    # collisions with bars (ball)
    if ball_x <= (bar1_x+15):
        if ball_y >= bar1_y:
            if ball_y <= (bar1_y + 45):  #checks if ball y cord is between bar y cord and bar length
                # To right direction up
                #ball_x += (bar1_x +15)
                #ball_x += ball_speed_x
                #ball_speed_y *= -1
                ball_y *= -1
                ball_x = (bar1_x +15)
                ball_speed_y = -ball_speed_y
                ball_speed_x = ball_speed_x

                # To right direction down
            if ball_y +45 <= (bar1_y + 90):#half down bar make y cord negative
                #ball_speed_y = ball_speed_y
                #ball_x += (bar1_x +15)
                #ball_x += ball_speed_x
                ball_y *= -1
                ball_x = (bar1_x +15)
                ball_speed_y = -ball_speed_y
                ball_speed_x = ball_speed_x

    if (ball_x+25) >= bar2_x:
        if ball_y >= bar2_y:
            if ball_y <= (bar2_y + 44):  #checks if ball y cord is between bar y cord and bar length
                # To right direction up
                #ball_x = (bar1_x )#+15)
                #ball_x -= ball_speed_x
                ball_y *= -1
                ball_x = (bar1_x +15)
                ball_speed_y = -ball_speed_y
                ball_speed_x = -ball_speed_x

            if ball_y +45 <= (bar2_y + 90):#half down bar make y cord negative
                #ball_speed_y = ball_speed_y
                #ball_x = (bar2_x )#+15)
                #ball_x = ball_speed_x
                ball_y *= -1
                ball_x = (bar1_x +15)
                ball_speed_y = -ball_speed_y
                ball_speed_x = -ball_speed_x

    #collisions of ball with up down walls
    if ball_y == 0:
        if ball_x > window_WIDTH/2:
            ball_speed_y = ball_speed_y
            ball_speed_x = ball_speed_x
        if ball_x < window_WIDTH/2:
            ball_speed_y = ball_speed_y
            ball_speed_x *= -1

    if ball_y == window_HEIGHT:
        if ball_x > window_WIDTH/2:
            ball_speed_y *= -1
            ball_speed_x = ball_speed_x
        if ball_x < window_WIDTH/2:
            ball_speed_y *= -1
            ball_speed_x *= -1
    #AI player
    if ball_x >= window_WIDTH/2:
        if not bar2_y == ball_y + 7.5:
            if bar2_y < ball_y + 7.5:
                bar2_y += bar_speed
            if  bar2_y > ball_y - 42.5:
                bar2_y -= bar_speed
        else:
            bar2_y == ball_y + 7.5
    if bar1_y >= 420.: bar1_y = 420.
    elif bar1_y <= 10. : bar1_y = 10.
    if bar2_y >= 420.: bar2_y = 420.
    elif bar2_y <= 10.: bar2_y = 10.

    bar1_y+= bar_speed
    ball_x += ball_speed_x
    ball_y += 1


    window.fill(BLACK)
    window.blit(middle_line,(window_WIDTH/2,0))
    window.blit(bar1,(bar1_x, bar1_y))
    window.blit(bar2,(bar2_x,bar2_y))
    window.blit(ball, (ball_x, ball_y))

    clock.tick(fps)
    pygame.display.update()
pygame.quit()
#\user\bin\env python
导入pygame,sys
从pygame.locals导入*
从系统导入退出
pygame.init()
#博弈常数
fps=60
clock=pygame.time.clock()
#颜色
黑色=(0,0,0)
白色=(255,255,255)
蓝色=(0,0255)
绿色=(0,255,0)
红色=(255,0,0)
尺寸=窗宽,窗高=800600
window=pygame.display.set_模式(大小,pygame.resizeable)
窗口填充(黑色)
球=pygame.表面((25,25))
ball=ball.convert()
填充球(白色)
球x,球y=(窗宽/2-12),(窗高/2-12)
球速x=7#球速=20
球速y=7
bar=pygame.Surface((15,90))
条形填充(白色)
bar1=bar.convert()
bar2=bar.convert()
巴_速度=0
栏杆1_x,栏杆1_y=(50),(窗户高度/2-60)
bar2_x,bar2_y=(窗宽-50),(窗高/2-60)
中间线=pygame.Surface((2,窗高))
中间线填充(白色)
中间线=中间线。转换()
运行=真
运行时:
对于pygame.event.get()中的事件:
如果(event.type==pygame.QUIT)或(event.type==pygame.KEYDOWN和event.key==pygame.K_ESCAPE):
运行=错误
如果event.type==pygame.KEYDOWN:
如果event.key==K_UP:
巴速-=20
如果event.key==K_DOWN:
巴_速度+=20
如果event.type==pygame.KEYUP:
如果event.key==pygame.K_UP:
巴_速度=0
如果event.key==pygame.K_向下:
巴_速度=0
#因为我对碰撞一无所知,所以击球杆是这样的。
#与墙的共线(钢筋的真实墙)
如果bar1_y>=(窗口高度-90)或bar1_y=(窗口高度-90)或bar2_y=窗口宽度/2:
如果不是bar2_y==ball_y+7.5:
如果bar2_yball_y-42.5:
巴2_y-=巴速度
其他:
bar2_y==球y+7.5
如果bar1_y>=420:bar1_y=420。
elif bar1_y=420.:bar2_y=420。

elif bar2_y我认为你的碰撞过程是正确的。 虽然有一些部分很难理解,但我认为球在上下墙的碰撞效果很好

现在你应该去掉桨叶/杆的X、Y坐标,现在考虑球和桨的碰撞。实际上,你可能想让桨叶“可移动”,所以桨叶的x,y坐标应该保存在某个地方,通过你所做的桨叶的移动来转换


就像你在《碰撞》中所做的那样,你应该将方向(y或x)变换为-1

我建议你使用pygame,如果有以下原因,可以使用类:

  • 这样可以很容易地检查与车辆的碰撞
  • 使用像素完美碰撞也很容易
  • 使用
    Rect.top
    Rect.bottom
    检查球是否在屏幕顶部或底部反弹也变得非常容易
  • 防止挡板从屏幕上消失只需呼叫即可
这是一个基本的双人乒乓球,应该是一个很好的起点。请注意,代码是多么简单:

import pygame
import math
pygame.init()
screen = pygame.display.set_mode((640, 480))
clock = pygame.time.Clock()

# some helpful vector math functions
def normalize(v):
    vmag = magnitude(v)
    return [v[i]/vmag  for i in range(len(v))]
def magnitude(v):
    return math.sqrt(sum(v[i]*v[i] for i in range(len(v))))
def add(u, v):
    return [ u[i]+v[i] for i in range(len(u)) ]

class Paddle(pygame.sprite.Sprite):
    def __init__(self, start_pos, up_key, down_key):
        pygame.sprite.Sprite.__init__(self)
        # the image is just a white rect
        self.image = pygame.surface.Surface((20, 100))
        self.image.fill(pygame.color.Color('White'))
        self.image.set_colorkey(pygame.color.Color('Black'))
        self.rect = self.image.get_rect(topleft=start_pos)
        # using a mask so we can use pixel perfect collision
        self.mask = pygame.mask.from_surface(self.image)
        self.up_key, self.down_key = up_key, down_key
    def update(self, pressed):
        if pressed[self.up_key]:   self.rect.move_ip(0, -3)
        if pressed[self.down_key]: self.rect.move_ip(0,  3)
        # keep the paddle inside the screen
        self.rect.clamp_ip(pygame.display.get_surface().get_rect())

class Ball(pygame.sprite.Sprite):
    def __init__(self, start_pos):
        pygame.sprite.Sprite.__init__(self)
        # the image is just a white ball
        self.image = pygame.surface.Surface((20, 20))
        self.rect = self.image.get_rect(center=start_pos)
        pygame.draw.circle(self.image, pygame.color.Color('White'), self.image.get_rect().center, 10)
        self.image.set_colorkey(pygame.color.Color('Black'))
        # using a mask so we can use pixel perfect collision
        self.mask = pygame.mask.from_surface(self.image)
        # the vector we use to move the ball
        self.move_v = (1, 0.7)
        # store the absolute position in self.pos
        # because a rect can only use integers
        self.pos = self.rect.center
    def update(self, pressed):
        # check if the ball collides with any other sprite
        collide = [s for s in pygame.sprite.spritecollide(self, self.groups()[0], False, pygame.sprite.collide_mask) if s != self]
        if collide:
            # warning: this does not handle the case of the ball hits 
            # the top or bottom of the paddle, only the sides.
            self.move_v = [-self.move_v[0], self.move_v[1]]

        # check if the ball would go out of screen
        display = pygame.display.get_surface().get_rect()
        if self.rect.top < display.top and self.move_v[1] < 0 or \
           self.rect.bottom > display.bottom and self.move_v[1] > 0:
            self.move_v = [self.move_v[0], -self.move_v[1]]

        # apply a constant speed and update the position
        move_vector = [c * 4 for c in normalize(self.move_v)]
        self.pos = add(self.rect.center, move_vector)
        self.rect.center = map(int, self.pos)

player1 = Paddle((30,  190), pygame.K_w , pygame.K_s)
player2 = Paddle((590, 190), pygame.K_UP, pygame.K_DOWN)
ball = Ball(screen.get_rect().center)
sprites = pygame.sprite.Group(player1, player2, ball)

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT: break
    else:
        pressed = pygame.key.get_pressed()
        sprites.update(pressed)
        screen.fill(pygame.color.Color('black'))
        sprites.draw(screen)
        pygame.display.flip()
        clock.tick(60)
        continue
    break
pygame.quit()
导入pygame
输入数学
pygame.init()
screen=pygame.display.set_模式((640480))
clock=pygame.time.clock()
#一些有用的向量数学函数
def正常化(v):
vmag=震级(v)
返回[v[i]/vmag(len(v))]
def量级(v):
返回math.sqrt(范围(len(v))中i的和(v[i]*v[i]))
def添加(u,v):
返回[u[i]+v[i]表示范围内的i(len(u))]
班级桨(pygame.sprite.sprite):
定义初始(自我、启动位置、向上键、向下键):
pygame.sprite.sprite.\uuuuu init\uuuuuuu(自我)
#图像只是一个白色矩形
self.image=pygame.surface.surface((20100))
self.image.fill(pygame.color.color('White'))
self.image.set_colorkey(pygame.color.color('Black'))
self.rect=self.image.get\u rect(左上角=开始位置)
#使用遮罩以便使用像素完美碰撞
self.mask=pygame.mask.from_surface(self.image)
self.up\u键,self.down\u键=up\u键,down\u键
def更新(自我,按下):
如果按下[self.up\u键]:self.rect.move\u ip(0,-3)
如果按[self.down\u键]:self.rect.move\u ip(0,3)
#将挡板保持在屏幕内
self.rect.clamp_ip(pygame.display.get_surface().get_rect())
班级舞会(pygame.sprite.sprite):
定义初始化(自启动位置):
pygame.sprite.sprite.\uuuuu init\uuuuuuu(自我)
#图像只是一个白色的球
self.image=pygame.surface.surface((20,20))
self.rect=self.image.get_rect(中心=开始位置)
pygame.draw.circle(self.image,pygame.color.color('White'),self.image.get_rect().center,10)
self.image.set_colorkey(pygame.color.color('Black'))
#使用遮罩以便使用像素完美碰撞
self.mask=pygame.mask.from_surface(self.image)
#我们用来移动球的向量
self.move_v=(1,0.7)
#将绝对位置存储在self.pos中
#因为rect只能使用整数
self.pos=self.rect.center
def更新(自我,按下):
#检查球是否与任何其他精灵碰撞
collide=[s代表pygame.sprite.spritecollide(self,self.groups()[0],False,pygame.sprite.collide_mask)中的s,如果s!=self]
如果发生碰撞: