Digging tiles out

Hi,

I have a 2d array containing all my map - made up of tiles. I can dig down but struggling to dig left and right as using left and right keys just moves my
player. I use W key at the moment to dig (remove a tile), but would like to be able to dig in the left right directions also…


	private void removeBlock(Vector3 position, boolean bDown, boolean bLeft, boolean bRight)
	{
		Vector3 screenSpace = toScreenSpace(position);
		int x = Math.round(screenSpace.x);
		int y = Math.round(screenSpace.y);
		if(bDown) y--;
		if(bRight) x+=1;
		if(bLeft) x-=1;
		BlankEntity entity = this.worldMap.getBlock(x, y);
		if(entity !=null && !entity.toString().equals("CAVE")
				&& !entity.toString().equals("WATER")) {
			this.worldMap.removeEntity(x, y);
		}
	}

The method above is meant to know if you pressed the left, right or down key, these are stored in some booleans I have set up, but they are always false.


		if (Gdx.input.isKeyPressed(Input.Keys.W))
		{
			removeBlock(camera.position, bDown, bLeft, bRight);
		}


The code above just calls the removeBlock method. What is the best way about going about removing blocks where the player ‘digs’?

Thanks

Hmm. First try this:


int x = Math.round(screenSpace.x);
int y = Math.round(screenSpace.y);

to:


int x = (int) screenSpace.x;
int y = (int) screenSpace.y;

Let me know if there’s a change.

Thanks for that, but still pretty much the same. When click right, block I remove is still removed from under player.

Try this:

System.out.println("Down: " + bdown +" Left: " + bleft + " Right: " + bright);

Are you actually getting the results you expect? If yes, add this:

System.out.println("Player Coords: " + position.x +", " + position.y);

(assuming that’s how this works)
and:

System.out.println("Block remove at: " + x +", "+ y );

If these values check out, then it should work, or you’re removing the wrong entity or not hitting one of your qualifiers. Your code is written pretty badly in terms of understandability, and you may want to just change your map to something along the lines of a multidimensional array that isn’t tied to entities, since I assume tiles are not treated as entities in any other way except that they have a position and a type.

(At least, this would make more sense to me, as then you wouldn’t need to do any of that round about entity work in there, just

 "Array[x][y].type = air"

or whatever.)

Can we see getBlock(x, y) and check if bdown is always true. I dont think the issue is in the code we see. (Besides the rounding issue.)

I believe you aren’t setting bDown, bLeft, bRight properly.

It could be a lot. Do you have this in a repo? I could fork it and take a look.

Hi,

getBlock is just a simple get from the map array:


	public BlankEntity getBlock(int x, int y)
	{
		return worldMap[x][y];
	}

and here is the code for render which does the keyboard input:

