Question

I'm trying to create a Game of Life emulator. I previously got it working with a StrGrid however that was slower and I was told to use a DrawGrid.

My program works by having two arrays, strArray that holds all the values for the next generation of cells, and currentArray that holds all the values for the current generation of cells (both are type array [1 .. 127] of array [1 .. 127] of string;, I know it would be better to use a boolean array but this is an older program). On a timer, an algorithm counts the number of alive cells around each cell and gives it a value in strArray, T (Designating an alive cell) or F (Designating a dead cell). This pattern is then written to currentArray to be used the next time the alive cells need to be calculated. I then would like to change the color of each cell to white if the relevant cell matches 'F' in the currentArray, and change it to black if it matches 'T'. I'd also like to be able to color a cell I click black and change it's value in the data table to 'T'.

However, I'm unfamiliar with drawgrids and can't seem to find any relevant information that makes any sense to me. When I was using a string grid, you could access the contents of each cell by using stringgrid.cells[stringgrid.col, stringgrid.row] := 'whatever'; however I can't find a similar method for a DrawGrid.

To summarise, I need help to:

  • Change the color of a cell in a drawgrid inside a timer.onTick procedure.
  • Chage the color of a cell in a drawgrid when I click on it.

I hope you can help me. Thankyou!

Was it helpful?

Solution

The only real difference between TDrawGrid and TStringGrid is that TDrawGrid does not store any cell data itself whereas TStringGrid does, and also that you have to draw everything yourself in a TDrawGrid whereas TStringGrid default-draws the cell strings for you (but you can also custom draw the cells if desired). You have your own arrays for storing your cell data. Use the OnDrawCell event to draw the cells however you want. It gives you the Col and Row of the cell currently being drawn. You would simply access the corresponding array elements and set the grid's Canvas properties accordingly, such as its Brush.Color and Font.Color, then call the Canvas.FillRect() and Canvas.TextRect() methods as needed.

As for handling clicks, all you would do is update your array as needed and then Invalidate() the grid to trigger a repaint using the latest data.

For example:

procedure TForm1.TimerTick(Sender: TObject);
begin
  // update contents of currentArray as needed...
  DrawGrid1.Invalidate;
end;

procedure TForm1.DrawGrid1Click(Sender: TObject);
begin
  if currentArray[DrawGrid1.Col][DrawGrid1.Row] <> 'T' then
  begin
    currentArray[DrawGrid1.Col][DrawGrid1.Row] := 'T';
    DrawGrid1.Invalidate;
  end;
end;

procedure TForm1.DrawGrid1DrawCell(Sender: TObject; ACol, ARow: Longint; Rect: TRect; State: TGridDrawState);
begin
  if currentArray[ACol][ARow] = 'F' then
  begin
    DrawGrid1.Canvas.Brush.Color := clWhite;
    DrawGrid1.Canvas.Font.Color := clBlack;
  end else
  begin
    DrawGrid1.Canvas.Brush.Color := clBlack;
    DrawGrid1.Canvas.Font.Color := clWhite;
  end;
  DrawGrid1.Canvas.FillRect(Rect);
  DrawGrid1.Canvas.TextRect(Rect, Rect.Left, Rect.Top, currentArray[ACol][ARow]);
end;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top