Воскресенье, 11 Апреля 2021, 18:03

Приветствую Вас Гость

[ Новые сообщения · Игроделы · Правила · Поиск ]
Форум игроделов » Программирование » Delphi/Pascal/Object Pascal » Delphi:Вопрос-Ответ (Спросил - получил ответ)
Delphi:Вопрос-Ответ
TimKruzДата: Четверг, 27 Декабря 2012, 20:55 | Сообщение # 301
старожил
Сейчас нет на сайте
CyberStorm, скриншот под спойлер спрячь.
Цитата (CyberStorm)
то выделнный красным квадрат - был бы белым.

Он был бы не совсем белым (для этого нужно больше итераций), но белых точек содержал бы больше, чем на остальной поверхности.

Раз уж делать тестирующую программу, то вот что я сделал:

Можно скачать, поиграться для наглядности (а ещё проверить - вдруг у кого-то random не такой). Примечание: "общее число вычислений" должно быть во много раз больше "верхняя граница", иначе фигня получится; чем больше числа - тем лучше, но слишком большие числа приведут к очень медленному процессу на 98%-99% (но она не зависает, она думает); включённый флаг "Randomize каждое вычисление" заставляет перед каждым random() делать randomize (это я сделал на всякий случай, если кто-то именно так пытается применять randomize).

Если бы было следующее:
Цитата (Nanotentacle)
с вероятностью в 95% эти числа попадают в промежуток 1700-2000
то график получался бы со смещением правого (1700..2000) конца сильно вверх (к тысячам и десяткам тысяч), а левый (0..1700) стремился бы к нулю.

Цитата (Nanotentacle)
Есть ли более "случайные" генераторы для Делфи

Хм, поищи в интернете... Генераторы наверняка есть, вот только "случайность" у них будет примерно такая же.
Цитата (Nanotentacle)
или лучше написать его самостоятельно?

Попробуй написать, но всё равно будет что-то вроде random... wacko




Сообщение отредактировал TimKruz - Четверг, 27 Декабря 2012, 21:07
NanotentacleДата: Пятница, 28 Декабря 2012, 09:15 | Сообщение # 302
был не раз
Сейчас нет на сайте
Да, сейчас проверил собственноручно, вы правы. Но тогда возникает вопрос: в моей программе при создании объекта вычисляется случайная величина, и каждый раз она оказывается как раз в промежутке 1700-2000. Не было ни одного случая, чтобы значение оказывалось меньше 1700. С чем такое может быть связано?
CyberStormДата: Пятница, 28 Декабря 2012, 12:37 | Сообщение # 303
был не раз
Сейчас нет на сайте
Цитата (Nanotentacle)
Да, сейчас проверил собственноручно, вы правы. Но тогда возникает вопрос: в моей программе при создании объекта вычисляется случайная величина, и каждый раз она оказывается как раз в промежутке 1700-2000. Не было ни одного случая, чтобы значение оказывалось меньше 1700. С чем такое может быть связано?

Думаю у тебя там ведь не такая функция: a:=rndom(2000), скорее всего перемедрил где-то типа a:=1700+random(300) smile без кода трудно анализировать cool
NanotentacleДата: Пятница, 28 Декабря 2012, 14:03 | Сообщение # 304
был не раз
Сейчас нет на сайте
Там именно a := random(2000). Перед всеми рандомами стоит randomize.

Я и раньше замечал, что с помощью рандома не получается делать случайные события. Допустим, после x := random(100) все попытки разделить вероятности, например, по 20 путем
if x <= 20
if (x > 20) and(x <=40)
ни к чему не приводило, приходилось подбирать некие коэффициенты, чтобы получать те самые 20 процентов, которые мне требовались. Возможно, дело в том, что у меня не 10 миллионов итераций, а порядка 100-1000.


Сообщение отредактировал Nanotentacle - Пятница, 28 Декабря 2012, 14:08
DestroyДата: Четверг, 10 Января 2013, 23:46 | Сообщение # 305
постоянный участник
Сейчас нет на сайте
возникла проблема пытаюсь связать timage и timagelist
решил записать все в таймер чтобы сменял картинки через некоторое время
Код

procedure TForm1.tmr1Timer(Sender: TObject);
  const
    n:integer=0;

begin
ImageList1.Draw(Image1.Canvas, 10,10,n);

n:=n+1;//n это номер картинки

end;


выдает ошибку: [Error] Unit1.pas(35): Left side cannot be assigned to
GECKДата: Пятница, 11 Января 2013, 11:51 | Сообщение # 306
заслуженный участник
Сейчас нет на сайте
Destroy, дык еще бы, ты константе присвоить что-то пытаешься. Замени const на var.

Всё гениальное просто. И хреново работает.

Сообщение отредактировал GECK - Пятница, 11 Января 2013, 11:54
TimKruzДата: Пятница, 11 Января 2013, 21:29 | Сообщение # 307
старожил
Сейчас нет на сайте
GECK, запись вида n:integer=0; не константа, точнее не простая константа, а типизированная, т.е. может менять значение по ходу выполнения программы. Но в данном случае записать её в разделе var нельзя, т.к. нельзя давать инициализирующее значение переменным в процедурах/функциях.
Почему вылетает ошибка - не знаю (она ведь на n:=n+1 указывает?), но лучше просто вынеси описание переменной n из обработчика таймера в переменные модуля, так будет логичнее и ошибок не будет.
А конструкцию n:=n+1 тут можно заменить на inc(n), так удобнее, если название переменной длинное (ты же не собираешься делать n1, n2, n3 и т.д.?).


GECKДата: Пятница, 11 Января 2013, 21:54 | Сообщение # 308
заслуженный участник
Сейчас нет на сайте
Цитата (TimKruz)
запись вида n:integer=0; не константа, точнее не простая константа, а типизированная, т.е. может менять значение по ходу выполнения программы.

Менять значение она может только в том случае, если это явно разрешить компилятору(директива {$WriteableConst On}). Обычно же делфи этого не позволяет, именно с такой ошибкой.
Так что либо разрешать переписывать константы, либо делать из n переменную(что как-то логичней, на мой взгляд) smile


Всё гениальное просто. И хреново работает.
DestroyДата: Воскресенье, 20 Января 2013, 21:54 | Сообщение # 309
постоянный участник
Сейчас нет на сайте
вытащил n:integer из процедуры описал в разделе var перед implementation
теперь работает
Цитата (TimKruz)
inc(n)

и это тоже позаимствовал
всем спасибо за внимание biggrin

Добавлено (20.01.2013, 21:54)
---------------------------------------------
попытался тут сделать небольшой эффект моря бьющегося об берег.
беру из имейдж листа изображение и вывожу имейдж. Возникла проблема.
1 изображение оставляет после себя белые следы
вот исходник

CyberStormДата: Воскресенье, 20 Января 2013, 22:54 | Сообщение # 310
был не раз
Сейчас нет на сайте
ты вроде .pas файл забыл приложить в архив sad
"Unit1 in '..\..\..\..\games\Delphi7\Projects\pirate project\Unit1.pas' {Form1};"
DestroyДата: Понедельник, 21 Января 2013, 10:05 | Сообщение # 311
постоянный участник
Сейчас нет на сайте
ой прошу прощения
вот сейчас вроде все положил smile
CyberStormДата: Понедельник, 21 Января 2013, 12:34 | Сообщение # 312
был не раз
Сейчас нет на сайте
В ImageList'e ты вроде выставил прозрачный цвет, а вот надо было еще указать в инспекторе - чтоб заместо него ничего не выводил:


Не советую рисовать на Image'ах, выводи изображения на канвас формы
http://rghost.ru/43199466
masb8ly-GCДата: Понедельник, 21 Января 2013, 12:37 | Сообщение # 313
постоянный участник
Сейчас нет на сайте
CyberStorm, canvas не лучший способ хранения графики по той причине, что, например, при "наезжании" другим окном на окно с канвасом, канвас очищается. И таких нюансов очень много!

Backend Developer ESIS
Client Side Developer Room8Studio
Technical Leader Lucid Reality Labs
Chief Technology Officer The Intruders
DestroyДата: Понедельник, 21 Января 2013, 14:15 | Сообщение # 314
постоянный участник
Сейчас нет на сайте
Цитата (CyberStorm)
В ImageList'e ты вроде выставил прозрачный цвет, а вот надо было еще указать в инспекторе - чтоб заместо него ничего не выводил:

все равно все также без изменений

Добавлено (21.01.2013, 14:15)
---------------------------------------------
но да ладно
более менее разобрался с этим

TimKruzДата: Понедельник, 21 Января 2013, 16:34 | Сообщение # 315
старожил
Сейчас нет на сайте
Цитата (masb8ly-GC)
canvas не лучший способ хранения графики

Ну если ты игру пишешь, то у тебя минимум 30 кадров в секунду, так что канва формы будет постоянно обновляться. Канва TImage просто сама по себе обновляется заданной картинкой, поэтому сохраняет изображение. А канва TForm вроде бы по-умолчанию непрерывно обновляется, поэтому просто нарисовать не получится, нужно самому всё обновлять (если вручную [средствами WinAPI, без использования VCL] создать окно - такого не будет, т.к. обработчик события перерисовки окна самому писать надо, хотя не обязательно). Если у тебя игра не использует какие-то сложные компоненты VCL (ну которые ты кидаешь на форму), то лучше создавать окно вручную, так быстрее должно получиться (правда структура приложения усложнится и никакими дизайнерами не воспользуешься). А вообще, для игр лучше OpenGL использовать... Конечно, он устроен иначе, и придётся потратить какое-то время на его изучение, но вообще-то ничего в нём особо сложного нет... Вот, например, книга: Краснов М.В., "OpenGL графика в проектах Delphi", там основы просто и понятно изложены.

Короче, изучай всё постепенно, но не старайся написать очень сложную (графически) игру чисто на канве image и тому подобного...


DestroyДата: Суббота, 26 Января 2013, 17:22 | Сообщение # 316
постоянный участник
Сейчас нет на сайте
вот у меня например есть 3 переменные img1, img2, img3. можно ли сделать что то типа imgN, где N (1,2,3)
то есть мне не нужен массив. в зависимости от значения N вызывается разные img
чтобы имя переменной изменялось
может немного некорректно изложил мысль


Сообщение отредактировал Destroy - Суббота, 26 Января 2013, 17:22
TimKruzДата: Воскресенье, 27 Января 2013, 20:32 | Сообщение # 317
старожил
Сейчас нет на сайте
Цитата (Destroy)
вот у меня например есть 3 переменные img1, img2, img3. можно ли сделать что то типа imgN, где N (1,2,3)
то есть мне не нужен массив. в зависимости от значения N вызывается разные img
чтобы имя переменной изменялось

Так сделать не получится (вообще, по-моему, ни в одном компилируемом языке нельзя менять идентификаторы "на лету", потому что в коде не может быть двусмысленности - компилятор просто не поймёт такого imgN). Придётся использовать массив img[n], а если требуется задание неопределённого заранее числа переменных - использовать динамический массив. Если ты не можешь использовать массивы напрямую, например, у тебя заранее созданы визуальные компоненты с именами img1/img2/../imgn, а ты хочешь перебирать их циклом for - тогда можно использовать массив указателей. Каждый элемент массива img содержит ссылку на соответствующий компонент. Если ты используешь классы (типа TImage), то можно сделать так:
Код
type TForm1=class(TForm)
img1,img2,img3:TImage; //Описание компонентов в классе формы
<...>
var img:array [1..3] of TImage; //Где-то задан массив указателей на эти компоненты
<...>
//Где-то копируем ссылки на экземпляры класса TImage в наш массив
img[1]:=img1;
img[2]:=img2;
img[3]:=img3;
<...>
//А тут используем их в цикле:
for i:=1 to 3 do img[i].canvas.clear;
<...>

Вроде бы должно работать. Писать в месте копирования ссылок много, но если циклов for достаточно много - будет всё-таки проще делать так.

Теоретически, можно в классе формы (TForm1) задать массив компонентов img:array [1..3] of TImage, только, наверное, возникнут сложности с редактором форм. wacko Но в обычном классе (не привязанном к редактору форм) такое легко делается.


DestroyДата: Вторник, 05 Февраля 2013, 20:38 | Сообщение # 318
постоянный участник
Сейчас нет на сайте
спасибо, немного по другому решил проблему. но схоже с твоим

Добавлено (05.02.2013, 15:27)
---------------------------------------------
Очередной вопрос.
очень прошу объяснить про потоки (treads), желательно с комментариями, на примере приложения, которое допустим должно менять img1 на img2, img3...img5. С интервалом в 1 секунду.
Таймер не предлагать!нужны именно потоки

