#StackBounty: #collision-detection #physics #collision-resolution Issue with 2d Angular Car Collision Response

Bounty: 50

I am having trouble getting the angular collision response to work properly in my 2d car simulation. I have gotten the linear collision response to work between the vehicles, however, the angular collision response does not seem to be working. The problem seems to arise from my slip angle calculation for the car, and it seems to override the angular impulse. The slip angle is necessary to make the vehicle move realistically.

Here’s the code to calculate the slip angle:

// Calculate slip angle for front/back wheel
this.wheels.front.slipAngle = -Math.atan2(this.localVelocity.y + yawSpeedFront, Math.abs(this.localVelocity.x));
this.wheels.back.slipAngle = -Math.atan2(this.localVelocity.y + yawSpeedRear,  Math.abs(this.localVelocity.x));

As can be seen in the following pictures, the car rotation response is correctly simulated when it hits the top of the car and rotates clockwise. On the other hand, when the car hits the bottom of the other car, the rotation should be clockwise, but actually still goes clockwise. It seems to me that the problem arises because the slipAngle overrides the angular rotation of the collision.

enter image description here

enter image description here

My project can be seen here: https://victorwei.com/projects/car-sim/ Feel free to take play around with the simulation and view the code to figure out the issue. If there are any suggestions on how to mitigate this problem, that would be greatly appreciated.


Get this bounty!!!

#StackBounty: #unity #physics #movement #projectile-physics Interpolation on Rigidbody2D not working

Bounty: 50

I’m trying to achieve smooth movement for a ball. I seem to be failing to achieve this and now I’ve created a sample scene, which shows my setup from the game and the problem exists in that sample scene, as well.

I’ve uploaded the sample project to github: https://github.com/iQew/PhysicsTesting (open Assets/Scenes/SampleScene)

Here’s a recording of the problem. It’s a bit more extreme here than it is in the editor, but it shows the problem even better because of it: https://imgur.com/a/ByzwKlg

Scenario:
I have a 2D mobile game (android) using Unity 2019.4.14f1 with URP. The camera does not move and will always have the same settings. The playfield consists of a certain area, which is blocked in by walls, which have a BoxCollider2D on them. The ball is a simple sprite with a CircleCollider2D, RigidBody2D and a Trail Renderer.

I have deleted all quality settings except the "Low" one, which has VSync Count set to "Don’t Sync". In the Awake block of a controller script I set the Application.targetFrameRate to 60. In the Start block I use BallRigidBody2D.AddForce(new Vector2(1f, 10f), ForceMode2D.Impulse) to make the ball move.

The RigidBody2D of the Ball has the following settings:

  • Body Type: Dynamic
  • Material: DefaultBall (a Physics2D material with friction: 0 | bounciness: 1)
  • Simulated: true
  • Use Auto Mass: false
  • Mass: 0.025f
  • Linear Drag: 0
  • Angular Drag: 0
  • Gravity Scale: 0
  • Collision Detection: Continous
  • Sleeping Mode: Start Awake
  • Interpolate: Interpolate

All other project settings are at default.

When I launch the game, the ball starts moving as expected. Most of the time the movement is smooth, but there is stuttering every now and then. I am wondering, if there is a way to make this stuttering go away. The tutorials I found on the internet, which solve this exact problem set the Interpolation mode of the RigidBody2D to "Interpolate", but I did that and there’s no change.

There are no other scripts interfering with the physics calculation at all. So, I assume this has to do with some kind of project settings? Using a smaller Fixed Timestep does not help, in fact it gets a lot worse, if I use 1/120 for example.

Any help would be greatly appreciated!

enter image description here

enter image description here

enter image description here


Get this bounty!!!

#StackBounty: #unity #physics #vehicle Custom steering system in Unity for braking and sliding

Bounty: 50

I am developing a game where the player controls a vehicle. But instead of using a first person view, the camera is top-down and orthographic.

I tried using Unity’s wheel collider system. While that would work just fine for a first-person view (e.g. a traditional racing game), the controls don’t work well with a top-down view (e.g. think Micromachines on the NES). The reason, I think, is that turning and acceleration need to be much more responsive with a top-down view than with a real vehicle steering simulation. You’re not racing on a track. When viewing from top-down, the vehicle needs to accelerate and turn much more quickly than a “real” vehicle ever could.

