碰撞检测/简单游戏的物理 [英] Collision detection / physics for simple game

查看:41
本文介绍了碰撞检测/简单游戏的物理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

 导入pygame,sys,时间从pygame.locals导入*随机导入导入数学#颜色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)#方面w = 800h = 600pygame.init()fpsClock = pygame.time.Clock()屏幕= pygame.display.set_mode((w,h))pygame.display.set_caption('SUMO')centerX = w//2centerY = h//2#阶段阶段R = 250def阶段(centerX,centerY):"舞台(centerX,centerY)-创建具有给定中心点的舞台""pygame.draw.circle(screen,colorBlue,(centerX,centerY),stageR)#字符1xR = int((stageR//10))x1 = int(centerX-(stageR * 0.8))y1 =中心Yx1_dir = 0y1_dir = 0def char1(x1,y1):""char1(x1,y1)-在给定坐标处创建char1""pygame.draw.circle(screen,colorRed,(x1,y1),xR)列印(x1)列印(centerX)#角色2x2 = int(centerX +(stageR * 0.8))y2 =中心Yx2_dir = 0y2_dir = 0def char2(x2,y2):""char2(x2,y2)-在给定坐标处创建char1""pygame.draw.circle(screen,colorGreen,(x2,y2),xR)而True:screen.fill(colorBlack)对于pygame.event.get()中的事件:#游戏出口如果event.type == QUIT:pygame.quit()sys.exit()距离= math.hypot(x1-x2,y1-y2)如果距离< = 2 * xR:打印(命中")键= pygame.key.get_pressed()如果是键[K_d]或键[K_a]:x1_dir + = 0.1如果keys [K_d]否则-0.1别的:x1_dir * = 0.98如果键[K_w]或键[K_s]:y1_dir + = 0.1如果key [K_s]否则-0.1别的:y1_dir * = 0.98#-------------------- CHAR2运动--------------------如果按键[K_RIGHT]或按键[K_LEFT]:x2_dir + = 0.1如果键[K_RIGHT]否则-0.1别的:x2_dir * = 0.98如果按键[K_UP]或按键[K_DOWN]:y2_dir + = 0.1,如果键[K_DOWN]则其他-0.1别的:y2_dir * = 0.98阶段(centerX,centerY)char1(舍入(x1),舍入(y1))char2(舍入(x2),舍入(y2))x1 + = x1_diry1 + = y1_dirx2 + = x2_diry2 + = y2_dirpygame.display.update()fpsClock.tick(60) 

解决方案

您必须反映运动矢量( x1_dir y1_dir )和( x2_dir y2_dir ).对于给定的入射矢量 I 和表面法线 N ,反射方向的计算公式为 I-2.0 * dot(N,I)* N .

法向矢量是从一个中心点到另一个中心点的


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

  v12 = pygame.math.Vector2(x1-x2,y1-y2)距离= v12.length()hit_dist = 2 * xR如果距离< = hit_dist:#中心点之间的矢量nv = v12.normalize()#运动方向和组合的相对运动d1 = pygame.math.Vector2(x1_dir,y1_dir)d2 = pygame.math.Vector2(x2_dir,y2_dir)dd = d1-d2如果dd.length()== 0:#归一化的运动和正常距离ddn = dd.normalize()dir_dist = ddn.dot(v12)norm_dist = pygame.math.Vector2(-ddn [0],ddn [1]).dot(v12)#沿相对运动线的最小距离min_dist = math.sqrt(hit_dist * hit_dist-norm_dist * norm_dist)如果dir_dist<min_dist:#更新玩家的位置,使距离为2 * xRd1l,d2l = d1.length(),d2.length()如果d1> 1,则d1n = d1/d1l.0其他d1如果d2l> d2n,则d2n = d2/d2l.0其他d2x1-= d1n.x * d1l/(d1l + d2l)y1-= d1n.y * d1l/(d1l + d2l)x2-= d2n.x * d2l/(d1l + d2l)y2-= d2n.y * d2l/(d1l + d2l)#重新计算中心点之间的向量v12 = pygame.math.Vector2(x1-x2,y1-y2)nv = v12.normalize()#反映运动矢量rd1 = d1.reflect(nv)rd2 = d2.reflect(nv)len1,len2 = rd1.length(),rd2.length()如果len1>0:rd1 = rd1 * len2/len1x1_dir,y1_dir = rd1.x,rd1.y别的:x1_dir,y1_dir = -x2_dir,-y2_dir如果len2>0:rd2 = rd2 * len1/len2x2_dir,y2_dir = rd2.x,rd2.y别的:x2_dir,y2_dir = -x1_dir,-y1_dir 

