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 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 "{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.
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.
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.
No comments:
Post a Comment