I have implemented my own steering system based on Ackermann steering, which works fine. What I am missing is a good simulation of friction and skidding. For instance, I would like my vehicle to skid and slide if the user brakes while turning.

I don’t have a background in physics or mechanics so I am not sure where to start. Can someone give me some pointers?

Here is the code I have so far for simple steering:

void Move() {
    bool isLeft = Input.GetKey (KeyCode.A);
    bool isRight = Input.GetKey (KeyCode.D);
    bool isUp = Input.GetKey (KeyCode.W);
    bool isDown = Input.GetKey (KeyCode.S);

    turn = 0;

    acceleration = 0;
    speed *= friction;

    if (isReverse != isDown && (isUp || isDown)) {
        speed *= reverseDamping;
    }

    turn += isLeft ? (int) (-angleVel * speed) : 0;
    turn += isRight ? (int) (angleVel * speed) : 0;

    acceleration += isUp ? Time.deltaTime : 0;
    acceleration += isDown ? -Time.deltaTime : 0;
    speed += acceleration;

    transform.Rotate (0, turn, 0);
    transform.Translate (Vector3.forward * speed, Space.Self);

    isReverse = isDown;
}


Get this bounty!!!

#StackBounty: #physics #physics-engine Time complexity of solving constraints in physics engine

Bounty: 100

Erin Catto mentioned in a talk that solving constraints precisely requires cubic time and quadratic space. What algorithm is he talking about when he mentions cubic time?

pdf of slides with following quote:

We can model and program our constraints perfectly. Good enough to drive a robot arm on an assembly line or
launch a satellite into space. Unfortunately for games, we do not have enough cycles to solve constraints accurately.
Solving constraints precisely requires cubic time and quadratic space. For games we make due with linear time and
space, so we are constantly wrestling with our solvers. The better you understand constraint solvers, the better
chance you’ll have of creating robust simulations in your game.


Get this bounty!!!

#StackBounty: #python #numpy #matplotlib #simulation #physics Why are the arrows of the 3d quiver plot pointing the wrong way?

Bounty: 50

I have been working on modeling magnetic fields for research. The code below allows me to calculate correct values of the field for any given point (x,y,z); however, when I pass a np.meshgrid object through the code, the results start to get wonky.

This is my code:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d


def normal_vector(u):
    return u/np.linalg.norm(u)
class Path:
    """
    This defines the Path class which allows for the calculations of the magnetic field.
    """

    def __init__(self, xs, ys, zs):
        self.points = zip(*[xs, ys, zs])  # defines the points
        self.x = xs
        self.y = ys
        self.z = zs
        self.path_vectors = [(self.points[i + 1][0] - self.points[i][0],
                              self.points[i + 1][1] - self.points[i][1],
                              self.points[i + 1][2] - self.points[i][2]) for i in range(len(self.x) - 1)]
    def get_length(self):
        """
        Calculates the path length
        :return: returns float length
        """
        return sum([np.sqrt(((self.x[i + 1] - self.x[i]) ** 2) + ((self.y[i + 1] - self.y[i]) ** 2) + (
                (self.z[i + 1] - self.z[i]) ** 2)) for i in
                    range(len(self.x) - 1)])

    def get_magnetlic_function(self,axes,current=1.0,magnetic_constant = 1.25663706212e-6):
        magnetic_parameter = (current*magnetic_constant)/(4*np.pi)
        field_function = lambda x,y,z: sum([magnetic_parameter*np.cross(self.path_vectors[j],normal_vector(np.stack([x-self.x[j],y-self.y[j],z-self.z[j]],axis=-1)))/(np.linalg.norm(np.stack([x-self.x[j],y-self.y[j],z-self.z[j]],axis=-1))**2) for j in range(len(self.x)-1)]).swapaxes(0,-1)
        return field_function

n = 200
r = 1
h = 5
grid_x,grid_y,grid_z = np.meshgrid(np.linspace(-10,10,5),
                    np.linspace(-10,10,5),
                    np.linspace(-10,10,5))
c = h / (2 * n * np.pi)
t = np.linspace(0,2*np.pi, 5000)
xp = 3*np.cos(t)
yp = 3*np.sin(t)
zp = 0*t
p = Path(list(xp), list(yp), list(zp))
func = p.get_magnetlic_function([grid_x,grid_y,grid_z])
u,v,w = func(grid_x,grid_y,grid_z)
r = np.sqrt(u**2+v**2+w**2)
print func(-10.0,00.0,0.0)
ax1 = plt.subplot(111,projection='3d')
ax1.plot(xp,yp,zp,'r-')
ax1.plot([-10],[0],[0],'ro')
ax1.quiver(grid_x,grid_y,grid_z,u/r,v/r,w/r,length=1)
plt.show()

