Advertisement
Guest User

Snake stabilization

a guest
Sep 3rd, 2014
581
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // See result at http://gfycat.com/ValuableIdioticAfricanpiedkingfisher
  2. // Settings
  3. var cellWidth = 15;
  4. var cellHeight = 15;
  5. var cellOffsetX = -1;
  6. var cellOffsetY = -1;
  7. var rows = 20;
  8. var cols = 20;
  9. var startX = 7;
  10. var startY = 0;
  11. var startDir = 2;
  12. var rotateDivide = 5;
  13.  
  14. // Return 0 for empty, 1 for snake, 2 for apple
  15. function getCellContent(frame, cellX, cellY) {
  16.     if (cellX < 0 || cellX >= cols ||
  17.         cellY < 0 || cellY >= rows) {
  18.         return 0;
  19.     }
  20.     var pixelX = cellX * cellWidth + cellOffsetX;
  21.     var pixelY = cellY * cellHeight + cellOffsetY;
  22.     var snakeX = pixelX + 7;
  23.     var snakeY = pixelY + 7;
  24.     var appleX = pixelX + 11;
  25.     var appleY = pixelY + 11;
  26.     var snakeTestPixel = frame.getPixel(snakeX, snakeY);
  27.     var appleTestPixel = frame.getPixel(appleX, appleY);
  28.     if (appleTestPixel.red == 255) {
  29.         return 2;
  30.     } else if (snakeTestPixel.red == 255) {
  31.         return 1;
  32.     } else {
  33.         return 0;
  34.     }
  35. }
  36.  
  37. function getDirOffsetX(dir) {
  38.     if (dir == 2) {
  39.         return -1;
  40.     } else if (dir == 3) {
  41.         return 1;
  42.     } else {
  43.         return 0;
  44.     }
  45. }
  46.  
  47. function getDirOffsetY(dir) {
  48.     if (dir == 0) {
  49.         return -1;
  50.     } else if (dir == 1) {
  51.         return 1;
  52.     } else {
  53.         return 0;
  54.     }
  55. }
  56.  
  57. // Return the next position as a triplet
  58. // 0 = up, 1 = down, 2 = left, 3 = right, -1 = no head movement
  59. // [x, y, dir] (coordinates in cells unit)
  60. function findNextMove(previousFrame, frame, lastX, lastY) {
  61.     for (var dir = 0; dir <= 3; ++dir) {
  62.         var checkX = lastX + getDirOffsetX(dir);
  63.         var checkY = lastY + getDirOffsetY(dir);
  64.         var oldContent = getCellContent(previousFrame, checkX, checkY);
  65.         if (oldContent == 1) {
  66.             continue;
  67.         }
  68.         var newContent = getCellContent(frame, checkX, checkY);
  69.         if (newContent == 1) {
  70.             return [checkX, checkY, dir];
  71.         }
  72.     }
  73.     return [lastX, lastY, -1];
  74. }
  75.  
  76. function fillMoves(source) {
  77.     var frameCount = source.frameCount;
  78.     var previousFrame = source.getFrame(0);
  79.     var lastX = startX;
  80.     var lastY = startY;
  81.     var moves = [[startX, startY, startDir]];
  82.     for (var currentFrame = 1; currentFrame < frameCount; ++currentFrame) {
  83.         var frame = source.getFrame(currentFrame);
  84.         var move = findNextMove(previousFrame, frame, lastX, lastY);
  85.         moves[moves.length] = move;
  86.         lastX = move[0];
  87.         lastY = move[1];
  88.         previousFrame = frame;
  89.     }
  90.     return moves;
  91. }
  92.  
  93. function dirToAngle(dir) {
  94.     switch (dir) {
  95.         case 0: return 0;
  96.         case 1: return Math.PI;
  97.         case 2: return Math.PI / 2;
  98.         case 3: return -Math.PI / 2;
  99.     }
  100. }
  101.  
  102. function transformCenter(canvas, cellX, cellY, angle) {
  103.     canvas.identity();
  104.     canvas.translate(canvas.width / 2 -cellX * cellWidth - cellOffsetX - cellWidth / 2, canvas.height / 2 -cellY * cellHeight - cellOffsetY - cellHeight / 2);
  105.     if (angle != 0) {
  106.         canvas.rotatecenter(angle, cellX * cellWidth + cellOffsetX + cellWidth / 2, cellY * cellHeight + cellOffsetY + cellHeight / 2);
  107.     }
  108. }
  109.  
  110. function blankCanvas(canvas, color) {
  111.     canvas.identity();
  112.     canvas.scale(canvas.width, canvas.height);
  113.     canvas.fillRect(color);
  114. }
  115.  
  116. function computeAngleOffset(oldDir, newDir) {
  117.     // TODO wake up brain to write this correctly
  118.     var dir;
  119.     switch (oldDir) {
  120.         case 0:
  121.             switch(newDir) {
  122.                 case 2: dir = 1; break;
  123.                 case 3: dir = -1; break;
  124.             }
  125.             break;
  126.         case 1:
  127.             switch(newDir) {
  128.                 case 2: dir = -1; break;
  129.                 case 3: dir = 1; break; // OK
  130.             }
  131.             break;
  132.         case 2:
  133.             switch(newDir) {
  134.                 case 0: dir = -1; break;
  135.                 case 1: dir = 1; break; // OK
  136.             }
  137.             break;
  138.         case 3:
  139.             switch(newDir) {
  140.                 case 0: dir = 1; break; // OK
  141.                 case 1: dir = -1; break;
  142.             }
  143.             break;
  144.     }
  145.     return dir * Math.PI / 2;
  146. }
  147.  
  148. function render(source, dest, moves, doRotate) {
  149.     var black = new Color(0, 0, 0, 255);
  150.     var frame = source.getFrame(0);
  151.     var w = frame.width * 2;
  152.     var h = frame.height * 2;
  153.     var canvas = new Canvas(w, h);
  154.     var frameCount = source.frameCount;
  155.     var previousDir = moves[0][2];
  156.     if (moves[0][2] == -1) {
  157.         // Failsafe
  158.         moves[0][2] = 0;
  159.     }
  160.     if (!doRotate) {
  161.         previousDir = 0;
  162.     }
  163.     blankCanvas(canvas, black);
  164.     transformCenter(canvas, moves[0][0], moves[0][1], dirToAngle(moves[0][2]));
  165.     canvas.drawImage(frame);
  166.     dest.addCanvas(canvas, source.getFrameDelay(0));
  167.     for (var currentFrame = 1; currentFrame < frameCount; ++currentFrame) {
  168.         print("Rendering frame " + (currentFrame + 1) + " out of " + frameCount);
  169.         if (doRotate) {
  170.             var newDir = moves[currentFrame][2];
  171.             if (newDir != previousDir && newDir != -1) {
  172.                 // Do a rotation sequence
  173.                 var oldAngle = dirToAngle(previousDir);
  174.                 var offset = computeAngleOffset(previousDir, newDir) / rotateDivide;
  175.                 for (var angleIter = 1; angleIter < (rotateDivide + 1); ++angleIter) {
  176.                     blankCanvas(canvas, black);
  177.                     transformCenter(canvas, moves[currentFrame - 1][0], moves[currentFrame - 1][1], oldAngle + offset * angleIter);
  178.                     canvas.drawImage(frame);
  179.                     dest.addCanvas(canvas, source.getFrameDelay(currentFrame - 1));
  180.                 }
  181.                 previousDir = newDir;
  182.             }
  183.         }
  184.         blankCanvas(canvas, black);
  185.         frame = source.getFrame(currentFrame);
  186.         transformCenter(canvas, moves[currentFrame][0], moves[currentFrame][1], dirToAngle(previousDir));
  187.         canvas.drawImage(frame);
  188.         dest.addCanvas(canvas, source.getFrameDelay(currentFrame));
  189.     }
  190. }
  191.  
  192. var source = new FrameSource("e:/src.gif");
  193. var moves = fillMoves(source);
  194. //var dest = new FrameSink("e:/dst1.gif");
  195. var dest2 = new FrameSink("e:/dst2.gif");
  196. //var dest2 = new FrameSink("e:/t2");
  197. //render(source, dest, moves, false);
  198. render(source, dest2, moves, true);
  199. //dest.close();
  200. dest2.close();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement