带有移动按钮控件的蛇游戏

时间:2015-06-03 19:57:02

标签: javascript jquery jquery-mobile canvas html5-canvas

在这个Snake游戏中,我需要按钮来控制蛇,就像箭头键一样。这将允许游戏在移动设备上播放。你可以看到我在那里有按钮的代码,但它们没有正常工作而且没有控制蛇的运动。

任何使按钮工作的建议都将不胜感激!谢谢!

HTML

<section class="game" id="share">

<div class="container">

    <div class="columns twelve borders center">

        <div class="game-container">

            <div class="container">

                <div class="SplashScreen">
                    <h1>
                        Snake
                    </h1>
                    <h2>
                        Click To Start.
                    </h2>
                    <input class="StartButton" type="button" value="Start" />
                </div>

                <div class="FinishScreen" style="display:none">
                    <h1>
                        Game Over
                    </h1>
                    <p>
                        Your score was: <span id="score"></span>
                    </p>
                    <input class="StartButton" type="button" value="Restart" />
                </div>

                <canvas id="canvasArea" height="300" width="300" style="display:none;"></canvas>

            </div>

            <div class="button-pad">
                <div class="btn-up">
                    <input type="image" src="http://aaronblomberg.com/sites/ez/images/btn-up.png" alt="Up" class="button up-btn" />
                </div>

                <div class="btn-right">
                    <input type="image" src="http://aaronblomberg.com/sites/ez/images/btn-right.png" alt="Right" class="button right-btn" />
                </div>

                <div class="btn-down">
                    <input type="image" src="http://aaronblomberg.com/sites/ez/images/btn-down.png" alt="Down" class="button down-btn" />
                </div>

                <div class="btn-left">
                    <input type="image" src="http://aaronblomberg.com/sites/ez/images/btn-left.png" alt="Left" class="button left-btn" />
                </div>
            </div>

        </div>

    </div>

</div>

</section>

JAVASCRIPT

( function( $ ) {

    $( function() {

        $(document).ready(function () {

            $(".StartButton").click(function () {
                $(".SplashScreen").hide();
                $(".FinishScreen").hide();
                $("#canvasArea").show();
                init();
            });

            //Canvas stuff
            var canvas = $("#canvasArea")[0];
            var ctx = canvas.getContext("2d");
            var w = $("#canvasArea").width();
            var h = $("#canvasArea").height();

            //Lets save the cell width in a variable for easy control
            var sw = 10;
            var direction;
            var nd;
            var food;
            var score;

            //Lets create the snake now
            var snake_array; //an array of cells to make up the snake

            function endGame() {
                $("#canvasArea").hide();
                $("#score").text(score);
                $(".FinishScreen").show();
            }

            function init() {
                direction = "right"; //default direction
                nd = [];
                create_snake();
                create_food(); //Now we can see the food particle
                //finally lets display the score
                score = 0;

                //Lets move the snake now using a timer which will trigger the paint function
                //every 60ms
                if (typeof game_loop != "undefined") clearInterval(game_loop);
                game_loop = setInterval(paint, 60);
            }

            function create_snake() {
                var length = 5; //Length of the snake
                snake_array = []; //Empty array to start with
                for (var i = length - 1; i >= 0; i--) {
                    //This will create a horizontal snake starting from the top left
                    snake_array.push({
                        x: i,
                        y: 0
                    });
                }
            }

            //Lets create the food now
            function create_food() {
                food = {
                    x: Math.round(Math.random() * (w - sw) / sw),
                    y: Math.round(Math.random() * (h - sw) / sw),


                };
                //This will create a cell with x/y between 0-44
                //Because there are 45(450/10) positions accross the rows and columns

            }

            //Lets paint the snake now
            function paint() {
                if (nd.length) {
                    direction = nd.shift();
                }

                //To avoid the snake trail we need to paint the BG on every frame
                //Lets paint the canvas now
                ctx.fillStyle = "#0056a0";
                ctx.fillRect(0, 0, w, h);
                ctx.strokeStyle = "#ffffff";
                ctx.strokeRect(0, 0, w, h);

                //The movement code for the snake to come here.
                //The logic is simple
                //Pop out the tail cell and place it infront of the head cell
                var nx = snake_array[0].x;
                var ny = snake_array[0].y;

                //These were the position of the head cell.
                //We will increment it to get the new head position
                //Lets add proper direction based movement now
                if (direction == "right") nx++;
                else if (direction == "left") nx--;
                else if (direction == "up") ny--;
                else if (direction == "down") ny++;

                //Lets add the game over clauses now
                //This will restart the game if the snake hits the wall
                //Lets add the code for body collision
                //Now if the head of the snake bumps into its body, the game will restart
                if (nx == -1 || nx == w / sw || ny == -1 || ny == h / sw || check_collision(nx, ny, snake_array)) {
                    //end game
                    return endGame();
                }

                //Lets write the code to make the snake eat the food
                //The logic is simple
                //If the new head position matches with that of the food,
                //Create a new head instead of moving the tail
                if (nx == food.x && ny == food.y) {
                    var tail = {
                        x: nx,
                        y: ny
                    };
                    score++;

                    //Create new food
                    create_food();
                } else

                {
                    var tail = snake_array.pop(); //pops out the last cell
                    tail.x = nx;
                    tail.y = ny;
                }

                //The snake can now eat the food.
                snake_array.unshift(tail); //puts back the tail as the first cell

                for (var i = 0; i < snake_array.length; i++) {
                    var c = snake_array[i];

                    //Lets paint 10px wide cells
                    paint_cell(c.x, c.y);
                }

                //Lets paint the food
                paint_cell(food.x, food.y);

                //Lets paint the score
                var score_text = "Score: " + score;
                ctx.fillStyle = "#ffffff";
                ctx.fillText(score_text, 5, h - 5);

                //Set the font and font size
                ctx.font = '12px Arial';

                //position of the fill text counter
                ctx.fillText(itemCounter, 10, 10);

            }

            //Lets first create a generic function to paint cells
            function paint_cell(x, y) {
                ctx.fillStyle = "#d8d8d8";
                ctx.fillRect(x * sw, y * sw, sw, sw);
            }

            function check_collision(x, y, array) {
                //This function will check if the provided x/y coordinates exist
                //in an array of cells or not
                for (var i = 0; i < array.length; i++) {
                    if (array[i].x == x && array[i].y == y) return true;
                }

                return false;
            }

            // Lets prevent the default browser action with arrow key usage
            var keys = {};
            window.addEventListener("keydown",
                function(e){
                    keys[e.keyCode] = true;
                    switch(e.keyCode){
                        case 37: case 39: case 38:  case 40: // Arrow keys
                        case 32: e.preventDefault(); break; // Space
                        default: break; // do not block other keys
                    }
                },
            false);
            window.addEventListener('keyup',
                function(e){
                    keys[e.keyCode] = false;
                },
            false);

            //Lets add the keyboard controls now
            $(document).keydown(function (e) {
                var key = e.which;
                var td;
                if (nd.length) {
                    var td = nd[nd.length - 1];

                } else {
                    td = direction;
                }

                //We will add another clause to prevent reverse gear
                if (key == "37" && td != "right") nd.push("left");
                else if (key == "38" && td != "down") nd.push("up");
                else if (key == "39" && td != "left") nd.push("right");
                else if (key == "40" && td != "up") nd.push("down");

                //The snake is now keyboard controllable

            });

        });


        $(document).on('click', '.button-pad > button', function(e) {
            if ($(this).hasClass('left-btn')) {
                e = 37;
            }
            else if ($(this).hasClass('up-btn')) {
                e = 38;
            }
            else if ($(this).hasClass('right-btn')) {
                e = 39;
            }
            else if ($(this).hasClass('down-btn')) {
                e = 40;
            }
            $.Event("keydown", {keyCode: e});
        }); 

    });

})( jQuery );

FIDDLE

2 个答案:

答案 0 :(得分:0)

AND TIME

所以基本上你有一些错误。你的第一个是你的造型。你真的需要让你的风格更灵活,但这将解决我遇到的正确按钮问题。

.button-pad > div {
    z-index: 9999;
    width: 50px;
}

http://jsfiddle.net/34oeacnm/8/

 $(document).on('click', '.button-pad .button', function(e) {
     var e = jQuery.Event("keydown");
     if ($(this).hasClass('left-btn')) {
        e.which = 37;
     }
     else if ($(this).hasClass('up-btn')) {
        e.which = 38;
     }
     else if ($(this).hasClass('right-btn')) {
         e.which = 39;
     }
     else if ($(this).hasClass('down-btn')) {
        e.which = 40;
     }
     $(document).trigger(e);
}); 

你关闭了一些选择器。我偷了一些关于如何从Definitive way to trigger keypress events with jQuery触发的信息。

答案 1 :(得分:0)

这是在蛇游戏中添加Moile控制的代码; (如果您想要蛇游戏的全部代码,请评论);

// The dogList parameter
ParameterExpression dogParam = Expression.Parameter(typeof(List<Dog>), "dog");

// Begin of inner Select expression

// d parameter
ParameterExpression dParam = Expression.Parameter(typeof(Dog), "d");

// d.Breed *property* access (if it is a *field*, use Expression.Field)
MemberExpression dogProperty = Expression.Property(dParam, nameof(Dog.Breed));

