0
\$\begingroup\$

I am currently working on a mini game for class (first time doing something like this) and I don't really know how to start with collision detection at all. 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 you want to assist me on this project later via 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)
    ```
\$\endgroup\$
  • \$\begingroup\$ Presumably you started by searching for tutorials about how to create a 2D physics engine, and working through the material you found there? Where specifically did you get stuck? \$\endgroup\$ – DMGregory Jan 9 at 17:30
  • \$\begingroup\$ uhm i didnt actually look for a tutorial about how to create a physics engine yet \$\endgroup\$ – Chynx Jan 13 at 13:53
  • \$\begingroup\$ Start there — they'll explain this stuff. \$\endgroup\$ – DMGregory Jan 13 at 14:02
0
\$\begingroup\$

Your goal is to prevent them from going into each other, which means once you detect a collision they shouldn't go toward each other. I assume the sumos are circles.

I wrote some pseudo code to show how to do it:

# We compute how much one moves relative to the other.
velocity = velocity_B - velocity_A; 

# If the sumos are circles the normal is the direction from one center to the other.
normal = Normalize(position_B - position_A);

# We find the proportion of the relative velocity that is in the direction of the normal. 
# Basically we want to find out how fast they are moving toward each other.
vel_normal = Dot(velocity, normal);

if vel_normal < 0:
    # if vel_normal is positive that means they are already moving away from each other
    # now we modify their velocity so that vel_normal becomes 0
    impulse = normal * vel_normal

    # we modify their velocity depending on their mass. The bigger one is the less it will move.
    sum_inv_mass = 1/mass_A + 1/mass_B
    velocity_A += impulse  * (1/mass_A) / sum_inv_mass
    velocity_B -= impulse  * (1/mass_B) / sum_inv_mass

This is the basics, if you want them to bounce you can multiply vel_normal by something bigger than one.

Because of small errors in the calculations it's possible they will be able to go into each other very slowly. There are ways to fix that but it's probably better as its own question.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.