//flash as Wemos D1 R2 & mini #include #ifdef __AVR__ #include #endif #include #include "wagon.h" #include "effect.h" #include "fx_scanner.h" #include "fx_flash.h" #define PIN D2 #define NUMPIXELS 600 Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800); long lastPixelUpdate=0; #define PIXELUPDATETIME 20 long lastRoutineUpdate=0; #define ROUTINEUPDATETIME 20 long lastCheckspawn=0; #define CHECKSPAWNDELAY 4000 //delay in ms to check random spawn #define SPAWNCHANCE 20 //1 out of x times wagon will spawn #define SPAWNCHANCEDOUBLE 5 //change of spawning a two trains simultaneously #define BRIGHTNESS_RUN 200 #define BRIGHTNESS_DEBUG 150 long loopmillis=0; uint8_t height[NUMPIXELS]; uint8_t heightraw[NUMPIXELS]; //uninterpolated values #define MAXHEIGHT 254 std::vector wagon_arr; uint8_t maxid=0; bool configmode=false; int selectedpixel=-1; //-1 = none uint8_t wagoncount=0; Effect* effect = NULL; //define config //#define RESPAWNWAGON #define MAXWAGONS 5 //maximum number of wagons void setup() { Serial.begin(115200); strip.begin(); strip.setBrightness(BRIGHTNESS_RUN); //150 strip.show(); // Initialize all pixels to 'off' Serial.println("Started"); resetHeightmap(); //fixed heightmap heightraw[0]=254; heightraw[20]=253; heightraw[40]=254; heightraw[67]=241; heightraw[79]=240; heightraw[90]=237; heightraw[130]=218; heightraw[144]=217; heightraw[159]=218; heightraw[196]=232; heightraw[228]=197; heightraw[236]=191; heightraw[245]=197; heightraw[275]=235; heightraw[300]=210; heightraw[345]=178; heightraw[362]=176; heightraw[369]=176; heightraw[381]=169; heightraw[421]=112; heightraw[460]=80; heightraw[474]=78; heightraw[489]=80; heightraw[524]=112; heightraw[534]=121; heightraw[542]=122; heightraw[561]=123; heightraw[580]=145; heightraw[599]=172; interpolateHeightValues(); /* Serial.println(); for (int i=0;i length 1 float interpolateStep= ((int)(interpolateEndvalue)-(int)(interpolateStartvalue))*1.0 /(interpolateLength+1); Serial.println(); Serial.print("interpolateStep="); Serial.print("("); Serial.print(interpolateEndvalue); Serial.print("-"); Serial.print(interpolateStartvalue); Serial.print(")/"); Serial.print(interpolateLength+1); Serial.print("="); Serial.println(interpolateStep); int interpolateStepCounter=1; Serial.println(); Serial.print("interpolateStartpos="); Serial.println(interpolateStartpos); Serial.print("interpolateEndpos="); Serial.println(interpolateEndpos); Serial.print("interpolateStartvalue="); Serial.println(interpolateStartvalue); Serial.print("interpolateEndvalue="); Serial.println(interpolateEndvalue); Serial.print("interpolateLength="); Serial.println(interpolateLength); Serial.print("interpolateStep="); Serial.println(interpolateStep,6); for (int setinti=interpolateStartpos;setinti<=interpolateEndpos;setinti++) { //for all coherent elements to interpolate height[setinti]=height[interpolateStartpos-1]+(int)(interpolateStep*interpolateStepCounter); /*Serial.print(height[interpolateStartpos-1]); Serial.print("+("); Serial.print(interpolateStep); Serial.print("*"); Serial.print(interpolateStepCounter); Serial.print(")="); Serial.println(height[setinti]);*/ interpolateStepCounter++; } interpolateStartpos=interpolateEndpos; } } } void previewHeightmap(int waittime){ for (int i=0;i0){ strip.show(); delay(waittime); } } void spawnWagon(){ //Wagon tmpr = Wagon(maxid++,NUMPIXELS,&strip, height, 35, 6, 0.5,0); //spawn new wagon // pos, wagonlength, startvel, startacc, trainmass, wagoncolor //Wagon tmpr = Wagon(maxid++,NUMPIXELS,&strip, height, random(0, 20), random(3,20), random(0.2, 50)/10.0, 0 , random(5,100) , Wheel(random(0,256))); //spawn new wagon int _randomlength=random(3,40); //Zelt: 3-> minimum vel 10, 40 -> minium vel 30 // pos, wagonlength, startvel , startacc, trainmass, wagoncolor //Wagon tmpr = Wagon(maxid++,NUMPIXELS,&strip, height, random(0, 20), _randomlength, random(map(_randomlength,3,40,1,1), map(_randomlength,3,40, 13,40))/10.0 , 0 , 5 , Wheel((uint8_t)random(0,255))); //spawn new wagon Wagon tmpr = Wagon(maxid++,NUMPIXELS,&strip, height, NUMPIXELS+_randomlength, _randomlength, -random(map(_randomlength,3,40,10,20), map(_randomlength,3,40, 22,60))/10.0 , 0 , 2.0 , Wheel((uint8_t)random(0,255))); //spawn new wagon //special spawns if (random(0,50)==0){ tmpr.setType(1); //make rainbow tmpr.setLength(_randomlength*random(1,3)); } wagon_arr.push_back(tmpr); Serial.println("Spawned Wagon"); } void spawnWagon(float pos, float wagonlength,float startvel, float startacc, float mass, uint8_t wheelcolor){ //Wagon tmpr = Wagon(maxid++,NUMPIXELS,&strip, height, 35, 6, 0.5,0); //spawn new wagon // pos, wagonlength, startvel, startacc, wagonmass, wagoncolor Wagon tmpr = Wagon(maxid++,NUMPIXELS,&strip, height, pos, wagonlength, startvel, startacc , mass , Wheel(wheelcolor)); //spawn new wagon wagon_arr.push_back(tmpr); Serial.println("Spawned Custom Wagon"); } void loop() { loopmillis=millis(); checkSerial(); if (configmode){ loop_configmode(); }else{ loop_achterbahn(); } } void checkSerial(){ static String serialstring_temp=""; String serialstring=""; while(Serial.available()){ if (Serial.available()>0){ char c = Serial.read(); if (c!='\n') { serialstring_temp+=c; Serial.print(c); //echo }else{ Serial.println(""); //new line serialstring=serialstring_temp; serialstring_temp=""; } } } if (serialstring.length()>0) { Serial.println("String:"+serialstring); if (serialstring.equals("run")){ strip.setBrightness(BRIGHTNESS_RUN); configmode=false; }else if (serialstring.equals("debug")){ strip.setBrightness(BRIGHTNESS_DEBUG); configmode=true; }else if (serialstring.equals("print")){ printHeightmapRaw(); }else if (serialstring.equals("remove")){ removeAllWagons(); }else if (serialstring.equals("clear")){ resetHeightmap(); interpolateHeightValues(); previewHeightmap(0); //show heightmap strip.show(); }else if (serialstring.startsWith("spawn=")){ String rest=serialstring.substring(serialstring.indexOf('=')+1); //part after = int spawnpos=rest.substring(0,rest.indexOf(',')).toInt(); //part to next , rest=rest.substring(rest.indexOf(',')+1); //part after , int spawnlength=rest.substring(0,rest.indexOf(',')).toInt(); //part to next , rest=rest.substring(rest.indexOf(',')+1); //part after , int spawnstartvel=rest.substring(0,rest.indexOf(',')).toInt(); //part to next , rest=rest.substring(rest.indexOf(',')+1); //part after , int spawnstartacc=rest.substring(0,rest.indexOf(',')).toInt(); //part to next , rest=rest.substring(rest.indexOf(',')+1); //part after , float spawnmass=rest.substring(0,rest.indexOf(',')).toInt()/1000.0; //part to next , //mass in gramm rest=rest.substring(rest.indexOf(',')+1); //part after , int spawncolor=rest.substring(0).toInt(); //part to next , Serial.print("spawning "); Serial.print(spawnpos); Serial.print(","); Serial.println(spawnlength); Serial.print(","); Serial.println(spawnstartvel); //startvel will be /10 Serial.print(","); Serial.println(spawnstartacc); //startacc will be /10 Serial.print(","); Serial.println(spawnmass); Serial.print(","); Serial.println(spawncolor); spawnWagon(spawnpos,spawnlength,spawnstartvel/10.0,spawnstartacc/10.0,spawnmass,spawncolor); }else if (serialstring.equals("spawn")){ spawnWagon(); //random }else if (serialstring.startsWith("setpx=")){ String pixelnumberstring=serialstring.substring(serialstring.indexOf('=')+1,serialstring.indexOf(',')); //part between = and , String pixelvaluestring=serialstring.substring(serialstring.indexOf(',')+1); //part after , int pixelnumber=pixelnumberstring.toInt(); int pixelvalue=pixelvaluestring.toInt(); Serial.print("set pixel "); Serial.print(pixelnumber); Serial.print("="); Serial.println(pixelvalue); if (pixelnumber>=0 && pixelnumber=0 && pixelvalue<=255){ heightraw[pixelnumber]=pixelvalue; }else{ Serial.println("Error: Value out of range!"); } interpolateHeightValues(); Serial.println(); for (int i=0;i=0){ uint32_t c=strip.Color(255,255,255); strip.setPixelColor(selectedpixel,c); if (selectedpixel>=1){ uint32_t c=strip.Color(0,0,0); strip.setPixelColor(selectedpixel-1,c); } if (selectedpixel::iterator it = wagon_arr.begin(); it != wagon_arr.end(); ++it) //all wagons { Wagon & w = *it; w.updateGraphics(); } //Effects if (effect != NULL ){ if (effect->active()){ effect->updateGraphics(); } } strip.show(); } if (lastRoutineUpdate+ROUTINEUPDATETIME::iterator it = wagon_arr.begin(); it != wagon_arr.end(); ++it) //all wagons { Wagon & w = *it; w.updatePhysics(ROUTINEUPDATETIME); if (!w.alive()) { it = wagon_arr.erase(it); // After erasing, it is now pointing the next element. --it; #ifdef RESPAWNWAGON spawnWagon(); //spawn new one #endif }else{ //wagon is alive wagoncount++; } } //Effects if (effect != NULL ){ if (effect->active()){ effect->updateRoutine(ROUTINEUPDATETIME); }else{ //effect not active anymore delete effect; effect=NULL; } } } //Check spawning if (lastCheckspawn+CHECKSPAWNDELAY::iterator it = wagon_arr.begin(); it != wagon_arr.end(); ++it) //all wagons { Wagon & w = *it; w.updatePhysics(ROUTINEUPDATETIME); it = wagon_arr.erase(it); // After erasing, it is now pointing the next element. --it; } } // Input a value 0 to 255 to get a color value. // The colours are a transition r - g - b - back to r. uint32_t Wheel(byte WheelPos) { WheelPos = 255 - WheelPos; if(WheelPos < 85) { return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3); } if(WheelPos < 170) { WheelPos -= 85; return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3); } WheelPos -= 170; return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0); }