ajout de contenu

main
Etienne Veau 1 month ago
parent b93f098f53
commit 180706052a

BIN
.DS_Store vendored

Binary file not shown.

@ -0,0 +1,25 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>2048</title>
<link rel="stylesheet" href="style_2048.css">
</head>
<body>
<div class="container">
<div class="header">
<h1>2048</h1>
<div class="score-container">
Score: <span id="score">0</span>
</div>
<button id="new-game">Nouvelle partie</button>
</div>
<div class="grid"></div>
</div>
<script src="script_2048.js"></script>
</body>
</html>

Binary file not shown.

@ -23,13 +23,12 @@
</nav>
<div class="container contact-container">
<section class="cv-preview">
<h2>Contactez-moi</h2>
<img src="mail.png" alt="Contactez-moi" style="max-width: 200px; margin-bottom: 20px;">
<br><br><br><br>
<div class="contact-button">
<a href="mailto:etienne.veau@etu.uca.fr?subject=Contact%20via%20le%20portfolio&body=Bonjour%20Etienne,%0D%0A%0D%0A"
class="btn submit-btn">Envoyer un e-mail</a>
</div>
</section>
</div>

BIN
images/.DS_Store vendored

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

@ -23,7 +23,7 @@
</nav>
<div class="container">
<h2>Mes Projets</h2>
<h2>Mes projets</h2>
<div class="projets-grid">
<div class="card projet">
@ -46,6 +46,40 @@
<p><b>Document :</b> <button onclick="window.open('rapport.pdf')">Voir le document</button></p>
</div>
</div>
<div class="projets-grid">
<div class="card projet">
<h3>Développement d'un jeu de société - Qawale</h3>
<p><b>Contexte :</b> Projet personnel de développement d'application mobile cross-platform.</p>
<p><b>Objectifs du projet :</b> Recréer le jeu de société Qawale en version numérique en utilisant .NET
MAUI et C#,
permettant de jouer sur différentes plateformes (iOS, Android, Windows).</p>
<p><b>Travail réalisé :</b> J'ai développé une application complète incluant :
<ul>
<li>Une interface utilisateur intuitive et responsive</li>
<li>Un mode deux joueurs local</li>
<li>Un système de validation des coups selon les règles officielles</li>
<li>Une intelligence artificielle pour jouer contre l'ordinateur</li>
<li>Un système de sauvegarde des parties</li>
</ul>
</p>
<p><b>Technologies utilisées :</b>
<ul>
<li>.NET MAUI pour le développement cross-platform</li>
<li>C# pour la logique du jeu</li>
<li>XAML pour l'interface utilisateur</li>
</ul>
</p>
<p><b>Résultats du projet :</b> Ce projet m'a permis d'approfondir mes compétences en développement
avec .NET MAUI, en programmation orientée objet avec C#, et en conception d'interfaces utilisateur.
J'ai également acquis de l'expérience dans la gestion de la logique de jeu complexe et dans
l'implémentation d'IA basiques.</p>
<p><b>Code source :</b> <a
href="https://codefirst.iut.uca.fr/git/clement.sellier/SAE_1A_G4_LEJUEZ_VEAU_TARDY_SELLIER.git"
target="_blank" class="btn">Voir le dépôt Git</a></p>
</div>
</div>
<div class="projets-grid">
<div class="card projet">
<h3>Création dun Portfolio Web</h3>
@ -103,8 +137,10 @@
sur internet afin de comprendre et réaliser les tâches demandées. Je me suis également grandement
familiarisé avec l'utilisation du terminal et ses lignes de commandes. Enfin, cela m'a permis d'en
apprendre plus sur le fonctionnement d'un espace disque et d'un système d'exploitation.</p>
<p><b>Document :</b> <button onclick="window.open('linux_administration.pdf')">Voir le document</button>
</p>
<p><b>Résultats du projet :</b> J'ai réussi à installer une distribution Debian, à la configurer avec
les paquets demandés, à partitionner les disques et à mettre en place les Backports ainsi que
FlatPak. J'ai également appris à utiliser le terminal de manière efficace, ce qui m'a permis de
gagner en autonomie dans la gestion de systèmes Linux.</p>
</div>
</div>
@ -123,7 +159,7 @@
<p><b>Résultats du projet :</b> Ce projet m'a permis de me familiariser avec le langage C et m'a appris
à gérer des tableaux de manière efficace (Chargement, Recherche, Tri, Affichage). Cela m'a également
permis d'utiliser différents types de fichiers afin d'effectuer des sauvegardes.</p>
<p><b>Document :</b> <button onclick="window.open('gestion_stages.pdf')">Voir le document</button></p>
</div>
</div>
@ -138,11 +174,11 @@
particulier au respect de l'utilisation des différentes structures (Pile, File, Liste). Ce projet a
renforcé ma compréhension des structures de données et m'a introduit à la notion de complexité et à
l'utilisation de fichiers binaires pour effectuer des sauvegardes.</p>
<p><b>Document :</b> <button onclick="window.open('jeu_tour_par_tour.pdf')">Voir le document</button>
<p><b>Sujet du projet :</b> <button onclick="window.open('sujet.pdf')">Voir le document</button>
</p>
</div>
</div>
<h2>Mes projets personnels</h2>
<!-- Projet 5 -->
<div class="projets-grid">
<div class="card projet">
@ -154,13 +190,54 @@
algorithme en C# capable d'interagir avec le jeu afin qu'il soit imbattable. Une fois le programme
fonctionnel, je souhaite entraîner une IA capable de battre le jeu et comparer les deux solutions
pour analyser celle qui obtient le meilleur score.</p>
<p><b>Résultats du projet :</b> Ce projet m'a permis de m'autoformer sur Unity et C#, de travailler sur
un projet complexe, et de m'introduire aux notions d'IA et de robotique.</p>
<p><b>Document :</b> <button onclick="window.open('crossy_road.pdf')">Voir le document</button></p>
<p><b>Résultats du projet :</b> Ce projet me permettra de m'autoformer sur Unity et C#, de travailler
sur
un projet complexe, et sera une bonne introduction aux notions d'IA et de robotique.</p>
<div class="video-container">
<div class="video-wrapper" id="videoWrapper">
<video src="CrossyRoad.mp4" autoplay loop muted playsinline class="embedded-video">
</video>
</div>
</div>
<p><b>Vidéo d'inspiration :</b> <a href="https://www.youtube.com/watch?v=71UbDN4csas" target="_blank"
class="btn video-btn">Voir sur YouTube</a></p>
</div>
</div>
<!-- Projet 2048 -->
<div class="projets-grid">
<div class="card projet">
<h3>Développement du jeu 2048</h3>
<p><b>Contexte :</b> Projet personnel réalisé pour approfondir mes compétences en développement web.</p>
<p><b>Objectifs du projet :</b> Recréer le célèbre jeu 2048 en utilisant HTML, CSS et JavaScript, tout
en
développant une interface utilisateur moderne et responsive.</p>
<p><b>Travail réalisé :</b> J'ai développé une version complète du jeu 2048 en intégrant plusieurs
fonctionnalités :
<ul>
<li>Un système de score en temps réel</li>
<li>Des animations fluides pour les déplacements et fusions</li>
<li>Une grille 4x4 réactive aux touches directionnelles</li>
<li>Un bouton de nouvelle partie</li>
</ul>
</p>
<p><b>Résultats du projet :</b> Ce projet m'a permis de renforcer mes compétences en JavaScript,
notamment
dans la manipulation de tableaux 2D, la gestion des événements clavier, et la création d'animations
CSS.
J'ai également approfondi en gestion de
la
logique de jeu.</p>
<p><b>Jouer :</b> <a href="2048.html" class="btn game-btn">Jouer à 2048</a></p>
</div>
</div>
</div>
</div>
<script>
const hamburger = document.querySelector('.hamburger');
const navMenu = document.querySelector('nav ul');
@ -176,6 +253,31 @@
hamburger.setAttribute('aria-expanded', 'false');
});
});
// Gestion de la vidéo
const videoWrapper = document.getElementById('videoWrapper');
const video = videoWrapper.querySelector('video');
let isExpanded = false;
videoWrapper.addEventListener('click', () => {
isExpanded = !isExpanded;
if (isExpanded) {
videoWrapper.classList.add('expanded');
video.muted = false;
video.controls = true;
} else {
videoWrapper.classList.remove('expanded');
video.muted = true;
video.controls = false;
}
});
// Fermer la vidéo avec la touche Escape
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && isExpanded) {
videoWrapper.click();
}
});
</script>
</body>

