2
\$\begingroup\$

I'm currently playing around with a base builder/manager-esque type of game similar to Evil Genius. To build a room I would like to have the following process: 1. Select room type 2. Click and hold the mouse. Drag to create a rectangle over the area. 3. On release, place entire room.

I have already implemented this, but I find it inefficient and I would like to improve it. As of now the indicator rectangle is simply a sprite that is scaled and moved to fit. I would, however, like to have the indicator rectangle to be "adaptive". Meaning that if I drag a placement rectangle over an invalid area the indicator will be red at that point.

To do this I figured I could go with some sort of loop. I.e. "A change in rectangle size noticed. Update all new indicator tiles with correct colour". I had all the pseudo code figured out, but then I realised instantiating a number of gameobjects would be kinda inefficient. If the player is making a large rectangle in a short amount of time, that would surely slow down the game? Is there any other way to solve my problem, or is this the most efficient solution?

I should note that this build system is grid based. Each tile has a coordinate given by two integers and is saved in a 2D array. You can easily access the array and see what tile is at any given point or find the coordinate of any tile.

\$\endgroup\$
  • \$\begingroup\$ Dont check on every frame? \$\endgroup\$ – HgMerk Jun 3 '15 at 17:23
0
\$\begingroup\$

There's a trick to this:

Selecting Areas:

As you move the mouse, the only tiles you need to check for new impassable tiles are the newly highlighted tiles. If the mouse is dragged from X=25 to X=26, then you only need to iterate over the tiles at the X=26 column from the Y of the starting tile to the Y of the tile the mouse is over. The worst case scenario is you cross both X and Y axis, in which case you will only iterate over L+W-1 tiles.

Deselecting Areas:

The catch is if the player selects a large valid area, crosses an invalid tile, then backs off of it to go back to the large valid area he had a moment before.

To keep from having to check the entire space when your area shrinks, keep track of how many impassable tiles were crossed as you cross them. Then when bounds change, subtract the number of impassables that were in the column or row that was deselected. As soon as your impassable count is 0, you no longer need to check so long as the selected area is shrinking.

This still ensures you never iterate over more than L+W-1 tiles at any time.

Highlighting:

While Selecting areas, as you iterate over, spawn a red rectangle at the location of the impassable tile you are currently looking at. Store them in a 2D array for when you need to remove them. You could do some magic and scale a single rectangle for contiguous blocks of impassables with a little thought.

While Deselecting areas, iterate over the column or row in the 2D array mentioned above and remove any object found in the row or column. this will be fast, as you know the column or row you're looking at, and since most will be empty, they will more or less be skipped.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.