Airships Engine

A buildable airship thingy engine that I made as a proof of concept.

I’ve had a few errors.

I’m wondering how I can make the engine check if a block is connected to the ship or not. If it’s not, delete it. I’ve already attempted it with collisions and keep getting a NullPointerException. Maybe there is a way to do this without collisions. IDK

I encourage you guys to take the source and play with it. Make it better! And then post your version down below so I know the most efficient way to do this. Maybe you don’t want to have to edit the code and compress all the .java files and send the code back to me, still post below with your code ideas. Any post helps. [sup]Besides the posts that don’t help![/sup]

Here is the windows only version: https://dl.dropboxusercontent.com/s/0i7desm3ercwc3n/Airships_Test_v0.1.0.jar?dl=1&token_hash=AAFEeV1-hixDQN3sRpsXGQiRc723M-m2kb-VWMRnhsk-Hg

Here is the source: https://dl.dropboxusercontent.com/s/gvunr8injpjdw7i/Airships_src.zip?dl=1&token_hash=AAF25V0mFFBuifL8G73jY5jl-eb3TkN7oY2WncmFSYP06Q

Enjoy!

For determining blocks that are apart of the ship you could use the algorithm I used to identify islands for the RTS i am currently making.

Note that i do not know the algorithm’s name as i derived it myself:

  1. determine whether the cell at 0,0 is either ship or non ship, record this as the region type
  2. scan your grid left to right. for each cell:
    1a. check to see if the cell’s region type does not match the recorded region type. If it does not then:
    1aa. update the recorded region type
    1ab. increment the master id
    1ac. set the current region id to the master id
    1ad. set the initial regionIdMapping entry for this id to be this id.
    1b. check to see whether the cell above’s region type matches the recorded region type. If is does then:
    1ba. set the current region id to the regionIdMapping entry of the region id of the cell above.
    1bb. check to see whether the cell to the left’s region type matches the recorded region type. If is does then:
    1bba. iterate over the regionIdMapping entries and update those entries who map to the left cell’s region id to be now mapped to the current region id.
    1c. update the current cell’s region id to be that of the current region id.
  3. scan your grid left to right. for each cell:
    2a. consolidate the associated region ids by setting each cell’s region id to the regionIdMapping entry of the cell’s region.

This is implemented in my code as below:


			/**
			 * Region identification
			 */
			int id = 0;
			int masterId = 0;
			int regionType = improvements[0][0] & LAND_FLAG;
			int[] regionSize = new int[MAX_POTENTIAL_REGIONS];
			int[] cellRegionMapping = new int[MAX_POTENTIAL_REGIONS]; // TODO use temp[]

			for (j = 0; j < MAP_SIZE; j++)
			{
				for (i = 0; i < MAP_SIZE; i++)
				{

					// if the current region type does not match cell type then
					// set region type to the opposite type and update the
					// current region id
					if ((improvements[i][j] & LAND_FLAG) != regionType)
					{
						regionType = improvements[i][j] & LAND_FLAG;
						id = ++masterId;
						cellRegionMapping[id] = id;
					}

					// check to see whether the cell above is the same region
					// type. If so then set the current region id to the that
					// cell's mapped region id
					if (j > 0 && (improvements[i][j - 1] & LAND_FLAG) == regionType)
					{
						id = cellRegionMapping[region[i][j - 1]];
						if (i > 0)
						{
							int otherId = region[i - 1][j];

							// if the cell to the left is the same region type
							// then ensure that any references to region id of
							// that cell point to the current id.
							if ((improvements[i - 1][j] & LAND_FLAG) == regionType)
							{
								for (k = 0; k < MAX_NO_POTENTIAL_REGIONS; k++)
								{
									if (cellRegionMapping[k] == otherId)
									{
										cellRegionMapping[k] = id;
									}
								}
							}
						}
					}

					// set the region id for the cell
					region[i][j] = id;
				}
			}

			// using the map of associated cell region ids, consolidate the
			// regions ids to one per region
			for (i = 0; i < MAP_SIZE; i++)
			{
				for (j = 0; j < MAP_SIZE; j++)
				{
					regionSize[region[i][j] = cellRegionMapping[region[i][j]]]++;
				}
			}

Note that this was code for a java4k game so is pretty rough. For your case I would suggest using a proper collection for the regionIdMapping.

Obviously you will need to change the

 improvements[i][j - 1] & LAND_FLAG 

test to be your test for a placed block. But you can then use the regionSize array to pick the largest group of ship blocks (region) and make the assumption that they represent the ship.

This algorithm also assumes that only non-diagonally touching cells are grouped together… if you want to do that then you need to repeat 1b above for the cell to the above left of current and for the cell to above right of the cell.

One piece of advice: people will be more inclined to peek in your code if you put it online, e.g. using BitBucket or GitHiub. It also gives you a great way to manage and safely store your code.

I don’t understand this… “Proof of concept” what concept? I thought when I started viewing gif that you build a ship and you can fly with it afterwards in realistic physics.

What I can see is all you did make a pixel editing program with only 1 color available… What is the concept?

That is pretty much what I see but I would have chosen my words in a Scottish manner.

For this? I think that you’re over thinking the check for connection.

Based on what can be seen from your example you can do this using a simple BFS or DFS search from a known airship point (Say the engine room or the cockpit, just for an understandable analogy). You keep track of the number of the total number of cells that make up the ship. Then from that known point you do either a Depth First or Breadth First expansion catching all of the connected airship cells (However you define connected.) Then you take the compliment of that list (All cells not connected) and those are your disconnected squares.

If you’d like some pseudo-code later on I can throw something together for you.

I made this just last night to see if I can program a simple build a object game and then move it afterwards. I succeed. I didn’t want to have to program the crazy physics just yet but I probably will get around to it,=.

About the pseudo:

Yes, I’d love to have some when you get around to it. :stuck_out_tongue:

Honestly making a bunch of assumptions for my pseudo-code. :smiley:

Assumption 1: You’ve got a grid of some sort, or some easy method by which you can tell whether two cells in your grid are adjacent.
Assumption 2: You’re keeping track of all cells that are added to an airship.

That said, here’s a bit of psuedo-code for figuring out which are included/excluded from a connectivity set: http://www.java-gaming.org/?action=pastebin&id=872

If you have to, for whatever reason, deal with directionality (The you seem to describe it if Cell A is adjacent to Cell B then Cell B is adjacent to Cell A) such as with ‘portal-y’ things or one-way connections then the method will have to be changed. That’s probably way outside the scope.

what you could do is start with a list (array) of all the tiles on the screen, then have a command that checks each tile , firstly if its connected to anything at all if not then just delete it but it checks each tile from the starting tile , if something isnt connected to the block then its left on the list and anything left on the list is destroyed.

How do you record without a youtube video? gif?