Vive le rouge !
This commit is contained in:
@@ -82,7 +82,7 @@ export class GameSession {
|
|||||||
else if (input === en.InputEnum.down) {
|
else if (input === en.InputEnum.down) {
|
||||||
client.racket.dir.y = 1;
|
client.racket.dir.y = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input !== en.InputEnum.noInput) {
|
if (input !== en.InputEnum.noInput) {
|
||||||
client.racket.moveAndCollide(delta, [gc.wallTop, gc.wallBottom]);
|
client.racket.moveAndCollide(delta, [gc.wallTop, gc.wallBottom]);
|
||||||
}
|
}
|
||||||
@@ -220,7 +220,7 @@ export class GameSession {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
private async _matchEnd(winner: en.PlayerSide, forfeit_flag: boolean = false)
|
private async _matchEnd(winner: en.PlayerSide, forfeit_flag: boolean = false)
|
||||||
{
|
{
|
||||||
this.matchEnded = true;
|
this.matchEnded = true;
|
||||||
let eventEnd: ev.EventMatchEnd;
|
let eventEnd: ev.EventMatchEnd;
|
||||||
@@ -232,7 +232,6 @@ export class GameSession {
|
|||||||
client.socket.send(JSON.stringify(eventEnd));
|
client.socket.send(JSON.stringify(eventEnd));
|
||||||
});
|
});
|
||||||
|
|
||||||
/* // WIP nest , send match result
|
|
||||||
const gc = this.components;
|
const gc = this.components;
|
||||||
await fetch(c.addressBackEnd + "/game/matchEnd",
|
await fetch(c.addressBackEnd + "/game/matchEnd",
|
||||||
{
|
{
|
||||||
@@ -245,7 +244,7 @@ export class GameSession {
|
|||||||
scoreLeft: gc.scoreLeft,
|
scoreLeft: gc.scoreLeft,
|
||||||
scoreRight: gc.scoreRight,
|
scoreRight: gc.scoreRight,
|
||||||
})
|
})
|
||||||
}); */
|
});
|
||||||
|
|
||||||
// logs
|
// logs
|
||||||
if (winner === en.PlayerSide.left) {
|
if (winner === en.PlayerSide.left) {
|
||||||
|
|||||||
@@ -9,4 +9,4 @@ export const fixedDeltaTime = serverGameLoopIntervalMS/1000; // second
|
|||||||
export const playersUpdateIntervalMS = 1000/30; // millisecond
|
export const playersUpdateIntervalMS = 1000/30; // millisecond
|
||||||
export const spectatorsUpdateIntervalMS = 1000/30; // millisecond
|
export const spectatorsUpdateIntervalMS = 1000/30; // millisecond
|
||||||
|
|
||||||
export const addressBackEnd = "http://backend_dev:3000";
|
export const addressBackEnd = "http://backend_dev:3000/api/v2";
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ async function clientAnnounceListener(this: WebSocket, data: string)
|
|||||||
if (msg.role === en.ClientRole.player)
|
if (msg.role === en.ClientRole.player)
|
||||||
{
|
{
|
||||||
const announce: ev.ClientAnnouncePlayer = <ev.ClientAnnouncePlayer>msg;
|
const announce: ev.ClientAnnouncePlayer = <ev.ClientAnnouncePlayer>msg;
|
||||||
|
|
||||||
// WIP nest, fetch token validation
|
// WIP nest, fetch token validation
|
||||||
const body = {
|
const body = {
|
||||||
playerOneUsername: announce.username,
|
playerOneUsername: announce.username,
|
||||||
@@ -78,7 +78,7 @@ async function clientAnnounceListener(this: WebSocket, data: string)
|
|||||||
if (announce.privateMatch) {
|
if (announce.privateMatch) {
|
||||||
body.playerTwoUsername = announce.playerTwoUsername;
|
body.playerTwoUsername = announce.playerTwoUsername;
|
||||||
}
|
}
|
||||||
const response = await fetch(c.addressBackEnd + "/game/validateToken",
|
const response = await fetch(c.addressBackEnd + "/game/gameserver/validate",
|
||||||
{
|
{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
@@ -163,12 +163,12 @@ function publicMatchmaking(player: ClientPlayer)
|
|||||||
|
|
||||||
|
|
||||||
function privateMatchmaking(player: ClientPlayer)
|
function privateMatchmaking(player: ClientPlayer)
|
||||||
{
|
{
|
||||||
const minPlayersNumber = 2;
|
const minPlayersNumber = 2;
|
||||||
const maxPlayersNumber = 2;
|
const maxPlayersNumber = 2;
|
||||||
privateMatchmakingMap.set(player.id, player);
|
privateMatchmakingMap.set(player.id, player);
|
||||||
const matchOptions = player.matchOptions;
|
const matchOptions = player.matchOptions;
|
||||||
|
|
||||||
const token = player.token;
|
const token = player.token;
|
||||||
const compatiblePlayers: ClientPlayer[] = [];
|
const compatiblePlayers: ClientPlayer[] = [];
|
||||||
for (const [id, client] of privateMatchmakingMap)
|
for (const [id, client] of privateMatchmakingMap)
|
||||||
@@ -243,17 +243,18 @@ async function playerReadyConfirmationListener(this: WebSocket, data: string)
|
|||||||
{
|
{
|
||||||
// WIP nest , send gameSession.id
|
// WIP nest , send gameSession.id
|
||||||
const gameSessionPlayersIterator = gameSession.playersMap.values();
|
const gameSessionPlayersIterator = gameSession.playersMap.values();
|
||||||
const response = await fetch(c.addressBackEnd + "/game/newGameSession",
|
const response = await fetch(c.addressBackEnd + "/game/gameserver/creategame",
|
||||||
{
|
{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
id: gameSession.id,
|
gameServerIdOfTheMatch : gameSession.id,
|
||||||
gameOptions: gameSession.matchOptions,
|
gameOptions: gameSession.matchOptions,
|
||||||
playerOneUsername: (<ClientPlayer>gameSessionPlayersIterator.next().value).username,
|
playerOneUsername: (<ClientPlayer>gameSessionPlayersIterator.next().value).username,
|
||||||
playerTwoUsername: (<ClientPlayer>gameSessionPlayersIterator.next().value).username,
|
playerTwoUsername: (<ClientPlayer>gameSessionPlayersIterator.next().value).username,
|
||||||
|
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
if (!response.ok)
|
if (!response.ok)
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { IsBoolean, IsNotEmpty, IsNumber, IsString } from "class-validator";
|
||||||
|
|
||||||
|
export class CreateGameDto {
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
gameServerIdOfTheMatch : string
|
||||||
|
@IsNumber()
|
||||||
|
@IsNotEmpty()
|
||||||
|
gameOptions: number
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
playerOneUsername : string
|
||||||
|
@IsString()
|
||||||
|
playerTwoUsername : string
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { IsBoolean, IsNotEmpty, IsNumber, IsString } from "class-validator";
|
||||||
|
|
||||||
|
export class UpdateGameDto {
|
||||||
|
@IsNumber()
|
||||||
|
@IsNotEmpty()
|
||||||
|
playerOneUsernameResult : number
|
||||||
|
@IsNumber()
|
||||||
|
@IsNotEmpty()
|
||||||
|
playerTwoUsernameResult : number
|
||||||
|
@IsBoolean()
|
||||||
|
isMatchIsFinished : boolean
|
||||||
|
}
|
||||||
@@ -11,15 +11,15 @@ export class Game {
|
|||||||
@Column()
|
@Column()
|
||||||
playerTwoUsername: string
|
playerTwoUsername: string
|
||||||
|
|
||||||
@Column()
|
@Column({default : 0, nullable : true})
|
||||||
playerOneUsernameResult : number
|
playerOneUsernameResult : number
|
||||||
|
|
||||||
@Column()
|
@Column({default : 0, nullable : true})
|
||||||
playerTwoUsernameResult : number
|
playerTwoUsernameResult : number
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
gameServerIdOfTheMatch: string
|
gameServerIdOfTheMatch: string
|
||||||
|
|
||||||
@Column({default: false}) //éric pourra trouver un meilleur mot : ongoing ?
|
@Column({default: false, nullable : true}) //éric pourra trouver un meilleur mot : ongoing ?
|
||||||
isMatchIsFinished: boolean
|
isMatchIsFinished: boolean
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import { Body, Controller, Get, HttpException, HttpStatus, Post, Req, UseGuards } from '@nestjs/common';
|
import { Body, Controller, Get, HttpException, HttpStatus, Post, Req, UseGuards } from '@nestjs/common';
|
||||||
|
import { Console } from 'console';
|
||||||
import { request } from 'http';
|
import { request } from 'http';
|
||||||
import { use } from 'passport';
|
import { use } from 'passport';
|
||||||
import { AuthenticateGuard, TwoFactorGuard } from 'src/auth/42/guards/42guards';
|
import { AuthenticateGuard, TwoFactorGuard } from 'src/auth/42/guards/42guards';
|
||||||
import { User } from 'src/users/entities/user.entity';
|
import { User } from 'src/users/entities/user.entity';
|
||||||
import { UsersService } from 'src/users/users.service';
|
import { UsersService } from 'src/users/users.service';
|
||||||
|
import { CreateGameDto } from './dto/createGame.dto';
|
||||||
import { GrantTicketDto } from './dto/grantTicket.dto';
|
import { GrantTicketDto } from './dto/grantTicket.dto';
|
||||||
import { ValidateTicketDto } from './dto/validateTicket.dto';
|
import { ValidateTicketDto } from './dto/validateTicket.dto';
|
||||||
import { TokenGame } from './entity/tokenGame.entity';
|
import { TokenGame } from './entity/tokenGame.entity';
|
||||||
@@ -21,8 +23,8 @@ export class GameController {
|
|||||||
const user : User = req.user
|
const user : User = req.user
|
||||||
if (grantTicketDto.playerOneUsername != user.username)
|
if (grantTicketDto.playerOneUsername != user.username)
|
||||||
return new HttpException('You can\'t request a game for another person.', 403 )
|
return new HttpException('You can\'t request a game for another person.', 403 )
|
||||||
else if (user.status !== "connected")
|
// else if (user.status !== "connected")
|
||||||
return new HttpException('You must not be in game...', HttpStatus.FORBIDDEN )
|
// return new HttpException('You must not be in game...', HttpStatus.FORBIDDEN )
|
||||||
return this.gameService.generateToken(user, grantTicketDto);
|
return this.gameService.generateToken(user, grantTicketDto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,11 +39,12 @@ export class GameController {
|
|||||||
|
|
||||||
|
|
||||||
//N'est valable que pour le game-serveur.
|
//N'est valable que pour le game-serveur.
|
||||||
@Post('gameServer/validate')
|
@Post('gameserver/validate')
|
||||||
async validateTicket(@Body() validateTicketDto : ValidateTicketDto, @Req() request)
|
async validateTicket(@Body() validateTicketDto : ValidateTicketDto, @Req() request)
|
||||||
{
|
{
|
||||||
if (await this.gameService.validateToken(validateTicketDto) === false)
|
if (await this.gameService.validateToken(validateTicketDto) === false)
|
||||||
return new HttpException("The token is not valid", HttpStatus.NOT_FOUND);
|
return new HttpException("The token is not valid", HttpStatus.NOT_FOUND);
|
||||||
|
console.log("200 retourné côté nest")
|
||||||
return HttpStatus.OK;
|
return HttpStatus.OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,4 +75,12 @@ export class GameController {
|
|||||||
return this.gameService.findInvitations(user);
|
return this.gameService.findInvitations(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Post('gameserver/creategame')
|
||||||
|
async createGame(@Body() creategameDto : CreateGameDto)
|
||||||
|
{
|
||||||
|
return this.gameService.createGame(creategameDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { Game } from './entity/game.entity';
|
|||||||
import { ValidateTicketDto } from './dto/validateTicket.dto';
|
import { ValidateTicketDto } from './dto/validateTicket.dto';
|
||||||
import { TokenGame } from './entity/tokenGame.entity';
|
import { TokenGame } from './entity/tokenGame.entity';
|
||||||
import { UsersService } from 'src/users/users.service';
|
import { UsersService } from 'src/users/users.service';
|
||||||
|
import { CreateGameDto } from './dto/createGame.dto';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class GameService {
|
export class GameService {
|
||||||
@@ -37,9 +38,10 @@ export class GameService {
|
|||||||
|
|
||||||
async generateToken(user : User, grantTicketDto : GrantTicketDto)
|
async generateToken(user : User, grantTicketDto : GrantTicketDto)
|
||||||
{
|
{
|
||||||
if (user.status === "In Game")
|
// if (user.status === "In Game")
|
||||||
return new HttpException("You can't play two games", HttpStatus.FORBIDDEN);
|
// return new HttpException("You can't play two games", HttpStatus.FORBIDDEN);
|
||||||
else if (grantTicketDto.isGameIsWithInvitation === true)
|
// else
|
||||||
|
if (grantTicketDto.isGameIsWithInvitation === true)
|
||||||
{
|
{
|
||||||
const secondUser : Partial<User> = await this.userService.findOneByUsername(user.id.toString(), grantTicketDto.playerTwoUsername)
|
const secondUser : Partial<User> = await this.userService.findOneByUsername(user.id.toString(), grantTicketDto.playerTwoUsername)
|
||||||
if (!secondUser)
|
if (!secondUser)
|
||||||
@@ -141,8 +143,8 @@ export class GameService {
|
|||||||
|
|
||||||
async declineInvitation(user : User, token : string)
|
async declineInvitation(user : User, token : string)
|
||||||
{
|
{
|
||||||
if (user.status === "In Game")
|
// if (user.status === "In Game")
|
||||||
return new HttpException("You must finish your game before decline.", HttpStatus.FORBIDDEN)
|
// return new HttpException("You must finish your game before decline.", HttpStatus.FORBIDDEN)
|
||||||
const tokenGame = await this.tokenGameRepository.createQueryBuilder('tokengame')
|
const tokenGame = await this.tokenGameRepository.createQueryBuilder('tokengame')
|
||||||
.andWhere('tokengame.playerTwoUsername = :playerTwoUsername', {playerTwoUsername : user.username})
|
.andWhere('tokengame.playerTwoUsername = :playerTwoUsername', {playerTwoUsername : user.username})
|
||||||
.andWhere('tokengame.token = :token', {token : token})
|
.andWhere('tokengame.token = :token', {token : token})
|
||||||
@@ -154,8 +156,8 @@ export class GameService {
|
|||||||
|
|
||||||
async acceptInvitation(user : User, token : string)
|
async acceptInvitation(user : User, token : string)
|
||||||
{
|
{
|
||||||
if (user.status === "In Game")
|
// if (user.status === "In Game")
|
||||||
return new HttpException("You must finish your game before accept.", HttpStatus.FORBIDDEN)
|
// return new HttpException("You must finish your game before accept.", HttpStatus.FORBIDDEN)
|
||||||
const tokenGame = await this.tokenGameRepository.createQueryBuilder('tokenGame')
|
const tokenGame = await this.tokenGameRepository.createQueryBuilder('tokenGame')
|
||||||
.andWhere('tokenGame.playerTwoUsername = :playerTwoUsername', {playerTwoUsername : user.username})
|
.andWhere('tokenGame.playerTwoUsername = :playerTwoUsername', {playerTwoUsername : user.username})
|
||||||
.andWhere('tokenGame.token = :token', {token : token})
|
.andWhere('tokenGame.token = :token', {token : token})
|
||||||
@@ -170,8 +172,8 @@ export class GameService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async requestIfAnotherUserHasRespondToquestForGame(user : User, token : string) {
|
async requestIfAnotherUserHasRespondToquestForGame(user : User, token : string) {
|
||||||
if (user.status === "In Game")
|
// if (user.status === "In Game")
|
||||||
return new HttpException("You can't do that.", HttpStatus.BAD_REQUEST)
|
// return new HttpException("You can't do that.", HttpStatus.BAD_REQUEST)
|
||||||
const tokenGame = await this.tokenGameRepository.createQueryBuilder('tokenGame')
|
const tokenGame = await this.tokenGameRepository.createQueryBuilder('tokenGame')
|
||||||
.where('tokenGame.token = :token', {token : token})
|
.where('tokenGame.token = :token', {token : token})
|
||||||
.andWhere('tokenGame.isSecondUserAcceptedRequest = :isSecondUserAcceptedRequest', {isSecondUserAcceptedRequest : true})
|
.andWhere('tokenGame.isSecondUserAcceptedRequest = :isSecondUserAcceptedRequest', {isSecondUserAcceptedRequest : true})
|
||||||
@@ -183,5 +185,16 @@ export class GameService {
|
|||||||
else if (!tokenGame)
|
else if (!tokenGame)
|
||||||
return new HttpException("Not Found", HttpStatus.NOT_FOUND)
|
return new HttpException("Not Found", HttpStatus.NOT_FOUND)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async createGame(creategameDto : CreateGameDto)
|
||||||
|
{
|
||||||
|
const game = this.gameRepository.create(creategameDto)
|
||||||
|
this.gameRepository.save(game);
|
||||||
|
if (!game)
|
||||||
|
return HttpStatus.INTERNAL_SERVER_ERROR
|
||||||
|
console.log("200 retourné pour la création de partie")
|
||||||
|
return HttpStatus.OK
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,186 @@
|
|||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import * as enumeration from './shared_js/enums'
|
||||||
|
import * as constants from './client/constants'
|
||||||
|
import { initPong, initGc, initMatchOptions, initStartFunction } from './client/global'
|
||||||
|
import { GameArea } from './client/class/GameArea';
|
||||||
|
import { GameComponentsClient } from './client/class/GameComponentsClient';
|
||||||
|
import { handleInput } from './client/handleInput';
|
||||||
|
import {gameLoop} from './client/gameLoop'
|
||||||
|
import { drawLoop } from './client/draw';
|
||||||
|
import {countdown} from './client/utils'
|
||||||
|
import { initWebSocket } from './client/ws';
|
||||||
|
import { initAudio } from './client/audio';
|
||||||
|
import { pong, gc} from './client/global'
|
||||||
|
|
||||||
|
let optionsAreNotSet = true
|
||||||
|
|
||||||
|
let sound = "on"; // possible de faire un boolean avec svelte et radio buttons ?
|
||||||
|
let multi_balls = false;
|
||||||
|
let moving_walls = false;
|
||||||
|
let matchOptions : enumeration.MatchOptions = enumeration.MatchOptions.noOption;
|
||||||
|
|
||||||
|
const init = async() => {
|
||||||
|
// WIP nest, fetch token generation
|
||||||
|
// const address = "http://transcendance:8080";
|
||||||
|
// const responsePromise = fetch(address + "/token");
|
||||||
|
|
||||||
|
if (sound === "off") {
|
||||||
|
initAudio(true);
|
||||||
|
}
|
||||||
|
else if (sound === "on") {
|
||||||
|
initAudio(false);
|
||||||
|
}
|
||||||
|
console.log(sound); //debug
|
||||||
|
|
||||||
|
if (multi_balls === true) {
|
||||||
|
matchOptions |= enumeration.MatchOptions.multiBalls;
|
||||||
|
}
|
||||||
|
if (moving_walls === true) {
|
||||||
|
matchOptions |= enumeration.MatchOptions.movingWalls;
|
||||||
|
}
|
||||||
|
initMatchOptions(matchOptions);
|
||||||
|
optionsAreNotSet = false;
|
||||||
|
|
||||||
|
initPong(new GameArea());
|
||||||
|
initGc(new GameComponentsClient(matchOptions, pong.ctx));
|
||||||
|
initStartFunction(start);
|
||||||
|
|
||||||
|
// const response = await responsePromise;
|
||||||
|
// if (!response.ok) {
|
||||||
|
// console.log("Token retrieve failed"); // TODO: error message
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// const responseJson = await response.json();
|
||||||
|
initWebSocket(matchOptions, "yolo", "usernamePLACEHOLDER");
|
||||||
|
// ou est stocké le username dans le front svelte ?
|
||||||
|
}
|
||||||
|
|
||||||
|
function start() : void {
|
||||||
|
gc.text1.pos.assign(constants.w*0.5, constants.h*0.75);
|
||||||
|
countdown(constants.matchStartDelay/1000, (count: number) => {
|
||||||
|
gc.text1.clear();
|
||||||
|
gc.text1.text = `${count}`;
|
||||||
|
gc.text1.update();
|
||||||
|
}, resume);
|
||||||
|
}
|
||||||
|
|
||||||
|
function resume(): void {
|
||||||
|
gc.text1.text = "";
|
||||||
|
window.addEventListener('keydown', function (e) {
|
||||||
|
pong.addKey(e.key);
|
||||||
|
});
|
||||||
|
window.addEventListener('keyup', function (e) {
|
||||||
|
pong.deleteKey(e.key);
|
||||||
|
});
|
||||||
|
pong.handleInputInterval = window.setInterval(handleInput, constants.handleInputIntervalMS);
|
||||||
|
// pong.handleInputInterval = window.setInterval(sendLoop, c.sendLoopIntervalMS);
|
||||||
|
pong.gameLoopInterval = window.setInterval(gameLoop, constants.gameLoopIntervalMS);
|
||||||
|
pong.drawLoopInterval = window.setInterval(drawLoop, constants.drawLoopIntervalMS);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
{#if optionsAreNotSet}
|
||||||
|
<form on:submit|preventDefault={init}>
|
||||||
|
<div id="div_game_options">
|
||||||
|
<fieldset>
|
||||||
|
<legend>game options</legend>
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" id="multi_balls" name="multi_balls">
|
||||||
|
<label for="multi_balls">multiples balls</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" id="moving_walls" name="moving_walls">
|
||||||
|
<label for="moving_walls">moving walls</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<!-- svelte-ignore a11y-label-has-associated-control -->
|
||||||
|
<label>sound :</label>
|
||||||
|
<input type="radio" id="sound_on" name="sound_selector" bind:group={sound} value="on">
|
||||||
|
<label for="sound_on">on</label>
|
||||||
|
<input type="radio" id="sound_off" name="sound_selector" bind:group={sound} value="off">
|
||||||
|
<label for="sound_off">off</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<button id="play_pong_button">PLAY</button>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<div id="div_game_instructions">
|
||||||
|
<h2>--- keys ---</h2>
|
||||||
|
<p>move up: 'w' or 'up arrow'</p>
|
||||||
|
<p>move down: 's' OR 'down arrow'</p>
|
||||||
|
<p>grid on/off: 'g'</p>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<div id="canvas_container">
|
||||||
|
<!-- <p> =) </p> -->
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Bit5x3";
|
||||||
|
src:
|
||||||
|
url("/fonts/Bit5x3.woff2") format("woff2"),
|
||||||
|
local("Bit5x3"),
|
||||||
|
url("/fonts/Bit5x3.woff") format("woff");
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
background-color: #222425;
|
||||||
|
}
|
||||||
|
#canvas_container {
|
||||||
|
margin-top: 20px;
|
||||||
|
text-align: center;
|
||||||
|
/* border: dashed rgb(245, 245, 245) 5px; */
|
||||||
|
/* max-height: 80vh; */
|
||||||
|
/* overflow: hidden; */
|
||||||
|
}
|
||||||
|
#div_game_instructions {
|
||||||
|
text-align: center;
|
||||||
|
font-family: "Bit5x3";
|
||||||
|
color: rgb(245, 245, 245);
|
||||||
|
font-size: large;
|
||||||
|
}
|
||||||
|
#div_game_options {
|
||||||
|
margin-top: 20px;
|
||||||
|
text-align: center;
|
||||||
|
font-family: "Bit5x3";
|
||||||
|
color: rgb(245, 245, 245);
|
||||||
|
font-size: x-large;
|
||||||
|
}
|
||||||
|
#div_game_options fieldset {
|
||||||
|
max-width: 50vw;
|
||||||
|
width: auto;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
#div_game_options fieldset div {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
#play_pong_button {
|
||||||
|
font-family: "Bit5x3";
|
||||||
|
color: rgb(245, 245, 245);
|
||||||
|
background-color: #333333;
|
||||||
|
font-size: x-large;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
canvas {
|
||||||
|
background-color: #333333;
|
||||||
|
max-width: 75vw;
|
||||||
|
/* max-height: 100vh; */
|
||||||
|
width: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -20,21 +20,13 @@
|
|||||||
let user;
|
let user;
|
||||||
let allUsers;
|
let allUsers;
|
||||||
|
|
||||||
|
|
||||||
//init function
|
|
||||||
let isSecondPlayerAnsweredYes = false;
|
|
||||||
let isSecondPlayerRefused = false;
|
|
||||||
let isSomethingWentWrong = true;
|
|
||||||
|
|
||||||
|
|
||||||
//Game's stuff nest side
|
//Game's stuff nest side
|
||||||
let optionsAreNotSet = true;
|
let optionsAreNotSet = true;
|
||||||
let invite_someone = false;
|
let isSomeoneIsIvited = false;
|
||||||
let playerTwoUsername = "";
|
let playerTwoUsername = "";
|
||||||
let token = "";
|
|
||||||
|
|
||||||
//Game's stuff gameserver side
|
//Game's stuff gameserver side
|
||||||
let sound = "";
|
let sound = "on";
|
||||||
let multi_balls = false;
|
let multi_balls = false;
|
||||||
let moving_walls = false;
|
let moving_walls = false;
|
||||||
let matchOption : enumeration.MatchOptions = enumeration.MatchOptions.noOption;
|
let matchOption : enumeration.MatchOptions = enumeration.MatchOptions.noOption;
|
||||||
@@ -44,6 +36,7 @@
|
|||||||
let showInvitations = false;
|
let showInvitations = false;
|
||||||
let showGameOption = true;
|
let showGameOption = true;
|
||||||
let showError = false;
|
let showError = false;
|
||||||
|
let showCanvas = false;
|
||||||
|
|
||||||
let isThereAnyInvitation = false;
|
let isThereAnyInvitation = false;
|
||||||
let invitations;
|
let invitations;
|
||||||
@@ -51,8 +44,6 @@
|
|||||||
let waitingMessage = "Please wait..."
|
let waitingMessage = "Please wait..."
|
||||||
let errorMessageWhenAttemptingToGetATicket = "";
|
let errorMessageWhenAttemptingToGetATicket = "";
|
||||||
|
|
||||||
let responseToCheckIfOtherUserHasAnswered;
|
|
||||||
|
|
||||||
onMount( async() => {
|
onMount( async() => {
|
||||||
user = await fetch('http://transcendance:8080/api/v2/user')
|
user = await fetch('http://transcendance:8080/api/v2/user')
|
||||||
.then( x => x.json() );
|
.then( x => x.json() );
|
||||||
@@ -68,23 +59,24 @@
|
|||||||
matchOption |= enumeration.MatchOptions.multiBalls
|
matchOption |= enumeration.MatchOptions.multiBalls
|
||||||
if (moving_walls === true )
|
if (moving_walls === true )
|
||||||
matchOption |= enumeration.MatchOptions.movingWalls
|
matchOption |= enumeration.MatchOptions.movingWalls
|
||||||
const res = await fetch("http://transcendance:8080/api/v2/game/ticket", {
|
|
||||||
|
const responseWhenGrantToken = fetch("http://transcendance:8080/api/v2/game/ticket", {
|
||||||
method : "POST",
|
method : "POST",
|
||||||
headers : {'Content-Type': 'application/json'},
|
headers : {'Content-Type': 'application/json'},
|
||||||
body : JSON.stringify({
|
body : JSON.stringify({
|
||||||
playerOneUsername : user.username,
|
playerOneUsername : user.username,
|
||||||
playerTwoUsername : playerTwoUsername,
|
playerTwoUsername : playerTwoUsername,
|
||||||
gameOptions : matchOption,
|
gameOptions : matchOption,
|
||||||
isGameIsWithInvitation : invite_someone
|
isGameIsWithInvitation : isSomeoneIsIvited
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.then(x => x.json())
|
const responseFromServer = await responseWhenGrantToken;
|
||||||
.catch(error => {
|
console.log("Response.ok : " + responseFromServer.ok )
|
||||||
console.log(error)
|
console.log("//")
|
||||||
})
|
const responseInjson = await responseFromServer.json()
|
||||||
if (res.status === 403 || res.status === 404 || res.status === 500)
|
if (!responseFromServer.ok || !responseInjson.token)
|
||||||
{
|
{
|
||||||
errorMessageWhenAttemptingToGetATicket = res.message;
|
errorMessageWhenAttemptingToGetATicket = responseInjson.message;
|
||||||
showError = true;
|
showError = true;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
showError = false;
|
showError = false;
|
||||||
@@ -92,40 +84,27 @@
|
|||||||
optionsAreNotSet = true
|
optionsAreNotSet = true
|
||||||
playerTwoUsername = "";
|
playerTwoUsername = "";
|
||||||
matchOption = 0;
|
matchOption = 0;
|
||||||
token = ""
|
|
||||||
}, 5000)
|
}, 5000)
|
||||||
return ;
|
|
||||||
}
|
}
|
||||||
else if (res.status === 200)
|
else
|
||||||
{
|
{
|
||||||
initAudio(sound)
|
showError = false
|
||||||
|
showWaitPage = false
|
||||||
|
const token = responseInjson.token
|
||||||
|
console.log("Token === " + token)
|
||||||
|
if (sound === "off") {
|
||||||
|
initAudio(true);
|
||||||
|
}
|
||||||
|
else if (sound === "on") {
|
||||||
|
initAudio(false);
|
||||||
|
}
|
||||||
initMatchOptions(matchOption)
|
initMatchOptions(matchOption)
|
||||||
initPong(new GameArea())
|
initPong(new GameArea())
|
||||||
initGc(new GameComponentsClient(matchOption, pong.ctx))
|
initGc(new GameComponentsClient(matchOption, pong.ctx))
|
||||||
initStartFunction(start)
|
initStartFunction(start)
|
||||||
initWebSocket(matchOption)
|
console.log("Avant init websocket")
|
||||||
|
initWebSocket(matchOption, token, user.username)
|
||||||
}
|
}
|
||||||
// const fetch = await fetch("http://transcendance:8080/api/v2/game/gameServer/validate", {
|
|
||||||
// method : "POST",
|
|
||||||
// headers : {'Content-Type': 'application/json'},
|
|
||||||
// body : JSON.stringify({
|
|
||||||
// playerOneUsername : user.username,
|
|
||||||
// playerTwoUsername : playerTwoUsername,
|
|
||||||
// gameOptions : matchOption,
|
|
||||||
// isGameIsWithInvitation : invite_someone,
|
|
||||||
// token : token
|
|
||||||
// })
|
|
||||||
// })
|
|
||||||
// .then(x => x.json())
|
|
||||||
// .catch(error => {
|
|
||||||
// console.log(error)
|
|
||||||
// })
|
|
||||||
// if (res.status !== 200)
|
|
||||||
// {
|
|
||||||
// showError = true;
|
|
||||||
// errorMessageWhenAttemptingToGetATicket = "Your session is not valid. Please try again."
|
|
||||||
// return ;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function start() : void {
|
function start() : void {
|
||||||
@@ -134,10 +113,10 @@
|
|||||||
gc.text1.clear();
|
gc.text1.clear();
|
||||||
gc.text1.text = `${count}`;
|
gc.text1.text = `${count}`;
|
||||||
gc.text1.update();
|
gc.text1.update();
|
||||||
}, resume);
|
}, responseWhenGrantTokenume);
|
||||||
}
|
}
|
||||||
|
|
||||||
function resume(): void {
|
function responseWhenGrantTokenume(): void {
|
||||||
gc.text1.text = "";
|
gc.text1.text = "";
|
||||||
window.addEventListener('keydown', function (e) {
|
window.addEventListener('keydown', function (e) {
|
||||||
pong.addKey(e.key);
|
pong.addKey(e.key);
|
||||||
@@ -160,6 +139,7 @@
|
|||||||
showInvitations = true;
|
showInvitations = true;
|
||||||
invitations = await fetch("http://transcendance:8080/api/v2/game/invitations")
|
invitations = await fetch("http://transcendance:8080/api/v2/game/invitations")
|
||||||
.then(x => x.json())
|
.then(x => x.json())
|
||||||
|
console.log(...invitations)
|
||||||
}
|
}
|
||||||
|
|
||||||
const rejectInvitation = async() => {
|
const rejectInvitation = async() => {
|
||||||
@@ -188,12 +168,13 @@
|
|||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="preload_font">.</div>
|
<div id="preload_font">.</div>
|
||||||
|
|
||||||
{#if showError === true}
|
{#if showError === true}
|
||||||
<div id="div_game">
|
<div id="div_game">
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>Error</legend>
|
<legend>Error</legend>
|
||||||
<p>{errorMessageWhenAttemptingToGetATicket}</p>
|
<p>{errorMessageWhenAttemptingToGetATicket}</p>
|
||||||
<button id="pong_button" on:click={() => push('/game')}>Retry</button>
|
<button id="pong_button">Retry</button>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -223,14 +204,18 @@
|
|||||||
<label for="moving_walls">Moving walls</label>
|
<label for="moving_walls">Moving walls</label>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<input type="checkbox" id="moving_walls" name="moving_walls" bind:checked={sound}>
|
<!-- svelte-ignore a11y-label-has-associated-control -->
|
||||||
<label for="moving_walls">Sound</label>
|
<label>sound :</label>
|
||||||
|
<input type="radio" id="sound_on" name="sound_selector" bind:group={sound} value="on">
|
||||||
|
<label for="sound_on">on</label>
|
||||||
|
<input type="radio" id="sound_off" name="sound_selector" bind:group={sound} value="off">
|
||||||
|
<label for="sound_off">off</label>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<input type="checkbox" id="invite_someone" name="moving_walls" bind:checked={invite_someone}>
|
<input type="checkbox" id="isSomeoneIsIvited" name="moving_walls" bind:checked={isSomeoneIsIvited}>
|
||||||
<label for="moving_walls">Invite a friend</label>
|
<label for="moving_walls">Invite a friend</label>
|
||||||
</div>
|
</div>
|
||||||
{#if invite_someone === true}
|
{#if isSomeoneIsIvited === true}
|
||||||
<select bind:value={playerTwoUsername}>
|
<select bind:value={playerTwoUsername}>
|
||||||
{#each allUsers as user }
|
{#each allUsers as user }
|
||||||
<option value={user.username}>{user.username}</option>
|
<option value={user.username}>{user.username}</option>
|
||||||
@@ -266,12 +251,13 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<div id="canvas_container">
|
<div id="canvas_container">
|
||||||
<!-- <p> =) </p> -->
|
<canvas id="gameArea"></canvas>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
@@ -312,6 +298,7 @@ body {
|
|||||||
color: rgb(143, 19, 19);
|
color: rgb(143, 19, 19);
|
||||||
font-size: x-large;
|
font-size: x-large;
|
||||||
}
|
}
|
||||||
|
|
||||||
#div_game fieldset {
|
#div_game fieldset {
|
||||||
max-width: 50vw;
|
max-width: 50vw;
|
||||||
width: auto;
|
width: auto;
|
||||||
@@ -328,7 +315,7 @@ body {
|
|||||||
padding: 10px;
|
padding: 10px;
|
||||||
}
|
}
|
||||||
canvas {
|
canvas {
|
||||||
background-color: #333333;
|
background-color: #ff0000;
|
||||||
max-width: 75vw;
|
max-width: 75vw;
|
||||||
/* max-height: 100vh; */
|
/* max-height: 100vh; */
|
||||||
width: 80%;
|
width: 80%;
|
||||||
|
|||||||
@@ -9,13 +9,14 @@ export class GameArea {
|
|||||||
canvas: HTMLCanvasElement;
|
canvas: HTMLCanvasElement;
|
||||||
ctx: CanvasRenderingContext2D;
|
ctx: CanvasRenderingContext2D;
|
||||||
constructor() {
|
constructor() {
|
||||||
this.canvas = document.createElement("canvas");
|
this.canvas = document.getElementById("gameArea");
|
||||||
|
if (this.canvas)
|
||||||
|
console.log("Le canvas a été trouvé !")
|
||||||
|
else
|
||||||
|
console.log("Le canvas a été mangé par un être mystérieux...")
|
||||||
this.ctx = this.canvas.getContext("2d") as CanvasRenderingContext2D;
|
this.ctx = this.canvas.getContext("2d") as CanvasRenderingContext2D;
|
||||||
this.canvas.width = c.CanvasWidth;
|
this.canvas.width = c.CanvasWidth;
|
||||||
this.canvas.height = c.CanvasWidth / c.CanvasRatio;
|
this.canvas.height = c.CanvasWidth / c.CanvasRatio;
|
||||||
let container = document.getElementById("canvas_container");
|
|
||||||
if (container)
|
|
||||||
container.insertBefore(this.canvas, container.childNodes[0]);
|
|
||||||
}
|
}
|
||||||
addKey(key: string) {
|
addKey(key: string) {
|
||||||
key = key.toLowerCase();
|
key = key.toLowerCase();
|
||||||
|
|||||||
Reference in New Issue
Block a user