Skip to content

Instantly share code, notes, and snippets.

@lovyan03
Forked from tobozo/CompoundOscillation.ino
Last active April 16, 2022 00:58
Show Gist options
  • Save lovyan03/c1b8d2aa029341138d1c392b087a0d03 to your computer and use it in GitHub Desktop.
Save lovyan03/c1b8d2aa029341138d1c392b087a0d03 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 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;
static float angle = 0;
static int sqWidth;
static int sqSize;
static int offsetX = gridMargin;
static int offsetY = gridMargin;
static int spritePosX, spritePosY;
uint8_t blend(float a, float b, float bias=0.5f)
{
return sqrtf( ((1 - bias) * (a*a)) + ( bias * (b*b ) ) );
}
void drawGrid( float angle_offset = 0 )
{
int xlist[gridSize], ylist[gridSize];
for( int i=1; i<=gridSize; i++ ) {
int pos = (i*sqWidth)+sqSize;
int xp = roundf(cosf( (angle * (float)i + angle_offset) ) * sqSize);
int yp = roundf(sinf( (angle * (float)i + angle_offset) ) * sqSize);
xlist[i-1] = xp+pos;
ylist[i-1] = yp+pos;
uint16_t c = map( i, 0, gridSize, 0, 255 );
spriteLines->setColor(tft.color332( c, 255-c, 128 ));
spriteLines->drawPixel( offsetX + xp + pos, offsetY + yp + sqSize );
spriteLines->drawPixel( offsetX + xp + sqSize, offsetY + yp + pos );
}
for( int v = 1; v <= gridSize; v++ ) {
int cv = map( v, 0, gridSize, 0, 255 );
for( int h = 1; h <= gridSize; h++ ) {
int ch = map( h, 0, gridSize, 0, 255 );
int c = blend(cv, ch);
spriteLines->setColor(tft.color332( c, 255-c, 128 ));
spriteLines->drawPixel( offsetX + xlist[h-1], offsetY + ylist[v-1] );
}
}
}
void drawBullet( int x, int y )
{
spriteLines->pushSprite( spriteMix, 4-x, 4-y );
spriteMix->fillCircle( 4, 4, 2, TFT_WHITE );
spriteMix->pushSprite(spritePosX+x-4, spritePosY+y-4);
}
void drawBullets( float angle_offset = 0 )
{
int xlist[gridSize], ylist[gridSize];
for( int i=1; i<=gridSize; i++ ) {
int pos = (i*sqWidth)+sqSize;
int xp = roundf(cosf( (angle * (float)i + angle_offset) ) * sqSize);
int yp = roundf(sinf( (angle * (float)i + angle_offset) ) * sqSize);
xlist[i-1] = xp+pos;
ylist[i-1] = yp+pos;
drawBullet( offsetX + xp + pos, offsetY + yp + sqSize );
drawBullet( offsetX + xp + sqSize, offsetY + yp + pos );
}
for( int v = 0; v < gridSize; v++ ) {
for( int h = 0; h < gridSize; h++ ) {
drawBullet( offsetX + xlist[h], offsetY + ylist[v] );
}
}
}
void setupSprites()
{
uint16_t squareSize = min(tft.width(),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) delay(1);
}
spriteLines->fillSprite(bgcolor);
spriteMix->setColorDepth( 8 );
if( ! spriteMix->createSprite( 9, 9 ) ) {
Serial.println("Can't create spriteMix, halting");
while(1) delay(1);
}
spriteMix->fillSprite(bgcolor);
spritePosX = (tft.width() - spriteLines->width() ) >> 1;
spritePosY = (tft.height() - spriteLines->height()) >> 1;
}
void setup()
{
M5.begin();
tft.fillScreen(tft.color16to8(tft.color24to16(bgcolor)));
setupSprites();
// fill the grid, only needs one pass
// also animate bullets
for( float a=0; a<2*PI*gridSize; a +=.01f ) {
angle = fmodf( a, 2*PI );
drawGrid();
drawBullets();
}
}
void loop()
{
drawBullets();
angle = fmodf( angle, 2*PI );
angle += .01f;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment