Advertisement
Guest User

Canvas problems

a guest
May 5th, 2017
381
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. <!doctype html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <title>Simple Snake Game</title>
  6.    
  7.     <!-- Basic styling, centering of the canvas. -->
  8.     <style>
  9.     canvas {
  10.         display: block;
  11.         position: absolute;
  12.         border: 1px solid #000;
  13.         margin: auto;
  14.         top: 0;
  15.         bottom: 0;
  16.         right: 0;
  17.         left: 0;
  18.     }
  19.     </style>
  20. </head>
  21. <body>
  22. <script>
  23.  
  24. var
  25.  
  26. /**
  27.  * Constante
  28.  */
  29. COLS = 28,
  30. ROWS = 28,
  31.  
  32. EMPTY = 0,
  33. SNAKE = 1,
  34. FRUIT = 2,
  35.  
  36. LEFT  = 0,
  37. UP    = 1,
  38. RIGHT = 2,
  39. DOWN  = 3,
  40.  
  41. KEY_LEFT  = 37,
  42. KEY_UP    = 38,
  43. KEY_RIGHT = 39,
  44. KEY_DOWN  = 40,
  45.  
  46. /**
  47.  * Game objects
  48.  */
  49. canvas,   /* HTMLCanvas */
  50. ctx,      /* CanvasRenderingContext2d */
  51. keystate, /* keyboard inputs */
  52. frames,   /* used for animation */
  53. score;    /* keep track of the player score */
  54.  
  55.  
  56. /**
  57.  * Grid datastructor, usefull in games where the game world is
  58.  * confined in absolute sized chunks of data or information.
  59.  *
  60.  * @type {Object}
  61.  */
  62. grid = {
  63.    
  64.     width: null,  /* number, the number of columns */
  65.     height: null, /* number, the number of rows */
  66.     _grid: null,  /* Array<any>, data representation */
  67.  
  68.     /**
  69.      * Initiate and fill a c x r grid with the value of d
  70.      * @param  {any}    d default value to fill with
  71.      * @param  {number} c number of columns
  72.      * @param  {number} r number of rows
  73.      */
  74.     init: function(d, c, r) {
  75.         this.width = c;
  76.         this.height = r;
  77.  
  78.         this._grid = [];
  79.         for (var x=0; x < c; x++) {
  80.             this._grid.push([]);
  81.             for (var y=0; y < r; y++) {
  82.                 this._grid[x].push(d);
  83.             }
  84.         }
  85.     },
  86.  
  87.     /**
  88.      * Set the value of the grid cell at (x, y)
  89.      *
  90.      * @param {any}    val what to set
  91.      * @param {number} x   the x-coordinate
  92.      * @param {number} y   the y-coordinate
  93.      */
  94.     set: function(val, x, y) {
  95.         this._grid[x][y] = val;
  96.     },
  97.  
  98.     /**
  99.      * Get the value of the cell at (x, y)
  100.      *
  101.      * @param  {number} x the x-coordinate
  102.      * @param  {number} y the y-coordinate
  103.      * @return {any}   the value at the cell
  104.      */
  105.     get: function(x, y) {
  106.         return this._grid[x][y];
  107.     }
  108. }
  109. /**
  110. ****/
  111. /**
  112.  * The snake, works as a queue (FIFO, first in first out) of data
  113.  * with all the current positions in the grid with the snake id
  114.  *
  115.  * @type {Object}
  116.  */
  117. snake = {
  118.  
  119.     direction: null, /* number, the direction */
  120.     last: null,      /* Object, pointer to the last element in
  121.                         the queue */
  122.     _queue: null,    /* Array<number>, data representation*/
  123.  
  124.     /**
  125.      * Clears the queue and sets the start position and direction
  126.      *
  127.      * @param  {number} d start direction
  128.      * @param  {number} x start x-coordinate
  129.      * @param  {number} y start y-coordinate
  130.      */
  131.     init: function(d, x, y) {
  132.         this.direction = d;
  133.  
  134.         this._queue = [];
  135.         this.insert(x, y);
  136.     },
  137.  
  138.     /**
  139.      * Adds an element to the queue
  140.      *
  141.      * @param  {number} x x-coordinate
  142.      * @param  {number} y y-coordinate
  143.      */
  144.     insert: function(x, y) {
  145.         // unshift prepends an element to an array
  146.         this._queue.unshift({x:x, y:y});
  147.         this.last = this._queue[0];
  148.     },
  149.  
  150.     /**
  151.      * Removes and returns the first element in the queue.
  152.      *
  153.      * @return {Object} the first element
  154.      */
  155.     remove: function() {
  156.         // pop returns the last element of an array
  157.         return this._queue.pop();
  158.     }
  159. };
  160.  
  161. /**
  162.  * Set a food id at a random free cell in the grid
  163.  */
  164. function setFood() {
  165.     var empty = [];
  166.     // iterate through the grid and find all empty cells
  167.     for (var x=0; x < grid.width; x++) {
  168.         for (var y=0; y < grid.height; y++) {
  169.             if (grid.get(x, y) === EMPTY) {
  170.                 empty.push({x:x, y:y});
  171.             }
  172.         }
  173.     }
  174.     // chooses a random cell
  175.     var randpos = empty[Math.round(Math.random()*(empty.length - 1))];
  176.     grid.set(FRUIT, randpos.x, randpos.y);
  177. }
  178.  
  179. /**
  180.  * Starts the game
  181.  */
  182. function main() {
  183.    
  184.     // create and initiate the canvas element
  185.     canvas = document.createElement("canvas");
  186.     canvas.width = COLS*20;
  187.     canvas.height = ROWS*20;
  188.     ctx = canvas.getContext("2d");
  189.     // add the canvas element to the body of the document
  190.     document.body.appendChild(canvas);
  191.  
  192.     // sets an base font for bigger score display
  193.     ctx.font = "15px Helvetica";
  194.  
  195.     frames = 0;
  196.     keystate = {};
  197.     // keeps track of the keybourd input
  198.     document.addEventListener("keydown", function(evt) {
  199.         keystate[evt.keyCode] = true;
  200.     });
  201.    
  202.     document.addEventListener("keyup", function(evt) {
  203.         delete keystate[evt.keyCode];
  204.     });
  205.  
  206.     // intatiate game objects and starts the game loop
  207.     init();
  208.     loop();
  209. }
  210. /** function that pauses the game **/
  211.  
  212. /**
  213.  * Resets and inits game objects
  214.  */
  215. function init() {
  216.     score = 0;
  217.  
  218.     grid.init(EMPTY, COLS, ROWS);
  219.  
  220.     var sp = {x:Math.floor(COLS/2), y:ROWS-1};
  221.     snake.init(UP, sp.x, sp.y);
  222.     grid.set(SNAKE, sp.x, sp.y);
  223.  
  224.     setFood();
  225. }
  226.  
  227. /**
  228.  * The game loop function, used for game updates and rendering
  229.  */
  230. function loop() {
  231.     if(togglePause) return;
  232.     update();
  233.     draw();
  234.     // When ready to redraw the canvas call the loop function
  235.     // first. Runs about 60 frames a second
  236.     window.requestAnimationFrame(loop, canvas);
  237.    
  238. }
  239.  
  240. /**
  241.  * Updates the game logic
  242.  */
  243. function update() {
  244.     frames++;
  245.  
  246.     // changing direction of the snake depending on which keys
  247.     // that are pressed
  248.     if (keystate[KEY_LEFT] && snake.direction !== RIGHT) {
  249.         snake.direction = LEFT;
  250.     }
  251.     if (keystate[KEY_UP] && snake.direction !== DOWN) {
  252.         snake.direction = UP;
  253.     }
  254.     if (keystate[KEY_RIGHT] && snake.direction !== LEFT) {
  255.         snake.direction = RIGHT;
  256.     }
  257.     if (keystate[KEY_DOWN] && snake.direction !== UP) {
  258.         snake.direction = DOWN;
  259.     }
  260.  
  261.     // each five frames update the game state.
  262.     if (frames%5 === 0) {
  263.         // pop the last element from the snake queue i.e. the
  264.         // head
  265.         var nx = snake.last.x;
  266.         var ny = snake.last.y;
  267.  
  268.         // updates the position depending on the snake direction
  269.         switch (snake.direction) {
  270.             case LEFT:
  271.                 nx--;
  272.                 break;
  273.             case UP:
  274.                 ny--;
  275.                 break;
  276.             case RIGHT:
  277.                 nx++;
  278.                 break;
  279.             case DOWN:
  280.                 ny++;
  281.                 break;
  282.         }
  283.  
  284.         // checks all gameover conditions
  285.         if (0 > nx || nx > grid.width-1  ||
  286.             0 > ny || ny > grid.height-1 ||
  287.             grid.get(nx, ny) === SNAKE
  288.         ) {
  289.             return init();
  290.         }
  291.  
  292.         // check wheter the new position are on the fruit item
  293.         if (grid.get(nx, ny) === FRUIT) {
  294.             // increment the score and sets a new fruit position
  295.             score++;
  296.             setFood();
  297.         } else {
  298.             // take out the first item from the snake queue i.e
  299.             // the tail and remove id from grid
  300.             var tail = snake.remove();
  301.             grid.set(EMPTY, tail.x, tail.y);
  302.         }
  303.  
  304.         // add a snake id at the new position and append it to
  305.         // the snake queue
  306.         grid.set(SNAKE, nx, ny);
  307.         snake.insert(nx, ny);
  308.     }
  309. }
  310.  
  311.  
  312. /** TOGGLE PAUSE AND KEYDOWN FUNCTION **/
  313.  
  314.  
  315. function togglePause()
  316. {
  317.     if (!paused)
  318.     {
  319.         paused = true;
  320.     } else if (paused)
  321.     {
  322.        paused= false;
  323.     }
  324.  
  325. }
  326.  
  327. window.addEventListener('keydown', function (e) {
  328. var key = e.keyCode;
  329. if (key === 80)// p key
  330. {
  331.     togglePause();
  332. }
  333. });
  334.  
  335.  
  336.  
  337.  
  338. /**
  339.  * Render the grid to the canvas.
  340.  */
  341.  
  342.  
  343. function draw() {
  344.     // calculate tile-width and -height
  345.     var tw = canvas.width/grid.width;
  346.     var th = canvas.height/grid.height;
  347.     // iterate through the grid and draw all cells
  348.     for (var x=0; x < grid.width; x++) {
  349.         for (var y=0; y < grid.height; y++) {
  350.             // sets the fillstyle depending on the id of
  351.             // each cell
  352.             switch (grid.get(x, y)) {
  353.                 case EMPTY:
  354.                     ctx.fillStyle = "#d9ddd9";
  355.                     break;
  356.                 case SNAKE:
  357.                     ctx.fillStyle = "#038423";
  358.                     break;
  359.                 case FRUIT:
  360.                     ctx.fillStyle = "#f00";
  361.                     break;
  362.             }
  363.             ctx.fillRect(x*tw, y*th, tw, th);
  364.         }
  365.     }
  366.     // changes the fillstyle once more and draws the score
  367.     // message to the canvas
  368.     ctx.fillStyle = "#000";
  369.     ctx.fillText("SCORE: " + score, 10, canvas.height-10);
  370. }
  371.  
  372. // start and run the game
  373. main();
  374. </script>
  375. </body>
  376. </html>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement