bclindner Posted September 12, 2017 Share Posted September 12, 2017 Hello! I'm not well versed in game development but I write a lot of JS for my classes and my job, so I'd like to think I have some semblance of knowing what I'm doing, but the issue I'm having with Phaser right now is completely beyond me. It's hard to accurately describe my problem in words, so I've left the entire project as an attachment for you to see for yourself. (Cursor keys to control.) Essentially, I'm trying to write a simple platformer using a tilemap larger than the screen. However, when the camera is set to follow an object, and that object crosses the center of the window in a given direction on either axis, the camera slides in that direction at high speed - it seems to depend on how far you've crossed the threshold - until it reaches the stage boundary. The most difficult part is that the object seems to move properly relative to the camera - meaning it moves across the stage itself at very high speeds, confusing the arcade physics system and causing clips and zips galore if you're in the wrong places (try jumping under the spawn platform, for instance - you'll zip to the left or right) The problem doesn't happen at all when the stage size is equal to the game window size, nor does it happen if the camera is not following an object. Here are some things I've tried to resolve the issue: Removing game window scaling code Rewriting of Tilemap import code & use of different maps and tilesets Refactoring/simplification of the Player object (as well as forgoing the use of a class and extending Phaser.Sprite) Applying "layer.fixedToCamera = false" and "layer.fixedToCamera = true" Restarting the project and rewriting all code (this happened on a prior test project as well) Rolling back to some prior versions of Phaser I'm not certain whether the issue is with my Tilemap setup, my use of the camera, the general jankiness of the arcade physics system, or maybe something else I haven't taken into account, but given half of my Google searches lead here, I'm sure someone's got some kind of answer for me. For convenience, here's the important bits of my code, in case anything looks off at first glance: (game.js, the main game code) 'use strict' /* global Phaser, Player */ var game = new Phaser.Game( 161, // width 145, // height Phaser.AUTO, // idek 'game', // game name { create: create, update: update, preload: preload, render: render } // functions ) game.antialias = false function preload () { game.load.tilemap('mapTest', 'assets/map/testmap.json', null, Phaser.Tilemap.TILED_JSON) game.load.image('tileGrass', 'assets/img/grass.png') game.load.image('bgClouds', 'assets/img/bg.png') game.load.spritesheet('spritePlayer', 'assets/img/player.png', 9, 9) } let bg, player, map, layer function create () { // display background bg = game.add.image(1, 1, 'bgClouds') bg.fixedToCamera = true // instantiate the map map = game.add.tilemap('mapTest') map.addTilesetImage('tileGrass', 'tileGrass') layer = map.createLayer('terrain') map.setCollisionBetween(1, 10, 'terrain') layer.resizeWorld() layer.debug = true // initialize physics and set gravity game.physics.startSystem(Phaser.Physics.ARCADE) game.physics.arcade.gravity.y = 257 // set up the player player = new Player(game, 33, 49) game.physics.arcade.enable(player) // set game scale game.scale.scaleMode = Phaser.ScaleManager.USER_SCALE game.scale.setUserScale(6, 6) game.renderer.renderSession.roundPixels = true Phaser.Canvas.setImageRenderingCrisp(game.canvas) // camera: follow the player game.camera.follow(player) } function update () { game.physics.arcade.collide(player, layer) } function render () { game.debug.body(player) game.debug.body(layer) game.debug.text(Math.round(player.body.position.x), 9, 17) } game.antialias = false (player.js, the Player object file) /* global Phaser */ class Player extends Phaser.Sprite { constructor (game, x, y) { // set up the player super(game, x, y, 'spritePlayer') // physics game.physics.enable(this, Phaser.Physics.ARCADE) this.velCap = {x: 64, y: 150} this.jumpVel = -100 this.acceleration = 500 // units per second // animations this.anims = { 'idle': this.animations.add('idle', [0, 1, 2, 3], 6, true), 'walk': this.animations.add('walk', [8, 9, 10, 11, 12, 13, 14, 15], 15, true), 'down': this.animations.add('down', [21, 22], 15, false), 'jump': this.animations.add('jump', [16, 17, 18, 19], 15, false), 'fall': this.animations.add('fall', [19], 20, true), 'land': this.animations.add('land', [20, 21, 22, 23], 10, false) } this.animations.play('idle') this._facing = true this.anchor.setTo(0.5, 1) this.body.setSize(6,8,1,0) this.body.tilePadding.x = 12 this.body.tilePadding.y = 12 // input this.keys = game.input.keyboard.createCursorKeys() // add the player to the stage game.stage.addChild(this) } // facing code set face (bool) { if (bool) { this.scale.x = 1 } else { this.scale.x = -1 } this._facing = bool } get face () { return this._facing } update () { let airborne = !(this.body.blocked.down || this.body.touching.down) let dt = game.time.physicsElapsed if(this.keys.right.isDown) { this._move(dt, true, airborne) } else if(this.keys.left.isDown) { this._move(dt, false, airborne) } else{ this._decelerate(airborne) } if(this.keys.up.isDown && !airborne) { this._jump() } else if(this.keys.down.isDown && !airborne) { this._crouch() } this._capMovement() } _move (dt, right, airborne) { if(this.face != right){ this.face = right if(!airborne){ this.body.velocity.x = -this.body.velocity.x } } else { this.body.velocity.x += Math.floor(this.acceleration * (right ? 1 : -1) * dt) if (airborne) { this.animations.play('fall') } else { this.animations.play('walk') } } } _jump () { this.body.velocity.y = this.jumpVel this.animations.play('jump') } _crouch() { // stop all movement and crouch the player this.body.velocity.x = 0 if(this.animations.currentAnim.name != 'down'){ this.animations.play('down') } } _decelerate(airborne) { this.body.velocity.x = this.body.velocity.x / 2 if(airborne){ this.animations.play('fall') } else { this.animations.play('idle') } } _capMovement () { if(this.body.velocity.y > this.velCap.y){ this.body.velocity.y = this.velCap.y } else if (this.body.velocity.y < -this.velCap.y) { this.body.velocity.y = -this.velCap.y } if(this.body.velocity.x > this.velCap.x){ this.body.velocity.x = this.velCap.x } else if (this.body.velocity.x < -this.velCap.x) { this.body.velocity.x = -this.velCap.x } } } Thanks in advance! phaser_wtf.zip Link to comment Share on other sites More sharing options...
samme Posted September 12, 2017 Share Posted September 12, 2017 My first guess is you should put the player in the World, not the Stage: // add the player this.game.world.add(this); Also add game.debug.cameraInfo(…). Link to comment Share on other sites More sharing options...
bclindner Posted September 13, 2017 Author Share Posted September 13, 2017 1 hour ago, samme said: My first guess is you should put the player in the World, not the Stage: // add the player this.game.world.add(this); Also add game.debug.cameraInfo(…). Good call - that was exactly it, thanks! Link to comment Share on other sites More sharing options...
Recommended Posts