Merge branch 'master' into 'master'

[Mobile] Fix targeting arrows on Netplay

See merge request core-developers/forge!5502
This commit is contained in:
Michael Kamensky
2021-10-05 06:16:02 +00:00
8 changed files with 55 additions and 63 deletions

View File

@@ -854,6 +854,16 @@ public class CardView extends GameEntityView {
public void updateNeedsTransformAnimation(boolean value) {
set(TrackableProperty.NeedsTransformAnimation, value);
}
public Float getTargetingOriginVectorX() {
return get(TrackableProperty.TargetingOriginVectorX);
}
public Float getTargetingOriginVectorY() {
return get(TrackableProperty.TargetingOriginVectorY);
}
public void setTargetingOriginVector(float x, float y) {
set(TrackableProperty.TargetingOriginVectorX, x);
set(TrackableProperty.TargetingOriginVectorY, y);
}
void updateState(Card c) {
updateName(c);
updateZoneText(c);

View File

@@ -83,6 +83,8 @@ public enum TrackableProperty {
NeedsTransformAnimation(TrackableTypes.BooleanType, FreezeMode.IgnoresFreeze),
NeedsUntapAnimation(TrackableTypes.BooleanType, FreezeMode.IgnoresFreeze),
NeedsTapAnimation(TrackableTypes.BooleanType, FreezeMode.IgnoresFreeze),
TargetingOriginVectorX(TrackableTypes.FloatType, FreezeMode.IgnoresFreeze),
TargetingOriginVectorY(TrackableTypes.FloatType, FreezeMode.IgnoresFreeze),
ImprintedCards(TrackableTypes.CardViewCollectionType),
HauntedBy(TrackableTypes.CardViewCollectionType),

View File

@@ -162,6 +162,22 @@ public class TrackableTypes {
ts.write(value);
}
};
public static final TrackableType<Float> FloatType = new TrackableType<Float>() {
@Override
public Float getDefaultValue() {
return 0f;
}
@Override
public Float deserialize(TrackableDeserializer td, Float oldValue) {
return td.readFloat();
}
@Override
public void serialize(TrackableSerializer ts, Float value) {
ts.write(value);
}
};
public static final TrackableType<String> StringType = new TrackableType<String>() {
@Override
public String getDefaultValue() {

View File

@@ -3,6 +3,7 @@ package forge.screens.match;
import java.util.*;
import java.util.Map.Entry;
import com.badlogic.gdx.math.Vector2;
import forge.animation.ForgeAnimation;
import forge.assets.FImage;
import forge.game.spellability.StackItemView;
@@ -405,14 +406,13 @@ public class MatchScreen extends FScreen {
}
//draw arrows for paired cards
Set<CardView> pairedCards = new HashSet<>();
for (VPlayerPanel playerPanel : playerPanels.values()) {
for (CardView card : playerPanel.getField().getRow1().getOrderedCards()) {
if (pairedCards.contains(card)) { continue; } //prevent arrows going both ways
if (card != null) {
if (card.getPairedWith() != null) {
TargetingOverlay.drawArrow(g, card, card.getPairedWith());
final Vector2 vCard = new Vector2(card.getTargetingOriginVectorX(), card.getTargetingOriginVectorY());
final Vector2 vPairedWith = new Vector2(card.getPairedWith().getTargetingOriginVectorX(), card.getPairedWith().getTargetingOriginVectorY());
TargetingOverlay.drawArrow(g, vCard, vPairedWith, TargetingOverlay.ArcConnection.Friends);
}
}
}
@@ -425,28 +425,36 @@ public class MatchScreen extends FScreen {
//connect each attacker with planeswalker it's attacking if applicable
final GameEntityView defender = combat.getDefender(attacker);
if (defender instanceof CardView) {
TargetingOverlay.drawArrow(g, attacker, (CardView) defender);
final Vector2 vDefender = new Vector2(((CardView) defender).getTargetingOriginVectorX(), ((CardView) defender).getTargetingOriginVectorY());
final Vector2 vAttacker = new Vector2(attacker.getTargetingOriginVectorX(), attacker.getTargetingOriginVectorY());
TargetingOverlay.drawArrow(g, vAttacker, vDefender, TargetingOverlay.ArcConnection.FoesAttacking);
}
final Iterable<CardView> blockers = combat.getBlockers(attacker);
if (blockers != null) {
//connect each blocker with the attacker it's blocking
for (final CardView blocker : blockers) {
TargetingOverlay.drawArrow(g, blocker, attacker);
final Vector2 vBlocker = new Vector2(blocker.getTargetingOriginVectorX(), blocker.getTargetingOriginVectorY());
final Vector2 vAttacker = new Vector2(attacker.getTargetingOriginVectorX(), attacker.getTargetingOriginVectorY());
TargetingOverlay.drawArrow(g, vBlocker, vAttacker, TargetingOverlay.ArcConnection.FoesBlocking);
}
}
final Iterable<CardView> plannedBlockers = combat.getPlannedBlockers(attacker);
if (plannedBlockers != null) {
//connect each planned blocker with the attacker it's blocking
for (final CardView blocker : plannedBlockers) {
TargetingOverlay.drawArrow(g, blocker, attacker);
final Vector2 vBlocker = new Vector2(blocker.getTargetingOriginVectorX(), blocker.getTargetingOriginVectorY());
final Vector2 vAttacker = new Vector2(attacker.getTargetingOriginVectorX(), attacker.getTargetingOriginVectorY());
TargetingOverlay.drawArrow(g, vBlocker, vAttacker, TargetingOverlay.ArcConnection.FoesBlocking);
}
}
//player
if (is4Player() || is3Player()) {
int numplayers = is3Player() ? 3 : 4;
for (final PlayerView p : game.getPlayers()) {
if (combat.getAttackersOf(p).contains(attacker))
TargetingOverlay.drawArrow(g, attacker, p, numplayers);
if (combat.getAttackersOf(p).contains(attacker)) {
final Vector2 vAttacker = new Vector2(attacker.getTargetingOriginVectorX(), attacker.getTargetingOriginVectorY());
final Vector2 vPlayer = MatchController.getView().getPlayerPanel(p).getAvatar().getTargetingArrowOrigin();
TargetingOverlay.drawArrow(g, vAttacker, vPlayer, TargetingOverlay.ArcConnection.FoesAttacking);
}
}
}
}

View File

@@ -63,42 +63,6 @@ public class TargetingOverlay {
private TargetingOverlay() {
}
public static void drawArrow(Graphics g, CardView startCard, CardView endCard) {
ArcConnection connects;
if (startCard.getOwner().isOpponentOf((endCard.getOwner()))) {
if (startCard.isAttacking()) {
connects = ArcConnection.FoesAttacking;
} else {
connects = ArcConnection.FoesBlocking;
}
} else {
connects = ArcConnection.Friends;
}
drawArrow(g, CardAreaPanel.get(startCard).getTargetingArrowOrigin(),
CardAreaPanel.get(endCard).getTargetingArrowOrigin(),
connects);
}
public static void drawArrow(Graphics g, CardView startCard, PlayerView targetPlayer, int numplayers) {
drawArrow(g, CardAreaPanel.get(startCard).getTargetingArrowOrigin(),
MatchController.getView().getPlayerPanel(targetPlayer).getAvatar().getTargetingArrowOrigin(numplayers),
ArcConnection.FoesAttacking);
}
public static void drawArrow(Graphics g, Vector2 start, CardView targetCard, ArcConnection connects) {
drawArrow(g, start,
CardAreaPanel.get(targetCard).getTargetingArrowOrigin(),
connects);
}
public static void drawArrow(Graphics g, Vector2 start, PlayerView targetPlayer, ArcConnection connects) {
drawArrow(g, start,
MatchController.getView().getPlayerPanel(targetPlayer).getAvatar().getTargetingArrowOrigin(),
connects);
}
public static void drawArrow(Graphics g, FDisplayObject startCardDisplay, FDisplayObject endCardDisplay, ArcConnection connects) {
drawArrow(g, CardAreaPanel.getTargetingArrowOrigin(startCardDisplay, false),
CardAreaPanel.getTargetingArrowOrigin(endCardDisplay, false),
connects);
}
public static void drawArrow(Graphics g, Vector2 start, Vector2 end, ArcConnection connects) {
if (start == null || end == null) { return; }

View File

@@ -106,21 +106,9 @@ public class VAvatar extends FDisplayObject {
}
public Vector2 getTargetingArrowOrigin() {
return getTargetingArrowOrigin(2);
}
public Vector2 getTargetingArrowOrigin(int numplayers) {
Vector2 origin = new Vector2(screenPos.x, screenPos.y);
float modx = numplayers > 2 ? 0.25f : 0.75f;
origin.x += WIDTH * modx;
if (origin.y < MatchController.getView().getHeight() / numplayers) {
origin.y += HEIGHT * 0.75f; //target bottom right corner if on top half of screen
}
else {
origin.y += HEIGHT * 0.25f; //target top right corner if on bottom half of screen
}
Vector2 origin = new Vector2(this.screenPos.x, this.screenPos.y);
origin.x += getWidth()/2f;
origin.y += getWidth()/2f;
return origin;
}

View File

@@ -229,11 +229,11 @@ public class VStack extends FDropDown {
while (instance != null) {
for (CardView c : instance.getTargetCards()) {
TargetingOverlay.ArcConnection conn = activator.isOpponentOf(c.getController()) ? TargetingOverlay.ArcConnection.FoesStackTargeting : TargetingOverlay.ArcConnection.FriendsStackTargeting;
TargetingOverlay.drawArrow(g, arrowOrigin, c, conn);
TargetingOverlay.drawArrow(g, arrowOrigin, new Vector2(c.getTargetingOriginVectorX(), c.getTargetingOriginVectorY()), conn);
}
for (PlayerView p : instance.getTargetPlayers()) {
TargetingOverlay.ArcConnection conn = activator.isOpponentOf(p) ? TargetingOverlay.ArcConnection.FoesStackTargeting : TargetingOverlay.ArcConnection.FriendsStackTargeting;
TargetingOverlay.drawArrow(g, arrowOrigin, p, conn);
TargetingOverlay.drawArrow(g, arrowOrigin, MatchController.getView().getPlayerPanel(p).getAvatar().getTargetingArrowOrigin(), conn);
}
instance = instance.getSubInstance();
}

View File

@@ -101,12 +101,16 @@ public class FCardPanel extends FDisplayObject {
float x = padding-mod/2;
float y = padding-mod/2;
float w = (getWidth() - 2 * padding)+mod;
float xoffset = w / 2f;
float h = (getHeight() - 2 * padding)+mod;
float yoffset = h / 2f;
if (w == h) { //adjust width if needed to make room for tapping
w = h / ASPECT_RATIO;
}
float edgeOffset = w / 2f;
card.setTargetingOriginVector(tapped? this.screenPos.x + yoffset : this.screenPos.x + edgeOffset, tapped ? this.screenPos.y + h - yoffset/1.5f : this.screenPos.y + h - xoffset);
if (!ZoneType.Battlefield.equals(card.getZone())) {
rotateTransform(g, x, y, w, h, edgeOffset, false);
return;