Saturday, December 28, 2024

Excel Pong Game

In this post we recreate the Arcade Pong game in Excel using VBA macros. Shape objects are used for the two paddles and the ball. Movement is achieved using the Windows Timer API (SetTimer function) that calls a moving procedure repeatedly. The ball position is then updated as per the value in increment variables for row and column. We move the paddle using keyboard or mouse. Computer’s move follows closely the position of the ball at any time. Not easy to beat!


Pong game

Pong is a classic arcade game released by Atari a long time ago. It was probably one of the first computer games with movement. It represents a table-tennis or tennis game between two players. Each player moves a paddle vertically to hit the ball; whoever misses the ball passed by loses the game (or gives a point to the other player).



This version of Pong in Excel tries to recreate the original game. However, there are a few differences and simplifications. I believe in the original game two real players are needed. Here we will play against the computer. The ball can take different trajectories depending how is hit in the original game. Here we will let the ball move with similar increments for row and column position, which will let the ball always move with a 45 degree angle. But this can easily be adapted to have Excel Pong as close as possible to the original game.

 

Game display

The playground spans a range from cells B2 to I14, which interior color is black and has a white vertical line in the middle that represents the net. The two paddles are rectangular shapes (Player1 and Player2) and the ball an oval shape (ball).


The first macro (StartGame) defines the Shape objects and variables that are used. Note that these are declared at module level. That macro also initializes the position for each object: player1, player2, and ball, as well as the initial direction of the ball, which is defined by the increment added to the horizontal and vertical position of the ball (1 or -1).

  
  Set player1 = Sheet1.Shapes("Player1")
  Set player2 = Sheet1.Shapes("Player2")
  player1.Top = 90: player2.Top = 90

  Set ball = Sheet1.Shapes("ball")
  ball.Left = 135: ball.Top = 98
  ballColInc = 1: ballRowInc = 1


Ball movement

In order to achieve the continuous movement of the ball, we need to call a “moving” procedure (MoveBall) every certain time interval, and that time interval should be in the range of milliseconds. We can do that using the SetTimer function of the Windows API library (user32.dll). We have already seen how to create movement in Excel with SetTimer in previous posts (Excel Circles Movement, Excel Tron Game, Excel Geometry Dash, or Excel Snake Game). The timer routines have been added to another module (Timer).


SetTimer creates a timer that triggers an event after a certain number of milliseconds have elapsed (25 milliseconds in this game). It has been configured to call the TimerEvent procedure, which calls the MoveBall procedure in the Main module of the Excel Pong Game VBA project. The timer continues triggering events between intervals until is removed using KillTimer. That happens in the StopTimer subroutine, which is called when a player cannot hit the ball and the ball reaches either the left or right edge of the playground, or when pressing the Stop button.

 

Paddle movement

We play with the blue paddle (player1) and can move it with the up and down keyboard arrows or the mouse cursor (much easier using the mouse). To use the keyboard, we link the up and down arrow keys with the corresponding macros to move up or down the paddle using Application.OnKey.

  
  Application.OnKey "{UP}", "moveUp"
  Application.OnKey "{DOWN}", "moveDown"


However, pressing a key in Excel repeatedly slows down code execution or even stops it until the key is released, so it does not work very well with this game. It’s good for games where we just need to press once to set the direction (such as the snake game, tron game, and some other). There are some tricks to come around this problem but, ultimately, using the mouse is a much better alternative.

In order to move the paddle with the mouse we need to get the position of the cursor each time the moving macro is called and see if the vertical position has changed to move the paddle in that direction. Excel does not have the built-in functionality to get or set the cursor position. However, we can use the GetCursorPos function of the Windows API library (user32.dll) to get the current cursor position.

We need to declare GetCursorPos at module level as indicated below; this has PtrSafe to avoid error if not 64-bit. GetCursorPos requires a variable declared as a custom data type (POINTAPI) that holds the values for the x and y position of the cursor.

 
  Declare PtrSafe Function GetCursorPos Lib "user32" (Point As POINTAPI) As Long
 
  Type POINTAPI
      x As Long
      y As Long
  End Type


The following function returns the vertical coordinate of the cursor. That’s what we need to check each time and move the paddle up or down if the vertical coordinate is less or more than before respectively. We could also get the horizontal coordinate with Hold.x, but is not needed here because the paddle only moves vertically.

 
  Function CursorY()
      Dim Hold As POINTAPI
      GetCursorPos Hold
      CursorY = Hold.y
  End Function


The red paddle is player2: the computer. The move of player2 follows a simple algorithm that checks the position of the ball each time the moving procedure is called and moves the racket up or down when the vertical position of the ball (Top property) is less or more than the edge of the paddle respectively. To make it more challenging, the computer only moves when the ball is on its field (from the left of column F). It’s simple but effective, and despite player2 moves only 2 points while we move 4 points each time, is still very hard or impossible to beat. Modifying the trajectory of the ball depending on how it’s hit would make the game more interesting, but I will leave that for another article.


Download Excel Pong Game


No comments:

Post a Comment

Popular Posts