Skip to content

Commit 9d5b1ed

Browse files
committed
single player
1 parent 78680ad commit 9d5b1ed

File tree

9 files changed

+408
-8
lines changed

9 files changed

+408
-8
lines changed

API/API/urls.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
path('', include('Apps.Home.urls')),
2727
path('profile/', include('Apps.Profile.urls')),
2828
path('social/', include('Apps.SocialMedia.urls')),
29-
path('game/', include('Apps.Game.urls')),
29+
path('', include('Apps.Game.urls')),
3030
path('matchmaking/', include('Apps.Matchmaking.urls')),
3131
path('', include('Apps.Tournament.urls'))
3232
]

API/Apps/Game/urls.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@
44
from . import views
55

66
urlpatterns = [
7-
path('<uuid:game_id>/',views.index,name='index'),
7+
path('game/<uuid:game_id>/', views.index, name='index'),
8+
path('play/', views.offline_game, name='offline_game'),
89
]

API/Apps/Game/views.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,8 @@
22

33

44
def index(request, game_id):
5-
return render(request, 'Game/Game.html')
5+
return render(request, 'Game/Game.html')
6+
7+
8+
def offline_game(request):
9+
return render(request, 'Game/OfflineGame.html')

API/static/scripts/login.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,17 @@ import Spinner from "../components/spinner.js";
44
import {request} from "./Request.js";
55

