DelphiFeeds.com

  • Dashboard
  • Popular Stories
  • Trending Stories
  • Feeds
  • Login
Trending now

HeidiSQL Is A Lightweight Open Source Database Management Tool Built In Delphi

Incredibly Powerful Enhanced Terminal And Network Toolkit For Windows Is Built In Delphi

Learn How To Use C++ Explicit Virtual Overrides In Windows Development

Learn Python With The 5 Best Python GUI Libraries Video

Trial – TMS VCL WebGMaps

Trial – TMS VCL UI Pack

Trial – TMS VCL Cloud Pack

Trial – TMS VCL Chart

Trial – TMS Scripter

Brook Framework

Get These Visually Stunning FireMonkey Styles Free To Enhance User Experience In Your Delphi Apps

VCL Styles: Master The Secrets Of Beautiful Modern Apps In Windows 10

grep for Delphi .dproj file containing copy commands for certain DLLs

Powerful Cross Platform Multitrack Music Recording Software Built In Delphi FireMonkey

Ultra-Fast Enterprise-Grade List And Label Reporting Tool For Delphi

Memory 3D – Full Source Code Delphi Game

1
zarkogajic zarkogajic 2 years ago in Delphi, games, memory, oop, tgridpanel, timage, User Interface 0

Memory3D“If you want it to be playable and more interesting you need to jazz it up a bit!”

That’s what’s been cooking in my head from the time I’ve finished implementing the back end for the game of Memory (Match Up, Concentration, or whatever you are used to call it). As a proof of concept, I’ve coded a very simple application, aka the front end for the game – juts to have a workable user interface.

Now, the time has come to finish the series and introduce a more eye candy version of the game, one that’s not using dull buttons with numbers for field display values but that actually looks like card game type of Memory, with nice fancy images/icons for game fields. Why stop there? Why not go a step forward and introduce a new dimension for the game: make it 3D having fields appear on planes/layers, so players need to switch between planes to match a pair.

Memory 3D

Here’s the idea: in the standard Memory game, all fields containing game pairs, would be presented to the player at once. Meaning that if the game has 12 fields, that is 6 pairs, all 12 playable fields are visible and the player can pick from to find a match – so basically 2 dimensions: a number of rows and columns where fields are presented in a grid like fashion (say 4×3 for 12 fields).

What if I would to introduce one more, 3rd, dimension: a plane (a layer). So if the game has 8 pairs (16 fields) and 2 planes – only 8 fields are visible/presented to the player at one time. 8 fields on first plane, 8 more on the second plane. So one field of a pair can be on the first plane and the second field can be on the second plane. Player needs to switch between planes to find a match – remember the row and column but also the plane.

Sounds interesting, so let’s see the UI and some code …

For those living by the TL;DR: mantra: download full source code.

As stated I want to have some graphics displayed on each game field. For this purpose I’ve went to browse the https://www.freepik.com web site hosting some free to use icons and graphics. I was looking for some handy set of icons and have found one from @makyzz:

There are 10×10 icons/glyphs here – quite enough as that would result in game of Memory of maximum 200 fields (100 pairs). I’ll store the entire image in a hidden “ClipImage” TImage control and will cut out the piece I need for a game field. Since field values would go from 0 to 99 the icon/glyph in second row, third column would have the index of 12. Here’s a function to get the image graphics for a field with the value of “fieldIndex”:

function TMainForm.GetFieldGraphics(const fieldIndex: integer): TPicture;
var
  clipWidth, clipHeight : Integer;
  srcRect, destRect : TRect;
begin
  clipWidth := ClipImage.Picture.Width div ClipColumns;
  clipHeight := ClipImage.Picture.Height div ClipRows;

  destRect := Rect(0, 0, clipWidth, clipHeight) ;
  srcRect.Left := (fieldIndex mod ClipColumns) * clipWidth;
  srcRect.Top := (fieldIndex div ClipRows) * clipHeight;
  srcRect.Right := srcRect.Left + clipWidth;
  srcRect.Bottom := srcRect.Top + clipHeight;

  PictureClip.Bitmap.Width := clipWidth;
  PictureClip.Bitmap.Height := clipHeight;
  PictureClip.Bitmap.Canvas.CopyRect(destRect, ClipImage.Canvas, srcRect) ;

  result := PictureClip;
end;

The UI

The user interface looks pretty much the same as in the 2D version of the game. We need to have a way to switch between planes so 2 more buttons added to the UI. Also, I’ve added some Display options: to display (or not) some field info like what plane are we one, what player has claimed the pair and alike.

The New Game

Here’s how the game is created and started:

procedure TMainForm.btnNewGameClick(Sender: TObject);
var
  newGamePairs, newGamePlayers, newGamePlanes : integer;
  newGameFieldValueShift : integer;