Hi i am currently working on a mini game for class (first time doing something like this) and i dont really know how to start with collision detection at all. Okay the game i'm creating is a top down sumo fighting game on a icy circular arena where you move around gaining momentum and velocity and try to knock each other off to gain points. So far i have the movement acceleration/friction pretty much down and I also have a system to detect when a collision occurs, i just don't know how to actually push the characters away when they collide. I think i will base the knock back amount/ damage on the velocity the attacker has against their velocity alongside the character's resistance stat that i will be adding. I also assume that I will have to do some intense math with like tangents and stuff to get the direction correct but i'm not sure how to do that at all. I would greatly appreciate any help and i am open to future help if u want to assist me on this project later via through like discord or something. Thanks for everything

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)

解决方案

You have to reflect the movement vectors (x1_dir, y1_dir) and (x2_dir, y2_dir) when the objects hit. For a given incident vector I and surface normal N, the reflection direction calculated as I - 2.0 * dot(N, I) * N.

The normal vector is the Unit vector from one center point to the other, when the objects hit, Detect the hit and normalize the vector between the center points (divide the vector by distance):

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

Use pygame.math.Vector2.reflect to calculate the reflection. Use pygame.math.Vector2.length to compute the length of the reflected vectors and exchange there length by 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


Since it is not possible to detect the "hit" exactly, when the distance between the players is 2*xR it is necessary to correct the position of the players and to find the point when the distance is exactly 2*xR:

v12 = pygame.math.Vector2(x1-x2, y1-y2)
distance = v12.length()
hit_dist = 2*xR
if distance <= hit_dist:
    # vector beteween center points
    nv = v12.normalize()
    # movement direction and combined relative movement
    d1 = pygame.math.Vector2(x1_dir, y1_dir)
    d2 = pygame.math.Vector2(x2_dir, y2_dir)
    dd = d1 - d2
    if dd.length() == 0:
        # normalized movement and normal distances
        ddn = dd.normalize()
        dir_dist  = ddn.dot(v12)
        norm_dist = pygame.math.Vector2(-ddn[0], ddn[1]).dot(v12)
        # minimum distance along the line of relative movement
        min_dist = math.sqrt(hit_dist*hit_dist - norm_dist*norm_dist)
        if dir_dist < min_dist:
            # update postions of the players so that the distance is 2*xR
            d1l, d2l = d1.length(), d2.length()
            d1n = d1/d1l if d1l > 0 else d1
            d2n = d2/d2l if d2l > 0 else d2
            x1 -= d1n.x * d1l / (d1l+d2l)
            y1 -= d1n.y * d1l / (d1l+d2l)
            x2 -= d2n.x * d2l / (d1l+d2l)
            y2 -= d2n.y * d2l / (d1l+d2l)
            # recalculate vector beteween center points
            v12 = pygame.math.Vector2(x1-x2, y1-y2)
            nv = v12.normalize()

        # reflect movement vectors
        rd1 = d1.reflect(nv)
        rd2 = d2.reflect(nv)
        len1, len2 = rd1.length(), rd2.length()
        if len1 > 0:
            rd1 = rd1 * len2 / len1
            x1_dir, y1_dir = rd1.x, rd1.y
        else:
            x1_dir, y1_dir = -x2_dir, -y2_dir
        if len2 > 0:
            rd2 = rd2 * len1 / len2
            x2_dir, y2_dir = rd2.x, rd2.y
        else:
            x2_dir, y2_dir = -x1_dir, -y1_dir

这篇关于碰撞检测/简单游戏的物理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