Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум на Исходниках.RU > Delphi: Общие вопросы > Как установить бонус если пользователь выбрал 5 фигур в течении 3 секунд?


Автор: Katerina1993 26.09.22, 16:52
Здравствуйте, разместила 10 примитивных фигур. По щелчку по этим фигурам они исчезают и прибавляется 50 очков. Мне нужно сделать бонус, что если пользователь щелкнут по 5 фигурам в течении трех секунд то вместо 50 очков он получит 100 а в Label1 появится сообщение бонус открыт. Как это сделать?

P.S. У меня есть таймер который срабатывает каждую секунду. В нем нужно как-то условие прописать, чтобы начислять бонус за нахождении 5 предметов в течении 3 секунд.

Вот мой код:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    unit Unit1;
     
    interface
     
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, ExtCtrls, AppEvnts;
    type
      TForm1 = class(TForm)
        Button1: TButton;
        Timer1: TTimer;
        Label1: TLabel;
        Label2: TLabel;
        ApplicationEvents1: TApplicationEvents;
        Label3: TLabel;
        Memo1: TMemo;
        Image1: TImage;
        Timer2: TTimer;
        procedure ApplicationEvents1Message(var Msg: tagMSG;
          var Handled: Boolean);
        procedure FormPaint(Sender: TObject);
        procedure Button1Click(Sender: TObject);
        procedure FormShow(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
      TRect = class
      private
          x0, y0: Integer;
          width, height: Integer;
          color : TColor;
          exists : Boolean;
          Map_X, Map_Y: Integer;
      public
        constructor Create(_x0, _y0, _MapX, _MapY, w1, h1: Integer; _Color:TColor; _exists:Boolean);
        Procedure Draw(Cs:TCanvas;x:Integer;y,MapX,MapY:Integer); //Прорисовка
      end;
     
    var
      Form1: TForm;
      rightb, leftb, upb, downb : Boolean;
      OldX, OldY : integer;
      //dragok : Boolean;
      dragok:Integer;
      StartX:Integer;
      StartY:Integer;
      H1, W1 : Integer;
      rect : Array [0..10] Of TRect;
      
      Position2: Array[1..10,1..2] of Integer;
      col:Integer = 1;
      hGap:Integer = 34;
      vGap:Integer = 30;
      xPos:Integer = 50;
      yPos:Integer = 50;
      id11:Integer = 0;
    implementation
     
    {$R *.dfm}
     
    constructor TRect.Create(_x0,_y0,_MapX,_MapY,w1,h1: Integer; _Color: TColor; _exists:Boolean);
    begin
      inherited Create;
      x0 := _x0;
      y0 := _y0;
      width := w1;
      height := h1;
      color := _Color;
      Map_X := _MapX;
      Map_Y := _MapY;
      exists:=_exists;
    end;
     
     
    procedure TRect.Draw(Cs: TCanvas; x, y, MapX, MapY: Integer);
    begin
      //x0 := x;
      //y0 := y;
      Map_X := MapX;
      Map_Y := MapY;
      Cs.Brush.Color:=color;
      //Form1.Canvas.Brush.Color:=color;
      Cs.Rectangle(x0+Map_X,y0+Map_Y,x0+width+Map_X,y0+height+Map_Y);
    end;
     
    procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG;
      var Handled: Boolean);
      var
       P : TPoint;
       i : Integer;
    begin
       if Msg.message = WM_LBUTTONDOWN then
       begin
           P:=Image1.ScreenToClient(Mouse.CursorPos);
       for i := 1 to 9 do
         begin
           if (rect[i].x0 < P.X) and
           (rect[i].x0+rect[i].width > P.X)
           and (rect[i].y0 < P.Y) and
           (rect[i].y0+rect[i].height > P.Y)
            then
            begin
              
               if rect[i].exists = true then
               begin
                   //
                  
                   rect[i].exists := false;
                   id11:=id11+50;
                   Label3.Caption:='Очки='+IntToStr(id11)
               end;
            end;
           end;
        end;
        if Msg.message = WM_LBUTTONUP then
        begin
            for i := 1 to 9 do
            begin
              
              //rect[i].dragok:=false;
            end;
        end;
        if Msg.message = WM_MOUSEMOVE then
        begin
            
        end;
        
     
    end;
     
    procedure TForm1.FormPaint(Sender: TObject);
    var i: Integer;
    begin
    {osition2[1,1]:=100;
    Position2[2,1]:=200;
    Position2[3,1]:=11;
    Position2[4,1]:=55;
    Position2[5,1]:=155;
    Position2[6,1]:=70;
    Position2[7,1]:=10;
    Position2[8,1]:=30;
    Position2[9,1]:=40;
    Position2[10,1]:=70;
    Position2[1,2]:=100;
    Position2[2,2]:=44;
    Position2[3,2]:=344;
    Position2[4,2]:=244;
    Position2[5,2]:=100;
    Position2[6,2]:=100;
    Position2[7,2]:=100;
    Position2[8,2]:=150;
    Position2[9,2]:=180;
    Position2[10,2]:=100;
         }
        // xPos:=50;
        // yPos:=50;
         //
    Image1.Canvas.Brush.Color:=clWhite;
    Image1.Canvas.FillRect(Image1.ClientRect);
    for i := 1 to 9 do
    begin
     
       if rect[i].exists = true then
          rect[i].Draw(Image1.Canvas,xPos,yPos,0,0);
     
      
     
     
    end;
     
     
     
     
    end;
     
    procedure SaveToFile(file1:string;str:string);
    var
     f:TextFile;
     FileDir:String;
    begin
     FileDir:='c:\docum\'+file1;
    AssignFile(f,FileDir);
    if not FileExists(FileDir) then
     begin
      Rewrite(f);
      CloseFile(f);
     end;
    Append(f);
    Writeln(f,str);
    Flush(f);
    CloseFile(f);
    end;
     
    procedure TForm1.Button1Click(Sender: TObject);
    var i:Integer;
    begin
     
    //Image1.Canvas.Brush.Color:=clWhite;
    //Image1.Canvas.FillRect(Image1.ClientRect);
    Label3.Caption:=IntToStr(id11);
    for i := 1 to 9 do
    begin
     if rect[i].exists = true then
      SaveToFile('1docum.txt','true')
     else
      SaveToFile('1docum.txt','false');
    end;
    end;
     
    procedure TForm1.FormShow(Sender: TObject);
    var i: Integer;
    begin
    xPos:=50;
    yPos:=50;
     
    for i := 1 to 9 do
    begin
       rect[i] := TRect.Create(xPos,yPos,0,0,50,50,clBlue,true);
       //if rect[i].exists = true then
         // rect[i].Draw(Image1.Canvas,xPos,yPos,0,0);
        xPos := xPos + 50 + hGap;
        inc(col);
      if col > 3 then
       begin
        col := 1;
        xPos := 50;
        yPos := yPos + 50 + vGap;
       end;
    end;
    end;
     
    end.

