Plane Crazy

-- Misc 

function newGame()
    spinTimer = 0
    soundTimer = 0
    timer = 200
    crashed = false
    east = 0
    north = 250
    heading = 0
    roll = 0
    pitch = 0
    speed = 0
    gas = 50
    altimeter.val = 0
    flightTimer.val = 0
end

function createMapElements()
    local i
    trees.texture ="Planet Cute:Tree Short"
    trees2.texture ="Planet Cute:Tree Ugly"
    trees.setColors(255,255,255,255)
    mud.texture = "Small World:Dirt Patch"
    bushes.texture = "Small World:Bush"
    rocks.texture = "Tyrian Remastered:Rock 3"

    for i = 1, 2000 do
        bushes:addRect(math.random(20000) - 10000,
        math.random(9800) - 10000, 32, 27)
    end
    for i = 1, 500 do
        mud:addRect(math.random(20000) - 10000,
        math.random(4000) - 10000, 130, 100)
    end
  
    for i = 1, 1000 do
        trees:addRect(math.random(10000) - 10200,
        math.random(5800), 100, 171)
        trees:addRect(math.random(10000) + 200,
        math.random(5800), 100, 171)
    end
    for i = 1, 1500 do
        trees2:addRect(math.random(20000) - 10000,
        math.random(4000) + 5600 , 100, 171)
    end
    
    i =0
   
    for x = 1, 100 do
        for y = 1, 100 do
            ground:addRect(x*500 - 25000,y*500-25000,500,500)
            i = i + 1
            if y < 48 and y > 40 then
                ground:setRectColor(i, 88+math.random(64), 
                154+math.random(64),  33)
            elseif y <= 40 then
                ground:setRectColor(i, 144+math.random(64), 
                144+math.random(64),  33)
            elseif y == 70 then 
                ground:setRectColor(i, 155+math.random(64), 
                154+math.random(55),  122)
            elseif y > 70 then
                ground:setRectColor(i, 22, 22,  155+math.random(55))
            elseif x < 20 and y < 30 then
                ground:setRectColor(i, 100, 100 + math.random(40), 
                30, 255)
            elseif x > 50 and y < 15 then
                ground:setRectColor(i, 22, 22,  155+math.random(55))
            else
                ground:setRectColor(i, 22, 166+math.random(55),22)
            end
        end
    end
    
    for x = 1, 100 do
        y = 50 + math.random(2) - 1
        ground:setRectColor(5000 + i, 22, 22, 151+math.random(55))
    end

    runway = mesh()
    runway:addRect(0,0,200,2000)
    runway:setRectColor(1, 122, 122, 122)
end

function newTarget(i)
    local z
    z = math.floor(math.random(3) + 1) * 500
    target[i] = vec3( math.random(20000) - 10000, 
    math.random(20000) - 10000, z)
end

function calcPosition()
    -- direction
    if speedo.val > 10 then
        heading = heading + horizon.roll / 100
        if heading < 0 then heading = heading + 360 end
        if heading > 360 then heading = heading - 360 end
    end
    -- position
    north = north - math.cos(math.rad(heading)) * speedo.val/20
    if north > 25000 then north = -25000 
    elseif north < -25000 then north = 25000 end
    east = east - math.sin(math.rad(heading)) * speedo.val/20
    if east > 25000 then east = -25000 
    elseif east < -25000 then east = 25000 end
    -- altitude
    altimeter.val = altimeter.val - 0.1
    altimeter.val = altimeter.val - math.abs(horizon.roll) / 50
    altimeter.val = altimeter.val + (horizon.pitch * -speedo.val / 60)
    if speedo.val + horizon.pitch * 100 < 60 then
        stall= true
        if altimeter.val > 0 then
            altimeter.val = altimeter.val - 1
            spinTimer = spinTimer + 10
            sound(SOUND_JUMP, 40113)
        end
    else
        stall = false
        spinTimer = 0
    end
    if altimeter.val <= 0 then
        -- on ground
        -- check for landing / crash
        altimeter.val = 0
        if east < -200 or east > 200 or north > 2300 
        or north < -1300 then
            --big crash
            crashed = true
            timer = 0
            speedo.val = 0
            sound(SOUND_EXPLODE, 18933)
            status = 1
        else
        -- on runway
            if horizon.pitch < 0 then 
                speedo.val = speedo.val - 1 
                fontSize(22)
                text("Brakes Applied. Tilt forward to release.", 
                WIDTH / 2, 320)
            end
        end
    else
        -- in air
        speedo.val = speedo.val + horizon.pitch * 2
    end
    -- speed
    if timer > 0 then
        speedo.val = speedo.val + throttle.val / 100 
    else
        fontSize(22)
        text("Out of gas.", WIDTH / 2, 320)
    end
    
    if speedo.val < 0 then speedo.val=0 end
    if speedo.val > 222 then speedo.val = 220 end
    -- fuel
    timer = timer - throttle.val * 0.001
    if timer < 0 then timer = 0 end
    -- sound
    if timer > 0 and soundTimer + 0.1 < ElapsedTime then
        if throttle.val > 30 then
            sound(DATA, 
            "ZgNAFAA6Pz05PDxCIsyOvCq8qT4jd5g+JAA7fz9EREFCOz5F")
        elseif throttle.val > 0 then
            sound(DATA, 
            "ZgNAFw06Ozs5Pj5FmteWPa+b2j419Z8+JAA4f0FER0VCOz1I")
        end
        soundTimer = ElapsedTime
    end
    -- timer
    pushStyle()
    fill(165, 207, 223, 99)
    fontSize(96)
    textAlign(LEFT)
    textMode(CORNER)
    text(math.floor(timer), 20, 300)
    fill(223, 138, 138, 185)
    textMode(CENTER)
    textAlign(CENTER)
    font("MarkerFelt-Wide")
    if stall and altimeter.val > 10 then
        text("Stall Warning", WIDTH / 2, HEIGHT / 2)
    end
    popStyle()
