Edit Game Settings via Wfi
- Several settings can be updates via wifi during game play - Some seetings code cleanup
This commit is contained in:
15
README.md
15
README.md
@@ -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.~~
|
||||
|
||||

|
||||
|
||||
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.
|
||||
|
||||
11
TWANG32.ino
11
TWANG32.ino
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
65
settings.h
65
settings.h
@@ -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
103
wifi_ap.h
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user