处理鼠标单击的序列,其中每次单击取决于之前的单击

时间:2017-07-24 09:11:53

标签: java mouseclick-event

我正在创建一个基于平铺的回合制游戏,您可以在命令下使用多个单位,并使用鼠标点击控制它们(有点像国际象棋,但有更多的机制)。它们都是使用Java Graphics(g.drawImage或g.draw(shape))绘制的。用户每次单击鼠标都应执行某项任务,具体取决于之前的鼠标点击。

例如:要攻击敌方单位,必须先单击自己的单位,然后单击敌方单位。或者如果你点击你自己的单位,但他已经攻击了,那么你随后点击敌方单位不应该引起攻击。

游戏使用勾选/渲染系统,其中所有用户输入都以tick方法处理(每秒多次调用),然后使用渲染方法(也称为每秒多次)绘制到屏幕上

我解决这个问题的方法是使用很多不同的变量和if语句太多。我不会粘贴整个代码,因为它很长,但它的处理鼠标点击部分已被附加到下面。

一旦tick方法达到某一目的,它将调用" checkwhattoshow"比这更长的方法,但它会给渲染方法指示画在屏幕上。

代码对我想要的东西起了一半作用,但是我主要问的是,是否有一种更有效的方法,而不是制作过多的if语句和变量,以处理鼠标点击的序列,因为这似乎不必要和低效。

//class variables
private boolean unitclickedon; //if a friendly unit is selected
private int xTile, yTile; 
private int onlyonce; //helps me perform a block of code only once
private int prevxTile, prevyTile;
private int speed; //distance the unit can move
private int maxRange; //how far the unit can attack

private Tile tile, newTile;
private Unit unit;

    @Override
    public void tick() {

    //every time the left mouse button is clicked
    if (handler.getMouseManager().buttonJustPressed(MouseEvent.BUTTON1)) {

        //keep track of the tile you're clicking on
        xTile = handler.getPosition().getCoordX();
        yTile = handler.getPosition().getCoordY();

        //if clicking outside of map do nothing
        if (xTile > handler.getMap().getWidth() - 2
                || xTile < 1
                || yTile < 1
                || yTile > handler.getMap().getHeight() - 2) {
            return;
        }

        //if you click on a unit
        if (handler.getMap().getTileAt(xTile, yTile).getUnit() != null) {

            //save the tile and unit info
            tile = handler.getMap().getTileAt(xTile, yTile);
            unit = tile.getUnit();
            speed = unit.getSpeed();
            maxRange = unit.getMaxRange();

            //if nothing is currently selected at all
            //select the unit and exit this method.
            if (onlyonce++ == 0) {
                unitclickedon = true;
                prevxTile = xTile;
                prevyTile = yTile;
                //check what should render to the screen
                checkWhatToShow();
                return;
            }

            //if you've clicked on the same tile twice unselect the unit and reset 
            if (prevxTile == xTile && prevyTile == yTile) {
                unitclickedon = false;
                onlyonce = 0;
            } else { // you're clicking on another unit
                Unit prevUnit = handler.getMap().getUnit(prevxTile, prevyTile);
                if (prevUnit.getOwner() == unit.getOwner()) { //selecting another one of your units
                    unitclickedon = true;
                    //check what should render to the screen
                    checkWhatToShow();
                } else { //clicking an enemy unit
                    if (validAttack(prevxTile, xTile, prevyTile, yTile, maxRange + speed)) { //attack
                        System.out.println("attacking unit!");
                        unitclickedon = false;
                        prevUnit.setHasAttacked(true);
                        return;
                    } else { //cant attack
                        unitclickedon = false;
                        checkWhatToShow();
                    }

                }
            }

        } else { //if you're not clicking on a unit

            if (unitclickedon) { //you're attempting to move a unit

                if (validMove(prevxTile, xTile, prevyTile, yTile, speed)) { //move the unit if its legal

                    tile = handler.getMap().getTileAt(prevxTile, prevyTile);
                    unit = tile.getUnit();
                    if (!unit.isActive() || unit.hasMoved()) {
                        unitclickedon = false;
                        return;
                    } else { //move the unit
                        newTile = handler.getMap().getTileAt(xTile, yTile);
                        tile.removeUnit();
                        newTile.addUnit(unit);
                        unit.setHasMoved(true);
                        unitclickedon = false;
                        onlyonce = 0;
                    }
                } else { //dont move the unit because you're clicking outside of its range
                    unitclickedon = false;
                    onlyonce = 0;
                }
            } else { //you're not doing anything unit related
                unitclickedon = false;
                onlyonce = 0;
            }
        }
        //record your last click
        prevxTile = xTile;
        prevyTile = yTile;
    }
}

简短版本: 试图解决使大型版本更高效的问题:

if (first mouse click does x1)
   if (second mouse click does y)
      third mouse click does z
   if (second mouse click was y2)
      third mouse click z2
if (first mouse click does x2)
   bla bla bla

然后获得最终结果并将其渲染到屏幕上

感谢和抱歉,如果它没有意义:c

1 个答案:

答案 0 :(得分:0)

**你可以类似于:

List<Rule> rules = .... ; // your n rules initialized here somehow
for(Rule r : rules) {
  if(r.condition()) {
    r.action();
  }
}**