Voxel - a start

Hi,

Wanting to add a player to the voxel engine now. I’ve basically just centred a cube as the player
in the centre of the screen. I’m just applying the camera’s pitch to the player, something like this:


		glRotatef(-yRot, 0.0f, 1.0f, 0.0f);

Where yRot is the camera’s pitch, now I’m presuming I don’t move the player about, just the world as I am doing with my camera? I did try to make the player cube rotate on the X-axis, but it looks silly as the cube goes out of alignment with the world:


		glRotatef(-xRot, 1.0f, 0.0f, 0.0f);

My question is, how do you add a player and move it around the world correctly - i.e. so it ‘angles’ with the land so to speak…

Regards,
Steve

Sorry I have no idea about octrees at the moment.

As far as your player is concerned…
Are you saying the player is viewed in the 3rd person?

If you want ur player to rotate in line with there facing direction you will have to use the vector components of x and z.

I notice when u move the camera in ur video , u also rotate the landscape rather than use the camera rotation, then move it forward with its x and a vector.

I can paste code tomorrow for this if you would like.

Hi,

Basically show a cube in the middle of the screen as the player, yes third person.

Here is a video of me of the player as a cube, looks ok now :slight_smile:

https://www.youtube.com/watch?v=CNrTUXPKbO4

Thanks

Yea that looks cool, moves fine. Are you going to use models or keep it as blocks?

Hi,

The player will possibly be made up of a couple of blocks…

Just added in block detection - basically detect if block you are on is active or not, need check if block in front, back etc are active also and then need to stop you moving when you are!

How is yours going?

The way I did that is when u press to move it adds on you x and z vectors to your position, then if that block is solid at you height, then you can’t move, otherwise you go ahead and apply those vectors.

It’s going we’ll thank you, will be posting a video update tomorrow. Got vertex lighting, and a new map loading done today.

I like how yours is looking, are your maps going to be bigger or are you having levels in your game? Like to solve puzzles on smaller maps? Sorry for asking questions!

Hi,

I got camera moving up and down, my player always stays in same place, don’t know if this is
correct?

I’m trying to put collision detection in, can detect when player has a block in front, underneath etc, but if player turns (camera turns) and then move’s forwards my collision is all messed up. Think I need to know which way the camera is facing, thought I had this with some trig:

direction = atan(camerapos.x / camerapos.z );

How are you doing the player movement, collision detection?

Anybody else got any tips on collision detection with block - and how would I implement a vector slide?

Maps will be larger, just messing around at the moment, just want to get the collision stuff working, thought this would be simple.

Thanks,
Steve

Hi

This is how I impliment the collison and player moving:

