Welcome to the Java Programming Forums

The professional, friendly Java community. 21,500 members and growing!

The Java Programming Forums are a community of Java programmers from all around the World. Our members have a wide range of skills and they all have one thing in common: A passion to learn and code Java. We invite beginner Java programmers right through to Java professionals to post here and share your knowledge. Become a part of the community, help others, expand your knowledge of Java and enjoy talking with like minded people. Registration is quick and best of all free. We look forward to meeting you.

>> REGISTER NOW TO START POSTING

# Thread: Running ChainRXN like game

1. ## Running ChainRXN like game

I can't quite seem to get this code to work correctly. This example is from User:Ciancun on github

I think I have it fairly close to working, which is why I'm posting here rather than giving up on it. In the code, it is left to the user how to define the game logic in the main class. I'll show you how I tried to do it below. Unfortunately, the designer seems to have become fairly inactive, so contacting him directly doesn't seem promising.

```package ball;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;

import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import gui.RxnPanel;

public class Ball {

private float x;
private float y;
private float sX;
private float sY;

private final transient Ellipse2D.Float ellipse = new Ellipse2D.Float();

private static float initialRadius = 6f;
private static float finalRadius = 40f;
private static long expandDuration = 900000000L; // 1.5 sec expand

static double getInitialRadius() {
}

}

static double getFinalRadius() {
}

}

static long getExpandDuration() {
return expandDuration;
}

public static void setExpandDuration(int expandDuration) {
Ball.expandDuration = (long) ((expandDuration / 1000f + 0.5f)*1000000000);
}

private int chainCount;
private long explodeTime;
private long lastUpdateTime;
private Color color;
private boolean ended;

BallManager manager;

public int getChainCount() {
return chainCount;
}

Ball(float x, float y, float sX, float sY, Color color) {
this(x, y, sX, sY, color, 0);
}

Ball(float x, float y, float sX, float sY, Color color, long explodeTime) {
this.x = x;
this.y = y;
this.sX = sX;
this.sY = sY;
this.explodeTime = explodeTime;
this.chainCount = 0;
this.color = new Color(color.getRed(), color.getGreen(), color.getBlue(),
127);
this.ended = false;
}

public boolean isExploded() {
return explodeTime != 0;
}

private void move(long time) {
if (lastUpdateTime == 0) {
return;
}
long delta = time - lastUpdateTime;
x += delta * sX;
y += delta * sY;

Rectangle boundries = manager.getBoundries();
if (x < radius) {
x = radius + 0.01f;
sX = -sX;
} else if (x > boundries.width - radius) {
x = boundries.width - radius - 0.01f;
sX = -sX;
}

if (y < radius) {
y = radius + 0.01f;
sY = -sY;
} else if (y > boundries.height - radius) {
y = boundries.height - radius - 0.01f;
sY = -sY;
}

Ball collider = manager.checkCollision(this);
if (collider != null) {
explodeTime = time;
chainCount = collider.chainCount + 1;
manager.informCollision(this);
}
}

private float getExpansionFraction(long time) {
return (float) (time - explodeTime) / expandDuration;
}

private void expand(long time) {
float expansionFraction = getExpansionFraction(time);
if (expansionFraction < 0.75f) {
} else if (expansionFraction < 2f) {
} else if (expansionFraction < 2.33f) {
float inverseFraction = 3 * (2.33f - expansionFraction);
color = new Color(color.getRed(), color.getGreen(), color.getBlue(),
(int) (127 * inverseFraction));
} else {
ended = true;
}
}

public void update(long time) {
if (isExploded()) {
expand(time);
} else {
move(time);
}
ellipse.x = x - radius;
ellipse.y = y - radius;
ellipse.width = ellipse.height = radius * 2;
lastUpdateTime = time;
}

public int getPoint() {
return 100 * chainCount * chainCount * chainCount;
}

public Ellipse2D getBounds() {
return ellipse;
}

public boolean isEnded() {
return ended;
}

public void draw(Graphics2D g) {
if (!ended) {
Color c = g.getColor();
g.setColor(color);
g.fill(getBounds());
if (isExploded() && getPoint() != 0 &&
System.nanoTime() < explodeTime + expandDuration * 0.75) {
String point = "+"+RxnPanel.decimalFormat.format(getPoint());
Rectangle2D bounds = g.getFontMetrics().getStringBounds(point, g);
g.setColor(Color.WHITE);
g.drawString(point, (float) (x - bounds.getWidth()/2),
(float) (y + bounds.getHeight()/2));
}
g.setColor(c);
}
}

}```