begin
  Randomize;

  newGamePairs := StrToInt(ledPairs.Text);
  newGamePlayers := StrToInt(ledPlayers.Text);;
  newGamePlanes := StrToInt(ledPlanes.Text);;

  fClipImage := imgImagesGrid100;
  fClipColumns := 10;
  fClipRows := 10;
  fMaxPairs := fClipColumns * fClipRows;

  if newGamePairs > MaxPairs then
  begin
    newGamePairs := MaxPairs;
    ledPairs.Text := newGamePairs.ToString;
  end;

  newGameFieldValueShift := Random(MaxPairs - newGamePairs + 1);

  try
    MGame.NewGame(newGamePairs, newGamePlayers, newGamePlanes, newGameFieldValueShift);
  except on E:Exception do
    begin
      MessageDlg(E.Message, mtError, [mbOk], -1);
      Exit;
    end;
  end;
end;

Set the wanted number of fields, planes and players. The “newGameFieldValueShift” ensures we always pick random range of icons from the available set – so not to always use the same ones.

The MGame.NewGame would raise the OnGameCreate and OnGameStart events I’m using to setup the user interface. If the total number of fields (2 x number of pairs) is not dividable by the number of planes – the game would raise an exception and would not start.

The OnPlaneChaned even handler is the most interesting one as this is where the icons would be extracted:

procedure TMainForm.PlaneChanged(Sender : TObject);
var
  i : integer;
  mField : TMField;
  pnl : TPanel;
  img : TImage;
  lbl : TLabel;
begin
  lblCurrentPlane.Caption := Format('Current plane: %d of %d planes.', [MGame.CurrentPlane, MGame.PlanesCount]);

  //set field hosts for current plane
  for i := 0 to -1 + gameGrid.ControlCount do
  begin
    mField := MGame.Fields[i + MGame.FirstFieldIndexOnCurrentPlane];

    pnl := TPanel(gameGrid.Controls[i]);
    img := TImage(pnl.Controls[0]);
    lbl := TLabel(pnl.Controls[1]);

    if chkShowPlaneInfo.Checked then
    begin
      lbl.Caption := Format('%d / %d / %d', [i + 1, MGame.CurrentPlane, MGame.PlanesCount]);
      lbl.Visible := MGame.PlanesCount > 1;
    end
    else
      lbl.Visible := false;

    mField.Host := img;

    if mField = MGame.OpenedField then
    begin
      pnl.BevelKind := bkTile;
      TImage(mField.Host).Picture.Assign(GetFieldGraphics(mField.Value))
    end
    else if mField.Player <> nil then
    begin
      pnl.BevelKind := bkNone;
      TImage(mField.Host).Picture.Assign(GetFieldGraphics(mField.Value));

      if chkShowClaimedInfo.Checked then
      begin
        lbl.Caption := Format('%s', [mField.Player.Name]);
        lbl.Visible := true;
      end;
    end
    else
    begin
      pnl.BevelKind := bkTile;
      TImage(mField.Host).Picture.Assign(imgQuestionField.Picture);
      //TImage(mField.Host).Picture.Assign(GetFieldGraphics(mField.Value))
    end;
  end;

  pnlGameGrid.Refresh;
end;

The rest of the code is more or less the same as in the 2D version of the game.

Hope you like it and if you do a FireMonkey version for mobiles – do share 😉

Trending Stories

  • Incredibly Powerful Enhanced Terminal And Network Toolkit For Windows Is...

  • Learn How To Use C++ Explicit Virtual Overrides In Windows...

  • Learn Python With The 5 Best Python GUI Libraries Video

  • Trial – TMS VCL WebGMaps

  • Trial – TMS VCL UI Pack

Embarcadero GetIt

  • Brook Framework

    Microframework which helps to develop web Pascal applications.

  • Trial - TMS Scripter

    Add the ultimate flexibility and power into your apps with native Pascal or Basic scripting and […]

  • Trial - TMS VCL Chart

    DB-aware and non DB-aware feature-rich charting components for business, statistical, financial […]

  • Trial - TMS VCL Cloud Pack

    TMS VCL Cloud Pack is a Delphi and C++Builder component library to seamlessly use all major cloud […]

  • Trial - TMS VCL UI Pack

    Create modern-looking & feature-rich Windows applications faster with well over 600 components […]

  • Learn Delphi Programming
  • Learn C++
  • Embarcadero Blogs
  • BeginEnd.net
  • Python GUI
  • Firebird News
  • Torry’s Delphi Pages
Copyright DelphiFeeds.com 2021. All Rights Reserved
Embarcadero
Login Register

Login

Lost Password

Register

Lost Password