@Override
public void render() {

	Vector3 poss = new Vector3(camera.position);
	poss.y-=8;

	// Need to check if not jumping as we need to jump Y amount before any downward force happens
 	if(!bLeft && !bRight)  // this needs fixing as doesn't happen when moving right
	{
 		if(checkCollision(poss))
		{
			camera.position.y -= 3;  // scroll map down
		}
	}
	
	int fps = Gdx.graphics.getFramesPerSecond();
			
	Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
	 
	cloudBackground.render(0.05f, ambientShader);   // render clouds

	batch.setProjectionMatrix(camera.combined);

	if (Gdx.input.isKeyPressed(Input.Keys.W))
	{
		removeBlock(camera.position, bDown, bLeft, bRight);
	}
		
	if (Gdx.input.isKeyPressed(Input.Keys.R))
		camera.zoom = 1;
	if (Gdx.input.isKeyPressed(Input.Keys.MINUS))
		camera.zoom += 3.0f;
	if (Gdx.input.isKeyPressed(Input.Keys.I))
		camera.zoom -= 3.0f;

	if (Gdx.input.isKeyPressed(Input.Keys.LEFT)) {
		bRight = false;
		bDown = false;
		player.moveRight(1);
		Vector3 po = new Vector3(camera.position);
		po.x-=2;//TILEWIDTH;
		po.y-=4;//TILEHEIGHT/2;
		if(checkCollision(po)) {
			camera.position.x -= 1;  // scroll map left
			bLeft = false;	
		}
		else // collision, move up
		{
			if(displayBlockDiagAbove(false,camera.position))
			{
				bLeft = true;
				camera.position.y += 2;
			} else
			{
				bLeft = false;
			}
		}
	}
	
	if (Gdx.input.isKeyPressed(Input.Keys.RIGHT)) {
	
		bLeft = false;
		bDown = false;
		player.moveRight(1);
		Vector3 po = new Vector3(camera.position);
		po.y-=4;//TILEHEIGHT/2;
		
		if(checkCollision(po)) {			
			camera.position.x += 1; // scroll map right
			bRight = false;
		}
		else // collision - how do we go up - go up until no collision
		{	
			// is it clear above block? (water, cave, blank)
			if(displayBlockDiagAbove(true,camera.position))
			{
				bRight = true;				
				camera.position.y += 2; // scroll map up
			}
			else
			{
				bRight = false;
			}
		}
	} 
	
	// We need to do a jump - TO DO
	if (Gdx.input.isKeyPressed(Input.Keys.UP)) {
	}
	if (Gdx.input.isKeyPressed(Input.Keys.DOWN)) {
		bDown = true;
		bRight = false; bLeft = false;
	}
	if (Gdx.input.isKeyPressed(Input.Keys.PAGE_UP)) {
		camera.position.y += 200; // jump map up
	}
	if (Gdx.input.isKeyPressed(Input.Keys.PAGE_DOWN)) {
		camera.position.y -= 200; // jump map down
	}
	if (Gdx.input.isKeyPressed(Input.Keys.D)) {
		debug = true; // turn debug on - basically draw the whole map
	}
	if (Gdx.input.isKeyPressed(Input.Keys.F)) {
		debug = false; // turn debug off
	}

	camera.position.set(MathUtils.roundPositive(camera.position.x),
			MathUtils.roundPositive(camera.position.y),0);
	
	camera.update();

	// Calculate what we should draw
	int camX = (int) camera.position.x - SCREENWIDTH / 2;
	camX /= TILEWIDTH;
	int endX = SCREENWIDTH / TILEHEIGHT + camX;

	int camY = (int) camera.position.y - SCREENHEIGHT / 2;
	camY /= TILEHEIGHT;
	int endY = SCREENHEIGHT / TILEHEIGHT + camY;

	batch.setShader(ambientShader);

	batch.begin();

	
	// Draw the map - only draw what camera sees
	worldMap.drawMap(debug, batch, regions, camX - 2, camY, endX + 2, endY,
			WORLDWIDTH, WORLDHEIGHT);

	batch.end();

	// HUD - Draw hud (in our case some text!)
	Matrix4 uiMatrix = hudCamera.combined.cpy();
	uiMatrix.setToOrtho2D(0, 0, SCREENWIDTH, SCREENHEIGHT);
	batch.setProjectionMatrix(uiMatrix);
	hudCamera.update();

	
	// Draw player after we have drawn the world
	player.render(0);

	 
	batch.begin();
	drawCameraPosition(batch, camera.position);
	String pos = String.format("SteRraria V1.0");
	font.draw(batch, pos, 10, SCREENHEIGHT);

	this.drawFps(batch, fps);
	
	batch.end();
}

	@Override
	public void render() {

		Vector3 poss = new Vector3(camera.position);
		poss.y-=8;

		// Need to check if not jumping as we need to jump Y amount before any downward force happens
	 	if(!bLeft && !bRight)  // this needs fixing as doesn't happen when moving right
		{
	 		if(checkCollision(poss))
			{
				camera.position.y -= 3;  // scroll map down
			}
		}
		
		int fps = Gdx.graphics.getFramesPerSecond();
				
		Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
		 
		cloudBackground.render(0.05f, ambientShader);   // render clouds

		batch.setProjectionMatrix(camera.combined);

		if (Gdx.input.isKeyPressed(Input.Keys.W))
		{
			removeBlock(camera.position, bDown, bLeft, bRight);
		}
			
		if (Gdx.input.isKeyPressed(Input.Keys.R))
			camera.zoom = 1;
		if (Gdx.input.isKeyPressed(Input.Keys.MINUS))
			camera.zoom += 3.0f;
		if (Gdx.input.isKeyPressed(Input.Keys.I))
			camera.zoom -= 3.0f;
	
		if (Gdx.input.isKeyPressed(Input.Keys.LEFT)) {
			bRight = false;
			bDown = false;
			player.moveRight(1);
			Vector3 po = new Vector3(camera.position);
			po.x-=2;//TILEWIDTH;
			po.y-=4;//TILEHEIGHT/2;
			if(checkCollision(po)) {
				camera.position.x -= 1;  // scroll map left
				bLeft = false;	
			}
			else // collision, move up
			{
				if(displayBlockDiagAbove(false,camera.position))
				{
					bLeft = true;
					camera.position.y += 2;
				} else
				{
					bLeft = false;
				}
			}
		}
		
		if (Gdx.input.isKeyPressed(Input.Keys.RIGHT)) {
		
			bLeft = false;
			bDown = false;
			player.moveRight(1);
			Vector3 po = new Vector3(camera.position);
			po.y-=4;//TILEHEIGHT/2;
			
			if(checkCollision(po)) {			
				camera.position.x += 1; // scroll map right
				bRight = false;
			}
			else // collision - how do we go up - go up until no collision
			{	
				// is it clear above block? (water, cave, blank)
				if(displayBlockDiagAbove(true,camera.position))
				{
					bRight = true;				
					camera.position.y += 2; // scroll map up
				}
				else
				{
					bRight = false;
				}
			}
		} 
		
		// We need to do a jump - TO DO
		if (Gdx.input.isKeyPressed(Input.Keys.UP)) {
		}
		if (Gdx.input.isKeyPressed(Input.Keys.DOWN)) {
			bDown = true;
			bRight = false; bLeft = false;
		}
		if (Gdx.input.isKeyPressed(Input.Keys.PAGE_UP)) {
			camera.position.y += 200; // jump map up
		}
		if (Gdx.input.isKeyPressed(Input.Keys.PAGE_DOWN)) {
			camera.position.y -= 200; // jump map down
		}
		if (Gdx.input.isKeyPressed(Input.Keys.D)) {
			debug = true; // turn debug on - basically draw the whole map
		}
		if (Gdx.input.isKeyPressed(Input.Keys.F)) {
			debug = false; // turn debug off
		}

		camera.position.set(MathUtils.roundPositive(camera.position.x),
				MathUtils.roundPositive(camera.position.y),0);
		
		camera.update();

		// Calculate what we should draw
		int camX = (int) camera.position.x - SCREENWIDTH / 2;
		camX /= TILEWIDTH;
		int endX = SCREENWIDTH / TILEHEIGHT + camX;

		int camY = (int) camera.position.y - SCREENHEIGHT / 2;
		camY /= TILEHEIGHT;
		int endY = SCREENHEIGHT / TILEHEIGHT + camY;

		batch.setShader(ambientShader);

		batch.begin();

		
		// Draw the map - only draw what camera sees
		worldMap.drawMap(debug, batch, regions, camX - 2, camY, endX + 2, endY,
				WORLDWIDTH, WORLDHEIGHT);

		batch.end();

		// HUD - Draw hud (in our case some text!)
		Matrix4 uiMatrix = hudCamera.combined.cpy();
		uiMatrix.setToOrtho2D(0, 0, SCREENWIDTH, SCREENHEIGHT);
		batch.setProjectionMatrix(uiMatrix);
		hudCamera.update();

		
		// Draw player after we have drawn the world
		player.render(0);

		 
		batch.begin();
		drawCameraPosition(batch, camera.position);
		String pos = String.format("SteRraria V1.0");
		font.draw(batch, pos, 10, SCREENHEIGHT);

		this.drawFps(batch, fps);
		
		batch.end();
	}


