Networked Gaming

keep separate components for separate things - do one thing and do it well / separation of concerns.
Your console thing probably doesn’t require input etc. There are a couple of different approaches that work and there isn’t really a consensus about what’s best. Have a look at GoF and not just the MVC cause that can be implemented a zillion ways. But the idea of how complex components are just a collection of simple components.

I think I get where your going, being ‘smart’ doesn’t necessary work well and will spin the complexity out of the control.

update:userName
remove:userName

u:username might look like a good idea but there are pretty much only 26 options for identifiers going from update to u throws human readability out the window so why stick to ‘u’ at all then? you might as well use numbers (IRC is based on this if I remember correctly.) but note that it is performance optimization (which might well be premature) and is an implementation detail that shouldn’t spread in your code.(which is a code smell,to use a hip word)

enums work well and also it allows you to use in a switch

public class Protocol {
	
	enum MessageType {
		AddUser(1),
		RemoveUser(2);
		
		private final int indentifier;

		private MessageType(int indentifier) {
			this.indentifier = indentifier;
		}
		
		public MessageType getMessageByInt(int indentifier) {
			for(MessageType type : values()) {
				if(type.indentifier == indentifier) return type;
			}
			return null;
		}
	}

}

all that makes sense but i still dont understand how the client will interpret the data…

say it recieves:

‘1 me’
‘1 you’
‘1 hi’

1 being add user like in your example. how does the client get rid of the 1 in front of everything? you wouldn’t want a 1 to appear in front of every username. the only way i can think of would be to send multiple messages, the first one being a 1 then followed by a username but that seems uneccasary and not optimized.

just to make sure we are on the same page i have only been sending and recieving strings like this…

to send a message…

out.println(text);

and to recieve…

text = in.readLine().trim();

Interesting topic! Mr_Light your making this into a tutorial or what :slight_smile:

To answer your q
well, you can split on spaces and have a string for each parameter.
search for array split

But that won’t work for user W A C K O because it will return 5 whitespaces.
So to work around that you can prefix the username with the length of the username

1 = login
9 = amount to read
W A C K O = name
1 9W A C K O

I’ve been struggling with the same problem.

awesome thanks for the help. ill see what i can find on google but why is it called array split? aren’t i using strings? or is it that you split the strings different parts into an array?

edit: nevermind i answered my own question. However, would it not be easier to do it something like this:

1*W A C K O

and split it at the “*” instead of spaces

Might actually do that at some point but considering other work I also need to finish work for well euh work :wink:

The result is probably an array of strings :wink:

As you can probably tell there are a couple of approaches to arrange the data in the protocol:

You can use a predefined fixed length fixed format.
You can encode the lengths in the message.
EndOfXXX / separator ‘bit’(can be a character or a certain series of bytes).

Depending on the data your sending any of the above might work well. (There are a couple of other variants but those don’t really make sense considering games)

It’s probably wise to use an EndOfXXX / separator ‘bit’ that doesn’t occur often (never presume that you never send it, in a different context) When you do send the ‘bit’ make sure you escape it. (Google for escape characters)

in terms of creating widgets what should my class extend? canvas? panel? component?

each widget is its own object correct? and then is added to the applet?

maybe you know a good website on creating custom widgets?

Well if you create your own they really don’t need to extend anything. You probably want an interface with adleast a method draw(Graphics g) or similar.

but without extending anything what graphics object am i drawing to?

Well because you do active rendering your eventually draw on the bufferstrategy

But overall you just pass a graphics context to a draw method; you’ll call the graphics context with instructions and it eventually ends up at your screen.

‘Drawing to… something’ is a matter of abstraction, 't is in the eye of the beholder really.

Perhaps an example will work better: (from memory)


Graphics g = null; // ... get somewhere.
for(Drawable drawable : drawables) {
	Location location = drawable.getLocation();
	Graphics localGraphics = g.create();
	localGraphics.translate(location.x, location.y);
	localGraphics.setClip(0, 0, drawable.getWidth(), drawable.getHeight());
	drawable.draw(localGraphics);
	localGraphics.dispose();
}

You’ll have to look if setClip works as advertised.

Which will make the draw(Graphics g) work the same as any paint()(AWT)/paintComponent()(swing)

so a much simpler example just to clarify this is what you are talking about…

import java.applet.*;
import java.awt.*;
import java.awt.Graphics;

public class Widget extends Applet
{
    TextBox text = new TextBox();
    
    public void paint(Graphics g)
    {
        text.draw(g);
    }
}

