zack_falcon

Members
  • Content Count

    7
  • Joined

  • Last visited

  1. By a client's request, I'm supposed to make two phaser games launch from a single html. I decided to do this via the game.js that (our) phaser template spits out because the games trade data between each other. Here's my code for game.js: import GameOneBoot from './states/GameOne/boot'; import GameOnePreload from './states/GameOne/preload'; import GameOneTitle from './states/GameOne/title'; import GameOneGameplay from './states/GameOne/gameplay'; import GameTwoBoot from './states/GameTwo/boot'; // etc, etc... class Game extends Phaser.Game { { constructor() { super(config.gameWidth, config.gameHeight, Phaser.AUTO, 'game'); } startGameOne() { this.state.add('GameOneBoot', GameOneBoot); this.state.add('GameOnePreload', GameOnePreload); this.state.add('GameOneGameplay', GameOneGameplay); this.state.add('GameOnePostgame', GameOnePostgame); this.state.start('GameOneBoot'); } startGameTwo() { // Same as GameOne, but GameTwo } destroyStates() { this.state.destroy(); document.getElementById('mainOverlay').style.display = 'block'; console.log("States destroyed!"); } } var phaserGame = new Game(); window.globalGame = phaserGame; The functions startGameOne and startGameTwo are triggered by an HTML menu, so the player can pick what he wants to play right there. However, I've hit a snag. The function destroyStates (called after a game over screen) does indeed return the player the HTML menu (with a blackened-out-but-still-visible empty game screen behind it), but clicking the menu to play either game again triggers this error: game.js:3368 Uncaught TypeError: Cannot read property 'stage' of null at c.StateManager.a [as start] (game.js:3368) I thought about just restarting the state, but part of the games change (such as assets) depending on objectives completed from the other one. I also tried not destroying the states, which worked, but the game is still in the background, and I'm not sure running over and over again is any good. Anything else I can try? Perhaps a way to restart game.js itself?
  2. This is my first time integrating any outside source into my phaser project, so please bear with me. Also, if there's anything that's unclear (regarding errors), lemme know so I can update this. For the first question, please check my steps below if I imported them right: Navigate into base project directory in a terminal, type in npm i / install "scroll-plugin-of-your-choice-here" Watch a lot of text scroll by (Mostly warnings) Find the folder in the node_modules directory of my project, copy the required file from the dist folder into my folders (this one is called: plugins) Import the required file in JS files that will use it ??? Profit I've tried three so far. This is the first one, heard good things about it: http://jdnichollsc.github.io/Phaser-Kinetic-Scrolling-Plugin/ I couldn't even get past step 4 tho. Assuming it doesn't need importing, it appears my project structure is different enough (more on this later), that I'm not entirely sure where to put the "load plug-in code"; putting it in my game.js (the JS file that is called by the HTML file) gets me a "Cannot read property 'plugins' of undefined". Putting it in the 'create' function of my boot.js (the first Phaser state started) gets me a "Cannot set property 'game' of undefined". That pretty much ends it. Also, I read it uses the camera, so I'm not sure if it was the way to go anyway. I have two things to scroll: the toolbar, and map itself. The second one is this: https://github.com/mattcolman/phaser-list-view It appeared to have clearer instructions than the first one, regarding import and usage. Unfortunately, there is some sort of 'Promise' code in the source, which to my limited experience is only used in async functions. This one fails outright, and throws an error the moment the game is loaded: "Cannot read property 'Promise' of undefined" The third and final one is this: https://github.com/trueicecold/phaser-scrollable It looks to be the simplest one of all, and is based on the amazing work of the first one, but like the first one didn't tell me about whether or not I need to copy-paste the plugin anywhere and/or import it anywhere I need to use it. Just copying the code into my mapEditor.js (the final state loaded, after boot.js - the "game" itself), results in the following error: "ScrollableArea is not defined". D'oh. So does that mean I need to import it after all? Well about that... import ScrollableArea from '../../plugins/phaser-scrollable.min'; class CreateModeMapEditor extends Phaser.State { create() { this.scroller = this.game.add.existing(new ScrollableArea(100, 100, 200, 400)); var textStyle = {font:"30px Arial", fill:"#ffff00"}; for (var i=0;i<10;i++) { for (var j=0;j<80;j++) { var text = game.make.text(i*330, j*30, "Yes, everything scrolls", textStyle); scroller.addChild(text); } } scroller.start(); } } export default CreateModeMapEditor; That returns this error: "Uncaught TypeError: _phaserScrollable2.default is not a constructor". Among the errors so far, that's probably the one that's somewhat close to being within my very, very limited understanding. But it's not close enough. Project Structure: index.html: <html> <body> <div id="game" width="1366" height="768"></div> <script src="scripts/phaser.min.js"></script> <script src="scripts/game.js"></script> </body> </html> game.js import config from './config'; import transition from './plugins/phaser-state-transition.min'; import CreateModeBoot from './states/createMode/boot'; import CreateModePreload from './states/createMode/preload'; import CreateModePostgame from './states/createMode/postgame'; import CreateModeMapEditor from './states/createMode/mapEditor'; class Game extends Phaser.Game { constructor() { super(config.gameWidth, config.gameHeight, Phaser.AUTO, 'game'); } loadCreateModeStates(mapSize) { document.getElementById('mainOverlay').style.display = 'none'; this.startCreateMode(this, mapSize); } startCreateMode(phaserGame, mapSize) { phaserGame.state.add('createModeBoot', CreateModeBoot); phaserGame.state.add('createModePreload', CreateModePreload); phaserGame.state.add('createModeMapEditor', CreateModeMapEditor); phaserGame.state.add('createModePostgame', CreateModePostgame); phaserGame.state.start('createModeBoot'); } } var phaserGame = new Game(); window.globalGame = phaserGame; Is there anything else I can try? Currently we're doing a HTML Overlay with a table on it on top of the phaser game, but it's tedious at best, and scaling is another can of worms.
  3. Fixed it. The problem is with this code: this.touchBtnUp = this.game.add.button(160, this.game.world.height - 300, 'ctrlBtn_up', this.touchUpCallback, this, 'btn_up.png'); For some reason, on game restart, the game.world.height changes. So it's less a case of it disappearing than it is getting set up in the wrong place. For now, I just hard-coded in my usual height, until I figure out why that changes.
  4. Exactly as it says on the tin. The buttons in question are on-screen buttons, for mobile devices. Here's my code them. this.touchBtnUp = this.game.add.button(160, this.game.world.height - 300, 'ctrlBtn_up', this.touchUpCallback, this, 'btn_up.png'); this.touchBtnDown = this.game.add.button(160, this.game.world.height - 150, 'ctrlBtn_down', this.touchDownCallback, this, 'btn_down.png'); this.touchBtnLeft = this.game.add.button(20, this.game.world.height - 150, 'ctrlBtn_left', this.touchLeftCallback, this, 'btn_left.png'); this.touchBtnRight = this.game.add.button(300, this.game.world.height - 150, 'ctrlBtn_right', this.touchRightCallback, this, 'btn_right.png'); this.touchBtnUp.fixedToCamera = true; this.touchBtnDown.fixedToCamera = true; this.touchBtnLeft.fixedToCamera = true; this.touchBtnRight.fixedToCamera = true; Nothing out of place, except for one thing: 'ctrlBtn_up' doesn't exist as a spritesheet. Since this is a temporary code, I've used temporary assets, which are not in a spritesheet, but individually created. I'm not sure if that has an effect on anything. Now, come game over, I show a game over layer (if the player wins) or immediately reset the game (if the player loses). Here's my code for those: create() { this.gameOverLayer = new GameOverLayer(this.game); this.gameOverLayer.fixedToCamera = true; } restartGame() { console.log("Restart Level"); this.bIsGameOver = true; var slideOut = Phaser.Plugin.StateTransition.Out.ScaleUp; slideOut.duration = 1000; var slideIn = Phaser.Plugin.StateTransition.In.SlideBottom; slideIn.duration = 1000; this.game.state.start('gameplay' , slideOut ); } endGame() { //Finished Level console.log("Finished Level"); this.gameOverLayer.showGameOver(0); } And the game over layer has a button that essentially does the same thing as the restartGame function. However, whether the game is over or restarts, the buttons go missing on the next play through (reloading the browser makes them show up again). I've tried resetting the x and y, but to no avail. About the only thing that works is to disable the fixedToCamera but that would mean the buttons getting left behind when the player moves. Anything else I can try?
  5. Thank you so much for the reply. I think I see where I failed, and I'm quite embarrassed to say that instead of adding the sprite object itself to the the game group, I've been adding the empty sprite object container. My error is in fact visible in the code above. I've since corrected the code, and re-applied the sort('y', Phaser.Group.SORT_ASCENDING) code back, and took your advice and moved the floor tiles into a group of their own, one that is drawn earlier. So now, I have two groups: Floor Group - This is unsorted, and spawned / drawn earlier than the Player/Object Group. This is used to contain the floor tiles, which by all accounts should be beneath the player at all times. Player/Object Group - This is the group that contains the player and the objects. The player is the last to be added to this group. The walls are also here, but as the player cannot travel to tiles with walls, and objects cannot spawn where there are already walls, how they stack against the player / objects of similar Y value is not my concern, for as long as they cover the player if the player's Y is lower than the wall's. However, I do still have a question: Ideally, in the Player/Object Group, the higher the object Y is (player included), the more "in-front" it will be right? Moving my player into a tile with an object puts the player on top of that object (intended), unless the player moves in from a tile above, in which case, the player comes in behind the object. From there, if I move a tile lower, and then move back up to the tile with the object, the player is on top again. I've added a this.playerObjectGroup.moveUp(this.player); after every move, in hopes of curing this, but so far no luck. Any suggestions?
  6. First off, please take note that I'm not just new to this forum, I'm new to phaser in general. I know a lot of people had z-ordering issues before. I've read about them. And most of the replies amount to "use the built-in sorting system." Which is great... if or when it works. However, I haven't seen anything that approaches my code, so I'm not entirely sure what to do. And boy does it produce some unique issues when the group sort is applied. There is one difference between the samples I see online and my code: I don't use +/-x and +/-y to move my character; instead, I use tween. This is so I can have a "snap to tile". Without further ado, my (mess of a) code: class Gameplay extends Phaser.State { create() { this.backgroundGroup = this.game.add.group(); this.mainGroundGroup = this.game.add.group(); this.foregroundGroup = this.game.add.group(); // GET MAP this.mapFile = this.game.cache.getJSON('protomap'); // SETUP GRID AND WORLD this.colCount = this.mapFile.columns; this.rowCount = this.mapFile.rows; this.game.world.setBounds(0, 0, (this.colCount * CONST.TILESIZE), (this.rowCount * CONST.TILESIZE)); this.grid = new Grid(this.game, this.colCount, this.rowCount); this.grid.x = 0; this.grid.y = 0; this.mainGroundGroup.add(this.grid); // SETUP OBJECTS this.spawnManager = new SpawnManager(this.game, this.grid, this.backgroundGroup, this.mainGroundGroup, this.foregroundGroup, this.mapFile); // SETUP PLAYER this.player = this.spawnManager.player; this.game.camera.follow(this.player); } update() { this.mainGroundGroup.sort('y', Phaser.Group.SORT_ASCENDING); this.player.z = this.player.currentTile.z; } } class Grid extends Phaser.Group { constructor(game, p_columnCount, p_rowCount) { super(game); game.add.existing(this); this.game = game; this.columnCount = p_columnCount; this.rowCount = p_rowCount; this.gridTiles = []; this.grid2DArray = [[]]; for(var i = 0; i < this.rowCount; i++) { this.grid2DArray[i] = []; for(var j = 0; j < this.columnCount; j++) { var gridTileObj = new GridTile(this.game, (CONST.TILESIZE * j), (CONST.TILESIZE * i + yAnchorOffset), zArray, j, i); this.add(gridTileObj); this.gridTiles.push(gridTileObj); this.grid2DArray[i][j] = gridTileObj; } } } } class SpawnManager { constructor(game, grid, back, main, fore, mapFile) { this.game = game; this.grid = grid; this.main = main; this.mapFile = mapFile; this.playerStartX = 0; this.playerStartY = 0; this.playerStartTile = null; this.initializeFloor(); this.initializeObjects(); } initializeFloor() { for(var i = 0; i < this.mapFile.floors.length; i++) { if (this.mapFile.floors[i] === CONST.TILE.BASE.FLOOR) { var gridTile = this.grid.getTileAtIndex(i); gridTile.tileBaseObj = new Floor(this.game, gridTile.x, gridTile.y, null, gridTile); gridTile.tileBaseType = CONST.TILE.BASE.FLOOR; } } } initializeObjects() { for(var i = 0; i < this.mapFile.objects.length; i++) { if (this.mapFile.objects[i] === CONST.TILE.OBJECT.WALL) { var gridTile = this.grid.getTileAtIndex(i); if (gridTile.tileBaseObj) { var wall = new Wall(this.game, gridTile.x, gridTile.y, null, gridTile); gridTile.tileBaseObj.addObject(wall, CONST.TILE.OBJECT.WALL); gridTile.tileBaseObj.z = 2; } } else if (this.mapFile.objects[i] === CONST.TILE.OBJECT.START) { var gridTile = this.grid.getTileAtIndex(i); if (gridTile.tileBaseObj) { var startObj = new FloorObject(this.game, 'gridSampleStartPoint', gridTile, null); gridTile.tileBaseObj.addObject(wall, CONST.TILE.OBJECT.START); gridTile.tileBaseObj.z = 1; } } else if (this.mapFile.objects[i] === CONST.TILE.OBJECT.END) { var gridTile = this.grid.getTileAtIndex(i); if (gridTile.tileBaseObj) { var startObj = new FloorObject(this.game, 'gridSampleEndPoint', gridTile, null); gridTile.tileBaseObj.addObject(wall, CONST.TILE.OBJECT.END); gridTile.tileBaseObj.z = 1; } } } this.player = new Player(this.game, 'prohyasIdle', this.playerStartTile); this.player.z = 3; this.main.add(this.player); } } With the above code, the player doesn't actually spawn on top of anything. It's firmly behind everything. Changing the sort('y', Phaser.Group.SORT_ASCENDING) into sort by Z, or by ascending or descending, doesn't really change anything. I've tried moving the this.main.add(this.player) from SpawnManager into the main Gameplay class - no dice. About the only thing that seemed to improve it was to outright remove the sort function, which leaves me with a player that does spawn on the tiles, but is located behind every other object. Is there anything else I can try?