skip to Main Content

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
}

2

Answers


  1. Chosen as BEST ANSWER

    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)
            }
    

  2. The main issue is that there is no layer created. create a layer (with a tileset) and there should be no errors.

    btw.: the arrow functions and the this scopes are in this specific case (phaser development) correct.

    Mini Example that solves the issue:
    (I might update it to make it look better)
    Just click the white square. and check the Browser console

    document.body.style = 'margin:0;';
    console.clear();
    
    class MainScene extends Phaser.Scene{
        create () {
            this.add.text(10,10, 'DEMO TEXT')
            const tileHeight = 10
            const tilesPerRow = 3
            
            // just for the demo -- START
            let graphics  = this.make.graphics();
            graphics.fillStyle(0xffffff);
            graphics.fillRect(0, 0, 100, 100);
            graphics.generateTexture('tileset', 100, 100);
            // just for the demo -- END        
            
            if(!this.map){
                this.map = this.make.tilemap({ 
                    tileWidth: tileHeight, 
                    tileHeight: tileHeight,
                    width: config.width,
                    height: config.height
                })  
                
                const tileset = this.map.addTilesetImage('tileset', null, 10, 10);
                this.layer = this.map.createBlankLayer('layer1', tileset);
            }
            
            for (let i = 0; i < 9 ; i++) {
                const x = ((i % tilesPerRow) * tileHeight)
                const y = (Math.floor(i / tilesPerRow) * tileHeight)
        
                // just for the demo
                graphics.generateTexture('tile (' + i + ')', 10, 10);
                
                this.tile = this.add.image(x, y, 'tile (' + i + ')')
                this.tile.setOrigin(0)
                this.tile.setScale(10, 10)
            }
        
            // 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 && (/tile (/).test(child.texture.key))
                tiles.forEach((tile, i) => {
                    tile.setInteractive()
                    tile.on('pointerdown', () => {
                        this.tileIndex = i
                        this.tilePicked = true
                        tile.setTint(0xff0000)
                        console.log('Selected tile index:', this.tileIndex)
                        this.setupPointerEvents()
                    })
                })
            } else {
                this.input.on('pointerdown', (pointer) => {
                    const tileX = Math.floor(pointer.x / 10)
                    const tileY = Math.floor(pointer.y / 10)
                    this.placeTile(tileX, tileY)
                })
            }
        }
        
        placeTile(tileX, tileY) {
            console.info('tileplaced')
            this.map.putTileAt(this.tileIndex, tileX, tileY, this.layer) 
        }
    }
    
    var config = {
        width: 536,
        height: 183,
        scene: MainScene
    }; 
    
    
    
    new Phaser.Game(config);
    <script src="//cdn.jsdelivr.net/npm/phaser/dist/phaser.min.js"></script>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search