javascriptphaser-frameworkphaserjs

TypeError: Cannot read properties of undefined (reading 'width')


I am trying to make my own world editor in Javascript. I am using a folder of individual tiles and placing them on screen. Then when you press on the tile you basically choose it. That works, but when the pointerdown switches from tile picking to tile placing I get this error.

I have checked if everything is defined but I might be missing something

Update: I have changed the arrow functions to use normal ones but it still doesnt work and gives the same error and am now providing the whole file code

i have encountered this console.log(this.map) VM10362:1 undefined undefined

These are the errors aka stack trace i think

this is my code

class WorldEditor extends Phaser.Scene {
    constructor() {
        super("editWorld")
        this.tileSize = 48
        this.tileIndex = 0
        this.tileFolder = 'Assets/Tiles/'
        this.tilesPerRow = 37
        this.totalTiles = 160
        this.tilePicked = false
    }

    preload() {
        // Load tile images from the folder
        for (let i = 0; i < this.totalTiles; i++) {
            this.load.image('tile (' + i + ')', this.tileFolder + 'tile (' + i + ').png')
        }
    }

    create() {
        const tileWidth = this.tileSize
        const tileHeight = this.tileSize
        const tilesPerRow = this.tilesPerRow
    
        if(!this.map){
            this.map = this.make.tilemap({ 
                tileWidth: this.tileSize, 
                tileHeight: this.tileSize,
                width: 1200,
                height: 720
            })  
        }
        
        for (let i = 0; i < this.totalTiles; i++) {
            const x = ((i % tilesPerRow) * tileWidth)/1.48
            const y = (Math.floor(i / tilesPerRow) * tileHeight)/1.48
    
            this.tile = this.add.image(x, y, 'tile (' + i + ')')
            this.tile.setOrigin(0)
            this.tile.setScale((tileWidth / this.tile.width)/1.48, (tileHeight / this.tile.height)/1.48)
        }
    
        // Set up pointer events
        this.setupPointerEvents()
        
        // Keyboard event to switch back to tile selection
        this.input.keyboard.on('keydown-F', () => {
            this.tilePicked = false
            console.log('Switched back to tile selection')
            this.setupPointerEvents() // Update pointer events after switching back
        })
    }
    
    setupPointerEvents() {
        this.input.off('pointerdown')
    
        if (!this.tilePicked) {
            const tiles = this.children.list.filter(child => child.texture && child.texture.key.startsWith('tile ('))
            tiles.forEach((tile, i) => {
                tile.setInteractive()
                tile.on('pointerdown', function() {
                    this.tileIndex = i
                    this.tilePicked = true
                    tile.setTint(0xff0000)
                    console.log('Selected tile index:', this.tileIndex)
                    this.setupPointerEvents()
                }, this)
            })
        } else {
            this.input.on('pointerdown', function(pointer) {
                this.tileX = Math.floor(pointer.x / this.tileSize)
                this.tileY = Math.floor(pointer.y / this.tileSize)
                this.placeTile(this.tileX, this.tileY)
            }, this)
        }
    }
    // Other methods...
    
    placeTile(tileX, tileY) {
        this.map.putTileAt(this.tileIndex, tileX, tileY) 
    }

    // Implement saveMap and loadMap functions to save and load level data
}


Solution

  • I added a tileset image i dont use and a layer and now it works thank you for all of the help!

    if(!this.map){
                this.map = this.make.tilemap({ 
                    tileWidth: this.tileSize, 
                    tileHeight: this.tileSize,
                    width: 1200,
                    height: 720
                })  
    
                const tileset = this.map.addTilesetImage('tiles', 'tiles', this.tileSize, this.tileSize)
                const groundLayer = this.map.createBlankLayer('groundLayer', tileset)
            }