Рисование на Canvas и обновление объектов [2]

Ответить
Аватара пользователя
kondra007
Сообщения: 91
Зарегистрирован: 23 янв 2013, 14:49

Рисование на Canvas и обновление объектов [2]

Сообщение kondra007 » 09 июн 2013, 21:02

Этот вопрос будет более полным, нежели предыдущим, чтобы лучше понять проблему.
Я пытаюсь сделать что-то типа "Морского боя" для одного игрока.
Генерируются корабли, затем юзер тычет в экран, а на экране видно, попал или нет. Собственно, всё.
Проблема заключается в графической реализации этой модели.

Есть изначально поле: Изображение
Его код:
[syntax=java]public void onDraw(Canvas canvas) {

if (getWidth() > getHeight()) {
rebro = getHeight();
} else {
rebro = getWidth(); // ребро - по наименьшей стороне
}
rebro_piece = rebro / 10; // делаем сетку 10х10 "клеток"

Paint background = new Paint();
background.setColor(getResources().getColor(R.color.game_background));
canvas.drawRect(0, 0, rebro, rebro, background); // рисуем фон

Paint divider = new Paint();
divider.setColor(getResources().getColor(R.color.divider_black));

// разделительные линии
for (int i=0; i<11; i++) {
canvas.drawLine(0, i*rebro_piece, rebro, i*rebro_piece, divider); // горизонтальные
canvas.drawLine(i*rebro_piece, 0, i*rebro_piece, rebro, divider); // вертикальные
}

canvas.drawLine(rebro-1, 0, rebro-1, rebro, divider); // последняя линяя на 1 пиксель левее, чтобы попасть в экран
}
[/syntax]

В другом классе путем некоторых вычислений я получаю 2 числа - это координаты, которые нажал юзер и которые надо изобразить на поле. Эти значения Х и У.
Для этого я написал метод drawShip(int x, int y)
Руководствуясь одним из вопросов со StackOverflow http://stackoverflow.com/questions/1206 ... ent-doesnt
я написал этот метод так:
[syntax=java]public void drawShip(int x, int y) {
myX = x; // переменная класса
myY = y; // переменная класса
needToPaintShip = true; //boolean
invalidate(); // это обновит экран?
needToPaintShip = false;
}[/syntax]

Здесь needToPaintShip - это булево значение, показывающее, есть ли координаты, чтобы их отобразить на экране.

После этого я обновил метод onDraw(Canvas canvas), дописав следующее:
[syntax=java]if(needToPaintShip == true) {
Paint ship = new Paint();
ship.setColor(getResources().getColor(R.color.ship_color));
Log.d(TAG, "onDraw(): rebro_piece = " + rebro_piece + " , myX = "+ myX + " , myY = " + myY); // здесь выводятся только последние координаты!
Rect r = new Rect(myX*(rebro_piece),myY*rebro_piece, myX*(rebro_piece+1), myY*(rebro_piece+1));
canvas.drawRect(r, ship);
}[/syntax]

Но результат...в общем, взгляните сами.
Изображение

Товарищи, я в отчаянии. Почему не работает - не понимаю.

xr0m
Сообщения: 131
Зарегистрирован: 06 апр 2013, 14:01

Re: Рисование на Canvas и обновление объектов [2]

Сообщение xr0m » 09 июн 2013, 22:15

Желтый квадрат разве не оно?

Аватара пользователя
kondra007
Сообщения: 91
Зарегистрирован: 23 янв 2013, 14:49

Re: Рисование на Canvas и обновление объектов [2]

Сообщение kondra007 » 09 июн 2013, 22:18

В результате должен быть изображен один четырехпалубник и один трехпалубник (по клеткам).
Странные разметры у этого квадрата, ведь rebro_piece = 48 пикселей в данном случае, как раз по ширине клетки.
А это изображение вообще нереально мелкое и всего одно.

xr0m
Сообщения: 131
Зарегистрирован: 06 апр 2013, 14:01

Re: Рисование на Canvas и обновление объектов [2]

Сообщение xr0m » 09 июн 2013, 22:21

Потому что ты так отрисовываешь (rebro_piece+1), ты добавляешь 1 пиксель.

Аватара пользователя
kondra007
Сообщения: 91
Зарегистрирован: 23 янв 2013, 14:49

Re: Рисование на Canvas и обновление объектов [2]

Сообщение kondra007 » 09 июн 2013, 22:23

xr0m,
спасибо огромное! Да, тут была проблема.

Но есть гораздо бОльшая неприятность. Отображается только одна клетка...а где остальные 6 ?

