In this post we recreate the Arcade Breakout game in Excel using VBA macros. Shape objects are used for the paddle 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.
Breakout game
Breakout is another classic
arcade game released by Atari a long time ago. It is fundamentally similar to
another arcade game we saw earlier in this blog (see Pong game here).
The goal of the game is to destroy a formation of rows of bricks at the top
portion of the screen, by repeatedly bouncing a ball off a paddle into them.
This version of Breakout in Excel tries to recreate the first versions of the original game. One of the key features is that the ball can take different trajectories depending how is hit. The latest versions of the game have additional functionalities and effects that are not contemplated here.
Game display
The playground spans a range
from cells B2 to I21 with interior color black. There is a formation of bricks
throughout rows 4 to 7. The bricks and player’s paddle are rectangular shapes
and the ball is an oval shape.
The first macro (StartGame)
defines the Shape objects and variables that are used. Note that these are
declared at module level. That macro can also initialize the position of the
player 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.
Set ball = Sheet1.Shapes("ball")
ball.Left = 135: ball.Top = 98
ballColInc = 1: ballRowInc = 1
StartGame calls another
macro to add the bricks. These are rectangular shapes that span the dimension
of each cell along the playground from rows 4 to 7. There are a total of 32
bricks in this version of Excel Breakout.
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 (M2_Timer).
SetTimer creates a timer that triggers an event after a
certain number of milliseconds have elapsed (35 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 Breakout 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 the player misses to hit the ball on its way down and the
ball reaches the bottom, or when pressing the Stop button.
Paddle movement
We can move the paddle with
the right and left keyboard arrows or with the mouse cursor (much easier using the
mouse). To use the keyboard, we link the right and left arrow keys with the
corresponding macros to move right or left the paddle using Application.OnKey.
Application.OnKey "{RIGHT}", "moveRight"
However, pressing a key in
Excel repeatedly slows down code execution or even stops it until the key is
released, so using the keys does not work very well in Excel Breakout. There
are some tricks to come around this problem but, ultimately, using the mouse is
a 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 horizontal coordinate of the cursor. That’s what we need to check
each time to move the paddle either left or right if the horizontal coordinate
is less or more than before respectively. We could also get the vertical
coordinate with Hold.y, but is not needed here because the paddle only moves horizontally.
GetCursorPos Hold
CursorX = Hold.x
End Function
Conditional statements in
the moving macro check whether the cursor has moved using a variable the holds
the horizontal position of the cursor (x). The value of the variable is updated
each time. Note that the variable x is declared as Long.
player1.Left = player1.Left - 6
End If
player1.Left = player1.Left + 6
End If
x = CursorX
Another macro checks
whether the ball hits any of the bricks by comparing the horizontal and
vertical position of the ball against the position of each of the bricks. If
the ball intersects with any of the bricks, the shape is deleted and points are
updated.




No comments:
Post a Comment