0

I'm working on a Kaboom JS project, which was working fine, until now that an error box pops up with "n is not a function".

I have no function called n, no function is being called, and the only edit I made in between when it worked and when it didn't was when I changed some popup text. There are no errors I can see, and no errors Replit is pointing out, either.

import kaboom from "kaboom"

// initialize context
kaboom({ background: [189, 196, 84] })

// load assets
loadSprite("avivo", "sprites/avivo.png")
loadSprite("ghosty", "sprites/ghosty.png")
loadSprite("spike", "sprites/spike.png")
loadSprite("grass", "sprites/grass.png")
loadSprite("prize", "sprites/jumpy.png")
loadSprite("apple", "sprites/apple.png")
loadSprite("portal", "sprites/portal.png")
loadSprite("coin", "sprites/coin.png")
loadSprite("gate", "sprites/gateClosed.png")
loadSound("coin", "sounds/score.mp3")
loadSound("powerup", "sounds/powerup.mp3")
loadSound("blip", "sounds/blip.mp3")
loadSound("hit", "sounds/hit.mp3")
loadSound("portal", "sounds/portal.mp3")

// define some constants
const JUMP_FORCE = 1500
const MOVE_SPEED = 480
const FALL_DEATH = 2400

layers([
    "game",
    "ui",
], "game")
          
const LEVELS = [
    [
        "  ===========                  ",
        "         ====                  ",
        "         ====                  ",
        "===      ====                  ",
        "==       ====                  ",
        "==        ===                  ",
        "==         ==    $   ==        ",
        "==                   ==   $  ===",
        "==         $         ==      ===",
        "==     ^^  $     >   ==     @===",
        "================================",
    ],
    [
        "     $         $           ",
        "     $         $           ",
        "                           ",
        "       ======              ",
        "       ======              ",
        "       ======             @",
        "       ======              ",
        "     > =======^^    >   ^^^",
        "===========================",
    ],
    [
        "                           ",
        "                           ",
        "                           ",
        "       =====               ",
        "       =====               ",
        "       =====               ",
        "                           ",
        " $    > | @     ^^^   $$   ",
        "===========================",
    ],
    [
        "                                ",
        "                                ",
        "                                ",
        "                                ",
        "                                ",
        "                                ",
        "                                ",
        "                                ",
        "                 ==             ",
        "                X==            @",
        "================================",
    ],
    [
                "                                ",
        "                                ",
        "                                ",
        "                                ",
        "                                ",
        "==                              ",
        "==                              ",
        "==                  ==        ==",
        "==            ====            ==",
        "==     ^^    >====  ^         >==",
        "================================", 
    ],
]

// define what each symbol means in the level graph
const levelConf = {
    // grid size
    width: 64,
    height: 64,
    // define each object as a list of components
    "=": () => [
        sprite("grass"),
        area(),
        solid(),
        origin("bot"),
        "block",
    ],
    "$": () => [
        sprite("coin"),
        area(),
        pos(0, -9),
        origin("bot"),
        "coin",
    ],
    "%": () => [
        sprite("prize"),
        area(),
        solid(),
        origin("bot"),
        "prize",
    ],
    "^": () => [
        sprite("spike"),
        area(),
        solid(),
        origin("bot"),
        "danger",
    ],
    "#": () => [
        sprite("apple"),
        area(),
        origin("bot"),
        body(),
        "apple",
    ],
    ">": () => [
        sprite("ghosty"),
        area(),
        origin("bot"),
        body(),
        patrol(),
        "enemy",
    ],
    "@": () => [
        sprite("portal"),
        area({ scale: 0.5, }),
        origin("bot"),
        pos(0, -12),
        "portal",
    ],
    "|": () => [
        sprite("gate"),
        area({scale: 0.5, }),
        origin("bot"),
        pos(0, -9),
        "danger",
    ], 
    "X": () => [
        sprite("boss"),
        area({scale: 0.5, }),
        origin("bot"),
        pos(0, 0),
        body(),
        patrol(),
        "enemy",
    ],
    
}

// custom component controlling enemy patrol movement
function patrol(speed = 60, dir = 1) {
    return {
        id: "patrol",
        require: [ "pos", "area", ],
        add() {
            this.on("collide", (obj, col) => {
                if (col.isLeft() || col.isRight()) {
                    dir = -dir
                }
            })
        },
        update() {
            this.move(speed * dir, 0)
        },
    }
}

// custom component that makes stuff grow big
function big() {
    let timer = 0
    let isBig = false
    let destScale = 1
    return {
        // component id / name
        id: "big",
        // it requires the scale component
        require: [ "scale" ],
        // this runs every frame
        update() {
            if (isBig) {
                timer -= dt()
                if (timer <= 0) {
                    this.smallify()
                }
            }
            this.scale = this.scale.lerp(vec2(destScale), dt() * 6)
        },
        // custom methods
        isBig() {
            return isBig
        },
        smallify() {
            destScale = 1
            timer = 0
            isBig = false
        },
        biggify(time) {
            destScale = 2
            timer = time
            isBig = true
        },
    }
}

