0

I'm having a strange issue which I can't understand. I'm trying to apply an isNPC boolean to a PlayerMP object through the constructor, so I can cause NPC's (non-player characters) to move without user input. I've created a tick() method to override the super class, while calling it again when the player is not an NPC (allowing the player to use keyboard inputs to move the character), as can be seen below:

public class PlayerMP extends Player {

    public InetAddress ipAddress;
    public int port;
    protected boolean isNPC;   //used in server class to prevent sending of packets to NPC entities registered in PlayerMP list.

    public PlayerMP(Level lvl, int x, int y, InputHandler ipt, String usr, InetAddress ipAdd, int prt, int col) {
        super(lvl, x, y, ipt, usr, col);
        ipAddress = ipAdd;
        port = prt;
        isNPC = false;
    }

    public PlayerMP(Level lvl, int x, int y, String usr, InetAddress ipAdd, int prt, int col) {
        super(lvl, x, y, usr, col);
        ipAddress = ipAdd;
        port = prt;
        isNPC = false;
    }

    public PlayerMP(Level lvl, int x, int y, String usr, InetAddress ipAdd, int prt) {   //constructor for local player
        super(lvl, x, y, null, usr);
        ipAddress = ipAdd;
        port = prt;
        isNPC = false;
    }

    public PlayerMP(Level lvl, int x, int y, String usr, int col) {
        super(lvl, x, y, usr, col);
        isNPC = true;
    }

    @Override
    public synchronized void tick(){

        if(!isNPC) {
            super.tick();
        }
        else{
            int xa = 0;             //reset xa and ya so character stops when no keys are pressed (i.e. doesn't move continuously)
            int ya = 0;

            xa++;

            if (xa != 0 || ya != 0) {
                move(xa, ya);
                isMoving = true;

                Packet02Move packet = new Packet02Move(getUsername(), x, y, 050, noSteps, isMoving, movingDir);      //sending move pack to let server/other clients know that this character is moving + where to
                packet.writeData(GameApplication.game.client);

            } else {
                isMoving = false;
            }
            if (level.getTile(x >> 3, y >> 3).getId() == 3) {               //when tile is water
                isSwimming = true;
            }
            if (isSwimming && level.getTile(x >> 3, y + 3 >> 3).getId() != 3) { //return to normal when tile is no longer water (y+3 to allow for collision rather than rendering coords)
                isSwimming = false;
            }
            if (level.getTile(x >> 3, y >> 3).getId() == 8 || level.getTile(x >> 3, y >> 3).getId() == 9 || level.getTile(x >> 3, y >> 3).getId() == 10) {               //when tile is tree trunk or leaves
                isBehind = true;
            }
            //x + y coords need tweaking
            if (isBehind && level.getTile(x+3 >> 3, y >> 3).getId() != 8 && level.getTile(x+3 >> 3, y >> 3).getId() != 9 && level.getTile(x+3 >> 3, y >> 3).getId() != 10) { //return to normal when tile is no longer tree trunk/leaves
                isBehind = false;
            }
        }
    }

    public boolean isNPC(){return isNPC;}
}

The xa++; causes to character's x co-ordinate to increase, i.e. it moves to the right - this is simply to test movement, but when I add these NPC entities using the above constructor which initialises isNPC to true, they still execute super.tick() instead of the else{} block. Is there any reason why this would be happening?

When I change !isNPC to isNPC in the tick() method, it moves to the right, as expected, so I know the code is working.

EDIT: Super class constructor below + full PlayerMP class code above:

public Player(Level level, int x, int y, String usrname, int col) {
        super(level, "Player", x, y, 1);
        shortColour = col;
        setBodyColour(col);
        username = usrname;
    }

Initialisation of PlayerMP object with correct constructor (only one has 5 parameters):

PlayerMP npc2 = new PlayerMP(game.level, 316, 250, "NPC Gerald", 020);

I should also add that the isNPC variable is working as intended for other purposes such as the directing of packets to clients in the server class.

Constructor for Player's superclass (Mob):

public Mob(Level lvl, String nm, int x, int y, int spd) {
        super(lvl);
        name = nm;
        this.x = x;
        this.y = y;
        speed = spd;
    }

EDIT: Anyone else have any suggestions? isNPC is applying in some constructors as expected and won't work in others....

  • http://stackoverflow.com/questions/30965206/why-do-i-get-an-infinite-while-loop-even-if-i-modify-the-lock-variable/30965392#30965392 – Jean-François Savard Jul 31 '15 at 01:14
  • Hi Jean-François, thanks for your reply. I changed the boolean declaration from "protected boolean isNPC;" to "volatile boolean isNPC", but this has unfortunately not resolved the issue. – Ruairi McGowan Jul 31 '15 at 01:20
  • 1
    `volatile` does not make any difference here as you're using `synchronized` method. Would it be possible to share the entire code so that we can run and compile.Also, are you sure you're not setting `isMoving` variable anywhere else? – TheCodingFrog Jul 31 '15 at 01:24
  • You have several different constructors. Are you 100% sure you are calling the constructor where `isNPC` is set to `true`? – Tagir Valeev Jul 31 '15 at 01:37
  • It's likely that something is still missing in your problem description. It simply cannot work as you described. Just for the case declare `isNPC` as `final` to denote that it cannot change after the construction. Will the compile error pop from some place? – Tagir Valeev Jul 31 '15 at 01:50
  • Can we see the `Player` class? Also, where is `tick` called? Couldn't you make `isNPC` final? – Paul Boddington Jul 31 '15 at 01:50
  • The Player class' tick method is virtually identical to the else block in PlayerMP, with the exception of an input handler that increments/decrements xa/ya using key input. Making isNPC final made no difference unfortunately. – Ruairi McGowan Jul 31 '15 at 02:02
  • Also, if I change isNPC to true in the top-most constructor (which is for the local client's character) it moves to the right as expected! So why is isNPC = true applying correctly in one constructor but not the other!? – Ruairi McGowan Jul 31 '15 at 02:09
  • Can we see the constructor for Player's superclass? – Paul Boddington Jul 31 '15 at 02:13
  • I don't understand how you can even write `isNPC = true` in the top-most constructor because the field is a member of `PlayerMP`. – Paul Boddington Jul 31 '15 at 02:16
  • What? All of the constructors are in the PlayerMP class. I can only guess that the variable is getting written by the first constructor and for some reason won't change to true again for other entities. – Ruairi McGowan Jul 31 '15 at 02:25
  • Oh I see. When you said top-most I thought you meant the superclass of `Mob` (how long is this chain of super classes by the way?), not the top one on the page. The basic problem here is that we need a complete, verifiable example. Otherwise we're just guessing. – Paul Boddington Jul 31 '15 at 02:29

0 Answers0