// d.Breed.Trim() method call
MethodCallExpression trimCall = Expression.Call(dogProperty, nameof(string.Trim), Type.EmptyTypes);

// d.Breed.Trim().Length property access
MemberExpression lengthProperty = Expression.Property(trimCall, nameof(string.Length));

// d => d.Breed.Trim().Length
Expression<Func<Dog, int>> selectExpression = Expression.Lambda<Func<Dog, int>>(lengthProperty, dParam);

// End of inner Select expression

// Find the "right" overload of Enumerable.Select... A pain.
MethodInfo selectTSourceTResult = (from x in typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public)
                                    where x.Name == nameof(Enumerable.Select)
                                    let args = x.GetGenericArguments()
                                    where args.Length == 2
                                    let pars = x.GetParameters()
                                    where pars.Length == 2 &&
                                        pars[0].ParameterType == typeof(IEnumerable<>).MakeGenericType(args[0]) &&
                                        pars[1].ParameterType == typeof(Func<,>).MakeGenericType(args[0], args[1])
                                    select x).Single();

// Make the generic overload of Enumerable.Select "specific" for using with Func<Dog, int>
MethodInfo selectDogInt32 = selectTSourceTResult.MakeGenericMethod(typeof(Dog), typeof(int));

// Note that Enumerable.Select is a static method, the first parameter is the IEnumerable, the second is the Func<,>
// Enumerable.Select(dogList, d => d.Breed.Trim().Length)
MethodCallExpression selectCall = Expression.Call(selectDogInt32, dogParam, selectExpression);

// Begin of inner OrderByDescending expression

// d1 parameter
ParameterExpression d1Param = Expression.Parameter(typeof(int), "d1");

// d1 => d1
Expression<Func<int, int>> orderByExpression = Expression.Lambda<Func<int, int>>(d1Param, d1Param);

// End of inner OrderByDescending expression

// Find the "right" overload of Enumerable.OrderByDescending... Another pain.
MethodInfo orderByDescendingTSourceTKey = (from x in typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public)
                                            where x.Name == nameof(Enumerable.OrderByDescending)
                                            let args = x.GetGenericArguments()
                                            where args.Length == 2
                                            let pars = x.GetParameters()
                                            where pars.Length == 2 &&
                                                pars[0].ParameterType == typeof(IEnumerable<>).MakeGenericType(args[0]) &&
                                                pars[1].ParameterType == typeof(Func<,>).MakeGenericType(args[0], args[1])
                                            select x).Single();

// Make the generic overload of Enumerable.OrderByDescending "specific" for using with Func<int, int>
MethodInfo orderByDescendingInt32Int32 = orderByDescendingTSourceTKey.MakeGenericMethod(typeof(int), typeof(int));

// Note that Enumerable.OrderByDescending is a static method, the first parameter is the IEnumerable, the second is the Func<,>
// Enumerable.OrderByDescending(Enumerable.Select(...), d1 => d1)
MethodCallExpression orderByDescendingCall = Expression.Call(orderByDescendingInt32Int32, selectCall, orderByExpression);

// Find the "right" overload of Enumerable.First... Third big pain.
MethodInfo firstTSource = (from x in typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public)
                            where x.Name == nameof(Enumerable.First)
                            let args = x.GetGenericArguments()
                            where args.Length == 1
                            let pars = x.GetParameters()
                            where pars.Length == 1 &&
                                pars[0].ParameterType == typeof(IEnumerable<>).MakeGenericType(args[0])
                            select x).Single();

// Make the generic overload of Enumerable.OrderByDescending "specific" for using with int
MethodInfo firstInt32 = firstTSource.MakeGenericMethod(typeof(int));

// Note that Enumerable.First is a static method, the first parameter is the IEnumerable
// Enumerable.First(Enumerable.OrderByDescending(...))
MethodCallExpression firstCall = Expression.Call(firstInt32, orderByDescendingCall);

这里是HTML;

//Here is javascript;

// left key
  function l() {
    if(snake.dx === 0) {
      snake.dx = -grid;
      snake.dy = 0;
    }
  }

  // up key
  function u() {
    if(snake.dy === 0) {
      snake.dy = -grid;
      snake.dx = 0;
    }
  }

  // right key 
  function r() {
    if(snake.dx === 0) {
      snake.dx = grid;
      snake.dy = 0;
    }
  }
  // down key 
  function d() {
    if(snake.dy === 0) {
      snake.dy = grid;
      snake.dx = 0;
    }
  }

说明:我只是在html页面中添加了四个按钮,在js中创建了四个函数,它们将移动蛇,因为它应该沿不同的方向移动并将它们分别添加到不同按钮的'onclick'属性中。