Estou tentando seguir este tutorial http://www.tonypa.pri.ee/tbw/tut05.html para implementar colisões em tempo real em um mundo baseado em blocos.
Eu encontro as coordenadas centrais das minhas entidades graças a estas propriedades:
public float CenterX
{
get { return X + Width / 2f; }
set { X = value - Width / 2f; }
}
public float CenterY
{
get { return Y + Height / 2f; }
set { Y = value - Height / 2f; }
}
Então, no meu método de atualização, na classe player, que é chamada de cada quadro, tenho este código:
public override void Update()
{
base.Update();
int downY = (int)Math.Floor((CenterY + Height / 2f - 1) / 16f);
int upY = (int)Math.Floor((CenterY - Height / 2f) / 16f);
int leftX = (int)Math.Floor((CenterX + Speed * NextX - Width / 2f) / 16f);
int rightX = (int)Math.Floor((CenterX + Speed * NextX + Width / 2f - 1) / 16f);
bool upleft = Game.CurrentMap[leftX, upY] != 1;
bool downleft = Game.CurrentMap[leftX, downY] != 1;
bool upright = Game.CurrentMap[rightX, upY] != 1;
bool downright = Game.CurrentMap[rightX, downY] != 1;
if(NextX == 1)
{
if (upright && downright)
CenterX += Speed;
else
CenterX = (Game.GetCellX(CenterX) + 1)*16 - Width / 2f;
}
}
downY, upY, leftX e rightX devem, respectivamente, encontrar a posição Y mais baixa, a posição Y mais alta, a posição X mais à esquerda e a posição X mais à direita. Eu adiciono + Speed * NextX, porque no tutorial a função getMyCorners é chamada com estes parâmetros:
getMyCorners (ob.x+ob.speed*dirx, ob.y, ob);
Os métodos GetCellX e GetCellY:
public int GetCellX(float mX)
{
return (int)Math.Floor(mX / SGame.Camera.TileSize);
}
public int GetCellY(float mY)
{
return (int)Math.Floor(mY / SGame.Camera.TileSize);
}
O problema é que o jogador "pisca" ao bater em uma parede, e a detecção de canto nem funciona corretamente, pois pode sobrepor paredes que atingem apenas um dos cantos. Eu não entendo o que está errado. No tutorial, os campos ob.x e ob.y devem ser iguais às minhas propriedades CenterX e CenterY, e ob.width e ob.height devem ser iguais a Width / 2f e Height / 2f. No entanto, ainda não funciona.
Obrigado pela ajuda.
Respostas:
Algumas sugestões, embora não tenha certeza de que elas resolverão o problema, pois não tenho código completo para executar e depurar.
Neste código:
a instrução else está movendo o objeto, mesmo que o objeto não deva estar se movendo.
Eu acho que você está tentando fazer o objeto ficar encostado na parede, mas talvez o cálculo esteja incorreto.
Se você comentar a instrução else, o objeto ainda pisca?
O cálculo parece um pouco suspeito, pois subtrai (Width / 2f) e, em seguida, o operador do conjunto CenterX faz a mesma subtração novamente.
Outra coisa que eu gostaria de salientar, apenas para ajudar a clareza do código, é que você fez as propriedades do CenterX calcularem o valor de um lado para outro, mas o código ainda está cheio do mesmo cálculo repetidamente.
Isso pode muito bem ser parte do problema. De qualquer forma, eu sugiro criar mais algumas propriedades e estabelecer um padrão para todas elas. Por exemplo, torne o Centro a propriedade armazenada e calcule os outros:
fonte