player component

This commit is contained in:
Alberto Xamin 2020-11-20 17:33:15 +01:00
parent b8c6e72b42
commit c4ed006020
No known key found for this signature in database
GPG Key ID: 4F026F48309500A2
9 changed files with 191 additions and 31 deletions

View File

@ -3,7 +3,7 @@ import random
from cards import Card, get_starting_deck from cards import Card, get_starting_deck
class Deck: class Deck:
def __init__(self): def __init__(self, sio):
super().__init__() super().__init__()
self.cards: List[Card] = get_starting_deck() self.cards: List[Card] = get_starting_deck()
random.shuffle(self.cards) random.shuffle(self.cards)

View File

@ -15,6 +15,7 @@ class Game:
self.deck: Deck = None self.deck: Deck = None
self.started = False self.started = False
self.turn = 0 self.turn = 0
self.readyCount = 0
def handle_disconnect(self, player: players.Player): def handle_disconnect(self, player: players.Player):
print(f'player {player.name} left the game {self.name}') print(f'player {player.name} left the game {self.name}')
@ -35,6 +36,11 @@ class Game:
self.sio.emit('room', room=self.name, data={'name': self.name, 'started': self.started, 'players': [p.name for p in self.players]}) self.sio.emit('room', room=self.name, data={'name': self.name, 'started': self.started, 'players': [p.name for p in self.players]})
self.sio.emit('chat_message', room=self.name, data=f'{player.name} è entrato nella lobby.') self.sio.emit('chat_message', room=self.name, data=f'{player.name} è entrato nella lobby.')
def notify_character_selection(self):
self.readyCount += 1
if self.readyCount == len(self.players):
self.distribute_roles()
def choose_characters(self): def choose_characters(self):
char_cards = random.sample(all_characters(), len(self.players)*2) char_cards = random.sample(all_characters(), len(self.players)*2)
for i in range(len(self.players)): for i in range(len(self.players)):
@ -45,8 +51,9 @@ class Game:
if self.started: if self.started:
return return
self.sio.emit('chat_message', room=self.name, data=f'La partita sta iniziando...') self.sio.emit('chat_message', room=self.name, data=f'La partita sta iniziando...')
self.sio.emit('start', room=self.name)
self.started = True self.started = True
self.deck = Deck() self.deck = Deck(self.sio)
self.choose_characters() self.choose_characters()
def distribute_roles(self): def distribute_roles(self):
@ -61,6 +68,7 @@ class Game:
self.players[i].prepare() self.players[i].prepare()
for k in range(self.players[i].max_lives): for k in range(self.players[i].max_lives):
self.players[i].hand.append(self.deck.draw()) self.players[i].hand.append(self.deck.draw())
self.players[i].notify_self()
self.play_turn() self.play_turn()
def get_visible_players(self, player): def get_visible_players(self, player):

View File

@ -43,6 +43,7 @@ class Player:
def set_role(self, role: roles.Role): def set_role(self, role: roles.Role):
self.role = role self.role = role
print(f'I {self.name} am a {role.name}, my goal is "{role.goal}"') print(f'I {self.name} am a {role.name}, my goal is "{role.goal}"')
self.sio.emit('role', room=self.sid, data=json.dumps(role, default=lambda o: o.__dict__))
def set_character(self, character: str): def set_character(self, character: str):
print(self.available_characters, character) print(self.available_characters, character)
@ -50,6 +51,7 @@ class Player:
self.available_characters = [] self.available_characters = []
print(f'I {self.name} chose character {self.character.name}') print(f'I {self.name} chose character {self.character.name}')
self.sio.emit('chat_message', room=self.game.name, data=f'{self.name} ha scelto il personaggio.') self.sio.emit('chat_message', room=self.game.name, data=f'{self.name} ha scelto il personaggio.')
self.game.notify_character_selection()
def prepare(self): def prepare(self):
self.max_lives = self.character.max_lives + self.role.health_mod self.max_lives = self.character.max_lives + self.role.health_mod
@ -62,6 +64,13 @@ class Player:
print(f'I {self.name} have to choose between {available}') print(f'I {self.name} have to choose between {available}')
self.sio.emit('characters', room=self.sid, data=json.dumps(available, default=lambda o: o.__dict__)) self.sio.emit('characters', room=self.sid, data=json.dumps(available, default=lambda o: o.__dict__))
def notify_self(self):
ser = self.__dict__.copy()
ser.pop('game')
ser.pop('sio')
ser.pop('sid')
self.sio.emit('self', room=self.sid, data=json.dumps(ser, default=lambda o: o.__dict__))
def play_turn(self): def play_turn(self):
print(f'I {self.name} was notified that it is my turn') print(f'I {self.name} was notified that it is my turn')
self.was_shot = False self.was_shot = False
@ -70,6 +79,9 @@ class Player:
self.has_played_bang = False self.has_played_bang = False
if any([isinstance(c) == cards.Dinamite or isinstance(c) == cards.Prigione for c in self.equipment]): if any([isinstance(c) == cards.Dinamite or isinstance(c) == cards.Prigione for c in self.equipment]):
self.pending_action = PendingAction.PICK self.pending_action = PendingAction.PICK
else:
self.pending_action = PendingAction.DRAW
self.notify_self()
# # print(f'lives: {self.lives}/{self.max_lives} hand: {[str(c) for c in self.hand]}') # # print(f'lives: {self.lives}/{self.max_lives} hand: {[str(c) for c in self.hand]}')
# print(f'I {self.name} can see {[p.get_public_description() for p in self.game.get_visible_players(self)]}') # print(f'I {self.name} can see {[p.get_public_description() for p in self.game.get_visible_players(self)]}')
@ -80,6 +92,7 @@ class Player:
for i in range(2): for i in range(2):
self.hand.append(self.game.deck.draw()) self.hand.append(self.game.deck.draw())
self.pending_action = PendingAction.PLAY self.pending_action = PendingAction.PLAY
self.notify_self()
def pick(self): def pick(self):
pickable_cards = 1 + self.character.pick_mod pickable_cards = 1 + self.character.pick_mod

