Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Змейка, помогите пожалста :) 
V
    Опции темы
invis87
Дата 4.4.2009, 12:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 38
Регистрация: 1.11.2007
Где: город Королёв

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



Всем привет.
Не так давно начал изучать яву, и из-за необходимости практики решил написать своё приложение, так как нормальных идей нету остановился на змейке.
Итак змейку я представил как ArrayList содержащий в себе экземпляры класса отдельных кусочков её хвоста (квадратиков).
Шаг представляется добавлением нового экземпляра квадратика и стиранием предыдущего, но вот как раз в этом месте у меня косяк :(

Простой класс, нет ничего особенного и описывать не буду smile
Код

/**
 * Направления.
 */
public class Direction {
    protected static final byte UP=0, DOWN=1, LEFT=3, RIGHT=2;
    /**
     * текущее направление
     */
    private byte NOW;
    /**
     * Конструктор, первоначально змея смотрит вверх.
     */
    public Direction(){
        NOW=UP;
    }
    /**
     * Поворачивает змею.
     * @param WHERE куда повернуть
     */
    public void turn(byte WHERE){
        if((NOW==UP && WHERE!=DOWN) ||
           (NOW==LEFT && WHERE!=RIGHT) ||
           (NOW==DOWN && WHERE!=UP) ||
           (NOW==RIGHT && WHERE!=LEFT))
             NOW=WHERE;
    }
    
    public byte getNOW(){
        return NOW;
    }
}


Класс апплета, вроде тоже ничего сложного, надо сказать что пробел имитирует съедание змейкой одного объекта и фон чёрный для того чтобы было понятно как происходит движение змеи:
Код

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.*;
 
public class Game extends JApplet implements Runnable{
    private Direction direction = new Direction();
    Snake our_snake = new Snake();
    
    public Game(){
        setBackground(Color.BLACK);
        addKeyListener(new KeyAdapter(){
            @Override
            public void keyPressed(KeyEvent e) {
               switch(e.getKeyCode()){
                   case KeyEvent.VK_DOWN:
                       direction.turn(Direction.DOWN);break;
                   case KeyEvent.VK_UP:
                       direction.turn(Direction.UP);break;
                   case KeyEvent.VK_LEFT:
                       direction.turn(Direction.LEFT);break;
                   case KeyEvent.VK_RIGHT:
                       direction.turn(Direction.RIGHT);break;
                   case KeyEvent.VK_SPACE:
                       our_snake.add();
               }
            }
        });        
    }

    @Override
    public void paint(Graphics g){
        // g.clearRect(0, 0, getWidth(), getHeight());
        showStatus(Integer.toString(our_snake.ckolko()));
        our_snake.step(direction);
        our_snake.paint(g);
    }

    public void run() {
        for(;;){
            try {
            Thread.sleep(250);
            } catch (InterruptedException ex) {}
        repaint();
      }
    }

    @Override
    public void start() {
    Thread thread = new Thread(this);
    thread.setPriority(Thread.MIN_PRIORITY);
    thread.start();
    }
  }


И основной класс, который описывает змею, по идее тоже всё просто, но у меня косяк в методе paint, я не понимаю почему если добавить один квадратик, то предыдущие перестанут закрашиваться белым :( в этом основной косяк.
Код

import java.awt.*;
import java.util.ArrayList;

public class Snake {
    /**
     * Класс описывает поведение каждого отдельного квадрата
     * хвоста змеи.
     */
    private class Square{
        int NOW_X , NOW_Y;
 
        private Square(){}

        private void paint(int x, int y, int part, Graphics g){
            g.setColor(Color.green); // хвост зелёный
            g.fillRect(x, y, part, part); //квадратный
            NOW_X = x;
            NOW_Y = y;
        }

        private void erase(int part, Graphics g){
            g.setColor(Color.white);
            g.fillRect(NOW_X, NOW_Y, part, part);
        }

        private int getNOW_X(){
            return NOW_X;
        }

        private int getNOW_Y(){
            return NOW_Y;
        }
    }
    /**
     * Динамический массив содержит все отдельные части хвоста змеи.
     */
    ArrayList<Square> al = new ArrayList(4);
    /**
     * Ширина и высота одной части змеи
     */
    private final int part = 6;
    /**
     * Текущие координаты.
     */
    private int x=200,y=225;
    /**
     * С помощью этого флага удлиняем змейку.
     */
    private boolean delete = true;
    /**
     * Конструктор
     */
    Snake(){ al.add(new Square());}

    protected void paint(Graphics g){
        if(delete){
            al.get(al.size()-1).erase(part, g);  // мне кажется элементы не стираются когда их больше одного из-за отсутствия имени у экземпляра
                                                                 // класса, хотя может я не прав, это просто догадака
            al.remove(al.size()-1);        
        }
        delete = true;
        al.add(new Square());           // попробуйте перенести эти строки в начало метода
        al.get(0).paint(x, y, part, g); // опять же почему будет такой результат я не понимаю, стираться всё-равно же должно 
    }

    protected void add(){
        delete = false;
    }

    public int ckolko(){
        return al.size();
    }

    protected void step(Direction direction){
        switch(direction.getNOW()){
        case Direction.UP:
            y -= 6;break;
        case Direction.DOWN:
            y += 6;break;
        case Direction.LEFT:
            x -= 6;break;
        case Direction.RIGHT:
            x += 6;break;
        }
    }
}



Это сообщение отредактировал(а) invis87 - 4.4.2009, 12:49
PM MAIL   Вверх
Kangaroo
Дата 5.4.2009, 00:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


AA - Aussie Animal
****


Профиль
Группа: Участник Клуба
Сообщений: 2042
Регистрация: 7.10.2006
Где: US

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



Элементы добавляются в конец списка; попробуй так:
Код

if(delete){
            al.get(0).erase(part, g);  // тут использовать 0
            al.remove(0);        
        }
        delete = true;
        al.add(new Square());           
        al.get(al.size()-1).paint(x, y, part, g); // а тут - последний элемент



--------------------
Lost....
PM MAIL MSN   Вверх
invis87
Дата 5.4.2009, 16:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 38
Регистрация: 1.11.2007
Где: город Королёв

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



БЛИИИИИИИИИИИН !!!
Спасибо огромное, на такой фигне тупанул, заработало всё !!! Ура smile
PM MAIL   Вверх
invis87
Дата 13.4.2009, 23:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 38
Регистрация: 1.11.2007
Где: город Королёв

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



Довёл до разума. Всё ещё сырая, но играть можно smile
Буду рад услышать критику.
Вот она + исходники.

Snake.java
Код
import java.awt.*;
import java.util.Random;
import java.util.ArrayList;
/**
 *
 * @author invis
 */
public class Snake {
    /**
     * Класс описывает поведение каждого отдельного квадрата
     * хвоста змеи.
     */
    private class Square{
        private int NOW_X , NOW_Y;
 
        private Square(){}

        private void paint(int x, int y, int part, Graphics g){
            g.setColor(Color.green); // хвост зелёный
            g.fillRect(x, y, part, part); //квадратный
            NOW_X = x;
            NOW_Y = y;
        }

        private void erase(int part, Graphics g){
            g.setColor(Color.white);
            g.fillRect(NOW_X, NOW_Y, part, part);
        }
    }
    /**
     * Динамический массив содержит все отдельные части хвоста змеи.
     */
    ArrayList<Square> al = new ArrayList(4);
    /**
     * Ширина и высота одной части змеи
     */
    private final int part = 6;
    /**
     * Объект для рисования "еды" в случайном месте.
     */
    Random random = new Random();
    /**
     * Текущие координаты.
     */
    private int x=216,y=216;
    /**
     * Координата Х "еды".
     */
    private int eatX;
    /**
     * Координата Y "еды".
     */
    private int eatY;
    /**
     * С помощью этого флага удлиняем змейку.
     */
    private boolean delete = true;
    /**
     * Создана ли уже "еда" для змейки.
     */
    private boolean alreadyCreate = false;
    /**
     * Жива ли змея.
     */
    protected boolean alive = true;
    /**
     * Конструктор создаёт один экземпляр квадратика.
     */
    Snake(){ al.add(new Square());}

    protected void paint(Graphics g){
        if(delete){
            al.get(0).erase(part, g);
            al.remove(0);
        }else{delete = true;}
        al.add(new Square());
        al.get(al.size()-1).paint(x, y, part, g);
    }

    public int gdeY(){
        return al.get(al.size()-1).NOW_Y;
    }

    public int gdeX(){
        return al.get(al.size()-1).NOW_X;
    }

    protected void step(Direction direction){
        switch(direction.getNOW()){
        case Direction.UP:
            y -= 6;break;
        case Direction.DOWN:
            y += 6;break;
        case Direction.LEFT:
            x -= 6;break;
        case Direction.RIGHT:
            x += 6;break;
        }
        //не врезалась ли змейка в стену
        if(x > 471 || x < 4 || y > 471|| y < 4){
            alive=false;
        }
        //не съела ли змейка себя
        for (int i = 0; i < al.size()-1; i++) {
           if (x == al.get(i).NOW_X &&
               y == al.get(i).NOW_Y){
               alive=false;
               }
        }
    }
    /**
     * Рисует "еду" для змейки в случайном месте.
     * @param g
     */
    protected void food(Graphics g){
        if(eatX == x && eatY == y){
            alreadyCreate = false;
        }
        if(!alreadyCreate){
            eatX = (random.nextInt(77)+1)*6;
            eatY = (random.nextInt(77)+1)*6;
            g.setColor(Color.BLUE);
            g.fillRect(eatX, eatY, part, part);
            //добавить квадратик к змее.
            delete = false;
            alreadyCreate = true;
        }
    }
}


Direction.java
Код
/**
 * Направления.
 * @author invis
 */
public class Direction {
    protected static final byte UP=0, DOWN=1, LEFT=3, RIGHT=2;
    /**
     * текущее направление
     */
    private byte NOW;
    /**
     * Конструктор, первоначально змея смотрит вверх.
     */
    public Direction(){
        NOW=UP;
    }
    /**
     * Поворачивает змею.
     * @param WHERE куда повернуть
     */
    public void turn(byte WHERE){
        if((NOW==UP && WHERE!=DOWN) ||
           (NOW==LEFT && WHERE!=RIGHT) ||
           (NOW==DOWN && WHERE!=UP) ||
           (NOW==RIGHT && WHERE!=LEFT))
             NOW=WHERE;
    }
    
    public byte getNOW(){
        return NOW;
    }
}


Game.java
Код

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.*;
/**
 *
 * @author invis
 */
public class Game extends JApplet implements Runnable{
    private Direction direction = new Direction();
    Snake our_snake = new Snake();
    /**
     * Флаг нужнг для передачи фокуса во время первого рисования.
     */
    boolean mFirstPaint = true;
    
    public Game(){
        setSize(480, 480);
        setBackground(Color.white);
        addKeyListener(new KeyAdapter(){
            @Override
            public void keyPressed(KeyEvent e) {
               switch(e.getKeyCode()){
                   case KeyEvent.VK_DOWN:
                       direction.turn(Direction.DOWN);break;
                   case KeyEvent.VK_UP:
                       direction.turn(Direction.UP);break;
                   case KeyEvent.VK_LEFT:
                       direction.turn(Direction.LEFT);break;
                   case KeyEvent.VK_RIGHT:
                       direction.turn(Direction.RIGHT);break;
               }
            }
        });        
    }
    /**
     * Выводит сообщение о поражении.
     */
    public void loose(){
        getGraphics().drawString("LOOSER", 220, 230);
    }

    @Override
    public void paint(Graphics g){
        // передаём фокус апплету
        if (mFirstPaint){
            mFirstPaint = false;
            requestFocus();
        }
        showStatus("X - " + Integer.toString(our_snake.gdeX()) + "; Y - " + Integer.toString(our_snake.gdeY()));
        g.setColor(Color.black);
        g.drawRect(4, 4, 471, 471);
        our_snake.step(direction);
        our_snake.paint(g);
        our_snake.food(g);
    }

    public void run() {
        while(our_snake.alive){
            try {
            Thread.sleep(100);
            } catch (InterruptedException ex) {}
            repaint();
        }
        if(!our_snake.alive){loose();return;}
    }

    @Override
    public void start() {
    Thread thread = new Thread(this);
    thread.setPriority(Thread.MIN_PRIORITY);
    thread.start();
    }
  }

P.S. лучше открывать в appletviewer. У меня googlechrome и если апплет открыть 5-й страницей, то он немного подлагивает.
P.S.S Такая большая скорость только из-за того, что поле большое.

Это сообщение отредактировал(а) invis87 - 14.4.2009, 00:08
PM MAIL   Вверх
zoidberg
Дата 12.5.2009, 09:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Змейка клевая, убил на нее минут 20. Классика - затягивает. %)
PM MAIL   Вверх
KapsuL
Дата 14.6.2009, 23:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



чёт не могу сделать проект....ето ведь в NetBeans пишется???ява апликейшн или десктоп ява апликешн...?после того как создаю проект и классы пишет что не найден мейн класс... smile

Добавлено через 6 минут и 32 секунды
после запуска выдаёт такое:
а ещё плюётся на import java.awt.*;

Присоединённый файл ( Кол-во скачиваний: 16 )
Присоединённый файл  error.JPG 16,73 Kb
PM MAIL   Вверх
korob2001
Дата 21.6.2009, 11:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2871
Регистрация: 29.12.2002

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



Цитата(KapsuL @  14.6.2009,  20:28 Найти цитируемый пост)
чёт не могу сделать проект....ето ведь в NetBeans пишется???ява апликейшн или десктоп ява апликешн...?после того как создаю проект и классы пишет что не найден мейн класс...

Вообще-то это апплет.
1. Положи все файлы .java в один каталог.
2. В терминале дай команду javac /путь к каталогу/Game.java
3. В тот же каталог положи такой HTML файл:
Код

<html>
    <head>
        <title>Snake</title>
    </head>
    <body>
        <applet code="Game" width="500" height="600"></applet>
    </body>
</html>

4. Открой этот html в браузере.


--------------------
"Время проходит", - привыкли говорить вы по неверному пониманию. 
"Время стоит - проходите вы".
PM MAIL WWW ICQ MSN   Вверх
KapsuL
Дата 22.6.2009, 12:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



спасибо, разобрался)) smile 
PM MAIL   Вверх
invis87
Дата 27.6.2009, 18:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 38
Регистрация: 1.11.2007
Где: город Королёв

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



Я нашёл баг smile
 Синий квадратик может появиться прямо на змейке smile в этом случае когда последний квадрат змеи по нему проедет то он исчезнет, но съесть всё-равно можно ^^
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Апплеты | Следующая тема »


 




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


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

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