mirror of
https://github.com/lov3b/PlingPong.git
synced 2025-01-18 04:40:14 +01:00
initial
This commit is contained in:
commit
4f72ad85e7
38
.gitignore
vendored
Normal file
38
.gitignore
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea/modules.xml
|
||||
.idea/jarRepositories.xml
|
||||
.idea/compiler.xml
|
||||
.idea/libraries/
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
8
.idea/.gitignore
generated
vendored
Normal file
8
.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
7
.idea/encodings.xml
generated
Normal file
7
.idea/encodings.xml
generated
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||
</component>
|
||||
</project>
|
14
.idea/misc.xml
generated
Normal file
14
.idea/misc.xml
generated
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="MavenProjectsManager">
|
||||
<option name="originalFiles">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/pom.xml" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="temurin-1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
124
.idea/uiDesigner.xml
generated
Normal file
124
.idea/uiDesigner.xml
generated
Normal file
@ -0,0 +1,124 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Palette2">
|
||||
<group name="Swing">
|
||||
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
|
||||
</item>
|
||||
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
|
||||
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
|
||||
<initial-values>
|
||||
<property name="text" value="Button" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="RadioButton" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="CheckBox" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="Label" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
|
||||
<preferred-size width="-1" height="20" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
|
||||
</item>
|
||||
</group>
|
||||
</component>
|
||||
</project>
|
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
98
pom.xml
Normal file
98
pom.xml
Normal file
@ -0,0 +1,98 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.billenius</groupId>
|
||||
<artifactId>plingpong</artifactId>
|
||||
<version>1.0</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains</groupId>
|
||||
<artifactId>annotations</artifactId>
|
||||
<version>24.0.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-clean-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>3.0.2</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.22.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-install-plugin</artifactId>
|
||||
<version>2.5.2</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<version>2.8.2</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-site-plugin</artifactId>
|
||||
<version>3.7.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-project-info-reports-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>com.billenius.Main</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<addClasspath>true</addClasspath>
|
||||
<mainClass>com.billenius.Main</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
7
src/main/java/com/billenius/GetDimension.java
Normal file
7
src/main/java/com/billenius/GetDimension.java
Normal file
@ -0,0 +1,7 @@
|
||||
package com.billenius;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public interface GetDimension {
|
||||
Dimension get();
|
||||
}
|
32
src/main/java/com/billenius/Main.java
Normal file
32
src/main/java/com/billenius/Main.java
Normal file
@ -0,0 +1,32 @@
|
||||
package com.billenius;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
|
||||
public class Main extends JFrame {
|
||||
public Main() throws HeadlessException {
|
||||
super("Pling Pong!");
|
||||
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
setContentPane(new Pong(this));
|
||||
pack();
|
||||
setVisible(true);
|
||||
|
||||
Timer timer = new Timer(10, e -> {
|
||||
repaint();
|
||||
});
|
||||
timer.start();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
try {
|
||||
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
} catch (UnsupportedLookAndFeelException | ClassNotFoundException | InstantiationException |
|
||||
IllegalAccessException ignored) {
|
||||
}
|
||||
new Main();
|
||||
});
|
||||
}
|
||||
}
|
93
src/main/java/com/billenius/Pong.java
Normal file
93
src/main/java/com/billenius/Pong.java
Normal file
@ -0,0 +1,93 @@
|
||||
package com.billenius;
|
||||
|
||||
import com.billenius.VisibleObjects.*;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
|
||||
public class Pong extends PongBackground implements KeyListener, ComponentListener {
|
||||
private final PlayerPaddle[] playerPaddles = new PlayerPaddle[2];
|
||||
private final VisibleObject[] visibleObjects;
|
||||
|
||||
public Pong(JFrame root) {
|
||||
setPreferredSize(new Dimension(800, 600));
|
||||
setFocusable(true);
|
||||
addKeyListener(this);
|
||||
addComponentListener(this);
|
||||
playerPaddles[0] = new PlayerPaddle(Side.LEFT, this::getSize);
|
||||
playerPaddles[1] = new PlayerPaddle(Side.RIGHT, this::getSize);
|
||||
Score score = new Score(this::getSize, 5, (playerWon) -> {
|
||||
String[] choices = new String[]{"Yes", "No"};
|
||||
deSpawnAll();
|
||||
int choice = JOptionPane.showOptionDialog(this,
|
||||
String.format("Player %d won. Do you want to play again?", playerWon + 1),
|
||||
"Game Finished",
|
||||
JOptionPane.YES_NO_OPTION,
|
||||
JOptionPane.QUESTION_MESSAGE,
|
||||
null,
|
||||
choices,
|
||||
choices[1]
|
||||
);
|
||||
if (choice == 0)
|
||||
spawnAll();
|
||||
else {
|
||||
root.dispatchEvent(new WindowEvent(root, WindowEvent.WINDOW_CLOSING));
|
||||
}
|
||||
});
|
||||
Ball ball = new Ball(this::getSize, playerPaddles, score);
|
||||
visibleObjects = new VisibleObject[]{playerPaddles[0], playerPaddles[1], ball, score};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
Graphics2D g2 = (Graphics2D) g;
|
||||
for (VisibleObject visibleObject : visibleObjects)
|
||||
visibleObject.paint(g2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyTyped(KeyEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e) {
|
||||
for (PlayerPaddle playerPaddle : playerPaddles)
|
||||
playerPaddle.startMoving(e.getKeyCode());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyReleased(KeyEvent e) {
|
||||
for (PlayerPaddle playerPaddle : playerPaddles)
|
||||
playerPaddle.stopMoving(e.getKeyCode());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void componentResized(ComponentEvent e) {
|
||||
spawnAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void componentMoved(ComponentEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void componentShown(ComponentEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void componentHidden(ComponentEvent e) {
|
||||
}
|
||||
|
||||
private void spawnAll() {
|
||||
for (VisibleObject visibleObject : visibleObjects)
|
||||
visibleObject.spawn();
|
||||
}
|
||||
|
||||
private void deSpawnAll() {
|
||||
for (VisibleObject visibleObject : visibleObjects)
|
||||
visibleObject.deSpawn();
|
||||
}
|
||||
|
||||
}
|
43
src/main/java/com/billenius/PongBackground.java
Normal file
43
src/main/java/com/billenius/PongBackground.java
Normal file
@ -0,0 +1,43 @@
|
||||
package com.billenius;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.geom.Point2D;
|
||||
|
||||
public class PongBackground extends JPanel {
|
||||
private static final int DASH_LENGTH = 10;
|
||||
private static final int DASH_SPACE = 10;
|
||||
private static final Color STRIPES_BACKGROUND = new Color(Color.WHITE.getRed(), Color.WHITE.getGreen(), Color.WHITE.getBlue(), 100);
|
||||
|
||||
@NotNull
|
||||
private RadialGradientPaint getRadialGradientPaint() {
|
||||
double radius = Math.sqrt(Math.pow(getWidth() / 2d, 2) + Math.pow(getHeight() / 2d, 2));
|
||||
|
||||
// Bright in center, dark in corners
|
||||
return new RadialGradientPaint(
|
||||
new Point2D.Double(getWidth() / 2d, getHeight() / 2d),
|
||||
(float) radius,
|
||||
new float[]{0f, 1f},
|
||||
new Color[]{Color.BLUE.brighter(), Color.BLUE.darker().darker().darker().darker()}
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
Graphics2D g2d = (Graphics2D) g.create();
|
||||
|
||||
RadialGradientPaint radialGradientPaint = getRadialGradientPaint();
|
||||
g2d.setPaint(radialGradientPaint);
|
||||
g2d.fillRect(0, 0, getWidth(), getHeight());
|
||||
|
||||
// Draw the dashed line
|
||||
g2d.setColor(STRIPES_BACKGROUND);
|
||||
g2d.setStroke(new BasicStroke(3, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0, new float[]{DASH_LENGTH, DASH_SPACE}, 0));
|
||||
g2d.drawLine(getWidth() / 2, 0, getWidth() / 2, getHeight());
|
||||
|
||||
g2d.dispose();
|
||||
}
|
||||
}
|
10
src/main/java/com/billenius/Utils.java
Normal file
10
src/main/java/com/billenius/Utils.java
Normal file
@ -0,0 +1,10 @@
|
||||
package com.billenius;
|
||||
|
||||
public class Utils {
|
||||
public static boolean arrayContains(int[] array, int toCheck){
|
||||
for (int value : array)
|
||||
if (value == toCheck)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
5
src/main/java/com/billenius/Vector2D/BumpType.java
Normal file
5
src/main/java/com/billenius/Vector2D/BumpType.java
Normal file
@ -0,0 +1,5 @@
|
||||
package com.billenius.Vector2D;
|
||||
|
||||
public enum BumpType {
|
||||
WALL, PADDLE, BOTH;
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package com.billenius.Vector2D;
|
||||
|
||||
public enum PaddleDirection {
|
||||
UP, NOT_MOVING, DOWN
|
||||
}
|
64
src/main/java/com/billenius/Vector2D/Vector2D.java
Normal file
64
src/main/java/com/billenius/Vector2D/Vector2D.java
Normal file
@ -0,0 +1,64 @@
|
||||
package com.billenius.Vector2D;
|
||||
|
||||
import com.billenius.VisibleObjects.Side;
|
||||
import com.billenius.VisibleObjects.Wall;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Random;
|
||||
|
||||
public class Vector2D {
|
||||
private static final Random random = new Random();
|
||||
private static final double HYPOTENUSE = 2;
|
||||
double x, y;
|
||||
|
||||
/**
|
||||
* Creates a vector and randomizes the angle
|
||||
*/
|
||||
public Vector2D() {
|
||||
double angle = Math.toRadians(random.nextFloat() % 60 - 30);
|
||||
int sign = random.nextBoolean() ? 1 : -1;
|
||||
x = Math.cos(angle) * HYPOTENUSE * sign;
|
||||
y = Math.sin(angle) * HYPOTENUSE * sign;
|
||||
}
|
||||
|
||||
|
||||
public void bump(@NotNull BumpType bumpType, @Nullable PaddleDirection paddleDirection) {
|
||||
if (bumpType == BumpType.BOTH) {
|
||||
x = -x;
|
||||
y = -y;
|
||||
} else if (bumpType == BumpType.WALL) {
|
||||
y = -y;
|
||||
} else if (bumpType == BumpType.PADDLE) {
|
||||
x = -x;
|
||||
double angle = 0;
|
||||
if (paddleDirection != PaddleDirection.NOT_MOVING) {
|
||||
double degrees = random.nextDouble() % 5 + 15;
|
||||
degrees *= paddleDirection == PaddleDirection.UP ? -1 : 1;
|
||||
angle = Math.toRadians(degrees);
|
||||
|
||||
// Adjusting y direction based on the angle
|
||||
y = Math.sin(angle) * HYPOTENUSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This will modify the Point
|
||||
*/
|
||||
public void applyVector(Point point) {
|
||||
point.x += (int) Math.round(x);
|
||||
point.y += (int) Math.round(y);
|
||||
}
|
||||
|
||||
public Side horizontalDirection() {
|
||||
return x > 0 ? Side.RIGHT : Side.LEFT;
|
||||
}
|
||||
|
||||
public Wall verticalDirection() {
|
||||
return y > 0 ? Wall.DOWN : Wall.UP;
|
||||
}
|
||||
|
||||
}
|
||||
|
118
src/main/java/com/billenius/VisibleObjects/Ball.java
Normal file
118
src/main/java/com/billenius/VisibleObjects/Ball.java
Normal file
@ -0,0 +1,118 @@
|
||||
package com.billenius.VisibleObjects;
|
||||
|
||||
import com.billenius.GetDimension;
|
||||
import com.billenius.Vector2D.BumpType;
|
||||
import com.billenius.Vector2D.Vector2D;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
import static java.util.Objects.nonNull;
|
||||
|
||||
public class Ball implements VisibleObject {
|
||||
private static final int RADIUS = 12;
|
||||
private static final Color COLOR = Color.WHITE;
|
||||
Vector2D vector = null;
|
||||
/** NULL before the ball is spawned */
|
||||
Point point = null;
|
||||
GetDimension gameDimension;
|
||||
PlayerPaddle[] playerPaddles;
|
||||
Score score;
|
||||
|
||||
public Ball(GetDimension gameDimension, PlayerPaddle[] playerPaddles, Score score) {
|
||||
this.gameDimension = gameDimension;
|
||||
this.playerPaddles = playerPaddles;
|
||||
this.score = score;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawn() {
|
||||
Dimension dimension = gameDimension.get();
|
||||
point = new Point(dimension.width / 2, dimension.height / 2);
|
||||
vector = new Vector2D();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSpawned() {
|
||||
return point != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deSpawn() {
|
||||
point = null;
|
||||
vector = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint(Graphics2D g2) {
|
||||
if (!isSpawned())
|
||||
return;
|
||||
Side scored = sideScored();
|
||||
if (nonNull(scored)){
|
||||
score.incrementPlayerScore(scored.toInt());
|
||||
spawn();
|
||||
return;
|
||||
}
|
||||
move();
|
||||
vector.applyVector(point);
|
||||
Stroke stroke = g2.getStroke();
|
||||
|
||||
g2.setStroke(new BasicStroke(0));
|
||||
g2.setColor(COLOR);
|
||||
g2.fillOval(point.x, point.y, RADIUS, RADIUS);
|
||||
g2.setStroke(stroke);
|
||||
}
|
||||
|
||||
private @Nullable Side sideScored() {
|
||||
Dimension dimension = gameDimension.get();
|
||||
if (point.x >= dimension.width)
|
||||
return Side.LEFT;
|
||||
if (point.x <= 0)
|
||||
return Side.RIGHT;
|
||||
return null;
|
||||
}
|
||||
|
||||
public void move() {
|
||||
Wall wall = collidedWithWall();
|
||||
PlayerPaddle paddle = collidedWithPaddle(playerPaddles);
|
||||
|
||||
if (nonNull(wall) && nonNull(paddle)) vector.bump(BumpType.BOTH, null);
|
||||
else if (nonNull(wall) && vector.verticalDirection() == wall) {
|
||||
vector.bump(BumpType.WALL, null);
|
||||
} else if (nonNull(paddle) && vector.horizontalDirection() == paddle.getSide()) {
|
||||
vector.bump(BumpType.PADDLE, paddle.getPaddleDirection());
|
||||
} else vector.applyVector(point);
|
||||
}
|
||||
|
||||
|
||||
@Nullable PlayerPaddle collidedWithPaddle(PlayerPaddle[] playerPaddles) {
|
||||
for (PlayerPaddle playerPaddle : playerPaddles) {
|
||||
int paddleX = playerPaddle.getX();
|
||||
int paddleY = playerPaddle.getY();
|
||||
int paddleWidth = playerPaddle.getWidth();
|
||||
int paddleHeight = playerPaddle.getHeight();
|
||||
|
||||
// Check if the ball is within the x and y range of the paddle
|
||||
if (point.x + RADIUS >= paddleX && point.x - RADIUS <= paddleX + paddleWidth / 2 &&
|
||||
point.y + RADIUS >= paddleY && point.y - RADIUS <= paddleY + paddleHeight) {
|
||||
return playerPaddle;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
protected int getHeight() {
|
||||
return RADIUS;
|
||||
}
|
||||
|
||||
public @Nullable Wall collidedWithWall() {
|
||||
Dimension dimension = gameDimension.get();
|
||||
if (point.y <= 0)
|
||||
return Wall.UP;
|
||||
if (point.y + getHeight() >= dimension.height)
|
||||
return Wall.DOWN;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
114
src/main/java/com/billenius/VisibleObjects/PlayerPaddle.java
Normal file
114
src/main/java/com/billenius/VisibleObjects/PlayerPaddle.java
Normal file
@ -0,0 +1,114 @@
|
||||
package com.billenius.VisibleObjects;
|
||||
|
||||
import com.billenius.GetDimension;
|
||||
import com.billenius.Utils;
|
||||
import com.billenius.Vector2D.PaddleDirection;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.KeyEvent;
|
||||
|
||||
public class PlayerPaddle implements VisibleObject {
|
||||
|
||||
protected static final int height = 80, width = 20;
|
||||
private static final int MOVE_PER_TICK = 5;
|
||||
private final int[] upDown;
|
||||
private final Color color;
|
||||
private boolean movingDown = false, movingUp = false;
|
||||
private final GetDimension gameDimension;
|
||||
private final Side side;
|
||||
private int y = Integer.MIN_VALUE;
|
||||
|
||||
public PlayerPaddle(Side side, GetDimension gameDimension) {
|
||||
upDown = getUpDown(side);
|
||||
this.gameDimension = gameDimension;
|
||||
this.side = side;
|
||||
color = (side == Side.LEFT ? Color.YELLOW : Color.RED).brighter().brighter();
|
||||
}
|
||||
|
||||
|
||||
protected int getX() {
|
||||
if (side == Side.LEFT)
|
||||
return 0;
|
||||
return gameDimension.get().width - width;
|
||||
}
|
||||
|
||||
protected int getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
private static int[] getUpDown(Side side) {
|
||||
return side == Side.LEFT ? new int[]{KeyEvent.VK_W, KeyEvent.VK_S} : new int[]{KeyEvent.VK_UP, KeyEvent.VK_DOWN};
|
||||
}
|
||||
|
||||
|
||||
public void paint(Graphics2D g2) {
|
||||
if (!isSpawned())
|
||||
return;
|
||||
move();
|
||||
g2.setColor(color);
|
||||
g2.fillRect(getX(), getY(), width, height);
|
||||
}
|
||||
|
||||
protected int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
protected int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
private void move() {
|
||||
// We can't move both up and down. Don't move if we are down
|
||||
if (movingUp && movingDown)
|
||||
return;
|
||||
|
||||
boolean canMoveDown = getY() + getHeight() < gameDimension.get().getHeight();
|
||||
boolean canMoveUp = getY() > 0;
|
||||
if (movingUp && canMoveUp)
|
||||
y -= MOVE_PER_TICK;
|
||||
else if (movingDown && canMoveDown)
|
||||
y += MOVE_PER_TICK;
|
||||
}
|
||||
|
||||
public void startMoving(int keyCode) {
|
||||
if (!Utils.arrayContains(upDown, keyCode))
|
||||
return;
|
||||
if (keyCode == upDown[0])
|
||||
movingUp = true;
|
||||
else movingDown = true;
|
||||
}
|
||||
|
||||
public void stopMoving(int keyCode) {
|
||||
if (!Utils.arrayContains(upDown, keyCode))
|
||||
return;
|
||||
movingUp = false;
|
||||
movingDown = false;
|
||||
}
|
||||
|
||||
protected PaddleDirection getPaddleDirection() {
|
||||
if (movingUp != movingDown)
|
||||
return PaddleDirection.NOT_MOVING;
|
||||
else if (movingUp)
|
||||
return PaddleDirection.UP;
|
||||
return PaddleDirection.DOWN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawn() {
|
||||
y = gameDimension.get().height / 2 - height / 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSpawned() {
|
||||
return getY() != Integer.MIN_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deSpawn() {
|
||||
y = Integer.MIN_VALUE;
|
||||
}
|
||||
|
||||
public Side getSide() {
|
||||
return side;
|
||||
}
|
||||
}
|
88
src/main/java/com/billenius/VisibleObjects/Score.java
Normal file
88
src/main/java/com/billenius/VisibleObjects/Score.java
Normal file
@ -0,0 +1,88 @@
|
||||
package com.billenius.VisibleObjects;
|
||||
|
||||
import com.billenius.GetDimension;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class Score implements VisibleObject {
|
||||
private static final Color COLOR = Color.BLUE.brighter().brighter().brighter();
|
||||
private final int[] playerScores = new int[]{0, 0};
|
||||
private final int winningScore;
|
||||
private final WinAction winAction;
|
||||
private final GetDimension gameDimension;
|
||||
private boolean spawned = false;
|
||||
|
||||
public Score(GetDimension gameDimension, int winningScore, WinAction winAction) {
|
||||
this.gameDimension = gameDimension;
|
||||
this.winAction = winAction;
|
||||
this.winningScore = winningScore;
|
||||
}
|
||||
|
||||
public void incrementPlayerScore(int player) {
|
||||
playerScores[player]++;
|
||||
int playerWon = playerHasWon();
|
||||
if (playerWon != -1)
|
||||
winAction.run(playerWon);
|
||||
}
|
||||
|
||||
public int playerHasWon() {
|
||||
for (int i = 0; i < playerScores.length; i++) {
|
||||
if (playerScores[i] == winningScore) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void spawn() {
|
||||
spawned = true;
|
||||
Arrays.fill(playerScores, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSpawned() {
|
||||
return spawned;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deSpawn() {
|
||||
spawned = false;
|
||||
}
|
||||
|
||||
private static final Color SHADOW_COLOR = Color.GRAY;
|
||||
private static final Color TEXT_COLOR = Color.WHITE;
|
||||
private static final int SHADOW_OFFSET = 3;
|
||||
|
||||
public void paint(Graphics2D g2) {
|
||||
if (!isSpawned())
|
||||
return;
|
||||
/* We don't want to have the minus anywhere else than the in the middle */
|
||||
String measure = "0 - 0";
|
||||
String score = String.format("%d - %d", playerScores[0], playerScores[1]);
|
||||
|
||||
g2.setColor(SHADOW_COLOR);
|
||||
Font font = g2.getFont().deriveFont(Font.BOLD, 42f);
|
||||
g2.setFont(font);
|
||||
FontMetrics metrics = g2.getFontMetrics();
|
||||
int width = metrics.stringWidth(measure);
|
||||
int height = metrics.getHeight();
|
||||
int x = gameDimension.get().width / 2 - width / 2;
|
||||
int y = height - 3;
|
||||
|
||||
// Draw shadow
|
||||
g2.setColor(SHADOW_COLOR);
|
||||
g2.drawString(score, x + SHADOW_OFFSET, y + SHADOW_OFFSET);
|
||||
|
||||
// Create gradient from white to yellow from left to right across the text
|
||||
GradientPaint gradient = new GradientPaint(
|
||||
x, y, Color.YELLOW.brighter().brighter(), // start point for gradient (left edge of text)
|
||||
x + width, y, Color.RED.brighter().brighter()); // end point for gradient (right edge of text)
|
||||
|
||||
// Apply gradient and draw text
|
||||
g2.setPaint(gradient);
|
||||
g2.drawString(score, x, y);
|
||||
}
|
||||
}
|
16
src/main/java/com/billenius/VisibleObjects/Side.java
Normal file
16
src/main/java/com/billenius/VisibleObjects/Side.java
Normal file
@ -0,0 +1,16 @@
|
||||
package com.billenius.VisibleObjects;
|
||||
|
||||
public enum Side {
|
||||
LEFT(0), RIGHT(1);
|
||||
|
||||
private final int value;
|
||||
|
||||
Side(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int toInt() {
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package com.billenius.VisibleObjects;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public interface VisibleObject {
|
||||
void spawn();
|
||||
|
||||
boolean isSpawned();
|
||||
void deSpawn();
|
||||
|
||||
void paint(Graphics2D g2);
|
||||
|
||||
}
|
5
src/main/java/com/billenius/VisibleObjects/Wall.java
Normal file
5
src/main/java/com/billenius/VisibleObjects/Wall.java
Normal file
@ -0,0 +1,5 @@
|
||||
package com.billenius.VisibleObjects;
|
||||
|
||||
public enum Wall {
|
||||
UP, DOWN;
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package com.billenius.VisibleObjects;
|
||||
|
||||
public interface WinAction {
|
||||
void run(int playerWon);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user