Jump to content

UI problem using Slick - help!


Nige
 Share

Recommended Posts

So I'm making a pokemon-ish RPG with an inventory screen and a battle screen using Flaxis' SlickUI plugin. I'm running into a strange error:

phaser.min.js:3 Uncaught TypeError: Cannot read property 'camera' of null
    at Roast.i.Component.FixedToCamera.postUpdate (phaser.min.js:3)

'Roast' is a collectible you can put in your inventory. When I use an item on the battle screen, I remove it from the inventory array. Then I rebuild the inventory without the used item - then the first item in the inventory (regardless of which item was used) throws the above error on the next frame.

You can see all my code on GitHub here: https://github.com/niall-slater/cup/tree/master/src, but my ui.js file, as well as my collectable.js, is below (apologies for length).

If you've got any idea what I'm doing wrong your advice would be much appreciated! Cheers.

//collectable.js

class Collectable extends Phaser.Sprite {
	
    constructor(game, x, y) {
        super(game, 0, 0);
		
		this.collected = false;
		//Treat this as an abstract class - do not create anything of class Collectable.
	}
	
	update() {
		
		if (playState.player.isNextTo(this) && !this.collected) {
			this.onCollect();
		}
	}
	
	onCollect() {
		this.collected = true;
		
		playState.world.currentChunk.groupItems.remove(this);
		playState.groupUI.add(this);
		
		playState.player.addToInventory(this);
		
		this.destroy();
	}
}
//ui.js

//UI values
let uiSize = {
	buttonWidth: 128,
	buttonHeight: 32,
	margin: 4,
	panelX: 4,
	panelY: 72,
	panelWidth: 480-8,
	panelHeight: 270-78
};

let style_default = { font: "24px VT323", fill: "#000", wordWrap: "true", wordWrapWidth: 330};
let style_small = { font: "19px VT323", fill: "#333", wordWrap: "true", wordWrapWidth: 330};


