[Slick2d] Retro-Pixel Castles > Now on Steam! <

My best guess is you should be fine, because the biggest resource hog I have right now is rendering all the little 8x8 tiles. Because the game is an 8x8 tile based game, at full 1080p (operating at 640x360, since the game is scaled x3) there’s up-to 3600 tiles per layer rendered on screen at once. At 1440x900 there would only be 2250 per layer.

The engine is rendered at a fixed 1:3 scale regardless of the resolution. So a bigger screen wont make the images larger, it’ll just let you see more of the screen all at once. (Like the old Roller Coaster Tycoon games if you played them)

Not to mention I also haven’t put in that last tweak yet that should greatly drop the amount of tiles needing rendered in complex environments. :smiley:

Progress continues on the map editor!

  • New terrains, including water!
  • The minimap is fully functional!
  • Terrain transitions complexity increased, now even more natural looking terrain can be quickly drawn.
  • Many GUI changes
  • Bunch of optimizing, the engine runs even faster now.
  • Untested, but should now be running on Macs.

http://sixtygig.com/junk/InDev-2014-05-23-4.png

http://sixtygig.com/junk/InDev-2014-05-23-5.png

http://sixtygig.com/junk/terrainDrawing1.gif

It’s amazing :o
Nice work :smiley:

The map editor GIF looks actually very good!
Very smooth shaping, congratulations!

That smooth shaping looks like the Terraria game, good job! Now I have to look up how to do this…

After making all the drawing all the required terrain transitions tiles, you have to setup a way to check the 8 tiles around the tile you placed when you place it and change that one tile accordingly, I did it by building a small string of numbers like, say this for example:

111111000
…or… when broken down it looks like this
111
111
000

Basically every “1” is where a tile is the same terrain type as the one you just placed, every “0” is a empty spot, or an unmatching tile. Then, depending on the arrangement of the string of numbers (I used an int btw, not an actual String) you tell the engine what type of transition tile it should put there. Keep in mind the center “1” is your tile being checked. So in this case, it would of be converted to a down facing straight transition tile.

Where as something like this would have become a south west corner transition.:
011
011
000

Eventually after you hammer out every single possible variation that could exist, and code in a very fast way to do the checks, you’ll end up with what I have. :smiley:

One critical step is to make a “no valid connection at all” terrain tile (note my little tree “dots” in the gif) because there will be some illegal transitions that are impossible unless you want to make like 30 more texture transition variation possibilities. You’ll see when you get there, but there’s many very awkward transitions that require very awkward tiles, like this for example:
111
111
010
What do you do with that? Now you need a T-joint thing. In my game, in this situation the center just becomes the same tile as in my first example (Straight down facing transition)

…and the oddball 1 in the bottom row, does it’s check and it sees this …so it becomes an “illegal transition” and becomes a single stand alone texture:
111
010
000

So while I could make transitions for these situations as well, you get to a point where it’s just overkill.

Here’s one of my terrains, if you want to see how many transition tiles each of my terrains have. Only the top row is important, I just added texture variations on top of all this. But it’s not required.

http://sixtygig.com/junk/terrainTransitionExample1.png

EDIT: I think the theory behind this a lot of people may miss is they probably think you need to check the entire terrain/map as a whole, you really don’t. You only need to check each tile 1 by 1 and the 8 tiles around it, if it’s done correctly all the tiles will end up lining up perfectly… being completely unaware of the rest of the map, just the 8 tiles around it.

What is your code for doing the transitions? There was a good tutorial that I found (though I can’t find it again) that explained how to use powers of two. You would give each tested area a different power of two, then that would give you a unique number from which you would get a portion of the texture.


// The tile you are testing is map[1][1], and tiles are stored as 1 (same type), or 0 (empty or different type)
// 011
// 011
// 000
int transition = map[0][0] + 2 * map[0][1] + 4 * map[0][2] + 8 * map[1][0] + 16 * map[1][2] + 32 * map[2][0] + 64 * map[2][1] + 128 * map[2][2]
texture = getTexture(0, transition * textureSize);

heh, my way is embarrassing looking, I’ll be honest. :stuck_out_tongue:

The code is too complicated to explain in it’s current state (because it accounts for random textures, tile ranges and a mess of other things) but here’s a slight rewrite. Without my extra data this might actually be forloopable or simply compressed into a single line like your’s is. My original code can’t due to too many special rules/situations in the check though.

Note that my entire map is stored in a 3D int array; mapArray[tileX][tileY][layer]. So the mapArray parts will have to be however you fetch the tileId you’re checking against.

All we’re doing here is checking all possible tiles away from the center one, and also marking the center tile “1” every time (because it’s always 1). In mine, you’d actually generate an int with a 2 on the front, only because it’s easier to just pre-init the int with something in this situation. Basically it starts from the top left tile, moving across, jumps one row down, repeats, jumps one row down, repeats. Every check multiples the value by 10 or multiplies by 10 and adds 1. When it multiplies by 10, it’s basically just adding a 0 on the end of the int… or, if a tile is found multiplies by 10 and converts the 0 to a 1 by adding 1 to the entire value, a tile was found.

