Hey, well I have this problem, I am making a game in Java and it is getting really far. If anyone saw my last problem, that is resolved and I finished my networking code. Here is the problem, to start a new game window in my code, one would write something like this:

new Engine(1, "230.0.0.1", 2);

If I do this in the main entry point of the program in the class ENGINE itself, I do something like this:

new Engine(1, "230.0.0.1", 2);
new Engine(2, "230.0.0.1", 2);

Because I have to distribute the game to a few friends, I made another class called loader, and all it does is it gives the option to the user whether to be player 1 or player 2. The 1st parameter for initializing a new object of "Engine" is the player ID, the second is the server address, and the third is the total players. If I use this EXACTLY same code:

new Engine(2, "230.0.0.1", 2);

In the loader class, it starts a new game window that is ALL blank, until player 1 ends their turn. Player 1's game window starts fine from the loader though. I do not understand what is wrong in the program. It is pretty complicated to understand.

Debugging it actually let me find that the RECIEVE method of the network is blocking the loading as well, it actually loaded the map, but then went blank after the recieve method is called. Please help! Thank you!

Recommended Answers

All 16 Replies

starts a new game window that is ALL blank

What should the window show? And when should it show it?

but then went blank

What made it go blank?

Look at the logic of the code to see why the above is happening.

Woah thanks for the quick reply, well the window should show a black bar with 2 buttons and a canvas with tiles and 2 bases (its a 2d turn based). If I load the 2 player's game windows from the actual ENGINE classes main entry point, both windows are filled, and the first one is waiting for the user to click end turn, while the second wont let the user do anything until it is its turn (command received through network).

I am assuming that the recieve method made it go blank, because if I do JOptionPane.showMessageDialog() commands, it breaks down the loading step by step, and I see the world load, then it goes blank after the "Recieve" dialog comes up. I have been looking at the logic, I really dont get why this occurs :(

starts a new game window that is ALL blank

When should it show it? What is stopping it from being shown?

assuming that the recieve method made it go blank,

I wouldn't think it would. However it the Swing Event Dispatch Thread is being blocked by the receive() method it could. You need to do the I/O on its own thread and not allow the I/O to block the Swing EDT.

See there is the problem though, if I run the EXACT same code, creating a new Object of Type ENGINE on the engine's main entry point, it loads PERFECTLY, but if I make an object of type engine from a DIFFERENT class, it makes the 2nd player's game window blank, and it only cures / loads itself after it receives a packet (I made a custom packet(object)) from player 1. It is soo weird

Sounds like a program logic problem.

What is the difference between the code in the main() method and when you create the Engine object from a different class?

There is the problem, there is no difference, AT ALL :). It is LITERALLY a copy, I copied and pasted the code to initialize the object FROM the Engine's entry point. How can there POSSIBLE be a difference between initializing in your own entry point, and the entry point of another class. It is basically the same thing right?

How can there POSSIBLY be a difference

You'd be amazed at how many different ways students can find to do something. I see new ways every day.

At this point without seeing the code in the main() and the other code I can't tell.

Are either of these ways of creating the new Engine object on Swing's EDT?

ok

Engine varnaEngine = new Engine(2, "230.0.0.1", 2);

is the code in the Engine class's entry point.

Engine varnaEngine = new Engine(2, "230.0.0.1", 2);

is the code in the Loader.java class's main entry point. Btw, what do you mean

Are either of these ways of creating the new Engine object on Swing's EDT?

If you use Swing components in the GUI, you MUST take care not to block the thread that Swing uses to update the GUI. If you do, the GUI make not be updated properly.

For more info research the topic in the Tutorial.

oh ok, now i get it, i know my Network class extends thread, but i dont use thread.start();. obviously I am using the same thread as the gui,but the network code is all the way at the bottom, the last thing to be called.

If I called thread.start(), and it calls the RECIEVE method of the Network class, which is a thread by itself, how would I re-instantiates the receive method. The receive method is not in a while loop, it just blocks the thread until it receives, how would I re=instantiate that thread though?

thread.start(); // this goes through the hassle of the receive method and finally ends after it gets ONE packet

thread.stop();

My code is not as simple as above, it is very complicated in terms of turns, networks, and the game itself, because the user has a plethora of options ,like make a unit, firing, capturing and stuff. When a user clicks END TURN, it comes to a method, obviously named endTurn(), and that is where the code:

while(VarnaNetworkDataStructure.PLAYER_TURN != VarnaNetworkDataStructure.PLAYER_ID)
    	{
			VarnaNetworkDataStructure.gameNetwork.run();
			for(int i = 0; i < VarnaNetworkDataStructure.TOTAL_PLAYERS; i++)
			{
				if(VarnaNetworkDataStructure.units[i].size() > 0)
				{
					hasUnits = true;
				}
			}
			repaint();
    	}
    	myTurn = true;

That just makes the gameNetwork get ONE packet, which updates the player turn, if the player turn finally equals the player's id, then the loop breaks and it is your turn. here is my network code:

package Network;

import java.io.*;
import java.net.*;


public class VarnaNetwork implements Runnable{
	boolean myTurn = false;
	MulticastSocket socket;
	InetAddress address;
	
	final int maximumUnits = 100;
	