@ -0,0 +1,223 @@
class Game2048 {
constructor() {
this.grid = Array(4).fill().map(() => Array(4).fill(0));
this.score = 0;
this.gridElement = document.querySelector('.grid');
this.scoreElement = document.getElementById('score');
this.setupGrid();
this.addNumber();
this.addNumber();
this.setupEventListeners();
this.showInstructions(); // Ajout de l'appel à la nouvelle méthode
}
setupGrid() {
for (let i = 0; i < 16; i++) {
const cell = document.createElement('div');
cell.classList.add('cell');
this.gridElement.appendChild(cell);
}
this.updateGrid();
}
updateGrid() {
const cells = this.gridElement.getElementsByClassName('cell');
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 4; j++) {
const value = this.grid[i][j];
const cell = cells[i * 4 + j];
const previousValue = parseInt(cell.getAttribute('data-value')) || 0;
cell.textContent = value || '';
cell.setAttribute('data-value', value);
// Ajouter les animations
if (value && value !== previousValue) {
// Animation de fusion si la valeur a doublé
if (previousValue && value === previousValue * 2) {
cell.classList.add('merge');
}
// Animation de glissement selon la direction
else if (value) {
const lastMove = this.lastMoveDirection;
if (lastMove) {
cell.classList.add(`slide-${lastMove}`);
}
}
}
// Retirer les classes d'animation après leur exécution
cell.addEventListener('animationend', () => {
cell.classList.remove('merge', 'slide-left', 'slide-right', 'slide-up', 'slide-down');
});
}
}
this.scoreElement.textContent = this.score;
}
addNumber() {
const emptyCells = [];
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 4; j++) {
if (this.grid[i][j] === 0) {
emptyCells.push({ x: i, y: j });
}
}
}
if (emptyCells.length) {
const { x, y } = emptyCells[Math.floor(Math.random() * emptyCells.length)];
this.grid[x][y] = Math.random() < 0.9 ? 2 : 4;
}
}
move(direction) {
let moved = false;
const gridCopy = JSON.parse(JSON.stringify(this.grid));
// Convertir la direction en format plus simple
this.lastMoveDirection = direction.toLowerCase().replace('arrow', '');
switch (direction) {
case 'ArrowLeft':
moved = this.moveLeft();
break;
case 'ArrowRight':
moved = this.moveRight();
break;
case 'ArrowUp':
moved = this.moveUp();
break;
case 'ArrowDown':
moved = this.moveDown();
break;
}
if (moved) {
this.addNumber();
this.updateGrid();
if (this.isGameOver()) {
alert('Game Over! Score: ' + this.score);
}
}
}
moveRow(row) {
let arr = row.filter(x => x !== 0);
for (let i = 0; i < arr.length - 1; i++) {
if (arr[i] === arr[i + 1]) {
arr[i] *= 2;
this.score += arr[i];
arr.splice(i + 1, 1);
}
}
while (arr.length < 4) arr.push(0);
return arr;
}
moveLeft() {
let moved = false;
for (let i = 0; i < 4; i++) {
const oldRow = [...this.grid[i]];
const newRow = this.moveRow([...oldRow]);
this.grid[i] = newRow;
if (JSON.stringify(oldRow) !== JSON.stringify(newRow)) moved = true;
}
return moved;
}
moveRight() {
let moved = false;
for (let i = 0; i < 4; i++) {
const oldRow = [...this.grid[i]];
const newRow = this.moveRow([...oldRow].reverse()).reverse();
this.grid[i] = newRow;
if (JSON.stringify(oldRow) !== JSON.stringify(newRow)) moved = true;
}
return moved;
}
moveUp() {
let moved = false;
for (let j = 0; j < 4; j++) {
const oldColumn = this.grid.map(row => row[j]);
const newColumn = this.moveRow([...oldColumn]);
for (let i = 0; i < 4; i++) {
if (this.grid[i][j] !== newColumn[i]) {
moved = true;
this.grid[i][j] = newColumn[i];
}
}
}
return moved;
}
moveDown() {
let moved = false;
for (let j = 0; j < 4; j++) {
const oldColumn = this.grid.map(row => row[j]);
const newColumn = this.moveRow([...oldColumn].reverse()).reverse();
for (let i = 0; i < 4; i++) {
if (this.grid[i][j] !== newColumn[i]) {
moved = true;
this.grid[i][j] = newColumn[i];
}
}
}
return moved;
}
isGameOver() {
// Check for empty cells
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 4; j++) {
if (this.grid[i][j] === 0) return false;
}
}
// Check for possible merges
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 4; j++) {
const current = this.grid[i][j];
if ((j < 3 && current === this.grid[i][j + 1]) ||
(i < 3 && current === this.grid[i + 1][j])) {
return false;
}
}
}
return true;
}
setupEventListeners() {
document.addEventListener('keydown', (e) => {
if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(e.key)) {
e.preventDefault();
this.move(e.key);
}
});
document.getElementById('new-game').addEventListener('click', () => {
this.grid = Array(4).fill().map(() => Array(4).fill(0));
this.score = 0;
this.addNumber();
this.addNumber();
this.updateGrid();
});
}
showInstructions() {
const message = document.createElement('div');
message.className = 'instruction-message';
message.textContent = '↑ ↓ ← → Utilisez les flèches du clavier pour jouer';
document.body.appendChild(message);
// Supprime le message après 60 secondes
setTimeout(() => {
message.remove();
}, 60000);
}
}
// Start the game when the page loads
document.addEventListener('DOMContentLoaded', () => {
new Game2048();
});