It’s pretty messy looking, but it works amazingly fast considering how fugley it looks, and in this situation that’s extremely important because you may be running a few dozen of these checks all at once if you’re checking multiple layers or using a large terrain brush.


		int tileRange = mtl.getTileSetFirstGID((getTileId(tileX, tileY, layer))); //Fetch the first tileId in the sheet you're checking.
		int tileCheck = 2; //init the int
		int tileSetSize = 200; // The total size of the sheet. (how many GIDs exist)

		//EXAMPLE OF WHATS GOING ON BELOW
		//if ((mapArray[tileX-1][tileY-1][layer] < tileRange) || (mapArray[tileX-1][tileY-1][layer] > tileRange+tileSetSize)){ // If the tile you're checking is NOT between your start GID and the length of the tileSet.
		//	tileCheck = (tileCheck * 10); // Multiply by 10, basically adding a zero at the end claiming no tile was found.
		//}else{
		//	tileCheck = (tileCheck * 10) + 1; //A tile was found, multiply by 10 and add 1.
		//}


		if ((mapArray[tileX-1][tileY-1][layer] < tileRange) || (mapArray[tileX-1][tileY-1][layer] > tileRange+tileSetSize)){
			tileCheck = (tileCheck * 10);}else{tileCheck = (tileCheck * 10) + 1;}
		if ((mapArray[tileX][tileY-1][layer] < tileRange) || (mapArray[tileX][tileY-1][layer] > tileRange+tileSetSize)){
			tileCheck = (tileCheck * 10);}else{tileCheck = (tileCheck * 10) + 1;}
		if ((mapArray[tileX+1][tileY-1][layer] < tileRange) || (mapArray[tileX+1][tileY-1][layer] > tileRange+tileSetSize)){
			tileCheck = (tileCheck * 10);}else{tileCheck = (tileCheck * 10) + 1;}
		if ((mapArray[tileX-1][tileY][layer] < tileRange) || (mapArray[tileX-1][tileY][layer] > tileRange+tileSetSize)){
			tileCheck = (tileCheck * 10);}else{tileCheck = (tileCheck * 10) + 1;}
		tileCheck = (tileCheck * 10) + 1;
		if ((mapArray[tileX+1][tileY][layer] < tileRange) || (mapArray[tileX+1][tileY][layer] > tileRange+tileSetSize)){
			tileCheck = (tileCheck * 10);}else{tileCheck = (tileCheck * 10) + 1;}
		if ((mapArray[tileX-1][tileY+1][layer] < tileRange) || (mapArray[tileX-1][tileY+1][layer] > tileRange+tileSetSize)){
			tileCheck = (tileCheck * 10);}else{tileCheck = (tileCheck * 10) + 1;}
		if ((mapArray[tileX][tileY+1][layer] < tileRange) || (mapArray[tileX][tileY+1][layer] > tileRange+tileSetSize)){
			tileCheck = (tileCheck * 10);}else{tileCheck = (tileCheck * 10) + 1;}
		if ((mapArray[tileX+1][tileY+1][layer] < tileRange) || (mapArray[tileX+1][tileY+1][layer] > tileRange+tileSetSize)){
			tileCheck = (tileCheck * 10);}else{tileCheck = (tileCheck * 10) + 1;}

once you have that, it’ll built your int string (keep in mind, it’ll be something like 2111111000 instead of 111111000) because that 2 is still there. But you can now use that built number string to compare to situations and decide what tile belongs there.

EDIT: Code slightly cleaned up for clarity

Game can haz logo now?

http://sixtygig.com/junk/retroPixelLogo5.png

I just want to say that you have real talent when it comes to pixel art. Keep up the good work man.

Thanks! I love drawing this stuff, I think seeing it all come together is massively rewarding. :slight_smile:

The first tutorial that comes to my mind is this one.
Is that the tutorial you had in mind? :slight_smile:

This looks awesome, nice graphics. :slight_smile:
I too is working on a top down strategy game.

Yes, that’s the one. Thanks for finding it :slight_smile:

Hey! That’s one of the tutorials I found too when looking up ideas on how to do mine. I ended up going with my own method though, as far as I know there’s no tutorial for it. I can’t imagine I’m the first person to come up with the idea though. It’s not exactly groundbreaking. :stuck_out_tongue:

Here’s a method similar to mine I just found, it’s an interesting concept. Basically involves assigning a value to each corner of each tile. This has the potential to be faster than my method, but I think to implement it correctly you’d need a byte[][] array that’s 4 times larger than your entire map. At least, that’s where I’d start before attempting to optimize. Because assigning the 4 bit value to each tile on the fly seems like it would be painfully slow. It would make more sense to always have the data stored somewhere to recall.

Was working on optimizing the lighting system so the lighting map can be updated on-the-fly a bit faster, thought it would be a good time to show off the lighting working in-game with the new lava texture. :slight_smile:

(…and despite appearances, this is 100% shader free :stuck_out_tongue: )

http://sixtygig.com/junk/retrocastlelighting1.gif

You’re definitely the modest one, aren’t you? :smiley:
That said, very nice work.

I may have to write a tutorial on it later, it’s a bit too complicated to go into without pictures, and as far as I know there’s no tutorials anything like it on line. I’m not even entirely sure how to explain it without visuals. :confused:

It’s actually not that complicated of a concept, I just can’t think up how to explain how it works without a long detailed tutorial.

Hey, I am wandering how you coded placing in lots of entities?

Did you makes an array and fill it with entries of random positions or did you hard code?

I am talking about the picture that has lots of entities in it

It’s an ArrayList of entity objects, right now (since it’s just mostly testing) entities just randomly pop up somewhere on the map when created. So if I add 500 entities to the ArrayList they just set their X/Y coordinates to (random.nextInt(mapWidth)*tileWidth, random.nextInt(mapHeight)*tileHeight) on creation. (EDIT: there’s also a second check that makes sure they dont spawn in a wall or something, if that happens it just recycles and tries again)

End product obviously wont work that way though. :stuck_out_tongue: