Merge branch 'androidmultiaiplayers' into 'master'

3/4 player matches on Android

See merge request core-developers/forge!295
This commit is contained in:
Michael Kamensky
2018-03-21 18:20:22 +00:00
9 changed files with 154 additions and 89 deletions

View File

@@ -815,6 +815,10 @@ public class FDeckChooser extends FScreen {
/*if(selectedDeckType.equals(DeckType.STANDARD_CARDGEN_DECK)){ /*if(selectedDeckType.equals(DeckType.STANDARD_CARDGEN_DECK)){
return DeckgenUtil.buildCardGenDeck(lstDecks.getSelectedItem().getName()); return DeckgenUtil.buildCardGenDeck(lstDecks.getSelectedItem().getName());
}*/ }*/
//ensure a deck is selected first
if(lstDecks.getSelectedIndex() == -1){
lstDecks.setSelectedIndex(0);
}
DeckProxy proxy = lstDecks.getSelectedItem(); DeckProxy proxy = lstDecks.getSelectedItem();
if (proxy == null) { return null; } if (proxy == null) { return null; }
return proxy.getDeck(); return proxy.getDeck();

View File

@@ -43,7 +43,7 @@ import forge.util.Utils;
public abstract class LobbyScreen extends LaunchScreen implements ILobbyView { public abstract class LobbyScreen extends LaunchScreen implements ILobbyView {
private static final ForgePreferences prefs = FModel.getPreferences(); private static final ForgePreferences prefs = FModel.getPreferences();
private static final float PADDING = Utils.scale(5); private static final float PADDING = Utils.scale(5);
public static final int MAX_PLAYERS = 2; //8; //TODO: Support multiplayer public static final int MAX_PLAYERS = 4;
private static final FSkinFont VARIANTS_FONT = FSkinFont.get(12); private static final FSkinFont VARIANTS_FONT = FSkinFont.get(12);
// General variables // General variables
@@ -84,8 +84,6 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView {
public LobbyScreen(String headerCaption, FPopupMenu menu, GameLobby lobby0) { public LobbyScreen(String headerCaption, FPopupMenu menu, GameLobby lobby0) {
super(headerCaption, menu); super(headerCaption, menu);
initLobby(lobby0);
btnStart.setEnabled(false); //disable start button until decks loaded btnStart.setEnabled(false); //disable start button until decks loaded
add(lblPlayers); add(lblPlayers);
@@ -99,13 +97,23 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView {
@Override @Override
public void handleEvent(FEvent e) { public void handleEvent(FEvent e) {
int numPlayers = getNumPlayers(); int numPlayers = getNumPlayers();
while(lobby.getNumberOfSlots() < getNumPlayers()){
lobby.addSlot();
}
while(lobby.getNumberOfSlots() > getNumPlayers()){
lobby.removeSlot(lobby.getNumberOfSlots()-1);
}
for (int i = 0; i < MAX_PLAYERS; i++) { for (int i = 0; i < MAX_PLAYERS; i++) {
if(i<playerPanels.size()) {
playerPanels.get(i).setVisible(i < numPlayers); playerPanels.get(i).setVisible(i < numPlayers);
} }
}
playersScroll.revalidate(); playersScroll.revalidate();
} }
}); });
initLobby(lobby0);
add(lblVariants); add(lblVariants);
add(cbVariants); add(cbVariants);
cbVariants.setFont(VARIANTS_FONT); cbVariants.setFont(VARIANTS_FONT);
@@ -148,12 +156,16 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView {
public void run() { public void run() {
playerPanels.get(0).initialize(FPref.CONSTRUCTED_P1_DECK_STATE, FPref.COMMANDER_P1_DECK_STATE, FPref.TINY_LEADER_P1_DECK_STATE, DeckType.PRECONSTRUCTED_DECK); playerPanels.get(0).initialize(FPref.CONSTRUCTED_P1_DECK_STATE, FPref.COMMANDER_P1_DECK_STATE, FPref.TINY_LEADER_P1_DECK_STATE, DeckType.PRECONSTRUCTED_DECK);
playerPanels.get(1).initialize(FPref.CONSTRUCTED_P2_DECK_STATE, FPref.COMMANDER_P2_DECK_STATE, FPref.TINY_LEADER_P2_DECK_STATE, DeckType.COLOR_DECK); playerPanels.get(1).initialize(FPref.CONSTRUCTED_P2_DECK_STATE, FPref.COMMANDER_P2_DECK_STATE, FPref.TINY_LEADER_P2_DECK_STATE, DeckType.COLOR_DECK);
/*playerPanels.get(2).initialize(FPref.CONSTRUCTED_P3_DECK_STATE, DeckType.COLOR_DECK); if(getNumPlayers()>2) {
playerPanels.get(3).initialize(FPref.CONSTRUCTED_P4_DECK_STATE, DeckType.COLOR_DECK); playerPanels.get(2).initialize(FPref.CONSTRUCTED_P3_DECK_STATE, FPref.COMMANDER_P3_DECK_STATE, FPref.TINY_LEADER_P3_DECK_STATE, DeckType.COLOR_DECK);
playerPanels.get(4).initialize(FPref.CONSTRUCTED_P5_DECK_STATE, DeckType.COLOR_DECK); }
if(getNumPlayers()>3) {
playerPanels.get(3).initialize(FPref.CONSTRUCTED_P4_DECK_STATE, FPref.COMMANDER_P4_DECK_STATE, FPref.TINY_LEADER_P4_DECK_STATE, DeckType.COLOR_DECK);
}
/*playerPanels.get(4).initialize(FPref.CONSTRUCTED_P5_DECK_STATE, DeckType.COLOR_DECK);
playerPanels.get(5).initialize(FPref.CONSTRUCTED_P6_DECK_STATE, DeckType.COLOR_DECK); playerPanels.get(5).initialize(FPref.CONSTRUCTED_P6_DECK_STATE, DeckType.COLOR_DECK);
playerPanels.get(6).initialize(FPref.CONSTRUCTED_P7_DECK_STATE, DeckType.COLOR_DECK); playerPanels.get(6).initialize(FPref.CONSTRUCTED_P7_DECK_STATE, DeckType.COLOR_DECK);
playerPanels.get(7).initialize(FPref.CONSTRUCTED_P8_DECK_STATE, DeckType.COLOR_DECK);*/ //TODO: Support multiplayer and improve performance of loading this screen by using background thread playerPanels.get(7).initialize(FPref.CONSTRUCTED_P8_DECK_STATE, DeckType.COLOR_DECK);*/ //TODO: Improve performance of loading this screen by using background thread
FThreads.invokeInEdtLater(new Runnable() { FThreads.invokeInEdtLater(new Runnable() {
@Override @Override
@@ -164,9 +176,8 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView {
} }
}); });
//disable player count for now until multiplayer supported lblPlayers.setEnabled(true);
lblPlayers.setEnabled(false); cbPlayerCount.setEnabled(true);
cbPlayerCount.setEnabled(false);
} }
public GameLobby getLobby() { public GameLobby getLobby() {
@@ -180,6 +191,9 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView {
btnStart.setEnabled(hasControl); btnStart.setEnabled(hasControl);
lblVariants.setEnabled(hasControl); lblVariants.setEnabled(hasControl);
cbVariants.setEnabled(hasControl); cbVariants.setEnabled(hasControl);
while(lobby.getNumberOfSlots()<getNumPlayers()){
lobby.addSlot();
}
} }
private void updateVariantSelection() { private void updateVariantSelection() {
@@ -209,7 +223,7 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView {
} }
void updateLayoutForVariants() { void updateLayoutForVariants() {
for (int i = 0; i < MAX_PLAYERS; i++) { for (int i = 0; i < cbPlayerCount.getSelectedItem(); i++) {
playerPanels.get(i).updateVariantControlsVisibility(); playerPanels.get(i).updateVariantControlsVisibility();
} }
playersScroll.revalidate(); playersScroll.revalidate();
@@ -447,12 +461,11 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView {
@Override @Override
public void update(final boolean fullUpdate) { public void update(final boolean fullUpdate) {
int playerCount = lobby.getNumberOfSlots(); int playerCount = lobby.getNumberOfSlots();
cbPlayerCount.setSelectedItem(playerCount);
updateVariantSelection(); updateVariantSelection();
final boolean allowNetworking = lobby.isAllowNetworking(); final boolean allowNetworking = lobby.isAllowNetworking();
for (int i = 0; i < MAX_PLAYERS; i++) { for (int i = 0; i < cbPlayerCount.getSelectedItem(); i++) {
final boolean hasPanel = i < playerPanels.size(); final boolean hasPanel = i < playerPanels.size();
if (i < playerCount) { if (i < playerCount) {
// visible panels // visible panels
@@ -465,6 +478,12 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView {
} }
else { else {
panel = new PlayerPanel(this, allowNetworking, i, slot, lobby.mayEdit(i), lobby.hasControl()); panel = new PlayerPanel(this, allowNetworking, i, slot, lobby.mayEdit(i), lobby.hasControl());
if(i==2) {
panel.initialize(FPref.CONSTRUCTED_P3_DECK_STATE, FPref.COMMANDER_P3_DECK_STATE, FPref.TINY_LEADER_P3_DECK_STATE, DeckType.COLOR_DECK);
}
if(i==3) {
panel.initialize(FPref.CONSTRUCTED_P4_DECK_STATE, FPref.COMMANDER_P4_DECK_STATE, FPref.TINY_LEADER_P4_DECK_STATE, DeckType.COLOR_DECK);
}
playerPanels.add(panel); playerPanels.add(panel);
playersScroll.add(panel); playersScroll.add(panel);
isNewPanel = true; isNewPanel = true;

View File

@@ -232,7 +232,7 @@ public class PlayerPanel extends FContainer {
setMayControl(mayControl0); setMayControl(mayControl0);
//disable team combo boxes for now //disable team combo boxes for now
cbTeam.setEnabled(false); cbTeam.setEnabled(true);
} }
public void initialize(FPref savedStateSetting, FPref savedStateSettingCommander, FPref savedStateSettingTinyLeader, DeckType defaultDeckType) { public void initialize(FPref savedStateSetting, FPref savedStateSettingCommander, FPref savedStateSettingTinyLeader, DeckType defaultDeckType) {

View File

@@ -119,7 +119,7 @@ public class MatchController extends AbstractGuiGame {
final List<VPlayerPanel> playerPanels = new ArrayList<VPlayerPanel>(); final List<VPlayerPanel> playerPanels = new ArrayList<VPlayerPanel>();
for (final PlayerView p : allPlayers) { for (final PlayerView p : allPlayers) {
final boolean isLocal = isLocalPlayer(p); final boolean isLocal = isLocalPlayer(p);
final VPlayerPanel playerPanel = new VPlayerPanel(p, isLocal || noHumans); final VPlayerPanel playerPanel = new VPlayerPanel(p, isLocal || noHumans, allPlayers.size());
if (isLocal && !playerPanels.isEmpty()) { if (isLocal && !playerPanels.isEmpty()) {
playerPanels.add(0, playerPanel); //ensure local player always first among player panels playerPanels.add(0, playerPanel); //ensure local player always first among player panels
} }
@@ -359,7 +359,8 @@ public class MatchController extends AbstractGuiGame {
private static void actuateMatchPreferences() { private static void actuateMatchPreferences() {
final ForgePreferences prefs = FModel.getPreferences(); final ForgePreferences prefs = FModel.getPreferences();
final VPhaseIndicator fvAi = view.getTopPlayerPanel().getPhaseIndicator(); for (int i=0; i<view.getPlayerPanelsList().size()-1; ++i){
VPhaseIndicator fvAi = view.getPlayerPanelsList().get(i).getPhaseIndicator();
fvAi.getLabel(PhaseType.UPKEEP).setStopAtPhase(prefs.getPrefBoolean(FPref.PHASE_AI_UPKEEP)); fvAi.getLabel(PhaseType.UPKEEP).setStopAtPhase(prefs.getPrefBoolean(FPref.PHASE_AI_UPKEEP));
fvAi.getLabel(PhaseType.DRAW).setStopAtPhase(prefs.getPrefBoolean(FPref.PHASE_AI_DRAW)); fvAi.getLabel(PhaseType.DRAW).setStopAtPhase(prefs.getPrefBoolean(FPref.PHASE_AI_DRAW));
fvAi.getLabel(PhaseType.MAIN1).setStopAtPhase(prefs.getPrefBoolean(FPref.PHASE_AI_MAIN1)); fvAi.getLabel(PhaseType.MAIN1).setStopAtPhase(prefs.getPrefBoolean(FPref.PHASE_AI_MAIN1));
@@ -372,6 +373,7 @@ public class MatchController extends AbstractGuiGame {
fvAi.getLabel(PhaseType.MAIN2).setStopAtPhase(prefs.getPrefBoolean(FPref.PHASE_AI_MAIN2)); fvAi.getLabel(PhaseType.MAIN2).setStopAtPhase(prefs.getPrefBoolean(FPref.PHASE_AI_MAIN2));
fvAi.getLabel(PhaseType.END_OF_TURN).setStopAtPhase(prefs.getPrefBoolean(FPref.PHASE_AI_EOT)); fvAi.getLabel(PhaseType.END_OF_TURN).setStopAtPhase(prefs.getPrefBoolean(FPref.PHASE_AI_EOT));
fvAi.getLabel(PhaseType.CLEANUP).setStopAtPhase(prefs.getPrefBoolean(FPref.PHASE_AI_CLEANUP)); fvAi.getLabel(PhaseType.CLEANUP).setStopAtPhase(prefs.getPrefBoolean(FPref.PHASE_AI_CLEANUP));
}
final VPhaseIndicator fvHuman = view.getBottomPlayerPanel().getPhaseIndicator(); final VPhaseIndicator fvHuman = view.getBottomPlayerPanel().getPhaseIndicator();
fvHuman.getLabel(PhaseType.UPKEEP).setStopAtPhase(prefs.getPrefBoolean(FPref.PHASE_HUMAN_UPKEEP)); fvHuman.getLabel(PhaseType.UPKEEP).setStopAtPhase(prefs.getPrefBoolean(FPref.PHASE_HUMAN_UPKEEP));

View File

@@ -1,10 +1,6 @@
package forge.screens.match; package forge.screens.match;
import java.util.HashMap; import java.util.*;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry; import java.util.Map.Entry;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
@@ -63,6 +59,7 @@ public class MatchScreen extends FScreen {
public static FSkinColor BORDER_COLOR = FSkinColor.get(Colors.CLR_BORDERS); public static FSkinColor BORDER_COLOR = FSkinColor.get(Colors.CLR_BORDERS);
private final Map<PlayerView, VPlayerPanel> playerPanels = Maps.newHashMap(); private final Map<PlayerView, VPlayerPanel> playerPanels = Maps.newHashMap();
private List<VPlayerPanel> playerPanelsList;
private final VGameMenu gameMenu; private final VGameMenu gameMenu;
private final VPlayers players; private final VPlayers players;
private final VLog log; private final VLog log;
@@ -80,10 +77,16 @@ public class MatchScreen extends FScreen {
for (VPlayerPanel playerPanel : playerPanels0) { for (VPlayerPanel playerPanel : playerPanels0) {
playerPanels.put(playerPanel.getPlayer(), scroller.add(playerPanel)); playerPanels.put(playerPanel.getPlayer(), scroller.add(playerPanel));
playerPanel.setFlipped(true);
} }
bottomPlayerPanel = playerPanels0.get(0); bottomPlayerPanel = playerPanels0.get(0);
bottomPlayerPanel.setFlipped(false);
topPlayerPanel = playerPanels0.get(1); topPlayerPanel = playerPanels0.get(1);
topPlayerPanel.setFlipped(true); playerPanelsList=playerPanels0;
//reorder list so bottom player is at the end of the list ensuring top to bottom turn order
playerPanelsList.remove(bottomPlayerPanel);
playerPanelsList.add(bottomPlayerPanel);
bottomPlayerPrompt = add(new VPrompt("", "", bottomPlayerPrompt = add(new VPrompt("", "",
new FEventHandler() { new FEventHandler() {
@@ -154,6 +157,14 @@ public class MatchScreen extends FScreen {
} }
} }
private boolean is4Player(){
return playerPanels.keySet().size()==4;
}
private boolean is3Player(){
return playerPanels.keySet().size()==3;
}
private IGameController getGameController() { private IGameController getGameController() {
return MatchController.instance.getGameController(); return MatchController.instance.getGameController();
} }
@@ -274,6 +285,10 @@ public class MatchScreen extends FScreen {
return playerPanels; return playerPanels;
} }
public List<VPlayerPanel> getPlayerPanelsList() {
return playerPanelsList;
}
@Override @Override
public void onClose(Callback<Boolean> canCloseCallback) { public void onClose(Callback<Boolean> canCloseCallback) {
MatchController.writeMatchPreferences(); MatchController.writeMatchPreferences();
@@ -492,64 +507,64 @@ public class MatchScreen extends FScreen {
@Override @Override
public void drawOverlay(Graphics g) { public void drawOverlay(Graphics g) {
float midField = topPlayerPanel.getBottom(); float midField;
float x = 0; float x = 0;
float y = midField - topPlayerPanel.getField().getHeight(); float y;
float w = getWidth(); float w = getWidth();
//field separator lines //field separator lines
if (!Forge.isLandscapeMode()) { if (!Forge.isLandscapeMode()) {
if (topPlayerPanel.getSelectedTab() == null) { for (VPlayerPanel playerPanel: playerPanelsList){
y++; //ensure border goes all the way across under avatar midField = playerPanel.getTop();
y = midField - playerPanel.getField().getHeight();
if(playerPanel.getSelectedTab() == null) {
y++;
}
g.drawLine(1, BORDER_COLOR, x, y, w, y);
} }
g.drawLine(1, BORDER_COLOR, 0, y, w, y);
} }
for (VPlayerPanel playerPanel: playerPanelsList){
midField = playerPanel.getTop();
y = midField - 0.5f; y = midField - 0.5f;
g.drawLine(1, BORDER_COLOR, x, y, w, y); g.drawLine(1, BORDER_COLOR, x, y, w, y);
}
if (!Forge.isLandscapeMode()) { if (!Forge.isLandscapeMode()) {
y = midField + bottomPlayerPanel.getField().getHeight(); y = bottomPlayerPanel.getTop() + bottomPlayerPanel.getField().getHeight();
g.drawLine(1, BORDER_COLOR, 0, y, w, y); g.drawLine(1, BORDER_COLOR, x, y, w, y);
} }
} }
@Override
protected ScrollBounds layoutAndGetScrollBounds(float visibleWidth, float visibleHeight) { protected ScrollBounds layoutAndGetScrollBounds(float visibleWidth, float visibleHeight) {
float totalHeight = visibleHeight + extraHeight; float totalHeight = visibleHeight + extraHeight;
float avatarHeight = VAvatar.HEIGHT;
if(is4Player() || is3Player()){
avatarHeight *= 0.5f;
}
float playerCount = getPlayerPanels().keySet().size();
//determine player panel heights based on visibility of zone displays //determine player panel heights based on visibility of zone displays
float topPlayerPanelHeight, bottomPlayerPanelHeight; float cardRowsHeight = totalHeight - playerCount * avatarHeight;
if (Forge.isLandscapeMode()) { float totalCardRows=0;
topPlayerPanelHeight = totalHeight / 2; for(VPlayerPanel playerPanel:playerPanelsList){
bottomPlayerPanelHeight = topPlayerPanelHeight; if(playerPanel.getSelectedTab() != null){
totalCardRows += 1;
} }
else { totalCardRows += 2;
float cardRowsHeight = totalHeight - 2 * VAvatar.HEIGHT;
if (topPlayerPanel.getSelectedTab() == null) {
if (bottomPlayerPanel.getSelectedTab() != null) {
topPlayerPanelHeight = cardRowsHeight * 2f / 5f;
bottomPlayerPanelHeight = cardRowsHeight * 3f / 5f;
} }
else { float y=0;
topPlayerPanelHeight = cardRowsHeight / 2f; for(VPlayerPanel playerPanel:playerPanelsList){
bottomPlayerPanelHeight = topPlayerPanelHeight; float panelHeight;
if(playerPanel.getSelectedTab() != null){
panelHeight = cardRowsHeight * 3f / totalCardRows;
}else{
panelHeight = cardRowsHeight * 2f / totalCardRows;
} }
panelHeight += avatarHeight;
playerPanel.setBounds(0, y, visibleWidth, panelHeight);
y += panelHeight;
} }
else if (bottomPlayerPanel.getSelectedTab() == null) {
topPlayerPanelHeight = cardRowsHeight * 3f / 5f;
bottomPlayerPanelHeight = cardRowsHeight * 2f / 5f;
}
else {
topPlayerPanelHeight = cardRowsHeight / 2f;
bottomPlayerPanelHeight = topPlayerPanelHeight;
}
topPlayerPanelHeight += VAvatar.HEIGHT;
bottomPlayerPanelHeight += VAvatar.HEIGHT;
}
topPlayerPanel.setBounds(0, 0, visibleWidth, topPlayerPanelHeight);
bottomPlayerPanel.setBounds(0, totalHeight - bottomPlayerPanelHeight, visibleWidth, bottomPlayerPanelHeight);
return new ScrollBounds(visibleWidth, totalHeight); return new ScrollBounds(visibleWidth, totalHeight);
} }

View File

@@ -27,6 +27,12 @@ public class VAvatar extends FDisplayObject {
setSize(WIDTH, HEIGHT); setSize(WIDTH, HEIGHT);
} }
public VAvatar(PlayerView player0, float size) {
player = player0;
image = MatchController.getPlayerAvatar(player);
setSize(size, size);
}
@Override @Override
public boolean tap(float x, float y, int count) { public boolean tap(float x, float y, int count) {
ThreadUtil.invokeInGameThread(new Runnable() { //must invoke in game thread in case a dialog needs to be shown ThreadUtil.invokeInGameThread(new Runnable() { //must invoke in game thread in case a dialog needs to be shown

View File

@@ -45,13 +45,21 @@ public class VPlayerPanel extends FContainer {
private final Map<ZoneType, InfoTab> zoneTabs = new HashMap<ZoneType, InfoTab>(); private final Map<ZoneType, InfoTab> zoneTabs = new HashMap<ZoneType, InfoTab>();
private final List<InfoTab> tabs = new ArrayList<InfoTab>(); private final List<InfoTab> tabs = new ArrayList<InfoTab>();
private InfoTab selectedTab; private InfoTab selectedTab;
private float avatarHeight = VAvatar.HEIGHT;
private float displayAreaHeightFactor = 1.0f;
private boolean forMultiPlayer = false;
public VPlayerPanel(PlayerView player0, boolean showHand) { public VPlayerPanel(PlayerView player0, boolean showHand, int playerCount) {
player = player0; player = player0;
phaseIndicator = add(new VPhaseIndicator()); phaseIndicator = add(new VPhaseIndicator());
if(playerCount>2){
forMultiPlayer=true;
avatarHeight *= 0.5f;
//displayAreaHeightFactor *= 0.7f;
}
field = add(new VField(player)); field = add(new VField(player));
avatar = add(new VAvatar(player)); avatar = add(new VAvatar(player, avatarHeight));
lblLife = add(new LifeLabel()); lblLife = add(new LifeLabel());
addZoneDisplay(ZoneType.Hand, FSkinImage.HAND); addZoneDisplay(ZoneType.Hand, FSkinImage.HAND);
addZoneDisplay(ZoneType.Graveyard, FSkinImage.GRAVEYARD); addZoneDisplay(ZoneType.Graveyard, FSkinImage.GRAVEYARD);
@@ -200,23 +208,27 @@ public class VPlayerPanel extends FContainer {
} }
//layout for bottom panel by default //layout for bottom panel by default
float x = VAvatar.WIDTH; float x = avatarHeight;
float w = width - VAvatar.WIDTH; float w = width - avatarHeight;
float h = phaseIndicator.getPreferredHeight(w); float indicatorScale = 1f;
if(avatarHeight<VAvatar.HEIGHT){
indicatorScale = 0.6f;
}
float h = phaseIndicator.getPreferredHeight(w) * indicatorScale;
phaseIndicator.setBounds(x, height - h, w, h); phaseIndicator.setBounds(x, height - h, w, h);
float y = height - VAvatar.HEIGHT; float y = height - avatarHeight;
float displayAreaHeight = y / 3; float displayAreaHeight = displayAreaHeightFactor * y / 3;
y -= displayAreaHeight; y -= displayAreaHeight;
for (InfoTab tab : tabs) { for (InfoTab tab : tabs) {
tab.displayArea.setBounds(0, y, width, displayAreaHeight); tab.displayArea.setBounds(0, y, width, displayAreaHeight);
} }
y = height - VAvatar.HEIGHT; y = height - avatarHeight;
avatar.setPosition(0, y); avatar.setPosition(0, y);
float lifeLabelWidth = LIFE_FONT.getBounds("99").width * 1.2f; //make just wide enough for 2-digit life totals float lifeLabelWidth = LIFE_FONT.getBounds("99").width * 1.2f * indicatorScale; //make just wide enough for 2-digit life totals
float infoLabelHeight = VAvatar.HEIGHT - phaseIndicator.getHeight(); float infoLabelHeight = avatarHeight - phaseIndicator.getHeight();
lblLife.setBounds(x, y, lifeLabelWidth, infoLabelHeight); lblLife.setBounds(x, y, lifeLabelWidth, infoLabelHeight);
x += lifeLabelWidth; x += lifeLabelWidth;
@@ -461,9 +473,11 @@ public class VPlayerPanel extends FContainer {
else { else {
g.startClip(-1, y, w + 2, yAcross - y); g.startClip(-1, y, w + 2, yAcross - y);
} }
if(forMultiPlayer) {
g.drawLine(1, MatchScreen.BORDER_COLOR, 0, yAcross, w, yAcross); g.drawLine(1, MatchScreen.BORDER_COLOR, 0, yAcross, w, yAcross);
g.drawLine(1, MatchScreen.BORDER_COLOR, 0, y, 0, h); g.drawLine(1, MatchScreen.BORDER_COLOR, 0, y, 0, h);
g.drawLine(1, MatchScreen.BORDER_COLOR, w, y, w, h); g.drawLine(1, MatchScreen.BORDER_COLOR, w, y, w, h);
}
g.endClip(); g.endClip();
} }
} }

View File

@@ -238,7 +238,12 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards {
// Don't immediately close, wait for win/lose screen // Don't immediately close, wait for win/lose screen
return false; return false;
} else { } else {
return true; for(PlayerView player: getLocalPlayers()){
if(!player.isAI()){
getGameController(player).nextGameDecision(NextGameDecision.QUIT);
}
}
return false;
} }
} }
else if (spectator == null) { else if (spectator == null) {
@@ -421,7 +426,7 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards {
* @return null if choices is missing, empty, or if the users' choices are * @return null if choices is missing, empty, or if the users' choices are
* empty; otherwise, returns the first item in the List returned by * empty; otherwise, returns the first item in the List returned by
* getChoices. * getChoices.
* @see #getChoices(String, int, int, Object...) * @see #getChoices(String, int, int, List)
*/ */
@Override @Override
public <T> T oneOrNone(final String message, final List<T> choices) { public <T> T oneOrNone(final String message, final List<T> choices) {

View File

@@ -177,7 +177,7 @@ public abstract class GameLobby implements IHasGameType {
slot.setIsArchenemy(true); slot.setIsArchenemy(true);
lastArchenemy = 0; lastArchenemy = 0;
} }
updateView(false); updateView(true);
} }
private String randomName() { private String randomName() {
final List<String> names = Lists.newArrayListWithCapacity(MAX_PLAYERS); final List<String> names = Lists.newArrayListWithCapacity(MAX_PLAYERS);