class TextBox
{   
    public void draw(Graphics g)
    {
        g.drawRect(10,10,100,100);
    }
        
}

i know thats extremely simple but at least for the drawing of the widget am i heading in the right direction?

also i found this website that talks about creating widgets by extending canvas and composite

http://www.eclipse.org/articles/Article-Writing%20Your%20Own%20Widget/Writing%20Your%20Own%20Widget.htm

is this a bad strategy or would it be easier?

That is based on writing custom components for SWT since SWT is based on native implementation it’s probably not going to work with applets. Also it will draw in to much complexity and thus will kill the advantage as to why you where going to write your own.

Your code is in the right direction.

import java.applet.Applet;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.List;

public class Game extends Applet {
	
	private List<Widget> widgets = new ArrayList<Widget>();

	@Override
	public void init() {
		widgets.add(new NeoLabel("Hello world",Location.getLocation(10, 80),10,100));
		widgets.add(new NeoLabel("foobar",Location.getLocation(10, 20),10,100));
	}	
	
	@Override
	public void paint(Graphics g) {
		drawWidgets(g);
	}
	
	public void drawWidgets(Graphics g) {
		for(Widget widget : widgets) {
			Location location = widget.getPosition();
			Graphics localGraphics = g.create();
			localGraphics.translate(location.x, location.y);
			localGraphics.setClip(0, 0, widget.getWidth(), widget.getHeight());
			widget.draw(localGraphics);
			localGraphics.dispose();
		}
	}
	
}

interface Widget {
	void draw(Graphics g);
	Location getPosition();
	int getWidth();
	int getHeight();
}

class NeoLabel implements Widget {

	private Location position;
	private String value;
	private int height;
	private int width;

	public NeoLabel(String value, Location position, int height, int width) {
		this.value = value;
		this.position = position;
		this.height = height;
		this.width = width;
	}
	
	@Override
	public void draw(Graphics g) {
		g.drawString(value, 0, 10);
	}

	@Override
	public int getHeight() {
		return height;
	}

	@Override
	public Location getPosition() {
		return position;
	}

	@Override
	public int getWidth() {
		return width;
	}
}

class Location {
	public final int x,y;
	
	private Location(int x, int y) {
		this.x = x;
		this.y = y;
	}
	
	public static Location getLocation(int x, int y) {
		return new Location(x,y);
	}
}

But you might want to code against an interface.
Also translate(x,y) helps to allow you to move your widgets around. To be able to transelate you need to know the widgets position hence the method getPosition() on the interface.
SetClipping helps to improve performance and ‘sandboxes’ components. to be able to use it you need to know the height and width.

You probably want to add some methods so you can pass input to the components.

thanks for the example i understand now. however i am wondering what the advantage of doing all this is? essentially i am just drawing everything anyways so why not put it all in the same class? only reason i can think of is to be able to reuse my widgets but thats not really an issue. seems simplest to me to just create the user interface as one image and then based on events act accordingly.

Separation of concerns(entangleness, complexity, change leads to more change) - single point of definition(or DRY) - reuse(compound components). Well that’s slinging hyped and not so hyped words at ya - but there is no easy way to explain why, there isn’t really a need for iether as that is something that comes with experience. So tbh going for the monster class approach might not be a bad idea in your case. You need to rewire your brain a bit anyway else either way is not going to be faster.

hmm almost forgot an old favourite spaghetti code - that does look tasty ey?

[quote]You need to rewire your brain a bit anyway else either way is not going to be faster.
[/quote]
^^^ haha are you calling me stupid? im jk but seriously thanks so much for helping me out these past few weeks i really appreciate it. im gonna try to stay off of here and stop bugging you for a while. plus i cant think of anything else i could possibly need help with :slight_smile:

No, I’m not calling you stupid. It’s like going from java to a dynamic language or back.

after working on things a bit i can definately see why it is advantagous to write each widget as a separate class. in the monster class approach something as simple as making a button loook different when clicked becomes difficult because not only do you have to redraw the button but also the entire interface. so going back to the separate class approach im a little confused on where the actionlisteners go. are they all in the main applet class and based on the user input you have methods in the widgets to handle input? or does each widget have its own actionlisteners that are passed as parameters maybe ???

To handle the ‘feel’ I’d probably go with some method on the widget class that one needs to override or write delegating code in for handling user actions go with ‘traditional’ ActionListeners.


protected final Collections<XxxListener> listeners = new CopyOnWriteArrayList<XxxListener>();

protected void fireXxx() {
   for(XxxListener listener : listeners) {
      listener.onXxx();
   }
}

protected void addListener(XxxListener listener) {...}