```package ball;

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;

import java.util.List;

/**
*
* @author ToGo
*/
public class BallManager implements CollisionListener, Runnable {

private float minSpeed = 0.00000005f;
private float maxSpeed = 0.00000008f;

private final List<CollisionListener> collisionListeners = new LinkedList<CollisionListener>();
private final List<GameEndListener> gameEndListeners = new LinkedList<GameEndListener>();

private final List<Ball> balls = new LinkedList<Ball>();
private final int ballsToExplode;
private final int totalBallCount;

private final Rectangle boundries;

private int totalPoint;
private int nExplodedBalls;

private boolean initiallyClicked;

public void setMaxSpeed(int maxSpeed) {
this.maxSpeed = 0.0000001f * maxSpeed / 1000;
}

public void setMinSpeed(int minSpeed) {
this.minSpeed = 0.0000001f * minSpeed / 1000;
}

public int getTotalPoint() {
}

public int getNExplodedBalls() {
return nExplodedBalls;
}

public int getTotalBallCount() {
}

public BallManager(Rectangle boundries, int maxSpeed, int minSpeed, int totalBallCount, int ballsToExplode) {
this.boundries = boundries;
setMaxSpeed(maxSpeed);
setMinSpeed(minSpeed);
this.initiallyClicked = false;
this.totalBallCount = totalBallCount;
this.ballsToExplode = ballsToExplode;
this.nExplodedBalls = 0;
for (int i = 0; i < totalBallCount; ++i) {
}
}

public void initialClick(int x, int y, long time) {
if (!initiallyClicked) {
Ball ball = new Ball(x, y, 0, 0, new Color(0.5f, 0.5f, 0.5f), time);
ball.manager = this;
initiallyClicked = true;
System.out.println(Ball.getExpandDuration());
}
}

public boolean isInitiallyClicked() {
return initiallyClicked;
}

private Ball createBall() {
float x = (float) (Ball.getInitialRadius() + (boundries.width - 2 * Ball.getInitialRadius()) * Math.random());
float y = (float) (Ball.getInitialRadius() + (boundries.height - 2 * Ball.getInitialRadius()) * Math.random());
double speed = (maxSpeed - minSpeed)*Math.random() + minSpeed;
double angle = 2*Math.PI*Math.random();
float sX = (float) (Math.cos(angle)*speed);
float sY = (float) (Math.sin(angle)*speed);
Color color = new Color(
(int) (255 * Math.random()),
(int) (255 * Math.random()),
(int) (255 * Math.random()));
Ball b = new Ball(x, y, sX, sY, color);
b.manager = this;
return b;
}

public Rectangle getBoundries() {
return boundries;
}

public void update(long time) {
List<Ball> endeds = new LinkedList<Ball>();
synchronized (balls) {
for (Ball b : balls) {
b.update(time);
if (b.isEnded()) {
}
}
balls.removeAll(endeds);
}
boolean gameEnded = initiallyClicked;
for (Ball b : balls) {
if (b.isExploded()) {
gameEnded = false;
break;
}
}
if (gameEnded) {
for (GameEndListener gameEndListener : gameEndListeners) {
gameEndListener.gameEnded(ballsToExplode - nExplodedBalls);
}
stop();
}
}

public boolean isGoalAchieved() {
return ballsToExplode <= nExplodedBalls;
}

public void draw(Graphics2D g) {
synchronized (balls) {
for (Ball b : balls) {
b.draw(g);
}
}
}

Ball checkCollision(Ball ball) {
Shape shape = ball.getBounds();
synchronized (balls) {
for (Ball b : balls) {
if (b.isExploded() && b.getBounds().intersects(shape.getBounds2D())) {
return b;
}
}
}
return null;
}

public void addCollisionListener(CollisionListener listener) {
}

public void addGameEndListener(GameEndListener listener) {
}

void informCollision(Ball ball) {
for (CollisionListener listener : collisionListeners) {
listener.collided(ball);
}
}

public void collided(Ball ball) {
totalPoint += ball.getPoint();
++nExplodedBalls;
}

public void run() {
while(true) {
update(System.nanoTime());
try {
} catch (InterruptedException ex) {
return;
}
}
}

public void stop() {
if (logicThread == null) {
throw new IllegalStateException("Game is not started.");
}
}

}```

