Przekazywanie danych - wątki

0

Witam.

Chciałbym aby 2. wątek oddawał do wątku podstawowego(?) tablice/kilka zmiennych charakteryzujących położeie piłki. Obecny program działa i mogę odbijać sobie piłki okrawędzie JComponent, ale chciałbym do niego dodać deseczkę, która poruszana przez user'a będzie odbijała piłkę przy dolnej krawędzi (jak w starych grach).

public class Ball 
{
	public static void main (String[] args)
	{	
		EventQueue.invokeLater(new Runnable()
		{
			public void run()
			{
				JFrame frame = new BounceFrame();
				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				frame.setResizable(false);
				frame.setLocationByPlatform(true);
				frame.setVisible(true);
			}
		});
	}
}

class BallRunnable implements Runnable
{
	public BallRunnable(BallItem aBall, Component aComp)
	{
		ball = aBall;
		comp = aComp;
	}

	public void run()
	{
		try
		{
			kill = 0;
			while(kill < TIME)
			{				
				//throwI.move(comp.getBounds());
				ball.move(comp.getBounds(), 0, 0);
				comp.paint(comp.getGraphics());
				Thread.sleep(DELAY);
				kill++;				
			}
		}
		catch(InterruptedException e)
		{			
		}	
	}
	
	int kill;
	private BallItem ball;
	private Component comp;
	public static final int DELAY = 3;
	private static final int TIME = 5000;
}

class BounceFrame extends JFrame
{
	public BounceFrame()
	{
		setSize(DEF_WIDTH, DEF_HEIGHT);
		setTitle("Piłka");
		
		comp = new BallComponent();
		add(comp, BorderLayout.CENTER);
				
		kill = 0;

		JPanel buttonPanel = new JPanel();
		JButton startButtton = new JButton("Start");	
		startButtton.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent event)
			{
				addBall();
			}
		});
		buttonPanel.add(startButtton);

		final ThrowItem throwI = new ThrowItem();
		comp.addThrow(throwI);
	
		add(buttonPanel, BorderLayout.SOUTH);
	}
	
	public void addBall()
	{
		BallItem ball = new BallItem();
		comp.add(ball);
		
		Runnable r = new BallRunnable(ball, comp);
		Thread t = new Thread(r);
		t.start();
	}
		
	int kill;
	private BallComponent comp;
	ThrowItem throwI;
	public static final int DEF_WIDTH = 400;
	public static final int DEF_HEIGHT = 400;
	public static final int DELAY = 5;
}

comp to ten JCompoent. Ball to obiekt piłki, ThrowItem to obiekt "deseczki". Ball.move() sprawdza czy nie ma zderzenia z throwItem.

 
//throwI.move(comp.getBounds());
ball.move(comp.getBounds(), 0, 0);

Obecnie jest to wyłączone ale gdyby podać throwI.getX() i Y zamiast "0" to deseczka ruszałaby się i starała odbić piłkę. Problem pojawiasię gdy chcę oddać władzę nad ruchem deseczki użytkownikowi, który chyba "jest" w innym wątku :-( .

0

Nie wiem, czy dobrze zrozumiałem.
Użytkownik naciska raz strzałkę do góry i od tego czasu wątek ma stopniowo podnosić tą piłkę?

Jeżeli tak, to najprościej zrobić tak:

  1. Dodaj do klasy BallRunnable
volatile public int vx;
volatile public int vy;

2.Zmień

ball.move(comp.getBounds(), 0, 0);

na

ball.move(comp.getBounds(), vx, vy);
  1. W BounceFrame zapamiętaj referencję do BallRunnable na zmiennej obiektu.
class BounceFrame extends JFrame
{
   BallRunnable ballRunnable;
   (...)
   public void addBall(){
       ballRunnable = new BallRunnable(ball, comp);
   }
}
  1. Za pomocą ballRunnable.vx i ballRunnable.vy możesz zmieniać zachowanie piłki

Pamiętaj, że na zmiennych volatile zapis i odczyt jest atomowy, ale "vx++", czy "vx += 1" nie będą atomowe.
Jeżeli potrzebujesz czegoś takiego, to użyj klasy AtomicInteger.


Jeszcze jeden szczegół.
Zamiast

comp.paint(comp.getGraphics());

lepiej pisać

comp.repaint(); 
0

Chyba źle przedstawiłem problem -wybacz, bo nie o to mi chodziło. Jest JButton który dodaje nowy wątek z piłką odbijająca się okrawędzie - to działa i tak ma pozostać. Na razie zakładajmy że jest jedna piłka dla ułatwieia, więc dwa wątki - podstawowy i wątek piłki. Chciałbym aby, ten wątek piłki co każdy DELAY w pętli, czyli co przemieszczenie piłki o 1px w x,y oddawał te dane (x,y środka) do głównego procesu,gdzie moge dodać sobie np. akcje poruszające jakikolwiek inny przedmiot i aby robić obsługę zderzeń. Obecnie potrafię to zrobić w BallRunnable - dodałem deskę, która porusza się po ekranie w prawo lub lewo i odbija piłkę. Teraz chcę oddać władzę nad deską klawiaturz, czyli user'owi.

0

Nie wiem, czy wiesz, ale w Twoim rozwiązaniu niektóre piłki mogą poruszać się szybciej od innych.

Wątek główny może mieć listę obiektów BallItem lub BallRunnable i wyciągać z nich co będzie chciał.

Jeżeli bardzo chcesz, to możesz przekazywać te dane.
Stwórz obiekt DTO do przekazania danych (x,y).
Niech wątki piłek produkują te obiekty i wkładają do kolejki ArrayBlockingQueue. Natomiast niech wątek główny je wyjmuje i robi co tylko będzie chciał.
http://java.sun.com/javase/6/docs/api/java/util/concurrent/ArrayBlockingQueue.html

Chociaż moim zdaniem to rozwiązanie jest niepotrzebnie skomplikowane. Moim zdaniem te wszystkie wątki powinny się synchronizować, np. na CyclicBarrier.

1 użytkowników online, w tym zalogowanych: 0, gości: 1