Score.java - Score Display
The Score class manages the game scoreboard, tracking points for both players and rendering the score display with a center divider line.
Purpose: Tracks player scores and renders the scoreboard display with proper formatting and visual design.
Source Code
 1import java.awt.*;
 2
 3public class Score extends Rectangle{
 4    static int GAME_WIDTH;
 5    static int GAME_HEIGHT;
 6    int player1;
 7    int player2;
 8
 9    Score(int GAME_WIDTH, int GAME_HEIGHT){
10        Score.GAME_WIDTH = GAME_WIDTH;
11        Score.GAME_HEIGHT = GAME_HEIGHT;
12    }
13    
14    public void draw(Graphics g){
15        g.setColor(Color.white);
16        g.setFont(new Font("Consolas", Font.PLAIN, 60));
17        g.drawLine(GAME_WIDTH/2, 0, GAME_WIDTH/2, GAME_HEIGHT);
18        g.drawString(String.valueOf(player1/10)+String.valueOf(player1%10), (GAME_WIDTH/2)-85, 50);
19        g.drawString(String.valueOf(player2/10)+String.valueOf(player2%10), (GAME_WIDTH/2)+20, 50);
20    }
21}Code Analysis
Class Design
Static Field Usage
1static int GAME_WIDTH;
2static int GAME_HEIGHT;Static Fields for Dimensions:
- Shared State: All Score instances use same game dimensions
- Memory Efficiency: Only one copy of dimensions needed
- Global Access: Can be accessed without instance reference
- Initialization: Set once in constructor, used in drawing
Constructor Assignment:
1Score(int GAME_WIDTH, int GAME_HEIGHT){
2    Score.GAME_WIDTH = GAME_WIDTH;    // Assign to static field
3    Score.GAME_HEIGHT = GAME_HEIGHT;  // Using class name prefix
4}Score Storage
1int player1;  // Player 1's current score
2int player2;  // Player 2's current scoreScore Management:
- Integer Counters: Simple increment system
- Default Initialization: Both start at 0
- Public Access: GamePanel directly modifies these fields
- No Upper Limit: Scores can increment indefinitely
Rendering System
Visual Layout Design
 1public void draw(Graphics g){
 2    g.setColor(Color.white);
 3    g.setFont(new Font("Consolas", Font.PLAIN, 60));
 4    
 5    // Center divider line
 6    g.drawLine(GAME_WIDTH/2, 0, GAME_WIDTH/2, GAME_HEIGHT);
 7    
 8    // Player scores positioned relative to center
 9    g.drawString(player1Score, (GAME_WIDTH/2)-85, 50);  // Left of center
10    g.drawString(player2Score, (GAME_WIDTH/2)+20, 50);  // Right of center
11}Layout Elements:
- Center Line: Vertical divider separating player sides
- Font Choice: “Consolas” monospace font for consistent character width
- Font Size: Large 60pt for clear visibility during gameplay
- Positioning: Scores positioned symmetrically around center line
Score Formatting Logic
1String.valueOf(player1/10) + String.valueOf(player1%10)Two-Digit Display System:
- Tens Digit: player1/10- Integer division gives tens place
- Ones Digit: player1%10- Modulo gives remainder (ones place)
- Always 2 Digits: Ensures “05” instead of “5” for single digits
- String Concatenation: Combines digits into display string
Examples:
1Score = 7:  7/10=0, 7%10=7  → "0" + "7" = "07"
2Score = 15: 15/10=1, 15%10=5 → "1" + "5" = "15"
3Score = 23: 23/10=2, 23%10=3 → "2" + "3" = "23"Graphics Programming Concepts
Font and Typography
1g.setFont(new Font("Consolas", Font.PLAIN, 60));Font Configuration:
- Font Family: “Consolas” - monospace font for digital aesthetic
- Font Style: Font.PLAIN- no bold or italic styling
- Font Size: 60 points - large enough for game visibility
- Monospace Advantage: All digits have same width for consistent alignment
Alternative Font Options:
1new Font("Arial", Font.BOLD, 60);        // Bold sans-serif
2new Font("Courier New", Font.PLAIN, 60); // Alternative monospace
3new Font(Font.MONOSPACED, Font.PLAIN, 60); // System default monospaceCoordinate System
1// Center line coordinates
2g.drawLine(GAME_WIDTH/2, 0, GAME_WIDTH/2, GAME_HEIGHT);
3
4// Score positioning
5g.drawString(score, (GAME_WIDTH/2)-85, 50);  // Player 1
6g.drawString(score, (GAME_WIDTH/2)+20, 50);  // Player 2Positioning Strategy:
- Center Reference: All positioning relative to GAME_WIDTH/2
- Vertical Line: From top (y=0) to bottom (y=GAME_HEIGHT)
- Text Baseline: Y=50 positions text near top of screen
- Horizontal Offset: -85 and +20 create symmetric spacing around center
Integration with Game System
Score Updates
The GamePanel updates scores directly when goals occur:
 1// In GamePanel.checkCollision():
 2if(ball.x <= 0) {
 3    score.player2++;  // Player 2 scores
 4    newPaddles();
 5    newBall();
 6    System.out.println("Player 2: " + score.player2);
 7}
 8if(ball.x >= GAME_WIDTH - BALL_DIAMETER) {
 9    score.player1++;  // Player 1 scores  
10    newPaddles();
11    newBall();
12    System.out.println("Player 1: " + score.player1);
13}Scoring Logic:
- Left Goal: Ball exits left side → Player 2 scores
- Right Goal: Ball exits right side → Player 1 scores
- Immediate Update: Score incremented directly
- Game Reset: New ball and paddles created after each goal
Design Patterns and Architecture
Observer Pattern (Implicit)
- Score Display: Automatically reflects current game state
- No Notifications: Direct field access instead of events
- Simple Coupling: GamePanel modifies, Score displays
Utility Class Pattern
- Single Responsibility: Only handles score display
- Stateless Rendering: Draw method has no side effects
- Configuration Storage: Holds display parameters
Enhancement Ideas
Advanced Score Features
 1public class EnhancedScore extends Rectangle {
 2    private int player1, player2;
 3    private int winningScore = 11;
 4    private long lastScoreTime;
 5    private boolean gameWon = false;
 6    private String winnerName = "";
 7    
 8    public void incrementPlayer1() {
 9        player1++;
10        lastScoreTime = System.currentTimeMillis();
11        checkForWin();
12    }
13    
14    public void incrementPlayer2() {
15        player2++;
16        lastScoreTime = System.currentTimeMillis();
17        checkForWin();
18    }
19    
20    private void checkForWin() {
21        if(player1 >= winningScore) {
22            gameWon = true;
23            winnerName = "Player 1";
24        } else if(player2 >= winningScore) {
25            gameWon = true;
26            winnerName = "Player 2";
27        }
28    }
29    
30    public void draw(Graphics g) {
31        // Draw normal score
32        drawScore(g);
33        
34        // Flash recent scores
35        if(System.currentTimeMillis() - lastScoreTime < 1000) {
36            g.setColor(Color.YELLOW);
37            // Highlight recent score
38        }
39        
40        // Display winner
41        if(gameWon) {
42            g.setColor(Color.GREEN);
43            g.setFont(new Font("Arial", Font.BOLD, 40));
44            g.drawString(winnerName + " Wins!", GAME_WIDTH/2 - 100, 150);
45        }
46    }
47}Visual Improvements
 1public void draw(Graphics g) {
 2    // Gradient background for score area
 3    Graphics2D g2d = (Graphics2D) g;
 4    GradientPaint gradient = new GradientPaint(
 5        0, 0, Color.BLACK,
 6        0, 80, new Color(30, 30, 30)
 7    );
 8    g2d.setPaint(gradient);
 9    g2d.fillRect(0, 0, GAME_WIDTH, 80);
10    
11    // Animated center line
12    g.setColor(Color.WHITE);
13    for(int i = 0; i < GAME_HEIGHT; i += 20) {
14        if((System.currentTimeMillis() / 100 + i) % 40 < 20) {
15            g.fillRect(GAME_WIDTH/2 - 2, i, 4, 10);
16        }
17    }
18    
19    // Shadow effect for text
20    g.setFont(new Font("Consolas", Font.BOLD, 60));
21    g.setColor(Color.DARK_GRAY);
22    g.drawString(player1String, (GAME_WIDTH/2)-83, 52); // Shadow
23    g.setColor(Color.WHITE);
24    g.drawString(player1String, (GAME_WIDTH/2)-85, 50); // Main text
25}Study Questions
- Memory Management: Why use static fields for game dimensions?
- String Formatting: What’s the purpose of the complex score formatting logic?
- Architecture: How could you implement score limits or win conditions?
- Performance: Is creating new Font objects every frame efficient?
Common Issues and Solutions
Potential Issues:
- Large Numbers: Score formatting breaks for scores > 99
- Font Loading: Font may not be available on all systems
- Performance: String concatenation in drawing loop
- Positioning: Hard-coded offsets may not work with different fonts
Solutions:
- Use String.format("%02d", score)for better formatting
- Check font availability and provide fallbacks
- Pre-format score strings outside draw method
- Calculate text bounds for dynamic positioning
Summary: This completes the Pong game architecture! The Score class demonstrates simple state management, string formatting, and graphics programming concepts essential for game UI development.