Checking World Collision Without Physics

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
Quisciens
Prole
Posts: 2
Joined: Wed Jan 14, 2015 8:13 am

Checking World Collision Without Physics

Post by Quisciens »

The title may be worded improperly, I dunno. Here's the problem I'm having:
A day or two ago, I began work on a very simple physics engine. It lacks collision, but it contains the physics needed to operate that(ground collision is operated by a variable 'groundLevel').
Then, I have a Tiled map being drawn on the screen using STI. Of course, STI supports world collision for the map.
Since my player object doesn't function using love.physics at ALL, I'm wondering if it's possible to collide with the world without re-writing the entire player object with that in mind, or, if this is unfunctional, another method of detecting collision within this Tiled map.
As of the build attached to this post, the player object will collide with a single flat ground area, which, as previously stated, is determined by a variable 'groundLevel'. Q and E are work-in-progress attacks, complete with ending lag, while WASD and spacebar handle movement. I'm not asking for anyone to recode this for me, I simply need to know how to detect a collision within the world defined by STI without altering the entirety of the movement code to operate using love.physics, if possible.
Thanks in advance! :awesome:
probably didn't write any of this in a coherent manner, but I digress
Attachments
WIP.love
(59.43 KiB) Downloaded 203 times
User avatar
s-ol
Party member
Posts: 1077
Joined: Mon Sep 15, 2014 7:41 pm
Location: Cologne, Germany
Contact:

Re: Checking World Collision Without Physics

Post by s-ol »

Not only is not using love.physics not a hack, it probably is recommended even. You will need to go through all tiles near the player and check for collisions manually, or use a library like kikitos bump.lua.

If you go the latter route, you will need to extract the tile rectangles, it would be recommended that you also merge adjacent tiles to create larger rectangles (1 long rect instead of 20 small squares for a wall).

