Can now line up a card to play before your turn
Change-Id: I8b63183c39ae669a29b874245d53ddf975b4dad2
diff --git a/go/src/hearts/assets/UnplayedBorder1.png b/go/src/hearts/assets/UnplayedBorder1.png
new file mode 100644
index 0000000..0068dd5
--- /dev/null
+++ b/go/src/hearts/assets/UnplayedBorder1.png
Binary files differ
diff --git a/go/src/hearts/assets/UnplayedBorder2.png b/go/src/hearts/assets/UnplayedBorder2.png
new file mode 100644
index 0000000..48f6832
--- /dev/null
+++ b/go/src/hearts/assets/UnplayedBorder2.png
Binary files differ
diff --git a/go/src/hearts/img/reposition/reposition.go b/go/src/hearts/img/reposition/reposition.go
index 6d30a40..78d8fd1 100644
--- a/go/src/hearts/img/reposition/reposition.go
+++ b/go/src/hearts/img/reposition/reposition.go
@@ -7,6 +7,8 @@
package reposition
import (
+ "time"
+
"hearts/img/coords"
"hearts/img/direction"
"hearts/img/staticimg"
@@ -287,7 +289,7 @@
bannerImgs = append(bannerImgs, u.Buttons["takeTrick"])
bannerImgs = append(bannerImgs, u.Buttons["toggleSplit"])
tableImgs = append(tableImgs, u.DropTargets...)
- tableImgs = append(tableImgs, u.BackgroundImgs[:u.NumPlayers]...)
+ tableImgs = append(tableImgs, u.BackgroundImgs[:u.NumPlayers+1]...)
for _, img := range tableImgs {
from := img.GetCurrent()
to := coords.MakeVec(from.X, from.Y+topOfBanner)
@@ -326,7 +328,7 @@
bannerImgs = append(bannerImgs, u.Buttons["takeTrick"])
bannerImgs = append(bannerImgs, u.Buttons["toggleSplit"])
tableImgs = append(tableImgs, u.DropTargets...)
- tableImgs = append(tableImgs, u.BackgroundImgs[:u.NumPlayers]...)
+ tableImgs = append(tableImgs, u.BackgroundImgs[:u.NumPlayers+1]...)
for _, img := range tableImgs {
from := img.GetCurrent()
to := coords.MakeVec(from.X, from.Y-topOfBanner)
@@ -400,7 +402,7 @@
}
for i, c := range cards {
destination := c.GetDimensions().Times(-1)
- if i < len(cards) - 1 {
+ if i < len(cards)-1 {
animateCardNoChannel(c, destination, c.GetDimensions(), u)
} else {
animateCardMovement(ch, c, destination, c.GetDimensions(), u)
@@ -568,6 +570,19 @@
c.Move(pos, u.CardDim, u.Eng)
}
+func AlternateImgs(s *staticimg.StaticImg, u *uistate.UIState) {
+ <-time.After(100 * time.Millisecond)
+ node := s.GetNode()
+ node.Arranger = arrangerFunc(func(eng sprite.Engine, node *sprite.Node, t clock.Time) {
+ t0 := uint32(t) % 10
+ if t0 < 5 {
+ u.Eng.SetSubTex(s.GetNode(), s.GetImage())
+ } else {
+ u.Eng.SetSubTex(s.GetNode(), s.GetAlt())
+ }
+ })
+}
+
func RemoveAnimChan(ch chan bool, u *uistate.UIState) {
for i, c := range u.AnimChans {
if ch == c {
diff --git a/go/src/hearts/img/texture/texture.go b/go/src/hearts/img/texture/texture.go
index f59d539..9e3fe92 100644
--- a/go/src/hearts/img/texture/texture.go
+++ b/go/src/hearts/img/texture/texture.go
@@ -278,6 +278,7 @@
"PassPressed.png", "PassUnpressed.png", "RightArrowBlue.png", "LeftArrowBlue.png", "AcrossArrowBlue.png", "RightArrowGray.png",
"LeftArrowGray.png", "AcrossArrowGray.png", "TakeTrickTableUnpressed.png", "TakeTrickTablePressed.png", "TakeTrickHandPressed.png",
"TakeTrickHandUnpressed.png", "android.png", "cat.png", "man.png", "woman.png", "TakeUnpressed.png", "TakePressed.png",
+ "UnplayedBorder1.png", "UnplayedBorder2.png",
}
for _, f := range boundedImgs {
a, err := asset.Open(f)
diff --git a/go/src/hearts/img/uistate/uistate.go b/go/src/hearts/img/uistate/uistate.go
index 4effbe3..74ccb18 100644
--- a/go/src/hearts/img/uistate/uistate.go
+++ b/go/src/hearts/img/uistate/uistate.go
@@ -68,6 +68,9 @@
Buttons map[string]*staticimg.StaticImg
Other []*staticimg.StaticImg
ModText []*staticimg.StaticImg
+ RoundScores []int // the scores of the most recently finished round
+ Winners []int // the list of players, if any, who have won
+ CardToPlay *card.Card // the card, if any, curPlayer has decided to play before their turn
CurCard *card.Card // the card that is currently clicked on
CurImg *staticimg.StaticImg // the image that is currently clicked on
// lastMouseXY is in Px: divide by pixelsPerPt to get Pt
@@ -121,6 +124,7 @@
Buttons: make(map[string]*staticimg.StaticImg),
Other: make([]*staticimg.StaticImg, 0),
ModText: make([]*staticimg.StaticImg, 0),
+ RoundScores: make([]int, numPlayers),
LastMouseXY: coords.MakeVec(-1, -1),
NumPlayers: numPlayers,
NumSuits: numSuits,
diff --git a/go/src/hearts/img/view/view.go b/go/src/hearts/img/view/view.go
index d88f3da..9169a6b 100644
--- a/go/src/hearts/img/view/view.go
+++ b/go/src/hearts/img/view/view.go
@@ -38,7 +38,7 @@
case uistate.Take:
LoadTakeView(u)
case uistate.Play:
- LoadPlayView(u)
+ LoadPlayView(true, u)
case uistate.Split:
LoadSplitView(true, u)
}
@@ -377,8 +377,14 @@
// Decides which view of the player's hand to load based on what steps of the round they have completed
func LoadPassOrTakeOrPlay(u *uistate.UIState) {
p := u.CurTable.GetPlayers()[u.CurPlayerIndex]
- if p.GetDoneTaking() || u.CurTable.GetDir() == direction.None {
- LoadPlayView(u)
+ if u.CurTable.RoundOver() {
+ LoadScoreView(u)
+ } else if p.GetDoneTaking() || u.CurTable.GetDir() == direction.None {
+ if u.CurView == uistate.Play {
+ LoadPlayView(true, u)
+ } else {
+ LoadPlayView(false, u)
+ }
} else if p.GetDonePassing() {
LoadTakeView(u)
} else {
@@ -387,7 +393,7 @@
}
// Score View: Shows current player standings at the end of every round, including the end of the game
-func LoadScoreView(roundScores, winners []int, u *uistate.UIState) {
+func LoadScoreView(u *uistate.UIState) {
u.M.Lock()
defer u.M.Unlock()
reposition.ResetAnims(u)
@@ -396,8 +402,8 @@
u.CurView = uistate.Score
addHeader(u)
addScoreViewHeaderText(u)
- addPlayerScores(roundScores, u)
- addScoreButton(len(winners) > 0, u)
+ addPlayerScores(u.RoundScores, u)
+ addScoreButton(len(u.Winners) > 0, u)
}
// Pass View: Shows player's hand and allows them to pass cards
@@ -438,14 +444,15 @@
}
// Play View: Shows player's hand and allows them to play cards
-func LoadPlayView(u *uistate.UIState) {
+func LoadPlayView(reloading bool, u *uistate.UIState) {
u.M.Lock()
defer u.M.Unlock()
reposition.ResetAnims(u)
resetImgs(u)
resetScene(u)
u.CurView = uistate.Play
- addPlaySlot(u)
+ display := u.CurTable.GetTrick()[u.CurPlayerIndex] == nil && !u.CurTable.TrickNew() && reloading
+ addPlaySlot(display, u)
addHand(u)
addPlayHeader(getTurnText(u), false, u)
SetNumTricksHand(u)
@@ -453,15 +460,7 @@
addDebugBar(u)
}
// animate in play slot if relevant
- if u.CurTable.WhoseTurn() == u.CurPlayerIndex {
- if u.SequentialPhases {
- if u.CurTable.AllDoneTaking() {
- reposition.AnimateInPlay(u)
- }
- } else if u.CurTable.AllDonePassing() {
- reposition.AnimateInPlay(u)
- }
- } else if u.CurTable.GetTrickRecipient() == u.CurPlayerIndex {
+ if u.CurTable.TrickNew() || u.CurTable.GetTrickRecipient() == u.CurPlayerIndex || (!reloading && u.CurTable.GetTrick()[u.CurPlayerIndex] == nil) {
reposition.AnimateInPlay(u)
}
}
@@ -488,9 +487,18 @@
u.SwitchingViews = true
reposition.AnimateInSplit(ch, u)
go func() {
- onDone := func() { u.SwitchingViews = false }
+ onDone := func() {
+ u.SwitchingViews = false
+ if u.CardToPlay != nil {
+ reposition.AlternateImgs(u.BackgroundImgs[0], u)
+ }
+ }
reposition.SwitchOnChan(ch, quit, onDone, u)
}()
+ } else {
+ if u.CardToPlay != nil {
+ reposition.AlternateImgs(u.BackgroundImgs[0], u)
+ }
}
}
@@ -569,6 +577,17 @@
dropTargetPos := coords.MakeVec(dropTargetX, dropTargetY)
d := texture.MakeImgWithAlt(dropTargetImage, dropTargetAlt, dropTargetPos, dropTargetDimensions, true, u)
u.DropTargets = append(u.DropTargets, d)
+ // 'unplayed' border
+ borderImage := u.Texs["UnplayedBorder1.png"]
+ borderAlt := u.Texs["UnplayedBorder2.png"]
+ borderDim := dropTargetDimensions.Plus(2)
+ borderPos := dropTargetPos.Minus(1)
+ b := texture.MakeImgWithAlt(borderImage, borderAlt, borderPos, borderDim, true, u)
+ u.BackgroundImgs = append(u.BackgroundImgs, b)
+ if u.CardToPlay == nil {
+ var emptyTex sprite.SubTex
+ u.Eng.SetSubTex(b.GetNode(), emptyTex)
+ }
// first player icon
playerIconImage := uistate.GetAvatar(u.CurPlayerIndex, u)
u.BackgroundImgs = append(u.BackgroundImgs,
@@ -728,12 +747,15 @@
}
}
-func addPlaySlot(u *uistate.UIState) {
+func addPlaySlot(display bool, u *uistate.UIState) {
topOfHand := u.WindowSize.Y - 5*(u.CardDim.Y+u.Padding) - (2 * u.Padding / 5) - u.BottomPadding
// adding blue rectangle
blueRectImg := u.Texs["RoundedRectangle-LBlue.png"]
blueRectDim := coords.MakeVec(u.WindowSize.X-4*u.BottomPadding, topOfHand+u.CardDim.Y)
blueRectPos := coords.MakeVec(2*u.BottomPadding, -blueRectDim.Y)
+ if display {
+ blueRectPos = coords.MakeVec(blueRectPos.X, blueRectPos.Y+u.WindowSize.Y/3+u.TopPadding)
+ }
u.BackgroundImgs = append(u.BackgroundImgs,
texture.MakeImgWithoutAlt(blueRectImg, blueRectPos, blueRectDim, u))
// adding drop target
@@ -753,6 +775,9 @@
} else {
dropTargetImg := u.Texs["trickDrop.png"]
dropTargetPos := coords.MakeVec(u.WindowSize.X/2-u.CardDim.X/2, -u.CardDim.Y-3*u.Padding)
+ if display {
+ dropTargetPos = coords.MakeVec(dropTargetPos.X, dropTargetPos.Y+u.WindowSize.Y/3+u.TopPadding)
+ }
u.DropTargets = append(u.DropTargets,
texture.MakeImgWithoutAlt(dropTargetImg, dropTargetPos, u.CardDim, u))
}
@@ -1137,6 +1162,11 @@
texture.PopulateCardImage(u.Cards[i], u)
reposition.SetCardPositionHand(u.Cards[i], numInSuit, suitCounts, u)
}
+ if u.CardToPlay != nil && u.DropTargets[0].GetCardHere() == nil {
+ u.CardToPlay.Move(u.DropTargets[0].GetCurrent(), u.DropTargets[0].GetDimensions(), u.Eng)
+ u.DropTargets[0].SetCardHere(u.CardToPlay)
+ reposition.RealignSuit(u.CardToPlay.GetSuit(), u.CardToPlay.GetInitial().Y, u)
+ }
}
func addScoreViewHeaderText(u *uistate.UIState) {
diff --git a/go/src/hearts/logic/table/table.go b/go/src/hearts/logic/table/table.go
index f20e905..4eece8a 100644
--- a/go/src/hearts/logic/table/table.go
+++ b/go/src/hearts/logic/table/table.go
@@ -37,7 +37,7 @@
heartsBroken: false,
firstTrick: true,
winCondition: 100,
- dir: direction.Right,
+ dir: direction.None,
}
}
@@ -232,6 +232,16 @@
return true
}
+// Returns true if no players have played a card in the current trick
+func (t *Table) TrickNew() bool {
+ for _, c := range t.trick {
+ if c != nil {
+ return false
+ }
+ }
+ return true
+}
+
// Returns true if all players are out of cards, indicating the end of a round
func (t *Table) RoundOver() bool {
for _, p := range t.players {
diff --git a/go/src/hearts/sync/util.go b/go/src/hearts/sync/util.go
index 2f8d8fc..7155506 100644
--- a/go/src/hearts/sync/util.go
+++ b/go/src/hearts/sync/util.go
@@ -8,13 +8,13 @@
const (
// switch back to my mountpoint with the following code:
- //MountPoint = "users/emshack@google.com"
- MountPoint = "/192.168.86.254:8101"
- UserID = 2222
+ MountPoint = "users/emshack@google.com"
+ //MountPoint = "/192.168.86.254:8101"
+ UserID = 111
UserColor = 16777215
- UserAvatar = "man.png"
+ UserAvatar = "woman.png"
UserName = "Bob"
- SBName = "syncbase1"
+ SBName = "syncbase"
AppName = "app"
DbName = "db"
LogName = "games"
diff --git a/go/src/hearts/sync/watch.go b/go/src/hearts/sync/watch.go
index f2f2195..a52b82d 100644
--- a/go/src/hearts/sync/watch.go
+++ b/go/src/hearts/sync/watch.go
@@ -18,10 +18,10 @@
"hearts/img/uistate"
"hearts/img/view"
"hearts/logic/card"
+ "os"
"sort"
"strconv"
"strings"
- "os"
"time"
"v.io/v23/syncbase/nosql"
)
@@ -72,20 +72,7 @@
u.UserData[userID] = valueMap
for _, v := range u.PlayerData {
if v == userID {
- switch u.CurView {
- case uistate.Arrange:
- view.LoadArrangeView(u)
- case uistate.Table:
- view.LoadTableView(u)
- case uistate.Pass:
- view.LoadPassView(u)
- case uistate.Take:
- view.LoadTakeView(u)
- case uistate.Play:
- view.LoadPlayView(u)
- case uistate.Split:
- view.LoadSplitView(true, u)
- }
+ view.ReloadView(u)
}
}
if u.CurView == uistate.Discovery {
@@ -135,7 +122,7 @@
tmp := strings.Split(key, "/")
if len(tmp) == 3 {
keyTime, _ := strconv.ParseInt(strings.Split(tmp[2], "-")[0], 10, 64)
- fmt.Fprintf(file, fmt.Sprintf("diff: %d milliseconds\n\n", curTime - keyTime))
+ fmt.Fprintf(file, fmt.Sprintf("diff: %d milliseconds\n\n", curTime-keyTime))
} else {
fmt.Fprintf(file, "\n")
}
@@ -247,7 +234,7 @@
view.LoadTakeView(u)
}
} else if u.CurView == uistate.Play && u.CurTable.AllDonePassing() {
- view.LoadPlayView(u)
+ view.LoadPlayView(true, u)
}
}
@@ -269,14 +256,14 @@
}
// UI
if u.CurView == uistate.Play {
- view.LoadPlayView(u)
+ view.LoadPlayView(true, u)
}
}
} else if p.HasTwoOfClubs() {
u.CurTable.SetFirstPlayer(p.GetPlayerIndex())
// UI
if u.CurView == uistate.Play && u.CurPlayerIndex != playerInt {
- view.LoadPlayView(u)
+ view.LoadPlayView(true, u)
}
}
// UI
@@ -325,9 +312,42 @@
b := u.Buttons["takeTrick"]
u.Eng.SetSubTex(b.GetNode(), b.GetImage())
}
+ } else if u.CardToPlay != nil && u.CurTable.WhoseTurn() == u.CurPlayerIndex {
+ ch := make(chan bool)
+ if err := PlayCard(ch, u.CurPlayerIndex, u); err != "" {
+ view.ChangePlayMessage(err, u)
+ RemoveCardFromTarget(u.CardToPlay, u)
+ // add card back to hand
+ reposition.ResetCardPosition(u.CardToPlay, u.Eng)
+ }
+ u.CardToPlay = nil
+ u.BackgroundImgs[0].GetNode().Arranger = nil
+ var emptyTex sprite.SubTex
+ u.Eng.SetSubTex(u.BackgroundImgs[0].GetNode(), emptyTex)
}
} else if u.CurView == uistate.Play && u.CurPlayerIndex != playerInt {
- view.LoadPlayView(u)
+ view.LoadPlayView(true, u)
+ if u.CardToPlay != nil && u.CurTable.WhoseTurn() == u.CurPlayerIndex {
+ ch := make(chan bool)
+ if err := PlayCard(ch, u.CurPlayerIndex, u); err != "" {
+ view.ChangePlayMessage(err, u)
+ RemoveCardFromTarget(u.CardToPlay, u)
+ // add card back to hand
+ reposition.ResetCardPosition(u.CardToPlay, u.Eng)
+ reposition.RealignSuit(u.CardToPlay.GetSuit(), u.CardToPlay.GetInitial().Y, u)
+ }
+ u.CardToPlay = nil
+ quit := make(chan bool)
+ u.AnimChans = append(u.AnimChans, quit)
+ go func() {
+ onDone := func() {
+ if u.CurView == uistate.Play {
+ view.LoadPlayView(true, u)
+ }
+ }
+ reposition.SwitchOnChan(ch, quit, onDone, u)
+ }()
+ }
}
}
@@ -335,10 +355,8 @@
trickCards := u.CurTable.GetTrick()
recipient := u.CurTable.GetTrickRecipient()
roundOver := u.CurTable.SendTrick(recipient)
- var roundScores []int
- var winners []int
if roundOver {
- roundScores, winners = u.CurTable.EndRound()
+ u.RoundScores, u.Winners = u.CurTable.EndRound()
}
// UI
if u.CurView == uistate.Table {
@@ -364,7 +382,7 @@
var emptyTex sprite.SubTex
u.Eng.SetSubTex(u.Buttons["takeTrick"].GetNode(), emptyTex)
if roundOver {
- view.LoadScoreView(roundScores, winners, u)
+ view.LoadScoreView(u)
} else {
var trickDir direction.Direction
switch recipient {
@@ -384,13 +402,13 @@
}
} else if u.CurView == uistate.Play {
if roundOver {
- view.LoadScoreView(roundScores, winners, u)
+ view.LoadScoreView(u)
} else {
- view.LoadPlayView(u)
+ view.LoadPlayView(true, u)
}
}
// logic
- if len(winners) > 0 {
+ if len(u.Winners) > 0 {
u.CurTable.NewGame()
}
}
@@ -455,3 +473,46 @@
jKey := us[j].Row
return iKey < jKey
}
+
+func PlayCard(ch chan bool, playerId int, u *uistate.UIState) string {
+ c := u.DropTargets[0].GetCardHere()
+ if c == nil {
+ return "No card has been played"
+ }
+ // checks to make sure that:
+ // -player has not already played a card this round
+ // -all players have passed cards
+ // -the play is in the right order
+ // -the play is valid given game logic
+ if u.CurTable.GetPlayers()[playerId].GetDonePlaying() {
+ return "You have already played a card in this trick"
+ }
+ if !u.CurTable.AllDonePassing() {
+ return "Not all players have passed their cards"
+ }
+ if !u.CurTable.ValidPlayOrder(playerId) {
+ return "It is not your turn"
+ }
+ if err := u.CurTable.ValidPlayLogic(c, playerId); err != "" {
+ return err
+ }
+ success := LogPlay(u, c)
+ for !success {
+ success = LogPlay(u, c)
+ }
+ // no animation when in split view
+ if u.CurView == uistate.Play {
+ reposition.AnimateHandCardPlay(ch, c, u)
+ }
+ return ""
+}
+
+func RemoveCardFromTarget(c *card.Card, u *uistate.UIState) bool {
+ for _, d := range u.DropTargets {
+ if d.GetCardHere() == c {
+ d.SetCardHere(nil)
+ return true
+ }
+ }
+ return false
+}
diff --git a/go/src/hearts/touchhandler/touchhandler.go b/go/src/hearts/touchhandler/touchhandler.go
index bafcec1..32db10b 100644
--- a/go/src/hearts/touchhandler/touchhandler.go
+++ b/go/src/hearts/touchhandler/touchhandler.go
@@ -311,7 +311,7 @@
if u.CurCard != nil {
if !dropCardOnTarget(u.CurCard, t, u) {
// check to see if card was removed from a drop target
- removeCardFromTarget(u.CurCard, u)
+ sync.RemoveCardFromTarget(u.CurCard, u)
// add card back to hand
reposition.ResetCardPosition(u.CurCard, u.Eng)
reposition.RealignSuit(u.CurCard.GetSuit(), u.CurCard.GetInitial().Y, u)
@@ -402,7 +402,7 @@
}
}
for _, c := range cards {
- removeCardFromTarget(c, u)
+ sync.RemoveCardFromTarget(c, u)
// add card back to hand
reposition.ResetCardPosition(c, u.Eng)
reposition.RealignSuit(c.GetSuit(), c.GetInitial().Y, u)
@@ -417,7 +417,7 @@
fmt.Println("Invalid take")
} else {
if u.CurView == uistate.Take {
- view.LoadPlayView(u)
+ view.LoadPlayView(false, u)
}
}
}
@@ -459,28 +459,40 @@
func endClickPlay(t touch.Event, u *uistate.UIState) {
if u.CurCard != nil {
- if dropCardOnTarget(u.CurCard, t, u) {
- ch := make(chan bool)
- if err := playCard(ch, u.CurPlayerIndex, u); err != "" {
- view.ChangePlayMessage(err, u)
- removeCardFromTarget(u.CurCard, u)
+ if u.CurTable.GetTrick()[u.CurPlayerIndex] == nil {
+ if dropCardOnTarget(u.CurCard, t, u) {
+ if u.CurTable.WhoseTurn() == u.CurPlayerIndex {
+ ch := make(chan bool)
+ if err := sync.PlayCard(ch, u.CurPlayerIndex, u); err != "" {
+ view.ChangePlayMessage(err, u)
+ sync.RemoveCardFromTarget(u.CurCard, u)
+ u.CardToPlay = nil
+ // add card back to hand
+ reposition.ResetCardPosition(u.CurCard, u.Eng)
+ reposition.RealignSuit(u.CurCard.GetSuit(), u.CurCard.GetInitial().Y, u)
+ }
+ quit := make(chan bool)
+ u.AnimChans = append(u.AnimChans, quit)
+ go func() {
+ onDone := func() {
+ if u.CurView == uistate.Play {
+ view.LoadPlayView(true, u)
+ }
+ }
+ reposition.SwitchOnChan(ch, quit, onDone, u)
+ }()
+ } else {
+ u.CardToPlay = u.CurCard
+ }
+ } else {
// add card back to hand
+ if sync.RemoveCardFromTarget(u.CurCard, u) {
+ u.CardToPlay = nil
+ }
reposition.ResetCardPosition(u.CurCard, u.Eng)
reposition.RealignSuit(u.CurCard.GetSuit(), u.CurCard.GetInitial().Y, u)
}
- quit := make(chan bool)
- u.AnimChans = append(u.AnimChans, quit)
- go func() {
- onDone := func() {
- if u.CurView == uistate.Play {
- view.LoadPlayView(u)
- }
- }
- reposition.SwitchOnChan(ch, quit, onDone, u)
- }()
} else {
- // check to see if card was removed from a drop target
- removeCardFromTarget(u.CurCard, u)
// add card back to hand
reposition.ResetCardPosition(u.CurCard, u.Eng)
reposition.RealignSuit(u.CurCard.GetSuit(), u.CurCard.GetInitial().Y, u)
@@ -493,7 +505,7 @@
u.Eng.SetSubTex(b.GetNode(), emptyTex)
u.Buttons["takeTrick"] = nil
for _, takenCard := range u.TableCards {
- removeCardFromTarget(takenCard, u)
+ sync.RemoveCardFromTarget(takenCard, u)
reposition.BringNodeToFront(takenCard.GetNode(), u)
}
ch := make(chan bool)
@@ -527,7 +539,7 @@
onDone := func() {
u.SwitchingViews = false
if u.CurView == uistate.Split {
- view.LoadPlayView(u)
+ view.LoadPlayView(false, u)
}
}
reposition.SwitchOnChan(ch, quit, onDone, u)
@@ -555,17 +567,40 @@
func endClickSplit(t touch.Event, u *uistate.UIState) {
if u.CurCard != nil {
- if dropCardHere(u.CurCard, u.DropTargets[0], t, u) {
- ch := make(chan bool)
- if err := playCard(ch, u.CurPlayerIndex, u); err != "" {
- view.ChangePlayMessage(err, u)
- removeCardFromTarget(u.CurCard, u)
+ if u.CurTable.GetTrick()[u.CurPlayerIndex] == nil {
+ if dropCardHere(u.CurCard, u.DropTargets[0], t, u) {
+ if u.CurTable.WhoseTurn() == u.CurPlayerIndex {
+ ch := make(chan bool)
+ if err := sync.PlayCard(ch, u.CurPlayerIndex, u); err != "" {
+ view.ChangePlayMessage(err, u)
+ if sync.RemoveCardFromTarget(u.CurCard, u) {
+ u.CardToPlay = nil
+ u.BackgroundImgs[0].GetNode().Arranger = nil
+ var emptyTex sprite.SubTex
+ u.Eng.SetSubTex(u.BackgroundImgs[0].GetNode(), emptyTex)
+ }
+ // add card back to hand
+ reposition.ResetCardPosition(u.CurCard, u.Eng)
+ }
+ } else {
+ u.CardToPlay = u.CurCard
+ reposition.AlternateImgs(u.BackgroundImgs[0], u)
+ }
+ } else {
// add card back to hand
+ if sync.RemoveCardFromTarget(u.CurCard, u) {
+ u.CardToPlay = nil
+ u.BackgroundImgs[0].GetNode().Arranger = nil
+ var emptyTex sprite.SubTex
+ u.Eng.SetSubTex(u.BackgroundImgs[0].GetNode(), emptyTex)
+ }
reposition.ResetCardPosition(u.CurCard, u.Eng)
+ reposition.RealignSuit(u.CurCard.GetSuit(), u.CurCard.GetInitial().Y, u)
}
} else {
// add card back to hand
reposition.ResetCardPosition(u.CurCard, u.Eng)
+ reposition.RealignSuit(u.CurCard.GetSuit(), u.CurCard.GetInitial().Y, u)
}
}
pressed := unpressButtons(u)
@@ -677,39 +712,6 @@
return true
}
-func playCard(ch chan bool, playerId int, u *uistate.UIState) string {
- c := u.DropTargets[0].GetCardHere()
- if c == nil {
- return "No card has been played"
- }
- // checks to make sure that:
- // -player has not already played a card this round
- // -all players have passed cards
- // -the play is in the right order
- // -the play is valid given game logic
- if u.CurTable.GetPlayers()[playerId].GetDonePlaying() {
- return "You have already played a card in this trick"
- }
- if !u.CurTable.AllDonePassing() {
- return "Not all players have passed their cards"
- }
- if !u.CurTable.ValidPlayOrder(playerId) {
- return "It is not your turn"
- }
- if err := u.CurTable.ValidPlayLogic(c, playerId); err != "" {
- return err
- }
- success := sync.LogPlay(u, c)
- for !success {
- success = sync.LogPlay(u, c)
- }
- // no animation when in split view
- if u.CurView == uistate.Play {
- reposition.AnimateHandCardPlay(ch, c, u)
- }
- return ""
-}
-
func pressButton(b *staticimg.StaticImg, u *uistate.UIState) {
u.Eng.SetSubTex(b.GetNode(), b.GetAlt())
b.SetDisplayingImage(false)
@@ -780,16 +782,6 @@
return true
}
-func removeCardFromTarget(c *card.Card, u *uistate.UIState) bool {
- for _, d := range u.DropTargets {
- if d.GetCardHere() == c {
- d.SetCardHere(nil)
- return true
- }
- }
- return false
-}
-
func touchingCard(t touch.Event, c *card.Card, u *uistate.UIState) bool {
withinXBounds := t.X/u.PixelsPerPt >= c.GetCurrent().X && t.X/u.PixelsPerPt <= c.GetDimensions().X+c.GetCurrent().X
withinYBounds := t.Y/u.PixelsPerPt >= c.GetCurrent().Y && t.Y/u.PixelsPerPt <= c.GetDimensions().Y+c.GetCurrent().Y