end


Deleted – see new version below

-- Misc2
function showInstructions()
    local i
    pushStyle()
    fill(46, 45, 25, 255)
    rect(10, 315, WIDTH - 20, HEIGHT - 330)
    fill(219, 219, 219, 255)
    rect(20, 320, WIDTH - 40, HEIGHT - 340)
    stroke(67, 67, 67, 255)
    line(WIDTH / 2, 330, WIDTH / 2, HEIGHT - 50)
    textAlign(LEFT)
    textMode(CORNER)
    fontSize(24)
    fill(0, 0, 0, 255)
    font("HelveticaNeue-Bold")
    text("Log Book", 30, HEIGHT - 50)
    fill(23, 50, 167, 255)
    font("Noteworthy-Light")
    strokeWidth(1)
    for i = 1, 14 do
        line(40, HEIGHT - i * 43 - 50, 
        WIDTH / 2 - 10, HEIGHT - i * 43 - 50)
        line(WIDTH / 2 + 10, HEIGHT - i * 43 - 50, 
        WIDTH - 40, HEIGHT - i * 43 - 50)
    end
    fontSize(24 * WIDTH / 768)
    textWrapWidth(330 * WIDTH / 768)
    text("1. Tilt device left and right to change direction.", 
    40, HEIGHT - 142)
    text("2. Tilt device forward to dive and back to climb.", 
    40, HEIGHT - 227)
    text("3. Hold device flat for level flight.", 
    40, HEIGHT - 273)
    text("4. Tilt forward to release brakes on runway.", 
    40, HEIGHT - 355)
    text("5. If you try to climb too quickly you will"..
    " lose speed and stall.", 40, HEIGHT - 442)
    text("6. To recover from a stall tilt forward "..
    " and gain speed.", 40, HEIGHT - 528)
    text("7. It takes more power to hold altitude during "..
    " steeply banked turns.", 40, HEIGHT - 652)
    text("8. When the timer runs down, you're out of fuel. "..
    " ", WIDTH / 2 + 10, HEIGHT - 142)
    text("9. Fly to targets to get extra fuel. "..
    " ", WIDTH / 2 + 10, HEIGHT - 186)
    text("10. Smaller targets give more fuel. "..
    " ", WIDTH / 2 + 10, HEIGHT - 229)
    text("11. Ease off on the throttle to save fuel. "..
    " ", WIDTH / 2 + 10, HEIGHT - 315)
    text("12. Good luck!"..
    " ", WIDTH / 2 + 10, HEIGHT - 357)
    text("     Turn on control of throttle by acceleration. "..
    " Warning! Requires a lot of space and willingness"..
    " to look like an idiot.", WIDTH / 2 + 10, HEIGHT - 560)
    text("(c) 2012 by Mark Sumner"..
    " ", WIDTH / 2 + 60, HEIGHT - 659)
    stroke(0, 0, 0, 255)
    strokeWidth(2)
    fill(219, 219, 219, 255)
    accelFrame:draw()
    strokeWidth(5)
    stroke(31, 179, 22, 255)
    if accelMode then
        line(accelFrame.left, accelFrame:midY(), 
        accelFrame:midX(), accelFrame.bottom)
        line(accelFrame.right, accelFrame.top,
        accelFrame:midX(), accelFrame.bottom)
    end
    popStyle()
