Wiki
Clone wikiCore / SoundsPlus
Back to Codea's Example Projects
Sounds Plus by Dylan Sale and Simeon
Introduction
Sounds Plus is one of the example projects supplied with Codea. It provides a utility for exploring simple and advanced sounds. A user can use the integrated sound picker by tapping on the highlighted sound function.
The example also illustrates the implementation of button and menu elements, as well as the use of a subclass SoundButton
inheriting from a superclass Button
.
Tabs in the project
In addition to Main
the project comprises the following tabs:
Tab | Comment |
---|---|
BasicMenu | Establishes the class BasicMenu . |
AdvancedMenu | Establishes the class AdvancedMenu . |
RoundRect | Contains the function roundRect() . |
Button | Establishes the class Button . |
SoundButton | Establishes the class SoundButton , a subclass of Button . |
Each of the BasicMenu
and AdvancedMenu
classes implements the following functions: myMenu:onEnter()
, myMenu:draw()
and myMenu:touched(touch)
.
Main tab
The Main
tab implements three callback functions (which are explained further later in this section):
setup() -- called once
draw() -- called up to 60 times a second
touched(touch) -- called whenever a touch on screen begins, ends or moves
The Main
tab also implements the following functions:
toggleMenu() -- Toggles between menus
drawButton() -- Draws the button referred to by 'button'
setup()
This creates one instance of the BasicMenu
class (in basicMenu
and one instance of the AdvancedMenu
class (in advancedMenu
. Global variable menu
is set to refer to the same instance as basicMenu
. The onEnter()
function of menu
is then called.
Global variable button
is set to refer to an instance of the Button
class (initialised with string "Go To Advanced"). The action
field of button
is set to a function that toggles between menus:
button = Button("Go To Advanced")
button.action = function () toggleMenu() end -- Set to refer to a function
toggleMenu()
The toggleMenu()
function toggles the global variable menu
referring to the instance referred to by basicMenu
or the instance referred to by advancedMenu
. In each case, the displayName
field of button
is set to refer to the other menu option:
if menu == basicMenu then
menu = advancedMenu
button.displayName = "Go To Basic"
else
menu = basicMenu
button.displayName = "Go To Advanced"
end
Once menu
has been toggled, the onEnter()
function of menu
is then called.
draw()
The draw()
function is called by Codea up to 60 times a second and does three things:
function draw()
background(63, 63, 88, 255) -- Colour is a dark bluish grey
menu:draw() -- Draw 'menu'
drawButton() -- Draw 'button' (see below)
end
drawButton()
The drawButton()
function sets the pos
field of button
to be to the middle of the right of the viewer (as a vec2
value) and then calls the draw()
function of button
.
touched(touch)
This function is called when the viewer is touched. It passes the touch
on to first menu
and then button
to handle:
function touched(touch)
menu:touched(touch)
button:touched(touch)
end
BasicMenu tab
The BasicMenu
tab implements BasicMenu
as a class, defining the following functions:
BasicMenu:init()
BasicMenu:onEnter()
BasicMenu:draw()
BasicMenu:drawButtons()
BasicMenu:touched(touch)
AdvancedMenu tab
The AdvancedMenu
tab implements AdvancedMenu
as a class, defining the following functions:
AdvancedMenu:init()
AdvancedMenu:onEnter()
AdvancedMenu:draw()
AdvancedMenu:touched(touch)
It also implements a global function: playSound()
.
RoundRect tab
The RoundRect
tab holds the code for a global function: roundRect(x, y, w, h, r)
. As its name suggests, this function draws a rectangle with rounded corners (of radius r
). The bottom left-hand corner of the rectangle is at x, y
and it has width w
and height h
. That is, the rounded rectangle is drawn as if rectMode(CORNER)
has been called.
The method used is to use the built-in rect()
function to draw an 'inner', inset, rectangle:
insetPos = vec2(x + r, y + r) -- Bottom-left is one 'radius' in
insetSize = vec2(w - 2 * r, h - 2 * r) -- Width and height are two 'radii' shorter
...
noSmooth()
rectMode(CORNER)
rect(insetPos.x, insetPos.y, insetSize.x, insetSize.y)
and to use the built-in line
function with lineCapMode(ROUND)
to draw a boundary around it:
-- Copy fill into stroke
local red, green, blue, a = fill()
stroke(red, green, blue, a)
...
if r > 0 then -- Check that the radius is positive
smooth()
lineCapMode(ROUND) -- Set the line caps to rounded
strokeWidth(r * 2) -- Set width to the diameter
line(insetPos.x, insetPos.y,
insetPos.x + insetSize.x, insetPos.y) -- Line along the bottom
line(insetPos.x, insetPos.y,
insetPos.x, insetPos.y + insetSize.y) -- Line along left
line(insetPos.x, insetPos.y + insetSize.y,
insetPos.x + insetSize.x, insetPos.y + insetSize.y) -- Line along the top
line(insetPos.x + insetSize.x, insetPos.y,
insetPos.x + insetSize.x, insetPos.y + insetSize.y) -- Line along right
In order to protect the existing style, all the drawing takes place between a pushStyle()
and matching popStyle()
:
function roundRect(x,y,w,h,r)
pushStyle() -- Preserve the style on the stack
... -- Drawing
popStyle() -- Retrieve the style from the stack
end
Button tab
The Button
tab implements Button
as a class, defining the following functions:
Button:init(displayName)
Button:draw()
Button:hit(p)
Button:touched(touch)
The Button
class acts as the superclass for the SoundButton
class.
Button:hit(p)
This function returns true
if point p
falls within the boundary of the button (determined by fields pos
and size
), and false
otherwise.
Button:touched(touch)
This function checks whether the touch.state
is ENDED
and its location is within the boundary of the button (using self:touched(touch)
. If it is, the function referenced by the field action
is called (if it exists):
function Button:touched(touch)
if touch.state == ENDED and
self:hit(vec2(touch.x, touch.y)) then
if self.action then -- Does 'action' exist?
self.action() -- Call 'action'
end
end
end
SoundButton tab
The SoundButton
tab implements SoundButton
as a subclass of Button
, defining the following functions:
SoundButton:init(displayName)
SoundButton:draw()
Updated