You can also (and this is way easier and more flexible IMO) add an object layer in Tiled and fill it with collision rectangles (then you don't need to merge and can do some trickier collision cases, like a no-collision secret wall) loop through it's contents in STI and add those to your collision engine of choice.

If you want me to I can post my standard platformer STI/bump collision code.

s-ol.nu /blog  -  p.s-ol.be /st8.lua  -  g.s-ol.be /gtglg /curcur

Code: Select all

print( type(love) )
if false then
  baby:hurt(me)
end
User avatar
Foxcraft
Prole
Posts: 49
Joined: Sat Mar 22, 2014 8:56 pm

Re: Checking World Collision Without Physics

Post by Foxcraft »

Hey Quisciens,

bump.lua is a simple collision system using the idea of basic bounding boxes. As it's been said, you can dedicate a Tiled layer to collisions (either with some sort of overlay collision squares or just draw all colliding objects like the ground and walls in their own layer).

So you start bump with:

Code: Select all

bump = require "bump"
world = bump.newWorld()
You can throw a number in bump.newWorld to change the detection grid size from 32. This is not your tile size, but how bump cuts up the location into smaller chunks for detection, from what I understand. You can see this in the demos if you hit the button for the debug mode.

Anyway, you add your player and all the tiles you want to worry about to the world.

Code: Select all

world:add(item, item.l, item.t, item.width, item.height)
l and t are x and y, but to the top left corner of the object. It's just like drawing a rectangle around the object.

Then, with the player, you'll just have to adjust how you handle movement, making use of either the world:move or maybe the combination of world:check and world:update functions. Basically, you send it the player (so bump knows what to check) and where the player wants to go. world:move will automatically adjust the player's positions in the bump world (not allowing it to pass through the colliding objects, stopping at them) and return to you the right positions for the player for you to use.

world:check and world:update work such that you can check where the player would be without actually moving them. So getting the returned parts from world:move without messing with the player in the bump world. But then, you can use world:update to make those adjustments. It gives you more control on when updates to bump happen.

So the basic implementation of it won't require a whole lot of changes. There's a lot of good info on bump.lua's Github page.
Quisciens
Prole
Posts: 2
Joined: Wed Jan 14, 2015 8:13 am

Re: Checking World Collision Without Physics

Post by Quisciens »

I'm not sure about implementing either of those, primarily due to this: I want to know how to access the Tiled collision data, as generated by STI, without using love.physics, and it's worth noting that STI creates a love.physics world using the Tiled layout. Bump.lua appears as if it would conflict with that. The collision layer seems like it would work out well, if I could figure this out:
Essentially, I need to check the position of Box2D objects from my player.lua without implementing Box2D, because STI creates a Box2D world. Using this, I'd check the position of the world's tiles and collide accordingly.
User avatar
s-ol
Party member
Posts: 1077
Joined: Mon Sep 15, 2014 7:41 pm
Location: Cologne, Germany
Contact:

Re: Checking World Collision Without Physics

Post by s-ol »

Quisciens wrote:I'm not sure about implementing either of those, primarily due to this: I want to know how to access the Tiled collision data, as generated by STI, without using love.physics, and it's worth noting that STI creates a love.physics world using the Tiled layout. Bump.lua appears as if it would conflict with that. The collision layer seems like it would work out well, if I could figure this out:
Essentially, I need to check the position of Box2D objects from my player.lua without implementing Box2D, because STI creates a Box2D world. Using this, I'd check the position of the world's tiles and collide accordingly.
Simple: There is no such thing as collision data.
You have to interprete that on your own; take all tiles set in a layer; rectangles on an object layer or anything you can think of.

Also how would bump.lua conflict with anything? The "collision layer" method does not at all exclude bump.lua, I would even recommend using bump.lua to power your collision layer. bump.lua is very performant and feature rich and does exactly what you would need to do on your own (and no more; except probably better).

s-ol.nu /blog  -  p.s-ol.be /st8.lua  -  g.s-ol.be /gtglg /curcur

Code: Select all

print( type(love) )
if false then
  baby:hurt(me)
end
User avatar
Foxcraft
Prole
Posts: 49
Joined: Sat Mar 22, 2014 8:56 pm

Re: Checking World Collision Without Physics

Post by Foxcraft »

Hey Quisciens,

Let's look at the STI demo code (main.lua):

Code: Select all

	-- Load map
	map = sti.new("map")

	-- Prepare physics world
	world = love.physics.newWorld(0, 0)

	-- Prepare collision objects
	collision = map:initWorldCollision(world)

	-- Add a Custom Layer
	map:addCustomLayer("Sprite Layer", 3)

	local spriteLayer = map.layers["Sprite Layer"]

	-- Add Custom Data
	spriteLayer.sprite = {
		image = love.graphics.newImage("kim.png"),
		x = 1000,
		y = 800,
		r = 0,
	}

	spriteLayer.sprite.body		= love.physics.newBody(world, spriteLayer.sprite.x/2, spriteLayer.sprite.y/2, "dynamic")
	spriteLayer.sprite.shape	= love.physics.newRectangleShape(50, 50)
	spriteLayer.sprite.fixture	= love.physics.newFixture(spriteLayer.sprite.body, spriteLayer.sprite.shape)
Here's an example of STI with bump.lua, being part of someone's project: viewtopic.php?f=3&t=78847&start=10#p174480

The code's a little messy, having other stuff going on, but take a look (game.lua):

Code: Select all

local sti = require "sti"
local gr = love.graphics
bump = require "bump"
world = bump.newWorld(50)
bump_debug = require 'bump_debug'


function gameload()
	map = sti.new("maps/map_1")  
	playerload()
    enemiesLayer = map.layers["enemies"]
    camera:setBounds(0, 0, map.width * map.tilewidth - love.graphics.getWidth(), map.height * map.tileheight - love.graphics.getHeight() )
    --creating solid block info
    local mapfunction = love.filesystem.load("maps/map_1.lua")
    local mapdatatable = mapfunction()
    maptilesetdata = {}
    for x = 1, mapdatatable.layers[1].width do 
    	maptilesetdata[x] = {} 
    	for y = 1, mapdatatable.layers[1].height do 
    		maptilesetdata[x][y] = mapdatatable.layers[1].data[(y-1)*mapdatatable.layers[1].width+x]

    		if maptilesetdata[x][y] ~= 0 then 
    			block_create((x-1)*32, (y-1)*32)
    		end
    	end 
    end
    --create Collision Blocks from tiled solid blocks
    for i,v in pairs(blocks) do 
    	world:add(blocks[i], v.x,v.y,v.w,v.h)
    end 

    for i,v in ipairs(enemiesLayer.objects) do
        if v.properties.enemy then 
            enemy_create(v.x, v.y, v.width, v.height)
            world:add(enemies[i], v.x,v.y,v.width,v.height)
        end
    end


end
It doesn't seem to be a matter of love.physics being automatically part of STI as much as STI simply allowing you to grab what you want and feed it to whatever "world" you want (be it love.physics, bump.lua, or otherwise). Using the Box2D stuff is just possible, not built in. There is no conflict. :)
User avatar
s-ol
Party member
Posts: 1077
Joined: Mon Sep 15, 2014 7:41 pm
Location: Cologne, Germany
Contact:

Re: Checking World Collision Without Physics

Post by s-ol »

here's bump.lua and STI with object layers:

Code: Select all

	world = bump.newWorld()
	map = Map.threeplat -- "macro" to load map
	
	local col, ent, cnt = map.layers.collision, map.layers.entities, 1
	assert( col, "no collision layer in map" )
	assert( col.type == "objectgroup", "no collision layer in map" )
	for _,r in ipairs(col.objects) do
		world:add( {type = (r.type ~= "" and r.type or T_WRLD), id=cnt}, r.x, r.y, r.width, r.height )
		cnt = cnt+1
	end
	
	assert( ent, "no entity layer in map" )
	assert( ent.type == "objectgroup", "no entity layer in map" )
	for _,r in ipairs(ent.objects) do
		if r.type == "player" then
			if options.playerinfo[r.name] then -- don't spawn more players than we want to
				local p = Player.new( r.name, options.playerinfo[r.name], r.x, r.y )
				p.spawnweapon = require("weapons."..options.spawn[1])( p, options.spawn[2] )
				p.weapon = p.spawnweapon
				players[r.name] = p
			end
		elseif r.type == "crate" then
			cratespawn = { r.x, r.y, r.width, r.height }
		end
	end
	col.visible = false
	ent.visible = false

s-ol.nu /blog  -  p.s-ol.be /st8.lua  -  g.s-ol.be /gtglg /curcur

Code: Select all

print( type(love) )
if false then
  baby:hurt(me)
end
Post Reply

Who is online

Users browsing this forum: No registered users and 5 guests