Corona SDK: Create an Alphabet Soup Game - Interaction

This is the second installment in our Corona SDK Alphabet Soup Game tutorial. In today's tutorial, we'll add to our interface and start coding the game interaction. Read on!
Step 1: Declare Functions
Declare all functions as local at the start.
1 |
|
2 |
local Main = {} |
3 |
local addTitleView = {} |
4 |
local startBtnuttonListeners = {} |
5 |
local showCredits = {} |
6 |
local hideCredits = {} |
7 |
local showGameView = {} |
8 |
local gameListeners = {} |
9 |
local buildSoup = {} |
10 |
local startDraw = {} |
11 |
local hitTestObjects = {} |
12 |
local detectLetters = {} |
13 |
local alert = {} |
Step 2: Constructor
Next we'll create the function that will initialize all the game logic:
1 |
|
2 |
function Main() |
3 |
addTitleView() |
4 |
end |
Step 3: Add Title View
Now we place the TitleView in the stage and call a function that will add the tap listeners to the buttons.
1 |
|
2 |
function addTitleView() |
3 |
titleBg = display.newImage('titleBg.png') |
4 |
|
5 |
title = display.newImage('title.png') |
6 |
title.x = display.contentCenterX |
7 |
title.y = 120 |
8 |
|
9 |
startBtn = display.newImage('startBtn.png') |
10 |
startBtn.x = display.contentCenterX |
11 |
startBtn.y = display.contentCenterY + 20 |
12 |
|
13 |
aboutBtn = display.newImage('aboutBtn.png') |
14 |
aboutBtn.x = display.contentCenterX |
15 |
aboutBtn.y = display.contentCenterY + 65 |
16 |
|
17 |
titleView = display.newGroup() |
18 |
titleView:insert(titleBg) |
19 |
titleView:insert(title) |
20 |
titleView:insert(startBtn) |
21 |
titleView:insert(aboutBtn) |
22 |
|
23 |
startButtonListeners('add') |
24 |
end |
25 |
end |
Step 4: Start Button Listeners
This function adds the necesary listeners to the TitleView buttons.
1 |
|
2 |
function startButtonListeners(action) |
3 |
if(action == 'add') then |
4 |
aboutBtn:addEventListener('tap', showCredits) |
5 |
startBtn:addEventListener('tap', showGameView) |
6 |
else |
7 |
aboutBtn:removeEventListener('tap', showCredits) |
8 |
startBtn:removeEventListener('tap', showGameView) |
9 |
end |
10 |
end |
Step 5: Show Credits
The credits screen is shown when the user taps the about button, a tap listener is added to the credits view to remove it.
1 |
|
2 |
function showCredits:tap() |
3 |
aboutBtn.isVisible = false |
4 |
startBtn.isVisible = false |
5 |
about = display.newImage('about.png') |
6 |
about.x = about.width * 0.474 |
7 |
about.y = display.contentHeight + about.height |
8 |
|
9 |
transition.to(about, {time = 300, y = display.contentHeight - about.height/2.4, onComplete = function() about:addEventListener('tap', hideCredits) end}) |
10 |
end |
Step 6: Hide Credits
When the credits screen is tapped, it'll be tweened out of the stage and removed.
1 |
|
2 |
function hideCredits() |
3 |
transition.to(about, {time = 300, y = display.contentHeight+about.height, onComplete = function() aboutBtn.isVisible = true startBtn.isVisible = true about:removeEventListener('tap', hideCredits) display.remove(about) about = nil end}) |
4 |
end |
Step 7: Show Game View
When the Start button is tapped, the title view is tweened and removed revealing the game view.
1 |
|
2 |
function showGameView:tap() |
3 |
transition.to(titleView, {time = 300, y = -titleView.height, onComplete = function() display.remove(titleView) titleView = nil buildSoup() gameListeners('add') end}) |
4 |
end |
Step 8: Game Listeners
This code adds tap listeners to the game background, and these will be used to draw the selection line and identify the selected letters.
1 |
|
2 |
function gameListeners(action) |
3 |
|
4 |
if(action == 'add') then |
5 |
gameBg:addEventListener('touch', startDraw) |
6 |
gameBg:addEventListener('touch', detectLetters) |
7 |
else |
8 |
gameBg:removeEventListener('touch', startDraw) |
9 |
gameBg:removeEventListener('touch', detectLetters) |
10 |
end |
11 |
end |
Step 9: Build Soup Function
One of the main functions of the game; this will browse the Map table to create all the textfields and place them in the stage, continue to the next step to see its behavior.
1 |
|
2 |
function buildSoup() |
3 |
-- Code... |
4 |
end |
Step 10: Create Character TextFields
A double for is used to identify the elements in the Map table, one for the horizontal values and one for the vertical. The code will create a textfield for every value found in the table and then place them in the stage.
1 |
|
2 |
for i = 1, 10 do |
3 |
for j = 1, 12 do |
4 |
local tf = display.newText('', 0, 0, 'Arial', 19) |
5 |
tf:setTextColor(102, 102, 102) |
6 |
tf.width = 22 |
7 |
tf.height = 21 |
8 |
tf.x = math.floor(-10 + (31.3 * i)) |
9 |
tf.y = math.floor(-10 + (35 * j)) |
Step 11: Display Random Letters
The chosen words are already in the table, and the rest of the values are filled by 0's at the moment. The following lines change those 0's to a random letter.
1 |
|
2 |
-- Change 0's to Random Letters |
3 |
if(L1Map[j][i] == 0) then |
4 |
L1Map[j][i] = alphabet[math.floor(math.random() * table.maxn(alphabet))+1] |
5 |
end |
6 |
|
7 |
tf.text = L1Map[j][i] |
8 |
tfs:insert(tf) |
9 |
end |
10 |
end |
Step 12: Add Words List
This code creates two textfields that will contain the list of values to find and the values already found.
1 |
|
2 |
-- Add Words List |
3 |
|
4 |
local wordsString = '' |
5 |
|
6 |
for i = 1, #L1 do |
7 |
wordsString = wordsString .. ' ' .. L1[i] |
8 |
end |
9 |
|
10 |
wordsList = display.newText(wordsString, 5, 430, 'Arial', 14) |
11 |
wordsList:setTextColor(238, 238, 238) |
12 |
|
13 |
currentWords = display.newText('', 5, 455, 'Arial', 14) |
14 |
currentWords:setTextColor(238, 146, 63) |
Step 13: Draw Selection Line
A semi transparent line will be used to highlight the letters in the stage, in the next function this line is created and added to the stage.
1 |
|
2 |
function startDraw:touch(e) |
3 |
if(e.phase == 'began') then |
4 |
initX = e.x |
5 |
initY = e.y |
6 |
elseif(e.phase == 'ended') then |
7 |
line = display.newLine(initX, initY, e.x, e.y) |
8 |
line.width = 16 |
9 |
line:setColor(255, 142, 42, 60) |
10 |
lines:insert(line) |
11 |
end |
12 |
end |
Step 14: Code Review
Here is the full code written in this tutorial alongside comments to help you identify each part:
1 |
|
2 |
-- Alphabet Soup Game |
3 |
-- Developed by Carlos Yanez |
4 |
|
5 |
-- Hide Status Bar |
6 |
|
7 |
display.setStatusBar(display.HiddenStatusBar) |
8 |
|
9 |
-- Graphics |
10 |
-- [Background] |
11 |
|
12 |
-- [Game Background] |
13 |
|
14 |
local gameBg = display.newImage('bg.png') |
15 |
|
16 |
-- [Title View] |
17 |
|
18 |
local titleBg |
19 |
local title |
20 |
local startBtn |
21 |
local aboutBtn |
22 |
|
23 |
-- [TitleView Group] |
24 |
|
25 |
local titleView |
26 |
|
27 |
-- [CreditsView] |
28 |
|
29 |
local about |
30 |
|
31 |
-- [Words List Textfield] |
32 |
|
33 |
local wordsList |
34 |
local currentWords |
35 |
|
36 |
-- [Letter Texfields Container] |
37 |
|
38 |
local tfs = display.newGroup() |
39 |
|
40 |
-- [Selection Line] |
41 |
|
42 |
local line |
43 |
local lines = display.newGroup() |
44 |
|
45 |
-- [Alert] |
46 |
|
47 |
local alert |
48 |
|
49 |
-- [Sound] |
50 |
|
51 |
local bell = audio.loadStream('bell.caf') |
52 |
|
53 |
-- Variables |
54 |
|
55 |
local L1 = {'IPHONE', 'ANDROID', 'CORONA', 'MOBILE', 'GAMES'} |
56 |
local L1Map = {{0, 0, 'I', 0, 0, 0, 'G', 0, 0, 0}, |
57 |
{0, 0, 'P', 0, 0, 0, 'A', 0, 0, 0}, |
58 |
{0, 0, 'H', 0, 0, 0, 'M', 0, 0, 0}, |
59 |
{0, 'M', 'O', 'B', 'I', 'L', 'E', 0, 0, 0}, |
60 |
{0, 0, 'N', 0, 0, 0, 'S', 0, 0, 0}, |
61 |
{0, 0, 'E', 0, 0, 0, 0, 0, 0, 0}, |
62 |
{'C', 'O', 'R', 'O', 'N', 'A', 0, 0, 0, 0}, |
63 |
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, |
64 |
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, |
65 |
{0, 0, 'A', 'N', 'D', 'R', 'O', 'I', 'D', 0}, |
66 |
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, |
67 |
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}} |
68 |
|
69 |
local alphabet = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'} |
70 |
local correct = 0 |
71 |
|
72 |
-- Functions |
73 |
|
74 |
local Main = {} |
75 |
local addTitleView = {} |
76 |
local startBtnuttonListeners = {} |
77 |
local showCredits = {} |
78 |
local hideCredits = {} |
79 |
local showGameView = {} |
80 |
local gameListeners = {} |
81 |
local buildSoup = {} |
82 |
local startDraw = {} |
83 |
local hitTestObjects = {} |
84 |
local detectLetters = {} |
85 |
local alert = {} |
86 |
|
87 |
function Main() |
88 |
addTitleView() |
89 |
end |
90 |
|
91 |
function addTitleView() |
92 |
titleBg = display.newImage('titleBg.png') |
93 |
|
94 |
title = display.newImage('title.png') |
95 |
title.x = display.contentCenterX |
96 |
title.y = 120 |
97 |
|
98 |
startBtn = display.newImage('startBtn.png') |
99 |
startBtn.x = display.contentCenterX |
100 |
startBtn.y = display.contentCenterY + 20 |
101 |
--startBtn.name = 'startBtn' |
102 |
|
103 |
aboutBtn = display.newImage('aboutBtn.png') |
104 |
aboutBtn.x = display.contentCenterX |
105 |
aboutBtn.y = display.contentCenterY + 65 |
106 |
--aboutBtn.name = 'aboutBtn' |
107 |
|
108 |
titleView = display.newGroup() |
109 |
titleView:insert(titleBg) |
110 |
titleView:insert(title) |
111 |
titleView:insert(startBtn) |
112 |
titleView:insert(aboutBtn) |
113 |
|
114 |
startButtonListeners('add') |
115 |
end |
116 |
|
117 |
function startButtonListeners(action) |
118 |
if(action == 'add') then |
119 |
aboutBtn:addEventListener('tap', showCredits) |
120 |
startBtn:addEventListener('tap', showGameView) |
121 |
else |
122 |
aboutBtn:removeEventListener('tap', showCredits) |
123 |
startBtn:removeEventListener('tap', showGameView) |
124 |
end |
125 |
end |
126 |
|
127 |
function showCredits:tap() |
128 |
aboutBtn.isVisible = false |
129 |
startBtn.isVisible = false |
130 |
about = display.newImage('about.png') |
131 |
about.x = about.width * 0.474 |
132 |
about.y = display.contentHeight + about.height |
133 |
|
134 |
transition.to(about, {time = 300, y = display.contentHeight - about.height/2.4, onComplete = function() about:addEventListener('tap', hideCredits) end}) |
135 |
end |
136 |
|
137 |
function hideCredits() |
138 |
transition.to(about, {time = 300, y = display.contentHeight+about.height, onComplete = function() aboutBtn.isVisible = true startBtn.isVisible = true about:removeEventListener('tap', hideCredits) display.remove(about) about = nil end}) |
139 |
end |
140 |
|
141 |
function showGameView:tap() |
142 |
transition.to(titleView, {time = 300, y = -titleView.height, onComplete = function() display.remove(titleView) titleView = nil buildSoup() gameListeners('add') end}) |
143 |
end |
144 |
|
145 |
function gameListeners(action) |
146 |
|
147 |
if(action == 'add') then |
148 |
gameBg:addEventListener('touch', startDraw) |
149 |
gameBg:addEventListener('touch', detectLetters) |
150 |
else |
151 |
gameBg:removeEventListener('touch', startDraw) |
152 |
gameBg:removeEventListener('touch', detectLetters) |
153 |
end |
154 |
end |
155 |
|
156 |
function buildSoup() |
157 |
for i = 1, 10 do |
158 |
for j = 1, 12 do |
159 |
local tf = display.newText('', 0, 0, 'Arial', 19) |
160 |
tf:setTextColor(102, 102, 102) |
161 |
tf.width = 22 |
162 |
tf.height = 21 |
163 |
tf.x = math.floor(-10 + (31.3 * i)) |
164 |
tf.y = math.floor(-10 + (35 * j)) |
165 |
|
166 |
-- Change 0's to Random Letters |
167 |
|
168 |
if(L1Map[j][i] == 0) then |
169 |
L1Map[j][i] = alphabet[math.floor(math.random() * table.maxn(alphabet))+1] |
170 |
end |
171 |
|
172 |
tf.text = L1Map[j][i] |
173 |
tfs:insert(tf) |
174 |
end |
175 |
end |
176 |
|
177 |
-- Add Words List |
178 |
|
179 |
local wordsString = '' |
180 |
|
181 |
for i = 1, #L1 do |
182 |
wordsString = wordsString .. ' ' .. L1[i] |
183 |
end |
184 |
|
185 |
wordsList = display.newText(wordsString, 5, 430, 'Arial', 14) |
186 |
wordsList:setTextColor(238, 238, 238) |
187 |
|
188 |
currentWords = display.newText('', 5, 455, 'Arial', 14) |
189 |
currentWords:setTextColor(238, 146, 63) |
190 |
end |
191 |
|
192 |
function startDraw:touch(e) |
193 |
if(e.phase == 'began') then |
194 |
initX = e.x |
195 |
initY = e.y |
196 |
elseif(e.phase == 'ended') then |
197 |
line = display.newLine(initX, initY, e.x, e.y) |
198 |
line.width = 16 |
199 |
line:setColor(255, 142, 42, 60) |
200 |
lines:insert(line) |
201 |
end |
202 |
end |
Next Time...
In the next and final part of the series, we'll handle the letter identification, display the words already found, and the final steps to take prior to release like app testing, creating a start screen, adding an icon and, finally, building the app. Stay tuned for the final part!