Автор: macomics 26.09.22, 17:44
Вам нужен не таймер, а переменная, которая сохраняет время. Тогда при начислении очков станет элементарно проверить время прошедшее с момента первого нажатия.
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    fig[selected].click_time := GetTickCount;
    if selected = 5 then
      if min(fig[1].click_time, fig[2].click_time, fig[3].click_time,
             fig[4].click_time, fig[5].click_time) > GetTickCount - 3000 then // с момента щелчка не прошло 3 секунд.
    //(GetTickCount - 3000) = время, которое возвращала функция GetTickCount ровно 3 секунды назад
Такую переменную ассоциируете с каждой из выбранных фигур и проверяете минимальное значение из всех выбранных. Минимальное потому, что оно было сделано раньше всего и с этого момента прошло больше всего времени. Если самое ранее событие выбора фигуры было раньше чем 3 секунды, тогда все последующие события лежат в пределах 3 секунд. Если оно произошло раньше 3 секундного отрезка времени, тогда как минимум одну фигуру выбрали вне этого интервала.

Автор: Katerina1993 26.09.22, 20:37
Не понятно как это добавить в мой код, что такое массив fig, selecred и свойство click_time? У меня используется rect обозначающий объект.

Автор: macomics 26.09.22, 21:41
fig - массив объектов, которые были выбраны
selected - счетчик выбранных объектов
click_time - переменная типа int, в которой будет сохраняться количество миллисекунд прошедших с запуска компьютера, получаемых от функции GetTickCount
Переменную click_time добавьте в класс TRect. Когда по объекту будут кликать (выбирать), тогда в эту переменную будет заноситься значение GetTickCount. Когда с объекта будет сниматься выделение, значение в этой переменной можно обнулять.
Так как объектов выделять не нужно больше m, а всего объектов n (m < n), тогда можно не добавлять в класс TRect переменную click_time, а завести отдельный массив из структур типа TSelect
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    type
      PRect = ^TRect;
      TSelect = packed record
        item: PRect;
        click_time: Integer;
      end;
     
    var
      fig: array of TSelect; // В этот массив можно записывать выбранные объекты


Приведенный мной пример добавляется в событие OnClick

Автор: Katerina1993 26.09.22, 22:29
Все разобралась. Примерно так при нажатии на первом объекте записать время. Допустим это будет переменная firstTime, потом при нажатии на пятом объекте записать последнее время lastTime. Нужно делать инкримент при выборе объекта, чтобы знать где первый и пятый элемент. После того как удалось установить первый таймер и последний. Создаем условие где происходит вычитание и проверка на 3 секунды lastTime-firstTime < 3000. Потом выводим ту информация которая нужна, например "бонус получен". Это только в теории, но думаю если все сделать будет работат.

Добавлено
Вот переделанный код работает:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    ....
    for i := 1 to 9 do
         begin
           if (rect[i].x0 < P.X) and
           (rect[i].x0+rect[i].width > P.X)
           and (rect[i].y0 < P.Y) and
           (rect[i].y0+rect[i].height > P.Y)
            then
            begin
              
               if rect[i].exists = true then
               begin
                   //
                   inc(count);
                   if count = 1 then
                   begin
                      firstTimer := GetTickCount;
                   end;
     
                   if count = 5 then
                   begin
                      lastTimer := GetTickCount;
                      if lastTimer-firstTimer < 3000 then
                      begin
                          count := 0;
                          Label3.Caption:='Бонус получен';
                      end;
                    end
                    else
                    begin
                      lastTimer := GetTickCount;
                      if lastTimer-firstTimer > 3000 then
                        count := 0;
                    end;
                    Label1.Caption:=IntToStr(count);
     
     
                   rect[i].exists := false;
                   id11:=id11+50;
                end;
            end;
           end;
    ....

Автор: macomics 27.09.22, 07:22
Если объекты можно не только выделять, но и снимать выделение, тогда надо сохранять время выделения каждого объекта. Сохранять время только для двух объектов в этом случае не правильно. Если снимут выделение с первого выделенного объекта, тогда нужно будет время выделения второго объекта, а его не было записано.

Автор: Katerina1993 27.09.22, 10:07
Зачем нужно снимать выделение? Пользователь щелкает по объекту он удаляется время фиксируется на первом объекте и последнем, они уже не будут существовать после выбора. Когда объекты выбраны делаются расчеты по времени потом через условие происходит проверка (прошло 3 секунды или нет).

Powered by Invision Power Board (https://www.invisionboard.com)
© Invision Power Services (https://www.invisionpower.com)