Edit Game Settings via Wfi

- Several settings can be updates via wifi during game play
- Some seetings code cleanup
This commit is contained in:
bdring
2018-03-28 12:41:31 -05:00
parent a85100afd9
commit 1959787e9b
4 changed files with 169 additions and 67 deletions

View File

@@ -20,11 +20,20 @@ This was ported from the [TWANG fork](https://github.com/bdring/TWANG) by bdring
- **SSID:** TWANG_AP
- **Password:** esp32rocks
- **URL:** 192.168.4.1
- You can update these settings over wifi
- LED Brightness
- Audio Volume
- Joystick Deadzone (removes drift)
- Attack Threshold (twang sensitivity)
- Lives Per Level
**Coming Soon:**
- Wireless features
- ~~A wireless version of the serial port features of TWANG. I think the easiest way is to make it a Wifi access point with a simple web page interface. This allows control by any smartphone or computer with no client side work required.~~
![](http://www.buildlog.net/blog/wp-content/uploads/2018/03/20180328_122254.jpg)
Coming Soon:**
- Wireless features~~
- 2 Player features by linking controllers. TBD
- Digitized Audio
- Currently the port uses the same square wave tones of the the Arduino version.

View File

@@ -6,7 +6,7 @@
TWANG was originally created by Critters
https://github.com/Critters/TWANG
It was inspired by Robin Baumgarten's Line Wobbler Game_Audio
It was inspired by Robin Baumgarten's Line Wobbler Game
*/
@@ -288,7 +288,6 @@ void loop() {
tickWin(mm);
}else if(stage == BOSS_KILLED){
tickBossKilled(mm);
//tickComplete(mm);
} else if (stage == GAMEOVER) {
if (stageStartTime+GAMEOVER_FADE_DURATION > mm)
{
@@ -297,7 +296,7 @@ void loop() {
else
{
FastLED.clear();
save_game_stats(false);
save_game_stats(false); // boss not killed
//score = 0; // reset the score
levelNumber = 0;
lives = user_settings.lives_per_level;
@@ -874,6 +873,7 @@ void tickBossKilled(long mm) // boss funeral
}
SFXcomplete();
}else{
save_game_stats(true); // true = boss was killed
nextLevel();
}
}
@@ -1018,11 +1018,6 @@ bool inLava(int pos){
}
void updateLives(){
// Updates the life LEDs to show how many lives the player has left
//for(int i = 0; i<LIFE_LEDS; i++){
// digitalWrite(lifeLEDs[i], lives>i?HIGH:LOW);
//}
drawLives();
}

View File

@@ -10,20 +10,36 @@
#define EEPROM_SIZE 256
// LEDS
#define BRIGHTNESS 150
#define DEFAULT_BRIGHTNESS 150
#define MIN_BRIGHTNESS 10
#define MAX_BRIGHTNESS 255
// PLAYER
const uint8_t MAX_PLAYER_SPEED = 10; // Max move speed of the player
const uint8_t LIVES_PER_LEVEL = 3; // default lives per level
#define MIN_LIVES_PER_LEVEL 3
#define MAX_LIVES_PER_LEVEL 9
// JOYSTICK
#define JOYSTICK_ORIENTATION 1 // 0, 1 or 2 to set the axis of the joystick
#define JOYSTICK_DIRECTION 1 // 0/1 to flip joystick direction
#define ATTACK_THRESHOLD 30000 // The threshold that triggers an attack
#define JOYSTICK_DEADZONE 8 // Angle to ignore
#define DEFAULT_ATTACK_THRESHOLD 30000 // The threshold that triggers an attack
#define MIN_ATTACK_THRESHOLD 20000
#define MAX_ATTACK_THRESHOLD 30000
#define DEFAULT_JOYSTICK_DEADZONE 8 // Angle to ignore
#define MIN_JOYSTICK_DEADZONE 3
#define MAX_JOYSTICK_DEADZONE 12
// AUDIO
#define MAX_VOLUME 180 // 0 to 255
#define DEFAULT_VOLUME 180 // 0 to 255
#define MIN_VOLUME 0
#define MAX_VOLUME 255
#define DAC_AUDIO_PIN 25 // should be 25 or 26 only
enum ErrorNums{
@@ -80,11 +96,6 @@ uint8_t readIndex = 0;
void settings_init() {
//if (!EEPROM.begin(EEPROM_SIZE))
//{
// Serial.println("failed to initialize EEPROM");
//}
settings_eeprom_read();
show_settings_menu();
show_game_stats();
@@ -187,11 +198,12 @@ void change_setting(char *line) {
switch (param) {
case 'B': // brightness
if(newValue >=5 && newValue <=255) {
if(newValue >= MIN_BRIGHTNESS && newValue <= MAX_BRIGHTNESS) {
user_settings.led_brightness = (uint8_t)newValue;
settings_eeprom_write();
delay(1000);
ESP.restart(); // this one requires a restart right now
FastLED.setBrightness(user_settings.led_brightness);
//delay(1000);
//ESP.restart(); // this one requires a restart right now
}
else {
printError(ERR_SETTING_RANGE);
@@ -200,7 +212,7 @@ void change_setting(char *line) {
break;
case 'S': // sound
if (newValue >=0 && newValue < 255)
if (newValue >=MIN_VOLUME && newValue <= MAX_VOLUME)
user_settings.audio_volume = (uint8_t)newValue;
else {
printError(ERR_SETTING_RANGE);
@@ -209,7 +221,7 @@ void change_setting(char *line) {
break;
case 'D': // deadzone, joystick
if(newValue >=3 && newValue <=12)
if(newValue >=MIN_JOYSTICK_DEADZONE && newValue <=MAX_JOYSTICK_DEADZONE)
user_settings.joystick_deadzone = (uint8_t)newValue;
else {
printError(ERR_SETTING_RANGE);
@@ -218,7 +230,7 @@ void change_setting(char *line) {
break;
case 'A': // attack threshold, joystick
if(newValue >=20000 && newValue <=35000)
if(newValue >=MIN_ATTACK_THRESHOLD && newValue <=MAX_ATTACK_THRESHOLD)
user_settings.attack_threshold = (uint16_t)newValue;
else {
printError(ERR_SETTING_RANGE);
@@ -249,12 +261,12 @@ void change_setting(char *line) {
void reset_settings() {
user_settings.settings_version = SETTINGS_VERSION;
user_settings.led_brightness = BRIGHTNESS;
user_settings.led_brightness = DEFAULT_BRIGHTNESS;
user_settings.joystick_deadzone = JOYSTICK_DEADZONE;
user_settings.attack_threshold = ATTACK_THRESHOLD;
user_settings.joystick_deadzone = DEFAULT_JOYSTICK_DEADZONE;
user_settings.attack_threshold = DEFAULT_ATTACK_THRESHOLD;
user_settings.audio_volume = MAX_VOLUME;
user_settings.audio_volume = DEFAULT_VOLUME;
user_settings.lives_per_level = LIVES_PER_LEVEL;
@@ -297,10 +309,6 @@ void show_settings_menu() {
Serial.println(" ? to show current settings");
Serial.println(" R to reset everything to defaults)");
Serial.println(" P to reset play statistics)");
//Serial.println(" E to write changes to eeprom)");
//Serial.println(" ! to restart with current settings");
show_game_stats();
}
void show_game_stats()
@@ -314,9 +322,7 @@ void show_game_stats()
Serial.print("Boss kills: ");Serial.println(user_settings.boss_kills);
}
void settings_eeprom_read()
{
Serial.println("Begin EEPROM Read");
void settings_eeprom_read() {
EEPROM.begin(EEPROM_SIZE);
@@ -338,9 +344,11 @@ void settings_eeprom_read()
temp[i] = EEPROM.read(i);
}
EEPROM.end();
memcpy((char*)&user_settings, temp, sizeof(user_settings));
EEPROM.end();
}
@@ -353,9 +361,6 @@ void settings_eeprom_write() {
uint8_t temp[sizeof(user_settings)];
memcpy(temp, (uint8_t*)&user_settings, sizeof(user_settings));
Serial.println("Writing settings...");
for (int i=0; i<sizeof(user_settings); i++)
{
EEPROM.write(i, temp[i]);

103
wifi_ap.h
View File

@@ -1,10 +1,14 @@
#include <WiFi.h>
#include "settings.h"
const char* ssid = "TWANG_AP";
const char* passphrase = "esp32rocks";
WiFiServer server(80);
char linebuf[80];
int charcount=0;
void ap_setup() {
bool ret;
@@ -19,14 +23,13 @@ void ap_setup() {
*/
ret = WiFi.softAP(ssid, passphrase, 2, 0);
Serial.println("\r\nWiFi AP online ...");
//Serial.println("\r\nWiFi AP online ...");
server.begin();
}
void sendStatsPage(WiFiClient client) {
Serial.println("printUploadForm");
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
@@ -37,6 +40,7 @@ void sendStatsPage(WiFiClient client) {
client.println("<h1>TWANG32 Play Stats</h1>");
client.println("<ul>");
client.print("<li>Games played: "); client.print(user_settings.games_played); client.println("</li>");
if (user_settings.games_played > 0) { // prevent divide by 0
client.print("<li>Average score: "); client.print(user_settings.total_points / user_settings.games_played); client.println("</li>");
@@ -44,7 +48,32 @@ void sendStatsPage(WiFiClient client) {
client.print("<li>High score: "); client.print(user_settings.high_score); client.println("</li>");
client.print("<li>Boss kills: "); client.print(user_settings.boss_kills); client.println("</li>");
client.println("</ul>");
client.print("<h2>Adjustable Settings </h2>");
client.print("<table>");
client.print("<tr><td>Brightness</td><td><form><input type='text' name='B' value='");
client.print(user_settings.led_brightness);
client.print ("' size='4'><input type='submit'></form></td></tr>");
client.print("<tr><td>Sound Volume</td><td><form><input type='text' name='S' value='");
client.print(user_settings.audio_volume);
client.print("' size='4'><input type='submit'></form></td></tr>");
client.print("<tr><td>Joystick Deadzone (3-12)</td><td><form><input type='text' name='D' value='");
client.print(user_settings.joystick_deadzone);
client.print("' size='4'><input type='submit'></form></td></tr>");
client.print("<tr><td>Attack Sensitivity (20000-35000)</td><td><form><input type='text' name='A' value='");
client.print(user_settings.attack_threshold);
client.print("' size='4'><input type='submit'></form></td></tr>");
client.print("<tr><td>Lives Per Level (3-9)</td><td><form><input type='text' name='L' value='");
client.print(user_settings.lives_per_level);
client.print("' size='4'><input type='submit'></form></td></tr>");
client.print("</table>");
client.println("</body>");
client.println("</html>");
client.println();
@@ -57,9 +86,73 @@ void ap_client_check(){
int stat;
WiFiClient client = server.available(); // listen for incoming clients
if (client) { // if you get a client,
//if (client) { // if you get a client,
// sendStatsPage(client);
// Serial.println("printUploadForm");
//}
bool currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
//Serial.write(c);
linebuf[charcount]=c;
if (charcount<sizeof(linebuf)-1)
charcount++;
if (c == '\n' && currentLineIsBlank) {
sendStatsPage(client);
Serial.println("printUploadForm");
break;
}
if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
if (strstr(linebuf,"GET /?") > 0)
{
String line = String(linebuf);
int start = line.indexOf('=', 0) + 1;
int finish = line.indexOf('H', start)-1;
String val = line.substring(start, finish);
// if it is not numeric, it will convert to 0.
// The constrain functions will make it 0 or the min value
if (strstr(linebuf,"B=") > 0){ // typically look like this "GET /?S=100 HTTP/1.1"
user_settings.led_brightness = constrain(val.toInt(), MIN_BRIGHTNESS, MAX_BRIGHTNESS);
FastLED.setBrightness(user_settings.led_brightness);
settings_eeprom_write();
}
else if (strstr(linebuf,"S=") > 0){
//String val = line.substring(start, finish);
user_settings.audio_volume = constrain(val.toInt(), MIN_VOLUME, MAX_VOLUME);
settings_eeprom_write();
}
else if (strstr(linebuf,"D=") > 0){
user_settings.joystick_deadzone = constrain(val.toInt(), MIN_JOYSTICK_DEADZONE, MAX_JOYSTICK_DEADZONE);
settings_eeprom_write();
}
else if (strstr(linebuf,"A=") > 0){
user_settings.attack_threshold = constrain(val.toInt(), MIN_ATTACK_THRESHOLD, MAX_ATTACK_THRESHOLD);
settings_eeprom_write();
}
else if (strstr(linebuf,"L=") > 0){
user_settings.lives_per_level = constrain(val.toInt(), MIN_LIVES_PER_LEVEL, MAX_LIVES_PER_LEVEL);
settings_eeprom_write();
}
}
// you're starting a new line
currentLineIsBlank = true;
memset(linebuf,0,sizeof(linebuf));
charcount=0;
} else if (c != '\r') {
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
}