/* Snake * ------------------ * iio.js version 1.4 */ // define a new iio app Snake = function( app, settings ){ // initialize settings settings = settings || {}; // define the number of columns var num_columns = 20; // limit column number if preview if( settings.preview ) num_columns = 10; // define direction constants var UP = 0; var RIGHT = 1; var DOWN = 2; var LEFT = 3; // properties shared by snake and food var shared_props = { outline: 'white', lineWidth: 1, shadow: 'black', shadowBlur: 20, width: Math.floor( app.width / num_columns ) } // define game objects and initial values var food; var snake = { head: {}, body: [], initial_direction: RIGHT, initial_pos: new iio.Vector( shared_props.width * num_columns/2 + shared_props.width/2, shared_props.width * 4 + shared_props.width/2 ), initial_body_length: 4, initial_speed: 4, speed: 4, width: shared_props.width } // restart the game function reset(){ // clear all objects and loops from app app.clear(); // set the snake color to a random color shared_props.color = iio.Color.random(); // set the background color to the inverse color app.set({ color: shared_props.color.clone().invert() }); // create snake head snake.head = app.add( new iio.Quad( shared_props, { pos: snake.initial_pos.clone() // pass true to supress app draw }), true ); // clear snake body snake.body = []; // create snake body for(var i = 0; i < snake.initial_body_length-1; i++) snake.body[i] = app.add( new iio.Quad( shared_props, { pos:[ snake.initial_pos.x - snake.width * (i+1), snake.initial_pos.y ] // pass true to supress app draw }), true ); // set initial properties snake.direction = RIGHT; snake.speed = snake.initial_speed; // create food makeFood(); } // create food function makeFood(){ // define a random grid position in the view var randomPos = new iio.Vector( snake.width * iio.randomInt(0,num_columns) + snake.width/2, snake.width * iio.randomInt(0,app.height / snake.width) + snake.width/2 ); // create food object food = app.add( new iio.Quad( shared_props, { pos: randomPos // pass true to supress app draw }), true ); } // keypress handling // sets snake direction depending on key value app.keyDown = function( event, key ){ // if snake isn't moving down if( snake.direction != DOWN && key === 'up arrow' || key === 'w' ) snake.direction = UP; // if snake isn't moving left else if( snake.direction != LEFT && key === 'right arrow' || key === 'd' ) snake.direction = RIGHT; // if snake isn't moving up else if( snake.direction != UP && key === 'down arrow' || key === 's' ) snake.direction = DOWN; // if snake isn't moving right else if( snake.direction != RIGHT && key === 'left arrow' || key === 'a' ) snake.direction = LEFT; } // define a function to be called on every update // THE GAME LOOP app.onUpdate = function(){ // if not preview, reset the game if the snake's head // overlaps with the snake body if( !settings.preview ) for(var i=1; i<snake.body.length; i++) if( snake.head.pos.equals( snake.body[i].pos ) ) // GAME OVER reset(); // if the snake head overlaps the food, eat the food if( snake.head.pos.equals( food.pos ) ){ // add the food part of the snake body snake.body.push( food ); // make a new food object makeFood(); // increase the snake's speed snake.speed++; } // move all snake body parts to the position of // the preceding body part for( var i = snake.body.length-1; i>0; i-- ){ snake.body[i].pos.x = snake.body[i-1].pos.x; snake.body[i].pos.y = snake.body[i-1].pos.y; } // move the snake body directly behind the snake head // to the position of the snake head snake.body[0].pos.x = snake.head.pos.x; snake.body[0].pos.y = snake.head.pos.y; // if preview, randomize the snake direction if( settings.preview && iio.random() < 0.4 ) snake.direction = iio.randomInt(0,4); // move the snake head depending upon its direction // then check wall collisions for game over switch(snake.direction){ // move the snake head up case UP: snake.head.pos.y -= snake.width; // GAME OVER if snake hits the wall if(snake.head.pos.y-snake.width/2 < 0) reset(); break; // move the snake head right case RIGHT: snake.head.pos.x += snake.width; // GAME OVER if snake hits the wall if(snake.head.pos.x > app.width) reset(); break; // move the snake head down case DOWN: snake.head.pos.y += snake.width; // GAME OVER if snake hits the wall if(snake.head.pos.y>app.height) reset(); break; // move the snake head left case LEFT: snake.head.pos.x -= snake.width; // GAME OVER if snake hits the wall if(snake.head.pos.x-snake.width/2<0) reset(); break; } // set the speed of the game loop return snake.speed; } // initialize the game reset(); // loop onUpdate at the initial speed app.loop( snake.initial_speed ); } // start the app full screen iio.start( Snake );