Trying to make an object that has a sort of parent object.

          I have a Mother Ship class, and a Decoy Ship class. The Mother Ship in-game is supposed to spew out around 20 of these tiny little decoy ships for the enemy to shoot at. Problem is I have no idea how to organize and implement this, so I'm just playing around with everything. Here's my problem that I can't figure out:

I have a public static ArrayList for all my ships that I iterate through to render and stuffs in one class, and in My MotherShip class I create the tiny little decoy ships on startup and want them to move around their target but they don’t move at all.

for(int i = 0; i < maxDecoyShips; i++){
			Galaxy.shipList.add(new Ship_DecoyShip(Position.x, Position.y, this, Faction));
		}

That works out fine and all, but now I want to use this Mother Ship instance as a sort of Parent to the decoy Ship. So in the constructor I call for a Ship instance.

public Ship_DecoyShip(float x, float y, Ship MotherShip, int Faction){
		Position = new Vector2();
		goalPosition = new Vector2();
		shipTextureBlue = Assets.manager.get(Assets.Ship_Decoy_Blue);
		shipTextureRed = Assets.manager.get(Assets.Ship_Decoy_Red);
		shipTextureDown = Assets.manager.get(Assets.Ship_Decoy_Down);
		shipRegionBlue = new TextureRegion(shipTextureBlue);
		shipRegionRed = new TextureRegion(shipTextureRed);
		shipRegionDown = new TextureRegion(shipTextureDown);
		rand = new Random();
		this.Width = shipRegionBlue.getRegionWidth();
		this.Height = shipRegionBlue.getRegionHeight();
		this.OriginX = Width/2;
		this.OriginY = Height/2;
		this.select = Assets.manager.get(Assets.Select2);
		this.Position.x = x;
		this.Position.y = y;
		this.goalPosition.x = x;
		this.goalPosition.y = y;
		this.MotherShip = MotherShip;
		this.rect = new Rectangle(Position.x, Position.y, shipTextureBlue.getWidth(), shipTextureBlue.getHeight());
		this.Faction = Faction;
	}

I then want the decoy ship to target the target of it’s parent’s Mother Ship below, and if there is no target just move around the Mother Ship.

To Find the enemy (all ships implement this method, I just figured I could use this method without the need of using the ship passed through it):

@Override
	public void findEnemy(Ship ship) {
		if (TargetShip == null && MotherShip.getTargetShip() != null) {
			TargetShip = MotherShip.getTargetShip();
		}
		if(TargetShip == null && MotherShip.getTargetShip() == null){
			TargetShip = MotherShip;
		}
		
		if(TargetShip != null && !TargetShip.isAlive()){
			TargetShip = null;
		}

and what my decoy ship does to go around the enemy (does not seem to work, the ships don’t move):


// Set Goal Around TargetShip
			if(TargetShip != null && Position.x == goalPosition.x && Position.y == goalPosition.y){
				float positionX = TargetShip.getPosition().x;
				float positionY = TargetShip.getPosition().y;
				float width = TargetShip.getRectangle().width;
				float height = TargetShip.getRectangle().height;
				
				goalPosition.x = rand.nextInt((int) (positionX + width));
				goalPosition.y = rand.nextInt((int) (positionY + height));
			}

in my Galaxy class is where everything is rendered and updated:


updateFollowCamera(camera);
		
		batch.begin();
		batch.draw(decoyShipTexture, 5000, 5000);
		
		if(currentShip != null && Gdx.input.isButtonPressed(Buttons.LEFT) && currentShip.isHovered() == false){
			currentShip = null;
		}
		
		// Update and Render Ships
		for (Iterator<Ship> shipIter = shipList.iterator(); shipIter.hasNext();) {
			Ship ship = shipIter.next();
			
			ship.render(batch);
			ship.update(mousePos, camera);

			
		if(Gdx.input.isButtonPressed(Buttons.LEFT)){
			if (ship.isHovered() && ship.getFaction() == 0) {
				currentShip = ship;
			}
			
		}
		
		if(ship.getHull() < 0){
			ship.setAlive(false);
			shipIter.remove();
		}
		
		if(currentShip != null && !currentShip.isAlive()){
			currentShip = null;
		}
			
			
			
			/* Check if zoomed out */
			if (camera.zoom > 15) {
				ship.renderGlobal(batch);
				ship.setZoomedOut(true);
			}
			
			else{
				ship.setZoomedOut(false);
			}
			
			/* Check if inside camera */
			if(camera.frustum.pointInFrustum(ship.getOriginX(), ship.getOriginY(), 0)){
				ship.setInCamera(true);
			}
			else{
				ship.setInCamera(false);
			}
				
			/* Constantly check for enemies in area */
			
			for (int i = 0; i < shipList.size(); i++) {
				ship.findEnemy(shipList.get(i));
			}
			
			
			/* Check if ships collided with bullet */
			
			for (Iterator<Bullet> bulletIter = bulletList.iterator(); bulletIter
					.hasNext();) {
				Bullet bullet = bulletIter.next();

			
				bullet.render(batch);
				bullet.update();
				
				
				/* Check if bullet intersects with ships and destroy */
				if (bullet.getRectangle().overlaps(ship.getRectangle()) && bullet.getFaction() != ship.getFaction()) {
					int randSound = rand.nextInt(3);
					
					ship.damageHull(10);
					
					
					// Play Random Sound on Ship hit
					if(camera.zoom <= 14 && ship.getInCamera() == true){
						if(randSound == 0){
							hit1.play();
						}
						if(randSound == 1){
							hit2.play();
						}
						if(randSound == 2){
							hit3.play();
						}
					}
					bulletIter.remove();
				}
				
			}
			
		}
		batch.end();

	}

any help is appreciated, Thanks!:

Hm, they really should add sroll bar to long lists of code.

Or you should use a pastebin for extraordinary long code dumps.

This is a simple debugging question. Unless someone here wants to comb through your code line by line, you are not going to get an answer. Learning how to debug and figure out what is happening in your code when it’s not working is an invaluable tool that you will need to learn, and I suggest you start now.

Take a guess at what’s going wrong, find the relevant snippet of code, and then insert some print statements to figure out the exact issue. You could even learn how to use breakpoints and the advanced debugging tools your IDE (most likely) provides for you.

Thank you! I will start trying to learn the debugger then, it’s just every time I looked at it I felt like it was out my league and unnecessary to the point that it was dizzying. ;D

Well I got the little decoy ships to actually move! ;D, but now they’re generating coordinates to go to that are nowhere near the actual mother ships. My Mother ships are located from the x position 5000 to 6500, yet my little tiny ships are generating coordinates around 767.0. ???

As noted before, the debugger and/or some debug output are probably going to be your best bet. Assuming you’re still using this code though:

if(TargetShip != null && Position.x == goalPosition.x && Position.y == goalPosition.y){
            float positionX = TargetShip.getPosition().x;
            float positionY = TargetShip.getPosition().y;
            float width = TargetShip.getRectangle().width;
            float height = TargetShip.getRectangle().height;
            
            goalPosition.x = rand.nextInt((int) (positionX + width));
            goalPosition.y = rand.nextInt((int) (positionY + height));
         }

First, if the coordinate comparisons in the conditional involve floats, then that could be a red flag. Maybe you’re doing it that way for a reason, but keep in mind there are many circumstances involving floating-point values (perhaps most circumstances) where exact comparisons can’t be relied on due to numerical error.

Also, the use of nextInt() for computing the goal positions seems suspicious. Maybe you have a reason for this as well, but it’s not immediately obvious (without looking at the rest of your code, at least) what that’s supposed to do. Keep in mind that a) those values will always be integers (which is unlikely to make sense if, for example, the units in your game are very large compared to the entities), and b) it will only work with positive values (which may or may not make sense, depending).

Again, maybe the code is correct. But, it does seem like the kind of thing that could maybe use a second look.

goalPosition.x = rand.nextInt((int) (positionX + width));
gives a number inbetween (0,positionX + width)
so what you could do is convert positionX to screen/window coordinates instead of world coordinates.
and then convert goalPosition.x to world.