Implement mouse clicking for playing cards

master
En Yi 2019-06-11 19:10:04 +01:00
parent 36b0594106
commit ba88887a72
3 changed files with 112 additions and 37 deletions

24
main.py
View File

@ -37,16 +37,6 @@ class GameScreen(view.PygView):
pygame.display.flip()
def process_events(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
self.running = False
if event.key == pygame.K_p:
if not self.table.ongoing:
self.table.ongoing = True
#def get_player_inputs(self):
# while self.running:
@ -58,10 +48,20 @@ class GameScreen(view.PygView):
self.running = True
#self.player_thread.start()
while self.running:
self.process_events()
all_events = pygame.event.get()
for event in all_events:
if event.type == pygame.QUIT:
self.running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
self.running = False
if event.key == pygame.K_p:
if not self.table.ongoing:
self.table.ongoing = True
if self.table.ongoing:
self.table.continue_game()
self.table.continue_game(all_events)
#if not self.player_commands.empty():
# player_cmd = self.player_commands.get()
# print("Player Command Received: " + player_cmd)

View File

@ -1,5 +1,6 @@
import cards
import pprint
import pygame
from game_consts import GameState, PlayerRole, STARTING_HAND
@ -37,11 +38,12 @@ class Player(cards.Deck):
ai_comp.connect_to_player(self)
self.selectable = False
def make_decision(self, game_state, sub_state):
def make_decision(self, game_state, sub_state, game_events=None):
"""
The player will need to make a decision depending on the game state and sub-state
:param game_state: Current game state
:param sub_state: Sub-state which affects the output for the current game state
:param game_events: Pygame events
:return: For Bidding: Either a bid or a partner call, int
For Playing: A Card
For Reshuffle: bool, True to reshuffle, False otherwise
@ -65,7 +67,7 @@ class Player(cards.Deck):
play = self.AI.make_a_play(sub_state)
[_, pos] = self.check_card_in(play)
return self.remove_card(pos)
return self.make_a_play(sub_state)
return self.make_a_play(sub_state, game_events=game_events)
def make_a_bid(self):
"""
@ -111,7 +113,7 @@ class Player(cards.Deck):
else:
print("Invalid card call")
def make_a_play(self, substate):
def make_a_play(self, substate, game_events=None):
"""
The procedure to make a play in a round
:return: A valid Card
@ -124,10 +126,7 @@ class Player(cards.Deck):
else:
play = cards.convert_input_string(play)
if play > 0:
if substate == 0:
valid = self.check_for_valid_plays(play, True)
else:
valid = self.check_for_valid_plays(play, False)
valid = self.check_for_valid_plays(play, substate == 0)
if valid:
[_, pos] = self.check_card_in(play)
@ -189,8 +188,47 @@ class MainPlayer(Player):
self.AI = ai_component
self.table_status = None # This is found in Table and updated through Table
self.selectable = True
self.left_mouse_down = False
self.double_clicking = False
self.double_click_event = pygame.USEREVENT + 1
self.double_click_timing = 300
def make_a_play(self):
pass
def make_a_play(self, substate, game_events=None):
card = None
if game_events:
for event in game_events:
mouse_clicks = event.type == pygame.MOUSEBUTTONDOWN
if self.left_mouse_down and not mouse_clicks:
print('mouse click')
mouse_pos = pygame.mouse.get_pos()
if self.rect.collidepoint(mouse_pos):
reselect = self.get_selected_card(mouse_pos)
if self.selected_card >= 0 and not reselect:
card = 1
if self.double_clicking:
pygame.time.set_timer(self.double_click_event, 0)
print('Double clicked')
if reselect:
card_value = self.cards[self.selected_card].value
if self.check_for_valid_plays(card_value, substate == 0):
card = self.remove_selected_card()
self.deselect_card()
self.double_clicking = False
else:
self.double_clicking = True
pygame.time.set_timer(self.double_click_event, self.double_click_timing)
if reselect:
self.deselect_card()
card = 1
if event.type == self.double_click_event:
pygame.time.set_timer(self.double_click_event, 0)
self.double_clicking = False
print('double click disabled')
self.left_mouse_down = mouse_clicks
return card

View File

@ -142,11 +142,19 @@ class Table:
reveal_mode = cards.DeckReveal.HIDE_ALL
if i == 0 or view_all_cards:
reveal_mode = cards.DeckReveal.SHOW_ALL
self.players.append(players.Player(playerx[i], playery[i],
l_deck, w_deck,
spacing, vert_orientation=vert,
deck_reveal=reveal_mode, flip=(i == 1 or i == 2),
draw_from_last=(i == 2 or i == 3)))
if i == 0:
self.players.append(players.MainPlayer(playerx[i], playery[i],
l_deck, w_deck,
spacing, vert_orientation=vert,
deck_reveal=reveal_mode))
else:
self.players.append(players.Player(playerx[i], playery[i],
l_deck, w_deck,
spacing, vert_orientation=vert,
deck_reveal=reveal_mode, flip=(i == 1 or i == 2),
draw_from_last=(i == 2 or i == 3)))
self.players[i].connect_to_table(self.table_status)
if i > 0:
self.players[i].add_ai(ai.RandomAI(self.table_status))
@ -183,8 +191,6 @@ class Table:
self.ongoing = False
self.require_player_input = False
def center_text_on_surface(self, surf, rendered_text, clear_colour):
line_center = surf.get_rect().center
text_rect = rendered_text.get_rect(center=line_center)
@ -274,7 +280,7 @@ class Table:
def get_pos(self):
return self.x, self.y
def continue_game(self):
def continue_game(self, game_events):
"""
This is where the FSM is. State transition should occur here.
What takes place in the state should be in a function.
@ -303,7 +309,7 @@ class Table:
self.update_team_scores()
elif self.game_state == GameState.PLAYING:
self.play_a_round()
self.play_a_round(game_events)
if self.current_round == 13:
self.write_message("Game Set! Press P to play again!")
self.ongoing = False
@ -410,23 +416,54 @@ class Table:
self.write_message(msg, line=1, delay_time=1)
return True
def play_a_round(self):
def play_a_round(self, game_events):
"""
Ask each player to play a valid card and determine the winner of the round
This must work without pause if only bots are playing
The function will exit after every player decision or if a user input is needed.
If a user input is required, the function will continuously exit without proceeding to the next player
until a valid input is received.
:return: None
"""
if not any(self.table_status["played cards"]):
# Leading player starts with the leading card, which determines the leading suit
self.current_player = self.table_status['leading player']
self.display_current_player(self.current_player)
card = self.players[self.current_player].make_decision(self.game_state, 0)
if not self.require_player_input:
self.current_player = self.table_status['leading player']
self.display_current_player(self.current_player)
if not self.players[self.current_player].AI:
self.require_player_input = True
return
else:
card = self.players[self.current_player].make_decision(self.game_state, 0)
else:
card = self.players[self.current_player].make_decision(self.game_state, 0, game_events)
if not type(card) is cards.Card:
if card:
self.update_table.emit()
return
self.require_player_input = False
self.table_status["played cards"][self.current_player] = card
self.players_playzone[self.current_player].add_card(card)
elif not all(self.table_status["played cards"]):
# Subsequent player make their plays, following suit if possible
self.display_current_player(self.current_player)
print("Player {0:d}\n".format(self.current_player))
card = self.players[self.current_player].make_decision(self.game_state, 1)
if not self.require_player_input:
self.display_current_player(self.current_player)
if not self.players[self.current_player].AI:
self.require_player_input = True
return
else:
card = self.players[self.current_player].make_decision(self.game_state, 1)
else:
card = self.players[self.current_player].make_decision(self.game_state, 1, game_events)
if not type(card) is cards.Card:
if card:
self.update_table.emit()
return
self.require_player_input = False
self.players_playzone[self.current_player].add_card(card)
self.table_status["played cards"][self.current_player] = card
else: