Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I recently returned to face a problem I had with a game client of mine, i.e. the client's thread responsible for input & painting becomes unable to run after some while.

I suspect that it has something to do with server sent massages. Possibly client is unable to handle old ones before new ones are arriving. But when I am printing inQueue size after dequeue it always reaches 0.

What else could possibly be the reason of this block?

I was debugging using NetBeans and it says there is no deadlocks?

Are there other tools which I should/might use to find the reason.

I have tried lots of things and I think the code of my client is now in a state of disaster :)

I am using the engine coded by Bret Barker which I got from the book by David Brackeen titled "Developing Games in Java".

If you guys would need some code I can paste some snippets of bits which you would suspect the problem is since the whole code is big & fat. Plus the last thing all wants to do here is read and debug someone's code, right? :) Thus I think we can do it by need basic.

I am stuck and all your help/suggestions of stuff I should look after, even an article about similar issues, etc. is much appreciated.

EDIT1: Here is presented a test class which combines client for server communication and GUI/frame for display & user input.

public class NetworkingTest2 extends GameCore implements IGameFrame
{
    private static final long serialVersionUID = 1L;
    private float _scrollSpeed = 0.35f;
    private InputManager inputManager;
    //mouse Actions
    protected GameAction leftMouseClick;
    protected GameAction rightMouseClick;
    //keyboard Actions
    protected GameAction scrollMapUpKey;
    protected GameAction scrollMapDownKey;
    protected GameAction scrollMapLeftKey;
    protected GameAction scrollMapRightKey;
    //robot moves
    protected GameAction moveForwardKey;
    protected GameAction moveBackwardKey;
    protected GameAction moveLeftKey;
    protected GameAction moveRightKey;
    private RoboClient client;
    //your/client's bot
    private IUnit unit;

    private RoboGame game = null;
    public NetworkingTest2(String playerName, String password)
    {
        addWindowListener(new WindowAdapter()
        {
            @Override
            public void windowClosing(WindowEvent e)
            {
                System.out.println("NetworkingTest2 windowClosing");
                //used to call disconect once and then wait for it to finish
                Runnable doWork = new Runnable()
                {
                    public void run()
                    {
                        System.out.println("Stops client if it is still running.");
                        if(client.isRunning())
                            client.disconnect();
                    }
                };
                SwingUtilities.invokeLater(doWork);
            }
        });
        initializeInput();
        this.client = new RoboClient(this)
        {
            @Override
            public void onSuccessfulLogin()
            {
                System.out.println("././././onSuccessfulLogin././././");
                // 0 becaue we assume that there is only one game
                client.createAndEnqueueJoinGameEvent(0);
            }
        };
        boolean isConnected = client.connectToServer(GameConstants.SERVER_IP, playerName, password);
        System.out.println("isConnected with server (doesn't mean the player is logged)=" + isConnected);
    }

    private void initializeInput()
    {
        this.inputManager = new InputManager(this);
        // mouse
        this.leftMouseClick = new GameAction("left mouse click");//, GameAction.DETECT_INITIAL_PRESS_ONLY);
        this.rightMouseClick = new GameAction("righ mouse click", GameAction.DETECT_INITIAL_PRESS_ONLY);
        // key
        this.scrollMapDownKey = new GameAction("scrollDown", GameAction.NORMAL);
        this.scrollMapUpKey = new GameAction("scrollUp", GameAction.NORMAL);
        this.scrollMapLeftKey = new GameAction("scrollLeft", GameAction.NORMAL);
        this.scrollMapRightKey = new GameAction("scrollRight", GameAction.NORMAL);

        this.moveForwardKey = new GameAction("Move yout robot Forawrd/North");
        this.moveBackwardKey = new GameAction("Move yout robot Back/South");
        this.moveLeftKey = new GameAction("Move yout robot Left/West");
        this.moveRightKey = new GameAction("Move yout robot Right/East");
        // key mouse assigment
        inputManager.mapToMouse(leftMouseClick, InputManager.MOUSE_BUTTON_1);
        inputManager.mapToMouse(rightMouseClick, InputManager.MOUSE_BUTTON_3);
        // keybard assignment
        inputManager.mapToKey(scrollMapDownKey, KeyEvent.VK_DOWN);
        inputManager.mapToKey(scrollMapUpKey, KeyEvent.VK_UP);
        inputManager.mapToKey(scrollMapLeftKey, KeyEvent.VK_LEFT);
        inputManager.mapToKey(scrollMapRightKey, KeyEvent.VK_RIGHT);

        inputManager.mapToKey(moveForwardKey, KeyEvent.VK_W);
        inputManager.mapToKey(moveBackwardKey, KeyEvent.VK_S);
        inputManager.mapToKey(moveLeftKey, KeyEvent.VK_A);
        inputManager.mapToKey(moveRightKey, KeyEvent.VK_D);
    }

