forked from Eddy34743/Corona-Comics-SDK-2.0
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcover.lua
472 lines (412 loc) · 18.4 KB
/
cover.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
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
----------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------
--
-- Abstract: Corona Comics 2 Demo
-- Be Confident in Who You Are: A Middle School Confidential™ Graphic Novel Lite Version
--
-- Version: 2.0 (September 20, 2011)
-- Sample code is MIT licensed, see http://developer.anscamobile.com/code/license
-- Copyright (C) 2011 Electric Eggplant. All Rights Reserved.
-- Copyright (C) 2011 ANSCA Inc. All Rights Reserved.
--
-- Images and text excerpted from "Be Confident in Who You Are" by Annie Fox, M.Ed.,
-- (C) 2008. Used with permission of Free Spirit Publishing Inc., Minneapolis,
-- MN; 800-735-7323; www.freespirit.com. All Rights Reserved.
--
-- cover.lua - animation of the book cover.
--
----------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------
--
-- Notes: Whenever the app starts up again and you were last on the cover page
-- (0), this animation will run again. You can also trigger it through the Info
-- page by tapping on the cover icon.
--
-- If you have Particle Candy installed, the "smoke" effect will trigger when the
-- "Graphic Novel" stamp hits the page.
module(..., package.seeall)
local sndDir = "sound/"
local sndExt = ".m4a"
local imgDir = "images/cover/"
if _G.device == "android" then
sndExt = ".mp3"
end
----------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------
-- All cover routines are in this coverAnimation function
----------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------
function coverAnimation(restartFlag)
------------------------------------------------------------
-- Initialize: load images and sound
------------------------------------------------------------
local contentWidth = display.contentWidth
local contentHeight = display.contentHeight
local startOrientation = system.orientation
local isLandscape = _G.isDeviceLandscape
if _G.model == "nookcolor" then -- no orientation change on NOOK Color
isLandscape = false
_G.isDeviceLandscape = false
startOrientation = "portrait"
end
-- only exchange values if we're not on the simulator. Work-around for Corona bug?
if isLandscape and system.getInfo( "environment" ) ~= "simulator" then
contentWidth,contentHeight = contentHeight, contentWidth
end
local coverArt = display.newGroup( )
------------------------------------------------------------
-- Routines for screen orientation
------------------------------------------------------------
function setOrientation( orientation, animate, delta )
local angles = {
portrait = 0,
faceUp = -1, -- ignore faceUp and faceDown
faceDown = -1,
landscapeRight = 90,
landscapeLeft = 270,
portraitUpsideDown = 180
}
local lastOrientation = _G.lastOrientation
local device = _G.device
local rotation = angles[orientation]
if coverArt.rotation > 360 or coverArt.rotation < 0 then coverArt.rotation = 0 end -- if paused, sometimes this value gets crazy big
if rotation < 0 then
animate = false
if not coverArt.firstOrientationEventSuppressed then
rotation = angles[_G.lastOrientation] -- don't skip skip if faceUp or faceDown and this is first time through, set to initial orientation
else
return -- skip if we moved into faceUp or faceDown territory
end
else -- don't change landscape flag if we're flat
_G.isDeviceLandscape = ("landscapeLeft" == orientation or "landscapeRight" == orientation)
_G.lastOrientation = orientation
end
coverArt.screenW = display.contentWidth
coverArt.screenH = display.contentHeight
coverArt.contentCenterX = display.contentCenterX
coverArt.contentCenterY = display.contentCenterY
-- only exchange values if we're not on the simulator. Work-around for Corona bug?
if _G.isDeviceLandscape and system.getInfo( "environment" ) ~= "simulator" then
coverArt.screenW,coverArt.screenH = coverArt.screenH,coverArt.screenW
end
local scale = 1
if ( coverArt.contentWidth > coverArt.screenW ) or ( coverArt.contentHeight > coverArt.screenH ) then
local sx = coverArt.screenW / coverArt.screenWidth
local sy = coverArt.screenH / coverArt.screenHeight
scale = ( sx < sy ) and sx or sy
end
if not delta then animate = false end -- added to test cover rotation
if delta == -90 and rotation == 0 then
rotation = 360
elseif rotation == 270 and delta == 90 then
rotation = -90
end
if animate then
transition.to( coverArt, {
rotation=rotation,
time=300,
xScale=scale,
yScale=scale,
transition=easing.inOutQuad,
onComplete =
function()
if coverArt.rotation >= 360 then -- if paused, sometimes this value gets crazy big
coverArt.rotation = 0
elseif coverArt.rotation == -90 then
coverArt.rotation = 270
end
end})
else
coverArt.rotation = rotation
coverArt.xScale = scale
coverArt.yScale = scale
end
coverArt.firstOrientationEventSuppressed = true
end
------------------------------------------------------------
-- Orientation listener
------------------------------------------------------------
function orientation( event )
if _G.model ~= "nookcolor" then -- no orientation change on NOOK Color
setOrientation( event.type, true, event.delta )
end
end
------------------------------------------------------------
-- Set up the initial screen images
------------------------------------------------------------
local background = display.newImage(coverArt, imgDir .. "background.jpg", true)
local defaultPng
if restartFlag then
background.alpha = 0 -- need to set background to invisible so we can fade it up during this restart
else -- no need to pull in the background if this is a restart
local startup_image = "Default-Portrait.png"
if _G.device == "android" then startup_image = "startup.jpg" end
defaultPng = display.newImage(coverArt, startup_image, true)
end
coverArt.screenWidth = coverArt.width -- record the size before adding other elements
coverArt.screenHeight = coverArt.height
coverArt.screenW = display.contentWidth
coverArt.screenH = display.contentHeight
coverArt.xReference = 0.5*coverArt.contentWidth
coverArt.yReference = 0.5*coverArt.contentHeight
if isLandscape and system.getInfo( "environment" ) == "simulator" then
coverArt.x = 0.5*coverArt.screenH
coverArt.y = 0.5*coverArt.screenW
else
coverArt.x = 0.5*coverArt.screenW
coverArt.y = 0.5*coverArt.screenH
end
setOrientation(startOrientation, false, 0)
-- if Particle Candy is installed, then load smoke image (if you've 'required' their library file in main.lua)
if Particles then
local smoke = display.newImage(coverArt, imgDir .. "smoke.png", 0, -1380)
end
local backgroundDelay = 500 -- minimum time the default bacground should be displayed
if _G.model == "nookcolor" and not restartFlag then backgroundDelay = 500 end
local smokeDelay = backgroundDelay + 6170
local lastDelay = 0
-- x,y coordinates for the upper left corner of the rectangles that mask the MSC lettering
-- as the letters are "typed", we move the mask rectangle to the next position, uncovering
-- 1 letter
-- mask1 is for the top line of letters (Middle School)
local mask1 = {
{44,185},
{95,180},
{138,175},
{188,170},
{237,165},
{287,159},
{340,154},
{365,151},
{414,144},
{458,141},
{509,136},
{558,130},
{606,125},
{662,120},
}
-- mask2 is for the second line of letters (Confidential)
local mask2 = {
{107,262},
{152,257},
{208,251},
{257,246},
{303,241},
{353,235},
{407,229},
{464,223},
{513,218},
{558,215},
{615,208},
{678,200},
}
-- Load all the sound effects
local swishSnd = audio.loadSound( sndDir .. "swish" .. sndExt )
local typeSnd = audio.loadSound( sndDir .. "type" .. sndExt )
local typeReturnSnd = audio.loadSound( sndDir .. "type_return" .. sndExt )
local titleswishSnd = audio.loadSound( sndDir .. "title_swish" .. sndExt )
local bellSnd = audio.loadSound( sndDir .. "typewriter_bell" .. sndExt )
local stampSnd = audio.loadSound( sndDir .. "stamp" .. sndExt )
local rollSnd = audio.loadSound( sndDir .. "roll" .. sndExt )
------------------------------------------------------------
-- Routines for disposing of images and sound
------------------------------------------------------------
function cleanupImages()
if Particles then -- if Particle Candy is installed, clean up
Particles.CleanUp()
end
coverArt:removeSelf()
collectgarbage("collect")
-- print("collect garbage "..collectgarbage("count"))
-- print( "TextureMemory finished: " .. system.getInfo("textureMemoryUsed")/1024 .. " bytes" )
end
local function cleanupSound()
fadeAllSound(0)
swishSnd=nil
audio.dispose(typeSnd)
typeSnd=nil
audio.dispose(typeReturnSnd)
typeReturnSnd=nil
audio.dispose(titleswishSnd)
titleswishSnd=nil
audio.dispose(bellSnd)
bellSnd=nil
audio.dispose(stampSnd)
stampSnd=nil
audio.dispose(rollSnd)
rollSnd=nil
end
-- Load all the images and set to initial positions/scale/alpha (usually out of sight)
local masthead = display.newImage(coverArt, imgDir .. "masthead.png", 0, -1380, true)
masthead:setReferencePoint(display.TopLeftReferencePoint)
local msc = display.newImage(coverArt, imgDir .. "msc.png", 47, -5125, true)
msc:setReferencePoint(display.TopLeftReferencePoint)
local maskRect1 = display.newRect(coverArt, 0, 0, coverArt.screenWidth, 65 )
maskRect1:setFillColor(35,31,32 )
maskRect1:setReferencePoint(display.TopLeftReferencePoint)
maskRect1.y = -5190
maskRect1.x = 0
maskRect1:rotate(-6.3)
local maskRect2 = display.newRect(coverArt, 0, 0, coverArt.screenWidth, 65 )
maskRect2:setFillColor(35,31,32)
maskRect2:setReferencePoint(display.TopLeftReferencePoint)
maskRect2.y = -5274
maskRect2.x = 0
maskRect2:rotate(-6.3)
local title = display.newImage(coverArt, imgDir .. "title.png", -5000, 43, true)
title:setReferencePoint(display.TopLeftReferencePoint)
local book_1 = display.newImage(coverArt, imgDir .. "book_1.png", 664+74/2, 21, true)
book_1:setReferencePoint(display.CenterReferencePoint)
book_1.xScale=0.0001
book_1.yScale=0.0001
book_1.x=664+74/2 -- reset x after changing reference point?
-- if Particle Candy is installed, then initialize particle animation effect
if Particles then
-- CREATE AN EMITTER (NAME, SCREENW, SCREENH, ROTATION, ISVISIBLE, LOOP, AUTO-DESTROY)
Particles.CreateEmitter("stampEmitter", 289+222, 301+81, -10, false, false, true)
-- DEFINE PARTICLE TYPE PROPERTIES
local Properties = {}
Properties.imagePath = imgDir .. "smoke.png"
Properties.imageWidth = 256 -- PARTICLE IMAGE WIDTH (newImageRect)
Properties.imageHeight = 256 -- PARTICLE IMAGE HEIGHT (newImageRect)
Properties.velocityStart = 10 -- PIXELS PER SECOND
Properties.velocityVariation = 50 -- RANDOMLY ADDED SPEED VARIATION
Properties.alphaStart = 0.15 -- PARTICLE START ALPHA
Properties.alphaVariation = 0.65 -- RANDOMLY ADDED ALPHA VARIATION
Properties.fadeInSpeed = 1.0 -- PER SECOND
Properties.fadeOutSpeed = -0.45 -- PER SECOND
Properties.fadeOutDelay = 100 -- WHEN TO START FADE-OUT
Properties.scaleStart = 0.05 -- PARTICLE START SIZE
Properties.scaleVariation = 0.20 -- RANDOM SCALE VARIATION
Properties.scaleInSpeed = 0.40 -- SCALE-IN SPEED PER SECOND
Properties.scaleOutSpeed = 0.1 -- SCALE-OUT SPEED PER SECOND
Properties.scaleOutDelay = 5500 -- SCALE-OUT DELAY
Properties.rotationVariation = 360 -- RANDOM ROTATION
Properties.rotationChange = 10 -- ROTATION CHANGE PER SECOND
Properties.weight = 0.03 -- PARTICLE WEIGHT (>0 FALLS DOWN, <0 WILL RISE UPWARDS)
Properties.emissionShape = 1 -- 0 = POINT, 1 = LINE, 2 = RING, 3 = DISC
Properties.killOutsideScreen = false -- PARENT LAYER MUST NOT BE NESTED OR ROTATED!
Properties.lifeTime = 20000 -- MAX. LIFETIME OF A PARTICLE
Properties.emissionShape = 1
Properties.emissionRadius = 222
Particles.CreateParticleType ("particleLine", Properties)
local numSmokeParticles = 50
if _G.iPhone then numSmokeParticles = 25 end -- use fewer particles for the older iPhones to avoid a lag
Particles.AttachParticleType("stampEmitter", "particleLine", numSmokeParticles, 20000, smokeDelay ) -- trigger 300 ms early
-- CREATE A GROUP:
particleGroup = display.newGroup( )
coverArt:insert(particleGroup)
-- PUT EMITTER INTO GROUP:
particleGroup:insert( Particles.GetEmitter("stampEmitter") )
end
local stamp
if _G.liteVer then -- different "stamp" used on lite vs. production versions
stamp = display.newImage(coverArt, imgDir .. "stamp.png", 289, 281, true)
else
stamp = display.newImage(coverArt, imgDir .. "stamp.png", 289, 301, true)
end
stamp:setReferencePoint(display.CenterReferencePoint)
local stampStartScale = 5
stamp.xScale=stampStartScale
stamp.yScale=stampStartScale
stamp.alpha=0
local auth_illus = display.newImage(coverArt, imgDir .. "author_illustrator.png", 380, 897+120, true)
auth_illus:setReferencePoint(display.TopLeftReferencePoint)
local free_spirit = display.newImage(coverArt, imgDir .. "free_spirit.png", -170, 940, true)
free_spirit:setReferencePoint(display.TopLeftReferencePoint)
-- add a mask for the left and right edges, in case we're in Landscape rotation
-- we need to hide the images that are off-screen when in Portrait orientation,
-- they're not offscreen in Landscape
local maxWH = math.max(coverArt.screenWidth,coverArt.screenHeight) -- get the widest value of width or height
local rightEdge = coverArt.screenWidth
local bottomEdge = coverArt.screenHeight
local leftMaskRect = display.newRect(coverArt, 0, 0, maxWH, maxWH )
leftMaskRect:setFillColor(0,0,0) --(255,0,0)
leftMaskRect:setReferencePoint(display.TopRightReferencePoint)
leftMaskRect.y = 0
leftMaskRect.x = 0
local rightMaskRect = display.newRect(coverArt, 0, 0, maxWH, maxWH )
rightMaskRect:setFillColor(0,0,0) --(0,255,0)
rightMaskRect:setReferencePoint(display.TopLeftReferencePoint)
rightMaskRect.y = 0
rightMaskRect.x = rightEdge
local bottomMaskRect = display.newRect(coverArt, 0, 0, maxWH, maxWH )
bottomMaskRect:setFillColor(0,0,0) --(0,0,255)
bottomMaskRect:setReferencePoint(display.TopLeftReferencePoint)
bottomMaskRect.y = bottomEdge
bottomMaskRect.x = 0
-- fade background
if not restartFlag then
transition.dissolve( defaultPng, background, 600, backgroundDelay )
else
transition.to( background, { time=600, delay=backgroundDelay, alpha = 1, transition = easing.linear })
end
------------------------------------------------------------
-- Start the animation
------------------------------------------------------------
-- Drop down black masthead section
local tDelay = backgroundDelay + 200
local mastheadDelay = 500
transition.to(masthead, { delay=tDelay, time=mastheadDelay, y=0, transition=easing.inOutQuad } )
lastDelay = tDelay + mastheadDelay
tDelay = 500
typeDelay = 60
-- Move the MSC title in place plus the rectangles to cover the letters
transition.to(maskRect1, { delay=lastDelay, time=0, y=190, transition = easing.linear } )
transition.to(maskRect2, { delay=lastDelay, time=0, y=274, transition = easing.linear } )
transition.to(msc, { delay=lastDelay, time=0, y=125, transition = easing.linear } )
timer.performWithDelay(lastDelay-300, function() audio.play( swishSnd ) end)
-- Uncover the letters, one at a time using table data
for i = 1,#mask1 do
local bX,bY = unpack(mask1[i], 1, 2)
tDelay = lastDelay + typeDelay*i*2
transition.to(maskRect1, { delay=tDelay, time=typeDelay, x=bX, y=bY, transition = easing.linear } )
timer.performWithDelay(tDelay, function() audio.play( typeSnd ) end)
end
timer.performWithDelay(tDelay, function() audio.play( typeReturnSnd ) end )
lastDelay = tDelay+700
for i = 1,#mask2 do
local bX,bY = unpack(mask2[i], 1, 2)
tDelay = lastDelay + typeDelay*i*2
transition.to(maskRect2, { delay=tDelay, time=typeDelay, x=bX, y=bY, transition = easing.linear } )
timer.performWithDelay(tDelay, function() audio.play( typeSnd ) end )
end
lastDelay = tDelay
-- Slide in the title on the orange bar
transition.to(title, { delay=lastDelay, time=500, x=0, transition = easing.inOutQuad } )
timer.performWithDelay(lastDelay+200, function() audio.play( titleswishSnd ) end )
lastDelay = lastDelay + 500
-- Increase the scale of "Book 1" and shrink it to 1
local scale = 1.25
tDelay = 100
transition.to(book_1, { delay=lastDelay, time=0, transition = easing.linear } )
transition.to(book_1, { delay=lastDelay+tDelay, time=500, xScale=scale, yScale=scale, transition = easing.inOutQuad } )
timer.performWithDelay(lastDelay+tDelay+300, function() audio.play( bellSnd ) end )
lastDelay = lastDelay + tDelay + 500
scale = 1
transition.to(book_1, { delay=lastDelay, time=250, xScale=scale, yScale=scale, transition = easing.inOutQuad } )
lastDelay = lastDelay + 250
-- Scale down the stamp.
scale = 1
transition.to(stamp, { delay=lastDelay+tDelay, time=400, xScale=scale, yScale=scale, alpha=1, transition = easing.linear } )
lastDelay = lastDelay + tDelay + 500
if Particles then -- if Particle Candy is installed, then trigger the effect
-- Turn on the particles. One shot emission is set to true so all of the smoke appears immediately.
Particles.StartEmitter("stampEmitter",true)
end
-- Stamp impact sound effect
timer.performWithDelay(lastDelay-100, function() audio.play( stampSnd ) end )
-- Ratchet up the author and illustrator names
timer.performWithDelay(lastDelay+tDelay+100, function() audio.play( rollSnd ) end )
for i = 0,2 do
transition.to(auth_illus, { delay=lastDelay+tDelay+640*i, time=200, y=897+42.333333333333333*(2-i), transition = easing.inOutQuad } )
end
lastDelay = lastDelay+tDelay+640+640 + 300
-- Slide in the Free Spirit logo
transition.to(free_spirit, { delay=lastDelay, time=500, x=1, transition = easing.inOutQuad } )
timer.performWithDelay(lastDelay+300, function() audio.play( titleswishSnd, { onComplete=cleanupSound } ) end )
lastDelay = lastDelay + 500
--print("Last delay ="..lastDelay)
return lastDelay -- return the length of the entire animation to the calling routine so it knows how long to wait
end
return Cover