As is clear near the bottom, if the code is run, the direction of the vector at -10.0,00.0,0.0 is not the same as the value that gets printed. Why?
From the code, I recieve the quiver plot here:
My code.

It should look like:
enter image description here


Get this bounty!!!

#StackBounty: #physics #collision-resolution How do I apply angular velocity vector after a collision?

Bounty: 50

I’m writing a small 3D physics engine, And i am trying to get the use of Angular Velocity Vector of two shapes specially two cubes

For deep understanding i have divide the motion to Linear and Angular motion

For Angular motion i have done few steps

I calculated the inertia tensor matrix which 3×3 so i could get the torque as following:

Torque Formula

And for calculating the matrix i have used

Inertia Tensor

By all of that i could get the Impulse and the final angular velocities for all shapes as following:

Impulse And Final Angular Velocities

So my question how could i calculate the rotational angular which each object should rotate and for how long it should last ?


Get this bounty!!!

#StackBounty: #python #animation #pygame #physics Golf Physics "Game"

Bounty: 50

Continuation of this post

I wrote a program in pygame that basically acts as a physics engine for a ball. You can hit the ball around and your strokes are counted, as well as an extra stroke for going out of bounds. Recently, I added a few things like air resistance, and rewrote my movement physics to make it easier to bounce. I’m wondering if the physics approach is good. Also, is there any way to convert everything into SI units? Right now, my air drag is an arbitrary value.

import math
import pygame as pg


class Colors:

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

    YELLOW = (255, 255, 0)
    GOLD = (255, 215, 0)
    GRAY = (100, 100, 100)

    NIGHT =  (20, 24, 82)
    DAY = (135, 206, 235)
    MOON = (245, 243, 206)
    SMOKE = (96, 96, 96)



class Constants:

    SCREEN_WIDTH = 1500
    SCREEN_HEIGHT = 800
    WINDOW_COLOR = Colors.NIGHT

    TICKRATE = 60
    GAME_SPEED = .35

    LINE_COLOR = Colors.GOLD
    ALINE_COLOR = Colors.GOLD

    X_BOUNDS_BARRIER = 1
    Y_BOUNDS_BARRIER = 1
    BOUNCE_FUZZ = 0

    START_X = int(.5 * SCREEN_WIDTH)
    START_Y = int(.99 * SCREEN_HEIGHT)

    AIR_DRAG = .3
    GRAVITY = 9.80665


class Fonts:

    pg.font.init()
    strokeFont = pg.font.SysFont("monospace", 50)
    STROKECOLOR = Colors.YELLOW

    powerFont = pg.font.SysFont("arial", 15, bold=True)
    POWERCOLOR = Colors.GREEN

    angleFont = pg.font.SysFont("arial", 15, bold=True)
    ANGLECOLOR = Colors.GREEN

    penaltyFont = pg.font.SysFont("georgia", 40, bold=True)
    PENALTYCOLOR = Colors.RED

    toggleBoundsFont = pg.font.SysFont("geneva", 20)
    TOGGLEBOUNDSCOLOR = Colors.RED

    resistMultiplierFont = pg.font.SysFont("courier new", 13)
    RESISTMULTIPLIERCOLOR = Colors.RED

    powerMultiplierFont = pg.font.SysFont("courier new", 13)
    POWERMULTIPLIERCOLOR = Colors.RED