xr0m
Сообщения: 131
Зарегистрирован: 06 апр 2013, 14:01

Re: Рисование на Canvas и обновление объектов [2]

Сообщение xr0m » 09 июн 2013, 22:25

Не вижу в коде цикл, который должен дорисовать несколько квадратов. один вызов = один квадрат.

Аватара пользователя
kondra007
Сообщения: 91
Зарегистрирован: 23 янв 2013, 14:49

Re: Рисование на Canvas и обновление объектов [2]

Сообщение kondra007 » 09 июн 2013, 22:28

Метод drawShip() вызывается много раз (это видно по LogCat)
И каждый раз drawShip вызывает onDraw() - или я неправ?

И если это так, то...получается, что onDraw() каждый раз сам себя перерисовывает, оставляя только последний квадрат??

xr0m
Сообщения: 131
Зарегистрирован: 06 апр 2013, 14:01

Re: Рисование на Canvas и обновление объектов [2]

Сообщение xr0m » 09 июн 2013, 22:31

ну конечно, ты должен прорисовывать всю картину за один вызов.

Аватара пользователя
kondra007
Сообщения: 91
Зарегистрирован: 23 янв 2013, 14:49

Re: Рисование на Canvas и обновление объектов [2]

Сообщение kondra007 » 09 июн 2013, 22:34

Тогда подскажите, пожалуйста, как сохранять все квадраты? Не дорисовывать же каждый раз новое состояние в битмапу?

xr0m
Сообщения: 131
Зарегистрирован: 06 апр 2013, 14:01

Re: Рисование на Canvas и обновление объектов [2]

Сообщение xr0m » 09 июн 2013, 22:43

Каждый вызов onDraw() рисуется с чистого холста. Создай поле как массив квадратов(а лучше объектов) и сохраняй там состояние квадрата (пустой, мимо, корабль, подбитый корабль). Во время прорисовки канваса, пробегаешься по массиву циклом и рисуешь все объекты.

Аватара пользователя
kondra007
Сообщения: 91
Зарегистрирован: 23 янв 2013, 14:49

Re: Рисование на Canvas и обновление объектов [2]

Сообщение kondra007 » 09 июн 2013, 22:44

У меня так и сделано почти:
[syntax=java]public static void place_fourth(){
int ship_rand = 0;
int x_rand = 0;
int y_rand = 0;
int rand = (Math.random()<0.5)?0:1;
Log.d(TAG, "Направление = " + rand);
switch(rand){
case DIRECTION_RIGHT:
x_rand = (int) (0 + (Math.random() * (6 - 0) + 1));
y_rand = (int) (0 + (Math.random() * (9 - 0) +1));
for (int i=0; i<4; i++) {
field[x_rand + i][y_rand] = IS_SHIP;
Log.d(TAG, "Координаты четырёхпалубника: [" + (x_rand + i + 1) + "] [" + (y_rand + 1) + "];" );
}
break;

case DIRECTION_DOWN:
x_rand = (int) (0 + (Math.random() * (9 - 0) + 1));
y_rand = (int) (0 + (Math.random() * (6 - 0) +1));
for (int i=0; i<4; i++) {
field[x_rand][y_rand + i] = IS_SHIP;
Log.d(TAG, "Координаты четырёхпалубника: [" + (x_rand+1) + "] [" + (y_rand + 1 + i) + "];" );
}
break;
}[/syntax]

Я так понимаю, надо передавать не координаты в drawShip, а целый массив?

xr0m
Сообщения: 131
Зарегистрирован: 06 апр 2013, 14:01

Re: Рисование на Canvas и обновление объектов [2]

Сообщение xr0m » 09 июн 2013, 22:50

Если ты хочешь в новом обновлении канваса прорисовать все старые события, то тебе их надо куда-то сохранять. Как вариант - массив(линклист).

Эта функция рисует один корабль, а не поле.

Аватара пользователя
kondra007
Сообщения: 91
Зарегистрирован: 23 янв 2013, 14:49

Re: Рисование на Canvas и обновление объектов [2]

Сообщение kondra007 » 09 июн 2013, 22:52

Не-не, я показал просто, как я сохраняю состояния.
Потом мне передавать этот field[][] в drawShip?

xr0m
Сообщения: 131
Зарегистрирован: 06 апр 2013, 14:01

Re: Рисование на Canvas и обновление объектов [2]

Сообщение xr0m » 09 июн 2013, 22:56

Да... туда где ты рисуешь.

Ответить