feudalwars

Strike Tactics: A futuristic RTS made with Phaser.io

16 posts in this topic

Hi, I read about textures on your blog, but did not get it: " For the Strike Tactics map editor, I've devised a much better system. Instead of creating custom textures for each blended image, I create one single blended image from each texture, which is used as an overlay. The blended image is created in-engine from the base texture: "

Do you have to record every "stamp" of overlay texture in editor and then reproduce it in game? In game, do you have some base ground texture (made from tiles) and then you make stamps over it? For these stamps, do you have one big BMD as large as whole game map? Is there any problem with texture size?

 

Share this post


Link to post
Share on other sites
3 hours ago, Tom Atom said:

Hi, I read about textures on your blog, but did not get it: " For the Strike Tactics map editor, I've devised a much better system. Instead of creating custom textures for each blended image, I create one single blended image from each texture, which is used as an overlay. The blended image is created in-engine from the base texture: "

Do you have to record every "stamp" of overlay texture in editor and then reproduce it in game? In game, do you have some base ground texture (made from tiles) and then you make stamps over it? For these stamps, do you have one big BMD as large as whole game map? Is there any problem with texture size?

 

I use a base texture system. So every map starts out with a base texture and when you go to create a new map (with the map editor), you choose a base texture. Then when you want to draw another texture onto the map, it works exactly like a stamp. A single BMD is created not the size of the game world, but the size of the stamp. Imagine you have a 1024 x 1024 texture in photoshop, and you use the eraser tool to make the edges partially transparent. That's what i do with the BMD. The BMD is then drawn into the game world, when you click on an area of the map, by converting the base textures (which are normal Phaser.Images) into render textures and rendering on top. If the stamp intersects more than 1 tile, it will draw on multiple tiles. If you select a new texture, a new stamp is created using the same BMD.

Then, when you save and load the map, everything can be procedurally recreated as the stamp locations are simple x/y coordinates. There is never any problem with texture size as I never create anything larger than the base texture size (1024). 

Share this post


Link to post
Share on other sites

@feudalwars thanks for explanation. It sounds easy, but the result is really impressive!

Hmmm... also some of your stamps may need compostion from up to 4 parts of texture used as overlay if in corner? Stamp placed at positon 0,0 draws different part of texture than stamp of the same size at position 100,100 - it means you have to change BMD quite often when recreating map? On the other hand, it is during some initilaization part and not during game.

How many base textures form one level background? Single 1024 x 1024 RGBA texture eats 4MB and as it looks your game targets desktops with large monitors, you will have to to place at least 4x4 to form one level (= 64MB).

Share this post


Link to post
Share on other sites
22 hours ago, Tom Atom said:

@feudalwars thanks for explanation. It sounds easy, but the result is really impressive!

Hmmm... also some of your stamps may need compostion from up to 4 parts of texture used as overlay if in corner? Stamp placed at positon 0,0 draws different part of texture than stamp of the same size at position 100,100 - it means you have to change BMD quite often when recreating map? On the other hand, it is during some initilaization part and not during game.

How many base textures form one level background? Single 1024 x 1024 RGBA texture eats 4MB and as it looks your game targets desktops with large monitors, you will have to to place at least 4x4 to form one level (= 64MB).

> it means you have to change BMD quite often when recreating map?

Because it is all procedural, there are ways to avoid this. such as drawing all textures that use 1 BMD first, then drawing all textures that use a different BMD. Drawing the z-index (vertical stack) in order, etc. Generally, I don't use more than 3 different textures on a map, it doesn't add that much to the aesthetic (in fact most of the maps in the trailer use only 1 texture). But even if I use 10 different textures, it doesn't add much to load time or affect performance. The BMD only needs to be created once for each texture. Rendering to render textures does most of the heavily-lifting of map creation, and render textures are extremely fast (much more so than BMDs). 

4x4 what, you mean tiles?

Without auto-culling Pixi can easily handle 15 x 15 (225 tiles), let alone 4 x 4 (16 tiles), at least on CPUs with good graphics cards. With auto-culling, even old computers with bad cards can handle 225 tiles, such as my 8-year-old iMac. 

