Walking through collision when rotating camera

Started by Daslee, January 04, 2013, 16:39:24

Previous topic - Next topic

Daslee

Hello. I wanted to ask you guys, maybe someone has done fps camera with collision correctly in your own games? I have it, but it's wrong, here is video about this: http://www.youtube.com/watch?v=nz_joo1OFEI

When I go straight to object it works good with collision, but as you can see if I rotate camera player still not moving, but player must walk little bit, if more rotated so walk more, for example like in Counter Strike game.. Here is my fps camera code (from Lloyd Goodall):

package com.game.input;

import org.lwjgl.util.vector.*;
import static org.lwjgl.opengl.GL11.*;

public class FPControl {
	/* First Person Controller */
	public Vector3f position = null;
	public float yaw = 0.0f;
	public float pitch = 0.0f;
	
	public FPControl(float x, float y, float z){
		position = new Vector3f(x, y, z);
	}
	
	public void yaw(float amount){
		yaw += amount;
		if(yaw > 360) yaw = 0;
		else if(yaw < 0) yaw = 360;
	}
	
	public void pitch(float amount){
		pitch -= amount;
		if(pitch > 90) pitch = 90;
		else if(pitch < -90) pitch = -90;
	}
	
	public void walkForward(float distance){
		position.x += distance * (float)Math.sin(Math.toRadians(yaw));
	    position.z -= distance * (float)Math.cos(Math.toRadians(yaw));
	}
	 
	public void walkBackwards(float distance){
		position.x -= distance * (float)Math.sin(Math.toRadians(yaw));
		position.z += distance * (float)Math.cos(Math.toRadians(yaw));
	}
	 
	public void strafeLeft(float distance){
		position.x += distance * (float)Math.sin(Math.toRadians(yaw-90));
		position.z -= distance * (float)Math.cos(Math.toRadians(yaw-90));
	}
	 
	public void strafeRight(float distance){
		position.x += distance * (float)Math.sin(Math.toRadians(yaw+90));
		position.z -= distance * (float)Math.cos(Math.toRadians(yaw+90));
	}
	
	public void lookThrough(){
		glRotatef(pitch, 1.0f, 0.0f, 0.0f);
        glRotatef(yaw, 0.0f, 1.0f, 0.0f);
        glTranslatef(-position.x, -position.y, -position.z);
	}
}


And movement in player class:
dx = Mouse.getDX();
		dy = Mouse.getDY();
		if(Mouse.isGrabbed()){
			control.yaw(dx * mouseSensitivity);
			control.pitch(dy * mouseSensitivity);
		}


if(Keyboard.isKeyDown(Keyboard.KEY_W)){
			control.walkForward(movementSpeed);
			if(isCollision()){
				control.walkBackwards(movementSpeed);
			}
		}
		if(Keyboard.isKeyDown(Keyboard.KEY_S)){
			control.walkBackwards(movementSpeed);
			if(isCollision()){
				control.walkForward(movementSpeed);
			}
		}
		if(Keyboard.isKeyDown(Keyboard.KEY_A)){
			control.strafeLeft(movementSpeed);
		   	if(isCollision()){
		   		control.strafeRight(movementSpeed);
		   	}
		}
		if(Keyboard.isKeyDown(Keyboard.KEY_D)){
			control.strafeRight(movementSpeed);
		   	if(isCollision()){
		   		control.strafeLeft(movementSpeed);
		   	}
		}


Maybe someone have idea how to fix this?

Fool Running

I'm confused. You say you are having trouble with collision, but in the video it looks like you are correctly *not* going through the blocks.

Is your problem that you are having the picking of which block is being looked at?

Either way, none of the code that you posted would help as you posted no collision code or picking code. :P


EDIT: I think I understand now. Your problem is that when you hit an object (even at an angle) your camera stops and doesn't slide on the wall like most FPS games.
What you need to do is check a collision in each direction when moving. In other words, if you need to move along the Y-axis and the X-axis, check for a collision in the Y-axis first. If there is no collision, then move along the Y-axis. Then do the same thing for the X-axis.

Your current behavior is caused by the fact that you don't move in either direction if either direction is a collision.

NOTE: You might need to tweak this behavior as it might cause a stair-stepping problem when sliding against walls. You might have to move as far as you can in each direction until you hit something.
Programmers will, one day, rule the world... and the world won't notice until its too late.Just testing the marquee option ;D

Daslee

Look, I made something. At the top of player class I put this variable:
public int freeColliding = 1;


Now in collision checking method:
//if is collision then...
float front = obj.z, back = obj.z - obj.depth;
						if(z <= front && z >= back) freeColliding = 1;
						else if(x >= obj.x && x <= obj.x + obj.width) freeColliding = 2;


And walking:
x += movementSpeed * (float)Math.sin(Math.toRadians(control.yaw));
		    z -= movementSpeed * (float)Math.cos(Math.toRadians(control.yaw));
			if(isCollision()){
				x -= movementSpeed * (float)Math.sin(Math.toRadians(control.yaw));
				z += movementSpeed * (float)Math.cos(Math.toRadians(control.yaw));
				if(freeColliding == 1){
					z -= movementSpeed * (float)Math.cos(Math.toRadians(control.yaw));
				}else if(freeColliding == 2){
					x += movementSpeed * (float)Math.sin(Math.toRadians(control.yaw));
				}
			}


But sometimes I can go through object especially when going straight to object edge. Where could be the problem?

EDIT: I fixed it, but sometimes very rarely can go through object edge.