Need Help With My 2D Tile Engine

Alright I have redid my game engine twice now. First it was stored in a array of ints, then strings, and now its an array of the block class. But I hit a couple snags. It won’t show any tiles when I make a view port around my character and I have a feeling it is similarly related to why no blocks show up after the dirt ages and turns into grass. I was watching a tutorial on making a platformer and saw a guy use a block class that extended rectangle and I thought I could get more functionality of the blocks this way. Now each is able to age and store data that I couldn’t do before. Like I’ve said I have done tile maps before but I never tried with this approach.

This is my WorldGen code with it actually showing tiles and the render method down there has the commented out view port code that doesnt work for whatever reason.

;

import java.awt.Graphics;
import java.awt.Rectangle;

public class WorldGen{
	
	byte tileSize = 25;
	int worldSize = 1000;
	
	Block[][] block = new Block[worldSize][worldSize];

	
	public WorldGen()
	{
		for(int y = 0; y < worldSize; y++)
		{
			for(int x = 0; x < worldSize; x++)
			{
				block[x][y] = new Block(new Rectangle(x * tileSize, y * tileSize, tileSize, tileSize), "dirt"); // Makes all blocks dirt
			}
		}
	}
	
	public void tick() //Updates blocks I didn't check to see if this worked or not and im sure the little buffer to updating the tiles around you might not work out so well
	{
		for(int y = PlayerChar.playerY - GameMain.yBuff - 20; y < PlayerChar.playerY + GameMain.yBuff + 20; y++)
		{
			for(int x = PlayerChar.playerX - GameMain.xBuff - 20; x < PlayerChar.playerX + GameMain.xBuff + 20; x++)
			{
				block[x][y].tick();
			}
		}
	}
	
	public void render(Graphics g)
	{
		
		for(int y = 0; y < 100; y++) //Kinda Working Graphics
		{
			for(int x = 0; x < 100; x++)
			{				
				block[x][y].render(g, x * tileSize, y * tileSize, tileSize, tileSize);
			}
		}
		
		/*for(int y = PlayerChar.playerY - GameMain.yBuff; y < PlayerChar.playerY + GameMain.yBuff; y++) // Not Working
		{
			for(int x = PlayerChar.playerX - GameMain.xBuff; x < PlayerChar.playerX + GameMain.xBuff; x++)
			{				
				block[x][y].render(g, x * tileSize, y * tileSize, tileSize, tileSize);
			}
		}*/
	}
	
	
}

Heres the block code I hope it makes sense but I never used things like set bounds before and what not so I could be not grasping how this all works at the moment. Have it go around 30 fps to 60 running it full tilt will make the grass grow way to quick.


import java.awt.Graphics;
import java.awt.Rectangle;
import java.util.Random;

@SuppressWarnings("serial")
public class Block extends Rectangle{
	
	int randomAgeModifier = new Random().nextInt(5000); // I try to make my variables very self descriptive
	int age = 0;
	String blockDescriptor = null;
	String blockType = null;
	
	public Block(Rectangle size, String type) // Constructor
	{
		setBounds(size);
		blockType = type;
		getDescriptor(type);
		
	}
	
	public void tick() //Updert
	{
		age++;
		age();
	}
	
	public void age() // Ages the tiles should make sense there is a random number tacked on so they dont all start poppin up at the same time.
	{
		if(blockType == "dirt" && age > (randomAgeModifier + 4000))
		{
			blockType = "grass";
			getDescriptor("grass");
			randomAgeModifier = new Random().nextInt(4000);
			age = 0;
		}else if(blockType == "grass" && age > (randomAgeModifier + 8000))
		{
			blockType = "denseGrass";
			getDescriptor("denseGrass");
			randomAgeModifier = new Random().nextInt(4000);
			age = 0;
		}		
	}
	
	public void getDescriptor(String type) //Gives a descriptor to the block so if I put them together with an examine option it would give somthing like You look at the green grass blah blah blah
	{
		switch(type)
		{
		case "dirt":
			this.blockDescriptor = "brown";
			break;
		case "grass":
			this.blockDescriptor = "green";
			break;
		case "denseGrass":
			this.blockDescriptor = "darkGreen";
			break;
		}
	}
	
	

	
	public void render(Graphics g, int x, int y, int width, int height) // Draws Blocks with custom colors.
	{
		switch(blockDescriptor)
		{
		case "brown":
			g.setColor(GameRender.brown);
			break;
		case "grass":
			g.setColor(GameRender.yellowGreen);
			break;
		case "denseGrass":
			g.setColor(GameRender.grassGreen);
			break;
		}
		
		g.fillRect(x, y, width, height);
		
		g.setColor(GameRender.gridGray);
		g.drawRect(x, y, width, height); // Just makes a gray outline of each tile
	}
}

Drop those if-statements inside the block class. Instead, replace the whole block with a new object when time comes. Create some kind of watcher class which does the job.
Do not inherit from Rectangle but add a property for the rectangle boundary. Probably you will get along with one block class and different color or image attributes.

I’m going to be trying to fix this still but I’m going to need you to elaborate a little more as well. So make a separate class with a method that can check the age and determine what it should be if it returns true make a new block with the type and attributes? And have it in the for block, in the worldmap.render method?

I guess I don’t need to inherit Rectangle since I usually had the x , y of the for loop to choose which block, and moved the blocks real chords by adding the tilesize.

	int moveX = 0, moveY = 0;
	for(int y = (PlayerChar.playerY - GameMain.yBuff) + 1; y < PlayerChar.playerY + GameMain.yBuff + 5; y++)
	{
		for(int x = (PlayerChar.playerX - (90/Tiles.tileSize)/2)- GameMain.xBuff; x < PlayerChar.playerX + GameMain.xBuff - ((90/Tiles.tileSize)/2) + 5; x++)
		{
			GameMain.tiles.drawTile(g, moveX, moveY, map[x][y]);
			moveX += Tiles.tileSize;
		}
		moveX = 0;
		moveY += Tiles.tileSize;
	}

The rectangle thing sounded neat but I guess its the same thing maybe.

Yes. Changing object behaviour with if-statements is often a sign of missing design to benefit from inheritance, object composition, polymorphism, etc.

No, do it before. Modifying the game world is game logic. Rendering should, well, render. Clearly assign tasks and do not mix them.

Man wasted my time dickin around with this for a whole day…


switch(blockDescriptor)
      {
      case "white":   // <<<<<< Color
         g.setColor(GameRender.white);
         break;
      case "brown": // <<<<<<< Color
         g.setColor(GameRender.brown);
         break;
      case "grass": // <<<<<<< A whole day wasted
         g.setColor(GameRender.yellowGreen);
         break;
      case "denseGrass": // <<<<<<< A whole day wasted
         g.setColor(GameRender.grassGreen);
         break;
      }

Duh x 2 My playerX and Y along with the buffers are divided by tileSize already, so I needed to use the moveX and Y that I showed earlier. I guess I just needed some sleep lol.


int moveX = 0, moveY = 0; // Needed this afterall
for(int y = PlayerChar.playerY - GameMain.yBuff; y < PlayerChar.playerY + GameMain.yBuff; y++)
      {
         for(int x = PlayerChar.playerX - GameMain.xBuff; x < PlayerChar.playerX + GameMain.xBuff; x++)
         {   
            block[x][y].render(g, moveX, moveY); // Not block[x][y].render(g, x * tileSize, y * tileSize);
				moveX += tileSize; //Needed this too
         }
			moveX = 0; // <<< These too \/\/\/
			moveY += tileSize;
      }

Now to fix all my tiles for the old engine to work with the new one.