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 | -- Load external library (should be in the same folder as main.lua) local ui = require("ui") -- Labels for digital display local headingGeo = ui.newLabel{ bounds = { 25, 47, 88, 46 }, text = "0°", font = "Helvetica-Bold", textColor = { 35, 170, 255, 255 }, size = 38, align = "right" } local directionGeo = ui.newLabel{ bounds = { 111, 66, 31, 24 }, text = "N", font = "Helvetica-Bold", textColor = { 35, 170, 255, 255 }, size = 16, align = "left" } local headingMag = ui.newLabel{ bounds = { 175, 47, 88, 46 }, text = "0°", font = "Helvetica-Bold", textColor = { 153, 153, 153, 255 }, size = 38, align = "right" } local directionMag = ui.newLabel{ bounds = { 261, 66, 31, 24 }, text = "N", font = "Helvetica-Bold", textColor = { 153, 153, 153, 255 }, size = 16, align = "left" } local dial = display.newImage("compass_dial.png", 40, 150) local background = display.newImage("compass_bkg.png") local compassMode = "geo" local showGeo = function( event ) print("geo") headingGeo:setTextColor( 35, 170, 255, 255 ) directionGeo:setTextColor( 35, 170, 255, 255 ) headingMag:setTextColor( 153, 153, 153, 255 ) directionMag:setTextColor( 153, 153, 153, 255 ) compassMode = "geo" end local showMag = function( event ) print("mag") headingGeo:setTextColor( 153, 153, 153, 255 ) directionGeo:setTextColor( 153, 153, 153, 255 ) headingMag:setTextColor( 35, 170, 255, 255 ) directionMag:setTextColor( 35, 170, 255, 255 ) compassMode = "mag" end -- Add touch events to textfields (for switching between geographic/magnetic display modes) headingGeo:addEventListener( "touch", showGeo ) headingMag:addEventListener( "touch", showMag ) local directionForAngle = function( angle ) local text if ( angle <= 22 or angle > 337 ) then text = "N" elseif ( angle > 22 and angle <= 67 ) then text = "NE" elseif ( angle > 67 and angle <= 112 ) then text = "E" elseif ( angle > 112 and angle <= 157 ) then text = "SE" elseif ( angle > 157 and angle <= 202 ) then text = "S" elseif ( angle > 202 and angle <= 247 ) then text = "SW" elseif ( angle > 247 and angle <= 292 ) then text = "W" elseif ( angle > 292 and angle <= 337 ) then text = "NW" end return text end local dstRotation = 0 local updateCompass = function( event ) local angleMag, angleGeo -- Note: "magnetic" = magnetic north heading, and "geographic" = "true north" heading as seen on a map -- (The variance between these heading values depends on your position on the Earth) angleMag = event.magnetic -- Android does not support geographic headings, so we use magnetic headings for Android builds if system.getInfo( "platformName" ) ~= "Android" then angleGeo = event.geographic else angleGeo = angleMag end if ( "geo" == compassMode ) then dstRotation = -angleGeo else dstRotation = -angleMag end -- Format strings as whole numbers local valueGeo = string.format( '%.0f', angleGeo ) local valueMag = string.format( '%.0f', angleMag ) headingGeo:setText( valueGeo .. "°" ) directionGeo:setText( directionForAngle( angleGeo ) ) headingMag:setText( valueMag .. "°" ) directionMag:setText( directionForAngle( angleMag ) ) end local animateDial = function( event ) local curRotation = dial.rotation local delta = dstRotation - curRotation if math.abs( delta ) >= 180 then if delta < -180 then delta = delta + 360 elseif delta > 180 then delta = delta - 360 end end dial.rotation = curRotation + delta*0.3 end local didInitGPS = false local initGPS = function( event ) if ( not didInitGPS ) then didInitGPS = true -- We only need a single location event to calibrate "true north", then we can turn off GPS again local initDone = function( event ) Runtime:removeEventListener( "location", initGPS ) end -- Delay removal to let the hardware activate timer.performWithDelay( 1000, initDone ) end end -- Determine if running on Corona Simulator -- local isSimulator = "simulator" == system.getInfo("environment") -- Heading Events are not supported on Simulator -- if isSimulator then msg = display.newText( "Heading events not supported on Simulator!", 0, 20, "Verdana-Bold", 12 ) msg.x = display.contentWidth/2 -- center title msg:setTextColor( 255,255,0 ) end -- Location event listener if system.getInfo( "platformName" ) ~= "Android" then Runtime:addEventListener( "location", initGPS ) end -- This is not required if you only want the heading relative to magnetic north, but to calculate -- your "true north" offset, the iPhone needs at least one location reading. Location may already -- be cached by the OS, but if not, then geographic north heading defaults to "-1". -- Again, this is not required for Android, since Android does not support true north headings. -- Compass event listener Runtime:addEventListener( "heading", updateCompass ) -- Adaptive tweening to smooth the dial animation Runtime:addEventListener( "enterFrame", animateDial ) |