Start with the second card facing down
Dealer's hand
We shouldn't be seeing the second card right away, let's fix this.
For the dealer's hand it's quite simple for now, since they're always with 2 cards, we can just change it to:
let dealer_row = row![
image(String::from("img/") + &self.dealer_hand.cards[0].get_id() + ".png").height(Length::Fixed(200.)),
image(String::from("img/back.png")).height(Length::Fixed(200.))
].spacing(10);
And let's hide the dealer's hand value as well, otherwise there's no point in hiding the card:
let dealer_info = container(
col![
dealer_row,
text("?").size(35),
Rule::horizontal(4.),
Player's hand
Our hand is a bit more tricky, since there's more to do already.
This initial dealing of the 2 cards and the later part with the player dealing cards have quite a number of different UI elements, so perhaps it's good to have a way to know in which part of the game we're on, let's create a new enum to indicate in which stage of the game we're in and add it to our app's state:
(I'm only showing the changed lines, but you can click on the eye button to see everything)
#[derive(PartialEq)]
enum GameStage {
Init, Dealing
}
struct IcedTwentyOne {
deck: Deck,
player_hand: Hand,
dealer_hand: Hand,
game_stage: GameStage,
}
impl Default for IcedTwentyOne {
fn default() -> IcedTwentyOne {
let mut deck = Deck::new();
let mut player = Hand::new();
let mut dealer = Hand::new();
deck.shuffle();
player.push(deck.deal_card().unwrap());
player.push(deck.deal_card().unwrap());
dealer.push(deck.deal_card().unwrap());
dealer.push(deck.deal_card().unwrap());
IcedTwentyOne {
deck: deck,
player_hand: player,
dealer_hand: dealer,
game_stage: GameStage::Init,
}
}
}
If we're gonna hide our second card, we also need a way to start the game, so let's create a new Message
for that:
#[derive(Debug, Clone, Copy)]
enum Message {
Start,
DealCard
}
And add the processing of this message in our update()
:
fn update(&mut self, message: Self::Message) -> Command<Self::Message> {
match message {
Message::DealCard => {
if let Some(new_card) = self.deck.deal_card() {
self.player_hand.push(new_card);
}
} Message::Start => {
self.game_stage = GameStage::Dealing;
}
}
Command::none()
}
But this message has to come from somewhere, so along with changing the card's image and the hand's value, we need to have a button to start the game. These are a lot of changes, so we'll need to separate our column!
macro call in two.
We'll create the Column
in a variable, with an if
to check which version we want, replace the player_row
and the for
below it to this:
let player_info_col = if self.game_stage == GameStage::Init {
col![
Rule::horizontal(4.),
text("?").size(35),
row![
image(String::from("img/") + &self.player_hand.cards[0].get_id() + ".png").height(Length::Fixed(200.)),
image(String::from("img/back.png")).height(Length::Fixed(200.)),
].spacing(10),
button(text("Start Game")).on_press(Message::Start),
].width(Length::Fill).align_items(iced::Alignment::Center).spacing(20)
} else {
let mut player_row = Row::new().spacing(10);
for card in &self.player_hand.cards {
player_row = player_row.push(image(String::from("img/") + &card.get_id() + ".png").height(Length::Fixed(200.)));
}
col![
Rule::horizontal(4.),
text(self.player_hand.value().to_string()).size(35),
player_row,
button(text("Deal another card")).on_press(Message::DealCard),
].width(Length::Fill).align_items(iced::Alignment::Center).spacing(20)
};
we then, just pass that to the container later:
let player_info = container(player_info_col).height(Length::Fill).align_y(Vertical::Bottom);
Summary
So, to get everything together, this is our current view()
:
fn view(&self) -> Element<Message, iced::Renderer<theme::TwentyOneTheme>> {
let dealer_row = row![
image(String::from("img/") + &self.dealer_hand.cards[0].get_id() + ".png").height(Length::Fixed(200.)),
image(String::from("img/back.png")).height(Length::Fixed(200.))
].spacing(10);
let dealer_info = container(
col![
dealer_row,
text("?").size(35),
Rule::horizontal(4.),
].width(Length::Fill).align_items(iced::Alignment::Center).spacing(20)
).height(Length::Fill).align_y(Vertical::Top);
let player_info_col = if self.game_stage == GameStage::Init {
col![
Rule::horizontal(4.),
text("?").size(35),
row![
image(String::from("img/") + &self.player_hand.cards[0].get_id() + ".png").height(Length::Fixed(200.)),
image(String::from("img/back.png")).height(Length::Fixed(200.)),
].spacing(10),
button(text("Start Game")).on_press(Message::Start),
].width(Length::Fill).align_items(iced::Alignment::Center).spacing(20)
} else {
let mut player_row = Row::new().spacing(10);
for card in &self.player_hand.cards {
player_row = player_row.push(image(String::from("img/") + &card.get_id() + ".png").height(Length::Fixed(200.)));
}
col![
Rule::horizontal(4.),
text(self.player_hand.value().to_string()).size(35),
player_row,
button(text("Deal another card")).on_press(Message::DealCard),
].width(Length::Fill).align_items(iced::Alignment::Center).spacing(20)
};
let player_info = container(player_info_col).height(Length::Fill).align_y(Vertical::Bottom);
let table_col = col![
dealer_info,
player_info,
].align_items(iced::Alignment::Center).spacing(10);
container(table_col)
.width(Length::Fill)
.height(Length::Fill)
.center_y()
.padding(40)
.into()
}