/*
 * good old starfield - PASTIS 51 EDITION
 * 
 * See starfield25 for context and more comments, otherwise it may not make much
 * sense...
 * 
 * So basically the trick used to get more stars here, is not to free memory,
 * because that's not possible, but instead it's to make the stars use less memory.
 * To do that we change the type from float (4 bytes) to int (2 bytes).
 * The tradeoff is of course that now we have integers and not floating point numbers,
 * and that prevents us to have any meaningful results when we calculate vector related
 * stuff. But there's a workaround to this!
 * The workaround is very simple, we use int as floats without floating points, which
 * means that everytime we read from the array we convert the int to float and divide
 * it by an arbitrary precision value (here we use 100), and when we want to store a
 * float we multiply it by the same precision value and convert to int.
 * We loose in accuray, but that does not matter here at all.
 * 
 * ex: we want to store 12,345678
 * 12,3456 * 100 = 1234,56
 * int(1234,56) = 1234
 * and converted back
 * float(1234 / 100) = 12,34
 * in the process with this trick we lost 0,005678 (who cares?)
 * 
 * Note: most of the changes are in new_star(). There are some minor changes elsewhere,
 * mostly to try optimise things cheaply, ignore.
 */
#include <TVout.h>

TVout TV;

#define STARS 51

int x[STARS];
int y[STARS];
int vx[STARS];
int vy[STARS];

void
setup()
{
  randomSeed(analogRead(6));              // effective?
  TV.begin(NTSC,120,96);
  new_stars();
}

void
new_star(uint8_t i)
{
  uint8_t x_tmp, y_tmp;
  uint8_t ox = 60;
  uint8_t oy = 48;
  int dx, dy;
  float vl;
  
  x_tmp = 30 + random(60);
  y_tmp = 24 + random(48);
  
  dx = x_tmp - ox;
  dy = y_tmp - oy;

  switch(dx)
    case 0: dx = 1;                        // CHEAT
  
  vl = 1 / sqrt(dx*dx + dy*dy);
  vx[i] = int(dx * vl * 100);
  vy[i] = int(dy * vl * 100);

  x[i] = x_tmp * 100;
  y[i] = y_tmp * 100;
}

void
new_stars()
{
  for (uint8_t i = 0; i < STARS; i++)
    new_star(i);
}

void
update_stars()
{
  for (uint8_t i = 0; i < 40; i++) {
      x[i] = x[i] + vx[i];
      y[i] = y[i] + vy[i];
    if (x[i] > 12000 || x[i] < 0 || y[i] < 0 || y[i] > 9600)
      new_star(i);
  }
  for (uint8_t i = 40; i < STARS; i++) {
      x[i] = x[i] + (vx[i] << 1);
      y[i] = y[i] + (vy[i] << 1);
    if (x[i] > 12000 || x[i] < 0 || y[i] < 0 || y[i] > 9600)
      new_star(i);
  }
}

void
draw_stars()
{
  for (uint8_t i = 0; i < STARS; i++)
    TV.set_pixel(x[i]/100, y[i]/100, 1);
}

void
loop()
{
  TV.delay_frame(1);
  update_stars();
  TV.clear_screen();
  draw_stars();
}