    public void setUnit(IUnit robot)
    {
        setTitle(getTitle() + " for playerName=" + robot.getPlayer().getPlayerId());
        this.unit = robot;
        //center view on the player's robot
        System.out.println("screenWidth=" + screenWidth + ";;screenHeight=" + screenHeight);
        int initialOffsetX = (int) ((robot.getCenterPoint().getX() - getFrameWidth() / 2));
        int initialOffsetY = (int) ((robot.getCenterPoint().getY() - getFrameHeight() / 2));
        game = client.getGame();
        game.getGameLevel().getMap().setMapOffsetX(-initialOffsetX);
        game.getGameLevel().getMap().setMapOffsetY(-initialOffsetY);
    }

    @Override
    public void update(long elapsedTime)
    {
        System.out.println("NetworkingTest2 public void update(long elapsedTime)");
        checkInput(elapsedTime);
        if(game != null)
        {
            GameLevel gameLevel = game.getGameLevel();
            if(gameLevel != null)
            {
                List<IShot> shotList = gameLevel.getShotList();
                //update all animated projectiles -- thus user sees their animation
                for(int i = 0; i < shotList.size(); i++)
                    if(shotList.get(i).getProjectile() instanceof IAnimatedProjectile)
                    {
                        IAnimatedProjectile ap = (IAnimatedProjectile) shotList.get(i).getProjectile();
                        ap.update(elapsedTime);
                    }
            }
        }
    }
    // for debug purpose
    private String _clickedObjectName = "None";
    private String _clickedObjectToughness = "None";
    private long drawCounter = 0;

    @Override
    public void draw(Graphics2D g2)
    {
        g2.setColor(Color.BLACK);
        g2.fillRect(0, 0, this.getWidth(), this.getHeight());

        if(game != null)
        {
            GameLevel gameLevel = game.getGameLevel();
            if(gameLevel != null)
            {
                WorldMap map = gameLevel.getMap();
                //center view on the unit -- this way arrow key are not working as map offset is set again here
                int initialOffsetX = (int) ((unit.getCenterPoint().getX() - getFrameWidth() / 2));
                int initialOffsetY = (int) ((unit.getCenterPoint().getY() - getFrameHeight() / 2));
                map.setMapOffsetX(-initialOffsetX);
                map.setMapOffsetY(-initialOffsetY);
                gameLevel.draw(g2);//, offsetX, offsetY);//(g2, map.getMapOffsetX(), map.getMapOffsetY());
                g2.setColor(Color.YELLOW);
                g2.drawString("MapOffset X: " + map.getMapOffsetX(), 10, 100);
                g2.drawString("MapOffset Y: " + map.getMapOffsetY(), 10, 120);

                g2.drawString("Mouse X: " + inputManager.getMouseX(), 10, 160);
                g2.drawString("Mouse Y: " + inputManager.getMouseY(), 10, 180);

                g2.drawString("Mouse on Map X: " + (inputManager.getMouseX() + map.getMapOffsetX()), 10, 220);
                g2.drawString("Mouse on Map Y:" + (inputManager.getMouseY() + map.getMapOffsetY()), 10, 240);
            }
            //unit display update
            g2.setColor(Color.RED);
            IShootingClipWeapon head = (IShootingClipWeapon) unit.getEquipmentAtLocation(Robot.EQUIPMENT_ON_HEAD);
            g2.drawString("Ammo on head: "
                    + head.getClip().getCurrentAmmoAmount() + "/" + head.getClip().getMaximumAmmoCapacity(), 10, 450);
            g2.drawString("Money: " + unit.getPlayer().getMoney(), 10, 480);
            g2.drawString("Hp: " + unit.getHpCurrent() + "/" + unit.getHpMax(), 10, 510);
            g2.drawString("Speed: " + unit.getSpeed(), 10, 540);
        }
        g2.setColor(Color.YELLOW);
        g2.drawString("ClickedObjectName: " + _clickedObjectName, 10, 260);
        g2.drawString("ClickedObjectToughness: " + _clickedObjectToughness, 10, 290);
        g2.drawString("drawCounter= " + (drawCounter++), 10, 320);
    }

    @Override
    public void clean()
    {
    }

