mirror of
https://github.com/lov3b/PlingPong.git
synced 2025-01-18 12:50:13 +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