Java Swing Horse Simulation - java

I am having problem getting my horse position to update within my swing application. I have tried multiple methods to update the xPosition of the horses as they refresh across the swing panel that represents the racetrack.
public class HorseModel{
/*Horse dimensions*/
private int x;
private int y;
private final int horsePerimeter = 20;
public HorseModel(int xT, int yT){
/*Constructor*/
x = xT;
y = yT;
}
public void setDimensions(int dimX, int dimY){
/*Sets program dimensions*/
x = dimX;
y = dimY;
}
public void createHorse(Graphics2D h){
/*Paints HorseModel on screen as 2 dimensional object*/
Ellipse2D.Double horseModel = new Ellipse2D.Double(x, y, horsePerimeter, horsePerimeter);
h.setColor(Color.RED);
h.fill(horseModel);
h.setColor(Color.YELLOW);
h.draw(horseModel);
}
}
public class HorseMovement implements Runnable{
public final int xStartPos = 10; //change
public final int yStartPos = 20;
private RaceTrack hRaceTrack;
private HorseModel Horse2D;
private int xPos, yPos;
public HorseMovement(RaceTrack r, int yPos_Spacing){
/*Constructor*/
xPos = xStartPos;
yPos = yStartPos * yPos_Spacing;
Horse2D = new HorseModel(xPos, yPos);
hRaceTrack = r;
}
public HorseModel moveHorse(HorseModel horseObject){
/*Updates horse positon*/
horseObject = new HorseModel(xPos++, yPos);
return horseObject;
}
public void paintComponent(Graphics h){
/*paints the new horse after movement*/
this.Horse2D = moveHorse(Horse2D);
Graphics2D hMod = (Graphics2D) h;
Horse2D.createHorse(hMod);
}
public void run(){
/*Repaints the horse models as they increment movement across the screen*/
hRaceTrack.repaint();
hRaceTrack.revalidate();
}
}
public class RacePanel extends JFrame{
/*Frame Buttons*/
private JPanel mPanel;
private JButton startRace = new JButton("Start Race");
private JButton stopRace = new JButton("Stop Race");
private JButton startOver = new JButton("Start Over");
/*Panel to fill with HorseModels for race*/
private RaceTrack rTrack;
/*Window dimensions*/
public int Window_Height = 1024;
public int Window_Width = 768;
public RacePanel(){
/*Constructor*/
initGui();
initRace();
initQuit();
setSize(Window_Width, Window_Height);
}
public void initGui(){
/*Initializes the main race panel and sets button positions and layouts*/
mPanel = new JPanel(new BorderLayout());
rTrack = new RaceTrack();
JPanel horsePanel = new JPanel(); //panel to house horse objects before running across screen
horsePanel.setLayout(new GridLayout(1, 3));
positionJPanels(horsePanel, mPanel);
}
public void initRace(){
/*implements action listener for start race button*/
class StartRace implements ActionListener{
public void actionPerformed(ActionEvent e){
startRace.setEnabled(true);
rTrack.initTrack();
}
}
ActionListener event = new StartRace();
stopRace.addActionListener(event);
}
public void initQuit(){
/*Implements the action listener for stop race button*/
class StopRace implements ActionListener{
public void actionPerformed(ActionEvent e){
System.exit(0);//exits program if race is stopped
}
}
ActionListener event = new StopRace();
stopRace.addActionListener(event);
}
public void positionJPanels(JPanel h, JPanel p){
/*Handles adding buttons to a JPanel*/
h.add(startRace);
h.add(startOver);
h.add(stopRace);
p.add(h, BorderLayout.NORTH); //sets the horse panel buttons to the top of the layout
p.add(rTrack, BorderLayout.CENTER); //sets
add(p);
}
}
public class RaceController {
public static void main(String[] args){
new RaceController();
}
public RaceController(){
/*Constructor*/
JFrame mFrame = new RacePanel();
mFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mFrame.setVisible(true);
}
}
public class RaceTrack extends JPanel{
/*Sets horses within race track*/
private int numOfHorseObjects = 5;// change this to a dynamic
private int numOfThreads = 25;
/*Holds horse thread from HorseObject class*/
private ArrayList<HorseMovement> horses = new ArrayList<>();
private ArrayList<Thread> threads = new ArrayList(numOfThreads);
public RaceTrack(){
/*Constructor*/
setBackground(Color.black);
reset();
}
public void initTrack(){
/*Starts the RaceTrack simulation*/
threads.clear(); //clears the thread arraylist still residing
for(int i = 0; i < horses.size(); i++){
Thread T = new Thread(horses.get(i));
T.start();
threads.add(T);
}
}
public void reset(){
/*resets horse position within screen*/
horses.clear();
for(int i = 0; i < numOfHorseObjects; i++){
horses.add(new HorseMovement(this, i + 1));
}
}
public void paintComponent(Graphics g){
/*overrides graphics paint method in order to paint the horse movements
* through the arraylist of HorseMovements*/
super.paintComponent(g);
for(HorseMovement h : horses){
h.paintComponent(g);
}
}
}

Issues with your code:
You never give the startRace JButton an ActionListener, so how is button going to have any affect, and how is the race ever going to start? Note that you're adding the StartRace ActionListener object to the stopRace JButton, and I'm guessing that this was done in error.
Even if you added that Listener to the startRace button, the action listener will only advance all the horses one "step" and no more -- there are no loops in within your background threads to perform actions repetitively.
You seem to be creating new Horse2D objects needlessly. Why not simply advance the location of the existing Horse2D object?
Myself, I'd use a single Swing Timer rather than a bunch of Threads in order to simplify the code.

Related

How Could I add Jcomponent during runtime with Swing Timer

I have Problem with Making adding RandomText(with random size, font,x,y) to JFrame every seconds this is my Code
first one is JComponent which expects Randomly Made String to appear
public class RandomTextGenerator extends JComponent{
private String str;
private Random r;
private Color c;
private Font f;
private int x;
private int y;
Graphics g;
public RandomTextGenerator(String s)
{
r = new Random();
c = new Color(r.nextInt(255),r.nextInt(255),r.nextInt(255));
f = new Font("random",Font.BOLD,r.nextInt(100));
x = r.nextInt(100);
y = r.nextInt(100)+100;
//setPreferredSize(new Dimension(500,500));
str = s;
}
public void paintComponent(Graphics g)
{
g.setColor(c);
g.setFont(f);
System.out.println(str);
g.drawString(str, x, y);
}
}
Another one is JFrame
public class TextFrame extends JFrame{
public TextFrame() {
this.setSize(500, 500);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("Random Text Generator");
this.getContentPane().setBackground(Color.BLACK);
this.setLayout(new GridLayout(1,1));
this.add(new RandomTextGenerator("AAAAAAAA"));
this.add(new RandomTextGenerator("BBBBBBBBBB"));
this.setVisible(true);
}
public void addRandomText(RandomTextGenerator r)
{
this.add(r);
this.add(new RandomTextGenerator("CCC"));
System.out.println("Method called");
this.repaint();
}
}
above Code,
this.add(new RandomTextGenerator("AAAAAAAA"));
this.add(new RandomTextGenerator("BBBBBBBBBB"));
those ones Works well and display on Screen but problem is method addRandomText
this.add(r);
this.add(new RandomTextGenerator("CCC"));
those ones do not works at all.
my main method is here
public class tfmain {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
System.out.println("Enter Your Message");
String str = s.nextLine();
TextFrame tf = new TextFrame();
Timer t = new Timer(1000,new ActionListener(){
#Override
public void actionPerformed(ActionEvent arg0) {
tf.addRandomText(new RandomTextGenerator(str));
}
});
t.start();
}
}
with this code Method Called is appear which means that Timer Actually works.
but why adding Jcomponent isn't working?? adding Jcomponent in AddRandomtext never works(paintComponent is not called too)
Please Give me some advice. Sorry for my bad english

Creating simple TicTacToe GUI game

I am trying to create a simple Tic-Tac-Toe game using GUI. I have one button, which shows the player's turn (when pressed the button itself changes its text to 0 or 1 (drawing X or O)).
However I am stuck with a problem here, I have no idea why my test within the MouseListener is applied to every single Jcomponent object (my class TicTacToe extends it) and all of the 9 Panels, which are within GridLayout(3,3) are filled with the same drawing...
Here is my TicTacToe class
public class TicTacToe extends JComponent{
private int ovalOrX = 0;
public TicTacToe(){
super.setPreferredSize(new Dimension(300,300));
}
public void paintComponent(Graphics g){
g.setColor(Color.BLACK);
g.drawLine(0, 0, getWidth(), 0);//top line
g.drawLine(0, 0, 0, getHeight());//left line
g.drawLine(0, 300, getWidth(), getHeight());//botton line
g.drawLine(getWidth(),getHeight(), getWidth(), 0);//right line
if(ovalOrX == 1){
g.setColor(Color.RED);
g.drawLine(0,0,100,100);
g.drawLine(0,100,100,0);
}
if(ovalOrX == 2){
g.setColor(Color.BLUE);
g.drawOval(0,0,100,100);
}
}
public void drawX(){
ovalOrX = 1;
repaint();
}
public void drawCircle(){
ovalOrX = 2;
repaint();
}
}
And here is my JFrame class:
public class TicTacToeFrame extends JFrame {
private static final int FRAME_WIDTH = 300;
private static final int FRAME_HEIGHT = 300;
private JPanel mainPanel;
private TicTacToe scene;
private TicTacToe s00;
private TicTacToe s01;
private TicTacToe s02;
//finish top raw
private TicTacToe s10;
private TicTacToe s11;
private TicTacToe s12;
//finish middle raw
private TicTacToe s20;
private TicTacToe s21;
private TicTacToe s22;
private int buttonInt = 0;
private JButton OX;
class AddButtonListener implements ActionListener{
public void actionPerformed(ActionEvent event){
if(buttonInt == 0){
buttonInt++;
}
else if(buttonInt == 1){
buttonInt = 0;
}
OX.setText("Player: " + buttonInt);
}
}
class MyMouseListener extends MouseAdapter{
public void mouseClicked(MouseEvent event){
TicTacToe[] myPanelArray = {s00,s01,s02,s10,s11,s12,s20,s21,s22};
if(buttonInt == 0){
for(int i = 0; i < myPanelArray.length;i++){
if(myPanelArray[i].contains(event.getPoint())){
myPanelArray[i].drawCircle();
}
}
}
}
}
public TicTacToeFrame(){
scene = new TicTacToe();
scene.setPreferredSize(new Dimension(300,300));
add(scene,BorderLayout.CENTER);
OX = new JButton("Player: " + buttonInt);
OX.addActionListener(new AddButtonListener());
add(OX,BorderLayout.NORTH);
mainPanel = new JPanel();
mainPanel.setLayout(new GridLayout(3,3));
fillScene();
add(mainPanel,BorderLayout.CENTER);
setSize(FRAME_WIDTH,FRAME_HEIGHT);
}
private void fillScene(){
s00 = new TicTacToe();
s00.addMouseListener(new MyMouseListener());
s01 = new TicTacToe();
//s01.addMouseListener(new MyMouseListener());
s02 = new TicTacToe();
s10 = new TicTacToe();
s11 = new TicTacToe();
s12 = new TicTacToe();
s20 = new TicTacToe();
s21 = new TicTacToe();
s22 = new TicTacToe();
//finish bottom raw
mainPanel.add(s00);
mainPanel.add(s01);
mainPanel.add(s02);
mainPanel.add(s10);
mainPanel.add(s11);
mainPanel.add(s12);
mainPanel.add(s20);
mainPanel.add(s21);
mainPanel.add(s22);
}
}
The return value of event.getPoint() is relative to the source component, a TicTacToe in this case, no the entire frame. Therefore, it will always be true for all the TictacToe's since they are all the same size.
Istead, use the Event.getSource() to determine the source object.
Also, it advisable to put all you TicTacToe objects into a TicTacToe[][] instead of listed separately.

Did I structure this key listener properly?

I'm asking because I want the addShot() method in my GamePanel class to be called when the user hits enter," this initializes a shot object representing a missile fired from a ship, but it doesn't do anything. Is there a visibility issue here, or did I just structure the key event and listener relationship wrong? I'm only posting relevant code, but I can post the rest if necessary.
Here's the code:
public static class GameTest extends JFrame {
private static final int WINDOW_WIDTH = 800;
private static final int WINDOW_HEIGHT = 500;
public GamePanel gamePanel;
public GameTest() throws IOException {
super("Deep Fried Freedom");
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
setLayout(new BorderLayout());
gamePanel = new GamePanel();
add(gamePanel);
center(this);
setVisible(true);
this.addKeyListener(new aKeyListener());
this.setFocusable(true);
} // end constructor
public void center(JFrame frame) {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
Point center = ge.getCenterPoint();
int w = frame.getWidth();
int h = frame.getHeight();
int x = center.x - w / 2, y = center.y - h / 2;
frame.setBounds(x, y, w, h);
frame.validate();
}//end of center method
public class aKeyListener implements KeyListener {
#Override
public void keyTyped(KeyEvent e) {
}//end empty keyTyped method
#Override
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_A:
Launcher.lRun = -20;
gamePanel.move(gamePanel);
break;
case KeyEvent.VK_D:
Launcher.lRun = 20;
gamePanel.move(gamePanel);
break;
case KeyEvent.VK_ENTER:
gamePanel.addShot();
break;
default:
Launcher.lRun = 0;
}
}//end keyPressed method
#Override
public void keyReleased(KeyEvent e) {
}//end empty keyReleased method
}//end aKeyListener class
}//end GameTest class
Yours is likely a focus issue -- something in the GamePanel stealing focus perhaps, a very common problem with KeyListeners.
General advice: favor using Key Bindings, not a KeyListener for this type of need.
Useful links:
Swing Resources
Please check my second example program in my answer to a StackOverflow question here.
Overall Swing Tutorials
Key Bindings
Swing Timer
Concurrency in Swing
Edit
For example:
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;
public class GameTest extends JFrame {
private static final int WINDOW_WIDTH = 800;
private static final int WINDOW_HEIGHT = 500;
public GamePanel gamePanel;
public GameTest() {
super("Deep Fried Freedom");
setResizable(false);
// setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
// setSize(WINDOW_WIDTH, WINDOW_HEIGHT); // never do this
gamePanel = new GamePanel();
setUpKeyBinding(gamePanel);
add(gamePanel);
pack();
setLocationRelativeTo(null); // to center!
setVisible(true);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(WINDOW_WIDTH, WINDOW_HEIGHT);
}
private void setUpKeyBinding(GamePanel gamePanel2) {
// only need window to have focus
int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
// get the GamePanel's InputMap and ActionMap as these will be used to set
// up our Key Bindings
InputMap inputMap = gamePanel2.getInputMap(condition);
ActionMap actionMap = gamePanel2.getActionMap();
// bind the A key to move back 20 pixels
KeyStroke keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_A, 0);
inputMap.put(keyStroke, keyStroke.toString());
actionMap.put(keyStroke.toString(), new MoveAction(gamePanel2, -20));
// bind the D key to move forward 20 pixels
keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_D, 0);
inputMap.put(keyStroke, keyStroke.toString());
actionMap.put(keyStroke.toString(), new MoveAction(gamePanel2, 20));
// bind the ENTER key
keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
inputMap.put(keyStroke, keyStroke.toString());
actionMap.put(keyStroke.toString(), new EnterAction(gamePanel2));
}
public static void main(String[] args) {
new GameTest();
}
// our Action classes that will bound to key strokes
private class MoveAction extends AbstractAction {
private GamePanel gamePanel2;
private int distance;
public MoveAction(GamePanel gamePanel2, int distance) {
this.gamePanel2 = gamePanel2;
this.distance = distance;
}
#Override
public void actionPerformed(ActionEvent e) {
gamePanel2.moveItem(distance);
}
}
private class EnterAction extends AbstractAction {
private GamePanel gamePanel2;
public EnterAction(GamePanel gamePanel2) {
this.gamePanel2 = gamePanel2;
}
#Override
public void actionPerformed(ActionEvent e) {
gamePanel2.addShot();
}
}
}
// a trivial GamePanel class to just show that everything is working as expected
class GamePanel extends JPanel {
public void moveItem(int i) {
// your moveItem method will instead actually move something, a distance of i
System.out.println("Move Item Method distance: " + i);
}
public void addShot() {
// your addShot method will actually shoot
System.out.println("Add Shot Method");
}
}

Simple Java game using grid

This picture is edited with photoshop to show what I want to do:
Basically, what I want to do is to move the black-stick-man by clicking on it and move to available positions(gray boxes).
This is what I've done so far:
Arena.java
public class Arena extends JFrame{
JPanel a = new JPanel();
Player players[][] = new Player[10][10];
private ImageIcon player = new ImageIcon("player.jpg");
private ImageIcon player2 = new ImageIcon("player2.jpg");
private ImageIcon poop = new ImageIcon("poop.jpg");
private ImageIcon moves = new ImageIcon("moves.jpg");
public static void main(String args[]){
new Arena();
}
public Arena(){
setTitle("The Arena");
setSize(500,500);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
a.setLayout(new GridLayout(10,10));
for(int i=0;i<10;i++){
for(int j=0;j<10;j++){
players[i][j] = new Player();
a.add(players[i][j]);
}
}
//player position
players[9][4].setIcon(player);
//player 2 position
players[9][7].setIcon(player2);
//poop
players[7][2].setIcon(poop);
players[5][7].setIcon(poop);
add(a);
setVisible(true);
}
}
Player.java
public class Player extends JButton{
private int xPos;
private int yPos;
public Player(){
}
public int getXPos(){
return xPos;
}
public int getYPos(){
return yPos;
}
public void setXPos(){
this.xPos = x;
}
public void setYPos(){
this.yPos = y;
}
}
Thanks!