Добавлено (05.02.2013, 20:38)
---------------------------------------------
up

TimKruzДата: Среда, 06 Февраля 2013, 00:20 | Сообщение # 319
старожил
Сейчас нет на сайте
Цитата (Destroy)
очень прошу объяснить про потоки (treads)

Мог и сам посмотреть в интернете - уроков полно... Например, вот, первая ссылка в Яндексе...
Цитата (Destroy)
на примере приложения, которое допустим должно менять img1 на img2, img3...img5. С интервалом в 1 секунду.

Ммм, хочешь использовать потоки для создания анимации? Бред какой-то... wacko Я вообще не пойму, зачем тут потоки. Хотя... Нужна независимая от основного кода анимация, т.е. выполняемая в отдельном потоке? Но почему нельзя использовать таймер, ведь в нём можно производить несколько действий сразу...

Так. Вот, написал тебе простейший примерчик, на форме две надписи и кнопка:
Код
unit mainunit;

interface

uses
   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
   Dialogs, StdCtrls;

type
   TForm1 = class(TForm)
     Label1: TLabel;
     Label2: TLabel;
     Button1: TButton;
     procedure FormCreate(Sender: TObject);
     procedure FormClose(Sender: TObject; var Action: TCloseAction);
     procedure Button1Click(Sender: TObject);
   end;

   //Описываем собственный класс на основе базового
   TMyThread=class(TThread)
     //num юзаем для того, чтобы экземпляр класса
     //мог определить, кто он есть в этом мире...
     num:byte; //короче, типа идентификатора
   protected
     //Перезаписываем виртуальный абстрактный метод Execute
     procedure Execute; override;
   public
     //Создаём собственный конструктор
     constructor Create(nm:byte);
   end;

var
   Form1: TForm1;
   th1,th2:TMyThread; //Это наши экземплярчики

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
   //Создаём два процесса, первый и второй
   th1:=TMyThread.Create(1);
   th2:=TMyThread.Create(2);
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
   //Завершаем поток и удаляем экземпляры
   th1.Terminate;
   th2.Terminate;
end;

//Конструктор класса
constructor TMyThread.Create;
begin
   num:=nm; //Сохраняем тип
   //Следующая переменная, заданная в true,
   //удаляет экземпляр сразу после остановки
   FreeOnTerminate:=true;
   //Вызываем TThread.Create с параметром
   //CreateSuspended=true, т.е. поток изначально остановлен;
   //если false - поток запускается сразу после создания
   inherited Create(true);
end;

procedure TMyThread.Execute;
begin
   //Бесконечный цикл
   repeat
     //Выбираем действие по типу
     case num of
     1: form1.Label1.Caption:=inttostr(strtoint(form1.Label1.Caption)+1);
     2: form1.Label2.Caption:=inttostr(strtoint(form1.Label2.Caption)+1);
     end;
     //Делаем паузу
     sleep(500);
   until false;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
   //Переключаем состояние потоков: вкл/выкл
   if th1.Suspended then
   begin
     th1.Resume;
     th2.Resume;
   end else
   begin
     th1.Suspend; //Suspend - приостановка, но не завершение
     th2.Suspend;
   end;
end;

end.


Ещё есть хороший пример от разработчиков Delphi - смотри в C:\Program Files\Borland\Delphi7\Demos\Threads, если ты устанавливал с примерами. Там демонстрируется сортировка трёх списков тремя разными методами в трёх потоках - типа наглядная демонстрация разности в скорости между методами сортировок, т.к. потоки, теоретически, выполняются синхронно, если у них одинаковый приоритет.




Сообщение отредактировал TimKruz - Среда, 06 Февраля 2013, 00:27
DestroyДата: Четверг, 07 Февраля 2013, 15:12 | Сообщение # 320
постоянный участник
Сейчас нет на сайте
Цитата (TimKruz)
Ммм, хочешь использовать потоки для создания анимации? Бред какой-то..

нее, просто не знал на каком примере это можно сделать
а так спасибо за разъяснение
Форум игроделов » Программирование » Delphi/Pascal/Object Pascal » Delphi:Вопрос-Ответ (Спросил - получил ответ)
Поиск:

Все права сохранены. GcUp.ru © 2008-2021 Рейтинг