var ui = {
	
	inventory: {
		
		items: [],
		displaying: false,
		
		margin: 12,
		padding: 12,
		listStartY: 0,
		entryHeight: 18,
		
		init: function() {
		
			//Create inventory panel
			slickUI.add(ui.inventory.panel = new SlickUI.Element.Panel(this.margin, this.margin, gameWidth - this.margin*2, gameHeight - this.margin*2));

			//Title
			ui.inventory.panel.add(ui.inventory.panel.title = new SlickUI.Element.Text(0, 0, 'INVENTORY', null, style_default)).centerHorizontally();
			
			ui.inventory.panel.alpha = .95;
			ui.inventory.panel.x = this.margin + 256;
			
			for (let i = 0; i < this.items.length; i++) {
				this.addEntryToList(this.items[i]);
			}
		},
		
		//Toggle inventory display
		toggle: function() {
			if (this.displaying) {
				this.hideInventory();
				this.displaying = false;
				
			} else {
				this.showInventory();
				this.displaying = true;
			}
		},
		
		showInventory: function() {
            game.add.tween(ui.inventory.panel).to( {x: ui.inventory.margin}, 500, Phaser.Easing.Exponential.Out, true);

			//Bring UI to top
			game.world.bringToTop(playState.groupUI);
		},
		
		hideInventory: function() {
			
            game.add.tween(ui.inventory.panel).to( {x: 256 + ui.inventory.margin}, 500, Phaser.Easing.Exponential.Out, true);
			
		},
		
		addItem: function(item) {
			
			//itemSprite is the object from the game world, which is a sub-subtype of Phaser.Sprite
			//store the itemSprite in an item object, which will have item.sprite, item.label
			
			this.items.push(item);
			
			this.addEntryToList(item);
			
		},
		
		addEntryToList: function(item) {
			let numItems = this.items.length;
			
			ui.inventory.panel.add(item.icon = new SlickUI.Element.DisplayObject(this.padding, Math.floor(this.listStartY + this.padding * 2 + (numItems * this.entryHeight - 2)), item));
			
			ui.inventory.panel.add(item.label = new SlickUI.Element.Text(Math.floor(this.padding * 2), Math.floor(this.listStartY + numItems * this.entryHeight + this.padding), item.name, null, style_small));
		},
		
		removeItem: function(item) {
			
			let index = this.items.indexOf(item);
			
			ui.inventory.panel.destroy();
			
			this.items.splice(index, 1);
			
			ui.inventory.init();
			
		}
	},
	
	encounter: {
		
		margin: 4,
		padding: 2,
		
		menuHeight: 64,
		buttonWidth: 76,
		
		position_monster: {x: 144, y: 64},
		
		delay: 600,
		tweenDistance: 128,
		
		sprite_background: null,
		
		sprite_monster: null,
		
		cursor: null,
		
		init: function() {
			
			game.camera.x = 0;
			game.camera.y = 0;
			game.camera.unfollow();
			
			let numSprites = 5;
			let legsSelection, bodySelection, headSelection;
			legsSelection = Math.floor(Math.random() * numSprites);
			bodySelection = Math.floor(Math.random() * numSprites);
			headSelection = Math.floor(Math.random() * numSprites);
			
			//Create sprites
			this.sprite_background = game.add.sprite(0, 0, 'enc_background');
			this.sprite_player = game.add.sprite(16, gameHeight - 116, 'enc_player');
			this.sprite_monster = [];
			this.sprite_monster.push(game.add.sprite(this.position_monster.x + this.tweenDistance, this.position_monster.y, 'enc_monster_bodies', bodySelection));
			this.sprite_monster.push(game.add.sprite(this.position_monster.x + this.tweenDistance, this.position_monster.y, 'enc_monster_heads', headSelection));

			/* CREATE MENU */
			//base panel
			slickUI.add(this.menu = new SlickUI.Element.Panel(
				this.margin, gameHeight - this.menuHeight - this.margin,
				gameWidth - this.margin*2, this.menuHeight));
			this.menu.add(this.menu.title = new SlickUI.Element.Text(this.padding, 0, 'BATTLE', 14, style_small));
			
			//Give button
			this.menu.add(this.menu.buttonGive = new SlickUI.Element.Button(this.padding, this.padding + 20, this.buttonWidth, this.menuHeight/2));
			this.menu.buttonGive.add(this.menu.buttonGive.label = new SlickUI.Element.Text(this.padding, 0, 'FOOD', 10, style_small)).centerHorizontally();
			this.menu.buttonGive.events.onInputUp.add(this.openFood);
			
			/*
			//Eat button
			this.menu.add(this.menu.buttonEat = new SlickUI.Element.Button(this.padding * 2 + this.buttonWidth, this.padding + 20, this.buttonWidth, this.menuHeight/2));
			this.menu.buttonEat.add(this.menu.buttonEat.label = new SlickUI.Element.Text(this.padding, 0, 'EAT', 10, style_small)).centerHorizontally();
			this.menu.buttonRun.events.onInputUp.add(this.openGive);
			*/
			
			//Run button
			this.menu.add(this.menu.buttonRun = new SlickUI.Element.Button(this.padding * 3 + this.buttonWidth * 2, this.padding + 20, this.buttonWidth, this.menuHeight/2));
			this.menu.buttonRun.add(this.menu.buttonRun.label = new SlickUI.Element.Text(this.padding, 0, 'RUN', 10, style_small)).centerHorizontally();
			this.menu.buttonRun.events.onInputUp.add(this.endEncounter);
			
			//Put menu out of view so it can slide in
			this.menu.y += this.tweenDistance;
			game.camera.flash(0xffffff, this.delay/2, false);
			game.time.events.add(this.delay, this.tweenInUI, this);
			
			/* CREATE FOOD MENU */
			
			slickUI.add(this.menuFood = new SlickUI.Element.Panel(
				this.margin, this.margin,
				gameWidth*.75, gameHeight - this.margin*2));
			this.menuFood.add(this.menuFood.title = new SlickUI.Element.Text(this.margin, 0, 'FOOD', 14, style_small));
			this.menuFood.x = -gameWidth*.75;
			
			this.menuFood.add(this.menuFood.buttonClose = new SlickUI.Element.Button(this.menuFood.width - this.margin - 24, this.margin, 24, 24));
			this.menuFood.buttonClose.add(this.menuFood.buttonClose.label = new SlickUI.Element.Text(0, -4, 'x', 8, style_small)).centerHorizontally();
			this.menuFood.buttonClose.events.onInputUp.add(this.closeFood);
			
			this.menuFood.entries = [];
			for (let i = 0; i < ui.inventory.items.length; i++) {
				let itemButton;
				let itemHeight = 32;
				let itemWidth = 124;
				let itemsStartY = 16;
				let item = ui.inventory.items[i];
				this.menuFood.add(itemButton = new SlickUI.Element.Button(this.margin, itemsStartY + this.margin + (i * itemHeight), itemWidth, itemHeight));
				itemButton.add(new SlickUI.Element.Text(0, 0, item.name, 8, style_small));
				itemButton.events.onInputUp.add(()=>{ui.encounter.useFood(item)});
				this.menuFood.entries.push(itemButton);
			}
            
		},
		
		refreshFoodList: function() {
			
			for (let i = 0; i < this.menuFood.entries.length; i++) {
				this.menuFood.remove(this.menuFood.entries[i]);
			}
			
			this.menuFood.entries = [];
			
			for (let i = 0; i < ui.inventory.items.length; i++) {
				let itemButton;
				let itemHeight = 32;
				let itemWidth = 124;
				let itemsStartY = 16;
				let item = ui.inventory.items[i];
				this.menuFood.add(itemButton = new SlickUI.Element.Button(this.margin, itemsStartY + this.margin + (i * itemHeight), itemWidth, itemHeight));
				itemButton.add(new SlickUI.Element.Text(0, 0, item.name, 8, style_small));
				itemButton.events.onInputUp.add(()=>{ui.encounter.useFood(item)});
				this.menuFood.entries.push(itemButton);
			}
			
		},
		
		tweenInUI: function() {
			//Tween in the monster
			this.sprite_monster.forEach((element)=>{
				game.add.tween(element).to( {x: this.position_monster.x}, 500, Phaser.Easing.Cubic.Out, true);
			});
			
			//Tween in the menu after a delay
			game.time.events.add(this.delay, () => {
				game.add.tween(this.menu).to( {y: gameHeight - this.menuHeight - this.margin}, 500, Phaser.Easing.Cubic.Out, true)
			}, this);
			
		},
		
		//MENU OPTIONS
		
		openFood: function() {
			game.add.tween(ui.encounter.menu).to( {y: ui.encounter.menu.y + ui.encounter.tweenDistance}, 500, Phaser.Easing.Cubic.Out, true);
			
			game.add.tween(ui.encounter.menuFood).to( {x: ui.encounter.margin}, 500, Phaser.Easing.Cubic.Out, true);
		},
		
		closeFood: function() {
			game.add.tween(ui.encounter.menu).to( {y: ui.encounter.menu.y - ui.encounter.tweenDistance}, 500, Phaser.Easing.Cubic.Out, true);
			
			game.add.tween(ui.encounter.menuFood).to( {x: 0 - gameWidth*.75}, 500, Phaser.Easing.Cubic.Out, true);
		},
		
		useFood: function(item) {
			console.log('Chose ' + item.name);
			ui.inventory.removeItem(item);
			this.refreshFoodList();
//			ui.encounter.closeFood();
		},
		
		endEncounter: function() {
			playState.endEncounter();
		}
		
	}
};

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...