![]() |
![]() ![]() |
![]() |
Shpion |
![]()
Сообщение
#1
|
Группа: Пользователи Сообщений: 5 Пол: Мужской Реальное имя: Александр Репутация: ![]() ![]() ![]() |
Вот, попросили сделать задачу на Паскале..
Я взялся, даже не посмотрев... Оказалось, там требуется знание графических приемов программирования в Паскале... А я тогда вообще ничего не шарил... Ладно, большинство задач сделал, осталась одна - последняя: Нарисовать на Паскале град, падающий и отскакивающий от объекта. Так как я за такие вещи раньше никогда не брался, то с непревычки оказалось трудно... Дальше последует код, а пока 2 вопроса: 1)Как сделать так, чтобы при достижении градинок определенной границы, эти градинки продолжали движение, и создавались новые(т.е как бы создавался непрерывный поток) 2) Как "уловить" кривую" линию объекта(крыши дома, например) Вот код(c пояснениями) моей так называемой программы. Это далеко не законченный вариант, ибо у меня уже опускаются руки(может, ночь просто?): Код program rain; uses graph,crt; type grad = object {создается тип "град"} x,y:integer; radius:word; dx,dy:shortint; constructor initgrad(x0,y0:integer; radius0: word; dx0,dy0: shortint); {Конструктор - создатель града } procedure show; procedure hide; procedure move; procedure checkborder; end; var gd,gm,i,x,Radius,dx,y,dy:integer; grads:array[1..50] of grad; {Массив градин} procedure creategrad(k,x,y:integer); { k - если=0, то создается "кучка" градин, если k<>0(=i), то создается одна градина с текущими кординатами } begin if k=0 then for i:=1 to 10 do begin Radius:=3; dy:=1; y:=random(100); grads[i].initgrad(random(Getmaxx),y,radius,0,dy); end else grads[k].initgrad(random(getmaxx),y,radius,0,dy); end; procedure grad.move; begin x:=x+dx; y:=y+dy; end; procedure grad.show; begin SetFillStyle(1,8); FillEllipse(x,y,radius,radius); end; procedure grad.hide; begin setcolor(black); FillEllipse(x,y,radius,radius); end; procedure grad.checkborder; {Это я на CheckBorder'е и запарился!!!!!!} begin if y=250 then creategrad(i,x,random(10)); end; constructor grad.initgrad(x0,y0:integer; radius0: word; dx0,dy0: shortint); begin x:=x0; y:=y0; Radius:=Radius0; dx:=dx0; dy:=dy0; end; begin initgraph(gd,gm,''); if graphresult<> grOk then begin writeln('No graphics'); readln; halt; end; creategrad(0,x,y); repeat cleardevice; for i:=1 to 10 do begin randomize; grads[i].show; end; delay(500); for i:=1 to 10 do grads[i].hide; for i:=1 to 10 do begin grads[i].move; grads[i].checkborder; end; until keypressed; readln; closegraph; end. Вообщем, помогите, кто чем может - исходниками, советами.... Выручайте... ![]() ЗЫ: Может, удобней будет посмотреть мою ошибку - выложил этот исходник... Сообщение отредактировано: Shpion - 22.05.2006 1:15 Прикрепленные файлы ![]() |
AlienEmperor |
![]()
Сообщение
#2
|
![]() Бывалый ![]() ![]() ![]() Группа: Пользователи Сообщений: 160 Пол: Мужской Реальное имя: Серый Репутация: ![]() ![]() ![]() |
Единственное, что могу - дать совет: проверяй цвет точки, в которой "градина" должна оказаться в с следующий момент. Если бы "градины" были единичного размера, было бы еще проще. Короче алгоритм такой - "градина" двигается (к примеру) по сложной траектории с учетом притяжения и, скажем, ветра. Поверхность на которую она падает - произвольная: тогда бери функцию расчета траектории и смотри куда попадет точка перед отрисовкой (т.е. проверь цвет точки, прежде чем рисовать туда "градину"). Если цвет фона (т.е. ничего нет) - тогда перемещай; если нет - изменяй траекторию (т.е., к примеру, запрещай движение по одной из осей). Насколько я понял, в твоей проге фон одноцветный, а не битмап, так что можно это использовать.
P.S. Кстати, на твоем месте я бы сделал создание новой градины по завершению движения. Т.е.: если какая-то градина остановилась, то создаем еще одну. (А создавать штук по 10). Правда, это потребует более продвинутой "физики" - надо будет учитывать возможность потери "энергии", т.е. замедления и остановки. Сообщение отредактировано: AlienEmperor - 22.05.2006 9:03 -------------------- Все в жизни ботва... Кроме пчел!
|
Archon |
![]()
Сообщение
#3
|
![]() Профи ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 618 Пол: Мужской Репутация: ![]() ![]() ![]() |
В самом начале создавай столько градин, сколько нужно. При достижении градиной границ экрана инициализируй её параметры заново (y := 0; x := random(getmaxx); и тд, короче, повторный вызов конструктора). Тут правда если с отскакиванием, может получиться, что градина будет вечно прыгать и за границы экрана не упадёт, но можно ввести для каждой градины "время жизни" и перед прорисовкой вычитать из него 1. Когда оно заканчивается делаем тоже что и при выходе за границу.
На градины по вертикали действует сила тяжести, по горизонтали - ветер. Так что движение надо делать с ускорением. Например так: procedure grad.move; При этом dx, dy, ddx, ddy : real. И пусть ddx и ddy немного отличаются у разных градинок. Это чтобы падали они с разной скоростью и углы падения немного отличались. Лучше будет смотреться. Для отскакивания следует определиться, как задавать объекты (вроде крыши). Вариант с GetPixel мне не нравится тк сложно направление отскока определить. Shpion, а тебе обязательно нужно отскакивание от кривых поверхностей, может просто наклонных? Для отскакивания от плоской горизонтальной крыши сделать можно так:
где yroof - уровень крыши, а k < 1 - коэфициент "потерь", для того чтобы градины до потолка не отскакивали ![]() Да и градины лучше точечные - проще будет. -------------------- Close the World...txeN eht nepO
|
Shpion |
![]()
Сообщение
#4
|
Группа: Пользователи Сообщений: 5 Пол: Мужской Реальное имя: Александр Репутация: ![]() ![]() ![]() |
ВСЕМ СПАСИБО!
![]() 2 Archon: Это задачка для 1-го курса Пед-института, так, что, я думаю, заморачиваться особо не нужно... Отскок, естественно не от кривых, а от наклонных/прямых поверхностей(домика, например)... Еще раз thnx ![]() |
Shpion |
![]() ![]()
Сообщение
#5
|
Группа: Пользователи Сообщений: 5 Пол: Мужской Реальное имя: Александр Репутация: ![]() ![]() ![]() |
Опять возникли проблемы:
Код program rain; uses graph,crt; type grad = object x,y:integer; radius:word; dx,dy,ddx,ddy:real; constructor initgrad(x0,y0:integer; radius0: word; dx0,dy0,ddx0,ddy0: real); procedure show; procedure hide; procedure move; procedure checkborder; end; const maxgrads=30; var gd,gm,i,x,y,Radius:integer; dx,dy,ddx0,ddy0:real; grads:array[1..50] of grad; procedure dom; begin Setcolor($eeee); Rectangle(getmaxx-400,getmaxy,getmaxx-200,getmaxy-100); line(getmaxX-400,getmaxy-100,getmaxx-300,getmaxy-200); line(getmaxx-300,getmaxy-200,getmaxx-200,getmaxy-100); end; procedure creategrad(k,x,y:integer); begin dx:=random(6)/3; if k=0 then for i:=1 to maxGrads do begin Radius:=3; dy:=1; dx:=random(2); y:=random(GetMaxY); grads[i].initgrad(random(getmaxx),random(getmaxy),radius,dx,dy,0,0); end else grads[k].initgrad(x,y,radius,dx,1,0,0); end; procedure grad.move; begin dx:=dx+ddx; dy:=dy+ddy; x:=round(x+dx); y:=round(y+dy); end; procedure grad.show; begin setfillstyle(1,9); FillEllipse(x,y,radius,radius); end; procedure grad.hide; begin setcolor(black); FillEllipse(x,y,radius,radius); end; procedure grad.checkborder; begin if y=GetMaxY then creategrad(i,Random(GetMaxX),0) else if (getpixel(x,y)=$eeee) then begin dy:=-dy*0.6; dx:=dx*0.6; end; end; constructor grad.initgrad(x0,y0:integer; radius0: word; dx0,dy0,ddx0,ddy0: real); ... begin ... creategrad(0,x,y); repeat cleardevice; dom; setcolor(black); for i:=1 to maxgrads do begin grads[i].show; end; delay(60); for i:=1 to maxgrads do begin grads[i].hide; end; for i:=1 to maxgrads do begin grads[i].checkborder; grads[i].move; end; until keypressed; closegraph; end. 1)При повышении скорости dy больше 1, градины начинают постепенно пропадать 2)Так и не смог разобраться с: 2.1)Как "уловить" наклонную поверхность? Я пытался создавать массив точек.. ну, короче, делал чепуху.. ![]() 2.2)С GetPixel не получается... Цвета не сравнивает 2.3)Если установить на градину таймер, то она будет просто исчезать? 2.4) Отскакивает резко вверх, вообщем некрасиво... Выкладываю исходник: 2.2) Прикрепленные файлы ![]() |
Archon |
![]()
Сообщение
#6
|
![]() Профи ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 618 Пол: Мужской Репутация: ![]() ![]() ![]() |
Рассмотрим этот участок кода:
procedure grad.checkborder; 1) надо писать ... if y >= GetMaxY then ... (больше или равно) 2.1) Позже напишу, а для начала сделай отскакивание от плоской горизонтальной крыши шириной во весь экран 2.2) GetPixel в этой задаче не очень рулит. Сделай проверку по координатам. Для горизонтальной крыши я уже писал. 2.3) Цитата Когда оно заканчивается делаем тоже что и при выходе за границу. То есть добавь в сравнение с GetMaxY проверку на истекание жизненного срока:if (y>=GetMaxY) or (life_time <= 0) then creategrad(i,Random(GetMaxX),0) 2.4) У тебя коэффициенты слишком большие (0.6) поставь 0.1 или даже 0.05. Я твой код поподробней потом посмотрю и тогда скажу больше. Сообщение отредактировано: volvo - 3.11.2006 17:14 -------------------- Close the World...txeN eht nepO
|
![]() ![]() |
![]() |
Текстовая версия | 27.07.2025 5:50 |