@ -201,7 +201,20 @@ textarea {
text-decoration: none;
}
.game-btn {
display: inline-block;
padding: 10px 20px;
background-color: #0d082e;
color: white;
text-decoration: none;
border-radius: 5px;
transition: background-color 0.3s ease;
}
.game-btn:hover {
background-color: #45a049;
transform: scale(1.05);
}
.contact-container {
@ -355,4 +368,70 @@ b {
padding: 0 1rem;
margin: 6rem auto 2rem;
}
}
/* Styles pour la vidéo intégrée */
.video-container {
position: relative;
width: 100%;
margin: 20px 0;
overflow: hidden;
border-radius: 10px;
cursor: pointer;
}
.video-wrapper {
position: relative;
padding-bottom: 56.25%;
/* Ratio 16:9 */
height: 0;
transition: all 0.3s ease;
}
.video-wrapper.expanded {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 90vw;
height: 90vh;
padding-bottom: 0;
z-index: 1000;
}
.video-wrapper iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: 10px;
}
.video-wrapper video {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
border-radius: 10px;
}
.video-wrapper.expanded video {
object-fit: contain;
}
.video-btn {
display: inline-block;
padding: 8px 16px;
background-color: #ff0000;
color: white;
text-decoration: none;
border-radius: 5px;
transition: background-color 0.3s ease;
}
.video-btn:hover {
background-color: #cc0000;
}