class Ball(object):
    def __init__(self, x, y, dx = 0, dy = 0, bounce = .8, radius = 10, color=Colors.SMOKE, outlinecolor=Colors.RED, density=1):
        self.color = color
        self.outlinecolor = outlinecolor
        self.x = x
        self.y = y
        self.dx = dx
        self.dy = dy
        self.ax = 0
        self.ay = Constants.GRAVITY
        self.dt = Constants.GAME_SPEED
        self.bounce = bounce
        self.radius = radius
        self.mass = 4/3 * math.pi * self.radius**3 * density

    def show(self, window):
        pg.draw.circle(window, self.outlinecolor, (int(self.x), int(self.y)), self.radius)
        pg.draw.circle(window, self.color, (int(self.x), int(self.y)), self.radius - int(.4 * self.radius))

    def update(self, update_frame):
        update_frame += 1

        self.vx += self.ax * self.dt
        self.vy += self.ay * self.dt

        if resist_multiplier:
            drag = 6*math.pi * self.radius * resist_multiplier * Constants.AIR_DRAG
            air_resist_x = -drag * self.vx / self.mass
            air_resist_y = -drag * self.vy / self.mass

            self.vx += air_resist_x/self.dt
            self.vy += air_resist_y/self.dt

        self.x += self.vx * self.dt
        self.y += self.vy * self.dt

        bounced, stop, shoot = False, False, True

        # Top & Bottom
        if self.y + self.radius > Constants.SCREEN_HEIGHT:
            self.y = Constants.SCREEN_HEIGHT - self.radius
            self.vy = -self.vy
            bounced = True
            print('    Bounce!')

        if self.y - self.radius < Constants.Y_BOUNDS_BARRIER:
            self.y = Constants.Y_BOUNDS_BARRIER + self.radius
            self.vy = -self.vy
            bounced = True
            print('    Bounce!')

        # Speed/Resistance Rectangles
        if (self.x >= .875*Constants.SCREEN_WIDTH + self.radius) and (self.y + self.radius >= .98*Constants.SCREEN_HEIGHT):
            self.x = .88*Constants.SCREEN_WIDTH + self.radius
            self.y = .98*Constants.SCREEN_HEIGHT - self.radius
            self.x = .87*Constants.SCREEN_WIDTH + self.radius
            self.vy, self.vx = -self.vy, -2 * abs(self.vx)
            bounced = True

        if (self.x <= .1175*Constants.SCREEN_WIDTH + self.radius) and (self.y + self.radius >= .98*Constants.SCREEN_HEIGHT):
            self.x = .118*Constants.SCREEN_WIDTH + self.radius
            self.y = .98*Constants.SCREEN_HEIGHT - self.radius
            self.x = .119*Constants.SCREEN_WIDTH + self.radius
            self.vy, self.vx = -self.vy, 2 * abs(self.vx)
            bounced = True

        if x_bounded:
            if (self.x - self.radius < Constants.X_BOUNDS_BARRIER):
                self.x = Constants.X_BOUNDS_BARRIER + self.radius
                self.vx = -self.vx
                bounced = True

            if (self.x + self.radius > Constants.SCREEN_WIDTH - Constants.X_BOUNDS_BARRIER):
                self.x = Constants.SCREEN_WIDTH - Constants.X_BOUNDS_BARRIER - self.radius
                self.vx = -self.vx
                bounced = True

        if self.vx > 1000:
            self.vx = 1000
            self.y = Constants.SCREEN_HEIGHT/4

        if bounced:
            self.vx *= self.bounce
            self.vy *= self.bounce

        print(f'n    Update Frame: {update_frame}',
               '        x-pos: %spx' % round(self.x),
               '        y-pos: %spx' % round(self.y),
               '        x-vel: %spx/u' % round(self.vx),
               '        y-vel: %spx/u' % round(self.vy),
               sep='n', end='nn')

        return update_frame, shoot, stop

    @staticmethod
    def quadrant(x, y, xm, ym):
        if ym < y and xm > x:
            return 1
        elif ym < y and xm < x:
            return 2
        elif ym > y and xm < x:
            return 3
        elif ym > y and xm > x:
            return 4
        else:
            return False


