-
Notifications
You must be signed in to change notification settings - Fork 0
/
greenhouse.lua
290 lines (255 loc) · 8.63 KB
/
greenhouse.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
-----------------------------------------------------------------------------------------
--
-- greenhouse.lua
--
-- The greenhouse game for the Mars App
-- The user can plant, water, and harvest vegetables for food.
-----------------------------------------------------------------------------------------
-- Get local reference to the game globals
local game = globalGame
-- Create the act object
local act = game.newAct()
-- Constants
local msTimer = 100 -- timer interval
local maxHealth = 100 -- plant health ranges from 0 to 100
-- File local variables
local plants -- group for all the plants
local timerID -- repeating timer
local waterHintShown -- true when the hint to water plants has been shown
local nPlantsDied = 0 -- total number of plants that have died
local nWaterings = 0 -- total number of times user has watered any plant
local waterText -- water readout label
local foodText -- food readout label
local waterLight -- water status light
local foodLight -- food status light
-- Update a resource light's color based on its value, warning level, and low level
local function setResLightColor( light, value, low, warning )
if value < low then
light:setFillColor( 1, 0, 0 ) -- red for low
elseif value < warning then
light:setFillColor( 1, 1, 0 ) -- yellow for warning
else
light:setFillColor( 0, 1, 0 ) -- green
end
end
-- Update food and water level display
local function updateResDisplay()
waterText.text = string.format( "Water: %d liters", game.water() )
foodText.text = string.format( "Food: %d kg", game.food() )
setResLightColor( waterLight, game.water(), 50, 100 )
setResLightColor( foodLight, game.food(), 50, 150 )
end
-- Called when the drops are done animating
local function dropsDone( drops )
-- Water increases the plant's health
drops.plant.health = game.pinValue( drops.plant.health + 25, 0, maxHealth )
drops:removeSelf()
end
-- Water the plant
local function waterPlant( plant )
-- Make a group of 3 drops
local drops = act:newGroup()
drops.x = plant.x
drops.y = plant.y - 60 -- will animate down to the touch point
local dropSize = 12
act:newImage( "drop.png", { parent = drops, x = 3, y = -4, width = dropSize } )
act:newImage( "drop.png", { parent = drops, x = -3, y = -8, width = dropSize } )
act:newImage( "drop.png", { parent = drops, x = 0, y = 0, width = dropSize } )
drops.plant = plant
game.addWater( -1 )
updateResDisplay()
-- Animate the drops falling with sound effect
game.playSound( act.wateringSound )
transition.to( drops, { y = plant.y - 20, xScale = 2, yScale = 2,
time = 500, onComplete = dropsDone } )
end
-- Touch handler for plants
local function touchPlant( event )
if event.phase == "began" then
local plant = event.target
-- Process plant based on its state
if plant.health <= 0 then
-- Remove dead plant
if not plant.beingRemoved then
plant.beingRemoved = true
game.playSound( act.plantingSound )
transition.to( plant, { xScale = 1, yScale = 1, alpha = 0,
time = 500, onComplete = game.removeObj })
end
elseif plant.flowers then
-- Harvest mature plant
if not plant.beingHarvested then
plant.beingHarvested = true
game.playSound( act.plantingSound )
transition.fadeOut( plant, { time = 500, onComplete = game.removeObj } )
game.addFood( 10 )
updateResDisplay()
game.floatMessage( "10 kg food", event.x, event.y )
end
else
-- Water the plant
if game.water() <= 0 then
game.messageBox( "Out of water!" )
else
waterPlant( plant )
nWaterings = nWaterings + 1
end
end
end
return true
end
-- Make a new plant at the given location
local function makePlant( x, y )
local size = 40
local plant = act:newGroup( plants )
plant.x = x
plant.y = y + size / 2
local leaves = act:newImage( "potatoPlant.png", { parent = plant, height = size, x = 0, y = 0 } )
leaves.anchorY = 1 -- grow from bottom up
leaves:setFillColor( 0, 0.6, 0 )
plant.leaves = leaves
plant.health = maxHealth
plant:addEventListener( "touch", touchPlant )
end
-- Touch handler for the dirt background
local function touchDirt( event )
if event.phase == "began" then
makePlant( event.x, event.y )
game.playSound( act.plantingSound )
end
return true
end
-- Show the water hint if necessary
function checkWaterHint()
if not waterHintShown and nPlantsDied > nWaterings then
game.showHint( "Tap plants to water them.")
waterHintShown = true
end
end
-- Set a plant's color based on its health
local function adjustPlantColor( plant )
if plant.health <= 0 then
-- Color dead plants dark brown and remove flowers
if not plant.dead then
plant.dead = true
plant.leaves:setFillColor( 0.5, 0.25, 0 )
if plant.flowers then
plant.flowers:removeSelf()
end
nPlantsDied = nPlantsDied + 1
checkWaterHint()
end
else
-- Interpolate plant color based on health
local deadColor = { r = 0.5, g = 0.4, b = 0.0 } -- brown
local goodColor = { r = 0.0, g = 0.6, b = 0.0 } -- green
local hf = plant.health / 100
local ihf = 1 - hf
local r = ihf * deadColor.r + hf * goodColor.r
local g = ihf * deadColor.g + hf * goodColor.g
local b = ihf * deadColor.b + hf * goodColor.b
plant.leaves:setFillColor( r, g, b )
-- TODO: wither flowers
end
end
-- Add flowers to the plant if it doesn't already have them
local function addFlowers( plant )
if not plant.flowers then
local flowers = act:newGroup( plant )
local size = 8 -- in unscaled plant units
act:newImage( "flower.png", { parent = flowers, width = size, x = 0, y = -30 } )
act:newImage( "flower.png", { parent = flowers, width = size, x = 7, y = -25} )
act:newImage( "flower.png", { parent = flowers, width = size, x = -5, y = -20 } )
plant.flowers = flowers
end
end
-- Called for each timer tick
local function timerTick()
-- Grow/adjust all the plants
for i = 1, plants.numChildren do
-- Time decreases plant health due to need for more water
local plant = plants[i]
plant.health = game.pinValue( plant.health - 1, 0, maxHealth )
adjustPlantColor( plant )
if plant.xScale >= 3 and plant.health >= 70 then
-- Large, healthy plants make flowers and are ready to pick for food
addFlowers( plant )
elseif plant.xScale < 3 and plant.health > 80 then
-- Healthy plants grow (up to a certain size)
local newScale = plant.xScale * 1.02
transition.cancel( plant )
transition.to( plant, { xScale = newScale, yScale = newScale, time = msTimer } )
end
end
end
-- Handle tap on the back button
local function backButtonPress ( event )
-- Cheat mode adds 150 food immediately
if game.cheatMode then
game.addFood( 150 )
end
game.gotoAct ( "mainAct", { effect = "crossFade", time = 500 } )
return true
end
-- Create a resource label at the given y location and initally empty text
local function makeResLabel( y )
local t = display.newText( act.group, "", act.xCenter, y, native.systemFont, 16 )
t.anchorX = 0
t:setFillColor( 0 ) -- black text
return t
end
-- Make a resource status light
local function makeResLight( x, y )
return act:newImage( "roundLight.png", { x = x, y = y, height = 16 } )
end
-- Init the act
function act:init()
-- Dirt background
local dirt = act:newImage( "dirt.jpg", { height = act.height } )
dirt:addEventListener( "touch", touchDirt )
-- Group for plants
plants = act:newGroup()
-- UI/Display area
local uiHeight = 60
local area = act:newImage( "bamboo.png", { x = act.xCenter, y = act.yMin + uiHeight / 2,
width = act.width, height = uiHeight } )
waterText = makeResLabel( act.yMin + uiHeight * 0.3 )
foodText = makeResLabel( act.yMin + uiHeight * 0.7 )
waterLight = makeResLight( act.xMax - 20, waterText.y )
foodLight = makeResLight( waterLight.x, foodText.y )
-- back button
local backButton = act:newImage( "backButton.png", { width = 50 } )
backButton.x = act.xMin + uiHeight / 2
backButton.y = act.yMin + uiHeight / 2
backButton:addEventListener( "tap", backButtonPress )
backButton:addEventListener( "touch", game.eatTouch )
-- Load sound effects
act.plantingSound = act:loadSound( "Planting.wav" )
act.wateringSound = act:loadSound( "Pour4.wav" )
end
-- Prepare the act
function act:prepare()
-- Start a repeating timer for time action
assert( timerID == nil )
timerID = timer.performWithDelay( msTimer, timerTick, 0 )
updateResDisplay()
end
-- Start the act
function act:start()
game.playAmbientSound( "HarpPiano.mp3" )
end
-- Stop the act
function act:stop()
game.endMessageBox()
if timerID then
timer.cancel( timerID )
timerID = nil
end
end
-- Destroy the act
function act:destroy()
game.disposeSound( act.plantingSound )
game.disposeSound( act.wateringSound )
end
-- Corona needs the scene object returned from the act file
return act.scene