Maybe I should introduce keys where you can move a rectangle over the block you want to remove?

Sorry, not got all the gfx etc in a repo.

Thanks


I use a top level class in my multidimensional array:

BlankEntity which has quite a few abstract methods in there of which other classes derive from, for instance WaterEntity, GrassEntity, CaveEntity - polymorphism used
here to make my code simple imo. By having map made up of BlankEntities and derived ones makes it more workable and allows other things to be done going forward.

Think the problem in the code is the bRight / bLeft not being set correctly, they seem to go back to false…

You really need to clean your code up and stop using all those “magic” numbers. Make constants, it’ll make your life so much easier. Don’t lump together collision detection and response for a player into your main render method? All those input checks should be distributed across multiple classes to clean your code up. What you have there is a mess of code that at one little change could possibly break very fast and be very confusing to pin-point your problem. Why are you using toString on every object to figure out what kind of object it is? Use the instanceof operator, at the very least.

Thanks for the advice…Opiop, yes, I should be doing as you say.

I can write clean code, this has just been put together rather quickly as don’t have much time to ‘design’ it with having full-time job, I’m well aware of SOLID principles, design patterns etc, just not got time to do.

I have a full-time job as well and I strongly believe in writing solid code no matter what. Take your time and slow down if need be, I understand how challenging it can be to code and also has a job. Some days I don’t get to write code, but on the days I do I write clean and concise code that I don’t have to later spend hours refactoring because I was rushing. There’s no use in having to do something twice when you can do it right the first time and be done with it.

Yeah, just take your time with it. It’s supposed to be a fun project.

And the problem is that you pass booleans into removeBlock(). The if statements that you use to set those booleans are overwriting each other

For example:

 
if (Gdx.input.isKeyPressed(Input.Keys.LEFT)) {
         bRight = false;
         bDown = false;

after you do:


if (Gdx.input.isKeyPressed(Input.Keys.RIGHT)) {      
         bLeft = false;
         bDown = false;

Then finally:


if (Gdx.input.isKeyPressed(Input.Keys.DOWN)) {
         bDown = true;
         bRight = false; bLeft = false;

Which overwrites both.

I would look into an InputListener instead of polling your input. You are missing tons of events this way.

Hi,

Thanks guys.

For input listener do you mean implement InputListener and override the methods in there?

Thanks

Yes, and also make sure to call:


Gdx.input.setInputProcessor(yourInputProcessor);

I work iteratively and start with a rough sketch in Java that mostly works, then I refactor it repeatedly and severely to get it to a “final” shape. I don’t believe in investing too heavily in the first draft because I’m just going to change it as my ideas evolve. It is also easier to build the final system if you have a rough and ready prototype that works.