def draw_window():
    clock.tick(Constants.TICKRATE)

    window.fill(Constants.WINDOW_COLOR)

    resist_multiplier_text = 'Air Resistance: {:2.2f} m/s'.format(resist_multiplier)
    resist_multiplier_label = Fonts.resistMultiplierFont.render(resist_multiplier_text, 1, Fonts.RESISTMULTIPLIERCOLOR)
    pg.draw.rect(window, Colors.BLACK, (.8875*Constants.SCREEN_WIDTH, .98*Constants.SCREEN_HEIGHT, Constants.SCREEN_WIDTH, Constants.SCREEN_HEIGHT))
    pg.draw.arrow(window, Colors.MOON, Colors.GREEN, (.8875*Constants.SCREEN_WIDTH, .99*Constants.SCREEN_HEIGHT), (.88*Constants.SCREEN_WIDTH, .99*Constants.SCREEN_HEIGHT), 3, 3)
    pg.draw.arrow(window, Colors.MOON, Colors.GREEN, (Constants.SCREEN_WIDTH, .975*Constants.SCREEN_HEIGHT), (.88*Constants.SCREEN_WIDTH, .975*Constants.SCREEN_HEIGHT), 3)
    window.blit(resist_multiplier_label, (.8925*Constants.SCREEN_WIDTH, .98*Constants.SCREEN_HEIGHT))

    power_multiplier_text = f'Swing Strength: {int(power_multiplier*100)}%'
    power_multiplier_label = Fonts.powerMultiplierFont.render(power_multiplier_text, 1, Fonts.POWERMULTIPLIERCOLOR)
    pg.draw.rect(window, Colors.BLACK, (0, .98*Constants.SCREEN_HEIGHT, .1125*Constants.SCREEN_WIDTH, Constants.SCREEN_HEIGHT))
    pg.draw.arrow(window, Colors.MOON, Colors.GREEN, (.1125*Constants.SCREEN_WIDTH, .99*Constants.SCREEN_HEIGHT), (.12*Constants.SCREEN_WIDTH, .99*Constants.SCREEN_HEIGHT), 3, 3)
    pg.draw.arrow(window, Colors.MOON, Colors.GREEN, (0, .975*Constants.SCREEN_HEIGHT), (.12*Constants.SCREEN_WIDTH, .975*Constants.SCREEN_HEIGHT), 3)
    window.blit(power_multiplier_label, (.005*Constants.SCREEN_WIDTH, .98*Constants.SCREEN_HEIGHT))

    if not shoot:
        pg.draw.arrow(window, Constants.ALINE_COLOR, Constants.ALINE_COLOR, aline[0], aline[1], 5)
        pg.draw.arrow(window, Constants.LINE_COLOR, Constants.LINE_COLOR, line[0], line[1], 5)

    stroke_text = 'Strokes: %s' % strokes
    stroke_label = Fonts.strokeFont.render(stroke_text, 1, Fonts.STROKECOLOR)
    if not strokes:
        window.blit(stroke_label, (Constants.SCREEN_WIDTH - .21 * Constants.SCREEN_WIDTH, Constants.SCREEN_HEIGHT - .985 * Constants.SCREEN_HEIGHT))
    else:
        window.blit(stroke_label, (Constants.SCREEN_WIDTH - (.21+.02*math.floor(math.log10(strokes))) * Constants.SCREEN_WIDTH, Constants.SCREEN_HEIGHT - .985 * Constants.SCREEN_HEIGHT))

    power_text = 'Shot Strength: %sN' % power_display
    power_label = Fonts.powerFont.render(power_text, 1, Fonts.POWERCOLOR)
    if not shoot: window.blit(power_label, (cursor_pos[0] + .008 * Constants.SCREEN_WIDTH, cursor_pos[1]))

    angle_text = 'Angle: %s°' % angle_display
    angle_label = Fonts.angleFont.render(angle_text, 1, Fonts.ANGLECOLOR)
    if not shoot: window.blit(angle_label, (ball.x - .06 * Constants.SCREEN_WIDTH, ball.y - .01 * Constants.SCREEN_HEIGHT))

    if penalty:
        penalty_text = f'Out of Bounds! +1 Stroke'
        penalty_label = Fonts.penaltyFont.render(penalty_text, 1, Fonts.PENALTYCOLOR)
        penalty_rect = penalty_label.get_rect(center=(Constants.SCREEN_WIDTH/2, .225*Constants.SCREEN_HEIGHT))
        window.blit(penalty_label, penalty_rect)

        toggle_bounds_text = "Use [b] to toggle bounds"
        toggle_bounds_label = Fonts.toggleBoundsFont.render(toggle_bounds_text, 1, Fonts.TOGGLEBOUNDSCOLOR)
        toggle_bounds_rect = toggle_bounds_label.get_rect(center=(Constants.SCREEN_WIDTH/2, .275*Constants.SCREEN_HEIGHT))
        window.blit(toggle_bounds_label, toggle_bounds_rect)

    ball.show(window)

    pg.display.flip()


