Skip to content

Instantly share code, notes, and snippets.

@tobozo
Created April 15, 2022 16:43
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tobozo/d9fb5b7a930f31669cff6e5e0ec910c1 to your computer and use it in GitHub Desktop.
Save tobozo/d9fb5b7a930f31669cff6e5e0ec910c1 to your computer and use it in GitHub Desktop.
Compound oscillation demo for ESP32
// Compound oscillation demo for ESP32
// Loosely coded by tobozo (c+) apr 2022 -
// Inspired by this GIF
// - https://twitter.com/bayraitt/status/1514499189975134210
#include <ESP32-Chimera-Core.h> // https://github.com/tobozo/ESP32-Chimera-Core
static LGFX &tft(M5.Lcd);
static LGFX_Sprite* spriteLines = new LGFX_Sprite( &tft );
static LGFX_Sprite* spriteMix = new LGFX_Sprite( &tft );
static LGFX_Sprite* spriteBullets = new LGFX_Sprite( &tft );
static constexpr const int gridSize = 6;
static constexpr const int gridMargin = 10;
static constexpr const uint32_t bgcolor = 0x4d4845U;
static constexpr const uint32_t hgcolor = 0xffffffU;
static constexpr const uint32_t fgcolor = 0x888888U;
float angle = 0;
int sqWidth;
int sqSize;
int offsetX = gridMargin;
int offsetY = gridMargin;
int spritePosX, spritePosY;
uint8_t blend(float a, float b, float bias=0.5)
{
return sqrt( ((1 - bias) * (a*a)) + ( bias * (b*b ) ) );
}
void drawGrid( float angle_offset = 0 )
{
float xpos,ypos;
float x, y;
for( float h=0; h<=gridSize; h++ ) {
for( float v=0; v<=gridSize; v++ ) {
if( h == 0 && v == 0 ) continue;
xpos = (h*sqWidth)+sqSize;
ypos = (v*sqWidth)+sqSize;
bool circle = false;
uint16_t barcolor;
uint16_t ch = map( h, 0, gridSize, 0, 255 );
uint16_t cv = map( v, 0, gridSize, 0, 255 );
if( v == 0 ) {
x = xpos + cos( (angle * h + angle_offset) ) * sqSize;
y = ypos + sin( (angle * h + angle_offset) ) * sqSize;
barcolor = tft.color565( ch, 255-ch, 128 );
} else if( h == 0 ) {
x = xpos + cos( (angle * v + angle_offset) ) * sqSize;
y = ypos + sin( (angle * v + angle_offset) ) * sqSize;
barcolor = tft.color565( cv, 255-cv, 128 );
} else {
x = xpos + cos( (angle + angle_offset) * h ) * sqSize;
y = ypos + sin( (angle + angle_offset) * v ) * sqSize;
barcolor = tft.color565( blend(cv, ch), 255-blend(ch, cv), 128 );
}
spriteLines->drawPixel( offsetX+x, offsetY+y, barcolor );
}
}
}
void drawBullets( float angle_offset = 0 )
{
float xpos,ypos;
float x, y;
for( float h=0; h<=gridSize; h++ ) {
for( float v=0; v<=gridSize; v++ ) {
if( h == 0 && v == 0 ) continue;
xpos = (h*sqWidth)+sqSize;
ypos = (v*sqWidth)+sqSize;
if( v == 0 ) {
x = xpos + cos( (angle * h + angle_offset) ) * sqSize;
y = ypos + sin( (angle * h + angle_offset) ) * sqSize;
} else if( h == 0 ) {
x = xpos + cos( (angle * v + angle_offset) ) * sqSize;
y = ypos + sin( (angle * v + angle_offset) ) * sqSize;
} else {
x = xpos + cos( (angle + angle_offset) * h ) * sqSize;
y = ypos + sin( (angle + angle_offset) * v ) * sqSize;
}
spriteBullets->fillCircle( offsetX+x, offsetY+y, 2, 1 );
}
}
spriteLines->pushSprite( spriteMix, 0, 0 );
spriteBullets->pushSprite( spriteMix, 0, 0, 0 );
spriteMix->pushSprite( spritePosX, spritePosY );
spriteBullets->fillSprite( 0 );
}
void setupSprites()
{
uint16_t squareSize = tft.height();
sqWidth = (squareSize-gridMargin ) / (gridSize+1);
sqSize = (sqWidth/2)-4;
spriteLines->setColorDepth( 8 );
if( ! spriteLines->createSprite( squareSize, squareSize ) ) {
Serial.println("Can't create spriteLines, halting");
while(1);
}
spriteLines->fillSprite(bgcolor);
spriteMix->setColorDepth( 8 );
if( ! spriteMix->createSprite( squareSize, squareSize ) ) {
Serial.println("Can't create spriteMix, halting");
while(1);
}
spriteMix->fillSprite(bgcolor);
spriteBullets->setColorDepth( 1 );
spriteBullets->setPaletteColor( 0, bgcolor );
spriteBullets->setPaletteColor( 1, hgcolor );
if( ! spriteBullets->createSprite( squareSize, squareSize ) ) {
Serial.println("Can't create spriteBullets, halting");
while(1);
}
spriteBullets->fillSprite(0);
spritePosX = tft.width()/2 - spriteMix->width()/2;
spritePosY = tft.height()/2 - spriteMix->height()/2;
}
void setup()
{
M5.begin();
setupSprites();
// fill the grid, only needs one pass
// also animate bullets
for( float a=0; a<2*PI*gridSize; a +=.02 ) {
angle = fmod( a, 2*PI );
drawGrid();
drawBullets();
}
}
void loop()
{
drawBullets();
angle = fmod( angle, 2*PI );
angle += .02;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment