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

Typing game #64

Closed
wants to merge 63 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
5fa96fc
1人用の簡易的なタイピングゲーム
subarunrun0812 Jun 24, 2024
1034094
表示される要素を画面中央に配置
subarunrun0812 Jun 25, 2024
087efca
残り時間を円グラフで描画
subarunrun0812 Jun 25, 2024
273c059
単語を入力し終わっても、時間がリセットされないバグを修正
subarunrun0812 Jun 25, 2024
df83124
ゲーム中に入力された文字を表示する要素を修正
subarunrun0812 Jun 25, 2024
f0f5d1c
制限時間の短縮
subarunrun0812 Jun 25, 2024
3ea5406
bug: 不正解時に時間が減らない
subarunrun0812 Jun 25, 2024
e966046
入力ミス時のペナルティ
subarunrun0812 Jun 25, 2024
098f259
player image画像を配置
subarunrun0812 Jun 25, 2024
626034f
csvファイルから単語を取得
subarunrun0812 Jun 26, 2024
13e95af
単語の追加
subarunrun0812 Jun 26, 2024
a975a58
refactor
subarunrun0812 Jun 26, 2024
1c83860
refactor
subarunrun0812 Jun 27, 2024
af3e260
bug:araiさんにdockerの設定をしてもらった
subarunrun0812 Jun 27, 2024
e348510
fix: asgi.py
subarunrun0812 Jun 27, 2024
a8a5590
feat: create new realtime app
massahito Jul 7, 2024
69830b2
fix: change app name to realtime_pong_game
massahito Jul 7, 2024
102cd8b
feat: add consumers to realtime_pong_game
massahito Jul 7, 2024
783bf19
feat: add RoomManager to manage room event
massahito Jul 7, 2024
3a0ae48
fix: make consumers work
massahito Jul 7, 2024
a812eba
feat: add Participants State Management
massahito Jul 7, 2024
452d965
feat: change room state when room is full
massahito Jul 7, 2024
472c41e
feat: add action when user is connected and disconnected
massahito Jul 10, 2024
fbf5aa0
feat: add frontend
massahito Jul 10, 2024
4c9d6ae
Merge branch 'develop' into 73-create-realtime-pong
massahito Jul 10, 2024
a064045
feat: allow to communicate with room-manager
massahito Jul 12, 2024
0bdcb5a
feat: enable PoingGame to communicate with users
massahito Jul 12, 2024
f1da543
Merge branch 'develop' into typing-game
subarunrun0812 Jul 20, 2024
5d1dc94
feat: add game -logic
massahito Jul 20, 2024
5df4524
feat: add event handler
massahito Jul 20, 2024
b9fa126
feat: enable to send message individual from room-manager
massahito Jul 20, 2024
3490a2f
feat: add async_to_sync
massahito Jul 20, 2024
c709bf1
remote用のappを作成し始め
subarunrun0812 Jul 21, 2024
2af3434
tutorial:01
subarunrun0812 Jul 21, 2024
a105efc
feat: ゲームの処理を動かせるようにする。
massahito Jul 21, 2024
3e10aac
feat: send message to client when playerscore
massahito Jul 23, 2024
baba04c
chore: change disconnect behavior
massahito Jul 24, 2024
52e9c35
feat: change file name
massahito Jul 24, 2024
4a8ca99
feat: enable go back to home when matching
massahito Jul 24, 2024
cf49e99
Merge branch 'develop' into 73-create-realtime-pong
massahito Jul 24, 2024
618fd34
fix: liter
massahito Jul 24, 2024
2cba045
fix: linter
massahito Jul 24, 2024
4017466
fix: linter
massahito Jul 24, 2024
c2f5bd5
pongディレクトリ配下でtyping_game appを作成
subarunrun0812 Jul 25, 2024
bd2280c
typing-gameのディレクトリ整理
subarunrun0812 Jul 25, 2024
061e321
インデックスビューを追加
subarunrun0812 Jul 25, 2024
1d2b247
Merge remote-tracking branch 'origin/develop' into typing-game
subarunrun0812 Jul 27, 2024
05019ac
directory移動
subarunrun0812 Jul 27, 2024
0ee00f5
fix: change variable name and add space line at the end of file.
massahito Jul 28, 2024
6c0bfeb
Merge branch 'develop' into 73-create-realtime-pong
massahito Jul 28, 2024
46e607c
fix: change file and class name
massahito Jul 28, 2024
02dced9
Merge remote-tracking branch 'origin/develop' into typing-game
subarunrun0812 Aug 1, 2024
cd5e580
feat: change enum to appropriate name
massahito Aug 1, 2024
a5c87da
fix: change enum class name
massahito Aug 1, 2024
d70ec32
fix: None check of RoomManager when client disconnect
massahito Aug 1, 2024
f63d8cf
Merge branch '73-create-realtime-pong' into typing-game
subarunrun0812 Aug 1, 2024
dab89b7
bugfix: 試合中のdisconnectに対応することで、roomに再接続した際のバグを解決しました。
massahito Aug 1, 2024
9196c3d
pongをもとにtyping-game-homeを作成中
subarunrun0812 Aug 1, 2024
f204b49
araiさんのbranchをmargeする前にcommit
subarunrun0812 Aug 1, 2024
4af1444
Merge remote-tracking branch 'origin/73-create-realtime-pong' into ty…
subarunrun0812 Aug 1, 2024
40f30a0
fix: import
subarunrun0812 Aug 1, 2024
2eade2f
同じサーバーに入れた。ゲームロジックは未実装。
subarunrun0812 Aug 1, 2024
bd8e550
SPAに対応
subarunrun0812 Aug 2, 2024
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
2 changes: 1 addition & 1 deletion .devcontainer/requirements/Django/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Django==5.0.3
gunicorn==21.2.0
idna==3.7
packaging==24.1
psycopg2==2.9.9
psycopg2-binary==2.9.9
pycparser==2.22
PyJWT==2.8.0
requests==2.32.3
Expand Down
2 changes: 1 addition & 1 deletion .devcontainer/requirements/Nginx/conf.d/default.conf
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
upstream django {
server app:8000;
server app:8000;
}