def angle(cursor_pos):
    x, y, xm, ym = ball.x, ball.y, cursor_pos[0], cursor_pos[1]
    if x-xm:
        angle = math.atan((y - ym) / (x - xm))
    elif y > ym:
        angle = math.pi/2
    else:
        angle = 3*math.pi/2

    q = ball.quadrant(x,y,xm,ym)
    if q: angle = math.pi*math.floor(q/2) - angle

    if round(angle*deg) == 360:
        angle = 0

    if x > xm and not round(angle*deg):
        angle = math.pi

    return angle


def arrow(screen, lcolor, tricolor, start, end, trirad, thickness=2):
    pg.draw.line(screen, lcolor, start, end, thickness)
    rotation = (math.atan2(start[1] - end[1], end[0] - start[0])) + math.pi/2
    pg.draw.polygon(screen, tricolor, ((end[0] + trirad * math.sin(rotation),
                                        end[1] + trirad * math.cos(rotation)),
                                       (end[0] + trirad * math.sin(rotation - 120*rad),
                                        end[1] + trirad * math.cos(rotation - 120*rad)),
                                       (end[0] + trirad * math.sin(rotation + 120*rad),
                                        end[1] + trirad * math.cos(rotation + 120*rad))))
setattr(pg.draw, 'arrow', arrow)


def distance(x, y):
    return math.sqrt(x**2 + y**2)


def update_values(quit, rkey, skey, shoot, xb, yb, strokes, x_bounded):
    for event in pg.event.get():
        if event.type == pg.QUIT:
            quit = True

        if event.type == pg.KEYDOWN:
            if event.key == pg.K_ESCAPE:
                quit = True

            if event.key == pg.K_RIGHT:
                if rkey != max(resist_dict):
                    rkey += 1

            if event.key == pg.K_LEFT:
                if rkey != min(resist_dict):
                    rkey -= 1

            if event.key == pg.K_UP:
                if skey != max(strength_dict):
                    skey += 1

            if event.key == pg.K_DOWN:
                if skey != min(strength_dict):
                    skey -= 1

            if event.key == pg.K_b:
                x_bounded = not x_bounded

            if event.key == pg.K_q:
                rkey = min(resist_dict)
                skey = max(strength_dict)
                x_bounded = True

            if event.key == pg.K_e:
                rkey = max(resist_dict)
                skey = max(strength_dict)
                x_bounded = False


        if event.type == pg.MOUSEBUTTONDOWN:
            if not shoot:
                shoot, stop = True, False
                strokes, xb, yb = hit_ball(strokes)

    return quit, rkey, skey, shoot, xb, yb, strokes, x_bounded


def hit_ball(strokes):
    x, y = ball.x, ball.y
    xb, yb = ball.x, ball.y
    power = power_multiplier/4 * distance(line_ball_x, line_ball_y)
    print('nnBall Hit!')
    print('npower: %sN' % round(power, 2))
    ang = angle(cursor_pos)
    print('angle: %s°' % round(ang * deg, 2))
    print('cos(a): %s' % round(math.cos(ang), 2)), print('sin(a): %s' % round(math.sin(ang), 2))

    ball.vx, ball.vy = power * math.cos(ang), -power * math.sin(ang)

    strokes += 1

    return strokes, xb, yb


def initialize():
    pg.init()
    pg.display.set_caption('Golf')
    window = pg.display.set_mode((Constants.SCREEN_WIDTH, Constants.SCREEN_HEIGHT))
    pg.event.set_grab(True)
    pg.mouse.set_cursor((8, 8), (0, 0), (0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0))

    return window


rad, deg = math.pi/180, 180/math.pi
x, y, power, ang, strokes = [0]*5
xb, yb = None, None
shoot, penalty, stop, quit, x_bounded = [False]*5
p_ticks, update_frame = 0, 0

ball = Ball(Constants.START_X, Constants.START_Y)

clock = pg.time.Clock()

strength_dict = {0: .01, 1: .02, 2: .04, 3: .08, 4: .16, 5: .25, 6: .50, 7: .75, 8: 1}; skey = 6
resist_dict = {0: 0, 1: .01, 2: .02, 3: .03, 4: .04, 5: .05, 6: .1, 7: .2, 8: .3, 9: .4, 10: .5, 11: .6, 12: .7,
               13: .8, 14: .9, 15: 1, 16: 1.25, 17: 1.5, 18: 1.75, 19: 2, 20: 2.5, 21: 3, 22: 3.5, 23: 4, 24: 4.5,
               25: 5}; rkey = 7