Computers with good graphics cards, with auto-culling, can handle map sizes 100,000 pixels wide/high. That's 10 billion pixels. It's not practical for gameplay, and can slow things down, but it is possible. And that is tested in Chrome, FF and IE, in both Canvas and Webgl.

 

 

Share this post


Link to post
Share on other sites

@feudalwars Voted on Greenlight! :)

Thanks for explanation. Originally I made it wrong - i thought, you are creating BMD for every single recorded editor stroke, but I hope, I understand it now. Below is how I understand it now.

 Let's say your world has basic texture grass and there are small places with sand. Your textures looks like this:

Grass.png.2df4b507463a14d136d53199640122dd.pngSand.png.871c25290d04144a2b498af95f05ca92.png

 Whole world looks like this - it is made from 2x2 tiles:

Map.png.586a642213c709efe4d4a9d13ce10a8c.png

So in your data 2 strokes of sand are recorded. You have to create BMD for top left and top right tiles. BMD for top left is created like this:

Sand.png.871c25290d04144a2b498af95f05ca92.pngMask1.png.eb3ea1c37c099a96b001353b55c636d0.png = BMD_temp.png.499c1cd1f23b8a3fd85f26998c979b0e.png

BMD_temp.png.499c1cd1f23b8a3fd85f26998c979b0e.png+ ( Sand.png.871c25290d04144a2b498af95f05ca92.pngMask2.png.60f9a7881d3035f6de0bf2d8f2f9626d.png ) = BMD.png.3a16aca0423a6c8eb36fd8503bee87ea.png

Last image is your BMD for top left tile reconstructed from individual editor strokes. (For masking, do you use standard BitmapData.alphaMask? http://phaser.io/examples/v2/bitmapdata/alpha-mask)

During runtime, you take grass tile and draw this BMD over it.

 

20 hours ago, feudalwars said:

4x4 what, you mean tiles?

Yes, but I originally thought, you are creating individual RenderTexture for every single grass tile and "patching" it with editor strokes (one by one) before game is run. It would create unique patched grass tile, which would not be reusable anywhere else on map. You would then need lots of them and it would quickly exhaust texture memory. Now, if I made it right, I understand, that you create RenderTexture, draw original grass tile into it and then patch it with correct BMD for given tile.

 

 

Share this post


Link to post
Share on other sites
23 minutes ago, Tom Atom said:

@feudalwars Voted on Greenlight! :)

Thanks for explanation. Originally I made it wrong - i thought, you are creating BMD for every single recorded editor stroke, but I hope, I understand it now. Below is how I understand it now.

 Let's say your world has basic texture grass and there are small places with sand. Your textures looks like this:

Grass.png.2df4b507463a14d136d53199640122dd.pngSand.png.871c25290d04144a2b498af95f05ca92.png

 Whole world looks like this - it is made from 2x2 tiles:

Map.png.586a642213c709efe4d4a9d13ce10a8c.png

So in your data 2 strokes of sand are recorded. You have to create BMD for top left and top right tiles. BMD for top left is created like this:

Sand.png.871c25290d04144a2b498af95f05ca92.pngMask1.png.eb3ea1c37c099a96b001353b55c636d0.png = BMD_temp.png.499c1cd1f23b8a3fd85f26998c979b0e.png

BMD_temp.png.499c1cd1f23b8a3fd85f26998c979b0e.png+ ( Sand.png.871c25290d04144a2b498af95f05ca92.pngMask2.png.60f9a7881d3035f6de0bf2d8f2f9626d.png ) = BMD.png.3a16aca0423a6c8eb36fd8503bee87ea.png

