I love playing card games, one of them is Uno! and this month I tried to replicate it in Neptune just using UI5 objects, JavaScript, Redis and CSS.
Today I want to share the project available for everyone on my personal GitHub! At the end of the blog you will also find a full play demo.
A big thank you to my wife that gave me the idea.
- Planet 9 (Open Edition DXP 23 or higher)
- Redis installed / configured in the cockpit settings (you can follow my Getting Started)
- Open your Planet 9 instance and go inside the Development Package section
- Select the Import > Git option
- In Remote Repository URL paste my GitHub repository
https://github.com/fabriziopace/neptune-uno-card-game.git
- Click now on the OK button, this will import all artifacts used in this project
- You will find a new tile in the Neptune Cockpit > Entertainment section
- Have fun!
When the user access the first time to the application can create a new room.
In order to join in the room the host will send the link got from the share button in the header menu to other user. Example:
http://localhost:8080/app/uno_card_game?room=NeptuneCommunity
Then the user can enter the username and join.
- In the header bar we have the room / opponent user data and the button to exit from the room
- In the body two cards hands are rendered once the game starts, in addition of the deck and the pile
- Below we have a footer containing three action buttons (getting a new card, skip the turn or calling uno), your user data and the current color
- A crown will be visible near the user when he will get his turn and only playable cards will be enabled
In the App Designer I created four sap.m.List elements containing the opponent and personal hands, the deck and the pile.
When the game starts all cards are built in the startGame function, where for each of them an id is generated (to move a specific card from a list to another when needed).
The deck is shuffled and each user gets seven cards.
On any user action like getting a new card or skipping the turn the data is sent using Neptune Events to the other user.
The game tries to follow the official rules and is composed of 108 cards in total (excluding one "Wild Shuffle Hands" and three "Wild Customizable").
The first user to get rid of all personal hand cards wins the game.
- Allow to invite more users to play the game (currently maximum 2 per room)
- The game interface can be improved with smoother animations
- JavaScript code can be adapted for further logics like having more rounds and counting user points
- Cards data can be moved to a Planet 9 table
I had a lot of fun and improved my skills using SCSS. For example nesting CSS selectors, writing variables and mixin to reuse a group of properties in many places or even looping list items to apply an incremental rotation and z-index on cards hands / pile.
$rotateMyCardDeg: -10;
$rotateOppCardDeg: 10;
@for $i from 1 through 100 {
$rotateMyCardDeg: $rotateMyCardDeg + 1;
.listMyCards li:nth-child(#{$i}) {
z-index: $i;
rotate: $rotateMyCardDeg + deg;
}
$rotateOppCardDeg: $rotateOppCardDeg - 1;
.listOppCards li:nth-child(#{$i}) {
z-index: $i;
rotate: $rotateOppCardDeg + deg;
}
}
Was challenging building all UNO! cards assigning custom data to each list item:
// based on value property style the card
let cardValue = "";
if (
value !== "skip" &&
value !== "reverse" &&
value !== "drawtwo" &&
value !== "wild" &&
value !== "wilddrawfour"
) {
cardValue = value;
}
this.data("value", value, true);
return cardValue;
And then using SCSS to apply colors and UI5 icons:
// mixin for common styles
@mixin wildIcon($sapIcon: "") {
content: $sapIcon;
font-family: SAP-icons;
font-style: normal;
font-weight: normal;
background: linear-gradient(to right, $redColor 0%, $redColor 50%, $blueColor 50%, $blueColor 100%), linear-gradient(to right, $yellowColor 0%, $yellowColor 50%, $greenColor 50%, $greenColor 100%);
background-size: 100% 50%;
background-position: center top, center bottom;
background-repeat: no-repeat;
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
}
// wild cards
[data-value="wild"].textCardStyle:after {
@include wildIcon($sapIcon: '\e145');
}
// wild draw four cards
[data-value="wilddrawfour"].textCardHeader:after,
[data-value="wilddrawfour"].textCardFooter:after {
content: '+4';
fill: $whiteColor;
}
[data-value="wilddrawfour"].textCardBody:after {
@include wildIcon($sapIcon: '\e0bc');
}
I created a GIF (it may require some time to load):
Redis involved blogs
- Getting started with Redis and Planet 9
- Getting started with Drag and Drop & Events with Redis
- Queue management Applications
- JD Bingo – Game built in 1 day with Planet 9 and Redis
UI5 icons usage by CSS content property
SCSS tutorials
My motto: always make sure to have fun to unlock your limits!
Wish you all to reach and make your dreams real.
Happy coding and remember to call UNO! :)