Модераторы: Sardar, Aliance
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Змейка, Игра змейка 
:(
    Опции темы
PsiMagistr
Дата 9.11.2017, 08:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 479
Регистрация: 31.12.2009

Репутация: нет
Всего: 1



Ребята, помогите разобраться. Я решил написать канвасную (Canvas) змейку. Все шло довольно быстро, пока я не натолкнулся на следующую проблему.


Змейка это объект. У змейки есть метод moveSnake, который и двигает ее. Двигает он ее следующим образом В этом же самом методе вшит таймер setTimeout, который этот метод вызывает (как бы рекурсивно).
Пока мы играем первый раз - все замечательно. Но как только мы проиграли, хотим сделать перерисовку сцены, затираем Канвас, порождаем новую змейку, на экране их получается две! Наша старая змейка, в своих старых координатах, которая получает управление. И новая, которая видна на экране, но абсолютно мертва. Управление ведется клавишами со стрелками.




Код

var canvas; // Холст
var context; // Контекст холста.
var width = 20; // ширина сегмента
var vector = {value:''}; //= 'right';
var ban = 'left';
var fruit;
var free = true; //Свободен ли таймер.
var mySnake;
var message;



function elemBody(x, y) {
    this.x = x;
    this.y = y;
}

function drawFruit(){
    fruit.x = randomInteger(0, 39);
    fruit.y = randomInteger(0,39);
    paintSquare(fruit.x, fruit.y, '#800000');
}


function randomInteger(min, max) {// Функция случайного числа в звданном диапазоне.
    var rand = min + Math.random() * (max + 1 - min);
    rand = Math.floor(rand);
    return rand;
}



function paintSquare (x, y, color) { //Функция отрисовки сегмента
    if (color != '') {
        context.fillStyle = color;
        context.fillRect(width * x + 1, width * y + 1, width - 2, width - 2);
    }
    else {
        context.clearRect(width * x + 1, width * y + 1, width - 2, width - 2);
    }

} // Конец функции.



function snake(length, tailColor, headColor) { //Cоздаем змейку. Конструктор.
    this.body = [];
    this.length = length;
    this.last = new elemBody(-1, -1);
    this.hit = 0; //Очки
    this.timer;


    this.moveSnake = function(vector){ // Функция движения змейки Двигаем
        //alert();
        if(vector.value == 'left' || vector.value == 'right' || vector.value == 'up' || vector.value == 'down') {
            this.last.x = this.body[this.body.length - 1].x; //Запоминаем последний элемент хвоста по х
            this.last.y = this.body[this.body.length - 1].y; //запоминаем последний элемент хвоста по у
            paintSquare(this.last.x, this.last.y, ''); //затираем хвост.

            for (i = this.body.length-1; i >= 1; i--) {
                this.body[i].x = this.body[i - 1].x;
                this.body[i].y = this.body[i - 1].y;
                paintSquare(this.body[i].x, this.body[i].y, tailColor);
            } //Двигаем тело

            switch (vector.value) {
                case 'right':
                    this.body[0].x++;
                    break;
                case 'left':
                    this.body[0].x--;
                    break;
                case 'up':
                    this.body[0].y--;
                    break;
                case 'down':
                    this.body[0].y++;
                    break;
            }

            paintSquare(this.body[0].x, this.body[0].y, headColor);

            if(this.body[0].x == fruit.x && this.body[0].y == fruit.y){ //Если ты столкнулся с фруктом.
                //alert();
                this.body[this.body.length] = new elemBody(this.last.x, this.last.y);
                paintSquare(this.last.x, this.last.y, tailColor);
                drawFruit();
                this.hit++;
                message.innerHTML = 'Счет: ' + this.hit;
            }

            for(i=1; i < this.body.length-1; i++){
                if(this.body[0].x == this.body[i].x && this.body[0].y == this.body[i].y){
                    message.innerHTML = 'GameOver';
                   //clearInterval(timer);
                    alert('GameOver');
                    start();
                    break;
                }
            }
       }
      // var thiss = this;

         //  console.log(thiss);
           free = true;
          // thiss.moveSnake(vector);
         //  console.log(vector);

      // },100);
       // clearTimeout(timer);
        this.timer = setTimeout(() => this.moveSnake(vector), 100);
    }




    var j = -1;
    for(i=this.length; i >=1; i--){
        j++;
        this.body[i] = new elemBody(j, 0);
        paintSquare(this.body[i].x, this.body[i].y, tailColor);
    }
    j++;
    this.body[0] = new elemBody(j, 0);
    paintSquare(this.body[i].x, this.body[i].y, headColor); //создание змейки

}


window.onload = function () { //Событие загрузски страницы
   start();
 // timer = setInterval(function(){
     // clearTimeout(timer);
      mySnake.moveSnake(vector);
      free = true;
  // },100);


}


function loadScena() { //

    canvas = document.getElementById("canvas");
    context = canvas.getContext('2d');
    context.clearRect(0, 0, canvas.width, canvas.height);
    for (y = 0; y < 800; y += width) {
        for (x = 0; x < 800; x += width) {
            context.strokeRect(x, y, width, width);
        }
    }

}


function start(){
    //context.clearRect(0, 0, canvas.width, canvas.height);
   // alert(context);
    loadScena();
    vector.value = '';
    ban = 'left';
   // delete(mySnake);
    mySnake = new snake(3, 'orange', 'red');
    fruit = new elemBody(randomInteger(0,39), randomInteger(0,39));
    paintSquare(fruit.x, fruit.y, '#800000');
    message = document.getElementById('message');
    message.innerHTML = 'Счет: ' + mySnake.hit;
}


document.onkeydown = function (event) { //Обработчик событий клавиатуры

    if(free == true) {

        free = false;

        switch (event.keyCode) { //Вправо
            case 39:
                if (ban != 'right') {
                   ban = 'left';
                   vector.value = 'right';
                   // alert();
                }
                break;
            case 40: // вниз
                if (ban != 'down') {
                    ban = 'up';
                    vector.value = 'down';
                }
                break;
            case 37://Влево
                if (ban != 'left') {
                    ban = 'right';
                    vector.value = 'left';
                }
                break;
            case 38: //Вверх
                if (ban != 'up') {
                    ban = 'down';
                    vector.value = 'up';
                }
                break;
            case 32:
                vector.value = '';
                break;

        }

    }

}


Для тех кто захочет поиграть и увидеть проблему в действии, пожалуйста прилагаю полный набор. (html, css, js)




Если вынести таймер из объекта во внешний мир (только он уже будет setInterval) Такой проблемы не возникает.



Заранее спасибо тем, кто поможет разобраться!

Код

var canvas; // Холст
var context; // Контекст холста.
var width = 20; // ширина сегмента
var vector; //= 'right';
var ban = 'left';
var timer; // Таймер
var fruit;
var free = true; //Свободен ли таймер.
var mySnake;
var message;



function elemBody(x, y) {
    this.x = x;
    this.y = y;
}

function drawFruit(){
    fruit.x = randomInteger(0, 39);
    fruit.y = randomInteger(0,39);
    paintSquare(fruit.x, fruit.y, '#800000');
}


function randomInteger(min, max) {// Функция случайного числа в звданном диапазоне.
    var rand = min + Math.random() * (max + 1 - min);
    rand = Math.floor(rand);
    return rand;
}



function paintSquare (x, y, color) { //Функция отрисовки сегмента
    if (color != '') {
        context.fillStyle = color;
        context.fillRect(width * x + 1, width * y + 1, width - 2, width - 2);
    }
    else {
        context.clearRect(width * x + 1, width * y + 1, width - 2, width - 2);
    }

} // Конец функции.



function snake(length, tailColor, headColor) { //Cоздаем змейку. Конструктор.
    this.body = [];
    this.length = length;
    this.last = new elemBody(-1, -1);
    this.hit = 0; //Очки


    this.moveSnake = function(vector){ //Двигаем
        //alert();
        if(vector == 'left' || vector == 'right' || vector == 'up' || vector == 'down') {
            this.last.x = this.body[this.body.length - 1].x; //Запоминаем последний элемент хвоста по х
            this.last.y = this.body[this.body.length - 1].y; //запоминаем последний элемент хвоста по у
            paintSquare(this.last.x, this.last.y, ''); //затираем хвост.

            for (i = this.body.length-1; i >= 1; i--) {
                this.body[i].x = this.body[i - 1].x;
                this.body[i].y = this.body[i - 1].y;
                paintSquare(this.body[i].x, this.body[i].y, tailColor);
            } //Двигаем тело

            switch (vector) {
                case 'right':
                    this.body[0].x++;
                    break;
                case 'left':
                    this.body[0].x--;
                    break;
                case 'up':
                    this.body[0].y--;
                    break;
                case 'down':
                    this.body[0].y++;
                    break;
            }

            paintSquare(this.body[0].x, this.body[0].y, headColor);

            if(this.body[0].x == fruit.x && this.body[0].y == fruit.y){ //Если ты столкнулся с фруктом.
                //alert();
                this.body[this.body.length] = new elemBody(this.last.x, this.last.y);
                paintSquare(this.last.x, this.last.y, tailColor);
                drawFruit();
                this.hit++;
                message.innerHTML = 'Счет: ' + this.hit;
            }

            for(i=1; i < this.body.length-1; i++){
                if(this.body[0].x == this.body[i].x && this.body[0].y == this.body[i].y){
                    message.innerHTML = 'GameOver';
                   //clearInterval(timer);
                    alert('GameOver');
                    start();
                    break;
                }
            }
       }
     //  var thiss = this;
       //timer = setTimeout(function(){
         //  console.log(thiss);
          // thiss.moveSnake(vector);
         //  console.log(vector);

       //},100);

    }




    var j = -1;
    for(i=this.length; i >=1; i--){
        j++;
        this.body[i] = new elemBody(j, 0);
        paintSquare(this.body[i].x, this.body[i].y, tailColor);
    }
    j++;
    this.body[0] = new elemBody(j, 0);
    paintSquare(this.body[i].x, this.body[i].y, headColor); //создание змейки

}


window.onload = function () { //Событие загрузски страницы
   start();
  timer = setInterval(function(){
        mySnake.moveSnake(vector);
      free = true;
   },100);


}


function loadScena() { //

    canvas = document.getElementById("canvas");
    context = canvas.getContext('2d');
    context.clearRect(0, 0, canvas.width, canvas.height);
    for (y = 0; y < 800; y += width) {
        for (x = 0; x < 800; x += width) {
            context.strokeRect(x, y, width, width);
        }
    }

}


function start(){
    //context.clearRect(0, 0, canvas.width, canvas.height);
   // alert(context);
    loadScena();
    vector = '';
    ban = 'left';
    mySnake = new snake(3, 'green', 'red');
    fruit = new elemBody(randomInteger(0,39), randomInteger(0,39));
    paintSquare(fruit.x, fruit.y, '#800000');
    message = document.getElementById('message');
    message.innerHTML = 'Счет: ' + mySnake.hit;
}


document.onkeydown = function (event) { //Обработчик событий клавиатуры

   // if(free == true) {

       // free = false;

        switch (event.keyCode) { //Вправо
            case 39:
                if (ban != 'right') {
                   ban = 'left';
                   vector = 'right';
                   // alert();
                }
                break;
            case 40: // вниз
                if (ban != 'down') {
                    ban = 'up';
                    vector = 'down';
                }
                break;
            case 37://Влево
                if (ban != 'left') {
                    ban = 'right';
                    vector = 'left';
                }
                break;
            case 38: //Вверх
                if (ban != 'up') {
                    ban = 'down';
                    vector = 'up';
                }
                break;
            case 32:
                vector = '';
                break;

        }

  //  }

}








Присоединённый файл ( Кол-во скачиваний: 6 )
Присоединённый файл  snakeproblems.rar 3,25 Kb


--------------------
"Арфы нет? Возьмите бубен!

Ребята, будем жить!"

 (с) "В бой идут одни старики"

---

"ИЕ" - один из самых сумасшедших браузеров в нашей галактике.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Здесь публикуют скрипты, которые уже проверены в обсуждениях других тем (при этом полезно поставить ссылки на все смежные обсуждения) или переносятся кем-либо из модераторов по просьбе участников, если видно, что в результате обсуждения темы был написан полезный или интересный скрипт. Третий возможный вариант - участник форума публикует скрипт, заведомо известный как полезный и эффективный, для, возможно, небольшой доработки и обсуждения.
 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | JavaScript: Наши скрипты | Следующая тема »


 




[ Время генерации скрипта: 0.1117 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.