Java repaint() not working

I am making a simple program to paint a graph and some points in it. The points should be made with methods while changing coordinates of the g.fillOval but actually its painting only the last point.
Here is the code:
import javax.swing.*;
import java.awt.*;
public class PointGraphWriter extends JPanel
{
JFrame korniza = new JFrame();
private int x;
private int y;
private int length;
private String OX;
private String OY;
private String emri;
private int y_height;
private int x_num;
public PointGraphWriter()
{
int width= 500;
korniza.setSize(width,width);
korniza.setVisible(true);
korniza.setTitle(emri);
korniza.getContentPane().add(this);
}
public void paintComponent(Graphics g)
{
g.drawLine(x,y,x+length,y);
g.drawLine(x,y,x,y-length);
g.drawString(OX,x+length, y+15);
g.drawString(OY,x-15,y-length);
g.drawString("0", x -15,y);
g.drawString("0", x,y+15);
g.fillOval(x_num,y-y_height-2, 4 ,4);
}
public void setTitle(String name)
{
emri= name;
this.repaint();
}
public void setAxes(int x_pos, int y_pos, int axis_length, String x_label, String y_label)
{
x= x_pos;
y=y_pos;
length= axis_length;
OX = x_label;
OY = y_label;
}
public void setPoint1(int height)
{
y_height=height;
x_num = x-2;
this.repaint();
}
public void setPoint2(int height)
{
y_height=height;
x_num = x + length/5-2;
this.repaint();
}
}
and here is the main method:
public class TestPlot
{
public static void main(String[] a)
{
PointGraphWriter e = new PointGraphWriter();
e.setTitle("Graph of y = x*x");
e.setAxes(50, 110, 90, "5", "30");
int scale_factor = 3;
e.setPoint1(0 * scale_factor);
e.setPoint2(1 * scale_factor);
}
}
Please have a look at this example. Something in lines of this, you might have to incorporate in your example, to make it work. Simply use a Collection to store what you have previously painted, and when the new thingy comes along, simply add that thingy to the list, and repaint the whole Collection again. As shown below :
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import javax.swing.*;
public class RectangleExample {
private DrawingBoard customPanel;
private JButton button;
private Random random;
private java.util.List<Rectangle2D.Double> rectangles;
private ActionListener buttonActions =
new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
Rectangle2D.Double rectangle = new Rectangle2D.Double(
(double) random.nextInt(100), (double) random.nextInt(100),
(double) random.nextInt(100), (double) random.nextInt(100));
rectangles.add(rectangle);
customPanel.setValues(rectangles);
}
};
public RectangleExample() {
rectangles = new ArrayList<Rectangle2D.Double>();
random = new Random();
}
private void displayGUI() {
JFrame frame = new JFrame("Rectangle Example");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel contentPane = new JPanel();
contentPane.setLayout(new BorderLayout(5, 5));
customPanel = new DrawingBoard();
contentPane.add(customPanel, BorderLayout.CENTER);
button = new JButton("Create Rectangle");
button.addActionListener(buttonActions);
contentPane.add(button, BorderLayout.PAGE_END);
frame.setContentPane(contentPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
Runnable runnable = new Runnable() {
#Override
public void run() {
new RectangleExample().displayGUI();
}
};
EventQueue.invokeLater(runnable);
}
}
class DrawingBoard extends JPanel {
private java.util.List<Rectangle2D.Double> rectangles =
new ArrayList<Rectangle2D.Double>();
public DrawingBoard() {
setOpaque(true);
setBackground(Color.WHITE);
}
public void setValues(java.util.List<Rectangle2D.Double> rectangles) {
this.rectangles = rectangles;
repaint();
}
#Override
public Dimension getPreferredSize() {
return (new Dimension(300, 300));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Rectangle2D.Double rectangle : rectangles) {
g.drawRect((int)rectangle.getX(), (int)rectangle.getY(),
(int)rectangle.getWidth(), (int)rectangle.getHeight());
}
System.out.println("WORKING");
}
}
See Custom Painting Approaches for examples of the two common ways to do painting:
Keep a List of the objects to be painted
Paint onto a BufferedImage
The approach you choose will depend on your exact requirement.

Categories

Resources