碰撞检测/简单游戏物理

时间:2020-01-09 03:50:51

标签: python python-3.x pygame collision-detection game-physics

您好,我目前正在上课用小型游戏(第一次做这样的事情),我真的不知道如何从碰撞检测开始。好吧,我要创建的游戏是一个在冰冷的圆形竞技场上的自上而下的相扑格斗游戏,您在游戏中四处走动以获取动力和速度,并试图互相击败以获取积分。到目前为止,我已经大大降低了运动的加速/摩擦,并且我还拥有一个系统来检测何时发生碰撞,我只是不知道如何在角色碰撞时将它们推开。我认为我会根据攻击者的速度和我要添加的角色的 resistance 统计信息来确定击退数量/伤害。我还假设我将不得不对诸如切线和其他东西进行一些密集的数学运算,以使方向正确,但是我完全不确定该怎么做。我将不胜感激任何帮助,如果您以后想通过不和谐之类的方式在此项目上为我提供帮助,我也乐于接受将来的帮助。感谢一切

import pygame, sys, time
from pygame.locals import *
import random
import math


#Colors
colorRed=pygame.Color(241,59,62)
colorPurple=pygame.Color(200,254,249)
colorBlue=pygame.Color(52, 207, 235)
colorGreen=pygame.Color(100,182,100)
colorWhite=pygame.Color(255,250,250)
colorBlack=pygame.Color(0,0,0)
colorOrange=pygame.Color(242,164,0)
colorBrown=pygame.Color(148,103,58)

#Dimensions
w=800
h=600
pygame.init()
fpsClock=pygame.time.Clock()
screen=pygame.display.set_mode((w,h))
pygame.display.set_caption ('SUMO')
centerX=w//2
centerY=h//2

#Stage
stageR=250
def stage (centerX,centerY):
    """stage (centerX,centerY) - creates a stage with given centerpoint"""
    pygame.draw.circle(screen, colorBlue, (centerX,centerY),stageR)

#Character 1
xR=int((stageR//10))
x1=int(centerX-(stageR*0.8))
y1=centerY
x1_dir=0
y1_dir=0
def char1 (x1,y1):
    """char1 (x1,y1) - creates char1 at given coordinates"""
    pygame.draw.circle(screen, colorRed, (x1,y1),xR)
print (x1)
print (centerX)

#Character 2
x2=int(centerX+(stageR*0.8))
y2=centerY
x2_dir=0
y2_dir=0
def char2 (x2,y2):
    """char2 (x2,y2) - creates char1 at given coordinates"""
    pygame.draw.circle(screen, colorGreen, (x2,y2),xR)





while True:
    screen.fill(colorBlack)
    for event in pygame.event.get():
        #Game Exit
        if event.type== QUIT:
            pygame.quit()
            sys.exit()

    distance=math.hypot(x1-x2,y1-y2)
    if distance <= 2*xR:
        print ("HIT")

    keys = pygame.key.get_pressed()

    if keys[K_d] or keys[K_a]:
        x1_dir += 0.1 if keys[K_d] else -0.1
    else:
        x1_dir *= 0.98

    if keys[K_w] or keys[K_s]:
        y1_dir += 0.1 if keys[K_s] else -0.1
    else:
        y1_dir *= 0.98

# -------------------- CHAR2 MOVEMENT --------------------

    if keys[K_RIGHT] or keys[K_LEFT]:
        x2_dir += 0.1 if keys[K_RIGHT] else -0.1
    else:
        x2_dir *= 0.98

    if keys[K_UP] or keys[K_DOWN]:
        y2_dir += 0.1 if keys[K_DOWN] else -0.1
    else:
        y2_dir *= 0.98


    stage (centerX,centerY)
    char1 (round(x1),round(y1))
    char2 (round(x2),round(y2))
    x1+=x1_dir
    y1+=y1_dir
    x2+=x2_dir
    y2+=y2_dir
    pygame.display.update()
    fpsClock.tick(60)

1 个答案:

答案 0 :(得分:3)

当物体撞击时,您必须反映运动矢量(x1_diry1_dir)和(x2_diry2_dir)。 对于给定的入射矢量I和表面法线N,反射方向计算为I - 2.0 * dot(N, I) * N

法线向量是从一个中心点到另一个中心点的Unit vector,当物体撞击时, 检测击中并标准化中心点之间的向量(将向量除以distance):

nv = [x1-x2, y1-y2]
distance=math.hypot(nv[0], nv[1])
if distance <= 2*xR:
   nv = [nv[0]/distance, nv[1]/distance]

使用pygame.math.Vector2.reflect计算反射率。 使用pygame.math.Vector2.length计算反射向量的长度,并用pygame.math.Vector2.scale_to_length交换反射向量的长度:

nv = [x1-x2, y1-y2]
distance=math.hypot(nv[0], nv[1])
if distance <= 2*xR:
    nv = pygame.math.Vector2(nv[0], nv[1]) / distance

    rd1 = pygame.math.Vector2(x1_dir, y1_dir).reflect(nv)
    rd2 = pygame.math.Vector2(x2_dir, y2_dir).reflect(nv)

    len1, len2 = rd1.length(), rd2.length()
    if len1 > 0:
        rd1.scale_to_length(len2)
        x1_dir, y1_dir = rd1.x, rd1.y
    else:
        x1_dir, y1_dir = -x2_dir, -y2_dir
    if len2 > 0:
        rd2.scale_to_length(len1)
        x2_dir, y2_dir = rd2.x, rd2.y
    else:
        x2_dir, y2_dir = -x1_dir, -y1_dir


由于不可能精确地检测到“击中”,因此当玩家之间的距离为2*xR时,有必要校正玩家的位置并在距离恰好为{{ 1}}:

2*xR