scene("game", ({ levelId, coins } = { levelId: 0, coins: 0 }) => {

    gravity(3200)

    // add level to scene
    const level = addLevel(LEVELS[levelId ?? 0], levelConf)

    // define player object
    const player = add([
        sprite("avivo"),
        pos(0, 0),
        area(),
        scale(1),
        // makes it fall to gravity and jumpable
        body(),
        // the custom component we defined above
        big(),
        origin("bot"),
    ])

    // action() runs every frame
    player.onUpdate(() => {
        // center camera to player
        camPos(player.pos)
        // check fall death
        if (player.pos.y >= FALL_DEATH) {
            go("lose")
        }
    })

    // if player onCollide with any obj with "danger" tag, lose
    player.onCollide("danger", () => {
        go("lose")
        play("hit")
    })

    player.onCollide("portal", () => {
        play("portal")
        if (levelId + 1 < LEVELS.length) {
            go("game", {
                levelId: levelId + 1,
                coins: coins,
            })
        } else {
            go("win")
        }
    })

    player.onGround((l) => {
        if (l.is("enemy")) {
            player.jump(JUMP_FORCE * 1.15)
            destroy(l)
            addKaboom(player.pos)
            play("powerup")
        }
    })

    player.onCollide("enemy", (e, col) => {
        // if it's not from the top, die
        if (!col.isBottom()) {
            go("lose")
            play("hit")
        }
    })

    let hasApple = false

    // grow an apple if player's head bumps into an obj with "prize" tag
    player.onHeadbutt((obj) => {
        if (obj.is("prize") && !hasApple) {
            const apple = level.spawn("#", obj.gridPos.sub(0, 1))
            apple.jump()
            hasApple = true
            play("blip")
        }
    })

    // player grows big onCollide with an "apple" obj
    player.onCollide("apple", (a) => {
        destroy(a)
        // as we defined in the big() component
        player.biggify(3)
        hasApple = false
        play("powerup")
    })

    let coinPitch = 0

    onUpdate(() => {
        if (coinPitch > 0) {
            coinPitch = Math.max(0, coinPitch - dt() * 100)
        }
    })

    player.onCollide("coin", (c) => {
        destroy(c)
        play("coin", {
            detune: coinPitch,
        })
        coinPitch += 100
        coins += 1
        coinsLabel.text = coins
    })

    const coinsLabel = add([
        text(coins),
        pos(24, 24),
        fixed(),
    ])

    // jump with space
    onKeyPress("w", "up", () => {
        // these 2 functions are provided by body() component
        if (player.isGrounded()) {
            player.jump(JUMP_FORCE)
        }
    })

    onKeyDown("a", "left", () => {
        player.move(-MOVE_SPEED, 0)
    })

    onKeyDown("d", "right", () => {
        player.move(MOVE_SPEED, 0)
    })

    onKeyDown("z", () => {
        player.move(MOVE_SPEED, 5)
    })

    onKeyPress("s", "down", () => {
        player.weight = 3
    })

    onKeyRelease("s", "down", () => {
        player.weight = 1
    })

    onKeyPress("f", () => {
        fullscreen(!fullscreen())
    })

})

scene("lose", () => {
    add([
        text("Game Over"),
    ])
    onKeyPress(() => go("game"))
})

scene("win", () => {
    add([
        text("You passed"),
    ])
    onKeyPress(() => go("game"))
})

go("game")

I know it's a dumb problem, but stackoverflow is the only place I can get onto with my school computer (my only computer) and with the unnecessary filtering the admins do, Google searches have been very unhelpful.

I used Replit's version history to go back to before the error occurred, but it still did. I've completely redone my entire program, and this is still happening.

If you want to see what exactly this error is, just try moving the character with WASD on my Repl: https://dystation.aidankierstead.repl.co/ and the error message pops up.

OhNoItsA8
  • 58
  • 5
  • That error is coming from wrongly using that `kaboom` library, but I've never used so I don't know anything about it. But, your code has a function `addKaboom` and is not defined anywhere which tells me you have more codes which you have not shown. Also check their documentations. – Aleksandar Apr 27 '23 at 01:44
  • I believe that addKaboom() is built in to the kaboom library, thank you, though. – OhNoItsA8 Apr 27 '23 at 12:35

1 Answers1

1

Your problem appears to be the second (of three) argument (e.g., "left", "right", etc) in the call to the functions onKeyPress and onKeyDown; those functions take only two arguments, see the docs onKeyPress and onKeyDown, the key and the function to be called when the event occurs. (Actually, onKeyPress can be called with just one argument, the handler, but that's not relevant).

The program complains that the second argument is not a function. The name n is most likely the name of the formal argument to the function; you get the same error from this simple erroneous snippet:

function onKeyDown(key, n){
  //......
  n();
}

onKeyDown("a", "left", ()=>['run']);
kikon
  • 3,670
  • 3
  • 5
  • 20