if __name__ == '__main__':

    window = initialize()
    while not quit:
        power_multiplier = strength_dict[skey]
        resist_multiplier = resist_dict[rkey]

        seconds = (pg.time.get_ticks()-p_ticks)/1000
        if seconds > 1.2: penalty = False

        cursor_pos = pg.mouse.get_pos()
        line = [(ball.x, ball.y), cursor_pos]
        line_ball_x, line_ball_y = cursor_pos[0] - ball.x, cursor_pos[1] - ball.y

        aline = [(ball.x, ball.y), (ball.x + .015 * Constants.SCREEN_WIDTH, ball.y)]

        if not shoot:
            power_display = round(
                distance(line_ball_x, line_ball_y) * power_multiplier/5)

            angle_display = round(angle(cursor_pos) * deg)

        else:
            if stop or (abs(ball.vy) < 5 and abs(ball.vx) < 1 and abs(ball.y - (Constants.START_Y - 2)) <= Constants.BOUNCE_FUZZ):
                shoot = False
                #ball.y = Constants.START_Y
                print('nThe ball has come to a rest!')
                update_frame = 0
            else:
                update_frame, shoot, stop = ball.update(update_frame)

            if not Constants.X_BOUNDS_BARRIER < ball.x < Constants.SCREEN_WIDTH:
                shoot = False
                print(f'nOut of Bounds! Pos: {round(ball.x), round(ball.y)}')
                penalty = True
                p_ticks = pg.time.get_ticks()
                strokes += 1

                if Constants.X_BOUNDS_BARRIER < xb < Constants.SCREEN_WIDTH:
                    ball.x = xb
                else:
                    ball.x = Constants.START_X
                ball.y = yb

        quit, rkey, skey, shoot, xb, yb, strokes, x_bounded = update_values(quit, rkey, skey, shoot, xb, yb, strokes, x_bounded)

        draw_window()

    print("nShutting down...")
    pg.quit()


Get this bounty!!!

#StackBounty: #unity #c# #collision-detection #physics #collision-avoidance How do I keep a rigidbody from making unnecessary collision…

Bounty: 50

I have been having trouble with a custom character controller I am making. The root of the problem lies with collisions. I am trying to make movement code, but I have a problem with ground movement. Pay attention to this gif. It might be hard to notice due to the low frame rate, but the collider registers collisions with objects (in red) that do not point out of the ground. They share the same y-position as the ground. I’ve printed the normals of the collisions, and there are a lot of normals that are perpendicular to the normal of the ground (which is causing the rigidbody to get stuck).

The problem lies with collisions in unity. If I were to print the y-position of the bottom of my collider, it would be just a tad lower than the y-position of the ground. The collider actually rests below the ground by an almost negligible amount (which is why it doesn’t always collide with these objects).

Here is what I have tried: I created a function that runs at the beginning of every FixedUpdate() that uses current collisions to change the y-position of the rigidbody. It only runs on collisions that would ground the player (meaning that they are below the collider). The problem with this approach is that the same issue can occur with walls, meaning that the collider can get stuck on walls. I cannot create another function that would do the same for walls for various reasons.

Here is what would fix the issue: I need help figuring out how I can make collisions more discrete in unity. Colliders rest slightly below objects when ontop of them. They can also “sink” just a little into walls. In other words, colliders can rest into other colliders, and I need this to stop.

Any help is appreciated. Thank you.


Get this bounty!!!

#StackBounty: #unity #collision-detection #physics #mathematics #grid Redundant checks from spatial partitioning

Bounty: 100

A simple 2D grid partition system for collision detection divides space into equal-sized tiles. Colliders then map themselves to tiles with their bounding box in O(N) time. Collision detection only has to be performed between objects that occupy the same tile(s).

Collision detection is expensive so the more culled, the better. With a grid partitioning system, how are collisions culled when colliders share multiple tiles?

For example, Circle_A and Circle_B both sit on the edge between Tile_1 and Tile_2. Iterating both tiles would make collision detection between Circle_A & Circle_B run twice.
Sharing Multiple Tiles

A global pair hashtable seems performance expensive since it has to be cleared every frame. Tracking pairs inside colliders takes a lot of memory. How do you mitigate redundant pairs when iterating through partition grid tiles?


Get this bounty!!!