```package ball;

public interface CollisionListener {

void collided(Ball ball);

}```

```package ball;

public interface GameEndListener {

void gameEnded(int remainingBalls);

}```

```package gui;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JColorChooser;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

import static java.lang.Integer.*;

/**
*
* @author ToGo
*/
public class OptionPanel extends javax.swing.JFrame {

private Properties properties;

private void load(File file) throws IOException {
properties = new Properties();
if (file.exists()) {
}
minSpeedSlider.setValue(parseInt(properties.getProperty("minSpeed", "500")));
maxSpeedSlider.setValue(parseInt(properties.getProperty("maxSpeed", "800")));
expandTimeSlider.setValue(parseInt(properties.getProperty("expandTime", "400")));
widthField.setText(properties.getProperty("frameWidth", "640"));
heightField.setText(properties.getProperty("frameHeight", "400"));
ballCountField.setText(properties.getProperty("ballCount", "50"));
explodeCountField.setText(properties.getProperty("explodeCount", "34"));
backgroundColorLabel.setBackground(Color.decode(properties.getProperty("background", "0x090507")));
}

private void save(File file) throws IOException {
properties.setProperty("minSpeed", String.valueOf(minSpeedSlider.getValue()));
properties.setProperty("maxSpeed", String.valueOf(maxSpeedSlider.getValue()));
properties.setProperty("expandTime", String.valueOf(expandTimeSlider.getValue()));
properties.setProperty("frameWidth", widthField.getText());
properties.setProperty("frameHeight", heightField.getText());
properties.setProperty("ballCount", ballCountField.getText());
properties.setProperty("explodeCount", explodeCountField.getText());
properties.setProperty("background", toHexString(backgroundColorLabel.getBackground()));
properties.store(new FileOutputStream(file), "");
}

/** Creates new form OptionPanel */
public OptionPanel() {
initComponents();
setLocationRelativeTo(null);
reset();
}

/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {

jPanel1 = new javax.swing.JPanel();
jLabel1 = new javax.swing.JLabel();
maxSpeedSlider = new javax.swing.JSlider();
jLabel2 = new javax.swing.JLabel();
minSpeedSlider = new javax.swing.JSlider();
jLabel3 = new javax.swing.JLabel();
maxRadiusSlider = new javax.swing.JSlider();
jLabel4 = new javax.swing.JLabel();
minRadiusSlider = new javax.swing.JSlider();
jLabel5 = new javax.swing.JLabel();
expandTimeSlider = new javax.swing.JSlider();
jPanel2 = new javax.swing.JPanel();
jLabel6 = new javax.swing.JLabel();
jLabel7 = new javax.swing.JLabel();
widthField = new javax.swing.JTextField();
heightField = new javax.swing.JTextField();
jPanel3 = new javax.swing.JPanel();
jLabel8 = new javax.swing.JLabel();
ballCountField = new javax.swing.JTextField();
jLabel9 = new javax.swing.JLabel();
explodeCountField = new javax.swing.JTextField();
jLabel10 = new javax.swing.JLabel();
backgroundColorLabel = new javax.swing.JLabel();
startButton = new javax.swing.JButton();
loadButton = new javax.swing.JButton();
saveButton = new javax.swing.JButton();
jButton1 = new javax.swing.JButton();

setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setTitle("ChnRxn Configuration");

jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("Ball Properties"));

jLabel1.setText("Max Speed :");

maxSpeedSlider.setMaximum(1000);
maxSpeedSlider.setPaintLabels(true);
maxSpeedSlider.setPaintTicks(true);
maxSpeedSlider.setValue(800);
public void stateChanged(javax.swing.event.ChangeEvent evt) {
maxSpeedSliderStateChanged(evt);
}
});

jLabel2.setText("Min Speed : ");

minSpeedSlider.setMaximum(1000);
minSpeedSlider.setPaintLabels(true);
minSpeedSlider.setPaintTicks(true);
minSpeedSlider.setValue(500);
public void stateChanged(javax.swing.event.ChangeEvent evt) {
minSpeedSliderStateChanged(evt);
}
});

jLabel3.setText("Max Radius : ");

public void stateChanged(javax.swing.event.ChangeEvent evt) {
}
});

jLabel4.setText("Min Radius : ");

public void stateChanged(javax.swing.event.ChangeEvent evt) {
}
});

jLabel5.setText("Fade In/Out Time : ");

expandTimeSlider.setMaximum(1000);
expandTimeSlider.setPaintLabels(true);
expandTimeSlider.setPaintTicks(true);
expandTimeSlider.setValue(425);

javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
.addComponent(maxSpeedSlider, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(minSpeedSlider, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(expandTimeSlider, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))))
);

jPanel1Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {jLabel1, jLabel2, jLabel3, jLabel4, jLabel5});

jPanel1Layout.setVerticalGroup(
.addComponent(maxSpeedSlider, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(minSpeedSlider, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(expandTimeSlider, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
);

jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder("Frame Properties"));

jLabel6.setText("Width : ");

jLabel7.setText("Height : ");

widthField.setText("640");

heightField.setText("400");

javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
jPanel2.setLayout(jPanel2Layout);
jPanel2Layout.setHorizontalGroup(
.addComponent(widthField, javax.swing.GroupLayout.DEFAULT_SIZE, 65, Short.MAX_VALUE))
);

jPanel2Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {jLabel6, jLabel7});

jPanel2Layout.setVerticalGroup(
.addComponent(widthField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(heightField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
);

jPanel3.setBorder(javax.swing.BorderFactory.createTitledBorder("Game Properties"));

jLabel8.setText("Total Number of Balls : ");

ballCountField.setText("54");

jLabel9.setText("Number of Balls to Explode : ");

explodeCountField.setText("40");

jLabel10.setText("Background Color : ");

backgroundColorLabel.setBackground(new java.awt.Color(51, 255, 0));
backgroundColorLabel.setOpaque(true);
public void mouseClicked(java.awt.event.MouseEvent evt) {
backgroundColorLabelMouseClicked(evt);
}
});

javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
jPanel3.setLayout(jPanel3Layout);
jPanel3Layout.setHorizontalGroup(
.addComponent(backgroundColorLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 21, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(ballCountField, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 68, Short.MAX_VALUE)
.addComponent(explodeCountField, javax.swing.GroupLayout.DEFAULT_SIZE, 68, Short.MAX_VALUE))))
);

jPanel3Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {jLabel8, jLabel9});

jPanel3Layout.setVerticalGroup(
.addComponent(ballCountField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(explodeCountField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(backgroundColorLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE))
);

startButton.setText("Start!");
public void actionPerformed(java.awt.event.ActionEvent evt) {
startButtonActionPerformed(evt);
}
});

public void actionPerformed(java.awt.event.ActionEvent evt) {
}
});

saveButton.setText("Save");
public void actionPerformed(java.awt.event.ActionEvent evt) {
saveButtonActionPerformed(evt);
}
});

jButton1.setText("Reset");
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton1ActionPerformed(evt);
}
});

javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
.addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
layout.setVerticalGroup(
.addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
);

pack();
}// </editor-fold>//GEN-END:initComponents

private void startButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_startButtonActionPerformed
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new JFrame("ChnRxn");
final RxnPanel rxnPanel = new RxnPanel(frame);
rxnPanel.restartGame(
expandTimeSlider.getValue(),
minSpeedSlider.getValue(), maxSpeedSlider.getValue(),
Integer.parseInt(ballCountField.getText()),
Integer.parseInt(explodeCountField.getText()),
new Dimension(Integer.parseInt(widthField.getText()),
Integer.parseInt(heightField.getText())),
backgroundColorLabel.getBackground());
@Override
public void windowClosed(WindowEvent e) {
rxnPanel.getManager().stop();
OptionPanel.this.setVisible(true);
}

});
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
this.setVisible(false);
}//GEN-LAST:event_startButtonActionPerformed

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
expandTimeSlider.setValue(400);
minSpeedSlider.setValue(500);
maxSpeedSlider.setValue(800);
ballCountField.setText("50");
explodeCountField.setText("34");
widthField.setText("640");
heightField.setText("400");
backgroundColorLabel.setBackground(Color.decode("0x090507"));
}//GEN-LAST:event_jButton1ActionPerformed

private void maxSpeedSliderStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_maxSpeedSliderStateChanged
if (maxSpeedSlider.getValue() < minSpeedSlider.getValue()) {
maxSpeedSlider.setValue(minSpeedSlider.getValue());
maxSpeedSlider.updateUI();
}
}//GEN-LAST:event_maxSpeedSliderStateChanged

private void minSpeedSliderStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_minSpeedSliderStateChanged
if (minSpeedSlider.getValue() > maxSpeedSlider.getValue()) {
minSpeedSlider.setValue(maxSpeedSlider.getValue());
minSpeedSlider.updateUI();
}
}//GEN-LAST:event_minSpeedSliderStateChanged

}

}

JFileChooser fileChooser = new JFileChooser();
int result = fileChooser.showOpenDialog(this);
if(result == JFileChooser.APPROVE_OPTION) {
File file = fileChooser.getSelectedFile();
try {
} catch (IOException ex) {
Logger.getLogger(OptionPanel.class.getName()).log(Level.SEVERE, null, ex);
}
}

private void saveButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveButtonActionPerformed
JFileChooser fileChooser = new JFileChooser();
int result = fileChooser.showSaveDialog(this);
if(result == JFileChooser.APPROVE_OPTION) {
File file = fileChooser.getSelectedFile();
try {
save(file);
} catch (IOException ex) {
Logger.getLogger(OptionPanel.class.getName()).log(Level.SEVERE, null, ex);
}
}
}//GEN-LAST:event_saveButtonActionPerformed

private void backgroundColorLabelMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_backgroundColorLabelMouseClicked
Color newColor = JColorChooser.showDialog(this,
"Choose Background Color", null);
backgroundColorLabel.setBackground(newColor);
properties.setProperty("background", toHexString(newColor));
}//GEN-LAST:event_backgroundColorLabelMouseClicked

private String toHexString(Color color) {
int rgb = color.getBlue() + (color.getGreen() << 8) +
(color.getRed() << 16);
return "0x" + Integer.toHexString(rgb);
}

private void reset() {
try {
} catch (IOException ex) {
}
}

/**
* @param args the command line arguments
*/
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
Logger.getLogger(OptionPanel.class.getName()).log(Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
Logger.getLogger(OptionPanel.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
Logger.getLogger(OptionPanel.class.getName()).log(Level.SEVERE, null, ex);
} catch (UnsupportedLookAndFeelException ex) {
Logger.getLogger(OptionPanel.class.getName()).log(Level.SEVERE, null, ex);
}
new OptionPanel().setVisible(true);
}
});
}

// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel backgroundColorLabel;
private javax.swing.JTextField ballCountField;
private javax.swing.JSlider expandTimeSlider;
private javax.swing.JTextField explodeCountField;
private javax.swing.JTextField heightField;
private javax.swing.JButton jButton1;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel10;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel3;
private javax.swing.JLabel jLabel4;
private javax.swing.JLabel jLabel5;
private javax.swing.JLabel jLabel6;
private javax.swing.JLabel jLabel7;
private javax.swing.JLabel jLabel8;
private javax.swing.JLabel jLabel9;
private javax.swing.JPanel jPanel1;
private javax.swing.JPanel jPanel2;
private javax.swing.JPanel jPanel3;
private javax.swing.JSlider maxSpeedSlider;
private javax.swing.JSlider minSpeedSlider;
private javax.swing.JButton saveButton;
private javax.swing.JButton startButton;
private javax.swing.JTextField widthField;
// End of variables declaration//GEN-END:variables

}```

