Tylox Posted August 13, 2016 Share Posted August 13, 2016 Hello, here is the code : //not in the loop : this.canvas = document.getElementById("ctx"); this.canvas.width = 1920; //viewport of the player this.canvas.height = 1080; this.renderer = new PIXI.autoDetectRenderer(this.canvas.width, this.canvas.height, { view: this.canvas }); this.renderer.clearBeforeRender = false; this.stage = new PIXI.Container(); this.mapImage = new PIXI.Texture.fromImage('map.png'); //dimension of the map png : 1024x1024 //in the loop : //selfState has the position of the player (x,y) and his mass var drawMap = function(selfState) { if (!this.map) { this.map = new PIXI.extras.TilingSprite(this.mapImage, this.renderer.width, this.renderer.height); this.stage.addChild(this.map); } //center the player and move the map when the player move if (this.centerX === undefined) { this.centerX = selfState.x; this.centerY = selfState.y; } else { if (selfState.x !== this.centerX || selfState.y !== this.centerY) { this.map.tilePosition.x += this.centerX - selfState.x; this.map.tilePosition.y += this.centerY - selfState.y; this.centerX = selfState.x; this.centerY = selfState.y; } } } I would like that the viewport of the player increase with his mass I tried : //in the loop var resizeMass = function(mass) { scopeW = 1920 + mass * 2; scopeH = scopeW * 9 / 16; resizeCanvas(scopeW, scopeH); }; var resizeCanvas = function(w, h) { //... //resize canvas //... this.renderer.resize(w, h); if (this.map) { this.map.width = w; this.map.height = h; } } But it gets really big and there is performance issue. Do you have a solution to show to the player all the map game (5000x5000 or even 10000x10000) without performance issue ? I think that I have to reduce the TilingSprite width/height of the map and all the other Sprites to keep a viewport of 1920x1080. But how to do it efficiently for the TilingSprite ? And for the Sprites, if there is no performance issue, I don't want to decrease the scale of the Sprite because I lose the quality of the original sprite (blurry). I want to "reduce" the width of the image to draw and not to reduce the img.width or img.height. (like drawImage from canvas2d http://www.w3schools.com/tags/canvas_drawimage.asp ) Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted August 13, 2016 Share Posted August 13, 2016 Its ok to make TilingSprite width and height very big, it can handle it. Your problem is that you are resizing canvas and it is VERY bad. You have to scale the stage: stage.position.set(renderer.width/2, renderer.height/2); //position it in center, that way it will be scaled there stage.scale.set(2,2); //scale stuff ;) stage.pivot.set(centerX, centerY); // point on map that you are viewing //method number one: create big tilingsprite and forget about that you actually need only one part. videodriver will cull it for you ;) map.width = 10000; //your true map size, big one, including all the space of your map map.height = 10000; map.tilePosition.set(0, 0); // you dont have to change tileposition in this method. //method2: carefully make tilingsprite size the same as your view screen. I dont think that it is significally faster than method number one. map.width = renderer.width/stage.scale; map.height = renderer.height/stage.scale; map.position.set(centerX - map.width/2, centerY - map.height/2); map.tilePosition.copy(map.position); // actually, may have change the sign of it: -x, -y, i dont know if we need that The quality of the sprite can be retained by using mipmaps, which are enabled by default in pixi-v4 for power-of-two texture, like that one. But at the same time, pixi-v4 has some bugs that will lead to strange lines on tilingsprite border, so please wait while we fix it If you are using pixi-v3, you have to add line "this.mapImage.baseTexture.mipmap=true;" and it will work fine. Tylox 1 Quote Link to comment Share on other sites More sharing options...
Tylox Posted August 13, 2016 Author Share Posted August 13, 2016 Thank you for your reply. 1) For method 1, I scaled the stage successfully but I can't find a way to keep the player at the center of the viewport... I've also : player.sprite.position.x = this.canvas.width / 2; this.map.position.x = this.canvas.width / 2 - selfState.x; this.map.position.y = this.canvas.height / 2 - selfState.y; Maybe I don't understand where to put your line 1 and 3 in my first post code, and which centerX/Y to choose. 2) mipmap is a new concept for me, in adding line "this.mapImage.baseTexture.mipmap=true;", do you mean that the image will be blurry as I see it ? Because in setting it to "false", I keep the quality of the sprite (no blur). Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted August 14, 2016 Share Posted August 14, 2016 stage.position.set(renderer.width/2, renderer.height/2); //position it in center, that way it will be scaled there stage.scale.set(2,2); //scale stuff ;) stage.addChild(player); // add player // in the update: cameraX = player.position.x; cameraY = player.position.y; stage.pivot.set(cameraX, cameraY); // point on map that you are viewing PLEASE look at my comments again and think about how position/scale/pivot system works. I'm begging you to just stop and think. Quote Link to comment Share on other sites More sharing options...
caymanbruce Posted December 21, 2016 Share Posted December 21, 2016 On 8/13/2016 at 10:09 PM, ivan.popelyshev said: Its ok to make TilingSprite width and height very big, it can handle it. Your problem is that you are resizing canvas and it is VERY bad. You have to scale the stage: stage.position.set(renderer.width/2, renderer.height/2); //position it in center, that way it will be scaled there stage.scale.set(2,2); //scale stuff ;) stage.pivot.set(centerX, centerY); // point on map that you are viewing //method number one: create big tilingsprite and forget about that you actually need only one part. videodriver will cull it for you ;) map.width = 10000; //your true map size, big one, including all the space of your map map.height = 10000; map.tilePosition.set(0, 0); // you dont have to change tileposition in this method. //method2: carefully make tilingsprite size the same as your view screen. I dont think that it is significally faster than method number one. map.width = renderer.width/stage.scale; map.height = renderer.height/stage.scale; map.position.set(centerX - map.width/2, centerY - map.height/2); map.tilePosition.copy(map.position); // actually, may have change the sign of it: -x, -y, i dont know if we need that The quality of the sprite can be retained by using mipmaps, which are enabled by default in pixi-v4 for power-of-two texture, like that one. But at the same time, pixi-v4 has some bugs that will lead to strange lines on tilingsprite border, so please wait while we fix it If you are using pixi-v3, you have to add line "this.mapImage.baseTexture.mipmap=true;" and it will work fine. I am following your method to make my stage scale to the center point of the screen. However I don't know how to position my sprites on the stage. I am having a container as stage. On top of that stage there is a gameScene container. Then I put all my sprites on the gameScene. Something like this: const stage = new Container(); stage.position.set(renderer.view.width / 2, renderer.view.height / 2); stage.pivot.set(centerX, centerY); const gameScene = new Container(); for (let i = 0; i < COUNT; i++) { //... generate some texture and assign to let texture = ... let sprite = Sprite.from(texture); gameScene.addChild(sprite); } let player = Sprite.from(otherTexture); gameScene.addChild(player); stage.addChild(gameScene); Then in the animate update: if(timeToScale) { stage.scale.set(0.6); // zoom to make the map smaller. } However I am not sure which x and y is centerX and centerY. Is it the current position of my player sprite? I am totally confused. I know you are a very experienced PIXI developer. Please shed some light for me. Thanks in advance. EDIT: I have figured out the solution based on your code and the issue discussion here: https://github.com/pixijs/pixi.js/issues/190 It's really simple but just very confusing for beginner who comes across this scenario for the first time. All I need to do is change to pivot point to center, where my player sprite locates. and in update loop change my player sprite's scale, as is: const g = new PIXI.Graphics(); g.beginFill(0xff0000); g.lineStyle(0); g.drawCircle(0, 0, 30); g.endFill(); // ... stage.position.x = WIDTH / 2; // Shift stage position to center, WIDTH, HEIGHT is the renderer.view's size stage.position.y = HEIGHT / 2; stage.pivot.x = WIDTH / 2; // change pivot point to center stage.pivot.y = HEIGHT / 2; //... const gameScene = new PIXI.Container(); gameScene.addChild(g); stage.addChild(gameScene); let size = 5; In the update loop: g.position.x = Math.round(WIDTH / 2); // WIDTH, HEIGHT is the renderer.view's size g.position.y = Math.round(HEIGHT / 2); size++; if (timeToScale) { scale = scale < 1.8? 1 + 0.02 * (size / 100) : 1.8; g.scale.set(scale); } So now my sprite can scale in the center of the screen. I can also make the background zoom out at the same time. However the problem is, how can I make the scaling smoother? It's stuttering when scaling which is not very natural. I want a natural scaling. Tylox 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.