Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

result画面からの遷移(ゲームリセット)と画像の追加&ファイルアップロード実装 #26

Merged
merged 2 commits into from
Aug 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,19 @@
- [google drawings](https://docs.google.com/drawings/d/1RziwR98sGqgaBaB3Q2iUu9hP-BSzAivgzpFYMBZ3xn8/edit)
- [コード解説(wiki)](https://github.com/2d-rpg/dixitOnline/wiki/%E3%82%B3%E3%83%BC%E3%83%89%E8%A7%A3%E8%AA%AC)

- 7/26(Sun) :
- 8/2(Sun) :
- UIデザイン
- progressについて
- アニメーション

- 7/31(Fri) :
- hand_selection分離([PR #24](https://github.com/2d-rpg/dixitOnline/pull/24))
- progress修正([PR #25](https://github.com/2d-rpg/dixitOnline/pull/25), [PR #27](https://github.com/2d-rpg/dixitOnline/pull/27))
- ファイルのアップロード実装
- 画像の追加
- result画面後の遷移([PR #26](https://github.com/2d-rpg/dixitOnline/pull/26))

- 7/26(Sun) :
- cookieを用いた復帰実装([PR #23](https://github.com/2d-rpg/dixitOnline/pull/23))

- 7/24(Fri) :
- show_answer ~ calc_result ~ hand_selection までのループ実装([PR #20](https://github.com/2d-rpg/dixitOnline/pull/20))
Expand Down
11 changes: 8 additions & 3 deletions backend/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ const others_hand_selection = require('./src/scripts/stage/others_hand_selection
const field_selection = require('./src/scripts/stage/field_selection');
const calc_score = require('./src/scripts/stage/calc_score');
const round_end = require('./src/scripts/stage/round_end');
const restart = require('./src/scripts/stage/restart');

const disconnect = require('./src/scripts/stage/disconnect');
// const fs = require('fs');
const socketIO = require('socket.io');
// const app = express();
const server = http.Server();
Expand All @@ -45,8 +45,10 @@ io.on('connection', (socket) => {
socket.on('field_selection', (data) => field_selection.do(socket, data.index, game));
// クライアントからfield_selecitonがemitされた時
socket.on('calc_score', () => calc_score.do(socket, game));
// クライアントからfield_selecitonがemitされた時
// クライアントからround_endがemitされた時
socket.on('round_end', () => round_end.do(socket, game));
// クライアントからrestartがemitされた時
socket.on('restart', () => restart.do(io, socket, game));

// 通信終了時(ブラウザを閉じる/リロード/ページ移動)
// TODO: つまりリロードすると復帰不可
Expand All @@ -60,11 +62,13 @@ io.on('connection', (socket) => {
}
io.sockets.emit('chat_send_from_server', {name: name, value : data.value});
});
// 画像のアップロード
socket.on('upload', (data) => utils.uploadFile(data.filename, data.image));
});

setInterval(() => {
// 全プレイヤーがステージ移行可能ならば移行する
if (game.isAllDone()) { // 全てのプレイヤーが次のステージにいける状態
if (game.isAllDone() || game.isFinished()) { // 全てのプレイヤーが次のステージにいける状態
game.nextStage(io);
}
}, 1000/30);
Expand All @@ -82,6 +86,7 @@ setInterval(() => {
// response.sendFile(path.join(__dirname, '/src/index.html'));
// });


server.listen(4001, () => {
utils.log('Starting server on port 4001');
});
71 changes: 48 additions & 23 deletions backend/src/scripts/game.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const Discard = require('./discard');
const Field = require('./field');
const Card = require('./card');
const utils = require('./utils');
const fs = require('fs');

// private static property
// 外からのアクセス不可
Expand Down Expand Up @@ -34,8 +35,10 @@ class Game {
constructor() {
/** 山札(stock) */
this.stock = new Stock();
for (var i = 0; i < Game.CARD_NUM; i++) {
this.stock.push(new Card(utils.randomSample(18)));
const files = fs.readdirSync('../frontend/public/images/');
utils.shuffle(files);
for (var i = 0; i < files.length; i++) {
this.stock.push(new Card(files[i]));
}
/** このゲームに参加しているプレイヤー */
this.players = new Array(Game.PLAYER_NUM).fill(null);
Expand All @@ -56,6 +59,20 @@ class Game {
this.answers = [];
}

reset() {
this.stock = new Stock();
const files = fs.readdirSync('../frontend/public/images/');
utils.shuffle(files);
for (var i = 0; i < files.length; i++) {
this.stock.push(new Card(files[i]));
}
this.discard = new Discard();
this.field = new Field();
this.stage = status[0];
this.stageIndex = 0;
this.master = -1;
}

/** プレイヤーの追加 */
addPlayer(data, socket) {
let player = new Player({socketId: socket.id, username: data.username});
Expand Down Expand Up @@ -84,34 +101,39 @@ class Game {
this.stageIndex = 7; // result画面へ
}
}
if(this.stageIndex == 2){ // hand_selection
// 更新後
if (this.stageIndex == 2) { // hand_selection
this.updateMaster(); // 語り部更新
this.fieldToDiscard();
if(this.stock._array.length < this.players.length) {
if(this.stock._array.length < this.getLength()) {
this.discardToStock();
}
this.players.forEach(player => player.draw(this.stock));
this.resetAnswers();
}
if(this.stageIndex == 4){// fieldの更新
if (this.stageIndex === 4) {// fieldの更新
this.handToField();
}

this.stageIndex = this.stageIndex % 8;
this.stage = status[this.stageIndex];
this.players.forEach(player => { // 全プレイヤーの状態リセット
player.reset(); // 状態リセット
});
this.players.forEach(player => { // ステージ移行
// ディープコピー (何段階もコピーするのでObject.createは不可)
// TODO: もっといい方法あるかも
var others = new Array();
this.players.forEach(other => {
if (player != other) {
others.push(other);
}
if (this.stageIndex !== 0) {
this.players.forEach(player => { // 全プレイヤーの状態リセット
player.reset(); // 状態リセット
});
io.to(player.socketId).emit(this.stage, {others : others, player : player, game : this}); // ステージ移行
});
this.players.forEach(player => { // ステージ移行
// ディープコピー (何段階もコピーするのでObject.createは不可)
// TODO: もっといい方法あるかも
var others = new Array();
this.players.forEach(other => {
if (player != other) {
others.push(other);
}
});
io.to(player.socketId).emit(this.stage, {others : others, player : player, game : this}); // ステージ移行
});
} else {
this.reset();
}
utils.log('Move to stage [' + this.stage + ']');
}

Expand All @@ -122,6 +144,10 @@ class Game {
.filter(player => player.isDone()).length === 3;
}

isFinished() {
return this.players.filter(player => player == null).length === 3 && this.stageIndex === 7;
}

/** 語り部の更新 */
updateMaster() {
this.master = (this.master + 1) % 3; // 0 ~ 2 でループ
Expand Down Expand Up @@ -165,10 +191,9 @@ class Game {

/** socket idによるプレイヤー削除 */
deletePlayer(id) {
this.players.filter(player => player != null).forEach(player => {
if (player.socketId == id) {
var index = this.players.indexOf(player);
this.players.splice(index, 1);
this.players.forEach((player, index) => {
if (player != null && player.socketId == id) {
this.players[index] = null;
this.currentNum -= 1;
}
});
Expand Down
2 changes: 1 addition & 1 deletion backend/src/scripts/stage/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class Init {
static do(config, io, socket, game) {
io.sockets.emit('update_number_of_player', { num: game.getLength() });
console.log(socket.handshake.query);
if (game.getLength() < 3) { // プレイヤー人数が3人未満のとき
if (game.getLength() < 3 && game.stageIndex === 0) { // プレイヤー人数が3人未満のとき
utils.logWithStage('init', 'socket id: [' + socket.id + '] was added');
} else { // 3人以上場合
// クエリ(cookie)を取得し,ゲームへの復帰を行う
Expand Down
19 changes: 19 additions & 0 deletions backend/src/scripts/stage/restart.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* restart
*/

const utils = require('../utils');

class Restart {

constructor() {}

static do(io, socket, game) {
game.deletePlayer(socket.id);
io.sockets.emit('update_number_of_player', { num: game.getLength() });
console.log('delete');
socket.emit('restart');
}
}

module.exports = Restart;
4 changes: 3 additions & 1 deletion backend/src/scripts/stage/wait.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
// init
/**
* wait
*/

const utils = require('../utils');

Expand Down
52 changes: 29 additions & 23 deletions backend/src/scripts/utils.js
Original file line number Diff line number Diff line change
@@ -1,37 +1,43 @@
'use srtict';
const fs = require('fs');

/**
* utils
*/

/** Logger for debug */
exports.log = function(message) {
console.log('[debug] ' + message);
}
/** Logger for debug */
exports.log = (message) => {
console.log('[debug] ' + message);
};

/** Stage logger for debug */
exports.logWithStage = function(stage, message) {
console.log('[debug] [Stage: ' + stage + '] ' + message);
}
/** Stage logger for debug */
exports.logWithStage = (stage, message) => {
console.log('[debug] [Stage: ' + stage + '] ' + message);
};

/** Uniform random sample image */
exports.randomSample = function(max) {
var rand = Math.floor(Math.random() * max); // 0 to max-1
// TODO: 現在3枚しかないのでこうしているが,大量のデータになると要修正
if (rand < max / 3.0) {
return "akira_with_Ginkakuji";
} else if (rand < max * 2.0 / 3.0) {
return "akira_with_hood_and_Ginkakuji";
} else {
return "unko";
}
}
/** Uniform random sample image */
exports.randomSample = () => {
const files = fs.readdirSync('../frontend/public/images/')
var rand = Math.floor(Math.random() * files.length); // 0 to files.length-1
return files[rand];
};

/** Fisher-Yates shuffle */
exports.shuffle = ([...array]) => {
/** Fisher-Yates shuffle */
exports.shuffle = ([...array]) => {
for (let i = array.length - 1; i >= 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
return array;
}
};


exports.uploadFile = (filename, image) => {
var data = image.replace(/^data:image\/\w+;base64,/, "");
var buf = new Buffer.from(data, 'base64');
fs.writeFile('../frontend/public/images/' + filename, buf, (err) => {
if (err) {
console.log('err');
}
});
};
1 change: 1 addition & 0 deletions backend/unko.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/public/images/Characters
Binary file not shown.
Binary file added frontend/public/images/Dixit
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added frontend/public/images/Marie Cardouat
Binary file not shown.
Binary file added frontend/public/images/Rebecca Dautremer
Binary file not shown.
Binary file added frontend/public/images/c+8MLLDO.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file added frontend/public/images/slowlydrifting
Binary file not shown.
Binary file added frontend/public/images/solitude
Binary file not shown.
Binary file added frontend/public/images/umbrella
Binary file not shown.
Binary file removed frontend/public/images/unko.jpg
Binary file not shown.
5 changes: 2 additions & 3 deletions frontend/src/App.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import React, {useState, useEffect} from 'react';
import React, {useState} from 'react';
// import logo from './logo.svg';
import './App.css';
import 'bootstrap/dist/css/bootstrap.min.css';
import PlayerCounter from './scripts/playerCounter';
import Progress from './scripts/progress';
import Chat from './scripts/chat';
import Init from './scripts/stage/init';
import Entry from './scripts/stage/entry';
import Upload from './scripts/stage/upload';
import Start from './scripts/stage/start';
import HandSelection from './scripts/stage/hand_selection';
// import socketIOClient from "socket.io-client";
Expand All @@ -17,6 +15,7 @@ import FieldSelection from './scripts/stage/field_selection';
import ShowAnswer from './scripts/stage/show_answer';
import ShowScore from './scripts/stage/show_score';
import Result from './scripts/stage/result';
import Upload from './scripts/upload';
const ENDPOINT = "http://127.0.0.1:4001/";
// const socket = socketIOClient(ENDPOINT);
const socket = io(ENDPOINT, {
Expand Down
1 change: 1 addition & 0 deletions frontend/src/scripts/stage/entry.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export default function Entry(props) {
props.socket.on('show_answer', () => setShow(false));
props.socket.on('show_score', () => setShow(false));
props.socket.on('result', () => setShow(false));
props.socket.on('restart', () => setShow(true));
}, [ props.socket ]);

/** エントリーフォーム入力時の動作 */
Expand Down
15 changes: 9 additions & 6 deletions frontend/src/scripts/stage/field_selection.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

import React, { useEffect, useState } from 'react';

const WIDTH = '100';
const HEIGHT = '200';

export default function FieldSelection(props) {

/** フィールドを表示するか否か */
Expand All @@ -22,18 +25,18 @@ export default function FieldSelection(props) {
setFieldButtons(
data.game.field.cards.map((card, index) => {
var id = 'field' + index;
var hand_src = "../images/" + card.filename + ".jpg";
var hand_src = "../images/" + card.filename;
return (
<button id={ id } type='button' onClick={ () => others_field_select(props.socket, data, index)}>
<img width='100' height='100' src={ hand_src } alt={ card.filename }></img>
<img width={ WIDTH } height={ HEIGHT } src={ hand_src } alt={ card.filename }></img>
</button>);
})
);
}else{ // 語り部の場合
setFieldButtons(
data.game.field.cards.map((card) => {
var hand_src = "../images/" + card.filename + ".jpg";
return (<img width='100' height='100' src={ hand_src } alt={ card.filename }></img>);
var hand_src = "../images/" + card.filename;
return (<img width={ WIDTH } height={ HEIGHT } src={ hand_src } alt={ card.filename }></img>);
})
);
props.socket.emit('wait');
Expand All @@ -42,7 +45,7 @@ export default function FieldSelection(props) {
/** 語り部以外のプレイヤーがフィールド上のカードを選んだときの動作 */
const others_field_select = (socket,data,index) => {
setShowField(false);
setSrc("../images/" + data.game.field.cards[index].filename + ".jpg");
setSrc("../images/" + data.game.field.cards[index].filename);
setShowSelected(true);
socket.emit('field_selection', {index : index});
}
Expand All @@ -62,7 +65,7 @@ export default function FieldSelection(props) {
<div id="field" style={ {display: showfield ? 'inline' : 'none'} }>{ field_buttons }</div>
<div className="form-inline" id="selected_field_card" style={{display: showselected ? 'inline' : 'none'}}>
あなたが選んだカード:
<img id="selected_field_card" width="200" height="200" src={src} alt="フィールドから選んだカード"/>
<img id="selected_field_card" width={ WIDTH } height={ HEIGHT } src={ src } alt="フィールドから選んだカード"/>
</div>
</div>
);
Expand Down
Loading