player component
This commit is contained in:
parent
b8c6e72b42
commit
c4ed006020
@ -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)
|
||||||
|
@ -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):
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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%;
|
||||||
|
47
frontend/src/components/Chat.vue
Normal file
47
frontend/src/components/Chat.vue
Normal 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>
|
@ -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>
|
||||||
|
@ -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>
|
||||||
|
81
frontend/src/components/Player.vue
Normal file
81
frontend/src/components/Player.vue
Normal 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>
|
Loading…
Reference in New Issue
Block a user