player component
This commit is contained in:
parent
b8c6e72b42
commit
c4ed006020
@ -3,7 +3,7 @@ import random
|
||||
from cards import Card, get_starting_deck
|
||||
|
||||
class Deck:
|
||||
def __init__(self):
|
||||
def __init__(self, sio):
|
||||
super().__init__()
|
||||
self.cards: List[Card] = get_starting_deck()
|
||||
random.shuffle(self.cards)
|
||||
|
@ -15,6 +15,7 @@ class Game:
|
||||
self.deck: Deck = None
|
||||
self.started = False
|
||||
self.turn = 0
|
||||
self.readyCount = 0
|
||||
|
||||
def handle_disconnect(self, player: players.Player):
|
||||
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('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):
|
||||
char_cards = random.sample(all_characters(), len(self.players)*2)
|
||||
for i in range(len(self.players)):
|
||||
@ -45,8 +51,9 @@ class Game:
|
||||
if self.started:
|
||||
return
|
||||
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.deck = Deck()
|
||||
self.deck = Deck(self.sio)
|
||||
self.choose_characters()
|
||||
|
||||
def distribute_roles(self):
|
||||
@ -61,6 +68,7 @@ class Game:
|
||||
self.players[i].prepare()
|
||||
for k in range(self.players[i].max_lives):
|
||||
self.players[i].hand.append(self.deck.draw())
|
||||
self.players[i].notify_self()
|
||||
self.play_turn()
|
||||
|
||||
def get_visible_players(self, player):
|
||||
|
@ -43,6 +43,7 @@ class Player:
|
||||
def set_role(self, role: roles.Role):
|
||||
self.role = role
|
||||
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):
|
||||
print(self.available_characters, character)
|
||||
@ -50,6 +51,7 @@ class Player:
|
||||
self.available_characters = []
|
||||
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.game.notify_character_selection()
|
||||
|
||||
def prepare(self):
|
||||
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}')
|
||||
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):
|
||||
print(f'I {self.name} was notified that it is my turn')
|
||||
self.was_shot = False
|
||||
@ -70,6 +79,9 @@ class Player:
|
||||
self.has_played_bang = False
|
||||
if any([isinstance(c) == cards.Dinamite or isinstance(c) == cards.Prigione for c in self.equipment]):
|
||||
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'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):
|
||||
self.hand.append(self.game.deck.draw())
|
||||
self.pending_action = PendingAction.PLAY
|
||||
self.notify_self()
|
||||
|
||||
def pick(self):
|
||||
pickable_cards = 1 + self.character.pick_mod
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<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>
|
||||
<i style="font-size: x-small;">Bang! è un marchio registrato DVGiochi</i>
|
||||
</div>
|
||||
@ -70,6 +70,10 @@ export default {
|
||||
sockets: {
|
||||
connect() {
|
||||
this.isConnected = true;
|
||||
setTimeout(function(){
|
||||
this.username =(1+Math.random() * 100 % 100).toFixed(2).toString();
|
||||
this.setUsername();
|
||||
}.bind(this), 200)
|
||||
},
|
||||
disconnect() {
|
||||
this.isConnected = false;
|
||||
|
@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<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>
|
||||
<span>{{card.number}}{{card.suit}}</span>
|
||||
<span>{{card.number}}{{suit}}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -12,6 +12,15 @@ export default {
|
||||
props: {
|
||||
card: Object
|
||||
},
|
||||
computed: {
|
||||
suit() {
|
||||
if (this.card && !isNaN(this.card.suit)) {
|
||||
let x = ['♦️','♣️','♥️','♠️']
|
||||
return x[this.card.suit];
|
||||
}
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -31,6 +40,10 @@ export default {
|
||||
position: relative;
|
||||
transition: all 0.5s ease-in-out;
|
||||
color: #333;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
word-wrap: normal;
|
||||
/* word-wrap: break-word; */
|
||||
}
|
||||
.card.back{
|
||||
color:white;
|
||||
@ -52,7 +65,7 @@ export default {
|
||||
0 0 0 6pt white,
|
||||
0 0 5pt 6pt #aaa;
|
||||
}
|
||||
.card h3 {
|
||||
.card h4 {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
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>
|
||||
<div id="overlay" class="center-stuff">
|
||||
<h1>Scegli il tuo personaggio</h1>
|
||||
<h1>{{text}}</h1>
|
||||
<div>
|
||||
<Card v-for="c in cards" v-bind:key="c" :card="c" @click.native="select(c)"/>
|
||||
</div>
|
||||
@ -17,7 +17,8 @@ export default {
|
||||
},
|
||||
props: {
|
||||
cards: Array,
|
||||
select: Function
|
||||
select: Function,
|
||||
text: String,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
@ -6,27 +6,27 @@
|
||||
<Card v-if="startGameCard" :card="startGameCard" @click.native="startGame"/>
|
||||
<Card v-for="p in players" v-bind:key="p" :card="getPlayerCard(p)"/>
|
||||
</div>
|
||||
<h3>Chat</h3>
|
||||
<div id="chatbox" style="max-height:200px; overflow:auto;">
|
||||
<p style="margin:1pt;" v-for="msg in messages" v-bind:key="msg">{{msg}}</p>
|
||||
<div v-if="started">
|
||||
<player/>
|
||||
</div>
|
||||
<form @submit="sendChatMessage">
|
||||
<input v-model="text"/>
|
||||
<input type="submit"/>
|
||||
</form>
|
||||
<Chooser v-if="showChooser" :cards="availableCharacters" :select="setCharacter"/>
|
||||
<chat/>
|
||||
<Chooser v-if="showChooser" text="Scegli il tuo personaggio" :cards="availableCharacters" :select="setCharacter"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Card from '@/components/Card.vue'
|
||||
import Chooser from './Chooser.vue'
|
||||
import Chat from './Chat.vue'
|
||||
import Player from './Player.vue'
|
||||
|
||||
export default {
|
||||
name: 'Lobby',
|
||||
components: {
|
||||
Card,
|
||||
Chooser,
|
||||
Chat,
|
||||
Player,
|
||||
},
|
||||
props: {
|
||||
username: String
|
||||
@ -37,7 +37,7 @@ export default {
|
||||
players: [],
|
||||
messages: [],
|
||||
availableCharacters: [],
|
||||
text: ''
|
||||
self: {},
|
||||
}),
|
||||
sockets: {
|
||||
room(data) {
|
||||
@ -46,14 +46,12 @@ export default {
|
||||
this.started = data.started
|
||||
this.players = data.players
|
||||
},
|
||||
chat_message(msg) {
|
||||
this.messages.push(msg)
|
||||
let container = this.$el.querySelector("#chatbox");
|
||||
container.scrollTop = container.scrollHeight;
|
||||
},
|
||||
characters(data){
|
||||
this.availableCharacters = JSON.parse(data)
|
||||
},
|
||||
start() {
|
||||
this.started = true;
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
startGameCard() {
|
||||
@ -72,13 +70,6 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
sendChatMessage(e) {
|
||||
if (this.text.trim().length > 0){
|
||||
this.$socket.emit('chat_message', this.text.trim())
|
||||
this.text = ''
|
||||
}
|
||||
e.preventDefault();
|
||||
},
|
||||
getPlayerCard(username) {
|
||||
return {
|
||||
name: username,
|
||||
@ -100,6 +91,8 @@ export default {
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped>
|
||||
|
||||
<style >
|
||||
#logo {
|
||||
display:none;
|
||||
}
|
||||
</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