end

For what it’s worth, my record flight time is 630, but I expect it’s possible to keep flying nearly infinitely if you manage your fuel and build up altitude when possible.

Have fun.

Thank you. You always make incredible things.

I already pasted the code but I got an error at line 79 in main program about “compare number with nil”.

78   i = readLocalData("PlaneCrazyBest")
79      if i >0 then

To solve the error, I mark the line 78 as comment and it works.

78   --i = readLocalData("PlaneCrazyBest")

EDIT: Another solution by not marking as a comment in order to read the highest score

     i = readLocalData("PlaneCrazyBest") or 0

I’m definitely going to try this one out. After working on my shape explorer, I had the idea of using the iPad itself as a control device, measuring the pitch and yaw, but I got too busy to pursue the idea. So I’m excited to see someone’s done it.

oh wow! i cant find my answer in the code so… a very bisic question @mark :

how do you basicly do the map-drawings (not the little map, the big map where the plane is drawn on)? by drawing simply everything and translating it by the plane position? or are the out-of-screen-elements not drawn? I am interested in this me because i tried something comparable…

@sanit – thanks. I inserted that line for reading the high score, then never went back to test what happened if it wasn’t there.

@Maxiking16 – I’m using meshes, with rotate, translante, and scale (although I think scale is commeted out in this version) to adjust to the plane’s position. The big map itself is actually a stack of meshes – one for the square “ground” rects, one for the tree textures. one for runways. Then on top of that are some features drawn with primitives, like the details on the runway. Then there’s the plane, which is actually not quite at the center of rotation because I wanted to give you more space to see “ahead” than you’d get with the plane at the center of the screen. And the sprite for the plane itself is rotated 180 degrees. So I frequently get lost in mental fog thinking “okay, so the plane is heading north northeast. Now… what do I do with the meshes, and why is the mini map upside down?” I can tell you that, compared to iterating through arrays of sprites or primitives, meshes draw MUCH faster.

@Andrew_Stacey You should see the original test. Not only did I use the iPad for pitch and yaw, I used acceleration for the throttle. So to make the plane go faster you had to actually get up and move, and if you slowed down the plane slowed down. I may put a switch in there to turn that feature back on, but it does make it hard to play the game without an open space the size of a football field.

Please do, I love the acceleration idea :slight_smile:




Speedometer = class()

function Speedometer:init(x, y, r)
    self.x = x
    self.y = y
    self.r = r
    self.val = 0
end

function Speedometer:draw()
    local x, y, r, s
    x = self.x
    y = self.y
    r = self.r
    if self.val > 270 then self.val = 270 end
    font("ArialMT")
    pushMatrix()
    pushStyle()
    translate(x, y)
    fill(61, 61, 61, 255)
    stroke(84, 84, 84, 255)
    rect(-r/2-5, -r/2-5, r+10, r+10)
    fill(19, 19, 19, 255)
    ellipse(-r/2+5, -r/2+5, 10)
    ellipse(-r/2+5, r/2-5, 10)
    ellipse(r/2-5, -r/2+5, 10)
    ellipse(r/2-5, r/2-5, 10)
    strokeWidth(3)
    fill(176, 176, 176, 255)
    stroke(219, 191, 149, 255)
    ellipse(0, 0, r)
    stroke(141, 139, 139, 255)
    ellipse(0,0,r-10)
    
    stroke(0, 0, 0, 255)
    noFill()
    strokeWidth(19)
    ellipse(0,0,r-50)
    stroke(248, 248, 248, 255)
    strokeWidth(13)
    ellipse(0,0,r-55)
    noStroke()
    fill(176, 176, 176, 255)
    if r > 160 then
    rect(-r/2+20,0,40,40)
    rect(-40,r/2-60,40,40)
    rect(-50,15,40,40)
    end
    stroke(0, 0, 0, 255)
    strokeWidth(1)
    rotate(180)
    fontSize(9)
    fill(0, 0, 0, 255)
    for i=0,27 do
        line(r/2-37,0,r/2-30,0)
        rotate(10)
        if i/2 == math.floor(i/2) then
        s = 260 - i * 10
        text(s, r/2-15, 0)
        end
    end
    rotate(-10)
    -- set needle
    rotate(-self.val)
    stroke(255, 0, 0, 255)
    strokeWidth(5)
    line(0,0,r/3,0)
    stroke(82, 82, 82, 255)
    strokeWidth(3)
    fill(90, 90, 90, 255)
    stroke(219, 191, 149, 255)
    ellipse(0, 0, 25)
    stroke(141, 139, 139, 255)
    ellipse(0,0,20)
    fill(0, 0, 0, 255)
    font("ArialMT")
    fontSize(12)
    popMatrix()
    text("Speed", self.x, self.y - 20)
    popStyle()
    
end
Throttle = class()

function Throttle:init(l, b, r, t)
    -- you can accept and set parameters here
    self.x = x
    self.frame = Frame(l, b, r, t)
    self.val = 0
end

function Throttle:draw()
    local dy, vy
    noStroke()
    self.frame:gloss( color(155, 155, 155, 255))
    pushMatrix()
    pushStyle()
    translate(self.frame.left, self.frame.bottom)
    
    -- base
    strokeWidth(3)
    stroke(127, 127, 127, 255)
    fill(92, 92, 92, 255)
    rect(0, self.frame:height() - 40, self.frame:width(), 40)
    stroke(167, 40, 23, 255)
    line(20, 20, self.frame:width() - 20, 20)
    stroke(35, 35, 35, 255)
    line(20, self.frame:height() / 2 , 
    50, self.frame:height() / 2)
    line(20, self.frame:height() / 2 + 20, 
    50, self.frame:height() /2 + 20)
    line(20, self.frame:height() / 2 - 20, 
    50, self.frame:height() /2 - 20)
    -- axis
    vy = 100 / (self.frame:height() - 40)
    dy = self.val / vy + 40
    noStroke()
    fill(51, 51, 51, 255)
    rect(self.frame:width()/2 - 15, self.frame:height()-40- dy, 5, dy)
    fill(127, 127, 127, 255)
    rect(self.frame:width()/2 - 10, self.frame:height()-40- dy, 10, dy)
    fill(165, 165, 165, 255)
    rect(self.frame:width()/2 - 0, self.frame:height()-40- dy, 15, dy)
    fill(78, 31, 31, 255)
    strokeWidth(1)
    
    rect(self.frame:width()/2-35, self.frame:height()-40- dy + 15,
     70, 20)
    fill(43, 43, 43, 255)
    rect(self.frame:width()/2-25, self.frame:height()-40- dy + 5,
     50, 10)
    rect(self.frame:width()/2-25, self.frame:height()-40- dy + 35,
     50, 10)
    -- knob
    
    fontSize(14)
    fill(0, 0, 0, 255)
    text("Throttle", self.frame:width()/2, self.frame:height() - 20)
    line(2, self.frame:height()-vy * 50 , 20,
    self.frame:height()-vy * 50)
    popStyle()
    popMatrix()
end

function Throttle:touched(t)
    local dy, vy
    if self.frame:touched(t) then
        dy = self.frame.top - 80 - t.y
        vy = 100 / (self.frame:height() - 40)
        self.val = dy * vy
    end
    if self.val < 0 then self.val = 0 end
end

My apologies on the length. I’m certain others here could have done it not just better, but more neatly and elegantly. But my coding style really hasn’t changed since the invention of rocks.

@Mark - Thanks for the code! And by the way, your coding style isn’t too bad. It’s good enough that I can almost tell what it does without running it.

Will you add an objetive or mission? I like all those control and the ground flow, good job, congrats!

@jaurix originally I had several runways and had all the plane’s trips require landing and stopping at those locations. But it was just too tough for starting off. Landing the plane successfully takes too much practice.

So I created the “fly to a target” bit as a warm up exercise. Then I… ran out of time.

I hope no one minds me digging up old projects and making zips of them.

There seems to be a problem with gameplay that I can’t solve: I have to tilt forward to turn the brakes off, but I can’t achieve liftoff without tilting upward, and any time I tilt upward the brakes turn on again!

It doesn’t seem from the above comments like this is how it’s supposed to run; can anyone spot what’s wrong in the code?

@UberGoober Thanks for consolidating these, it’s a very noble task :smile:
Tapping on the ‘Pilot’s Log’ it seemed to imply that the brake stuff was intended. I managed to get off the ground for all of about 5 seconds before I stalled at least :lol:

I’m happy to say I’ve also added this to codea-community-repo and can now be downloaded and run via the WebRepo project.

How did you get it off the ground? You have to tip the pad down or else the brakes activate but you have to tip the pad up to achieve liftoff. It’s an unsolvable riddle, like why people make fruitcake!

I can do it if I increase the throttle, tilt forward to release the breaks and then tilt back as I reach the end of the runway. Seems to work like that.

@Steppers that did it!