if(!isBlock(xpos - (float) Math.sin(yrot * piover180) * 0.35f,zpos - (float) Math.cos(yrot * piover180) * 0.35f)){
					
				
				xpos -= (float) Math.sin(yrot * piover180) * 0.1f;
				zpos -= (float) Math.cos(yrot * piover180) * 0.1f;

piover180 = 0.0174532925f to convert to radiens
xpos, zpos are my float player positions. yrot, y axis rotation.
0.35 is the distanced moved (notice its more than the actual movment, this is so you cannot get too close to a block) (ie the camera has a size)
There is an issue with this and diagonally placed blocks. This will be sorted later.

the player updates are only applied if there is not a block.

	private boolean isBlock(float x, float z) {  
			
		int c = getChunk(x, z); //get the chunk of the block

                           x=x%16; //this will find the block within the chunk 
		z=z%16;
							
		if(chunks[c].getblockID(x, (int)playerheight,z)>0)return true;
		
		return false;
	}
	

This is a simplified version of my isBlock code. (ther is some stuff in there to sort out negativate coordinates)
The Chunk getBlockID just returns a value. 0 is Air, all other blocks are solid at the moment.
This assumes the player is 1 block high!

If you want any more code Ill pop it on. It works for me, but more experience programmers may have better solutions.

Mmmmm, not too clear on your code, is that all your camera code?

This is my camera code:


public class GameCamera {

	//3d vector to store the camera's position in
    private Vector3f    position    = null;
    //the rotation around the Y axis of the camera
    private float       yaw         = 0.0f;
    //the rotation around the X axis of the camera
    private float       pitch       = 0.0f;
    
    
  //Constructor that takes the starting x, y, z location of the camera
    public GameCamera(float x, float y, float z, float pitch, float yaw)
    {
        position = new Vector3f(x, y, z);
        this.yaw(yaw);
        this.pitch(pitch);
    }

    public float getCameraYaw() { return yaw; }
    public float getCameraPitch() { return pitch; }
    public Vector3f getCameraPosition() { return position; }
    
  //increment the camera's current yaw rotation (Y)
    public void yaw(float amount)
    {
        //increment the yaw by the amount param
    	if(yaw < 0.0) yaw += 360;
    	if(yaw > 360) yaw -= 360;
    		yaw += amount;
    }
     
    //increment the camera's current pitch rotation (X)
    public void pitch(float amount)
    {
        //increment the pitch by the amount param
    	if(pitch > 90) pitch = 90;
    	if(pitch < -90) pitch = -90;
    		pitch += amount;
    }
    
    public void roll(float amount)
    {
    	// not used
    }
    
    // X is sin(angle) * r
    public float getXPos(float angle)
    {
    	return (float)Math.sin(Math.toRadians(angle));    	
    }
    // Z is cos(angle) * r
    public float getZPos(float angle)
    {
    	return (float)Math.cos(Math.toRadians(angle));    	
    }
  //moves the camera forward relative to its current rotation (yaw)
    public void walkForward(float distance)
    {
        position.x -= distance * getXPos(yaw);
        position.z += distance * getZPos(yaw);
    }
     
    //moves the camera backward relative to its current rotation (yaw)
    public void walkBackwards(float distance)
    {
        position.x += distance * getXPos(yaw);
        position.z -= distance * getZPos(yaw);
    }
     
    //strafes the camera left relative to its current rotation (yaw)
    public void strafeLeft(float distance)
    {
    	// player position is x=sin(yaw), z=cos(yaw)
      	// x is distance * sin(yaw)
    	// z is distance * cos(yaw)  
    	// we subtract 90 to the angle so to strafe
        position.x -= distance * getXPos(yaw- 90);  // .5PI
        position.z += distance * getZPos(yaw- 90);  // .5PI
    }
     
    //strafes the camera right relative to its current rotation (yaw)
    public void strafeRight(float distance)
    {
    	// x is distance * sin(yaw)
    	// z is distance * cos(yaw)  
    	// we add 90 to the angle so to strafe
        position.x -= distance * getXPos(yaw+90);
        position.z += distance * getZPos(yaw+90);
    }
    
    public void jump(float distance)
    {
    	position.y -= 1;
    }
    public void down(float distance)
    {
    	position.y += distance;
    }

    public void resetPosition(float x, float y, float z, float pitch, float yaw)
    {
    	position.x = x; position.y = y; position.z = z;
    	this.pitch = pitch;
    	this.yaw = yaw;
    }
    
    //translates and rotate the matrix so that it looks through the camera
    //this does basically what gluLookAt() does
    public void lookThrough()
    {
        //rotate the pitch around the X axis
        GL11.glRotatef(pitch, 1.0f, 0.0f, 0.0f);
        //rotate the yaw around the Y axis
        // remove line below for third person
        GL11.glRotatef(yaw, 0.0f, 1.0f, 0.0f);
        //translate to the position vector's location
        GL11.glTranslatef(position.x, position.y, position.z);

    }
    
}

How do you initialise your camera position at the start and your floor?

PS - my math aint too good!

Regards,
Steve

You perhaps more organised than I am!
My camera is just xpos,ypos,zpos floats. Ypos is player height
Then I have lookup (-lookup is lookdown!)
That’s it. I don’t even have a class for it yet!

The floor is the start x,z blocks top surface. The camera is 1.8 units above that.

So in my update(). I always fall… Unless I’m = or a bit lower than the block surface.
I fall to the block surface.

So if block is at height 2. The floor 3. So the cam cannot be less than 4.8

When jumping I use acceleration, and falling is acceleration to rather than subtracting a linear value.

More realistic jumping can be done by setting the velocity once when the key is pressed and constantly applying gravity.*

Changing Position = Linear = Velocity
Changing Velocity = Quadratic = Acceleration

Acceleration -> Velocity -> Position

  • It sort-of works like this in real life. Force is only applied while you are on the ground. After that only gravity affects you (drag is minimal)

Any chance you could show how you position your camera and did you say your floor is just one block in height? Do you draw this separate of your chunking?

Thanks,

PS - does my camera class look ok?

the floor is the block that im stood on, so there is just the chunk, and the floor is found by litterally dropping out of the sky and landing on a block.

so if a block is 8 high, the floor is 9 in my game. the floor is not drawn,its just the block. here is my code to calculate that.

private void updateLogic() {
		
			ground = getGroundLevel(xpos, playerheight, zpos);
			
		 	playerheight+=yVelocity*TIME_STEP;
			yVelocity+=GRAVITY*TIME_STEP;
		
			if(playerheight<=ground)	{
				isJumping = false;
				yVelocity=0;
				playerheight= ground;
			}
                           }
			

my get ground level method is this:

int groundLevel=y;	
		//System.out.println("ground level =  " +  groundLevel);
		for(int gl = groundLevel;y>-1;y--){ //cycle thorugh the blocks under the player untill we hit one;
		
			if(chunks[c].getblockID(x, gl,z)>0)return gl;
		}

this is how I jump

if (Keyboard.isKeyDown(Keyboard.KEY_SPACE)) { 
				
				if(!isJumping){
					isJumping= true;
					yVelocity=6f;
					
				}
			}

Setup:

float yVelocity=0.0f;
final double TIME_STEP=1/60.0;
final float GRAVITY=-11f;

Before I render the VBO chunks:

//position the player/camera
				GL11.glRotatef(lookupdown, 1.0f, 0, 0);
				GL11.glRotatef(360.0f - yrot, 0, 1.0f, 0);
				GL11.glTranslatef(-xpos, camHieght , -zpos);

I should also mention that I add a walkbias to the cam hight to for rendering only,

I found this part in NeHe’s excellent tutorials.

walkbiasangle += 10.0f;

				if (walkbiasangle > 360.0f) {
					walkbiasangle -= 360.0f;
				}

				walkbias = (float) Math.sin(walkbiasangle * piover180) / 20.0f;
				
				}

