restyled doudizhu
|
@ -10,13 +10,6 @@
|
||||||
/* card itself
|
/* card itself
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
|
|
||||||
.playingCards.unselectable {
|
|
||||||
pointer-events: none;
|
|
||||||
-webkit-user-select: none;
|
|
||||||
-ms-user-select: none;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.playingCards {
|
.playingCards {
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
transform: translateY(0) scale(1);
|
transform: translateY(0) scale(1);
|
||||||
|
@ -184,7 +177,7 @@
|
||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
.playingCards .card.joker .rank:before {
|
.playingCards .card.joker .rank:before {
|
||||||
content: "\2605";
|
content: "";
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
}
|
}
|
||||||
|
@ -193,9 +186,19 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
/* inner multiple suits */
|
/* inner multiple suits */
|
||||||
.playingCards .card .suit:after {
|
.playingCards .card:not(full-content) .suit:after {
|
||||||
display: block;
|
display: block;
|
||||||
margin-top: -.8em;
|
margin-top: -.2em;
|
||||||
|
text-align: center;
|
||||||
|
white-space: pre;
|
||||||
|
line-height: .9;
|
||||||
|
font-size: 2.5em;
|
||||||
|
word-spacing: -.05em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playingCards .card.full-content .suit:after {
|
||||||
|
display: block;
|
||||||
|
margin-top: -.9em;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
white-space: pre;
|
white-space: pre;
|
||||||
line-height: .9;
|
line-height: .9;
|
||||||
|
@ -204,158 +207,170 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
/* make the hearts and clubs symbols fit, because they are a bit bigger than the others */
|
/* make the hearts and clubs symbols fit, because they are a bit bigger than the others */
|
||||||
.playingCards .card.hearts .suit:after {
|
.playingCards .card.full-content.hearts .suit:after {
|
||||||
word-spacing: -.15em;
|
word-spacing: -.15em;
|
||||||
}
|
}
|
||||||
.playingCards .card.hearts.rank-10 .suit:after {
|
.playingCards .card.full-content.hearts.rank-10 .suit:after {
|
||||||
word-spacing: -.05em;
|
word-spacing: -.05em;
|
||||||
letter-spacing: -.1em;
|
letter-spacing: -.1em;
|
||||||
}
|
}
|
||||||
.playingCards .card.clubs.rank-10 .suit:after {
|
.playingCards .card.full-content.clubs.rank-10 .suit:after {
|
||||||
word-spacing: -.15em;
|
word-spacing: -.15em;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 8, 9, 10 are the most crowded */
|
/* 8, 9, 10 are the most crowded */
|
||||||
.playingCards .card.rank-8 .suit:after,
|
.playingCards .card.full-content.rank-8 .suit:after,
|
||||||
.playingCards .card.rank-9 .suit:after {
|
.playingCards .card.full-content.rank-9 .suit:after {
|
||||||
letter-spacing: -.075em;
|
letter-spacing: -.075em;
|
||||||
}
|
}
|
||||||
.playingCards .card.rank-10 .suit:after {
|
.playingCards .card.full-content.rank-10 .suit:after {
|
||||||
letter-spacing: -.1em;
|
letter-spacing: -.1em;
|
||||||
}
|
}
|
||||||
.playingCards .card.clubs .suit:after {
|
.playingCards .card.full-content.clubs .suit:after {
|
||||||
letter-spacing: -.125em;
|
letter-spacing: -.125em;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*____________ symbols in the middle (suits, full) ____________*/
|
/*____________ symbols in the middle (suits, full) ____________*/
|
||||||
|
|
||||||
/* diamonds */
|
/* diamonds */
|
||||||
.playingCards .card.rank-2.diams .suit:after {
|
.playingCards .card.diams:not(full-content) .suit:after {
|
||||||
|
content: "\2666";
|
||||||
|
}
|
||||||
|
.playingCards .card.rank-2.diams.full-content .suit:after {
|
||||||
content: "\2666 \A\A\2666";
|
content: "\2666 \A\A\2666";
|
||||||
}
|
}
|
||||||
.playingCards .card.rank-3.diams .suit:after {
|
.playingCards .card.rank-3.diams.full-content .suit:after {
|
||||||
content: "\2666 \A\2666 \A\2666";
|
content: "\2666 \A\2666 \A\2666";
|
||||||
}
|
}
|
||||||
.playingCards .card.rank-4.diams .suit:after {
|
.playingCards .card.rank-4.diams.full-content .suit:after {
|
||||||
content: "\2666\00A0\00A0\00A0\2666 \A\A\2666\00A0\00A0\00A0\2666";
|
content: "\2666\00A0\00A0\00A0\2666 \A\A\2666\00A0\00A0\00A0\2666";
|
||||||
}
|
}
|
||||||
.playingCards .card.rank-5.diams .suit:after {
|
.playingCards .card.rank-5.diams.full-content .suit:after {
|
||||||
content: "\2666\00A0\00A0\00A0\2666 \A\2666 \A\2666\00A0\00A0\00A0\2666";
|
content: "\2666\00A0\00A0\00A0\2666 \A\2666 \A\2666\00A0\00A0\00A0\2666";
|
||||||
}
|
}
|
||||||
.playingCards .card.rank-6.diams .suit:after {
|
.playingCards .card.rank-6.diams.full-content .suit:after {
|
||||||
content: "\2666\00A0\00A0\00A0\2666 \A\2666\00A0\00A0\00A0\2666 \A\2666\00A0\00A0\00A0\2666";
|
content: "\2666\00A0\00A0\00A0\2666 \A\2666\00A0\00A0\00A0\2666 \A\2666\00A0\00A0\00A0\2666";
|
||||||
}
|
}
|
||||||
.playingCards .card.rank-7.diams .suit:after {
|
.playingCards .card.rank-7.diams.full-content .suit:after {
|
||||||
content: "\2666\00A0\00A0\2666 \A\2666\00A0\2666\00A0\2666 \A\2666\00A0\00A0\2666";
|
content: "\2666\00A0\00A0\2666 \A\2666\00A0\2666\00A0\2666 \A\2666\00A0\00A0\2666";
|
||||||
}
|
}
|
||||||
.playingCards .card.rank-8.diams .suit:after {
|
.playingCards .card.rank-8.diams.full-content .suit:after {
|
||||||
content: "\2666\00A0\2666\00A0\2666 \A\2666\00A0\00A0\2666 \A\2666\00A0\2666\00A0\2666";
|
content: "\2666\00A0\2666\00A0\2666 \A\2666\00A0\00A0\2666 \A\2666\00A0\2666\00A0\2666";
|
||||||
}
|
}
|
||||||
.playingCards .card.rank-9.diams .suit:after {
|
.playingCards .card.rank-9.diams.full-content .suit:after {
|
||||||
content: "\2666\00A0\2666\00A0\2666 \A\2666\00A0\2666\00A0\2666 \A\2666\00A0\2666\00A0\2666";
|
content: "\2666\00A0\2666\00A0\2666 \A\2666\00A0\2666\00A0\2666 \A\2666\00A0\2666\00A0\2666";
|
||||||
}
|
}
|
||||||
.playingCards .card.rank-10.diams .suit:after {
|
.playingCards .card.rank-10.diams.full-content .suit:after {
|
||||||
content: "\2666\00A0\2666\00A0\2666 \A\2666\00A0\2666\00A0\2666\00A0\2666 \A\2666\00A0\2666\00A0\2666";
|
content: "\2666\00A0\2666\00A0\2666 \A\2666\00A0\2666\00A0\2666\00A0\2666 \A\2666\00A0\2666\00A0\2666";
|
||||||
}
|
}
|
||||||
|
|
||||||
/* hearts */
|
/* hearts */
|
||||||
.playingCards .card.rank-2.hearts .suit:after {
|
.playingCards .card.hearts:not(full-content) .suit:after {
|
||||||
|
content: "\2665";
|
||||||
|
}
|
||||||
|
.playingCards .card.rank-2.hearts.full-content .suit:after {
|
||||||
content: "\2665 \A\A\2665";
|
content: "\2665 \A\A\2665";
|
||||||
}
|
}
|
||||||
.playingCards .card.rank-3.hearts .suit:after {
|
.playingCards .card.rank-3.hearts.full-content .suit:after {
|
||||||
content: "\2665 \A\2665 \A\2665";
|
content: "\2665 \A\2665 \A\2665";
|
||||||
}
|
}
|
||||||
.playingCards .card.rank-4.hearts .suit:after {
|
.playingCards .card.rank-4.hearts.full-content .suit:after {
|
||||||
content: "\2665\00A0\00A0\00A0\2665 \A\A\2665\00A0\00A0\00A0\2665";
|
content: "\2665\00A0\00A0\00A0\2665 \A\A\2665\00A0\00A0\00A0\2665";
|
||||||
}
|
}
|
||||||
.playingCards .card.rank-5.hearts .suit:after {
|
.playingCards .card.rank-5.hearts.full-content .suit:after {
|
||||||
content: "\2665\00A0\00A0\00A0\2665 \A\2665 \A\2665\00A0\00A0\00A0\2665";
|
content: "\2665\00A0\00A0\00A0\2665 \A\2665 \A\2665\00A0\00A0\00A0\2665";
|
||||||
}
|
}
|
||||||
.playingCards .card.rank-6.hearts .suit:after {
|
.playingCards .card.rank-6.hearts.full-content .suit:after {
|
||||||
content: "\2665\00A0\00A0\00A0\2665 \A\2665\00A0\00A0\00A0\2665 \A\2665\00A0\00A0\00A0\2665";
|
content: "\2665\00A0\00A0\00A0\2665 \A\2665\00A0\00A0\00A0\2665 \A\2665\00A0\00A0\00A0\2665";
|
||||||
}
|
}
|
||||||
.playingCards .card.rank-7.hearts .suit:after {
|
.playingCards .card.rank-7.hearts.full-content .suit:after {
|
||||||
content: "\2665\00A0\00A0\2665 \A\2665\00A0\2665\00A0\2665 \A\2665\00A0\00A0\2665";
|
content: "\2665\00A0\00A0\2665 \A\2665\00A0\2665\00A0\2665 \A\2665\00A0\00A0\2665";
|
||||||
}
|
}
|
||||||
.playingCards .card.rank-8.hearts .suit:after {
|
.playingCards .card.rank-8.hearts.full-content .suit:after {
|
||||||
content: "\2665\00A0\2665\00A0\2665 \A\2665\00A0\00A0\2665 \A\2665\00A0\2665\00A0\2665";
|
content: "\2665\00A0\2665\00A0\2665 \A\2665\00A0\00A0\2665 \A\2665\00A0\2665\00A0\2665";
|
||||||
}
|
}
|
||||||
.playingCards .card.rank-9.hearts .suit:after {
|
.playingCards .card.rank-9.hearts.full-content .suit:after {
|
||||||
content: "\2665\00A0\2665\00A0\2665 \A\2665\00A0\2665\00A0\2665 \A\2665\00A0\2665\00A0\2665";
|
content: "\2665\00A0\2665\00A0\2665 \A\2665\00A0\2665\00A0\2665 \A\2665\00A0\2665\00A0\2665";
|
||||||
}
|
}
|
||||||
.playingCards .card.rank-10.hearts .suit:after {
|
.playingCards .card.rank-10.hearts.full-content .suit:after {
|
||||||
content: "\2665\00A0\2665\00A0\2665 \A\2665\00A0\2665\00A0\2665\00A0\2665 \A\2665\00A0\2665\00A0\2665";
|
content: "\2665\00A0\2665\00A0\2665 \A\2665\00A0\2665\00A0\2665\00A0\2665 \A\2665\00A0\2665\00A0\2665";
|
||||||
}
|
}
|
||||||
|
|
||||||
/* spades */
|
/* spades */
|
||||||
.playingCards .card.rank-2.spades .suit:after {
|
.playingCards .card.spades:not(full-content) .suit:after {
|
||||||
|
content: "\2660";
|
||||||
|
}
|
||||||
|
.playingCards .card.rank-2.spades.full-content .suit:after {
|
||||||
content: "\2660 \A\A\2660";
|
content: "\2660 \A\A\2660";
|
||||||
}
|
}
|
||||||
.playingCards .card.rank-3.spades .suit:after {
|
.playingCards .card.rank-3.spades.full-content .suit:after {
|
||||||
content: "\2660 \A\2660 \A\2660";
|
content: "\2660 \A\2660 \A\2660";
|
||||||
}
|
}
|
||||||
.playingCards .card.rank-4.spades .suit:after {
|
.playingCards .card.rank-4.spades.full-content .suit:after {
|
||||||
content: "\2660\00A0\00A0\00A0\2660 \A\A\2660\00A0\00A0\00A0\2660";
|
content: "\2660\00A0\00A0\00A0\2660 \A\A\2660\00A0\00A0\00A0\2660";
|
||||||
}
|
}
|
||||||
.playingCards .card.rank-5.spades .suit:after {
|
.playingCards .card.rank-5.spades.full-content .suit:after {
|
||||||
content: "\2660\00A0\00A0\00A0\2660 \A\2660 \A\2660\00A0\00A0\00A0\2660";
|
content: "\2660\00A0\00A0\00A0\2660 \A\2660 \A\2660\00A0\00A0\00A0\2660";
|
||||||
}
|
}
|
||||||
.playingCards .card.rank-6.spades .suit:after {
|
.playingCards .card.rank-6.spades.full-content .suit:after {
|
||||||
content: "\2660\00A0\00A0\00A0\2660 \A\2660\00A0\00A0\00A0\2660 \A\2660\00A0\00A0\00A0\2660";
|
content: "\2660\00A0\00A0\00A0\2660 \A\2660\00A0\00A0\00A0\2660 \A\2660\00A0\00A0\00A0\2660";
|
||||||
}
|
}
|
||||||
.playingCards .card.rank-7.spades .suit:after {
|
.playingCards .card.rank-7.spades.full-content .suit:after {
|
||||||
content: "\2660\00A0\00A0\2660 \A\2660\00A0\2660\00A0\2660 \A\2660\00A0\00A0\2660";
|
content: "\2660\00A0\00A0\2660 \A\2660\00A0\2660\00A0\2660 \A\2660\00A0\00A0\2660";
|
||||||
}
|
}
|
||||||
.playingCards .card.rank-8.spades .suit:after {
|
.playingCards .card.rank-8.spades.full-content .suit:after {
|
||||||
content: "\2660\00A0\2660\00A0\2660 \A\2660\00A0\00A0\2660 \A\2660\00A0\2660\00A0\2660";
|
content: "\2660\00A0\2660\00A0\2660 \A\2660\00A0\00A0\2660 \A\2660\00A0\2660\00A0\2660";
|
||||||
}
|
}
|
||||||
.playingCards .card.rank-9.spades .suit:after {
|
.playingCards .card.rank-9.spades.full-content .suit:after {
|
||||||
content: "\2660\00A0\2660\00A0\2660 \A\2660\00A0\2660\00A0\2660 \A\2660\00A0\2660\00A0\2660";
|
content: "\2660\00A0\2660\00A0\2660 \A\2660\00A0\2660\00A0\2660 \A\2660\00A0\2660\00A0\2660";
|
||||||
}
|
}
|
||||||
.playingCards .card.rank-10.spades .suit:after {
|
.playingCards .card.rank-10.spades.full-content .suit:after {
|
||||||
content: "\2660\00A0\2660\00A0\2660 \A\2660\00A0\2660\00A0\2660\00A0\2660 \A\2660\00A0\2660\00A0\2660";
|
content: "\2660\00A0\2660\00A0\2660 \A\2660\00A0\2660\00A0\2660\00A0\2660 \A\2660\00A0\2660\00A0\2660";
|
||||||
}
|
}
|
||||||
|
|
||||||
/* clubs */
|
/* clubs */
|
||||||
.playingCards .card.rank-2.clubs .suit:after {
|
.playingCards .card.clubs:not(full-content) .suit:after {
|
||||||
|
content: "\2663";
|
||||||
|
}
|
||||||
|
.playingCards .card.rank-2.clubs.full-content .suit:after {
|
||||||
content: "\2663 \A\A\2663";
|
content: "\2663 \A\A\2663";
|
||||||
}
|
}
|
||||||
.playingCards .card.rank-3.clubs .suit:after {
|
.playingCards .card.rank-3.clubs.full-content .suit:after {
|
||||||
content: "\2663 \A\2663 \A\2663";
|
content: "\2663 \A\2663 \A\2663";
|
||||||
}
|
}
|
||||||
.playingCards .card.rank-4.clubs .suit:after {
|
.playingCards .card.rank-4.clubs.full-content .suit:after {
|
||||||
content: "\2663\00A0\00A0\00A0\2663 \A\A\2663\00A0\00A0\00A0\2663";
|
content: "\2663\00A0\00A0\00A0\2663 \A\A\2663\00A0\00A0\00A0\2663";
|
||||||
}
|
}
|
||||||
.playingCards .card.rank-5.clubs .suit:after {
|
.playingCards .card.rank-5.clubs.full-content .suit:after {
|
||||||
content: "\2663\00A0\00A0\00A0\2663 \A\2663 \A\2663\00A0\00A0\00A0\2663";
|
content: "\2663\00A0\00A0\00A0\2663 \A\2663 \A\2663\00A0\00A0\00A0\2663";
|
||||||
}
|
}
|
||||||
.playingCards .card.rank-6.clubs .suit:after {
|
.playingCards .card.rank-6.clubs.full-content .suit:after {
|
||||||
content: "\2663\00A0\00A0\00A0\2663 \A\2663\00A0\00A0\00A0\2663 \A\2663\00A0\00A0\00A0\2663";
|
content: "\2663\00A0\00A0\00A0\2663 \A\2663\00A0\00A0\00A0\2663 \A\2663\00A0\00A0\00A0\2663";
|
||||||
}
|
}
|
||||||
.playingCards .card.rank-7.clubs .suit:after {
|
.playingCards .card.rank-7.clubs.full-content .suit:after {
|
||||||
content: "\2663\00A0\00A0\2663 \A\2663\00A0\2663\00A0\2663 \A\2663\00A0\00A0\2663";
|
content: "\2663\00A0\00A0\2663 \A\2663\00A0\2663\00A0\2663 \A\2663\00A0\00A0\2663";
|
||||||
}
|
}
|
||||||
.playingCards .card.rank-8.clubs .suit:after {
|
.playingCards .card.rank-8.clubs.full-content .suit:after {
|
||||||
content: "\2663\00A0\2663\00A0\2663 \A\2663\00A0\00A0\2663 \A\2663\00A0\2663\00A0\2663";
|
content: "\2663\00A0\2663\00A0\2663 \A\2663\00A0\00A0\2663 \A\2663\00A0\2663\00A0\2663";
|
||||||
}
|
}
|
||||||
.playingCards .card.rank-9.clubs .suit:after {
|
.playingCards .card.rank-9.clubs.full-content .suit:after {
|
||||||
content: "\2663\00A0\2663\00A0\2663 \A\2663\00A0\2663\00A0\2663 \A\2663\00A0\2663\00A0\2663";
|
content: "\2663\00A0\2663\00A0\2663 \A\2663\00A0\2663\00A0\2663 \A\2663\00A0\2663\00A0\2663";
|
||||||
}
|
}
|
||||||
.playingCards .card.rank-10.clubs .suit:after {
|
.playingCards .card.rank-10.clubs.full-content .suit:after {
|
||||||
content: "\2663\00A0\2663\00A0\2663 \A\2663\00A0\2663\00A0\2663\00A0\2663 \A\2663\00A0\2663\00A0\2663";
|
content: "\2663\00A0\2663\00A0\2663 \A\2663\00A0\2663\00A0\2663\00A0\2663 \A\2663\00A0\2663\00A0\2663";
|
||||||
}
|
}
|
||||||
|
|
||||||
/*____________ symbols in the middle (faces as images) ____________*/
|
/*____________ symbols in the middle (faces as images) ____________*/
|
||||||
|
|
||||||
.playingCards.faceImages .card.rank-j .suit:after,
|
.playingCards.faceImages .card.rank-j.full-content .suit:after,
|
||||||
.playingCards.faceImages .card.rank-q .suit:after,
|
.playingCards.faceImages .card.rank-q.full-content .suit:after,
|
||||||
.playingCards.faceImages .card.rank-k .suit:after {
|
.playingCards.faceImages .card.rank-k.full-content .suit:after {
|
||||||
content: '';
|
content: '';
|
||||||
}
|
}
|
||||||
.playingCards.faceImages .card.rank-j,
|
.playingCards.faceImages .card.rank-j.full-content,
|
||||||
.playingCards.faceImages .card.rank-q,
|
.playingCards.faceImages .card.rank-q.full-content,
|
||||||
.playingCards.faceImages .card.rank-k,
|
.playingCards.faceImages .card.rank-k.full-content,
|
||||||
.playingCards.faceImages .card.joker {
|
.playingCards.faceImages .card.joker.full-content {
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: -1em 0;
|
background-position: -1em 0;
|
||||||
/* @change: smaller cards: more negative distance from the left
|
/* @change: smaller cards: more negative distance from the left
|
||||||
|
@ -394,11 +409,11 @@
|
||||||
/*____________ symbols in the middle (faces as dingbat symbols) ____________*/
|
/*____________ symbols in the middle (faces as dingbat symbols) ____________*/
|
||||||
|
|
||||||
.playingCards.simpleCards .card .suit:after,
|
.playingCards.simpleCards .card .suit:after,
|
||||||
.playingCards .card.rank-j .suit:after,
|
.playingCards .card.rank-j.full-content .suit:after,
|
||||||
.playingCards .card.rank-q .suit:after,
|
.playingCards .card.rank-q.full-content .suit:after,
|
||||||
.playingCards .card.rank-k .suit:after,
|
.playingCards .card.rank-k.full-content .suit:after,
|
||||||
.playingCards .card.rank-a .suit:after,
|
.playingCards .card.rank-a.full-content .suit:after,
|
||||||
.playingCards .card.joker .rank:after {
|
.playingCards .card.joker.full-content .rank:after {
|
||||||
font-family: Georgia, serif;
|
font-family: Georgia, serif;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
font-size: 3em;
|
font-size: 3em;
|
||||||
|
@ -424,9 +439,12 @@
|
||||||
}
|
}
|
||||||
.playingCards .card.joker .rank:after {
|
.playingCards .card.joker .rank:after {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
content: "\2766";
|
content: "JOKER";
|
||||||
top: .4em;
|
writing-mode: vertical-lr;
|
||||||
left: .1em;
|
font-weight: bold;
|
||||||
|
font-size: 0.8em;
|
||||||
|
top: 0;
|
||||||
|
left: -0.1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* big suits in middle */
|
/* big suits in middle */
|
||||||
|
@ -519,6 +537,35 @@
|
||||||
.playingCards ul.hand li {
|
.playingCards ul.hand li {
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.playingCards.loose ul.hand li:nth-child(1) { left: 0; }
|
||||||
|
.playingCards.loose ul.hand li:nth-child(2) { left: 1.4em; }
|
||||||
|
.playingCards.loose ul.hand li:nth-child(3) { left: 2.8em; }
|
||||||
|
.playingCards.loose ul.hand li:nth-child(4) { left: 4.2em; }
|
||||||
|
.playingCards.loose ul.hand li:nth-child(5) { left: 5.6em; }
|
||||||
|
.playingCards.loose ul.hand li:nth-child(6) { left: 7.0em; }
|
||||||
|
.playingCards.loose ul.hand li:nth-child(7) { left: 8.4em; }
|
||||||
|
.playingCards.loose ul.hand li:nth-child(8) { left: 9.8em; }
|
||||||
|
.playingCards.loose ul.hand li:nth-child(9) { left: 11.2em; }
|
||||||
|
.playingCards.loose ul.hand li:nth-child(10) { left: 12.6em; }
|
||||||
|
.playingCards.loose ul.hand li:nth-child(11) { left: 14.0em; }
|
||||||
|
.playingCards.loose ul.hand li:nth-child(12) { left: 15.4em; }
|
||||||
|
.playingCards.loose ul.hand li:nth-child(13) { left: 16.8em; }
|
||||||
|
|
||||||
|
.playingCards.loose ul.hand li:nth-child(14) { left: 18.2em; }
|
||||||
|
.playingCards.loose ul.hand li:nth-child(15) { left: 19.6em; }
|
||||||
|
.playingCards.loose ul.hand li:nth-child(16) { left: 21em; }
|
||||||
|
.playingCards.loose ul.hand li:nth-child(17) { left: 22.4em; }
|
||||||
|
.playingCards.loose ul.hand li:nth-child(18) { left: 23.8em; }
|
||||||
|
.playingCards.loose ul.hand li:nth-child(19) { left: 25.2em; }
|
||||||
|
.playingCards.loose ul.hand li:nth-child(20) { left: 26.6em; }
|
||||||
|
.playingCards.loose ul.hand li:nth-child(21) { left: 28em; }
|
||||||
|
.playingCards.loose ul.hand li:nth-child(22) { left: 29.4em; }
|
||||||
|
.playingCards.loose ul.hand li:nth-child(23) { left: 30.8em; }
|
||||||
|
.playingCards.loose ul.hand li:nth-child(24) { left: 32.2em; }
|
||||||
|
.playingCards.loose ul.hand li:nth-child(25) { left: 33.6em; }
|
||||||
|
.playingCards.loose ul.hand li:nth-child(26) { left: 35em; }
|
||||||
|
|
||||||
.playingCards ul.hand li:nth-child(1) { left: 0; }
|
.playingCards ul.hand li:nth-child(1) { left: 0; }
|
||||||
.playingCards ul.hand li:nth-child(2) { left: 1.1em; }
|
.playingCards ul.hand li:nth-child(2) { left: 1.1em; }
|
||||||
.playingCards ul.hand li:nth-child(3) { left: 2.2em; }
|
.playingCards ul.hand li:nth-child(3) { left: 2.2em; }
|
||||||
|
|
|
@ -1,5 +1,14 @@
|
||||||
@import "cards.css";
|
@import "cards.css";
|
||||||
|
|
||||||
.doudizhu-wrapper {
|
.doudizhu-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: #FEF9E7;
|
||||||
|
background-image: url("./images/table.png");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 100% 70%;
|
||||||
|
background-position: bottom;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
.played-card-area {
|
.played-card-area {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
@ -7,6 +16,37 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
||||||
|
.timer.fade-in {
|
||||||
|
visibility: hidden;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timer.fade-out {
|
||||||
|
visibility: hidden;
|
||||||
|
transition: visibility 0.1s, opacity 0.05s;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timer {
|
||||||
|
visibility: visible;
|
||||||
|
transition: visibility 0s, opacity 0.2s, transform 0.3s;
|
||||||
|
opacity: 1;
|
||||||
|
width: 51px;
|
||||||
|
height: 60px;
|
||||||
|
.timer-text {
|
||||||
|
color: #303133;
|
||||||
|
margin-top: 3px;
|
||||||
|
font-size: 23px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-shadow: 0 2px 2px #909399;
|
||||||
|
line-height: 57px;
|
||||||
|
}
|
||||||
|
text-align: center;
|
||||||
|
background-image: url("./images/timer.png");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 100% 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.non-card {
|
.non-card {
|
||||||
display: table;
|
display: table;
|
||||||
width: 280px;
|
width: 280px;
|
||||||
|
@ -16,7 +56,13 @@
|
||||||
display: table-cell;
|
display: table-cell;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 16px;
|
font-size: 23px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-shadow: 0 2px 2px rgba(0, 0, 0, 0.87);
|
||||||
|
//letter-spacing: -4px;
|
||||||
|
color: #F2F6FC;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,14 +82,11 @@
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
width: 130px;
|
width: 130px;
|
||||||
height: 130px;
|
height: 130px;
|
||||||
border-radius: 25px;
|
div {
|
||||||
border: 2px solid #73AD21;
|
text-align: center;
|
||||||
display: table;
|
}
|
||||||
|
|
||||||
span {
|
span {
|
||||||
white-space: pre;
|
white-space: pre;
|
||||||
display: table-cell;
|
|
||||||
vertical-align: middle;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -175,7 +218,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.non-card {
|
.non-card {
|
||||||
height: 138px;
|
height: 70px;
|
||||||
//transform: translateY(-25px);
|
//transform: translateY(-25px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,77 @@
|
||||||
.progress-bar {
|
.progress-bar {
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.header-bar {
|
||||||
|
width: 1000px;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
padding: 5px;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.stretch {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.github-info {
|
||||||
|
flex: 0 100px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: color 0.5s ease;
|
||||||
|
|
||||||
|
&:hover{
|
||||||
|
transition: color 0.5s ease;
|
||||||
|
color: #C0C4CC;
|
||||||
|
}
|
||||||
|
|
||||||
|
.github-icon {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
-ms-transform: translateY(-50%);
|
||||||
|
transform: translateY(-50%);
|
||||||
|
.MuiSvgIcon-root {
|
||||||
|
font-size: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.github-text {
|
||||||
|
left: 45px;
|
||||||
|
line-height: 18px;
|
||||||
|
position: relative;
|
||||||
|
top: 50%;
|
||||||
|
font-size: 18px;
|
||||||
|
-ms-transform: translateY(-50%);
|
||||||
|
transform: translateY(-50%);
|
||||||
|
span {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin-left: 12px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 26px;
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
-ms-transform:scale(1, 1.1) translateY(-1px);
|
||||||
|
-webkit-transform:scale(1, 1.1) translateY(-1px);
|
||||||
|
-moz-transform:scale(1, 1.1) translateY(-1px);
|
||||||
|
-o-transform:scale(1, 1.1) translateY(-1px);
|
||||||
|
|
||||||
|
.subtitle {
|
||||||
|
color: #C0C4CC;
|
||||||
|
margin-left: 11px;
|
||||||
|
font-size: 16px;
|
||||||
|
-ms-transform: translateY(3px);
|
||||||
|
-webkit-transform: translateY(3px);
|
||||||
|
-moz-transform: translateY(3px);
|
||||||
|
-o-transform: translateY(3px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.game-controller {
|
.game-controller {
|
||||||
//width: calc(100% - 20px*2);
|
|
||||||
//padding: 20px;
|
|
||||||
//.el-row {
|
|
||||||
// margin-bottom: 10px;
|
|
||||||
//}
|
|
||||||
.game-controller-paper {
|
.game-controller-paper {
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
padding: 2px 10px;
|
padding: 2px 10px;
|
||||||
|
@ -31,6 +96,7 @@
|
||||||
|
|
||||||
.doudizhu-view-container {
|
.doudizhu-view-container {
|
||||||
width: 1000px;
|
width: 1000px;
|
||||||
|
margin-top: 5px;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
|
|
||||||
|
|
After Width: | Height: | Size: 44 KiB |
After Width: | Height: | Size: 55 KiB |
After Width: | Height: | Size: 51 KiB |
After Width: | Height: | Size: 35 KiB |
After Width: | Height: | Size: 46 KiB |
After Width: | Height: | Size: 47 KiB |
After Width: | Height: | Size: 47 KiB |
After Width: | Height: | Size: 39 KiB |
After Width: | Height: | Size: 7.3 KiB |
After Width: | Height: | Size: 526 KiB |
After Width: | Height: | Size: 13 KiB |
|
@ -11,3 +11,10 @@ code {
|
||||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||||
monospace;
|
monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.unselectable {
|
||||||
|
pointer-events: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
|
@ -2,7 +2,12 @@ import React from 'react';
|
||||||
import { translateCardData, millisecond2Second, computeHandCardsWidth } from '../../utils'
|
import { translateCardData, millisecond2Second, computeHandCardsWidth } from '../../utils'
|
||||||
|
|
||||||
import '../../assets/doudizhu.scss';
|
import '../../assets/doudizhu.scss';
|
||||||
import {fade} from "@material-ui/core";
|
import Landlord_wName from '../../assets/images/Portrait/Landlord_wName.png';
|
||||||
|
import Peasant_wName from '../../assets/images/Portrait/Peasant_wName.png';
|
||||||
|
import PlaceHolderPlayer from '../../assets/images/Portrait/Player.png';
|
||||||
|
|
||||||
|
import Chip from '@material-ui/core/Chip';
|
||||||
|
import Avatar from '@material-ui/core/Avatar';
|
||||||
|
|
||||||
class DoudizhuGameBoard extends React.Component {
|
class DoudizhuGameBoard extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -10,12 +15,48 @@ class DoudizhuGameBoard extends React.Component {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
computePlayerPortrait(playerId, playerIdx){
|
||||||
|
if(this.props.playerInfo.length > 0){
|
||||||
|
return this.props.playerInfo[playerIdx].role === "landlord" ?
|
||||||
|
<div>
|
||||||
|
<img src={Landlord_wName} alt={"Landlord"} height="70%" width="70%" />
|
||||||
|
<Chip
|
||||||
|
avatar={<Avatar>ID</Avatar>}
|
||||||
|
label={playerId}
|
||||||
|
clickable
|
||||||
|
color="primary"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
:
|
||||||
|
<div>
|
||||||
|
<img src={Peasant_wName} alt={"Peasant"} height="70%" width="70%" />
|
||||||
|
<Chip
|
||||||
|
avatar={<Avatar>ID</Avatar>}
|
||||||
|
label={playerId}
|
||||||
|
clickable
|
||||||
|
color="primary"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
}else
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<img src={PlaceHolderPlayer} alt={"Player"} height="70%" width="70%" />
|
||||||
|
<Chip
|
||||||
|
avatar={<Avatar>ID</Avatar>}
|
||||||
|
label={playerId}
|
||||||
|
clickable
|
||||||
|
color="primary"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
computeSingleLineHand(cards, fadeClassName="") {
|
computeSingleLineHand(cards, fadeClassName="") {
|
||||||
if(cards === "P"){
|
if(cards === "P"){
|
||||||
return <div className="non-card"><span>Pass</span></div>
|
return <div className="non-card"><span>PASS</span></div>
|
||||||
}else{
|
}else{
|
||||||
return (
|
return (
|
||||||
<div className={"playingCards unselectable "+fadeClassName}>
|
<div className={"playingCards unselectable loose "+fadeClassName}>
|
||||||
<ul className="hand" style={{width: computeHandCardsWidth(cards.length, 12)}}>
|
<ul className="hand" style={{width: computeHandCardsWidth(cards.length, 12)}}>
|
||||||
{cards.map(card=>{
|
{cards.map(card=>{
|
||||||
const [rankClass, suitClass, rankText, suitText] = translateCardData(card);
|
const [rankClass, suitClass, rankText, suitText] = translateCardData(card);
|
||||||
|
@ -46,7 +87,7 @@ class DoudizhuGameBoard extends React.Component {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="player-hand-up">
|
<div className="player-hand-up">
|
||||||
<div className="playingCards unselectable">
|
<div className="playingCards unselectable loose">
|
||||||
<ul className="hand">
|
<ul className="hand">
|
||||||
{upCards.map(card => {
|
{upCards.map(card => {
|
||||||
const [rankClass, suitClass, rankText, suitText] = translateCardData(card);
|
const [rankClass, suitClass, rankText, suitText] = translateCardData(card);
|
||||||
|
@ -63,7 +104,7 @@ class DoudizhuGameBoard extends React.Component {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="player-hand-down">
|
<div className="player-hand-down">
|
||||||
<div className="playingCards unselectable">
|
<div className="playingCards unselectable loose">
|
||||||
<ul className="hand">
|
<ul className="hand">
|
||||||
{downCards.map(card => {
|
{downCards.map(card => {
|
||||||
const [rankClass, suitClass, rankText, suitText] = translateCardData(card);
|
const [rankClass, suitClass, rankText, suitText] = translateCardData(card);
|
||||||
|
@ -84,15 +125,18 @@ class DoudizhuGameBoard extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
playerDecisionArea(playerIdx){
|
playerDecisionArea(playerIdx){
|
||||||
if(this.props.currentPlayer === playerIdx){
|
|
||||||
return <div className="non-card"><span>{`Consideration Time: ${millisecond2Second(this.props.considerationTime)}s`}</span></div>
|
|
||||||
}else{
|
|
||||||
|
|
||||||
let fadeClassName = "";
|
let fadeClassName = "";
|
||||||
if(this.props.toggleFade === "fade-out" && (playerIdx+2)%3 === this.props.currentPlayer)
|
if(this.props.toggleFade === "fade-out" && (playerIdx+2)%3 === this.props.currentPlayer)
|
||||||
fadeClassName = "fade-out";
|
fadeClassName = "fade-out";
|
||||||
else if(this.props.toggleFade === "fade-in" && (playerIdx+1)%3 === this.props.currentPlayer)
|
else if(this.props.toggleFade === "fade-in" && (playerIdx+1)%3 === this.props.currentPlayer)
|
||||||
fadeClassName = "scale-fade-in";
|
fadeClassName = "scale-fade-in";
|
||||||
|
if(this.props.currentPlayer === playerIdx){
|
||||||
|
return (
|
||||||
|
<div className={"timer "+fadeClassName}>
|
||||||
|
<div className="timer-text">{millisecond2Second(this.props.considerationTime)}</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}else{
|
||||||
return this.computeSingleLineHand(this.props.latestAction[playerIdx], fadeClassName)
|
return this.computeSingleLineHand(this.props.latestAction[playerIdx], fadeClassName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,11 +172,11 @@ class DoudizhuGameBoard extends React.Component {
|
||||||
leftId = found.id;
|
leftId = found.id;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div className="doudizhu-wrapper" style={{width: "100%", height: "100%", backgroundColor: "#ffcc99", position: "relative"}}>
|
<div className="doudizhu-wrapper" style={{}}>
|
||||||
<div id={"left-player"}>
|
<div id={"left-player"}>
|
||||||
<div className="player-main-area">
|
<div className="player-main-area">
|
||||||
<div className="player-info">
|
<div className="player-info">
|
||||||
<span>{`Player Id ${leftId}\n${this.props.playerInfo.length > 0 ? this.props.playerInfo[leftIdx].role : ""}`}</span>
|
{this.computePlayerPortrait(leftId, leftIdx)}
|
||||||
</div>
|
</div>
|
||||||
{leftIdx >= 0 ? this.computeSideHand(this.props.hands[leftIdx]) : <div className="player-hand-placeholder"><span>Waiting...</span></div>}
|
{leftIdx >= 0 ? this.computeSideHand(this.props.hands[leftIdx]) : <div className="player-hand-placeholder"><span>Waiting...</span></div>}
|
||||||
</div>
|
</div>
|
||||||
|
@ -143,7 +187,7 @@ class DoudizhuGameBoard extends React.Component {
|
||||||
<div id={"right-player"}>
|
<div id={"right-player"}>
|
||||||
<div className="player-main-area">
|
<div className="player-main-area">
|
||||||
<div className="player-info">
|
<div className="player-info">
|
||||||
<span>{`Player Id ${rightId}\n${this.props.playerInfo.length > 0 ? this.props.playerInfo[rightIdx].role : ""}`}</span>
|
{this.computePlayerPortrait(rightId, rightIdx)}
|
||||||
</div>
|
</div>
|
||||||
{rightIdx >= 0 ? this.computeSideHand(this.props.hands[rightIdx]) : <div className="player-hand-placeholder"><span>Waiting...</span></div>}
|
{rightIdx >= 0 ? this.computeSideHand(this.props.hands[rightIdx]) : <div className="player-hand-placeholder"><span>Waiting...</span></div>}
|
||||||
</div>
|
</div>
|
||||||
|
@ -157,7 +201,7 @@ class DoudizhuGameBoard extends React.Component {
|
||||||
</div>
|
</div>
|
||||||
<div className="player-main-area">
|
<div className="player-main-area">
|
||||||
<div className="player-info">
|
<div className="player-info">
|
||||||
<span>{`Player Id ${bottomId}\n${this.props.playerInfo.length > 0 ? this.props.playerInfo[bottomIdx].role : ""}`}</span>
|
{this.computePlayerPortrait(bottomId, bottomIdx)}
|
||||||
</div>
|
</div>
|
||||||
{bottomIdx >= 0 ? <div className="player-hand">{this.computeSingleLineHand(this.props.hands[bottomIdx])}</div> : <div className="player-hand-placeholder"><span>Waiting...</span></div>}
|
{bottomIdx >= 0 ? <div className="player-hand">{this.computeSingleLineHand(this.props.hands[bottomIdx])}</div> : <div className="player-hand-placeholder"><span>Waiting...</span></div>}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import React from 'react';
|
|
||||||
import DoudizhuGameBoard from "./DoudizhuGameBoard";
|
import DoudizhuGameBoard from "./DoudizhuGameBoard";
|
||||||
import LeducHoldemGameBoard from "./LeducHoldemGameBoard";
|
import LeducHoldemGameBoard from "./LeducHoldemGameBoard";
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
import React, {useState} from "react";
|
||||||
|
import logo_white from "../assets/images/logo_white.png";
|
||||||
|
import GitHubIcon from "@material-ui/icons/GitHub";
|
||||||
|
import AppBar from "@material-ui/core/AppBar";
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
export function Navbar(props) {
|
||||||
|
const [stars, setStars] = useState("...");
|
||||||
|
axios.get("https://api.github.com/repos/datamllab/rlcard")
|
||||||
|
.then(res=>{
|
||||||
|
setStars(res.data.stargazers_count);
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<AppBar position="static">
|
||||||
|
<div className={"header-bar"}>
|
||||||
|
<img src={logo_white} alt={"Logo"} height="65px" />
|
||||||
|
<div className={"title unselectable"}>Showdown<span className={"subtitle"}>/ {props.gameName}</span></div>
|
||||||
|
<div className={"stretch"} />
|
||||||
|
<div className={"github-info"} onClick={()=>{window.location.href = 'https://github.com/datamllab/rlcard'}}>
|
||||||
|
<div className={"github-icon"}><GitHubIcon /></div>
|
||||||
|
<div className={"github-text"}>Github<br /><span>{stars} stars</span></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</AppBar>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Navbar;
|
|
@ -2,20 +2,19 @@ import React from 'react';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import '../assets/gameview.scss';
|
import '../assets/gameview.scss';
|
||||||
import { DoudizhuGameBoard } from '../components/GameBoard';
|
import { DoudizhuGameBoard } from '../components/GameBoard';
|
||||||
|
import Navbar from "../components/Navbar";
|
||||||
import {removeCards, doubleRaf, deepCopy, computeHandCardsWidth, translateCardData} from "../utils";
|
import {removeCards, doubleRaf, deepCopy, computeHandCardsWidth, translateCardData} from "../utils";
|
||||||
|
|
||||||
import { Layout } from 'element-react';
|
import { Layout, Message, Loading } from 'element-react';
|
||||||
import Slider from '@material-ui/core/Slider';
|
import Slider from '@material-ui/core/Slider';
|
||||||
import Button from '@material-ui/core/Button';
|
import Button from '@material-ui/core/Button';
|
||||||
import Paper from '@material-ui/core/Paper';
|
import Paper from '@material-ui/core/Paper';
|
||||||
import Divider from '@material-ui/core/Divider';
|
import Divider from '@material-ui/core/Divider';
|
||||||
import LinearProgress from '@material-ui/core/LinearProgress';
|
import LinearProgress from '@material-ui/core/LinearProgress';
|
||||||
import ButtonGroup from '@material-ui/core/ButtonGroup';
|
|
||||||
import PlayArrowRoundedIcon from '@material-ui/icons/PlayArrowRounded';
|
import PlayArrowRoundedIcon from '@material-ui/icons/PlayArrowRounded';
|
||||||
import PauseCircleOutlineRoundedIcon from '@material-ui/icons/PauseCircleOutlineRounded';
|
import PauseCircleOutlineRoundedIcon from '@material-ui/icons/PauseCircleOutlineRounded';
|
||||||
import ReplayRoundedIcon from '@material-ui/icons/ReplayRounded';
|
import ReplayRoundedIcon from '@material-ui/icons/ReplayRounded';
|
||||||
import NotInterestedIcon from '@material-ui/icons/NotInterested';
|
import NotInterestedIcon from '@material-ui/icons/NotInterested';
|
||||||
import PlayArrowIcon from '@material-ui/icons/PlayArrow';
|
|
||||||
import SkipNextIcon from '@material-ui/icons/SkipNext';
|
import SkipNextIcon from '@material-ui/icons/SkipNext';
|
||||||
import SkipPreviousIcon from '@material-ui/icons/SkipPrevious';
|
import SkipPreviousIcon from '@material-ui/icons/SkipPrevious';
|
||||||
|
|
||||||
|
@ -47,7 +46,8 @@ class DoudizhuGameView extends React.Component {
|
||||||
this.state = {
|
this.state = {
|
||||||
gameInfo: this.initGameState,
|
gameInfo: this.initGameState,
|
||||||
gameStateLoop: null,
|
gameStateLoop: null,
|
||||||
gameSpeed: 0
|
gameSpeed: 0,
|
||||||
|
fullScreenLoading: false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +72,11 @@ class DoudizhuGameView extends React.Component {
|
||||||
if (remainedCards !== false) {
|
if (remainedCards !== false) {
|
||||||
gameInfo.hands[newMove.playerIdx] = remainedCards;
|
gameInfo.hands[newMove.playerIdx] = remainedCards;
|
||||||
} else {
|
} else {
|
||||||
console.log("Cannot find cards in move from player's hand");
|
Message({
|
||||||
|
message: "Cannot find cards in move from player's hand",
|
||||||
|
type: "error",
|
||||||
|
showClose: true
|
||||||
|
});
|
||||||
}
|
}
|
||||||
// check if game ends
|
// check if game ends
|
||||||
if(remainedCards.length === 0){
|
if(remainedCards.length === 0){
|
||||||
|
@ -92,7 +96,11 @@ class DoudizhuGameView extends React.Component {
|
||||||
alert("Peasants Win");
|
alert("Peasants Win");
|
||||||
}, 200);
|
}, 200);
|
||||||
}else{
|
}else{
|
||||||
console.log("Error in finding winner");
|
Message({
|
||||||
|
message: "Error in finding winner",
|
||||||
|
type: "error",
|
||||||
|
showClose: true
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return gameInfo;
|
return gameInfo;
|
||||||
|
@ -100,13 +108,21 @@ class DoudizhuGameView extends React.Component {
|
||||||
gameInfo.considerationTime = this.initConsiderationTime;
|
gameInfo.considerationTime = this.initConsiderationTime;
|
||||||
gameInfo.completedPercent += 100.0 / (this.moveHistory.length - 1);
|
gameInfo.completedPercent += 100.0 / (this.moveHistory.length - 1);
|
||||||
}else {
|
}else {
|
||||||
console.log("Mismatched current player index");
|
Message({
|
||||||
|
message: "Mismatched current player index",
|
||||||
|
type: "error",
|
||||||
|
showClose: true
|
||||||
|
});
|
||||||
}
|
}
|
||||||
// if current state is new to game state history, push it to the game state history array
|
// if current state is new to game state history, push it to the game state history array
|
||||||
if(gameInfo.turn === this.gameStateHistory.length){
|
if(gameInfo.turn === this.gameStateHistory.length){
|
||||||
this.gameStateHistory.push(gameInfo);
|
this.gameStateHistory.push(gameInfo);
|
||||||
}else{
|
}else{
|
||||||
console.log("inconsistent game state history length and turn number");
|
Message({
|
||||||
|
message: "inconsistent game state history length and turn number",
|
||||||
|
type: "error",
|
||||||
|
showClose: true
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return gameInfo;
|
return gameInfo;
|
||||||
|
@ -129,7 +145,7 @@ class DoudizhuGameView extends React.Component {
|
||||||
this.gameStateTimer();
|
this.gameStateTimer();
|
||||||
}else{
|
}else{
|
||||||
let gameInfo = this.generateNewState();
|
let gameInfo = this.generateNewState();
|
||||||
if(gameInfo.gameStatus == "over") return;
|
if(gameInfo.gameStatus === "over") return;
|
||||||
gameInfo.gameStatus = "playing";
|
gameInfo.gameStatus = "playing";
|
||||||
if(this.state.gameInfo.toggleFade === "fade-out") {
|
if(this.state.gameInfo.toggleFade === "fade-out") {
|
||||||
gameInfo.toggleFade = "fade-in";
|
gameInfo.toggleFade = "fade-in";
|
||||||
|
@ -152,6 +168,8 @@ class DoudizhuGameView extends React.Component {
|
||||||
// for test use
|
// for test use
|
||||||
const replayId = 0;
|
const replayId = 0;
|
||||||
|
|
||||||
|
// start full screen loading
|
||||||
|
this.setState({fullScreenLoading: true});
|
||||||
axios.get(`${this.apiUrl}/replay/doudizhu/${replayId}`)
|
axios.get(`${this.apiUrl}/replay/doudizhu/${replayId}`)
|
||||||
.then(res => {
|
.then(res => {
|
||||||
res = res.data;
|
res = res.data;
|
||||||
|
@ -168,7 +186,7 @@ class DoudizhuGameView extends React.Component {
|
||||||
if(this.gameStateHistory.length === 0){ // fix replay bug
|
if(this.gameStateHistory.length === 0){ // fix replay bug
|
||||||
this.gameStateHistory.push(gameInfo);
|
this.gameStateHistory.push(gameInfo);
|
||||||
}
|
}
|
||||||
this.setState({gameInfo: gameInfo}, ()=>{
|
this.setState({gameInfo: gameInfo, fullScreenLoading: false}, ()=>{
|
||||||
if(this.gameStateTimeout){
|
if(this.gameStateTimeout){
|
||||||
window.clearTimeout(this.gameStateTimeout);
|
window.clearTimeout(this.gameStateTimeout);
|
||||||
this.gameStateTimeout = null;
|
this.gameStateTimeout = null;
|
||||||
|
@ -176,11 +194,18 @@ class DoudizhuGameView extends React.Component {
|
||||||
// loop to update game state
|
// loop to update game state
|
||||||
this.gameStateTimer();
|
this.gameStateTimer();
|
||||||
});
|
});
|
||||||
|
})
|
||||||
|
.catch(()=>{
|
||||||
|
this.setState({fullScreenLoading: false});
|
||||||
|
Message({
|
||||||
|
message: "Error in getting replay data",
|
||||||
|
type: "error",
|
||||||
|
showClose: true
|
||||||
});
|
});
|
||||||
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
runNewTurn(prevTurn){
|
runNewTurn(){
|
||||||
this.gameStateTimer();
|
this.gameStateTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,7 +250,7 @@ class DoudizhuGameView extends React.Component {
|
||||||
return <div className={"non-card "+this.state.gameInfo.toggleFade}><span>Pass</span></div>
|
return <div className={"non-card "+this.state.gameInfo.toggleFade}><span>Pass</span></div>
|
||||||
}else{
|
}else{
|
||||||
return (
|
return (
|
||||||
<div className={"unselectable playingCards "+this.state.gameInfo.toggleFade}>
|
<div className={"unselectable playingCards loose "+this.state.gameInfo.toggleFade}>
|
||||||
<ul className="hand" style={{width: computeHandCardsWidth(cards.length, 10)}}>
|
<ul className="hand" style={{width: computeHandCardsWidth(cards.length, 10)}}>
|
||||||
{cards.map(card=>{
|
{cards.map(card=>{
|
||||||
const [rankClass, suitClass, rankText, suitText] = translateCardData(card);
|
const [rankClass, suitClass, rankText, suitText] = translateCardData(card);
|
||||||
|
@ -247,7 +272,7 @@ class DoudizhuGameView extends React.Component {
|
||||||
computeProbabilityItem(idx){
|
computeProbabilityItem(idx){
|
||||||
if(this.state.gameInfo.gameStatus !== "ready" && this.state.gameInfo.turn < this.moveHistory.length){
|
if(this.state.gameInfo.gameStatus !== "ready" && this.state.gameInfo.turn < this.moveHistory.length){
|
||||||
let style = {};
|
let style = {};
|
||||||
style["backgroundColor"] = this.moveHistory[this.state.gameInfo.turn].probabilities.length > idx ? `rgba(189,183,107,${this.moveHistory[this.state.gameInfo.turn].probabilities[idx].probability})` : "#bdbdbd";
|
style["backgroundColor"] = this.moveHistory[this.state.gameInfo.turn].probabilities.length > idx ? `rgba(245, 176, 65 , ${this.moveHistory[this.state.gameInfo.turn].probabilities[idx].probability})` : "#bdbdbd";
|
||||||
return (
|
return (
|
||||||
<div className={"playing"} style={style}>
|
<div className={"playing"} style={style}>
|
||||||
<div className="probability-move">
|
<div className="probability-move">
|
||||||
|
@ -322,6 +347,8 @@ class DoudizhuGameView extends React.Component {
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<div>
|
||||||
|
<Navbar gameName={"Doudizhu"} />
|
||||||
<div className={"doudizhu-view-container"}>
|
<div className={"doudizhu-view-container"}>
|
||||||
<Layout.Row style={{"height": "540px"}}>
|
<Layout.Row style={{"height": "540px"}}>
|
||||||
<Layout.Col style={{"height": "100%"}} span="17">
|
<Layout.Col style={{"height": "100%"}} span="17">
|
||||||
|
@ -370,6 +397,7 @@ class DoudizhuGameView extends React.Component {
|
||||||
<div className="progress-bar">
|
<div className="progress-bar">
|
||||||
<LinearProgress variant="determinate" value={this.state.gameInfo.completedPercent} />
|
<LinearProgress variant="determinate" value={this.state.gameInfo.completedPercent} />
|
||||||
</div>
|
</div>
|
||||||
|
<Loading loading={this.state.fullScreenLoading}>
|
||||||
<div className="game-controller">
|
<div className="game-controller">
|
||||||
<Paper className={"game-controller-paper"} elevation={3}>
|
<Paper className={"game-controller-paper"} elevation={3}>
|
||||||
<Layout.Row style={{"height": "51px"}}>
|
<Layout.Row style={{"height": "51px"}}>
|
||||||
|
@ -424,11 +452,8 @@ class DoudizhuGameView extends React.Component {
|
||||||
</Layout.Col>
|
</Layout.Col>
|
||||||
</Layout.Row>
|
</Layout.Row>
|
||||||
</Paper>
|
</Paper>
|
||||||
{/*<Layout.Row>*/}
|
</div>
|
||||||
{/* <Layout.Col span="24">*/}
|
</Loading>
|
||||||
{/* {`Current Player: ${this.state.gameInfo.currentPlayer} , Consideration Time: ${this.state.gameInfo.considerationTime}, Turn: ${this.state.gameInfo.turn}`}*/}
|
|
||||||
{/* </Layout.Col>*/}
|
|
||||||
{/*</Layout.Row>*/}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
@ -10,12 +10,10 @@ import Button from '@material-ui/core/Button';
|
||||||
import Paper from '@material-ui/core/Paper';
|
import Paper from '@material-ui/core/Paper';
|
||||||
import Divider from '@material-ui/core/Divider';
|
import Divider from '@material-ui/core/Divider';
|
||||||
import LinearProgress from '@material-ui/core/LinearProgress';
|
import LinearProgress from '@material-ui/core/LinearProgress';
|
||||||
import ButtonGroup from '@material-ui/core/ButtonGroup';
|
|
||||||
import PlayArrowRoundedIcon from '@material-ui/icons/PlayArrowRounded';
|
import PlayArrowRoundedIcon from '@material-ui/icons/PlayArrowRounded';
|
||||||
import PauseCircleOutlineRoundedIcon from '@material-ui/icons/PauseCircleOutlineRounded';
|
import PauseCircleOutlineRoundedIcon from '@material-ui/icons/PauseCircleOutlineRounded';
|
||||||
import ReplayRoundedIcon from '@material-ui/icons/ReplayRounded';
|
import ReplayRoundedIcon from '@material-ui/icons/ReplayRounded';
|
||||||
import NotInterestedIcon from '@material-ui/icons/NotInterested';
|
import NotInterestedIcon from '@material-ui/icons/NotInterested';
|
||||||
import PlayArrowIcon from '@material-ui/icons/PlayArrow';
|
|
||||||
import SkipNextIcon from '@material-ui/icons/SkipNext';
|
import SkipNextIcon from '@material-ui/icons/SkipNext';
|
||||||
import SkipPreviousIcon from '@material-ui/icons/SkipPrevious';
|
import SkipPreviousIcon from '@material-ui/icons/SkipPrevious';
|
||||||
|
|
||||||
|
@ -106,7 +104,7 @@ class LeducHoldemGameView extends React.Component {
|
||||||
console.log("Error in player's latest action");
|
console.log("Error in player's latest action");
|
||||||
}
|
}
|
||||||
gameInfo.turn++;
|
gameInfo.turn++;
|
||||||
if(gameInfo.round !== 0 && gameInfo.turn == this.moveHistory[gameInfo.round].length){
|
if(gameInfo.round !== 0 && gameInfo.turn === this.moveHistory[gameInfo.round].length){
|
||||||
gameInfo.gameStatus = "over";
|
gameInfo.gameStatus = "over";
|
||||||
this.setState({gameInfo: gameInfo});
|
this.setState({gameInfo: gameInfo});
|
||||||
setTimeout(()=>{
|
setTimeout(()=>{
|
||||||
|
@ -150,7 +148,7 @@ class LeducHoldemGameView extends React.Component {
|
||||||
this.gameStateTimer();
|
this.gameStateTimer();
|
||||||
}else{
|
}else{
|
||||||
let gameInfo = this.generateNewState();
|
let gameInfo = this.generateNewState();
|
||||||
if(gameInfo.gameStatus == "over") return;
|
if(gameInfo.gameStatus === "over") return;
|
||||||
this.gameStateTimer();
|
this.gameStateTimer();
|
||||||
gameInfo.gameStatus = "playing";
|
gameInfo.gameStatus = "playing";
|
||||||
if(this.state.gameInfo.toggleFade === "fade-out") {
|
if(this.state.gameInfo.toggleFade === "fade-out") {
|
||||||
|
@ -244,7 +242,7 @@ class LeducHoldemGameView extends React.Component {
|
||||||
currentMove = this.moveHistory[this.state.gameInfo.round][this.state.gameInfo.turn];
|
currentMove = this.moveHistory[this.state.gameInfo.round][this.state.gameInfo.turn];
|
||||||
}
|
}
|
||||||
let style = {};
|
let style = {};
|
||||||
style["backgroundColor"] = currentMove !== null ? `rgba(189,183,107,${currentMove.probabilities[idx].probability})` : "#bdbdbd";;
|
style["backgroundColor"] = currentMove !== null ? `rgba(189,183,107,${currentMove.probabilities[idx].probability})` : "#bdbdbd";
|
||||||
return (
|
return (
|
||||||
<div className={"playing"} style={style}>
|
<div className={"playing"} style={style}>
|
||||||
<div className="probability-move">
|
<div className="probability-move">
|
||||||
|
@ -262,7 +260,7 @@ class LeducHoldemGameView extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
go2PrevGameState() {
|
go2PrevGameState() {
|
||||||
let gameInfo = null;
|
let gameInfo;
|
||||||
if(this.state.gameInfo.turn === 0 && this.state.gameInfo.round !== 0){
|
if(this.state.gameInfo.turn === 0 && this.state.gameInfo.round !== 0){
|
||||||
let prevRound = this.gameStateHistory[this.state.gameInfo.round-1];
|
let prevRound = this.gameStateHistory[this.state.gameInfo.round-1];
|
||||||
gameInfo = deepCopy(prevRound[prevRound.length-1]);
|
gameInfo = deepCopy(prevRound[prevRound.length-1]);
|
||||||
|
|