66
document.getElementById('ecole-login-button').addEventListener('click', async () => {
7-
const response = await request(`direct-42-login-page/`, {
7+
const response = await request(`auth/direct-42-login-page/`, {
88
method: 'POST',
99
})
10+
console.log(response)
1011
if (response.oauth_url) {
1112
window.location.href = response.oauth_url
1213
}
1314
})
1415

1516
async function handle42APICallback(code) {
16-
const response = await request(`login-with-42/${code}/`, {
17+
const response = await request(`auth/login-with-42/${code}/`, {
1718
method: "POST",
1819
})
1920
if (response) {
@@ -32,7 +33,7 @@ async function loginForm(event)
3233
username: username,
3334
password: password
3435
};
35-
const endpoint = `send-email-for-verification/`;
36+
const endpoint = `auth/send-email-for-verification/`;
3637
const loginButton = document.getElementById('login-button');
3738
loginButton.disabled = true;
3839
const spinner = new Spinner({isVisible:true,className:"login-button-loader"}, loginButton);

API/static/scripts/offline-game.js

+207
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
import {BASE_URL, loadPage} from "./spa.js";
2+
3+
const canvas = document.getElementById('pongCanvas');
4+
const ctx = canvas.getContext('2d');
5+
6+
// Set initial positions for paddles and ball
7+
let ballX = canvas.width / 2;
8+
let ballY = canvas.height / 2;
9+
let ballSpeedX = 3;
10+
let ballSpeedY = 3;
11+
12+
const paddleHeight = 200;
13+
const paddleWidth = 10;
14+
const paddleSpeed = 8;
15+
16+
let player1Y = canvas.height / 2 - paddleHeight / 2;
17+
let player2Y = canvas.height / 2 - paddleHeight / 2;
18+
19+
let pause = false
20+
let finish = false
21+
let firstStart = true
22+
23+
let playerOneScore = 0
24+
let playerTwoScore = 0
25+
26+
function drawRect(x, y, width, height, color) {
27+
ctx.fillStyle = color;
28+
ctx.fillRect(x, y, width, height);
29+
}
30+
31+
function drawCircle(x, y, radius, color) {
32+
ctx.fillStyle = color;
33+
ctx.beginPath();
34+
ctx.arc(x, y, radius, 0, Math.PI * 2, true);
35+
ctx.fill();
36+
}
37+
38+
function pauseGame() {
39+
pause = true
40+
setTimeout(function () {
41+
pause = false
42+
}, 3000)
43+
}
44+
45+
function draw() {
46+
// clear the canvas
47+
drawRect(0, 0, canvas.width, canvas.height, 'black');
48+
// draw net
49+
drawRect(canvas.width / 2 - 1, 0, 2, 1000, 'gray');
50+
// draw paddles
51+
drawRect(0, player1Y, paddleWidth, paddleHeight, 'white');
52+
drawRect(canvas.width - paddleWidth, player2Y, paddleWidth, paddleHeight, 'white');
53+
// draw ball
54+
drawCircle(ballX, ballY, 15, 'white');
55+
if (firstStart) {
56+
firstStart = false
57+
printCountdown()
58+
pauseGame()
59+
}
60+
}
61+
62+
function update() {
63+
ballX += ballSpeedX;
64+
ballY += ballSpeedY;
65+
66+
// ball collision with top and bottom walls
67+
if (ballY < 0 || ballY > canvas.height) {
68+
ballSpeedY = -ballSpeedY;
69+
}
70+
71+
// ball collision with paddles
72+
if (
73+
(ballX <= paddleWidth && ballY > player1Y && ballY < player1Y + paddleHeight) ||
74+
(ballX >= canvas.width - paddleWidth && ballY > player2Y && ballY < player2Y + paddleHeight)
75+
) {
76+
ballSpeedX = -ballSpeedX;
77+
}
78+
79+
// ball out of bounds, reset position
80+
if (ballX < 0 || ballX > canvas.width) {
81+
setCurrentPoints()
82+
ballX = canvas.width / 2;
83+
ballY = canvas.height / 2;
84+
ballSpeedX = -ballSpeedX;
85+
player1Y = canvas.height / 2 - paddleHeight / 2;
86+
player2Y = canvas.height / 2 - paddleHeight / 2;
87+
if (!finish) {
88+
printCountdown()
89+
pauseGame()
90+
}
91+
}
92+
}
93+
94+
function gameLoop() {
95+
if (!pause && !finish) {
96+
update();
97+
draw();
98+
}
99+
requestAnimationFrame(gameLoop);
100+
}
101+
102+
gameLoop();
103+
104+
function setCurrentPoints() {
105+
if (ballX < 0) {
106+
playerTwoScore++
107+
108+
} else {
109+
playerOneScore++
110+
}
111+
112+
let points = document.getElementById("game-points");
113+
114+
points.innerText = `${playerOneScore} - ${playerTwoScore}`;
115+
116+
if (playerOneScore == 5) {
117+
printWinner("Player 1")
118+
} else if (playerTwoScore == 5) {
119+
printWinner("Player 2")
120+
}
121+
122+
}
123+
124+
// handle player controls
125+
window.addEventListener('keydown', function (event) {
126+
if (!pause) {
127+
switch (event.key) {
128+
case 'w':
129+
if (player1Y > 0) { // Check if paddle 1 is not at the top edge
130+
player1Y -= paddleSpeed;
131+
}
132+
break;
133+
case 's':
134+
if (player1Y < canvas.height - paddleHeight) { // Check if paddle 1 is not at the bottom edge
135+
player1Y += paddleSpeed;
136+
}
137+
break;
138+
case 'ArrowUp':
139+
if (player2Y > 0) { // Check if paddle 2 is not at the top edge
140+
player2Y -= paddleSpeed;
141+
}
142+
break;
143+
case 'ArrowDown':
144+
if (player2Y < canvas.height - paddleHeight) { // Check if paddle 2 is not at the bottom edge
145+
player2Y += paddleSpeed;
146+
}
147+
break;
148+
}
149+
}
150+
151+
});
152+
153+
154+
function printCountdown() {
155+
let countdown = 3;
156+
let element = document.createElement("div");
157+
element.id = "game-message-wrapper";
158+
let textElement = document.createElement("h1");
159+
textElement.id = "countdown";
160+
textElement.innerText = countdown.toString();
161+
element.appendChild(textElement);
162+
document.body.appendChild(element);
163+
let interval = setInterval(() => {
164+
countdown -= 1;
165+
textElement.classList.add("fade-in");
166+
textElement.innerText = countdown.toString();
167+
if (countdown === 0) {
168+
clearInterval(interval);
169+
element.remove();
170+
}
171+
}, 1000);
172+
}
173+
174+
function printWinner(winner) {
175+
finish = true
176+
let winnerHTML = `
177+
<div class="winner-wrapper">
178+
<div class="winner-image-wrapper">
179+
<img src="https://picsum.photos/seed/picsum/200/300" alt="" />
180+
</div>
181+
<div class="info-area">
182+
<h2>Winner is ${winner}</h2>
183+
<h1 id="play-again" class="play-again">Play Again</h1>
184+
</div>
185+
</div>
186+
`
187+
let element = document.createElement("div");
188+
element.id = "game-message-wrapper";
189+
element.innerHTML = winnerHTML;
190+
document.body.appendChild(element);
191+
const playAgain = document.getElementById('play-again')
192+
playAgain.addEventListener('click', () => {
193+
element.remove()
194+
resStartGame()
195+
})
196+
}
197+
198+
199+
function resStartGame() {
200+
printCountdown()
201+
playerOneScore = 0
202+
playerTwoScore = 0
203+
let points = document.getElementById("game-points");
204+
points.innerText = `${playerOneScore} - ${playerTwoScore}`;
205+
pauseGame()
206+
finish = false
207+
}

API/static/scripts/spa.js

+100
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,57 @@ const routes = new Map([
522522
</div>
523523
`
524524
}],
525+
['game', {
526+
auth_required: true,
527+
url: ['/play/'],
528+
html: `
529+
530+
<div
531+
class="background container-fluid social-background"
532+
style="padding: 0"
533+
>
534+
<div class="game-container">
535+
536+
<div class="game-wrapper">
537+
<div class="game-data-wrapper">
538+
539+
<div class="game-player-data" id="player-one">
540+
<div class="player-image">
541+
<img src="https://picsum.photos/seed/picsum/200/300" alt="Player 2">
542+
</div>
543+
<div class="player-description" id="player-one-details">
544+
<span class="player-name">Player 1</span>
545+
<span class="player-points">Points?</span>
546+
</div>
547+
</div>
548+
<div class="game-points">
549+
<h1 id="game-points" class="skeleton">
550+
551+
</h1>
552+
</div>
553+
<div class="game-player-data" id="player-two">
554+
<div class="player-image">
555+
<img src="https://picsum.photos/seed/picsum/200/300" alt="Player 2">
556+
</div>
557+
<div class="player-description" id="player-two-details">
558+
<span class="player-name">Player 2</span>
559+
<span class="player-name">Points?</span>
560+
</div>
561+
</div>
562+
563+
</div>
564+
<div class="" id="canvas-wrapper">
565+
<div class="spectators-wrapper" id="spectators-wrapper">
566+
</div>
567+
<div class="canvas-wrapper">
568+
<canvas class="canvas-class" id="pongCanvas" width="1368" height="600"></canvas>
569+
</div>
570+
</div>
571+
</div>
572+
</div>
573+
</div>
574+
`
575+
}],
525576
['error', {
526577
auth_required: false,
527578
url: ['/error/'],
@@ -654,6 +705,54 @@ const routes = new Map([
654705
</div>
655706
`
656707

708+
}],
709+
['offline-game', {
710+
auth_required: true,
711+
url: ['/play/'],
712+
html: `
713+
<div
714+
class="background container-fluid social-background"
715+
style="padding: 0"
716+
>
717+
<div class="game-container">
718+
719+
<div class="game-wrapper">
720+
<div class="game-data-wrapper">
721+
722+
<div class="game-player-data" id="player-one">
723+
<div class="player-image">
724+
<img src="https://picsum.photos/seed/picsum/200/300" alt="Player 2">
725+
</div>
726+
<div class="player-description" id="player-one-details">
727+
<span class="player-name">Player 1</span>
728+
</div>
729+
</div>
730+
<div class="game-points">
731+
<h1 id="game-points" class="skeleton">
732+
0 - 0
733+
</h1>
734+
</div>
735+
<div class="game-player-data" id="player-two">
736+
<div class="player-image">
737+
<img src="https://picsum.photos/seed/picsum/200/300" alt="Player 2">
738+
</div>
739+
<div class="player-description" id="player-two-details">
740+
<span class="player-name">Player 2</span>
741+
</div>
742+
</div>
743+
744+
</div>
745+
<div class="" id="canvas-wrapper">
746+
<div class="spectators-wrapper" id="spectators-wrapper">
747+
</div>
748+
<div class="canvas-wrapper">
749+
<canvas class="canvas-class" id="pongCanvas" width="1368" height="600"></canvas>
750+
</div>
751+
</div>
752+
</div>
753+
</div>
754+
</div>
755+
`
657756
}]
658757
]);
659758
const routeToFile = [
@@ -663,6 +762,7 @@ const routeToFile = [
663762
[['/social/', '/social/\\w+/g'], 'social'],
664763
[['/home/'], 'home'],
665764
[['/verification/'], 'verification'],
765+
[['/play/'], 'offline-game'],
666766
[[/game\/([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})/], 'game'],
667767
[['/matchmaking/'], 'matchmaking'],
668768
[['/tournaments/'], 'tournaments'],

API/static/scripts/verification.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ document.getElementById("verify").addEventListener("click", async function() {
4949

5050
async function postVerificationCode(value) {
5151
try {
52-
let response = await request(`email-verification/`, {
52+
let response = await request(`auth/email-verification/`, {
5353
method: 'POST',
5454
headers: {
5555
'Content-Type': 'application/json',

0 commit comments

Comments
 (0)