View File

@ -1,6 +1,6 @@
<template> <template>
<div id="app"> <div id="app">
<div id="logo" class="center-stuff" style="margin-bottom:10pt;"> <div v-if="!username" id="logo" class="center-stuff" style="margin-bottom:10pt;">
<h1 style="margin-bottom:0pt;">PewPew!</h1> <h1 style="margin-bottom:0pt;">PewPew!</h1>
<i style="font-size: x-small;">Bang! è un marchio registrato DVGiochi</i> <i style="font-size: x-small;">Bang! è un marchio registrato DVGiochi</i>
</div> </div>
@ -70,6 +70,10 @@ export default {
sockets: { sockets: {
connect() { connect() {
this.isConnected = true; this.isConnected = true;
setTimeout(function(){
this.username =(1+Math.random() * 100 % 100).toFixed(2).toString();
this.setUsername();
}.bind(this), 200)
}, },
disconnect() { disconnect() {
this.isConnected = false; this.isConnected = false;

View File

@ -1,8 +1,8 @@
<template> <template>
<div :class="{ card: true, equipment: card.is_equipment, character:card.is_character }"> <div :class="{ card: true, equipment: card.is_equipment, character:card.is_character }">
<h3>{{card.name}}</h3> <h4>{{card.name}}</h4>
<div class="emoji">{{card.icon}}</div> <div class="emoji">{{card.icon}}</div>
<span>{{card.number}}{{card.suit}}</span> <span>{{card.number}}{{suit}}</span>
</div> </div>
</template> </template>
@ -12,6 +12,15 @@ export default {
props: { props: {
card: Object card: Object
}, },
computed: {
suit() {
if (this.card && !isNaN(this.card.suit)) {
let x = ['♦️','♣️','♥️','♠️']
return x[this.card.suit];
}
return '';
}
}
} }
</script> </script>
@ -31,6 +40,10 @@ export default {
position: relative; position: relative;
transition: all 0.5s ease-in-out; transition: all 0.5s ease-in-out;
color: #333; color: #333;
overflow: hidden;
text-overflow: ellipsis;
word-wrap: normal;
/* word-wrap: break-word; */
} }
.card.back{ .card.back{
color:white; color:white;
@ -52,7 +65,7 @@ export default {
0 0 0 6pt white, 0 0 0 6pt white,
0 0 5pt 6pt #aaa; 0 0 5pt 6pt #aaa;
} }
.card h3 { .card h4 {
position: absolute; position: absolute;
text-align: center; text-align: center;
width: 100%; width: 100%;

View File

@ -0,0 +1,47 @@
<template>
<div>
<h3>Chat</h3>
<div id="chatbox">
<p style="margin:1pt;" v-for="msg in messages" v-bind:key="msg">{{msg}}</p>
</div>
<form @submit="sendChatMessage" style="width:100%; padding:0">
<input v-model="text" style="width:80%;"/>
<input type="submit" style="width:18%;"/>
</form>
</div>
</template>
<script>
export default {
name: 'Chat',
data: () => ({
messages: [],
text: ''
}),
sockets: {
chat_message(msg) {
this.messages.push(msg)
let container = this.$el.querySelector("#chatbox");
container.scrollTop = container.scrollHeight;
},
},
methods: {
sendChatMessage(e) {
if (this.text.trim().length > 0){
this.$socket.emit('chat_message', this.text.trim())
this.text = ''
}
e.preventDefault();
},
},
}
</script>
<style >
#chatbox {
width:100%;
max-height:150px;
overflow:auto;
border: 1pt solid #ccc;
border-radius: 2pt;
}
</style>

View File

@ -1,6 +1,6 @@
<template> <template>
<div id="overlay" class="center-stuff"> <div id="overlay" class="center-stuff">
<h1>Scegli il tuo personaggio</h1> <h1>{{text}}</h1>
<div> <div>
<Card v-for="c in cards" v-bind:key="c" :card="c" @click.native="select(c)"/> <Card v-for="c in cards" v-bind:key="c" :card="c" @click.native="select(c)"/>
</div> </div>
@ -17,7 +17,8 @@ export default {
}, },
props: { props: {
cards: Array, cards: Array,
select: Function select: Function,
text: String,
}, },
} }
</script> </script>

View File

@ -6,27 +6,27 @@
<Card v-if="startGameCard" :card="startGameCard" @click.native="startGame"/> <Card v-if="startGameCard" :card="startGameCard" @click.native="startGame"/>
<Card v-for="p in players" v-bind:key="p" :card="getPlayerCard(p)"/> <Card v-for="p in players" v-bind:key="p" :card="getPlayerCard(p)"/>
</div> </div>
<h3>Chat</h3> <div v-if="started">
<div id="chatbox" style="max-height:200px; overflow:auto;"> <player/>
<p style="margin:1pt;" v-for="msg in messages" v-bind:key="msg">{{msg}}</p>
</div> </div>
<form @submit="sendChatMessage"> <chat/>
<input v-model="text"/> <Chooser v-if="showChooser" text="Scegli il tuo personaggio" :cards="availableCharacters" :select="setCharacter"/>
<input type="submit"/>
</form>
<Chooser v-if="showChooser" :cards="availableCharacters" :select="setCharacter"/>
</div> </div>
</template> </template>
<script> <script>
import Card from '@/components/Card.vue' import Card from '@/components/Card.vue'
import Chooser from './Chooser.vue' import Chooser from './Chooser.vue'
import Chat from './Chat.vue'
import Player from './Player.vue'
export default { export default {
name: 'Lobby', name: 'Lobby',
components: { components: {
Card, Card,
Chooser, Chooser,
Chat,
Player,
}, },
props: { props: {
username: String username: String
@ -37,7 +37,7 @@ export default {
players: [], players: [],
messages: [], messages: [],
availableCharacters: [], availableCharacters: [],
text: '' self: {},
}), }),
sockets: { sockets: {
room(data) { room(data) {
@ -46,14 +46,12 @@ export default {
this.started = data.started this.started = data.started
this.players = data.players this.players = data.players
}, },
chat_message(msg) {
this.messages.push(msg)
let container = this.$el.querySelector("#chatbox");
container.scrollTop = container.scrollHeight;
},
characters(data){ characters(data){
this.availableCharacters = JSON.parse(data) this.availableCharacters = JSON.parse(data)
}, },
start() {
this.started = true;
}
}, },
computed: { computed: {
startGameCard() { startGameCard() {
@ -72,13 +70,6 @@ export default {
} }
}, },
methods: { methods: {
sendChatMessage(e) {
if (this.text.trim().length > 0){
this.$socket.emit('chat_message', this.text.trim())
this.text = ''
}
e.preventDefault();
},
getPlayerCard(username) { getPlayerCard(username) {
return { return {
name: username, name: username,
@ -100,6 +91,8 @@ export default {
</script> </script>
<!-- Add "scoped" attribute to limit CSS to this component only --> <!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped> <style >
#logo {
display:none;
}
</style> </style>

View File

@ -0,0 +1,81 @@
<template>
<div>
<div class="equipment-slot">
<Card v-if="my_role" :card="my_role" class="back"/>
<Card v-if="character" :card="character"/>
<transition-group name="list" tag="equ">
<Card v-for="card in equipment" v-bind:key="card.name+card.number" :card="card" />
</transition-group>
</div>
<div class="hand">
<i>Mano</i>
<Card v-for="card in hand" v-bind:key="card.name+card.number" :card="card" />
</div>
</div>
</template>
<script>
import Card from '@/components/Card.vue'
export default {
name: 'Player',
components: {
Card
},
data: () => ({
my_role: null,
character: null,
equipment: [],
hand: [],
lives: 0,
max_lives: 0,
}),
sockets: {
role(role) {
this.my_role = JSON.parse(role)
},
self(self) {
self = JSON.parse(self)
this.character = self.character
this.character.is_character = true
this.hand = self.hand
this.equipment = self.equipment
this.lives = self.lives
this.max_lives = self.max_lives
}
},
methods: {
},
}
</script>
<style scoped>
.hand>i {
position: absolute;
top: 0;
left: 0;
font-weight: bold;
text-transform: uppercase;
opacity: 0.5;
}
.hand {
position: relative;
display:flex;
border: 1px solid #ccc;
padding: 10pt 40pt 0pt 40pt;
overflow:auto;
border-radius: 4pt;
min-height: 20pt;
}
.hand>.card{
margin-left: -30pt;
}
.hand>.card:hover {
margin-right:35pt;
margin-top:-0.5pt;
}
.equipment-slot, .equipment-slot>equ {
display:flex;
margin:0;
}
</style>