Collision detection without physics?

General discussion about LÖVE, Lua, game development, puns, and unicorns.
User avatar
Przemator
Party member
Posts: 107
Joined: Fri Sep 28, 2012 6:59 pm

Re: Collision detection without physics?

Post by Przemator »

I've been considering this, but each track also has parameters: acceleration and turn rate per each update (e.g. move by 10 pixels and rotate by 4 degrees). It's just all not physics-based.
User avatar
pgimeno
Party member
Posts: 3551
Joined: Sun Oct 18, 2015 2:58 pm

Re: Collision detection without physics?

Post by pgimeno »

I've implemented this kind of pixel-based collision in Thrust II Reloaded (see my sig for the full code).

What I do is draw in a small canvas the portion of the collision mask corresponding to the map and enemies around the player, then switch to multiplicative blending and draw the player's collision mask. Then I take the ImageData of the canvas and convert it to string, and compare the string with a precalculated string (don't create it every frame!) filled with all zeros.
User avatar
Przemator
Party member
Posts: 107
Joined: Fri Sep 28, 2012 6:59 pm

Re: Collision detection without physics?

Post by Przemator »

Yes, I saw your code. It's a neat trick with the string. But I decided against it, since I would not like to use graphics functions for collision detections. Graphics functions can only run from the main thread, so this would be a limitation, should I choose to separate update from drawing. In the end I think I will just go for a simple getPixel(x,y) to see if the middle of the car is still on the track.
grump
Party member
Posts: 947
Joined: Sat Jul 22, 2017 7:43 pm

Re: Collision detection without physics?

Post by grump »

Przemator wrote: Fri Apr 26, 2019 8:54 am I would not like to use graphics functions for collision detections. Graphics functions can only run from the main thread, so this would be a limitation, should I choose to separate update from drawing. In the end I think I will just go for a simple getPixel(x,y) to see if the middle of the car is still on the track.
If you want to solve this problem on a level that does not involve the actual rendered graphics, you need to build a representation of your game data that is on a higher level than just plain image files. Track boundaries can be represented by line segments; cars should be represented by geometric primitives, like boxes. Detecting and responding to collisions between boxes and line segments is "easy". Doing the same with pixels is hard - you won't be able to implement it, expect for trivial scenarios (no rotation, no scaling, and ideally no scrolling).
User avatar
Przemator
Party member
Posts: 107
Joined: Fri Sep 28, 2012 6:59 pm

Re: Collision detection without physics?

Post by Przemator »

I implemented my collisions the following way: the collisions between cars are made using distance. I measure the distance between all cars then get the smallest distance that is below the threshold (say, 32 pixels). Then i "push" the cars away from each other. I repeat until all cars are at least 32 pixels away.

Then I apply track collision. For this I've been using ImageData, but it's been kind of slow. So i've tried a few other methods:

Code: Select all

    local cnt = 20000000
    local tab_x = {}
    local tab_y = {}

    local t0 = love.timer.getTime()
    for i = 1, cnt do
        tab_x[i] = love.math.random() * w
        tab_y[i] = love.math.random() * h
    end
    local t1 = love.timer.getTime()
    print("random", t1 - t0)

    for i = 1, cnt do
        local x, y = tab_x[i], tab_y[i]
        local r, g, b, a = self.maskdata:getPixel(x, y)
    end
    local t2 = love.timer.getTime()
    print("getpix", t2 - t1)

    for i = 1, cnt do
        local x, y = tab_x[i], tab_y[i]
        local r = self.masktab[math.floor(x)][math.floor(y)]
    end
    local t3 = love.timer.getTime()
    print("tables", t3 - t2)

    for i = 1, cnt do
        local x, y = tab_x[i], tab_y[i]
        local loc = (math.floor(y) * w + math.floor(x)) * 4 + 1
        local r = string.byte(self.masktext, loc)
    end
    local t4 = love.timer.getTime()
    print("string", t4 - t3)
And the result:

Code: Select all

random  1.0678514140891
getpix  1.0594320619712
tables  0.17795943294186
string  0.11870640702546
So working with string is somehow the fastest, 10x faster than getPixel.
Post Reply

Who is online

Users browsing this forum: No registered users and 53 guests