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; }
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
and transmits to the client. public class LocalServerImpl { ... public void update(float delta){ clientImpl.states = server.getStates(); ... } }
Client
class each frame takes the current state from ClientImplementation
, and then displays the received data on the screen.ServerImplementation <-> ClientImplementation
, as well as for the state classes to implement an interface for serialization and deserialization: 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
replace on NetworkServerImpl
, transfer data is not more difficult: 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;
Source: https://habr.com/ru/post/200880/
All Articles