Create account / Log in

Connecting gaming pieces ? - RFE:1611311

Suggestions for additional features for the module editor and Vassal engine.

Moderators: uckelman, Tim M

Connecting gaming pieces ? - RFE:1611311

Postby mehrunes » December 29th, 2007, 10:36 pm

For some game systems (tabletops), it is important to move models in groups while maintaining the chance to move them alone when desired.

Is there a chance to connect game pieces temporarily so that you move more of them as "one piece" ?
I hope you understand what I mean.
Apologize my bad english - I'm not a native speaker. ;)
mehrunes
 
Posts: 84
Joined: December 28th, 2007, 1:33 am

Connecting gaming pieces ?

Postby rk » December 30th, 2007, 5:21 am

You can select multiple units by dragging the selection rectangle or shift-clicking on any group of pieces. Dragging any selected piece will move all selected pieces as a group. This is the only way to group pieces together and it lasts only for that move by that player.

rk

Post generated using Mail2Forum (http://www.mail2forum.com)
rk
Site Admin
 
Posts: 536
Joined: October 21st, 2007, 3:31 am

Postby mehrunes » December 30th, 2007, 10:20 am

I know about that feature but this is multi-selecting and not connecting.

For example I cannot pivot or rotate all models as one.

Some others ideas how to realize this ?
Apologize my bad english - I'm not a native speaker. ;)
mehrunes
 
Posts: 84
Joined: December 28th, 2007, 1:33 am

Postby bsmith » December 30th, 2007, 10:26 am

I remember trying to do this for Napoleon's Triumph.

What ultimately needs to happen is when a group of pieces are selected, instead of pivoting them all around their own axes, they should pivot around the central axis of the selection area. Maybe it could be added as an option for the Pivot trait?
User avatar
bsmith
Site Admin
 
Posts: 657
Joined: October 2nd, 2007, 4:47 pm

Postby Tim M » December 30th, 2007, 10:52 am

Similarily, this feature type is also brought up by the request 1611311. We discussed this last year but did not get far

http://sourceforge.net/tracker/index.ph ... tid=594234

There are some obstacles involved, that Brent would have to comment on.
Counters/pieces would probably need some sort of unique internal ID that Vassal can use to 'temporarily' allow certain ID's be joined together and act in conjunction with each other but still be able to act independent be it stacked/non-stacked
User avatar
Tim M
 
Posts: 1817
Joined: December 8th, 2007, 12:22 pm
Location: Earth

Connecting gaming pieces ?

Postby uckelman » December 31st, 2007, 11:44 am

Thus spake "bsmith":
I remember trying to do this for Napoleon's Triumph.

What ultimately needs to happen is when a group of pieces are selected, inste
ad of pivoting them all around their own axes, they should pivot around the c
entral axis of the selection area. Maybe it could be added as an option for
the Pivot trait?


If this gets implemented---call it a Group---I think it should be done
either similarly to, or as a subclass of Stack. A Group soulds like a
horizontal Stack to me.

--
J.

_______________________________________________
Messages mailing list
Messages@forums.vassalengine.org
http://forums.vassalengine.org/mailman/ ... engine.org

Post generated using Mail2Forum (http://www.mail2forum.com)
User avatar
uckelman
Site Admin
 
Posts: 8985
Joined: December 10th, 2007, 9:48 am
Location: Durham, England

Postby YojimboUsaka » December 31st, 2007, 11:42 pm

Being able to 'stack' a group of pieces and then having them act as a single large piece, rotation being one of the big ones, would be a perfect solution.

Of course this sounds a lot simpler then it would be to code in.

Yoj
User avatar
YojimboUsaka
 
Posts: 16
Joined: December 22nd, 2007, 11:42 pm
Location: Scott AFB, IL

Postby Tim M » December 31st, 2007, 11:53 pm

YojimboUsaka wrote:Being able to 'stack' a group of pieces and then having them act as a single large piece, rotation being one of the big ones, would be a perfect solution.

Of course this sounds a lot simpler then it would be to code in.

Yoj


Umm? You can already do this.

Provided all your pieces are stacked together of course, there is no need to select (or drag a marquee window around) every single piece and rotate it.

Instead all pieces should have a proto to control this behavior with a GKC / Trigger / Rotate trait sequence - The command would be 'Rotate Stack/Group' whatever.
You would then also need a stand alone Rotate trait with a different key command to rotate pieces individually
User avatar
Tim M
 
Posts: 1817
Joined: December 8th, 2007, 12:22 pm
Location: Earth

Connecting gaming pieces ?

Postby Brent Easton » January 1st, 2008, 4:35 am

He means have the pieces 'stacked' side by side, not on top of each other.

Be able to select a set of counters and 'Group' them, so that they now keep their positions relative to each other and move as one counter until 'ungrouped'.

Brent.

*********** REPLY SEPARATOR ***********

On 31/12/2007 at 3:53 PM Tim M wrote:

YojimboUsaka wrote:
Being able to 'stack' a group of pieces and then having them act as a
single large piece, rotation being one of the big ones, would be a perfect
solution.
Of course this sounds a lot simpler then it would be to code in.

Yoj


Umm? You can already do this.

Provided all your pieces are stacked together of course, there is no need
to select (or drag a marquee window around) every single piece and rotate
it.

Instead all pieces should have a proto to control this behavior with a GKC
/ Trigger / Rotate trait sequence - The command would be 'Rotate
Stack/Group' whatever.
You would then also need a stand alone Rotate trait with a different key
command to rotate pieces individually







_______________________________________________
Messages mailing list
Messages@forums.vassalengine.org
http://forums.vassalengine.org/mailman/ ... engine.org


--
No virus found in this incoming message.
Checked by AVG Free Edition.
Version: 7.5.516 / Virus Database: 269.17.13/1205 - Release Date: 31/12/2007 3:32 PM


____________________________________________________________
Brent Easton
Analyst/Programmer
University of Western Sydney
Email: b.easton@uws.edu.au


_______________________________________________
Messages mailing list
Messages@forums.vassalengine.org
http://forums.vassalengine.org/mailman/ ... engine.org

Post generated using Mail2Forum (http://www.mail2forum.com)
User avatar
Brent Easton
 
Posts: 3226
Joined: December 21st, 2007, 3:06 am
Location: Berry, NSW, Australia

Digging up past emails on subject

Postby Tim M » January 4th, 2008, 4:20 am

Brent,

I was looking back at some of the old emails on this back from Aug/Sep.
You mentioned the idea of a special link trait. The problem you said was not the recording or handling, but your list regarding movement.

What if this special link trait causes one of the linked pieces to act as some sort of cross combination between a layer/stack.

So you would make this link trait tell one of the pieces even though your a piece with your own unique keys/commands/properties you are also now a layer that belongs to this other piece (sort of like a super layer?) and as a super layer you follows all the rules of a regular layer like movement, to the piece you are linked to. Its sort of like joining the two pieces into one 'uber' piece if you follow what I mean. And would work for grouping as well I imagine.

Thing is - in making this super layer/uber piece can you still access the individual commands of each individual piece still by doing that?
User avatar
Tim M
 
Posts: 1817
Joined: December 8th, 2007, 12:22 pm
Location: Earth

Postby ghoust » May 21st, 2008, 8:08 pm

I had a look at the code and also thought that a stack subclass would do it, as stack already does most of the stuff..

I'd do the following to this special stack:
- the stack displays always expanded (but is not) while no expanded clicking on it and moving it around you would move the whole stack right?
- when double clicked it still displays expanded (but now is as a stack technically), so you can move pices in and out (for generals, joining, etc.) or shuffle pieces around in your special stack.
- on right click a new option r&f: you would define the file # of game pieces, the ranks will be adjusted acordingly dependandt of how many game pieces are on the stack
- any idea how to trigger the pivot? doing it with the stack based class should be easy, but how to trigger it so it can be done on a special corner of the rank & file stack ? 4 commands for each corner?

I'll give it a try in the next weeks, and report back here.

Any ideas on how to implement this, or generalize it, or input to the pivot center problem would be appreciated..
ghoust
 
Posts: 42
Joined: May 21st, 2008, 7:56 pm

Connecting gaming pieces ? - RFE:1611311

Postby rk » May 21st, 2008, 8:43 pm

A subclass of Stack makes sense. Sounds like your class needs to keep track of an angle in addition to the position. Then the code to draw the stack rotates all the pieces to the same angle but doesn't actually rotate the individual pieces until you remove them from the stack. You'll need some kind of visual border to distinguish between "expanded" and "unexpanded" stacks, but the selection highlighter will adapt easily.

You might actually put most of the logic into a subclass of StackMetrics. It includes a method for creating new Stacks, so that when a Map uses your new StackMetrics class, pieces will clump together into an instance of your new Stack class. The logic for drawing a Stack lives in the StackMetrics class anyway, so your Stack subclass may not need any extra code other than storing the angle.

rk

Post generated using Mail2Forum (http://www.mail2forum.com)
rk
Site Admin
 
Posts: 536
Joined: October 21st, 2007, 3:31 am

Postby ghoust » May 23rd, 2008, 4:58 pm

Thank you for the input. I already started to modify (for prototype) the stackmetrics class and it does at the moment create my rank & file layout. The clue I needed was to where the configuration which metric is used is configured in. I'll take a close look at the map.

Perhaps I can go without an extra stack (where I had the same problem of configurability.. which now I know how to solve, than again..).

For pivoting, I'd like to make a command for each corner. The way I intended it to work is: push the command or hotkey, now the cursor appears on the oposite corner. The user can move the cursor up an down, while he moves the arc will get shaded (something like the range underlay I saw in warhammer 40k). in addition the arc wil display the distance 'arced'. When the user clicks again he finishes the arc move an the pivoting is finally executed. Has something like this already been done? if not which components could I use for this effect. What bothers me is the click once, click twice behavior, can this be done in vassal?

thanx for the input, have not realized so far that stackmetrics also works as the stack factory..

I'll post some results as soon as I have the rank& file implementation running with multiple sized game pieces (which sometimes can be the case in warhammer..)
ghoust
 
Posts: 42
Joined: May 21st, 2008, 7:56 pm

Connecting gaming pieces ? - RFE:1611311

Postby rk » May 23rd, 2008, 11:05 pm

What bothers me is the click once, click twice behavior, can this be done in vassal?

Should be possible using Map.pushMouseListener(), which replaces the default mouse listener with another implementation, which you can later pop off. See the Pivot or FreeRotator code for examples.

rk

Post generated using Mail2Forum (http://www.mail2forum.com)
rk
Site Admin
 
Posts: 536
Joined: October 21st, 2007, 3:31 am

Postby ghoust » June 3rd, 2008, 9:08 pm

Hi,

here are classes, which support grouping. To use them create a groupmap an add a groupcommand. Enjoy!
Next Step is a GroupRotator with the described effect above.

GroupStackMetrics .java
Code: Select all
package VASSAL.counters;

import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.AffineTransform;

import VASSAL.build.module.map.StackMetrics;


/**
 * GroupStackMetrics just displays the pieces as they are as we are only
 * interrested in grouping them, and not doing anything fancy with them
 * @author tmi
 *
 */
public class GroupStackMetrics extends StackMetrics {
    /**
      * Fill the argument arrays with the positions, selection bounds and bounding boxes of the pieces in the argument stack
      * @param parent The parent Stack
      * @param positions If non-null will contain a {@link Point} giving the position of each piece in <code>parent</code>
      * @param shapes If non-null will contain a {@link Shape} giving the shape of for each piece in <code>parent</code>
      * @param boundingBoxes If non-null will contain a {@link Rectangle} giving the bounding box for each piece in <code>parent</code>
      * @param x the x-location of the parent
      * @param y the y-location of the parent
      * @return the number of pieces processed in the stack
      */
   @Override
     public int getContents(Stack parent, Point[] positions, Shape[] shapes, Rectangle[] boundingBoxes, int x, int y) {
       int count = parent.getMaximumVisiblePieceCount();
       Point orgPos = null;
      
       if (positions != null) {
         count = Math.min(count, positions.length);
       }
       if (boundingBoxes != null) {
         count = Math.min(count, boundingBoxes.length);
       }
       if (shapes != null) {
         count = Math.min(count,shapes.length);
       }

       for (int index = 0; index <count>= 0)
      return new Point(before[i]);
   else
      return getPosition();
}

public void insertChild(GamePiece child, int index) {
    if ( child.getParent() != null) {
       child.getParent().remove(child);
      child.setParent(null);
    }
    else if (child.getMap() != null) {
      child.getMap().removePiece(child);
    }
    lastPos = child.getPosition();
    child.setParent(this);
    insertPieceAt(child, index);
    lastPos = null;
  }

protected void insertPieceAt(GamePiece p, int index) {
    if (pieceCount >= contents.length) {
      GamePiece[] newContents = new GamePiece[contents.length + INCR];
      System.arraycopy(contents, 0, newContents, 0, pieceCount);
      contents = newContents;
     
      Point[] newPoints = new Point[contents.length + INCR];
      System.arraycopy(before, 0, newPoints, 0, pieceCount);
      before = newPoints;
    }
    for (int i = pieceCount; i > index; --i) {
      contents[i] = contents[i - 1];
      before[i] = before[i - 1];
    }
    contents[index] = p;
    before[index] = new Point(lastPos.x-pos.x,lastPos.y-pos.y);
    lastPos =null;
    pieceCount++;
  }

protected void removePieceAt(int index) {
    if (index >= 0 && index < pieceCount) {
      //set pos relative to us otherwise the piece will drop to the center of teh group :(
      contents[index].setPosition(new Point(pos.x +before[index].x, pos.y +before[index].y));
      pieceCount--;
      for (int i = index; i <pieceCount> 1);
    }
  }

public void insert(GamePiece p, int pos) {
    if (p == null) {
      return;
    }
    pos = Math.max(pos, 0);
    pos = Math.min(pos, pieceCount);
    int index = indexOf(p);
    if (index >= 0) {
      if (pos > index) {
        insertPieceAt(p, pos + 1);
        removePieceAt(index);
      }
      else {
        removePieceAt(index);
        insertPieceAt(p, pos);
      }
    }
    else {
      insertChild(p, pos);
    }
  }


}


GroupCommand.java

Code: Select all
package VASSAL.counters;

import java.awt.Point;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Iterator;

import VASSAL.build.GameModule;
import VASSAL.build.module.Map;
import VASSAL.build.module.map.MassKeyCommand;

/**
 * Just create a stack out of the pieces the user has selected throwing away
 * any previous stack the pieces may have belonged to.
 */
public class GroupCommand extends MassKeyCommand {

   public void apply(Map m) {
      
   if(m == null)
      return;
   
   GamePiece[] p = m.getAllPieces();

   if(p.length <= 1)
      return;
   
   ArrayList<GamePiece> selected = new ArrayList<GamePiece>();
   //collect all selected
    for(int i=0; i<p> 0) {
       //collect positions before
       Point before = null;
       Point summ = new Point(0,0);
       for (int i=0; i<selected.size(); i++) {
          GamePiece s = selected.get(i);
          before = s.getPosition();
         summ.translate(before.x, before.y);
      }
       //create new group
       Group grp = new Group();
       grp.setMap(selected.get(0).getMap());
       //position group on map
       summ.x /= selected.size();
       summ.y /= selected.size();
       grp.setPosition(summ);
       System.out.println("grp x:"+summ.x+" y:"+summ.y);
       //add to new group
       for (int i=0; i<selected.size(); i++) {
          GamePiece s = selected.get(i);
          grp.add(s);
      }
       
       //add group to game
       grp.getMap().addPiece(grp);
       GameModule.getGameModule().getGameState().addPiece(grp);
       grp.getMap().repaint();
    }
}

   private ArrayList<GamePiece> getSelected(Group grp) {
      ArrayList<GamePiece> l = new ArrayList<GamePiece>();
      GamePiece p = null;
      for(Iterator<GamePiece> it = grp.getPiecesIterator();it.hasNext();) {
      p=it.next();
         if(Boolean.TRUE.equals(p.getProperty(Properties.SELECTED))) {
          l.add(p);
         }
      }
       return l;
   }

}


GroupingMap.java

Code: Select all
package VASSAL.build.module;

import java.awt.AlphaComposite;
import java.awt.Component;
import java.awt.Composite;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;

import VASSAL.build.module.map.StackMetrics;
import VASSAL.counters.GamePiece;
import VASSAL.counters.GroupStackMetrics;
import VASSAL.counters.Properties;
import VASSAL.counters.Stack;


public class GroupingMap extends Map {
   
   
   
     public StackMetrics getStackMetrics() {
          if (metrics == null) {
            metrics = new GroupStackMetrics();
            metrics.build(null);
            add(metrics);
            metrics.addTo(this);
          }
          return metrics;
        }
    
    
     public void drawPiecesInRegion(Graphics g,
              Rectangle visibleRect,
              Component c) {
if (!hideCounters) {
Graphics2D g2d = (Graphics2D) g;
Composite oldComposite = g2d.getComposite();
g2d.setComposite(
AlphaComposite.getInstance(AlphaComposite.SRC_OVER, pieceOpacity));
GamePiece[] stack = pieces.getPieces();
for (int i = 0; i < stack.length; ++i) {
Point pt = componentCoordinates(stack[i].getPosition());
if (stack[i] instanceof Stack) {
getStackMetrics().draw(
(Stack) stack[i], pt, g, this, getZoom(), visibleRect);
}
else {
stack[i].draw(g, pt.x, pt.y, c, getZoom());
if (Boolean.TRUE.equals(stack[i].getProperty(Properties.SELECTED))) {
highlighter.draw(stack[i], g, pt.x, pt.y, c, getZoom());
}
}
}
g2d.setComposite(oldComposite);
}
}

}
ghoust
 
Posts: 42
Joined: May 21st, 2008, 7:56 pm

Next

Return to Feature Requests

Who is online

Users browsing this forum: No registered users and 2 guests