kikito / gamera

A camera system for LÖVE

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Floor camera coordinates?

s-ol opened this issue · comments

commented

I noticed that sometimes black seems occured between tiles when using STI. Usually flooring all coordinates fixes that, but at a large zoom (I am using x4) that produces very laggy and noticeable bad camer movement, so simply flooring the values is not enough, they need to be floored at zoom-level precision. Here is how I patched gamera for my purposes:
(optionally?) allow subpixel camera movement

function gamera:draw(f)
  love.graphics.setScissor(self:getWindow())

  love.graphics.push()
    local scale = self.scale
    love.graphics.scale(scale)

    local tx, ty = math.floor(self.w2 + self.l, self.h2 + self.t)
    love.graphics.translate(tx/scale, ty/scale)
    love.graphics.rotate(-self.angle)
    tx, ty = math.floor(-self.x*scale, -self.y*scale)
    love.graphics.translate(tx/scale, ty/scale)

    f(self:getVisible())

  love.graphics.pop()

  love.graphics.setScissor()
end

the code is messy, but it should be understandable; every coordinate used is first multiplied by scale, then floored and divided by scale again. Note that my math.floor can floor multiple values, the default doesn't.

The best way I know for not having "sears" when handling tiles is the following:

Usually the seams happen because you are using images instead of quads, or because the quads you are using are "touching each other", like this (each character is a pixel, each tile is 5x5)

$$$$$#####*****
$$$$$#####*****
$$$$$#####*****
$$$$$#####*****
$$$$$#####*****
%%%%%@@@@@^^^^^
%%%%%@@@@@^^^^^
%%%%%@@@@@^^^^^
%%%%%@@@@@^^^^^
%%%%%@@@@@^^^^^

The way OpenGL works, when you render a quad using non-integer values, a little of the tiles "touching it" (or another piece of memory) "bleeds in".

Flooring the coordinates is an easy fix, but if you want to do zooms or rotations you should abandon that approach and use the following one: Surround your tiles by "extra space", like this:

$$$$$$$#######*******
$$$$$$$#######*******
$$$$$$$#######*******
$$$$$$$#######*******
$$$$$$$#######*******
$$$$$$$#######*******
$$$$$$$#######*******
%%%%%%%@@@@@@@^^^^^^^
%%%%%%%@@@@@@@^^^^^^^
%%%%%%%@@@@@@@^^^^^^^
%%%%%%%@@@@@@@^^^^^^^
%%%%%%%@@@@@@@^^^^^^^
%%%%%%%@@@@@@@^^^^^^^
%%%%%%%@@@@@@@^^^^^^^

This is still a a grid of 6 5x5 tiles - but they are 'extended' - you use a 7x7 space for each 5x5 tile. In other words, the coordinates of the tiles are the dotted ones.

$$$$$$$#######*******
$.....$#.....#*.....*
$.....$#.....#*.....*
$.....$#.....#*.....*
$.....$#.....#*.....*
$.....$#.....#*.....*
$$$$$$$#######*******
%%%%%%%@@@@@@@^^^^^^^
%.....%@.....@^.....^
%.....%@.....@^.....^
%.....%@.....@^.....^
%.....%@.....@^.....^
%.....%@.....@^.....^
%%%%%%%@@@@@@@^^^^^^^

The extra pixels around each tile are the same color as the pixel's borders.
This way, when a tile "bleeds out" because OpenGL and floating point shenanigans, it still shows "the correct color".

Usually you will be fine with just 1 pixels, but you can also try with a 2-px border, just to be sure.

I think this solution is better suited for your particular problem - please try it and let me know.

commented

I know that this is a way to fix this also, but it is tiresome to use, especially with 3rd party spritesheets. I used the approach I presented above in Cruved Curse already, and it always worked flawlessy for me.

I am glad that worked out for you. However, at least for now, I don't think your patch is too specific for gamera, which should remain generic.

I've toyed in my brain about doing a pixel-perfect camera and sprite system for LÖVE, similar to this unity library. If I ever do that, I will see if I can include some version of it there.

For now though, I must close down this issue.