Merge branch 'master' into 'master'

[Mobile] Add Card Tap/Untap & Match Background Animation

See merge request core-developers/forge!5384
This commit is contained in:
Michael Kamensky
2021-09-18 07:03:11 +00:00
14 changed files with 190 additions and 11 deletions

View File

@@ -70,6 +70,7 @@ public class Forge implements ApplicationListener {
public static boolean allowCardBG = false;
public static boolean altPlayerLayout = false;
public static boolean altZoneTabs = false;
public static boolean animatedCardTapUntap = false;
public static String enableUIMask = "Crop";
public static boolean enablePreloadExtendedArt = false;
public static boolean isTabletDevice = false;
@@ -146,6 +147,7 @@ public class Forge implements ApplicationListener {
showFPS = prefs.getPrefBoolean(FPref.UI_SHOW_FPS);
altPlayerLayout = prefs.getPrefBoolean(FPref.UI_ALT_PLAYERINFOLAYOUT);
altZoneTabs = prefs.getPrefBoolean(FPref.UI_ALT_PLAYERZONETABS);
animatedCardTapUntap = prefs.getPrefBoolean(FPref.UI_ANIMATED_CARD_TAPUNTAP);
enableUIMask = prefs.getPref(FPref.UI_ENABLE_BORDER_MASKING);
if (prefs.getPref(FPref.UI_ENABLE_BORDER_MASKING).equals("true")) //override old settings if not updated
enableUIMask = "Full";

View File

@@ -7,6 +7,8 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import forge.animation.ForgeAnimation;
import forge.assets.FImage;
import org.apache.commons.lang3.tuple.Pair;
import com.badlogic.gdx.Input.Keys;
@@ -76,7 +78,7 @@ public class MatchScreen extends FScreen {
private final VPrompt bottomPlayerPrompt, topPlayerPrompt;
private VPlayerPanel bottomPlayerPanel, topPlayerPanel;
private AbilityEffect activeEffect;
private BGAnimation bgAnimation;
private ViewWinLose viewWinLose = null;
public MatchScreen(List<VPlayerPanel> playerPanels0) {
@@ -577,14 +579,45 @@ public class MatchScreen extends FScreen {
}
}
private class BGAnimation extends ForgeAnimation {
private static final float DURATION = 0.2f;
private float progress = 0;
private boolean finished;
private void drawBackground(Graphics g, FImage image, float x, float y, float w, float h, boolean darkoverlay) {
float percentage = progress / DURATION;
float oldAlpha = g.getfloatAlphaComposite();
if (percentage < 0) {
percentage = 0;
} else if (percentage > 1) {
percentage = 1;
}
g.setAlphaComposite(percentage);
g.drawImage(image, x, y, w, h, darkoverlay);
g.setAlphaComposite(oldAlpha);
}
@Override
protected boolean advance(float dt) {
progress += dt;
return progress < DURATION;
}
@Override
protected void onEnd(boolean endingAll) {
finished = true;
}
}
private class FieldScroller extends FScrollPane {
private float extraHeight = 0;
private String plane = "";
@Override
public void drawBackground(Graphics g) {
super.drawBackground(g);
if (FModel.getPreferences().getPrefBoolean(FPref.UI_MATCH_IMAGE_VISIBLE)) {
boolean isGameFast = MatchController.instance.isGameFast();
float midField = topPlayerPanel.getBottom();
float x = topPlayerPanel.getField().getLeft();
float y = midField - topPlayerPanel.getField().getHeight();
@@ -598,6 +631,11 @@ public class MatchScreen extends FScreen {
.replace(" ", "_")
.replace("'", "")
.replace("-", "");
if (!plane.equals(imageName)) {
bgAnimation = new BGAnimation();
bgAnimation.start();
plane = imageName;
}
if (FSkinTexture.getValues().contains(imageName)) {
bgFullWidth = bgHeight * FSkinTexture.valueOf(imageName).getWidth() / FSkinTexture.valueOf(imageName).getHeight();
if (bgFullWidth < w) {
@@ -605,10 +643,13 @@ public class MatchScreen extends FScreen {
bgFullWidth = w;
bgHeight = scaledbgHeight;
}
g.drawImage(FSkinTexture.valueOf(imageName), x + (w - bgFullWidth) / 2, y, bgFullWidth, bgHeight, true);
if (bgAnimation != null && !isGameFast) {
bgAnimation.drawBackground(g, FSkinTexture.valueOf(imageName), x + (w - bgFullWidth) / 2, y, bgFullWidth, bgHeight, true);
} else {
g.drawImage(FSkinTexture.valueOf(imageName), x + (w - bgFullWidth) / 2, y, bgFullWidth, bgHeight, true);
}
}
}
else {
} else {
bgFullWidth = bgHeight * FSkinTexture.BG_MATCH.getWidth() / FSkinTexture.BG_MATCH.getHeight();
if (bgFullWidth < w) {
scaledbgHeight = w * (bgHeight / bgFullWidth);

View File

@@ -259,6 +259,16 @@ public class SettingsPage extends TabPage<SettingsScreen> {
MatchController.instance.resetPlayerPanels();
}
},1);
lstSettings.addItem(new BooleanSetting(FPref.UI_ANIMATED_CARD_TAPUNTAP,
localizer.getMessage("lblAnimatedCardTapUntap"),
localizer.getMessage("nlAnimatedCardTapUntap")){
@Override
public void select() {
super.select();
//update
Forge.animatedCardTapUntap = FModel.getPreferences().getPrefBoolean(FPref.UI_ANIMATED_CARD_TAPUNTAP);
}
},1);
//Random Deck Generation
lstSettings.addItem(new BooleanSetting(FPref.DECKGEN_NOSMALL,

View File

@@ -1,9 +1,13 @@
package forge.toolbox;
import forge.Forge;
import forge.Graphics;
import forge.animation.ForgeAnimation;
import forge.card.CardRenderer;
import forge.card.CardRenderer.CardStackPosition;
import forge.game.card.CardView;
import forge.game.zone.ZoneType;
import forge.screens.match.MatchController;
import forge.util.Utils;
public class FCardPanel extends FDisplayObject {
@@ -15,12 +19,17 @@ public class FCardPanel extends FDisplayObject {
private CardView card;
private boolean tapped;
private boolean highlighted;
private boolean wasTapped;
CardTapAnimation tapAnimation;
CardUnTapAnimation untapAnimation;
public FCardPanel() {
this(null);
}
public FCardPanel(CardView card0) {
card = card0;
tapAnimation = new CardTapAnimation();
untapAnimation = new CardUnTapAnimation();
}
public CardView getCard() {
@@ -76,10 +85,75 @@ public class FCardPanel extends FDisplayObject {
return CardStackPosition.Top;
}
private class CardUnTapAnimation extends ForgeAnimation {
private static final float DURATION = 0.14f;
private float progress = 0;
private boolean finished;
private void drawCard(Graphics g, CardView card, float x, float y, float w, float h, float edgeOffset) {
float percentage = progress / DURATION;
if (percentage < 0) {
percentage = 0;
} else if (percentage > 1) {
percentage = 1;
}
float angle = -90 + (percentage*90);
if (wasTapped) {
g.startRotateTransform(x + edgeOffset, y + h - edgeOffset, angle);
CardRenderer.drawCardWithOverlays(g, card, x, y, w, h, getStackPosition());
g.endTransform();
} else {
CardRenderer.drawCardWithOverlays(g, card, x, y, w, h, getStackPosition());
}
}
@Override
protected boolean advance(float dt) {
progress += dt;
return progress < DURATION;
}
@Override
protected void onEnd(boolean endingAll) {
finished = true;
}
}
private class CardTapAnimation extends ForgeAnimation {
private static final float DURATION = 0.18f;
private float progress = 0;
private boolean finished;
private void drawCard(Graphics g, CardView card, float x, float y, float w, float h, float edgeOffset, float angle) {
float percentage = progress / DURATION;
if (percentage > 1) {
percentage = 1;
wasTapped = true;
}
g.startRotateTransform(x + edgeOffset, y + h - edgeOffset, percentage*angle);
CardRenderer.drawCardWithOverlays(g, card, x, y, w, h, getStackPosition());
g.endTransform();
}
@Override
protected boolean advance(float dt) {
progress += dt;
return progress < DURATION;
}
@Override
protected void onEnd(boolean endingAll) {
finished = true;
}
}
@Override
public void draw(Graphics g) {
if (card == null) { return; }
boolean isGameFast = MatchController.instance.isGameFast();
boolean animate = ZoneType.Battlefield.equals(card.getZone()) && Forge.animatedCardTapUntap;
float padding = getPadding();
float x = padding;
float y = padding;
@@ -88,16 +162,50 @@ public class FCardPanel extends FDisplayObject {
if (w == h) { //adjust width if needed to make room for tapping
w = h / ASPECT_RATIO;
}
float edgeOffset = w / 2f;
if (isGameFast) {
//don't animate if fast
if (tapped) {
g.startRotateTransform(x + edgeOffset, y + h - edgeOffset, getTappedAngle());
}
if (tapped) {
float edgeOffset = w / 2f;
g.startRotateTransform(x + edgeOffset, y + h - edgeOffset, getTappedAngle());
}
CardRenderer.drawCardWithOverlays(g, card, x, y, w, h, getStackPosition());
CardRenderer.drawCardWithOverlays(g, card, x, y, w, h, getStackPosition());
if (tapped) {
g.endTransform();
}
if (tapped) {
g.endTransform();
} else {
if (tapped) {
//reset untapAnimation
if (untapAnimation != null) {
untapAnimation.progress = 0;
}
//draw tapped
if (tapAnimation != null) {
if (tapAnimation.progress < 1 && animate) {
tapAnimation.start();
tapAnimation.drawCard(g, card, x, y, w, h, w / 2f, getTappedAngle());
} else {
g.startRotateTransform(x + edgeOffset, y + h - edgeOffset, getTappedAngle());
CardRenderer.drawCardWithOverlays(g, card, x, y, w, h, getStackPosition());
g.endTransform();
}
}
} else {
//reset tapAnimation
if (tapAnimation != null) {
tapAnimation.progress = 0;
}
//draw untapped
if (untapAnimation.progress < 1 && animate) {
untapAnimation.start();
untapAnimation.drawCard(g, card, x, y, w, h, edgeOffset);
} else {
wasTapped = false;
CardRenderer.drawCardWithOverlays(g, card, x, y, w, h, getStackPosition());
}
}
}
}

View File

@@ -121,6 +121,8 @@ lblAltLifeDisplay=Alternatives Spieler-Layout (Landscape-Modus)
nlAltLifeDisplay=Alternative Anzeige von Lebens-, Gift-, Energie- und Erfahrungspunkten.
lblAltZoneTabs=Alternatives Spielerbereich-Layout (Landscape-Modus)
nlAltZoneTabs=Alternative Anzeige von Kartenhand, Friedhof, Bibliothek und Exilzone.
lblAnimatedCardTapUntap=Enable Card Tap & Untap Animation
nlAnimatedCardTapUntap=Enables Card Tap & Untap Animation during gameplay.
lblPreferredArt=Kartenbild-Präferenz
nlPreferredArt=Gibt an, welche Grafik für Karten ausgewählt werden soll, wenn keine Edition angegeben ist.
lblPrefArtExpansionOnly=Kartenbilder aus Haupt-, Erweiterungs- und Reprint-Sets bevorzugen

View File

@@ -122,6 +122,8 @@ lblAltLifeDisplay=Alternate Player Layout (Landscape Mode)
nlAltLifeDisplay=Enables alternate layout for displaying Player Life, Poison, Energy and Experience counters.
lblAltZoneTabs=Alternate Player Zone Layout (Landscape Mode)
nlAltZoneTabs=Enables alternate layout for displaying Player Hand, Graveyard, Library and Exile zones.
lblAnimatedCardTapUntap=Enable Card Tap & Untap Animation
nlAnimatedCardTapUntap=Enables Card Tap & Untap Animation during gameplay.
lblPreferredArt=Card Art Preference
nlPreferredArt=Specifies which art should be selected for cards when no Edition is specified.
lblPrefArtExpansionOnly=Prefer Card Art from Core, Expansions, and Reprint Sets

View File

@@ -122,6 +122,8 @@ lblAltLifeDisplay=Diseño alternativo de jugador (Modo apaisado)
nlAltLifeDisplay=Permite un diseño alternativo para mostrar los contadores de vida, veneno, energía y experiencia.
lblAltZoneTabs=Diseño alternativo de la zona del jugador (Modo apaisado)
nlAltZoneTabs=Permite un diseño alternativo para mostrar las zonas de la mano del jugador, el cementerio, la biblioteca y el exilio.
lblAnimatedCardTapUntap=Enable Card Tap & Untap Animation
nlAnimatedCardTapUntap=Enables Card Tap & Untap Animation during gameplay.
lblPreferredArt=Preferencia de arte de carta
nlPreferredArt=Especifica qué arte debe seleccionarse para las cartas cuando no se especifica ninguna edición.
lblPrefArtExpansionOnly=Prefiere el arte de la carta de los conjuntos básicos, de expansión y de reimpresión

View File

@@ -121,6 +121,8 @@ lblAltLifeDisplay=Layout alternativo del giocatore (modalità panorama)
nlAltLifeDisplay=Abilita un layout alternativo per visalizzare i punti vita e i segnalini veleno, energia ed esperienza di un giocatore.
lblAltZoneTabs=Layout alternativo delle zone di gioco (modalità panorama)
nlAltZoneTabs=Abilita un layout alternativo per visalizzare la mano del giocatore, il cimitero, il grimorio e la zona di esilio.
lblAnimatedCardTapUntap=Enable Card Tap & Untap Animation
nlAnimatedCardTapUntap=Enables Card Tap & Untap Animation during gameplay.
lblPreferredArt=Preferenza per Illustrazione delle Carte
nlPreferredArt=Specifica quale illustrazione viene scelta per le carte, quando non è specificata alcuna espansione.
lblPrefArtExpansionOnly=Limita la selezione dell'illustrazione delle carte da Set Base, Espansioni, e Set Ristampa

View File

@@ -122,6 +122,8 @@ lblAltLifeDisplay=代替のプレイヤーライフレイアウト(ランド
nlAltLifeDisplay=代替のレイアウトでプレイヤーライフ、毒、エネルギーと経験カウンターを表示する
lblAltZoneTabs=代替のプレイヤーゾーンレイアウト(ランドスケープモード時)
nlAltZoneTabs=代替のレイアウトで手札、墓地、ライブラリーと除外領域を表示する
lblAnimatedCardTapUntap=Enable Card Tap & Untap Animation
nlAnimatedCardTapUntap=Enables Card Tap & Untap Animation during gameplay.
lblPreferredArt=カードアートの好み
nlPreferredArt=エディションが指定されていない場合にカードに選択するアートを指定します。
lblPrefArtExpansionOnly=コア、拡張、および再版セットからカードアートを好む

View File

@@ -122,6 +122,8 @@ lblAltLifeDisplay=备用牌手布局(横向模式)
nlAltLifeDisplay=启用备用牌手布局以显示玩家的生命以及中毒,能量和经验指示物。
lblAltZoneTabs=备用牌手区域布局(用于横向模式)
nlAltZoneTabs=启用用于显示牌手手牌、坟场、牌库、放逐区的备用布局。
lblAnimatedCardTapUntap=Enable Card Tap & Untap Animation
nlAnimatedCardTapUntap=Enables Card Tap & Untap Animation during gameplay.
lblPreferredArt=卡片艺术偏好
nlPreferredArt=指定在未指定版本时应为卡片选择哪种艺术。
lblPrefArtExpansionOnly=首选核心、扩展和重印套装中的卡片艺术

View File

@@ -43,6 +43,7 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards {
private final Map<PlayerView, IGameController> gameControllers = Maps.newHashMap();
private final Map<PlayerView, IGameController> originalGameControllers = Maps.newHashMap();
private boolean gamePause = false;
private boolean gameSpeed = false;
private boolean ignoreConcedeChain = false;
public final boolean hasLocalPlayers() {
@@ -281,7 +282,9 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards {
return !selectableCards.isEmpty();
}
public boolean isGamePaused() { return gamePause; }
public boolean isGameFast() { return gameSpeed; }
public void setgamePause(boolean pause) { gamePause = pause; }
public void setGameSpeed(boolean isFast) { gameSpeed = isFast; }
public void pauseMatch() {
IGameController controller = spectator;
if (controller != null && !isGamePaused())

View File

@@ -77,6 +77,7 @@ public class InputPlaybackControl extends InputSyncronizedBase {
else {
isFast = !isFast;
control.setSpeed(isFast);
getController().getGui().setGameSpeed(isFast);
setPause(isPaused); // update message
}
}

View File

@@ -174,6 +174,7 @@ public interface IGuiGame {
boolean isSelecting();
boolean isGamePaused();
public void setgamePause(boolean pause);
public void setGameSpeed(boolean gameSpeed);
void awaitNextInput();
void cancelAwaitNextInput();

View File

@@ -146,6 +146,7 @@ public class ForgePreferences extends PreferencesStore<ForgePreferences.FPref> {
UI_ANDROID_MINIMIZE_ON_SCRLOCK("false"),
UI_ROTATE_PLANE_OR_PHENOMENON("false"),
UI_ROTATE_SPLIT_CARDS("true"),
UI_ANIMATED_CARD_TAPUNTAP("true"),
UI_DYNAMIC_PLANECHASE_BG("false"),
UI_DISABLE_IMAGES_EFFECT_CARDS("false"),
UI_ENABLE_PRELOAD_EXTENDED_ART("false"),