Moth Goo - js1k 2013 entry

I had a lot of fun making this little game for the js1k 2013 spring competition. You play a moth that is flying through the night eating nectar from flowers that fly past you on the way.

The more nectar you eat the more points you get and the higher the level the more flowers become appear.

It is probably not too much fun to try and get the highscore since it is almost impossible to die and you can keep flying through space for ever. The original intention was that you would have to start over if you flew directly into a flower, but the math is a bit off. Try and see if you can do it.

Use the mouse pointer to navigate and any key to fire.

Visit js1k.com to play the game there.

You may have to reload the browser window to start the game as it is a bit buggy. If you see a 0 in the bottom right corner, the game loaded correctly.

Source Code

Here is the original source code.


//#Helpers
function pp() {
    console.warn.apply(console, [].slice.call(arguments));
}
//#end
// a = canvas context with id c
// b = document.body
// c = canvas element
bodies = [Random = Math.random,a.l = a.lineTo,
          a.f = a.fillText,
          number27=27,
          enemyIndex = c.height = c.width = defaultDepth = WidthAndHeight = 640,
          crossHairY = pointerY = pointerX = WidthAndHeight,
          WidthAndHeightSquared = WidthAndHeight*WidthAndHeight,
          bodiesMax = 4795,
          starIndex =  928,
          enemy = time = tmpVar = points = shot = b.bgColor = 0,
          fontString = 'px Arial',sprites = '❈❊❋❇✽✾❃✥❄❆✿❀✵❁7EC9BDA' + bodiesMax]

setInterval(onkeypress = onmousemove = function (Event) {
    Index = bodiesMax
    // Fire shot on keypress
    if (Event)
            shot = Event.keyCode ? 3 : (
                                     pointerX = Event.clientX,
                                     pointerY = Event.clientY, shot
                                   )
    // Game loop
    else if (time > 0) {
        a.clearRect(0, 0, WidthAndHeight, WidthAndHeight)
        while (Index --) {
            // Star movement
            elem = bodies[Index]
            posZ = elem.posZ -= 1 + time / starIndex
            size = (1 - posZ / defaultDepth) * 8
            // skew value
            tmpVar = Math.log(posZ)
            tmpVar /= posZ / 1 + (1 - 1/time)
            posY = elem.posY += (elem.posY - pointerY) * tmpVar
            posX = elem.posX += (elem.posX - pointerX) * tmpVar
            // color index
            tmpVar = 14 + Index % 8
            a.fillStyle = '#' + sprites.slice(tmpVar, tmpVar+3)

            if (posX*posX > WidthAndHeightSquared
                | posY*posY > WidthAndHeightSquared
                | elem.hit < 0
                | !posZ
              )
                elem.posX = Random() * WidthAndHeight  | 0,
                elem.posY = Random() * WidthAndHeight | 0,
                elem.posZ = defaultDepth,
                elem.type =  time / number27 | 0,
                enemyIndex = 3*time / defaultDepth

            // A hit by a star or an enemy, we die
            if (posX < WidthAndHeight && posY < WidthAndHeight && posZ < 2)
               a.font = number27 + fontString,
               a.f('BAM', posX - 79, posY + number27),
               time = - 99

            // Draw star
            if (Index < starIndex)
                a.fillRect(posX, posY, size, size)

            // enemy
            enemy = sprites[Index%14]
            if (time > defaultDepth & Index < enemyIndex) {
                (elem.hit -- > 0) ?
                  (
                    a.font = (1 - posZ/defaultDepth)*size*150 + fontString,
                    enemy = sprites[1+Index%13],
                    elem.type = 0
                  ) : elem.hit = 0

                enemySize = size* number27
                enemySizeSquare = enemySize*enemySize
                a.font = enemySize + fontString

                if (!elem.hit | elem.hit >= 0)
                    a.f(enemy, posX, posY)
                // enemy hit?
                dX = posX - pointerX
                dY = posY - crossHairY
                if (!shot & elem.hit <= 0
                        & (dX*dX < enemySizeSquare)
                        & (dY*dY < enemySizeSquare))
                    points += 1 + elem.type,  // TODO Use enemyIndex
                    elem.hit = 5*number27

            }
        }
        // mouseDistance
        posX = .7 - pointerY / WidthAndHeight
        crossHairY = pointerY - posX * 180
        posX = .7 * WidthAndHeight + (.5 * WidthAndHeight * posX)
        shotTriangle=[0, posX, WidthAndHeight, posX]
        if (shot -- > 0)
            for (IndexN=0; IndexN<4; IndexN++)
                with (a)
                    moveTo(shotTriangle[IndexN], shotTriangle[IndexN+1]),
                    beginPath(),
                    l(pointerX, crossHairY),
                    l(shotTriangle[IndexN], posX + 9),
                    l(shotTriangle[IndexN], shotTriangle[++IndexN]),
                    fill()
        a.font = number27 + fontString
        a.f(points, WidthAndHeight-120, WidthAndHeight - number27)

    } else
        while(Index --)
            bodies[Index] = {},
            points = 0

        if (time ++)
            starIndex += time/number27

}, number27)