	public VarnaNetwork() throws IOException {
    	socket = new MulticastSocket(VarnaNetworkDataStructure.PORT_NUM);
    	address = InetAddress.getByName(VarnaNetworkDataStructure.SERVER_ADDRESS);
		socket.joinGroup(address);
    	
    	if(VarnaNetworkDataStructure.PLAYER_ID == 1){
    		myTurn = true;
    	}
    }
	
	public void send()
	{
		try
		{
			if(myTurn)
			{
				VarnaPacket data = new VarnaPacket();
                byte[] buf = getBytes(data);
                
                byte[] buf2 = Integer.toString(buf.length).getBytes();
                
                InetAddress group2 = InetAddress.getByName(VarnaNetworkDataStructure.SERVER_ADDRESS);
                DatagramPacket packet2 = new DatagramPacket(buf2, buf2.length, group2, VarnaNetworkDataStructure.PORT_NUM);
                socket.send(packet2);
                
                if(VarnaNetworkDataStructure.PLAYER_TURN != VarnaNetworkDataStructure.PLAYER_ID)
                {
                	myTurn = false;
                }
                
                InetAddress group = InetAddress.getByName(VarnaNetworkDataStructure.SERVER_ADDRESS);
                DatagramPacket packet = new DatagramPacket(buf, buf.length, group, VarnaNetworkDataStructure.PORT_NUM);
                socket.send(packet);
			}
		}
		catch(Exception e)
		{
			
		}
	}
	
	public void recv()
	{
		try
		{
			if(!myTurn)
			{
				socket = new MulticastSocket(VarnaNetworkDataStructure.PORT_NUM);
		        address = InetAddress.getByName(VarnaNetworkDataStructure.SERVER_ADDRESS);
				socket.joinGroup(address);
				
				DatagramPacket packet2;
			    
			    byte[] buf2 = new byte[maximumUnits];
		        packet2 = new DatagramPacket(buf2, buf2.length);
		        socket.receive(packet2);
		        
			    DatagramPacket packet;
			    
			    byte[] buf = new byte[Integer.parseInt(new String(packet2.getData()).trim())];
			    ByteArrayInputStream b_in = new ByteArrayInputStream(buf);
		        packet = new DatagramPacket(buf, buf.length);
		        socket.receive(packet);
		        ObjectInputStream o_in = new ObjectInputStream(b_in);
		        VarnaPacket p = (VarnaPacket) o_in.readObject();
		        p.updateDataStructure();
	            
	            if(VarnaNetworkDataStructure.PLAYER_TURN == VarnaNetworkDataStructure.PLAYER_ID)
	            {
	            	myTurn = true;
	            }
			}
		}
		catch(Exception e)
		{
			
		}
	}
	
	public void run() {
		recv();
	}
	
	public void close()
	{
		try
		{
			socket.leaveGroup(InetAddress.getByName(VarnaNetworkDataStructure.SERVER_ADDRESS));
			socket.close();
		}
		catch(Exception e)
		{
			
		}
	}
    
    public static byte[] getBytes(Object obj) throws java.io.IOException{
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(obj);
        oos.flush();
        oos.close();
        bos.close();
        byte [] data = bos.toByteArray();
        return data;
    }

}

Thanks!

*bump* I really need an answer plz :(

As you can guess, using multiple threads is complicated.
You need to have the network I/O code on its own thread, completely separate from the GUI code's thread. You have to work out communications between the two threads using flags and synchronized code. It takes some design work.

As you can guess, using multiple threads is complicated.
You need to have the network I/O code on its own thread, completely separate from the GUI code's thread. You have to work out communications between the two threads using flags and synchronized code. It takes some design work.

Ok, I see what you mean, just out of curiosity, the vectors for the units and buildings in my game are STATIC, so one could access them anywhere in the game. If I was to run the RECEIVE method completely asynchronously (is that the right word?) from the GUI, would there ever be an error when one thread and the main thread try and access the same variable at the same time? I cannot simply make a receive thread run forever because when one game client recieved a (good to go) packet basically, it has to go into a state of NO threads, and just whenever the user presses END, it should send. The Send() method doesnt really need a thread, it is UDP, and there is no blocking, it just makes a new packet and shoves it into space right? You are right, it requires some designing, but I am pretty confused as to ways to do this. I have actually made recv() a thread once, but it made the building images in my game flicker alot, I dont know why either. Its really annoying. Thank you though! I will post an update or question here if I find another hurdle or anything :).

would there ever be an error when one thread and the main thread try and access the same variable at the same time

The data could be incorrect or corrupted in some cases.

make a receive thread run forever because when one game client recieved a (good to go) packet basically, it has to go into a state of NO threads, and just whenever the user presses END,

There is a model for that: Consumer / Producer where one thread (Producer) creates something that the Consumer thread wants. The consumer thread waits until the producer thread as created the thing and has told the consumer thread it is available at which point, the consumer thread starts running, does its job with what was created and then waits for the next thing to be created. The consumer basically runs in a loop, waiting for the producer to create what it needs.

Threads are a lot more complicated than most applications.

Alright, I fixed the code completely, now it works if I instantiate the object from either Entry point! It is beautiful, I must thank you for a good amount of it actually. I took your advice, and used some of my own "opinion" for lack of a better word. I made the receive method a separate thread, while the send is just a method. It works fantastically, and it is weird that honestly I still do not know why the screen went blank before, but at least that error caused me to take the initiative to make my network and ultimately my game multi-threaded(like it should be :P) thanks for help, I am declaring this solved! :D

Great. I'm sure you learned a bit on this project.

Good luck.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.