@ -0,0 +1,238 @@
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background-color: #faf8ef;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
font-family: Arial, sans-serif;
}
.container {
width: 460px;
text-align: center;
}
.header {
margin-bottom: 20px;
}
h1 {
font-size: 48px;
color: #776e65;
margin-bottom: 10px;
}
.score-container {
display: inline-block;
background: #bbada0;
padding: 10px 20px;
border-radius: 3px;
color: white;
font-weight: bold;
margin: 10px;
}
#new-game {
background: #8f7a66;
color: white;
border: none;
padding: 10px 20px;
border-radius: 3px;
cursor: pointer;
}
.grid {
background: #bbada0;
padding: 15px;
border-radius: 6px;
display: grid;
grid-template-columns: repeat(4, 100px);
/* Définition explicite de la largeur */
grid-gap: 15px;
position: relative;
box-shadow: 0 0 0 2px #bbada0;
/* Ajout d'une bordure sous forme d'ombre */
margin: 0 auto;
/* Centrage horizontal */
width: fit-content;
/* Ajustement automatique de la largeur */
}
.cell {
width: 100px;
height: 100px;
background: rgba(238, 228, 218, 0.35);
border-radius: 3px;
display: flex;
justify-content: center;
align-items: center;
font-size: 36px;
font-weight: bold;
color: #776e65;
transition: all 0.15s ease;
position: relative;
}
/* Animations de déplacement */
.cell.merge {
animation: merge 0.2s ease-in-out;
}
.cell.slide-left {
animation: slideLeft 0.2s ease-in-out;
}
.cell.slide-right {
animation: slideRight 0.2s ease-in-out;
}
.cell.slide-up {
animation: slideUp 0.2s ease-in-out;
}
.cell.slide-down {
animation: slideDown 0.2s ease-in-out;
}
@keyframes merge {
0% {
transform: scale(1);
}
50% {
transform: scale(1.2);
}
100% {
transform: scale(1);
}
}
@keyframes slideLeft {
0% {
transform: translateX(100px);
}
100% {
transform: translateX(0);
}
}
@keyframes slideRight {
0% {
transform: translateX(-100px);
}
100% {
transform: translateX(0);
}
}
@keyframes slideUp {
0% {
transform: translateY(100px);
}
100% {
transform: translateY(0);
}
}
@keyframes slideDown {
0% {
transform: translateY(-100px);
}
100% {
transform: translateY(0);
}
}
.cell[data-value="2"] {
background: #eee4da;
}
.cell[data-value="4"] {
background: #ede0c8;
}
.cell[data-value="8"] {
background: #f2b179;
color: #f9f6f2;
}
.cell[data-value="16"] {
background: #f59563;
color: #f9f6f2;
}
.cell[data-value="32"] {
background: #f67c5f;
color: #f9f6f2;
}
.cell[data-value="64"] {
background: #f65e3b;
color: #f9f6f2;
}
.cell[data-value="128"] {
background: #edcf72;
color: #f9f6f2;
font-size: 32px;
}
.cell[data-value="256"] {
background: #edcc61;
color: #f9f6f2;
font-size: 32px;
}
.cell[data-value="512"] {
background: #edc850;
color: #f9f6f2;
font-size: 32px;
}
.cell[data-value="1024"] {
background: #edc53f;
color: #f9f6f2;
font-size: 28px;
}
.cell[data-value="2048"] {
background: #edc22e;
color: #f9f6f2;
font-size: 28px;
}
.instruction-message {
position: fixed;
top: 20px;
left: 50%;
transform: translateX(-50%);
background-color: rgba(119, 110, 101, 0.9);
color: white;
padding: 15px 25px;
border-radius: 5px;
font-size: 16px;
animation: fadeOut 1s ease-in 59s forwards;
z-index: 1000;
}
@keyframes fadeOut {
from {
opacity: 1;
}
to {
opacity: 0;
visibility: hidden;
}
}

Binary file not shown.
Loading…
Cancel
Save