Skip to content

Commit

Permalink
Add player names support in network games
Browse files Browse the repository at this point in the history
The GUI will now request a player name once when enabling network
features. Names will be displayed for people you are hitting, people
that are hitting you, people that eliminated you, and when you score
a point.

A team score is now displayed. When someone on your team scores a
point, the team score will be updated. If a score limit is set,
the game will end when one team reaches the score limit.

Added a sound that plays when you score a point in network games.

Fixed a few bugs (and probably created a couple of new bugs).
  • Loading branch information
Dees-Troy committed Jan 20, 2018
1 parent 9f78eb8 commit c5c54e2
Show file tree
Hide file tree
Showing 9 changed files with 318 additions and 69 deletions.
4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ android {
applicationId "com.simplecoil.simplecoil"
minSdkVersion 21
targetSdkVersion 26
versionCode 2
versionName "1.1"
versionCode 3
versionName "1.2"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/assets/simplecoil.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
<p style="color: #ffffff">SimpleCoil is intended to be used with RECOIL laser tag toys and cannot be used without the appropriate accessories. This app does not need a Wi-Fi connection or hub to be used. Some of the advanced features that you may be used to with the first-party app are not available here. However, this simple app will not experience any connection issues and should run well on older, slower devices.</p>
<p style="color: #ffffff">Tap the power button to toggle recoil. Tap the thumb/rear/talk button to switch firing modes.</p>
<p style="color: #ffffff">Players that are on the same team cannot shoot each other - no friendly fire.</p>
<p style="color: #ffffff">Network support is rudimentary and may not work reliably. The network support does not require the use of the official hub, but will work with the official hub. Instead of using a server, clients will attempt to find and connect to each other directly over the same Wi-Fi network.</p>
<p style="color: #ffffff">The network support does not require the use of the official hub, but will work with the official hub. Instead of using a server, clients will attempt to find and connect to each other directly over the same Wi-Fi network.</p>
</HTML>
196 changes: 152 additions & 44 deletions app/src/main/java/com/simplecoil/simplecoil/FullscreenActivity.java

Large diffs are not rendered by default.

112 changes: 95 additions & 17 deletions app/src/main/java/com/simplecoil/simplecoil/UDPListenerService.java
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ public class UDPListenerService extends Service {
public static final String UDPMSG_LIMITLIVES = "UDPLIMITLIVES";
public static final String UDPMSG_LIMITSCORE = "UDPLIMITSCORE";
public static final String UDPMSG_UNLIMITED = "UDPUNLIMITED";
public static final String UDPMSG_PLAYERNAME = "UDPPLAYERNAME";
public static final String UDPMSG_TEAMELIMINATED = "UDPTEAMELIMINATED";

// UDPJOIN is UDPJOIN + playerID, so UDPJOIN2 for playerID 2
public static final String UDPMSG_JOIN = "UDPJOIN";
Expand All @@ -87,6 +89,7 @@ prefixed with the game mode so something like this (the leading 4 means 4 teams)
private int mLivesLimit = 0;

private volatile byte mPlayerID = 0;
private volatile String mPlayerName = "";

DatagramSocket socketBroadcast;
DatagramSocket socketGame;
Expand All @@ -96,6 +99,7 @@ prefixed with the game mode so something like this (the leading 4 means 4 teams)

private Map<InetAddress, Byte> mIPTeamMap;
private Map<Byte, InetAddress> mTeamIPMap;
private Map<Byte, String> mTeamPlayerNameMap;

private InetAddress mMyIP = null;
private InetAddress mBroadcastAddress = null;
Expand All @@ -107,11 +111,16 @@ prefixed with the game mode so something like this (the leading 4 means 4 teams)
private static volatile boolean doneListeningBroadcast = true;
private static volatile boolean doneListening = true;
private static volatile boolean mIsListService = false;
private static volatile boolean mSentPlayerName = false;
private static volatile int mReadyToScan = 0;

private volatile boolean mScanRunning = false;
private volatile boolean mGameRunning = false;

public static final String INTENT_PLAYERID = "playerid";
public static final String INTENT_LIMIT = "limit";
public static final String INTENT_MESSAGE = "message";

/**
* Get IP address from first non-localhost interface
* @return address or empty string
Expand Down Expand Up @@ -208,7 +217,7 @@ private void processMessage(InetAddress ip, String message) {
}
}
if (ip.equals(mMyIP)) {
Log.d(TAG, "IP matched so ignored");
//Log.d(TAG, "IP matched so ignored");
return;
}
if (message.startsWith(MESSAGE_PREFIX)) {
Expand All @@ -219,12 +228,15 @@ private void processMessage(InetAddress ip, String message) {
} else if (message.startsWith(UDPMSG_HIT)) {
// you hit someone!
intent = new Intent(UDPMSG_HIT);
intent.putExtra(INTENT_PLAYERID, mIPTeamMap.get(ip));
} else if (message.startsWith(UDPMSG_OUT)) {
// hitting a player that's already out
intent = new Intent(UDPMSG_OUT);
intent.putExtra(INTENT_PLAYERID, mIPTeamMap.get(ip));
} else if (message.startsWith(UDPMSG_ELIMINATED)) {
// you eliminated someone!
intent = new Intent(UDPMSG_ELIMINATED);
intent.putExtra(INTENT_PLAYERID, mIPTeamMap.get(ip));
} else if (message.startsWith(UDPMSG_JOIN)) {
if (mIPTeamMap == null)
mIPTeamMap = new HashMap<InetAddress, Byte>();
Expand Down Expand Up @@ -282,11 +294,19 @@ private void processMessage(InetAddress ip, String message) {
Log.e(TAG, "unrecognized IP " + ipStr);
}
}
Log.d(TAG, "Added " + playersAdded + "players");
Log.d(TAG, "Added " + playersAdded + " players");
mServerIP = ip;
if (!mSentPlayerName) {
mSentPlayerName = true;
sendUDPMessage(MESSAGE_PREFIX + UDPMSG_PLAYERNAME + String.format("%02d", mPlayerID) + mPlayerName, mServerIP, GAME_LISTEN_PORT);
}
intent = new Intent(UDPMSG_LISTPLAYERS);
} else if (message.startsWith(UDPMSG_LEAVE)) {
// This is a player left message
if (mIPTeamMap == null)
mIPTeamMap = new HashMap<InetAddress, Byte>();
if (mTeamIPMap == null)
mTeamIPMap = new HashMap<Byte, InetAddress>();
Byte team = mIPTeamMap.get(ip);
mTeamIPMap.remove(team);
mIPTeamMap.remove(ip);
Expand Down Expand Up @@ -318,22 +338,38 @@ private void processMessage(InetAddress ip, String message) {
message = message.substring(UDPMSG_LIMITTIME.length());
int limit = (int) Integer.parseInt(message);
intent = new Intent(UDPMSG_LIMITTIME);
intent.putExtra("limit", limit);
intent.putExtra(INTENT_LIMIT, limit);
} else if (message.startsWith(UDPMSG_LIMITLIVES)) {
// Game limited by lives
message = message.substring(UDPMSG_LIMITLIVES.length());
int limit = (int) Integer.parseInt(message);
intent = new Intent(UDPMSG_LIMITLIVES);
intent.putExtra("limit", limit);
intent.putExtra(INTENT_LIMIT, limit);
} else if (message.startsWith(UDPMSG_LIMITSCORE)) {
// Game limited by score
message = message.substring(UDPMSG_LIMITSCORE.length());
int limit = (int) Integer.parseInt(message);
intent = new Intent(UDPMSG_LIMITSCORE);
intent.putExtra("limit", limit);
intent.putExtra(INTENT_LIMIT, limit);
} else if (message.startsWith(UDPMSG_UNLIMITED)) {
// No game limit
intent = new Intent(UDPMSG_UNLIMITED);
} else if (message.startsWith(UDPMSG_PLAYERNAME)) {
// Player name
if (mTeamPlayerNameMap == null)
mTeamPlayerNameMap = new HashMap<Byte, String>();
message = message.substring(UDPMSG_PLAYERNAME.length());
String teamStr = message.substring(0, 2);
Byte team = (byte) (int) Integer.parseInt(teamStr);
message = message.substring(2);
mTeamPlayerNameMap.remove(team);
mTeamPlayerNameMap.put(team, message);
if (mIsListService) {
sendPlayerNames();
}
} else if (message.startsWith(UDPMSG_TEAMELIMINATED)) {
// Someone else on your team scored a point
intent = new Intent(UDPMSG_TEAMELIMINATED);
}
}
if (intent != null)
Expand Down Expand Up @@ -378,6 +414,29 @@ public void run() {
sendBroadcast(intent);
}

private void sendPlayerNames() {
Log.d(TAG, "sending player names");
if (mMyIP == null) {
try {
mMyIP = InetAddress.getByName(getIPAddress());
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
Thread sendListThread = new Thread(new Runnable() {
public void run() {
String message = UDPMSG_PLAYERNAME + String.format("%02d", mPlayerID) + mPlayerName;
sendUDPMessageAll(message);
for (Map.Entry<Byte, String> entry : mTeamPlayerNameMap.entrySet()) {
sleep(100);
message = UDPMSG_PLAYERNAME + String.format("%02d", entry.getKey()) + entry.getValue();
sendUDPMessageAll(message);
}
}
});
sendListThread.start();
}

Thread UDPBroadcastThread;

public void startListenForUDPBroadcast() {
Expand Down Expand Up @@ -459,16 +518,24 @@ private InetAddress getBroadcastAddress() {
}

public String getIP() {
if (mServerIP != null)
return mServerIP.toString();
String ip = "";
if (mServerIP != null) {
ip = mServerIP.toString();
if (ip.startsWith("/"))
ip = ip.substring(1);
return ip;
}
if (mMyIP == null) {
try {
mMyIP = InetAddress.getByName(getIPAddress());
} catch (UnknownHostException e) {
return null;
return "";
}
}
return mMyIP.toString();
ip = mMyIP.toString();
if (ip.startsWith("/"))
ip = ip.substring(1);
return ip;
}

public void createServer() {
Expand Down Expand Up @@ -553,7 +620,6 @@ public void run() {
sendFailedJoin();
return;
}
Log.e(TAG, "got here at least");
joinServer(ipAddr);
}
});
Expand Down Expand Up @@ -584,6 +650,7 @@ public void joinServer(InetAddress serverIP, Integer port) {
mScanRunning = true;
mGameRunning = false;
mReadyToScan = 0;
mSentPlayerName = false;
startListenForUDPGame();
startJoinFailTimer();
while(mReadyToScan < 1) {
Expand Down Expand Up @@ -630,13 +697,13 @@ public void sendUDPBroadcast(String message) {
sendUDPMessage(message, mBroadcastAddress, BROADCAST_LISTEN_PORT);
}

public void sendUDPMessage(String message, Byte team) {
public void sendUDPMessage(String message, Byte playerID) {
message = MESSAGE_PREFIX + message;
if (mTeamIPMap.get(team) == null) {
Log.e(TAG, "cannot send message to unknown team " + team);
if (mTeamIPMap.get(playerID) == null) {
Log.e(TAG, "cannot send message to unknown ID " + playerID);
return;
}
sendUDPMessage(message, mTeamIPMap.get(team), GAME_LISTEN_PORT);
sendUDPMessage(message, mTeamIPMap.get(playerID), GAME_LISTEN_PORT);
}

public void sendUDPMessageAll(String message) {
Expand All @@ -661,7 +728,7 @@ public void run() {
//Log.e(TAG, "IO Error:", e);
e.printStackTrace();
Intent intent = new Intent(UDPMSG_ERROR);
intent.putExtra("message", e.getLocalizedMessage());
intent.putExtra(INTENT_MESSAGE, e.getLocalizedMessage());
sendBroadcast(intent);
}
}
Expand Down Expand Up @@ -696,7 +763,7 @@ public void run() {
//Log.e(TAG, "IO Error:", e);
e.printStackTrace();
Intent intent = new Intent(UDPMSG_ERROR);
intent.putExtra("message", e.getLocalizedMessage());
intent.putExtra(INTENT_MESSAGE, e.getLocalizedMessage());
sendBroadcast(intent);
}
}
Expand Down Expand Up @@ -729,7 +796,7 @@ public void run() {
//Log.e(TAG, "IO Error:", e);
e.printStackTrace();
Intent intent = new Intent(UDPMSG_ERROR);
intent.putExtra("message", e.getLocalizedMessage());
intent.putExtra(INTENT_MESSAGE, e.getLocalizedMessage());
sendBroadcast(intent);
}
mSendingMessage = false;
Expand Down Expand Up @@ -834,4 +901,15 @@ private void sleep(long millis) {
}
}

public String getPlayerName(Byte playerID) {
if (mTeamPlayerNameMap == null)
return "";
String ret = mTeamPlayerNameMap.get(playerID);
if (ret == null)
ret = "";
return ret;
}

public void setPlayerName(String name) { mPlayerName = name; }

}
2 changes: 1 addition & 1 deletion app/src/main/res/anim/eliminatedfadeout.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
<alpha
android:fromAlpha="1.0"
android:toAlpha="0.1"
android:duration="400"
android:duration="800"
/>
</set>
63 changes: 60 additions & 3 deletions app/src/main/res/layout/activity_fullscreen.xml
Original file line number Diff line number Diff line change
Expand Up @@ -264,17 +264,28 @@
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:visibility="gone"
android:visibility="invisible"
android:text="@string/starting_game_label"
android:textAppearance="@android:style/TextAppearance.Material.Large.Inverse" />

<TextView
android:id="@+id/spawn_countdown_tv"
android:id="@+id/eliminated_by_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_below="@+id/eliminated_tv"
android:layout_marginTop="10dp"
android:visibility="invisible"
android:text=""
android:textAppearance="@android:style/TextAppearance.Material.Large.Inverse" />

<TextView
android:id="@+id/spawn_countdown_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_below="@+id/eliminated_by_tv"
android:layout_marginTop="10dp"
android:visibility="gone"
android:text="@string/spawn_in_label"
android:textAppearance="@android:style/TextAppearance.Material.Large.Inverse" />
Expand Down Expand Up @@ -390,6 +401,29 @@
android:text="0"
android:textAppearance="@android:style/TextAppearance.Material.Large.Inverse" />

<TextView
android:id="@+id/team_score_label_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/team_score_tv"
android:layout_marginEnd="15dp"
android:layout_alignParentEnd="true"
android:text="@string/team_score_label"
android:visibility="invisible"
android:textAppearance="@android:style/TextAppearance.Material.Small.Inverse" />

<TextView
android:id="@+id/team_score_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="15dp"
android:layout_marginBottom="20dp"
android:layout_alignParentEnd="true"
android:layout_above="@id/score_label_tv"
android:text="0"
android:visibility="invisible"
android:textAppearance="@android:style/TextAppearance.Material.Large.Inverse" />

<Button
android:id="@+id/ready_button"
style="@style/Widget.AppCompat.Button.Colored"
Expand Down Expand Up @@ -430,6 +464,17 @@
android:layout_marginTop="10dp"
android:layout_below="@+id/health_pb" />

<TextView
android:id="@+id/hit_player_name_tv"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/hit_player_iv"
android:layout_marginStart="10dp"
android:layout_marginTop="5dp"
android:text=""
android:textAppearance="@android:style/TextAppearance.Material.Small.Inverse" />

<ImageView
android:id="@+id/shots_fired_iv"
android:visibility="gone"
Expand All @@ -446,12 +491,24 @@
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toStartOf="@id/team_score_label_tv"
android:layout_marginEnd="10dp"
android:layout_alignParentEnd="true"
android:layout_marginTop="10dp"
android:layout_above="@+id/score_label_tv"
app:srcCompat="@drawable/ic_add_circle_green_50dp" />

<TextView
android:id="@+id/score_increase_player_name_tv"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/score_increase_iv"
android:layout_toStartOf="@id/team_score_label_tv"
android:layout_marginEnd="10dp"
android:layout_marginBottom="5dp"
android:text=""
android:textAppearance="@android:style/TextAppearance.Material.Small.Inverse" />

<Chronometer
android:id="@+id/game_timer_chronometer"
style="@android:style/TextAppearance.Material.Small.Inverse"
Expand Down
Loading

0 comments on commit c5c54e2

Please sign in to comment.