Page 1 of 1

Slow Game (Windows only?)

Posted: Sat Dec 01, 2012 6:03 pm
by TurtleP
Hello,

My game seems to run slow on my own OS (Windows) when there are a lot of "objects" on the screen. I am certain this is happening in my physics.lua:

http://pastebin.com/6PMKZQQA

OR

Code: Select all

function docollision() --Handles loops for physics. Lot less complicated than it seems.
	local lgamexscroll = gamexscroll
	local width = love.graphics.getWidth()
	local lobjects = objects
	for j, w in pairs(lobjects) do --
		for i, v in pairs(w) do -- Select first objects table
			if j ~= "block" then
				for name, lol in pairs(lobjects) do --Go through all objects names again
					for __, value in pairs(lol) do -- Goes through second objetcs table.
						if j ~= name then -- They dont need to collide with themselves.
							if value.x > lgamexscroll and value.x < value.x + value.width then
								collisionCheck(v, value, j, name, dt)
							end
						end
					end 
				end
			end
		end
	end
end
SPECS:

Windows 7 Pro SP1 32bit
NVIDIA Quadro FX 570M GPU
Intel Core 2 Duo @ 2.50 GHz
4.00GB RAM

My friend's mac runs this thing with 40-50 FPS when I get as low as 15 FPS with many objects on the map.

Re: Slow Game (Windows only?)

Posted: Sat Dec 01, 2012 11:57 pm
by Dattorz
That is a lot of nested for loops. You're basically comparing every single object against every single other object. For n objects this will take n^2 time, so for large numbers of n you're going to see some pretty bad performance. If you want decent performance with lots of objects on the screen, you'll need to narrow down the scope from which you are selecting potentially colliding objects - EG. dividing the world into sectors and only testing collisions between objects that share the same sector. There are many ways to do this from quadtrees to even static arrays. Find a method that works for what you're trying to do.

Re: Slow Game (Windows only?)

Posted: Sun Dec 02, 2012 1:56 am
by TurtleP
Dattorz wrote:That is a lot of nested for loops. You're basically comparing every single object against every single other object. For n objects this will take n^2 time, so for large numbers of n you're going to see some pretty bad performance. If you want decent performance with lots of objects on the screen, you'll need to narrow down the scope from which you are selecting potentially colliding objects - EG. dividing the world into sectors and only testing collisions between objects that share the same sector. There are many ways to do this from quadtrees to even static arrays. Find a method that works for what you're trying to do.
Now I changed up my game, so that each entity has a "self.mask = {name, name, name}" type of feature. However, now I don't know what to do with this bunch of other code which makes the game lag:

Code: Select all

local function collisionCheck(v1, v2, v1name, v2name, dt) --add masks
	local should = true
	local collision
	local horizontal, vertical
	local cancollide = false
	if not v1.mask[v2name] or v1.mask[v2name] == false or v2.mask[v2name] == false then
		cancollide = false
	else
		for i, v in pairs(v1.mask[v2name]) do
			if v == v2name or v == "all" then
				cancollide = true
				break
			end
		end
	end
	if v1name == "block" then
		if v1.x == v2.x then
			return
		end
	end
	if cancollide then
		collision = aabb(v1.x, v1.y, v1.width, v1.height, v2.x, v2.y, v2.width, v2.height)
	end

	local mtd

	
	
	if collision or v1.mask then
		mtd = calculatemtd(v1, v2)
	end

	if mtd then
		if mtd.x ~= 0 then
			horizontal = true
		end
		if mtd.y ~= 0 then
			vertical = true
		end
	end
 
	if v1.mask then
		if horizontal then
		local speed = v1.xSpeed
		if not v2.passive then
			v1.xSpeed = 0 --HOLD UP
			if not v1.static then
				v1.x = v1.x + mtd.x
			end
		end
		if speed >= 0 then --Moving right
			if v1.rightcollide then 
				v1:rightcollide(v2, v2name)
			end
		end
		if speed <= 0 then
			if v1.leftcollide then
				v1:leftcollide(v2, v2name)
			end
		end
	end
	if vertical then
		local speed = v1.ySpeed
		if not v2.passive then
			v1.ySpeed = 0
			if not v1.static then
				v1.y = v1.y + mtd.y
			end
		
		if speed <= 0 then
			if v1.upcollide then
				v1:upcollide(v2, v2name)
			end
		end
		if speed > 0 then
			if v1.downcollide then
				v1:downcollide(v2, v2name)
			end
		end
		end
	end
	end
	
	return should
end

Code: Select all

local function docollision(dt) --Handles loops for physics. Lot less complicated than it seems.
	for j, w in pairs(objects) do --
		for i, v in pairs(w) do -- Select first objects table
			local thing = true
			if j == "block" then
				if not v.thrown then
					thing = false
				end
			end
			if thing then
				for name, lol in pairs(objects) do --Go through all objects names again
					for __, value in pairs(lol) do -- Goes through second objetcs table.
						local canpass = false
						if j == "block" then
							canpass = true
						else
							if j ~= name then
								canpass = true
							end
						end
						if canpass then -- They dont need to collide with themselves.
							local properx = gamexscroll
							if value.x >= v.x - 16*scale*2 and value.x < v.x + v.width + 16*scale*2 then
								collisionCheck(v, value, j, name, dt)
							end
						end
					end 
				end
			end
		end
	end
end

function loadphysics(dt) --Deltatime	Put in game, will load all the physics
	docollision(dt) --Yay collision system that does physics for me
end

Re: Slow Game (Windows only?)

Posted: Sun Dec 02, 2012 6:36 am
by Qcode
I am "his friend" and we've figured out the problem. We had background tiles, and for each of those tiles we made an object and made it passive rather than just having it stored in our map table. So for background tiles we were calling calculatemtd every frame, and that really ate up FPS. Thanks for helping anyway!