рдирдорд╕реНрдХрд╛рд░ред
рдореИрдВрдиреЗ рд╣рд╛рд▓ рд╣реА рдореЗрдВ рдПрдВрдбреНрд░реЙрдЗрдб рдХреЗ рд▓рд┐рдП рдПрдХ рдореЛрдмрд╛рдЗрд▓ рдЧреЗрдо рдмрдирд╛рдпрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рд╕рдВрднрд╛рд╡рд┐рдд рд░реВрдк рд╕реЗ рдорд▓реНрдЯреАрдкреНрд▓реЗрдпрд░ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рдХрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдиреЗ рдЕрдиреБрд░реЛрдз рдХрд┐рдпрд╛ рд╣реИред
рдорд▓реНрдЯреАрдкреНрд▓реЗрдпрд░ рдкреНрд░рджрд╛рди рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдореЙрдбрд▓ рдФрд░ рдкреНрд░рд╕реНрддреБрддрд┐ рдХреЗ рдЕрд▓рдЧрд╛рд╡ рдХрд╛ рдЕрдиреБрдкрд╛рд▓рди рдирд╣реАрдВ рдХрд░рддрд╛ рдерд╛ред
рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рдореИрдВ рдЦреЗрд▓ рдХреЗ рдиреЗрдЯрд╡рд░реНрдХ рдореЛрдб рдХреЗ рдПрдХ рд╕рд░рд▓ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реВрдВрдЧрд╛ рдФрд░ рдЦреЗрд▓ рдХреА рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕реЛрдЪрдиреЗ рдХреЗ рдЪрд░рдг рдореЗрдВ рд╣реБрдИ рдЧрд▓рддрд┐рдпреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░реВрдВрдЧрд╛ред
рд▓реЗрдЦ
рдЧреЛрдмрд▓рд┐рди рдпреБрджреНрдзреЛрдВ II рд╕реЗ рдкреНрд░реЗрд░рд┐рдд рд╣реЛрдХрд░
, рдЦреЗрд▓
рдХреА рд╕рдВрд░рдЪрдирд╛ рдХреЛ рд╕реНрд╡рддрдВрддреНрд░ рдмреНрд▓реЙрдХреЛрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдЬреЛ рдЕрдВрддрддрдГ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ рдиреЗрдЯрд╡рд░реНрдХ рдкрд░ рдЦреЗрд▓рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рдерд╛ред
рд╕рднреА рдЧреЗрдо рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд▓рд┐рдП рдмреЗрд╕ рдХреНрд▓рд╛рд╕ рдореЗрдВ рдПрдорд╡реАрд╕реА рдореЙрдбрд▓ рдХреЗ рд╕рднреА рддрд░реНрдХ рдирд┐рд╣рд┐рдд рдереЗ - рдпрд╣ рдЦреБрдж рдХреЛ рдЖрдХрд░реНрд╖рд┐рдд рдХрд░рдиреЗ рдФрд░ рдЕрдкрдиреА рд╕реНрдерд┐рддрд┐ рдХреЛ рдмрджрд▓рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдерд╛ред
public abstract class BaseObject { public byte type; public byte state; public Rectangle body; public abstract void update(float delta); public abstract void draw(float delta); }
рдореЙрдбрд▓ рдХреЛ рджреГрд╢реНрдп рд╕реЗ рдЕрд▓рдЧ рдХрд░реЗрдВред
рдЦреЗрд▓ рд╡рд╕реНрддреБрдУрдВ рдХреЛ рдЦреАрдВрдЪрдиреЗ рд╡рд╛рд▓рд╛ рдХреЛрдИ рднреА рд╡рд░реНрдЧ рдПрдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд▓рд╛рдЧреВ рдХрд░реЗрдЧрд╛ред
public interface Drawer { void draw(BaseObject obj, float delta); }
рдорд▓реНрдЯреАрдкреНрд▓реЗрдпрд░ рдХреЗ рд▓рд┐рдП рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░рддреЗ рд╣реБрдП, рдЕрд░реНрдерд╛рддреН, рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рдЕрд▓рдЧ рдХрд░рдиреЗ рдФрд░ рд╕рд░реНрд╡рд░ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рдПрдХ рдЕрд▓рдЧ рд╡рд░реНрдЧ рдореЗрдВ рдЦреАрдВрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рдлрд╝реАрд▓реНрдб рдирд┐рдХрд╛рд▓рддреЗ рд╣реИрдВред
public abstract class State { public byte type; public float x, y; }
рдЗрд╕ рдкреНрд░рдХрд╛рд░, рд╣рдо рдХреЗрд╡рд▓ рдЧреНрд░рд╛рд╣рдХ рдкрдХреНрд╖ рдкрд░ рдПрдХ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рд╕реНрдЯреЛрд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдореЙрдбрд▓ рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рдиреЗ рдХреА рдХреЛрдИ рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реЛрдЧреАред
рдЬрдм рдЦреЗрд▓ рдореЗрдВ рдмрд╣реБрдд рд╕рд╛рд░реЗ рдСрдмреНрдЬреЗрдХреНрдЯ рд╣реЛрддреЗ рд╣реИрдВ, рддреЛ рдЗрд╕ рддрд░рд╣ рдХреЗ рдХреЛрдб рдХреЛ рдмрдирд╛рдП рд░рдЦрдирд╛ рдФрд░ рдирдИ рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдХреЛ рдЬреЛрдбрд╝рдирд╛ рдмрд╣реБрдд рдореБрд╢реНрдХрд┐рд▓ рд╣реЛ рдЧрдпрд╛ред
рдШрдЯрдХреЛрдВ рдХреЗ рд▓рд┐рдП рд╕рдВрдХреНрд░рдордг рдиреЗ рдирдИ рдЧреЗрдо рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреА рд╕реБрд╡рд┐рдзрд╛ рдкреНрд░рджрд╛рди рдХреА, рдХреНрдпреЛрдВрдХрд┐ рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ рдПрдХ рдирдИ рдЗрдХрд╛рдИ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдПрдХ рдирд┐рд░реНрдорд╛рддрд╛ рдерд╛ред
рдЦреЗрд▓ рдореЗрдВ рд╕рднреА рд╡рд╕реНрддреБрдУрдВ рдХреЛ рдПрдВрдЯрд┐рдЯреА рдмреЗрд╕ рдХреНрд▓рд╛рд╕ рд╕реЗ рд╡рд┐рд░рд╛рд╕рдд рдореЗрдВ рдорд┐рд▓рд╛ рд╣реИ, рдФрд░ рдПрдХрдорд╛рддреНрд░ рдЕрдВрддрд░ getState () рд╡рд┐рдзрд┐ рдФрд░ рдШрдЯрдХреЛрдВ рдХреЗ рдПрдХ рдЕрд▓рдЧ рд╕реЗрдЯ рджреНрд╡рд╛рд░рд╛ рд▓реМрдЯрд╛рдП рдЧрдП рд░рд╛рдЬреНрдп рдореЗрдВ рд╣реИред
рдРрд╕реЗ рд╡рд░реНрдЧ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг public class StoneBox extends Entity { private StoneBoxState stoneBoxState = new StoneBoxState(); private SolidBodyComponent solidBody; private MapBodyComponent mapBody; public StoneBox(SorterEntityManager entityManager, float x, float y) { super(entityManager); type = EntityType.BRICK_STONE; solidBody = new SolidBodyComponent(this); solidBody.isStatic = true; solidBody.rectangle.x = x; solidBody.rectangle.y = y; mapBody = new MapBodyComponent(this); SorterComponent sorterComponent = new SorterComponent(this, entityManager); addComponent(solidBody); addComponent(mapBody); addComponent(sorterComponent); } @Override public State getState() { stoneBoxState.x = solidBody.rectangle.x; stoneBoxState.y = solidBody.rectangle.y; return stoneBoxState; } }
рдЦреЗрд▓ рдХреА рд╕рдВрд░рдЪрдирд╛ рдореЗрдВ рдХрд╛рдлреА рдмрджрд▓рд╛рд╡ рдЖрдпрд╛ рд╣реИ, рдФрд░ рд╕рдВрд╕реНрдерд╛рдУрдВ рдХреЗ рдЕрд▓рдЧрд╛рд╡ рдиреЗ рд╣рдореЗрдВ рдЗрд╕ рддрд░рд╣ рдХрд╛ рдПрдХ рдЧреБрдЪреНрдЫрд╛ рдмрдирд╛рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреА рд╣реИ:
Server -> ServerImplementation <-> ClientImplementation <- Client
рдПрдХ рдиреЗрдЯрд╡рд░реНрдХ рдЧреЗрдо рдФрд░ рдПрдХ рд╕реНрдерд╛рдиреАрдп рдПрдХ рдХреЗ рдмреАрдЪ рд╕рднреА рдЕрдВрддрд░ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд▓рд┐рдП рдиреАрдЪреЗ рдЖрддреЗ рд╣реИрдВред
рд╕рд░реНрд╡рд░ рд╡рд░реНрдЧ рдХреА рдХреНрд░рд┐рдпрд╛рдПрдВ рдкреНрд░рддреНрдпреЗрдХ рдлреНрд░реЗрдо рд╣реИрдВ - рдпрд╣
ServerImplementation
рд▓рд┐рдП рд░рд╛рдЬреНрдпреЛрдВ рдХреА рд╡рд░реНрддрдорд╛рди рд╕рд░рдгреА рджреЗрддрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ
ServerImplementation
ред
рдпрд╣ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:
public class LocalServerImpl { ... public void update(float delta){ clientImpl.states = server.getStates(); ... } }
Client
рд╡рд░реНрдЧ, рдкреНрд░рддреНрдпреЗрдХ рдлрд╝реНрд░реЗрдо
ClientImplementation
рд╕реЗ рд╡рд░реНрддрдорд╛рди рд╕реНрдерд┐рддрд┐ рд▓реЗрддрд╛ рд╣реИ, рдФрд░ рдлрд┐рд░ рд╕реНрдХреНрд░реАрди рдкрд░ рдкреНрд░рд╛рдкреНрдд рдбреЗрдЯрд╛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИред
рдмреЗрд╢рдХ, рди рдХреЗрд╡рд▓ рд░рд╛рдЬреНрдпреЛрдВ рдХреЛ рдкреНрд░реЗрд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдмрд▓реНрдХрд┐ рдЦреЗрд▓ рдХреА рд╢реБрд░реБрдЖрдд, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЖрджреЗрд╢реЛрдВ рдФрд░ рдЕрдиреНрдп рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рднреА рдШрдЯрдирд╛рдПрдВ рд╣реЛрддреА рд╣реИрдВред рдЙрдирдХрд╛ рддрд░реНрдХ рд░рд╛рдЬреНрдп рд╕реНрдерд╛рдирд╛рдВрддрд░рдг рд╕реЗ рдЕрд▓рдЧ рдирд╣реАрдВ рд╣реИред
рдЕрдм, рдиреЗрдЯрд╡рд░реНрдХ рдореЛрдб рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ
ServerImplementation <-> ClientImplementation
рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рдмрджрд▓рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ
ServerImplementation <-> ClientImplementation
, рдФрд░ рд░рд╛рдЬреНрдп рд╡рд░реНрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рднреА,
ServerImplementation <-> ClientImplementation
рдФрд░
ServerImplementation <-> ClientImplementation
рд▓рд┐рдП рдПрдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд▓рд╛рдЧреВ рдХрд░реЗрдВ:
public interface BinaryParser { void parseBinary(DataInputStream stream); void fillBinary(DataOutputStream stream); }
рдРрд╕реЗ рд╡рд░реНрдЧ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг public class StoneBoxState extends State { public StoneBoxState() { super(StateType.STONE_BOX); } @Override public void parseBinary(DataInputStream stream) { x = StreamUtils.readFloat(stream); y = StreamUtils.readFloat(stream); } @Override public void fillBinary(DataOutputStream stream) { StreamUtils.writeByte(stream, type); StreamUtils.writeFloat(stream, x); StreamUtils.writeFloat(stream, y); } }
рдкрд░рд╕рд┐рдВрдЧ рдореЗрдВ рд╣рдо рдЯрд╛рдЗрдк рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рдмрд╛рдЗрдЯ рдХреЛ рдХреНрдпреЛрдВ рдирд╣реАрдВ рдкрдврд╝рддреЗ рд╣реИрдВ? рдЗрдирдкреБрдЯ рдмрд╛рдЗрдЯ рд╕рд░рдгреА рд╕реЗ рд╣рдореЗрдВ рдЬрд┐рд╕ рдЗрдХрд╛рдИ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЙрд╕реЗ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдирд┐рд░реНрдзрд╛рд░рдг рдХрд░рддреЗ рд╕рдордп рд╣рдо рдЗрд╕реЗ рдкрдврд╝рддреЗ рд╣реИрдВред
рд░рд╛рдЬреНрдп рдХреА рдкрд╛рд░реНрд╕рд┐рдВрдЧ public static State parseState(DataInputStream stream) { byte type = StreamUtils.readByte(stream); State state = null; switch (type) { case STONE_BOX: state = new StoneBoxState(); break; ... } state.parseBinary(stream); return state; }
рдореИрдВрдиреЗ рдиреЗрдЯрд╡рд░реНрдХ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП
рдХреНрд░рд╛рдпреЛрдиреЗрдЯ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛, рдпрд╣ рдмрд╣реБрдд рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ рдпрджрд┐ рдЖрдк рдЬрд╛рдирдирд╛ рдирд╣реАрдВ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдХрд┐ рдбреЗрдЯрд╛ рдкреИрдХреЗрдЯ рдХреИрд╕реЗ рдкреНрд░рд╕рд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдХреЗрд╡рд▓ рдкрд░рд┐рдгрд╛рдо рдЖрдкрдХреЗ рд▓рд┐рдП рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИред
LocalServerImpl
рдХреЛ
NetworkServerImpl
рдмрджрд▓ рджреЗрддреЗ рд╣реИрдВ, рдбреЗрдЯрд╛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдирд╛ рдЕрдзрд┐рдХ рдХрдард┐рди рдирд╣реАрдВ рд╣реИ:
рдЦреЗрд▓ рдХреА рд╕реНрдерд┐рддрд┐ рднреЗрдЬ рд░рд╣рд╛ рд╣реИ Array<State> states = entityManager.getStates(); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); DataOutputStream dataOutputStream = new DataOutputStream(byteArrayOutputStream); StreamUtils.writeByte(dataOutputStream, GameMessages.MESSAGE_SNAPSHOT); for (int i = 0; i < states.size; i++) { states.get(i).fillBinary(dataOutputStream); } byte[] array = byteArrayOutputStream.toByteArray(); byte[] compressedData = CompressionUtils.compress(array); sendToAllUDP(compressedData);
рд╣рдореЗрдВ рд╡рд░реНрддрдорд╛рди рд╕реНрдерд┐рддрд┐ рдорд┐рд▓рддреА рд╣реИ, рдЗрд╕реЗ рдмрд╛рдЗрдЯ рд╕рд░рдгреА рдореЗрдВ рд▓рд┐рдЦреЗрдВ, рдЗрд╕реЗ рд╕рдВрдЧреНрд░рд╣рд┐рдд рдХрд░реЗрдВ, рдЗрд╕реЗ рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреЛ рднреЗрдЬреЗрдВред
рдХреНрд▓рд╛рдЗрдВрдЯ рдкрд░, рдЕрдВрддрд░ рднреА рдиреНрдпреВрдирддрдо рд╣реИрдВ, рдпрд╣ рд░рд╛рдЬреНрдпреЛрдВ рдХреЛ рднреА рдкреНрд░рд╛рдкреНрдд рд╣реЛрдЧрд╛, рд▓реЗрдХрд┐рди рд╡реЗ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдиреЗрдЯрд╡рд░реНрдХ рдкрд░ рдЖ рдЬрд╛рдПрдВрдЧреЗ:
рдЦреЗрд▓ рдХреА рд╕реНрдерд┐рддрд┐ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ private void onReceivedData(byte[] data) { byte[] result = CompressionUtils.decompress(data); ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(result); DataInputStream dataInputStream = new DataInputStream(byteArrayInputStream); byte messageType = StreamUtils.readByte(dataInputStream); switch (messageType) { ... case GameMessages.MESSAGE_SNAPSHOT: snapshot.clear(); try { while (dataInputStream.available() > 0) { snapshot.add(StateType.parseState(dataInputStream)); } } catch (IOException e) { e.printStackTrace(); } break; } }
рдХреНрд▓рд╛рдЗрдВрдЯ рдФрд░ рд╕рд░реНрд╡рд░ рдХреЗ рдмреАрдЪ рд╕рдВрджреЗрд╢ рдХреЗ рдкреНрд░рдХрд╛рд░ public static final byte MESSAGE_PLAYER_ACTION = 0; public static final byte MESSAGE_SNAPSHOT = 1; public static final byte MESSAGE_ADD_PLAYER = 2; public static final byte MESSAGE_GAME_OVER = 3; public static final byte MESSAGE_LEVEL_COMPLETE = 4; public static final byte MESSAGE_LOADED_NEW_LEVEL = 5; public static final byte MESSAGE_CHANGE_ZOOM_LEVEL = 6;
рдХреНрд▓рд╛рдЗрдВрдЯ рд╕рд╛рдЗрдб рдкрд░ рдХреЛрдИ рднреА рдХрд╛рд░реНрд░рд╡рд╛рдИ рдкрд╣рд▓реЗ рд╕рд░реНрд╡рд░ рдкрд░ рднреЗрдЬреА рдЬрд╛рддреА рд╣реИ, рд╕рд░реНрд╡рд░ рдкрд░ рд╕реНрдерд┐рддрд┐ рдмрджрд▓ рдЬрд╛рддреА рд╣реИ рдФрд░ рдпрд╣ рдбреЗрдЯрд╛ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рд╡рд╛рдкрд╕ рдХрд░ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рдореИрдВрдиреЗ рдПрдХ рдЫреЛрдЯрд╛ рд╡реАрдбрд┐рдпреЛ рд░рд┐рдХреЙрд░реНрдб рдХрд┐рдпрд╛ рд╣реИ рдЬреЛ рдиреЗрдЯрд╡рд░реНрдХ рдореЛрдб рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИ (libgdx рдЗрдВрдЬрди рдЖрдкрдХреЛ рдкреАрд╕реА рдкрд░ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдЪрд▓рд╛рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ)