diff --git a/src/Dessin.java b/src/Dessin.java index a189d2c..c90cfaf 100644 --- a/src/Dessin.java +++ b/src/Dessin.java @@ -1,23 +1,88 @@ +import javax.swing.*; +import java.awt.*; /** -* La classe Dessin +* La classe Dessin gère uniquement le dessin du pendu * -* @version -* @author -* Date : +* @version 1.0 +* @author Adrien +* Date : 08-10-2025 * Licence : */ -public class Dessin { - //Attributs +public class Dessin extends JPanel { - //Constructeur - public Dessin() { + // --- Constructeur --- + public Dessin() { + // Taille préférée pour s'intégrer dans Fenetre + setPreferredSize(new Dimension(600, 350)); + setBackground(new Color(245, 245, 245)); + } - } - //Méthodes + // --- Dessin principal --- + @Override + protected void paintComponent(Graphics graphics) { + super.paintComponent(graphics); - //Affichage - public String toString() { - return "" ; - } + // Anti-aliasing pour des traits plus doux + Graphics2D graphics2D = (Graphics2D) graphics.create(); + graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + graphics2D.setStroke(new BasicStroke(3f)); + graphics2D.setColor(Color.DARK_GRAY); + + // Repères et proportions + int width = getWidth(); + int height = getHeight(); + int marginPixels = Math.min(width, height) / 12; // marge proportionnelle + + // Potence : socle + int baseYCoordinate = height - marginPixels; + graphics2D.drawLine(marginPixels, baseYCoordinate, width / 2, baseYCoordinate); + + // Montant vertical + int postXCoordinate = marginPixels + (width / 12); + graphics2D.drawLine(postXCoordinate, baseYCoordinate, postXCoordinate, marginPixels); + + // Traverse horizontale + int beamLength = width / 3; + graphics2D.drawLine(postXCoordinate, marginPixels, postXCoordinate + beamLength, marginPixels); + + // Renfort diagonal + graphics2D.drawLine(postXCoordinate, marginPixels + height / 10, postXCoordinate + width / 12, marginPixels); + + // Corde + int ropeXCoordinate = postXCoordinate + beamLength; + int ropeTopYCoordinate = marginPixels; + int ropeBottomYCoordinate = marginPixels + height / 12; + graphics2D.drawLine(ropeXCoordinate, ropeTopYCoordinate, ropeXCoordinate, ropeBottomYCoordinate); + + // Personnage : tête + int headRadiusPixels = Math.min(width, height) / 16; + int headCenterX = ropeXCoordinate; + int headCenterY = ropeBottomYCoordinate + headRadiusPixels; + graphics2D.drawOval(headCenterX - headRadiusPixels, headCenterY - headRadiusPixels, headRadiusPixels * 2, headRadiusPixels * 2); + + // Corps + int bodyTopYCoordinate = headCenterY + headRadiusPixels; + int bodyBottomYCoordinate = bodyTopYCoordinate + height / 6; + graphics2D.drawLine(headCenterX, bodyTopYCoordinate, headCenterX, bodyBottomYCoordinate); + + // Bras + int armSpanPixels = width / 10; + int shouldersYCoordinate = bodyTopYCoordinate + height / 24; + graphics2D.drawLine(headCenterX, shouldersYCoordinate, headCenterX - armSpanPixels, shouldersYCoordinate + height / 20); + graphics2D.drawLine(headCenterX, shouldersYCoordinate, headCenterX + armSpanPixels, shouldersYCoordinate + height / 20); + + // Jambes + int legSpanPixels = width / 12; + graphics2D.drawLine(headCenterX, bodyBottomYCoordinate, headCenterX - legSpanPixels, bodyBottomYCoordinate + height / 8); + graphics2D.drawLine(headCenterX, bodyBottomYCoordinate, headCenterX + legSpanPixels, bodyBottomYCoordinate + height / 8); + + graphics2D.dispose(); + } + + // Affichage + @Override + public String toString() { + return ""; + } } diff --git a/src/Event.java b/src/Event.java new file mode 100644 index 0000000..88d9394 --- /dev/null +++ b/src/Event.java @@ -0,0 +1,72 @@ +import javax.swing.*; +import java.awt.event.*; +import java.util.function.Consumer; + +/** + * La classe Event regroupe et branche tous les listeners liés à Fenetre. + * - Validation de la saisie (1 lettre A-Z, majuscule) + * - Action sur Entrée ou clic bouton + * - Notification du handler externe (fourni au constructeur) + * Aucune logique de jeu ici. + * @version 1.3 + * author Adrien + * Date : 08-10-2025 + */ +public class Event implements ActionListener { + + private final Fenetre window; + private final Consumer onLetterSubmitted; + + /** Constructeur : conserve les références et branche les événements. */ + public Event(Fenetre window, Consumer onLetterSubmitted) { + this.window = window; + this.onLetterSubmitted = onLetterSubmitted; + wireEvents(); + } + + /** Branche les listeners sur les composants de Fenetre.*/ + private void wireEvents() { + JTextField letterInput = window.getLetterInput(); + JButton sendButton = window.getSendButton(); + + // Même listener (this) pour Entrée et clic bouton + sendButton.addActionListener(this); + letterInput.addActionListener(this); + + // UX : limiter à une seule lettre et forcer la majuscule + letterInput.addKeyListener(new KeyAdapter() { + @Override + public void keyTyped(KeyEvent keyEvent) { + char typedChar = keyEvent.getKeyChar(); + if (!Character.isLetter(typedChar) || letterInput.getText().length() >= 1) { + keyEvent.consume(); + } else { + keyEvent.setKeyChar(Character.toUpperCase(typedChar)); + } + } + }); + } + + /** Réagit à Entrée ou au clic bouton : récupère, valide et transmet la lettre. */ + @Override + public void actionPerformed(ActionEvent actionEvent) { + JTextField letterInput = window.getLetterInput(); + + String inputText = letterInput.getText().trim().toUpperCase(); + letterInput.setText(""); // reset du champ après tentative + + // Validation : exactement une lettre A–Z + if (inputText.length() != 1 || !inputText.matches("[A-Z]")) { + JOptionPane.showMessageDialog(window.getWindow(), "Veuillez entrer une seule lettre (A-Z)."); + return; + } + + // Notification du handler externe, sinon placeholder + if (onLetterSubmitted != null) { + onLetterSubmitted.accept(inputText.charAt(0)); + } else { + JOptionPane.showMessageDialog(window.getWindow(), + "Lettre soumise (placeholder) : " + inputText); + } + } +} diff --git a/src/Fenetre.java b/src/Fenetre.java index bec8a54..a62c14e 100644 --- a/src/Fenetre.java +++ b/src/Fenetre.java @@ -1,23 +1,98 @@ +import javax.swing.*; +import java.awt.*; +import java.util.function.Consumer; /** -* La classe Fenetre +* La classe Fenetre gère uniquement l'interface graphique : +* - zone de dessin (assurée par la classe Dessin) +* - affichage du mot masqué +* - saisie d'une lettre (les événements sont gérés dans Event) * -* @version -* @author -* Date : +* Aucune logique de jeu ici. +* @version 1.5 +* @author Adrien +* Date : 08-10-2025 * Licence : */ + public class Fenetre { - //Attributs - //Constructeur - public Fenetre() { + // --- Composants de l'interface --- + private JFrame window; + private JLabel wordLabel; + private JTextField letterInput; + private JButton sendButton; + private JPanel drawZone; // instance de Dessin - } - //Méthodes + // --- Constructeur --- + public Fenetre() { + setupWindow(); - //Affichage - public String toString() { - return "" ; - } -} + JPanel root = new JPanel(); + root.setLayout(new BoxLayout(root, BoxLayout.Y_AXIS)); + window.setContentPane(root); + + drawZone = new Dessin(); + root.add(drawZone); + + wordLabel = createWordLabel(); + root.add(wordLabel); + + JPanel inputPanel = createInputPanel(); + root.add(inputPanel); + + window.setVisible(true); + letterInput.requestFocusInWindow(); + } + + // --- Initialisation fenêtre --- + private void setupWindow() { + window = new JFrame("Jeu du Pendu"); + window.setSize(600, 600); + window.setLocationRelativeTo(null); + window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + } + + // --- Sous-composants UI --- + private JLabel createWordLabel() { + JLabel label = new JLabel("_ _ _ _ _", SwingConstants.CENTER); + label.setFont(new Font("Segoe UI", Font.BOLD, 32)); + label.setBorder(BorderFactory.createEmptyBorder(20, 10, 20, 10)); + label.setAlignmentX(Component.CENTER_ALIGNMENT); + return label; + } + + private JPanel createInputPanel() { + JPanel inputPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 10)); + JLabel prompt = new JLabel("Entrez une lettre :"); + + letterInput = new JTextField(2); + letterInput.setHorizontalAlignment(JTextField.CENTER); + letterInput.setFont(new Font("Segoe UI", Font.BOLD, 24)); + + sendButton = new JButton("Envoyer"); + + inputPanel.add(prompt); + inputPanel.add(letterInput); + inputPanel.add(sendButton); + return inputPanel; + } + + // --- Getters pour Event --- + public JFrame getWindow() { return window; } + public JTextField getLetterInput() { return letterInput; } + public JButton getSendButton() { return sendButton; } + public JLabel getWordLabel() { return wordLabel; } + public JPanel getDrawZone() { return drawZone; } + + // --- Méthode principale de test --- + public static void main(String[] args) { + SwingUtilities.invokeLater(() -> { + Fenetre f = new Fenetre(); + // On passe le handler directement ici (pas de setOnLetterSubmitted) + new Event(f, ch -> + JOptionPane.showMessageDialog(f.getWindow(), "Lettre reçue : " + ch + " (sans logique de jeu)") + ); + }); + } +} \ No newline at end of file