Модераторы: Rickert

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Разработка игры "Территория" (Точки), Java, с нуля 
:(
    Опции темы
arilou
Дата 6.1.2009, 17:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Великий МунаБудвин
****


Профиль
Группа: Экс. модератор
Сообщений: 2646
Регистрация: 15.7.2004
Где: город-герой Минск

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



Qawra, я переименую тему в "Разработка игры "Территория", обащайтесь на здоровье.


--------------------
user posted imageuser posted image
PM WWW ICQ   Вверх
Rpahut
Дата 6.1.2009, 22:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


0xdeadbeef
*


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

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



Да уж с темами кавардак...

Давайте что-ли сначала выбор цвета добьем.
Итак, мы желаем чтобы пользователь мог выбрать цвета игроков, до того как будут созданы сами игроки. Поскольку игроков еще нет, сохранить цвет в них мы не можем, стало быть нам понадобятся переменные для хранения цвета, и их нужно будет две, потому что игроков двое и каждый из них должен иметь свой цвет. Одной переменной playerColor тут не обойтись.

Цитата

А что будет если игрок сразу нажмёт кнопку старт ? У него не будет предустановленного цвета ?

Да. Сам по себе он не появится. 

Цитата

Может быть приравнять в начале класса private Color playerColor = Color.white 

Вначале - это в конструкторе. И, если у нас будет две переменные, можно будет в каждую из них положить свой цвет - например красный и синий. Потом, когда создаем игроков, передаем каждому его цвет. И ничего уже проверять не нужно будет - независимо от того, станет пользователь менять цвет или нет, игроки все равно будут разноцветные.

Дополнительно, хотя и не обязательно:
1. Вставьте проверку на null в метод ShowChooser():
Код

public Color ShowChooser(Color defaultColor) {
    Color choosedColor = JColorChooser.showDialog(this, "Choose your color",  defaultColor);
    if(choosedColor==null) return defaultColor;
    return choosedColor;
}

Вместо того чтобы всякий раз проверять что там нам вернулось, так можно быть уверенным что вернется то что нужно.
Сам метод стоит переименовать, чтобы название соответствовало тому, что он делает с точки зрения программы - например ChangeColor или что-то в таком духе.

2. private  ColorChooser cchooser = new ColorChooser ();
Не нужно делать ColorChooser членом класса. Он не хранит внутри никаких данных, которые были бы нужны классу, и его можно создать когда он понадобится, например в методе где обрабатываются кнопки, а после использования выкинуть и забыть.

Так, что еще...

Цитата

Класс  Player совсем укоротился и выглядит так 

Тут зависит от того, как будет игра построена, но хранить orderOfPlayers внутри класса Игрок скорее всего не понадобится. Как раз должен быть вышестоящий класс, заведующий порядком ходов. В любом случае у нас уже есть переменные first и second, ясно что first это first, а second соответственно second.
--------------------
C/C++ GameDevRSS Раздела программирования игрOpenGL - уроки от NeHeКак продать идею?
PM MAIL   Вверх
Rpahut
Дата 7.1.2009, 00:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


0xdeadbeef
*


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

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



Теперь решетка.
Ну, помимо размера тут нам понадобится еще знать размер клетки. Вместо того чтобы самим считать и указывать размер Grids, мы дадим ему количество клеток по горизонтали и вертикали, плюс размер клетки. Тогда размер канваса можно будет посчитать:
width = rows*cellSize; и height = cols*cellSize;
Переменные width и height удобно сделать членами класса GridsCanvas и вычислять их значения в конструкторе. После вычисления размеров конструктор GridsCanvas должен сам вызывать SetSize(). 

Чем больше автоматики, тем меньше ручной работы. Так GridCanvas сам посчитает, сколько нужно места для отображения всех точек, у нас просто нет возможности сделать его слишком большим или слишком маленьким. Кроме того, у вас вычисляются rowHt и rowWid, вместо них можно использовать cellSize (эту переменную, кстати, тоже надо вписать в члены класса).

Касательно явы - возможно придется в GridCanvas переделать метод getPreferredSize() для того чтобы pack() сработал правильно. Еще хорошо бы вокруг канваса оставить пустое пространство, иначе крайние точки окажутся на самом краю окна и тыкать в них будет неудобно.

Еще момент, который кажется остался не понятым - мы не работаем с клетками, мы работаем с точками. Клетки чертятся по точкам, а не точки в углах клеток. Вообще сетку мы рисуем для красоты, работать все будет и без нее.

Дальше - т.к. каждый объект должен заниматься своим делом, расположение точек на канвасе мы оставим канвасу, а рисование точек - точкам. Поэтому класс Точка не будет знать свои координаты на канвасе. Вместо этого Точка будет рисовать всегда в координате [0, 0]
Код

// например
g.drawOval(-radius, -radius, radius*2, radius*2);

но!
Перед тем как просить точку нарисоваться, канвас будет вызывать Graphics.translate():
Код

// например
g.translate(pointPosX, pointPosY);

так что когда точка станет рисовать Oval, координаты [0, 0] будут именно там, где должна отобразиться точка.
В принцип работы translate() можно не вникать. Главное это после отрисовки точки вернуть все как было:
Код

g.translate(-pointPosX, -pointPosY);

иначе [0, 0] будет сдвигаться все дальше и дальше по мере рисования точек и улетит совсем. Не говоря уже о том, что точки будут появляться совсем не там где нам нужно.

Все вместе:
Если в классе Точка есть
Код

public void paint(Graphics g) {
  g.drawOval(-radius, -radius, radius*2, radius*2);
}

тогда в GridsCanvas.paint() пишем так:
Код

// рисуем сетку - опционально

// делаем цикл по всем точкам {
// вычисляем координаты точки на канвасе - pointPosX и pointPosY
g.translate(pointPosX, pointPosY);
currentPoint.paint(g);
g.translate(-pointPosX, -pointPosY);
// конец цикла по всем точкам }


Как считать координаты точки, зависит от того, как мы их храним. Я делал двумерный массив Точек размером [rows][cols], в цикле рисования поля у меня были переменные x и y, соответсвенно координаты точки [x][y] = [x*cellSize, y*cellSize].
Точки создаются все сразу, при создании игрового поля, и существуют уже до того как игроки их поставят. Вобще игроки у нас не ставят точки, они их просто помечают как свои... Точка, если она не помечена, либо не рисуется совсем, либо рисуется с меньшим радиусом, либо как-нибудь так рисуется чтобы ее можно было отличить от помеченной - ну это потом можно будет метод paint() точки дорабатывать по мере надобности.
--------------------
C/C++ GameDevRSS Раздела программирования игрOpenGL - уроки от NeHeКак продать идею?
PM MAIL   Вверх
Qawra
Дата 7.1.2009, 20:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



По порядку  и старательно :
1.  рисуем две независимые переменные хранящие предустановленный цвет игроков.
Код

private Color secondDefautColor= Color.red;
  private  ColorChooser cchooser = new ColorChooser (); 

на кнопках теперь будет 
Код

if (e.getSource().equals(startButton)) 
    {new Grids("Points", 800, 800, 20, 20).setVisible(true);
        Player first= new Player(1, firstDefaultColor);
        Player second = new Player(2,secondDefaultColor);  
     
    } else if (e.getSource().equals(firstPlayerButton)) 
    {  fistPlayerColor = cchooser.ChangeColor( firstDefaultColor  );
                
    } else if (e.getSource().equals(secondPlayerButton)) 
    { secondPlayerColor = cchooser.ChangeColor(secondDefaultColor  );       
    } 
 а вот с Color Chooser теперь непонятно..Что передавать в качестве аргумента если переменные хранящие цвет теперь имеют разные названия ?
Код

public Color ChangeColor(Color ?"?"?) {
    Color choosedColor = JColorChooser.showDialog(this, "Choose your color",  ?"?"?);
    if(choosedColor==null) return ?????;
    return choosedColor;
 получается нам нужна ещё одна переменная хранящая цвет или мы можем прописать метод дважды ChangeColor1 и ChangeColor2 ? smile

2 . без строчки private  ColorChooser cchooser = new ColorChooser (); не компелируется ( не может найти cchooser )

3.  В конструкторе Player опять проблема с именем переменной хранящей цвет .
Код

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Player 
 {
  private Color playerColor;
  
  public Player(Color ???? ) // constructor 
  {    
      this.????? = ????;   
    }
 }
 делать второй конструктор как то неудобно .Значит надо подумать о переменной хранящей цвет ..Не избежать её !

PM MAIL   Вверх
Qawra
Дата 7.1.2009, 21:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



 с решёткой .....я рассматриваю свой GridsCanvas и его конструктор 
Код

class GridsCanvas extends Canvas {

    int rows;
    int cols;

    GridsCanvas(int r, int c) {
        rows = r;
        cols = c;
    }

    public void paint(Graphics g) {
        int i;
        int width = getSize().width;
        int height = getSize().height;
        // draw the rows
        int rowHt = height / (rows);
        for (i = 0; i < rows; i++)
            g.drawLine(0, i * rowHt, width, i * rowHt);
        // draw the columns
        int rowWid = width / (cols);
        for (i = 0; i < cols; i++)
            g.drawLine(i * rowWid, 0, i * rowWid, height);
    }
}
 получается что метод public void paint(Graphics g) надо вызвать внутри конструктора . Там же вызвать метод SetSize(). Его видимо надо найти в sun tutorials .
О методе  getPreferredSize() я не знала я просто хотела наложить решётку на новую JFrame . Надеюсь то тогда целиться в точки будет удобнее .

Начиная с фразы "Клетки чертятся по точкам, а не точки в углах клеток. Вообще сетку мы рисуем для красоты, работать все будет и без нее."
я впала в процесс осмысления который видимо затянется до утра ...
Завтра я постараюсь нарисовать что я поняла smile 



PM MAIL   Вверх
Rpahut
Дата 7.1.2009, 23:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


0xdeadbeef
*


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

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



Цитата

с Color Chooser теперь непонятно..Что передавать в качестве аргумента если переменные хранящие цвет теперь имеют разные названия ?

Ну, вернемся к основам...
cchooser.ChangeColor(firstDefaultColor);
Когда мы вызываем метод, мы передаем ему аргументы. В данном случае у нас вписана переменная firstDefaultColor, в которой хранится Color.blue. Фишка в том, что мы не передаем саму переменную, мы не можем никак передать переменную - мы передаем значение которое хранится в переменной. Т.е. ChangeColor(firstDefaultColor) это то же самое что ChangeColor(СинийЦвет).

Внутри метода мы принимаем параметр
public Color ChangeColor(Color ?"?"?) {
не важно как он называется здесь, Ява просто засунет в эту переменную значение, которое мы передали(СинийЦвет). И Ява не запутается что куда класть, потому что метод принимает цвет, и мы передаем цвет, и там это первый параметр(и единственный), и тут первый параметр... Короче, компилятор ориентируется по типу и порядку аргументов, а не по их имени. Для самого метода этот параметр вообще выглядит как переменная, в которой как-то сам собой оказался синий цвет.
Программисту в отличии от компилятора проще ориентироваться по имени. Удобно называть параметр defaultColor, потому что это и есть по сути цвет по умолчанию, хотя вы можете выбрать название на свой вкус.


Цитата

2 . без строчки private  ColorChooser cchooser = new ColorChooser (); не компелируется ( не может найти cchooser )

А попробуйте сами его найти smile 
Его надо создать. Кажется, я писал об этом. Всякий объект перед тем как его можно будет использовать, должен быть создан. Но не нужно вписывать его как член класса, а нужно его прямо там создать где он используется, в методе где обрабатываются нажатия кнопок. Потому что он используется только там, потому что не хранит никакой нужной нам информации; нет никакой причины делать его членом класса. Вы же не выписываете все используемые в классе переменные в члены класса.

Цитата

3.  В конструкторе Player опять проблема...

А вот и нет. Тут то же что и с ChangeColor() - имя менять не нужно. Будет работать как есть.

Все. Когда с выбором цвета будет покончено, тогда перейдем к игровому полю.
--------------------
C/C++ GameDevRSS Раздела программирования игрOpenGL - уроки от NeHeКак продать идею?
PM MAIL   Вверх
Qawra
Дата 8.1.2009, 20:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Я решилась оставить только две переменные хранящие цвет 
Код

private Color firstDefautColor= Color.blue;
  private Color secondDefautColor= Color.red;


На кнопках результат такого сокращения выглядит как то странно  , но с точки компайлера возможно это вполне разумно 
Код

if (e.getSource().equals(startButton)) 
    {
        new Grids("Points", 800, 800, 20, 20).setVisible(true);
        //Vector points = (Point) GridCanvas
       Player first= new Player(  firstDefautColor);
       Player second = new Player( secondDefautColor);  
     
  } else if (e.getSource().equals(firstPlayerButton)) 
    { firstDefautColor = cchooser.ChangeColor( firstDefautColor  );
          
    } else if (e.getSource().equals(secondPlayerButton)) 
    { 
       secondDefautColor = cchooser.ChangeColor( secondDefautColor  );
    } 
 то есть цвет либо останется либо измениться но он всё равно будет ..
При выборе цвета у меня получилось 
Код

{
Color choosedColor = JColorChooser.showDialog(this, "Choose your color",  firstDefautColor);
    if(choosedColor==null)
    {   firstDefautColor=choosedColor;
        return  firstDefautColor;
    }return  firstDefautColor;
}
 не знаю как это будет работать . Идея была оставить игроку одно название цвета независимо от того сам он его выбрал или цвет был задан  по умолчанию.  Смущают правда  два идентичных return ... 
Конструктор для игрока предполагает  дополнительную переменную playerColor
Код

 public Player(Color firstDefautColor ) // constructor 
  {    
      this.playerColor = firstDefautColor;   
    }
 Что мы с ней потом  будем делать ? 



PM MAIL   Вверх
Rpahut
Дата 9.1.2009, 01:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


0xdeadbeef
*


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

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



Цитата

не знаю как это будет работать.


Работать это будет очень интересно:
Код

если(выбранныйЦвет==пустой) { // если пользователь отказался выбрать:
  цветПоУмолчанию = выбранныйЦвет; // т.е. цветПоУмолчанию = пустой;
  вернуть цветПоУмолчанию; // т.е. вернуть пустой(цвет)
}
// иначе, если пользователь выбрал цвет:
вернуть цветПоУмолчанию; // т.е. вернуть цвет, переданный в метод, не меняя его


Нам же нужно, чтобы возвращался:
1. цвет выбранный пользователем, если он его выбрал; 
2. а если не выбрал - то цвет по умолчанию (нам обязательно нужно вернуть обратно какой-то цвет, ради этого и существует метод; если пользователь не хочет выбирать цвет, нам придется вернуть цвет по умолчанию - потому что другого у нас просто нет).
Записываем это дело по-русски:
Код

если(пользователь выбрал цвет) {
  вернуть выбранный цвет;
}
иначе {
  вернуть цвет по умолчанию;
}


дальше переводим:
Код

если(выбранныйЦвет!=пустой) { // если выбранный цвет не пустой
  вернуть выбранныйЦвет;
}
иначе { // если выбранный цвет - пустой
  вернуть цветПоУмолчанию;
}


а теперь просто записываем то же самое на Яве:
Код

if(choosedColor!=null) { // если(выбранныйЦвет!=пустой) {
  return choosedColor; // вернуть выбранныйЦвет;
}
else { // иначе {
  return defaultColor; // вернуть цветПоУмолчанию;
}

============================================
Цитата

Идея была оставить игроку одно название цвета независимо от того сам он его выбрал или цвет был задан  по умолчанию.

Не надо так париться с именами. 
Когда мы возвращаем значение, мы возвращаем значение, т.е. то, что лежит внутри переменной. Мы пишем имя переменной, чтобы Ява знала, из какой переменной взять значение. Сама переменная не передается и не возвращается.
Код

// например:
int SomeMethod() {
  ...
  return myVariable; // Значение выдергивается из переменной с именем myVariable
}
...
int myOtherVariable = SomeMethod(); // ...и засовывается в переменную с именем myOtherVariable 
//=================================




//=================================
int integerVariable = 10; // засовываем в переменную с именем integerVariable значение 10
AnotherMethod(integerVariable); // из переменной integerVariable выдергивается значение 10
...
void AnotherMethod(int xz) { // ...и засовывается в переменную с именем xz
  ...
}


Или вот еще пример:
Код

// прекрасно работает:
Color choosedColor = showDialog(this, "Choose your color",  firstDefautColor);
// работает ничуть не хуже:
Color anyOtherName = showDialog(this, "Choose your color",  firstDefautColor);

А ведь внутри метода showDialog тоже есть строчка
return ...;
И мы даже не знаем, какое там имя используется. Нам и не нужно этого знать. Достаточно того что мы знаем какого типа значение возвращает метод - так мы можем создать подходящую переменную чтобы в нее положить значение:
Код

// showDialog() возвращает Color
Color anyNameYouLike;
anyNameYouLike = chooseColor(тут типа параметры);



Вобщем смысл всего этого:
1. Когда пишете какой-нибудь метод, позаботьтесь о том чтобы он делал то, что от него требуется. Определите, какая информация ему потребуется для работы - это и будут входные параметры. Как вы их назовете не важно, главное чтобы вы сами не путались в них.
2. Когда вызываете метод, передавайте значения, которые требуются ему для работы. Не важно как называются переменные, в которых эти значения лежат.
3. Если вы хотите чтобы метод возвращал вам что-то, нужна переменная соответствующего типа. С любым именем.
4. Перепишите метод ChangeColor(). Переименуйте параметр конструктора класса Игрок из firstDefautColor в color; конструктор будет работать и так, но у препода могут возникнуть вопросы.
--------------------
C/C++ GameDevRSS Раздела программирования игрOpenGL - уроки от NeHeКак продать идею?
PM MAIL   Вверх
Qawra
Дата 9.1.2009, 18:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Спасибо за такой подробный перевод с Java на русский .
 В рамках нашего курса , программированию посвящено  только два часа в неделю поэтому многие вещи просто  не досказаны. Например, нам говорили то что компайлер различает конструкторы только по типу аргументов , но примеры всегда были с одинаковыми названиями этих самых аргументов в конструкторе  и  как членов класса ... 
Теперь у меня получилось  так : 
Код

 public Color ChangeColor(  Color firstDefautColor) 
  {
     Color choosedColor = JColorChooser.showDialog(this, "Choose your color",  firstDefautColor);
    if(choosedColor!=null)
    {    return  choosedColor;
    }return  firstDefautColor;
  }
  и 
Код

 private Color color;
  
  public Player(Color color ) // constructor 
  {    
      this.color = color;   
    }
 

Для того что бы начать рисовать точки нам нужно их предварительно создать и сохранить ещё до начала игры.  Это правда что хранить их лучше в Vector  а не в Array ? О векторах мы знаем только то что это dynamic array (мы проходили это в топике data structures). Теоретически ,  если  точки это обьекты то когда они созданы память под них уже выделена . Количество их во время игры тоже не измениться ... Какой выигрыш от использования векторов ? Мы ещё ни разу не обращались к ним на программировании . 


PM MAIL   Вверх
Rpahut
Дата 9.1.2009, 21:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


0xdeadbeef
*


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

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



Цитата

Какой выигрыш от использования векторов ?

Можно написать с использованием векторов, но реальной причины для этого я не вижу. Вектора понадобятся нам позже, а точки поля мы будем хранить в двумерном массиве.
Массив этот должен быть членом класса Поле (или GridCanvas? или полем у вас будет другой класс?). Пара слов об инициализации массива:
если массив мы определим так
Код

private int rows;
private int cols;
private DrawablePoint points[rows][cols]; // <------
...

то у нас ничего не получится, потому что, во-первых, эта строчка выполнится до конструктора класса Поле, а значит в переменных rows и cols будут еще лежать нули(получится points[0][0], массив нулевого размера). Во-вторых, никаких Точек эта строчка не создает, независимо от размеров, а создает она массив. Мы определили массив, мы его и получили, и ничего больше.

Поэтому мы напишем так:
Код

private DrawablePoint points[][]; // размер пока неизвестен; просто двумерный массив

и в конструкторе класса Поле:
Код

...
points = new DrawablePoint[rows][cols]; // сейчас размер известен и массиву можно придать размер
for(int y=0; y<cols; y++) {
  for(int x=0; x<rows; x++) {
    // цикл по всем элементам массива
    points[x][y] = new DrawablePoint(типа параметры); /* <--- Вот тут
    собственно и создаются Точки. Запихиваем их по одной в
    каждый элемент массива.
    */
  }
}


Вот так мы создаем массив точек. Этот кусок кстати разумно выложить из конструктора в отдельный метод, потому что каждый раз начиная новую игру мы будем (пере)создавать массив.
===================================================

Когда точки созданы, можно попробовать их отрисовать. Так как DrawablePoint у нас extends Component, то по идее можно добавлять точки к GridsCanvas(метод add()) и они будут автоматически перерисовываться при перерисовке самого поля(т.е. автоматически будет вызываться метод paint() точек). Вот этого я делать не пробовал, вобще это больше по яве - а значит не совсем ко мне. У меня метод paint после нескольких попыток стал вызываться, но точек все равно не видно  smile 
--------------------
C/C++ GameDevRSS Раздела программирования игрOpenGL - уроки от NeHeКак продать идею?
PM MAIL   Вверх
Rpahut
Дата 9.1.2009, 23:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


0xdeadbeef
*


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

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



Ладно.
Раз уж мы используем SWING для GUI, давайте обойдемся без класса Component (он из AWT). Поле наше будет extends JPanel, точка вообще ничего не extends.
У поля должен быть метод void paintComponent(Graphics g); в нем нужно разместить код рисования сетки + в цикле для каждой Точки из массива вызывать метод paint(g). Разумеется в классе Точка нужно написать метод paint(Graphics g).
Дальше возможны два варианта - 
1. Если в классе Точка хранятся ее координаты, в методе Точка.paint() можно просто рисовать овал на этих координатах.
2. Если в классе Точка нет координат - тогда использовать метод translate() как я писал раньше.
--------------------
C/C++ GameDevRSS Раздела программирования игрOpenGL - уроки от NeHeКак продать идею?
PM MAIL   Вверх
Qawra
Дата 9.1.2009, 23:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Работать с полем я хотела в отдельном классе потому что иначе я запутаюсь smile
Назовём его BattleField .
Код

 public int rows;
  public int cols;
  были уже инициализированы в GridCanvas
Код

import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

class GridsCanvas extends Canvas {

   public  int rows;
    public int cols;

    GridsCanvas(int r, int c) {
        rows = r;
        cols = c;
    }

    public void paint(Graphics g) {
        int i;
        int width = getSize().width;
        int height = getSize().height;
        // draw the rows
        int rowHt = height / (rows);
        for (i = 0; i < rows; i++)
            g.drawLine(0, i * rowHt, width, i * rowHt);
        // draw the columns
        int rowWid = width / (cols);
        for (i = 0; i < cols; i++)
            g.drawLine(i * rowWid, 0, i * rowWid, height);
    }
}
 и использовались в Grids
Код

import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;


public class Grids extends Frame {

    Grids(String title, int w, int h, int rows, int cols) // constractor
    {
        setTitle(title);
        // Now create a Canvas and add it to the Frame.
        GridsCanvas canvas = new GridsCanvas(rows, cols);
        canvas.setSize(w, h);

        add(canvas);
        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                int exitCode = JOptionPane.showConfirmDialog(Grids.this, "Exit " + getTitle() + "?", "Confirm exit", JOptionPane.YES_NO_OPTION);
                if (exitCode == JOptionPane.OK_OPTION) {
                    System.exit(0);
                }
            }
        });
        pack();

        //Set this windown in the center
        setLocationRelativeTo(null);

        // Set it not resizable
        setResizable(false);
    }    
}
 Поэтому я надеюсь  мы можем их просто использовать в новом классе 

Код

public class BattleField
 {   private DrawablePoint points[][];

      public BattleField ( int rows , int cols ) // конструктор 
    {
       makePoints(rows,cols);  // вызываем метод
     }

     public void makePoints (int rows , int cols)
  {  points = new DrawablePoint[rows][cols];
      for(int y=0; y<cols; y++)
          {for(int x=0; x<rows; x++) 
             {
               points[x][y] = new DrawablePoint(int x, int y);
              }
           }
        }
    }
 Я правильно поняла что параметрами для заранее созданной точки могут быть только координаты ? У неё ведь ещё  нет владельца . Да и рисовать её нам пока не надо . Я краем уха в лаборатории  слышала smile 
что когда рисуется решётка и точки  - результат зависит от  порядка  действий . Решётка может  зарисовывать точки . А что ещё  мы будем делать в конструкторе поля ?

Добавлено @ 23:39
класс Точка в наброске пока выглядит так 
Код

import javax.swing.*;
import java.awt.*;
import java.awt.geom.Point2D;

public class DrawablePoint
 {  
    public Color color ;
    public int radius =6;
    
    DrawablePoint(Color color) 
    {
        this.color = color ;
    }

    private void   drawCircle(int x, int y, int radius, Graphics g)
    {
    g.drawOval(x - radius, y - radius, radius*2, radius*2);
   } 
 
пришлось снова прописать public Color color ;  потому что со словом this. иначе не компелируется

Это сообщение отредактировал(а) Qawra - 9.1.2009, 23:45
PM MAIL   Вверх
Rpahut
Дата 10.1.2009, 22:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


0xdeadbeef
*


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

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



Переделайте
1:
Код

class GridsCanvas extends Canvas { // в SWING нет класса Canvas
// поменять на 
class GridsCanvas extends JPanel { // зато есть JPanel; на ней можно рисовать


2:
Код

public class Grids extends Frame { // в SWING нет класса Frame
.....
public class Grids extends JFrame { // но есть JFrame


3:
Код

public void paint(Graphics g) { // это в классе GridsCanvas
....
public void paintComponent(Graphics g) { // в SWING нужно переопределять этот метод


Имеет смысл все-таки объединить классы GridsCanvas и BattleField. Два класса там во всяком случае не нужны.
Чтобы вы не путались, попробую обрисовать как это все должно выглядеть:
GridsCanvas(или BattleField) будет создавать, хранить точки и рисовать их на экран
Grids будет окном игры; окно нужно чтобы GridsCanvas можно было отобразить на экране

В классе Grids в качестве члена класса вписываем GridsCanvas. В конструкторе Grids, когда известны размеры поля, создаем(инициализируем, передаем размеры) GridsCanvas.
В классе GridsCanvas в члены класса вписываем массив points[][], в конструкторе инициализируем этот массив, точно так, как это сейчас сделано в BattleField.
Теперь чтобы создать поле в окне со всеми точками достаточно создать Grids с правильными параметрами; когда создается Grids, будет создан и GridsCanvas, а он в свою очередь создаст точки.
Касательно параметров конструктора Grids:
Код

Grids(String title, int w, int h, int rows, int cols)

title - не нужен; заголовок каждый раз будет тот же(или нет?), можно вписать в конструктор:
Код

setTitle("Фараонище");

w, h - не нужны; размер окна должен вычисляться в зависимости от размера поля
rows, cols - это все что нам нужно

=======================
Когда Ява решит отобразить окно, она вызовет метод GridsCanvas.paintComponent(); этот метод должен рисовать игровое поле. Пока он рисует только сетку, но должен еще и рисовать все точки на поле. Чтобы точки могли рисоваться, во-первых у них должен быть метод paint(Graphics g), во-вторых этот метод должен рисовать точку(при помощи drawOval() скорее всего), и наконец нужно чтобы при рисовании поля вызывался этот метод у каждой точки. Т.е. в GridsCanvas.paintComponent() нужно добавить цикл, в котором для каждой точки вызывается paint(g).

Цитата

Я правильно поняла что параметрами для заранее созданной точки могут быть только координаты ?

Да. Но если уж вы передаете координаты "points[x][y] = new DrawablePoint(x, y);", то конструктор точки должен принимать координаты - "DrawablePoint(int xcoord, int ycoord)" - и сохранять их внутри класса.

Кстати, мы работать теперь будем с двумя разными координатными системами - у нас есть координаты точки на поле, и координаты точки на экране. Координаты на поле [3][2] означают точку в третьем столбце и второй строчке. Координаты на экране будут другими, потому что нам нужно расстояние между точками. Расстояние между точками это размер клетки, cellSize; тогда экранные координаты точки:
xscreen = xfield * cellSize;
yscreen = yfield * cellSize;

Можно в GridsCanvas добавить private-метод для перевода координат на поле в экранные:
Код

private int field2screen(int value) {
  return value*cellSize; /* int cellSize должен быть членом класса
  и в нем должен лежать размер клетки */
}

Использовать его можно например так:
Код

// создаем точку и передаем ей экранные координаты
points[x][y] = new DrawablePoint(field2screen(x), field2screen(y));


============================
Тока сейчас заметил - у вас опять написаны параметры вместе с типом!
Код

... = new DrawablePoint(int x, int y);

============================
По возможности вносите изменения небольшими кусками и компилируйте код - Ява покажет где у вас ошибки.
В помощь - поправленный класс Grids:
Код

import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

public class Grids extends JFrame {
    GridsCanvas canvas; // canvas теперь член класса

    Grids(int rows, int cols) // constructor
    {

        canvas = new GridsCanvas(rows, cols, 20); /* !! передаем дополнительно cellSize
        Размер можно менять по вкусу */

        // канвас должен сам set свой size:
        // canvas.setSize(rows*cellSize , cols*cellSize);
        add(canvas);

        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                int exitCode = JOptionPane.showConfirmDialog(Grids.this, "Exit " + getTitle() + "?", "Confirm exit", JOptionPane.YES_NO_OPTION);
                if (exitCode == JOptionPane.OK_OPTION) {
                    System.exit(0);
                }
            }
        });

        pack();
        setTitle("Фараонище");
        setLocationRelativeTo(null);
        setResizable(false);
        // без этого окна не будет:
        setVisible(true);
    }    
}


Это сообщение отредактировал(а) Rpahut - 10.1.2009, 22:46
--------------------
C/C++ GameDevRSS Раздела программирования игрOpenGL - уроки от NeHeКак продать идею?
PM MAIL   Вверх
Qawra
Дата 11.1.2009, 00:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Когда я поменяла в class GridsCanvas extends Canvas на extends  JPanel решётка перестала выходить нормально. Появляется  окошко очень узкое и нерастягивающееся. Так что Canvas я пока оставила .Природа его не известна но на решётку он действует положительно .
Пытаюсь изменить свой класс Grid но пока от этого становиться только хуже. Окошко выходит но решётки на нём нет .
w, h  я пока хочу оставить потому окошко будет иметь постоянные размеры. У нас в школе разрешение мониторов  компьютером 800/600 и  я не  буду вводить функцию изменения размеров поля . Оно и так занимает весь экран .
Параметры у меня действительно написаны вместе с типом потому что иначе не комперировалось 
Код

import javax.swing.*;
import java.awt.*;
import java.awt.geom.Point2D;

class DrawablePoint //extends Component
{

    private Color color;
    public  int radius = 6;
    public int x;
    public int y;
    
    DrawablePoint(Color color) 
    {
        this.color = color ;
    }

    private void   drawCircle (  x,   y,  radius, Graphics g)
    {
    g.drawOval(x - radius, y - radius, radius*2, radius*2);
   }   
}

в строчке private void   drawCircle (  x,   y,  radius, Graphics g) компайлер требует идентифаер ..
PM MAIL   Вверх
Rpahut
Дата 11.1.2009, 19:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


0xdeadbeef
*


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

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



Цитата

Появляется  окошко очень узкое и нерастягивающееся.

Ну нерастягивающееся оно потому что в коде так написано.
А что касается размера, то когда вы в Grids вызываете pack(), Ява спрашивает у GridsCanvas через метод getPreferredSize(), какой бы ей хотелось иметь размер. Чтобы Ява знала, какой нам нужен размер, сначала надо вызвать setPreferredSize() с указанным размером.
Так же нужно вызвать setVisible(true) в конструкторе GridsCanvas, потому как по умолчанию элементы спрятаны и отображаться не будут.

Цитата

Пытаюсь изменить свой класс Grid но пока от этого становиться только хуже. 

Пока GridsCanvas не будет правильно оформлен, окно будет пустым или очень маленьким, это нормально; главное чтобы оно отображалось на экране и нормально закрывалось при нажатии [Х]. Это будет озачать что Grids работает.

Цитата

w, h  я пока хочу оставить потому окошко будет иметь постоянные размеры.

Если размер постоянный, то передавать его через параметры совсем уж не нужно. Можно просто вписать его в класс. То же самое касается количества точек - если настройки не будет, все можно вписывать внутрь класса Grids. 

Цитата

Параметры у меня действительно написаны вместе с типом потому что иначе не комперировалось 

Вот такое у меня хоть убейте не компилируется:
Код

    private void   drawCircle (  x,   y,  radius, Graphics g)
    {
     ...
    }

В заголовке метода типы должны указываться. Без них никак. Я уже писал о том что типы нужны компилятору.
Я имел ввиду кусок, в котором инициализируется массив точек:
Код

points[x][y] = new DrawablePoint(int x, int y); // ы?..

Разве BlueJ не ругается на эту строчку?
======================================

ОК, давайте по порядку.
Класс Grids
Можно скопировать код который я выкладывал. Если конструктор Grids не принимает параметров-размеров, скобки у него оставляем пустыми, но добавляем в него переменные:
Код

class Grids extends JFrame {
    GridsCanvas canvas;

public Grids() // constructor
    {
        int rows = 35; // желаемый размер поля
        int cols = 35;
        int cellSize = 15; // желаемый размер клетки
....

Тут у нас гадкая неопределенность - мы можем либо задать размер окна, размер клетки и вычислить сколько точек поместится в окне; либо мы можем задать опять размер окна, желаемое количество клеток, и из них посчитать размер клетки. Второй вариант мне не нравится, потому как размер клетки все-таки важнее количества точек, от него зависит насколько удобно будет тыкать в точки и как они будут выглядеть. Поэтому я прикинул и вписал клетку размером 15 пикселей и поле размером 35х35 клеток, потом если что эти цифры можно будет поменять.
Что еще нужно обязательно сделать в конструкторе - это создать GridsCanvas, передать ему размеры поля и клетки, добавить его...; все это есть в коде. 


Класс GridsCanvas
Обязательно extends JPanel, иначе работать не будет.
int rows, cols и cellSize делаем членами класса, мы будем часто пользоваться ими. В конструкторе помещаем в эти переменные конкретные значения, которые конструктор принимает как параметры.
Обязательно вызываем в конструкторе setVisible(true) и setPreferredSize(new Dimension(panelWidth, panelHeight)), иначе панель либо не будет отображаться совсем, либо будет слишком маленькой. Вместо panelWidth и panelHeight естественно нужно указать размер панели достаточный чтобы вместить все точки:
panelWidth = cols*cellSize;
panelHeight = rows*cellSize;

Еще один метод, необходимый в GridsCanvas - это
Код

void paintComponent(Graphics g) {
  // здесь рисование сетки и прочего
  // пока можно просто рисование сетки, прочее добавим позже
  ...
}


Класс DrawablePoint
Цитата

в строчке private void   drawCircle (  x,   y,  radius, Graphics g) компайлер требует идентифаер ..

Код

// вот так
private void drawCircle (int x, int y, int radius, Graphics g)


Еще нужно добавить метод
Код

public void paint(Graphics g, int x, int y) {
  int pointRadius = 3;
  drawCircle(x, y, pointRadius, g);
  // сейчас мы его не используем, но позже будем
}

Когда все это заработает, в метод GridsCanvas.paintComponent() можно будет добавить цикл, перебирающий все точки и вызывающий для каждой ее метод paint() - так наши точки будут рисоваться на экран.
--------------------
C/C++ GameDevRSS Раздела программирования игрOpenGL - уроки от NeHeКак продать идею?
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Программирование игр, графики и искуственного интеллекта"
Rickert

НА ЗЛОБУ ДНЯ: Дорогие посетители, прошу обратить внимание что новые темы касающиеся новых вопросов создаются кнопкой "Новая тема" а не "Ответить"! Любые оффтопиковые вопросы, заданные в текущих тематических темах будут удалены а их авторы, при рецедиве, забанены.

  • Литературу, связанную с программированием графики, обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы связанные с программированием графики и мультимедии на языках С++ и Delphi
  • Вопросы по реализации алгоритмов рассматриваются здесь

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

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


 




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


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

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