then I add this to the camHieght at rendertime, but it does not effect the actuall calculations for falling.

Thanks for that,

So, you seem to do like me, just draw your chunks, and ground is where the ‘player’ lands?

What is player height, this set to the size of a block?

I’m just having trouble doing the start position of the camera for the game, want it to be somewhere in the middle of all the chunks.

What is a ‘walkbias’ by the way??

Thanks

The “walkbias” is the up/down bobbing of the head while walking.
You don’t really need it.

Edit:
Random Question: How do you store/manage your chunks while they are loaded?

  • Longor1996

At the moment I just generate the same chunk:


public int SetupLandscape()
	{
		float r = 1 + (float)Math.random()*16;
		for (int x = 0; x < CHUNK_SIZE; x++) {
			for (int z = 0; z < CHUNK_SIZE; z++) {
				int height = (int) (SimplexNoise.noise(x / 16f, z / 16f) * Math.random()*16);
				if(height<=0) height = 1;
				for(int y = 0; y < height; y++) // set these blocks on
				{
					Blocks[x][y][z].SetActive(true);
					Blocks[x][y][z].SetType(BlockType.BlockType_Grass);
				}
			}
		}
		return this.rebuildChunk();
	}

I also have this code to do a sphere:


public int SetUpSphere() {
		for (int x = 0; x < CHUNK_SIZE; x++) {
			for (int y = 0; y < CHUNK_SIZE; y++) {
				for (int z = 0; z < CHUNK_SIZE; z++) {
					
					if (Math.sqrt((float) (x-CHUNK_SIZE/2)*(x-CHUNK_SIZE/2) + (y-CHUNK_SIZE/2)*(y-CHUNK_SIZE/2) + (z-CHUNK_SIZE/2)*(z-CHUNK_SIZE/2)) <= CHUNK_SIZE/2)
	                {
	                   Blocks[x][y][z].SetActive(true);
	                   Blocks[x][y][z].SetType(BlockType.BlockType_Grass);
	                }										
				}
			}
		}	
		return this.rebuildChunk();
	}

I have a singleton class for my chunkManager, it basically just has an ArrayList of Chunks, which in turn has a 3d array of Block objects. Thus a linear list.

I add a chunk as follows:


ChunkManager.getInstance().AddChunk(ChunkType.ChunkType_Land,0,0,1);

This adds a basic chunk created from simplex noise at xoffset=0, yoffset=0 and zoffset=1

What do you use to generate your chunks?

Thanks

PS - what data structure do you store your chunks in? I’m having an issues getting the correct chunk because it is a linear list…I guess you know the amount of chunks on X * Chunk Size * Z position to get the correct chunk?

Thanks,
Steve

PS - Just using this now to get chunk where we are:


int zchunk = (blockZ / Chunk.CHUNK_SIZE) * CHUNKS_ON_X;      
int xchunk = (blockX / Chunk.CHUNK_SIZE);
int chunkToGet = zchunk + xchunk;

Block b = ChunkManager.getInstance().getBlockInChunk(chunktoget, blockX,blockY,blockZ);
if(!b.isActive() ) {
     // air 
}		

Guess at some point, will need to modify the above to take into account the y-chunk?

Collision checks are driving me mad, just can’t seem to get it correctly working.

For instance, for when player jumps, I do the following to get the block that is in front
of the player:


int blockX = (int) Math.abs((pos.x/2));  
int blockZ = (int) Math.abs((pos.z/2))+1;
int blockY = (int) Math.abs(pos.y);

pos is the camera’s vector position.

I then do:


int zchunk = (blockZ / Chunk.CHUNK_SIZE) * 1;
int chunk = (blockX / Chunk.CHUNK_SIZE);// + (blockZ / Chunk.CHUNK_SIZE);
int chunktoget = zchunk + chunk;

To get the chunk to get:


Block b = ChunkManager.getInstance().getBlockInChunk(chunktoget, blockX,blockY,blockZ);

then just check if the block is active:


this.bNoCollision = b.IsActive();

Works sometimes, but seems very inaccurate. I just thought it would be a simple case of getting
the block in front of player and if player jumps and the block is active, I stop moving the camera down.

:frowning: >:( Doing my head in!

Thanks

Wait, what?

You are cheking the block in front of the player to check if you have to stop jumping.
I think it would be better to check the block below the player for collisions.

How about using AABB’s like Minecraft does?
That fixes most of the problems.

  • Longor1996

Hi,

I’ve also tried the block below, same result:

Here is a small video of the issue:


https://www.youtube.com/watch?v=CxAwerbBFx8

AABB - is there some information about this somewhere?

Thanks