    private void checkInput(long elapsedTime)
    {
        int step = Math.round(_scrollSpeed * elapsedTime);
        if(game != null)
        {
            GameLevel gameLevel = game.getGameLevel();
            if(gameLevel != null)
            {
                WorldMap map = gameLevel.getMap();

                if(scrollMapRightKey.isPressed())
                {
                    map.scroll(WorldMapDirection.EAST, step);
                    System.out.println("Pressed:" + scrollMapRightKey.getName());
                }
                if(scrollMapLeftKey.isPressed())
                {
                    map.scroll(WorldMapDirection.WEST, step);
                    System.out.println("Pressed:" + scrollMapLeftKey.getName());
                }
                if(scrollMapUpKey.isPressed())
                {
                    map.scroll(WorldMapDirection.NORTH, step);
                    System.out.println("Pressed:" + scrollMapRightKey.getName());
                }
                if(scrollMapDownKey.isPressed())
                {
                    map.scroll(WorldMapDirection.SOUTH, step);
                    System.out.println("Pressed:" + scrollMapLeftKey.getName());
                }
                if(client.isInGame() && unit != null)
                {
                    Point2D mousePoint = new Point2D.Double(
                            inputManager.getMouseX() - map.getMapOffsetX(),
                            inputManager.getMouseY() - map.getMapOffsetY());
                    double angleBetweenDirectionAndAxisX =
                            GeometricOperations.calculateAngleOfRotation(
                            unit.getCenterPoint(), mousePoint, 0.0);
                    if(unit.isAlive() && Math.abs(unit.getFaceAngle() - angleBetweenDirectionAndAxisX) >= 5.0)
                        client.createAndEnqueueTurnActionEvent(unit, mousePoint);
                    boolean isMoving = false;
                    double modX = 0;
                    double modY = 0;
                    boolean isForwardMove = false;
                    boolean isBackwardMove = false;
                    boolean isLeftMove = false;
                    boolean isRightMove = false;
                    if(moveLeftKey.isPressed())
                    {
                        isLeftMove = true;
                        isMoving = true;
                        modX = modX - 100 - unit.getSpeed();
                    }
                    if(moveRightKey.isPressed())
                    {
                        isRightMove = true;
                        isMoving = true;
                        modX = modX + 100 + unit.getSpeed();
                    }
                    if(moveForwardKey.isPressed())
                    {
                        isForwardMove = true;
                        isMoving = true;
                        modY = modY - 100 - unit.getSpeed();
                    }
                    if(moveBackwardKey.isPressed())
                    {
                        isBackwardMove = true;
                        isMoving = true;
                        modY = modY + 100 + unit.getSpeed();
                    }

                    if(isMoving && unit.isAlive())
                    {
                        if(unit.isMoving() == false || unit.isMoveFlagsStateChanged(
                                isForwardMove, isBackwardMove, isLeftMove, isRightMove))
                        {
                            unit.startMoving();
                            unit.setMoveFlags(isForwardMove, isBackwardMove, isLeftMove, isRightMove);
                            client.createAndEnqueueMoveMessageEvent(unit,
                                    isForwardMove, isBackwardMove, isLeftMove, isRightMove);
                        }
                    }//start and stop move/shoot are controlled by server
                    else if(unit.isMoving())
                    {
                        unit.stopMoving();
                        client.createAndEnqueueMoveStopEvent(unit);
                    }

                    if(leftMouseClick.isPressed())
                    {
                        if(unit.isFiring() == false && unit.isAlive())
                        {
                            Iterator<String> it = unit.getEquipmentLocationMap().keySet().iterator();
                            while(it.hasNext())
                            {
                                String key = it.next();
                                IEquipment eq = unit.getEquipmentAtLocation(key);
                                if(eq instanceof IClipWeapon)
                                {
                                    IClipWeapon cw = ((IClipWeapon) eq);
                                    if(cw.isEnoughAmmoToAttack() == true)
                                        ((IWeaponMR) cw.getMapRepresentation()).attack();
                                }
                            }

                            unit.startFiring();
                            client.createAndEnqueueFireActionEvent(unit, IUnit.EQUIPMENT_ON_ALL_SLOTS);
                        }
                    }
                    else if(unit.isFiring())
                    {
                        System.out.println("stop firing");
                        unit.stopFiring();
                        client.createAndEnqueueFireStopEvent(unit);
                    }
                }
            }
        }
    }

    public static void main(String[] args)
    {
        BasicConfigurator.configure();
        NetworkingTest2 nft = new NetworkingTest2("Alegroth2", "ElBoro");
        nft.setCoreFrameSize(600, 600);
        nft.run();
    }
}
share|improve this question

closed as off-topic by Byte56 May 21 at 14:18

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Questions about debugging a problem in your project must present a concise selection of code and context so as to allow a reader to diagnose the issue without needing to read all of your code or to engage in extensive back-and-forth dialog. For more information, see this meta thread." – Byte56
If this question can be reworded to fit the rules in the help center, please edit the question.

1 Answer 1

up vote 2 down vote accepted

I know it's hard to use the debugger to find these kinds of issues. From your question it sounds like you also have some network communication tasks inside the input and painting thread, I'd recommend pushing that functionality to a different thread. Network communication is unreliable, and having the painting and input threads possibly getting hung up on network time-outs would be bad news.

Try to figure out how to reproduce the failure, it will be much easier to solve if you can find a cause. Another way to find the offending bit of code is to try breaking the threads tasks down, or temporarily disabling some of it's functions. Then try to break it again.

Lastly, try posting the code you think is at fault so we can look at it.

Edit That code is a bit much to look at. Try placing break points at all your exit points for the thread, see if the thread is ending prematurely. Step through the thread a few times with the debugger, to make sure it's following the path you think it should. Make sure it's not getting hung up on network issues.

share|improve this answer
    
Thanks for your interest. I will take another look at the code today and will get back to you either with some code or some questions. –  Boro May 12 '11 at 6:24
    
thanks for your time and suggestions. (+1) I will try to rethink it again and maybe get a better code sample. But right now I cannot figure out what wrong is going on there - your suggestions have been tried. –  Boro May 14 '11 at 22:37
    
Thanks. I have figured it out a while ago. I had a bug in a different part of the project. –  Boro Sep 7 '11 at 8:50

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