```package gui;

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Toolkit;

import java.awt.event.MouseEvent;
import java.awt.geom.Rectangle2D;

import java.awt.image.BufferedImage;

import java.text.DecimalFormat;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

import ball.Ball;
import ball.BallManager;
import ball.CollisionListener;
import ball.GameEndListener;

/**
*
* @author ToGo
*/
public class RxnPanel extends JPanel implements Runnable, GameEndListener, CollisionListener {

private static final ExecutorService executorService = Executors.newCachedThreadPool();

private static BufferedImage sphereCursor;
private static BufferedImage nullCursor;

private static final Font pointFont = new Font("Impact", Font.PLAIN, 12);
private static final Font scoreFont = new Font("Impact", Font.PLAIN, 30);

public static DecimalFormat decimalFormat = new DecimalFormat("###,###,###,###");

private static Image getSphereCursor() {
if (sphereCursor == null) {
int radius = 40;
Graphics2D g = sphereCursor.createGraphics();
new float[]{0.1f, 0.2f, 0.9f},
new Color[]{
new Color(0.5f, 0.5f, 0.5f, 0.7f),
new Color(0.7f, 0.7f, 0.7f, 0.5f),
new Color(0.5f, 0.5f, 0.5f, 0.01f)}));
g.dispose();
}
return sphereCursor;
}

private static Image getNullCursor() {
if (nullCursor == null) {
nullCursor = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
}
return nullCursor;
}

private JFrame frame;
private Dimension preferredSize = new Dimension(640, 400);
private BallManager manager;
private Point mouseLocation;
private Color backgroundColor = new Color(0.1f, 0.1f, 0.12f);
private Color achievementColor = new Color(1f, 1f, 1f, 0.5f);

@Override
public Dimension getPreferredSize() {
return preferredSize;
}

public RxnPanel(JFrame frame) {
super();
this.frame = frame;
RxnMouseListener rxnMouseListener = new RxnMouseListener();
Cursor cursor = Toolkit.getDefaultToolkit().createCustomCursor(getNullCursor(), new Point(), "null");
setCursor(cursor);
executorService.execute(this);
}

minSpeed, maxSpeed, totalBall, goal;

public void restartGame(int initialRadius, int finalRadius, int expandDuration,
int minSpeed, int maxSpeed, int totalBall, int goal, Dimension size, Color background) {
if (manager != null) {
manager.stop();
}
this.expandDuration = expandDuration;
this.minSpeed = minSpeed;
this.maxSpeed = maxSpeed;
this.totalBall = totalBall;
this.backgroundColor = background;
this.goal = goal;
Ball.setExpandDuration(expandDuration);
this.preferredSize = size;
manager = new BallManager(new Rectangle(size), minSpeed, maxSpeed, totalBall, goal);
collided(null);
executorService.execute(manager);
}

@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(backgroundColor);
g2.fillRect(0, 0, getWidth(), getHeight());
g2.setFont(pointFont);
if (manager != null) {
manager.draw(g2);
if (!manager.isInitiallyClicked() && mouseLocation != null) {
Image img = getSphereCursor();
g2.drawImage(img, mouseLocation.x - img.getWidth(null) / 2,
mouseLocation.y - img.getHeight(null) / 2, null);
}
if (manager.isGoalAchieved()) {
g2.setColor(achievementColor);
g2.fillRect(0, 0, getWidth(), getHeight());
}
g2.setColor(Color.BLACK);
g2.setFont(scoreFont);
String score = decimalFormat.format(manager.getTotalPoint());
Rectangle2D rect = g2.getFontMetrics().getStringBounds(score, g);
g2.drawString(score, (float) (preferredSize.width - rect.getWidth()),
(float) (preferredSize.height));
}
}

public void run() {
while(true) {
repaint();
try {
} catch (InterruptedException ex) {
Logger.getLogger(RxnPanel.class.getName()).log(Level.SEVERE, null, ex);
}
}
}

public void gameEnded(int remainingBalls) {
if (remainingBalls <= 0) {
JOptionPane.showMessageDialog(this,
"Congratulations!\n" +
"You've made " + decimalFormat.format(manager.getTotalPoint())
+ " points!", "Game Over!",
JOptionPane.INFORMATION_MESSAGE);
} else {
JOptionPane.showMessageDialog(this,
"Sorry, you had " + remainingBalls + " balls remained.",
"Game Over!", JOptionPane.INFORMATION_MESSAGE);
}
maxSpeed, totalBall, goal, preferredSize, backgroundColor);
}

public void collided(Ball ball) {
frame.setTitle("ChnRxn " + manager.getNExplodedBalls() + "/" + manager.getTotalBallCount());
}

public BallManager getManager() {
return manager;
}

private class RxnMouseListener extends MouseAdapter {

@Override
public void mouseReleased(MouseEvent e) {
if (manager != null) {
manager.initialClick(e.getX(), e.getY(), System.nanoTime());
}
}

@Override
public void mouseDragged(MouseEvent e) {
mouseMoved(e);
}

@Override
public void mouseMoved(MouseEvent e) {
mouseLocation = e.getPoint();
}

}

}```

```package main;

import gui.RxnPanel;

import java.awt.Color;
import java.awt.Dimension;

import javax.swing.JFrame;

/**
*
* @author ToGo
*/
public class Main extends JFrame {

public Main(){

}

/**
* @param args the command line arguments
*/
public static void main(String[] args) {
JFrame frame = new JFrame();
RxnPanel rp = new RxnPanel(frame);
rp.restartGame(3, 6, 10, 1, 10, 100, 5, new Dimension(400,400), Color.black);
frame.setPreferredSize(new Dimension(600,600));
frame.pack();
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
frame.setVisible(true);
}

}```

The restart game is supposed to define all the variables important to the game, such as number of balls, background colour etc. (the labeling on the constructor is quite clear). Everything within the main method is my own code. It was originally empty. if you run it the way I have it, what you get is a black game screen on which you can see the cursor icon. however, no balls, even though if you follow the logic from the restartGame() method, the createBall() method will be called the number of times defined in the parameters. If you click, it will also activate the explosion, which you will not see, but you will know took place because the level will end and you won't have hit any balls (because they aren't there). Maybe someone more used to github than me can see what I'm doing incorrectly.

The original can be found here, if people aremore comfortable using github directly

--- Update ---

Oh, never mind. My numbers were too small. Far too small. What is it about this forum? Every time I post something here, I end up solving it moments afterwards anyway. I should probably make this a more frequent habit...

2. ## Re: Running ChainRXN like game

Whatever works.