Last image is your BMD for top left tile reconstructed from individual editor strokes. (For masking, do you use standard BitmapData.alphaMask? http://phaser.io/examples/v2/bitmapdata/alpha-mask)

During runtime, you take grass tile and draw this BMD over it.

 

Yes, but I originally thought, you are creating individual RenderTexture for every single grass tile and "patching" it with editor strokes (one by one) before game is run. It would create unique patched grass tile, which would not be reusable anywhere else on map. You would then need lots of them and it would quickly exhaust texture memory. Now, if I made it right, I understand, that you create RenderTexture, draw original grass tile into it and then patch it with correct BMD for given tile.

 

 

You're getting closer! Here are the differences. 

1. Instead of using a bitmap alpha mask, I first draw the texture onto the bitmap, then draw another texture with destination-out. This other texture look like this:

brush2_h2.png.67b9d93033b01601da46f5ce493d372b.png

The black parts will show the texture, transparent parts will draw transparency. the end result is something that blends quite well and can be used as an overlay. 

2. I don't need to create two BMDs for the top-left and top-right tiles like in your example, I only need to create one. Because it is anchored in the exact center, I only need to figure out the relative positions to draw that single overlay on each of the intersecting tiles.

        var relX = worldX - spriteX;
        var relY = worldY - spriteY;

SpriteX/Y are the base tiles x/y. 

Suppose the user clicks an area that intersects 4 base tiles. A piece of the overlay will be rendered on each of the 4 tiles using relative positioning on each, but it is all drawn from the same BMD. 

Share this post


Link to post
Share on other sites
32 minutes ago, feudalwars said:

Suppose the user clicks an area that intersects 4 base tiles

Thanks! Yes, I understand this for editor - you have to create BMD for every new user x/y position to take correct area from another texture, but you can paste it accross multiple tiles. So, your BMD in editor can cross tiles boundaries. And also BMD in editor is limited to single stroke at time - when user moves mouse to make another click, you have to update BMD with new area mouse cursor is at.

But in game? BMD in game has the same boundary as tile and contains all recorded strokes for that tile (recreated from map data)? So you can make final tile like drawing basic tile and then put single BMD with all strokes over it at once?

Share this post


Link to post
Share on other sites
27 minutes ago, Tom Atom said:

Thanks! Yes, I understand this for editor - you have to create BMD for every new user x/y position to take correct area from another texture, but you can paste it accross multiple tiles. So, your BMD in editor can cross tiles boundaries. And also BMD in editor is limited to single stroke at time - when user moves mouse to make another click, you have to update BMD with new area mouse cursor is at.

But in game? BMD in game has the same boundary as tile and contains all recorded strokes for that tile (recreated from map data)? So you can make final tile like drawing basic tile and then put single BMD with all strokes over it at once?

Nope, I only need to create 1 BMD for all textures and draw to it once when a user selects a different texture than the one already being used.

1. A Single BMD for ALL textures: when a new texture is clicked, I don't create a new BMD, that would be wasteful. Clearing and redrawing the same BMD I used on the previous texture is far more efficient. You'll run into a memory bottleneck if you continually create new BMDs, instead clear and redraw the same BMD for every texture, whenever you need it. One BMD to rule them all!

2. Draw to the BMD only once: I think you may have missed something from my post above. There is no need to redraw the BMD for every new stroke. Once you've created that overlay, and anchored it in the exact center, all you need is to calculate the correct relative position when it is drawn to a render texture. For example:

Suppose my map size is 100 x 100 and 10 x 10 pixels for each tile. The user clicks to place a texture at (45,0). This intersects two tiles: [tile #4 on X and #1 on Y] and [tile #5 on X and #1 on Y]. Both tile #4 and #5 are converted into render textures and the base texture is drawn on top of each. A BMD is then drawn to create the overlay, which is anchored at (.5,.5). The overlay is drawn on top of both render textures, but in different positions:

Tile #4 is at 40,0 and Tile #5 is at 50,0 (tile anchors are 0,0)

Therefore, when the BMD is rendered to the render texture (tile #4), it is rendered at:

X: (45 - 40) = 5

Y: (0 - 0) = 0

So, (5,0), and this is using the simple formula (to calculate the point the user clicks relative to the tile instead of the game world).

At tile #5, it is rendered at:

X: (45 - 50) = -5

Y: (0 - 0) = 0

(-5,0). Ultimately, we've drawn to the BMD only once and rendered it to 2 different render textures.

  

Tom Atom likes this

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.