map $http_upgrade $connection_upgrade {
Expand Down
15 changes: 11 additions & 4 deletions pong/config/asgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,16 @@

from channels.routing import ProtocolTypeRouter, URLRouter
from channels.security.websocket import AllowedHostsOriginValidator
from django.urls import path
from django.urls import re_path
from django.core.asgi import get_asgi_application

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings")
django_asgi_app = application = get_asgi_application()

# import consumers here
from .consumers import SampleConsumer
from pong.middleware.auth import ChannelsJWTAuthenticationMiddleware
from realtime_pong_game.consumers import PlayerConsumer
from realtime_typing_game.consumers import TypingGmaePlayerConsumer

application = ProtocolTypeRouter(
{
Expand All @@ -28,8 +29,14 @@
ChannelsJWTAuthenticationMiddleware(
URLRouter(
[
path("test/", SampleConsumer.as_asgi()),
# path("chat/", PublicChatConsumer.as_asgi()),
re_path(
r"realtime-pong/(?P<room_name>\w+)/$",
PlayerConsumer.as_asgi(),
),
re_path(
r"realtime-typing/(?P<room_name>\w+)/$",
TypingGmaePlayerConsumer.as_asgi(),
),
]
)
)
Expand Down
2 changes: 2 additions & 0 deletions pong/config/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
"django.contrib.messages",
"django.contrib.staticfiles",
"pong",
"realtime_pong_game",
"realtime_typing_game",
]

MIDDLEWARE = [
Expand Down
21 changes: 21 additions & 0 deletions pong/pong/static/pong/components/Error.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Component } from "../core/component.js";

export class Error extends Component {

constructor(router, parameters, state) {
super(router, parameters, state);
this.findElement("button.go-home").onclick = this.onClick;
}
onClick = () => {
this.router.goNextPage("/home");
}

get html() {
return (`
<h1> Oops Error occured!</h1>
<button class="go-home">go Home</button>
`)
}
}

export default Error;
13 changes: 13 additions & 0 deletions pong/pong/static/pong/components/Home.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,20 @@ import { Component } from "../core/component.js";
export class Home extends Component {
constructor(router, params, state) {
super (router, params, state);
this.findElement("button.go-realtime-pong-button").onclick = this.goRealtimePong
this.findElement("button.go-realtime-typing-button").onclick = this.goRealtimeTyping
this.findElement("form.signout-form").onsubmit = this.handleSignout;
this.verifyJwtToken();
}

goRealtimePong = () => {
this.router.goNextPage("/pong-game-home");
}

goRealtimeTyping = () => {
this.router.goNextPage("/typing-game-home");
}

verifyJwtToken = async () => {
const responseToken = await fetch("/pong/api/v1/auth/token/verify", {
method: "POST",
Expand Down Expand Up @@ -51,6 +61,9 @@ export class Home extends Component {
get html() {
return (`
<h1> signin後の仮ページ </h1>
<button class="go-realtime-pong-button">ポングゲーム</button>
<br>
<button class="go-realtime-typing-button">タイピングゲーム</button>
<form class="signout-form">
<button type="submit">signout</button>
</form>
Expand Down
38 changes: 38 additions & 0 deletions pong/pong/static/pong/components/Load.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Component } from "../core/component.js";

export class Load extends Component {
constructor(router, params, state) {
super(router, params, state);
}

verifyAndRefreshToken = async () => {
const verifyResponse = await fetch("/pong/api/v1/auth/token/verify", {
method: "POST",
});
if (verifyResponse.ok) {
return true;
}

const refreshResponse = await fetch("/pong/api/v1/auth/token/refresh", {
method: "POST",
});
if (refreshResponse.ok) {
return true;
}
throw Error(verifyResponse.statusText);
}

onload = () => {
this.verifyAndRefreshToken().then().catch((error)=>{
//Go To Error!
this.router.goNextPage("/signin");
});
}

get html() {
return (`
`);
}
}

export default Load;
106 changes: 106 additions & 0 deletions pong/pong/static/pong/components/PongGame.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { Component } from "../core/component.js";

export class PongGame extends Component {

constructor(router, parameters, state) {
super(router, parameters, state);

//setting websocket
this.connection = this.getRouteContext("WebSocket");
this.connection.onmessage = this.onMessage;

this.canvas = this.findElement("canvas.ponggame");
this.context = this.canvas.getContext('2d');
this.grid = 15;
this.ball = {
x: this.canvas.width / 2,
y: this.canvas.height / 2,
width: this.grid,
height: this.grid
};
this.leftPaddle = {
y: this.canvas.height / 2,
size: 80
};
this.rightPaddle = {
y: this.canvas.height / 2,
size: 80
};
document.addEventListener('keydown', (e) => {
if (e.which === 87) {
this.connection.send(JSON.stringify({"sender": "player", "type": "gameKeyEvent", "contents": "keyup-go-up"}));
}
else if (e.which === 83) {
this.connection.send(JSON.stringify({"sender": "player", "type": "gameKeyEvent", "contents": "keyup-go-down"}));
}
});
document.addEventListener('keyup', (e) => {
if (e.which === 87 || e.which === 83) {
this.connection.send(JSON.stringify({"sender": "player", "type": "gameKeyEvent", "contents": "keydown"}));
}
});
requestAnimationFrame(this.loop);
}

onMessage = (event) => {
const message = JSON.parse(event.data);
switch (message.type){
case "game-objects-moved":
this.ball.x = message.contents.ball.x_position;
this.ball.y = message.contents.ball.y_position;
this.leftPaddle.y = message.contents.player1_paddle;
this.rightPaddle.y = message.contents.player2_paddle;
break;
case "player-scored":
document.getElementById("player1-name").innerHTML = message.contents.player1.name
document.getElementById("player1-score").innerHTML = message.contents.player1.score
document.getElementById("player2-name").innerHTML = message.contents.player2.name
document.getElementById("player2-score").innerHTML = message.contents.player2.score
break;
case "game-ended":
this.connection.close();
this.goNextPage("/game-home");
break;

}

}

loop = () => {
requestAnimationFrame(this.loop);
this.context.clearRect(0,0,this.canvas.width,this.canvas.height);
// draw ball
this.context.fillRect(this.ball.x, this.ball.y, this.ball.width, this.ball.height);
// draw walls
this.context.fillStyle = 'black';
this.context.fillRect(0, 0, this.canvas.width, this.grid);
this.context.fillRect(0, this.canvas.height - this.grid, this.canvas.width, this.canvas.height);
// draw player1 paddle
this.context.fillRect(0, this.leftPaddle.y - this.leftPaddle.size / 2, this.grid, this.leftPaddle.size);
// draw player2 paddle
this.context.fillRect(this.canvas.width - this.grid, this.rightPaddle.y - this.rightPaddle.size / 2, this.grid, this.rightPaddle.size);
// draw dotted line down the middle
for (let i = this.grid; i < this.canvas.height - this.grid; i += this.grid * 2) {
this.context.fillRect(this.canvas.width / 2 - this.grid / 2, i, this.grid, this.grid);
}
}

get html() {
return (`
<main class="game">
<div class="container">
<div class="player1">
<span id="player1-name" class="name">Player 1</span>
&nbsp;
<span class="score">Score: <span id="player1-score">0</span></span>
</div>
<div class="player2">
<span id="player2-name" class="name">Player 2</span>
<span class="score">Score: <span id="player2-score">0</span></span>
</div>
</div>
<canvas width="1500" height="585" class="ponggame"></canvas>
</main>
`)
}
};
61 changes: 61 additions & 0 deletions pong/pong/static/pong/components/PongGameHome.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { Component } from "../core/component.js"
import { Load } from "./Load.js";

export class PongGameHome extends Component {
constructor(router, parameters, state) {
new Load(router, parameters, state).onload()
super(router, parameters, state);
this.findElement("form.entering-room-form").onsubmit = this.submitForm;

}

onWebSocketOpen = (event) => {
this.goNextPage("/pong-game-waiting");
}

onWebSocketClose = (event) => {
this.goNextPage("/pong-game-home");
}

onMessage = (event) => {
const message = JSON.parse(event.data);
switch (message.type) {
case 'waiting-for-other-participants':
this.goNextPage("/pong-game-waiting");
break;
case 'all-participants-connected':
this.setRouteContext("participants", message.contents);
this.goNextPage("/pong-game-room");
break;
case 'all-participants-ready':
this.goNextPage("/pong-game");
break;
}

}

submitForm = (event) => {
event.preventDefault();
this.setRouteContext("roomID", event.target.elements["room-id"].value);
const socketPath = "ws://" + window.location.hostname + ":" + window.location.port + "/realtime-pong/" + event.target.elements["room-id"].value + "/";
const connection = new WebSocket(socketPath);
this.setRouteContext("WebSocket", connection);
connection.onopen = this.onWebSocketOpen;
connection.onclose = this.onWebSocketClose;
connection.onmessage = this.onMessage;
}

get html() {
return (`
<h1>Welcome To Realtime Pong !</h1>
<form class="entering-room-form">
<label for="room-id">Room ID</label>
<input id="room-id" type="number" min="1000" max="9999" required><br>
<input id="enter-room-submit" name="enter-room" type="submit" value="enter room">
</form>

`);
}
}

export default PongGameHome;
28 changes: 28 additions & 0 deletions pong/pong/static/pong/components/PongGameRoom.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import {Component} from "../core/component.js"
import { Load } from "./Load.js";

export class PongGameRoom extends Component {
constructor(router, parameters, state) {
new Load(router, parameters, state).onload()
super(router, parameters, state);
this.findElement("button.ready").onclick = this.onClick
this.connection = this.getRouteContext("WebSocket");
}

onClick = () => {
this.connection.send(JSON.stringify({"sender": "user", "type": "ready"}));
}

get html() {
return (`
<h1>game room</h1>
<h1>Room member</h1>
<h2>${(this.getRouteContext("participants"))[0]}</h2>
<h2>${(this.getRouteContext("participants"))[1]}</h2>
<label>Are you ready?</label>
<button class="ready">I'm ready.</button>
`);
}
}

export default PongGameRoom;
23 changes: 23 additions & 0 deletions pong/pong/static/pong/components/PongGameWaiting.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import {Component} from "../core/component.js"
import { Load } from "./Load.js";

export class PongGameWaiting extends Component {
constructor(router, parameters, state) {
new Load(router, parameters, state).onload()
super(router, parameters, state);
this.connection = this.getRouteContext("WebSocket");
this.findElement("button.go-back-to-game-home").onclick = this.onClick;
}

onClick = (event) => {
this.connection.close();
}

get html() {
return (`
<h1>waiting other paricipants...</h1>
<h1>Don't reload this page.</h1>
<button class="go-back-to-game-home">go back to game home</button>
`)
}
}
6 changes: 6 additions & 0 deletions pong/pong/static/pong/components/TypingGame.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { Component } from "../core/component.js";

export class TypingGame extends Component {


}
Loading
Loading