Forums Développement Multimédia

Aller au contenu

Développement pour des tailles d'écran différentes.

Starling viewport scaleMode

14 réponses à ce sujet

#1 philippeonline

    Ceinture Marron

  • Members
  • PipPipPipPipPipPip
  • 102 messages

Posté 28 December 2014 - 02:45 AM

Bonjour,

J'ai crée un jeux avec Starling qui fonctionne bien sur tablette et mobile, cependant j'ai un problème de taille (sans jeux de mots).

Je n'arrive pas à gérer convenablement le changement de taille d'écran, entre un smartphone par exemple et une tablette.
La taille de base de mon document : 1024x768

J'utilise le code suivant, qui m'affiche mes images, boutons etc à la bonne taille et au bon emplacement mais avec une bordure visible... (beurk).
Ou alors sans bordure, mais avec un contenu étiré.(arf c'est presque ça !)
Ou alors sans bordure, mais avec un contenu trop zoomé.

Pourtant j'ai prévu le coup, il suffirai de pouvoir, à partir des réglages du code qui va suivre, élargir simplement la taille de la scène en largeur.
Cela marchait bien avec Flash.

En gros le résultat est bon, mais je souhaite supprimer les bords ou élargir la scène à la taille maximal de l'écran pour faire apparaître l'image du fond que j'ai pensé pour être assez large.(sans toucher au reste).

Merci pour votre aide :)




// Taille standard de mon document
var stageWidth:int  = 1024;
var stageHeight:int = 768;

var iOS:Boolean = Capabilities.manufacturer.indexOf("iOS") != -1;
Starling.handleLostContext = !iOS;  // not necessary on iOS. Saves a lot of memory!

// create a suitable viewport for the screen size
var viewPort:Rectangle = RectangleUtil.fit(
new Rectangle(0, 0, stageWidth, stageHeight),
new Rectangle(0, 0, stage.fullScreenWidth, stage.fullScreenHeight),
ScaleMode.SHOW_ALL, iOS);

//Lancement Starling
//myStarling = new Starling(Game, stage);
myStarling = new Starling(Game, stage, viewPort);
myStarling.stage.stageWidth  = stageWidth;  // <- same size on all devices!
myStarling.stage.stageHeight = stageHeight; // <- same size on all devices!
myStarling.antiAliasing = 1;
myStarling.start();
myStarling.simulateMultitouch  = false;
myStarling.enableErrorChecking = false;

 

J'ai essayé l'approche suivante sans succès:



// La taille de la scène égale la taille maximal de l’écran du périphérique.

myStarling.stage.stageWidth  = stage.fullScreenWidth;  
myStarling.stage.stageHeight = stage.fullScreenHeight;


trace(stage.stageWidth);  //Ca semble ok
trace(stage.stageHeight);



public function initTexture():void  
{

var ratio:Number = 1024 / stage.stageWidth;
var newScale:Number = 1 / ratio;


titrePrincipal = new Image(Assets.getTexture("ImageTitrePrincipal"));
titrePrincipal .alignPivot(); //Point d'alignement au centre de l'image.
titrePrincipal.scaleX = titrePrincipal.scaleY = newScale; //Met l'image à l'échelle.

//Place l'image aux centre de la scène.
titrePrincipal.x = stage.stageWidth / 2;
titrePrincipal.y = stage.stageHeight / 2;

}


#2 draad

  • Members
  • PipPipPipPipPipPipPipPip
  • 654 messages

Posté 28 December 2014 - 18:30 PM

Coucou,

Tu n'est pas très loin d'une solution.

Voici comment je m'y prends :



var scale :Number =  0; // scale a utiliser par default

var originalHeight :Number =  1024;   // hauteur de ton application
var originalWidth  :Number =   768;     // largeur de ton application
var osHeight  :Number = Capabilities.screenResolutionX;  // hauteur de l'ecran
var osWidth   :Number= Capabilities.screenResolutionY; // largeur de l'ecran


public static function getScaleValue () :void
{
// je compare les deux valeur de scale pour connaitre la plus petit, car je souhaite redimmentionner mon application a la plus grande taille possible mais sans dépasser de l'ecran ! Pour le moment, cela laissera des marges, mais on va s'en occuper plus tard
var vScale :Number = osHeight / originalHeight ;  // scale vertical
var hScale :Number = osWidth  / originalWidth ;  // scale horizontal
 
if (vScale > hScale)
{
   scale  =  hScale;
}
else
{
   scale  =  vScale;
}
}
 


Ensuite, lorsque tu récupère une image avec starling, tu n'as plus qu'a lui donner la bonne valeur de scale


  image.scaleX = image.scaleY = scale;
 

A ce point de l'application, tu as donc tes graphismes qui sont bien placés, avec la bonne taille et sans étirement, mais il y a des bordures sur les cotés. Pour régler ce problème, il suffit simplement d'utiliser une image en background, mais cette fois ci, au lieu de lui appliquer le scale que nous avons calculé, nous allons le dimensionner manuellement :


background.width  = Capabilities.screenResolutionX;
background.scaleY  = background.scaleX;
 

Bien sur, cette image elle, va dépasser de l'ecran, il faut donc t'assurer que rien d'indispensable n'y est présent.


Et voilà !

Par contre, cette solution ne prends pas en compte le faire qu'un mobile a deux orientation différentes. Si tu veux prendre ceci en compte, il faut rajouter quelques lignes pour recalculer la valeur de scale lorsque l'utilisateur bouge sa device, et pour savoir dans quelle position ce dernier se trouve.

J'espère que ca t'aidera !

#3 philippeonline

    Ceinture Marron

  • Members
  • PipPipPipPipPipPip
  • 102 messages

Posté 12 January 2015 - 20:21 PM

Hello,

Tout d'abord merci pour ta réponse Draad,

J'ai essayé ta solution, mais pour le moment le résultat n'est pas satisfaisant.
La mise à l’échelle est ok, mais pas la position des assets sur la scène.

Une question :

Pour les coordonnées suivantes, "monImage" est placé aux centre de l'écran sur une tablette avec un écran Ipad. (10,1 pouce je crois).
Sera t-elle toujours aux centre de l' écran d'un smartphone par ex ?

monImage.x = 512;
monImage.y = 384;

Je ne voit pas trop comment obtenir une position précise, qui soit valable sur tout les périphériques, en utilisant stage.stageWidth, monImage.width (etc...) uniquement aux lieux de coordonnées numériques pour positionner une image, lorsque celle ci peut être placé n'importe ou à l'écran.

#4 draad

  • Members
  • PipPipPipPipPipPipPipPip
  • 654 messages

Posté 12 January 2015 - 20:43 PM

Bonjour.

Etant donne que les tailles d'ecran different, si tu utilise une position en pixel, ton image se retrouvera a des endroits differents. C'est logique, imagine deux tailles d'ecran d'exemple :
A fait 500 pixels en largeur et 1000 pixels en hauteur
B fait 1000 pixels en largeur et 2000 pixels en hauteur

Si tu place ton element avec des coordonnees fixes comme :

         monImage.x = 250;
         monImage.y = 500;


Le pivot de ton image sera au centre de l'ecran A, mais pas au centre sur l'ecran B.
Pour etre sur que ton pivot se retrouve au centre de tous les ecrans, tu dois a la place utiliser un positionnement relatif aux tailles d'ecran.
Par exemple, si le pivot de ton image est bien en x=0, y=0

           largeurEcran = Capabilities.screenResolutionX;
           hauteurEcran = Capabilities.screenResolutionY;

           monImage.x  = largeurEcran / 2 - monImage.width / 2;
           monImage.y  = hauteurEcran / 2 - monImage.height / 2;

Ainsi, quelque soit la taille de l'ecran et quelque soit la taille de ton image, elle sera centree.

Maintenant, si tu souhaite utiliser des tailles en pixel a la place, tu peux te servir de la valeur de scale que l'on a calcule plus haut, par exemple:

        monImage.x = 512 * scale;
        monImage.y = 384 * scale;
Dans ce cas la, il faut que ta position en pixel soit basee sur la taille d'origine de ton document (1024 * 768 je crois ?).

Est-ce que tu vois l'idee ?

#5 philippeonline

    Ceinture Marron

  • Members
  • PipPipPipPipPipPip
  • 102 messages

Posté 12 January 2015 - 22:35 PM

Hello Draad,

Je voit l'idée !
Je vais tester et je te tiens au courant :)

Merci,

Bonne fin de soirée.

#6 philippeonline

    Ceinture Marron

  • Members
  • PipPipPipPipPipPip
  • 102 messages

Posté 21 January 2015 - 10:24 AM

Hello,

Bon c'est pas encore ça... :cry:

Avec stage.stageWidth / 2; les images sont bien placé aux milieux de la scène, mais trop petit.

Et

monImage.x = 512 * scale;
monImage.y = 384 * scale;

Ne centre pas l'image sur mon Samsung galaxy S5.

J'ai essayé toute sorte de variante sans succès. Notamment :

Dans la classe qui crée une instance de Starling:


[SWF(frameRate="60", width="1024", height="768", backgroundColor="0x000000")]

var viewPort:Rectangle = RectangleUtil.fit(
new Rectangle(0, 0, Capabilities.screenResolutionX, Capabilities.screenResolutionY),
new Rectangle(0, 0, Capabilities.screenResolutionX, Capabilities.screenResolutionY),
ScaleMode.NONE, iOS);


myStarling = new Starling(Game, stage, viewPort);
myStarling.antiAliasing = 1;
myStarling.simulateMultitouch  = false;
myStarling.enableErrorChecking = false;
myStarling.start();


 

Dans la classe EcranTitre:


private var scale :Number =  0; // scale a utiliser par default
private var originalHeight:Number =  768;   // hauteur de ton application
private var originalWidth :Number =   1024;     // largeur de ton application
private var osHeight:Number = Capabilities.screenResolutionX;  // hauteur de l'ecran
private var osWidth:Number= Capabilities.screenResolutionY; // largeur de l'ecran

private var vScale :Number = osHeight / originalHeight ;  // scale vertical
private var hScale :Number = osWidth  / originalWidth ;  // scale horizontal

public function initTexture():void  
{

if (vScale > hScale)
{
scale  =  hScale;
}
else
{
scale  =  vScale;
}

trace(osHeight);
trace(osWidth);
trace(scale);
trace(stage.stageWidth);

fond = new Image(Assets.getTexture("ImageFond"));
fond.alignPivot();
fond.width = Capabilities.screenResolutionX;
fond.height = Capabilities.screenResolutionY;


titrePrincipal = new Image(Assets.getTexture("ImageTitrePrincipal"));
titrePrincipal.scaleX = titrePrincipal.scaleY = scale;
titrePrincipal.alignPivot();


private function afficheEcranTitre():void  //affiche l'écran titre
{

//affiche le fond
this.addChild(fond);
fond.x = stage.stageWidth / 2;
fond.y = stage.stageHeight / 2;

//le titre principal
this.addChild(titrePrincipal);
titrePrincipal.x = 512 * scale);
titrePrincipal.y = 384 * scale);

}


#7 draad

  • Members
  • PipPipPipPipPipPipPipPip
  • 654 messages

Posté 21 January 2015 - 15:48 PM

Bon j'ai regarde en diagonale et je n'ai pas le temps de tester ton code, donc mes conseils seront peut-etre a cote de la plaque, mais voici ce que je note en regardant ton code.

Pourquoi utilise-tu cette ligne :

[[SWF(frameRate="60", width="1024", height="768", backgroundColor="0x000000")]

Tu ne devrais en aucun cas assigner une taille fixe a ton Stage, vu que chaque ecran aura une taille differente.
Utilise simplement ceci :

[SWF(frameRate="60", backgroundColor="#000000")]

Pour l'initialisation de Starling, j'utilise un simple rectangle comme ceci :

stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;

var rect:Rectangle = new Rectangle (0, 0, osWidth, osHeight);
mStarling = new Starling(Context, stage, rect);
 

Et je pense que ton probleme viens de la, car ensuite tu utilise la taille de ton Stage pour positionner tes elements, sauf que la taille de ton stage n'est plus correcte si tu lui donne des valeurs fixes. Utilise toujours les tailles que tu as recupere grace a Capabilities.screenResolution, et laisse ton stage prendre tout l'espace disponible.

#8 archiroc

    Ceinture Noire

  • Members
  • PipPipPipPipPipPipPip
  • 259 messages

Posté 21 January 2015 - 20:45 PM

Bon...

La réalité de la chose c'est que l'appli doit être configuré pour tout type de format.

Faire autrement c'est du bricolage.
Mais... Le bricolage c'est chouette...

Trouver le compromis entre pro et bidouilleur.

Bises les gens.

#9 draad

  • Members
  • PipPipPipPipPipPipPipPip
  • 654 messages

Posté 21 January 2015 - 22:16 PM

Je pense pas qu'il y ai de compromis possible lol, soit ca marche, soit ca ne marche pas ... Y'a pas d'entre deux.

#10 philippeonline

    Ceinture Marron

  • Members
  • PipPipPipPipPipPip
  • 102 messages

Posté 22 January 2015 - 12:20 PM

Eureka !

Ca y est ça marche :), merci beaucoup pour ton aide Draad.

J'ai résolu cette problématique d'une manière différente :


[SWF(frameRate="60", width="1024", height="768", backgroundColor="0x000000")]

var stageWidth:int  = 1024;
var stageHeight:int = 768;

var iOS:Boolean = Capabilities.manufacturer.indexOf("iOS") != -1;
Starling.handleLostContext = !iOS;  // not necessary on iOS. Saves a lot of memory!

// create a suitable viewport for the screen size
var viewPort:Rectangle = RectangleUtil.fit(
new Rectangle(0, 0, stageWidth, stageHeight),
new Rectangle(0, 0, stage.fullScreenWidth, stage.fullScreenHeight),
ScaleMode.SHOW_ALL, iOS);
 
myStarling = new Starling(Game, stage, viewPort);

myStarling.stage.stageWidth  = stageWidth;  
myStarling.stage.stageHeight = stageHeight;

myStarling.antiAliasing = 1;

myStarling.simulateMultitouch  = false;
myStarling.enableErrorChecking = false;

viewPort.inflate(250,0);
myStarling.stage.stageWidth = 1274;

myStarling.start();
 

Dans mon cas cette solution est parfaitement adapté et le résultat est tout à fait propre et satisfaisant quelque soit la taille du périphérique !

#11 draad

  • Members
  • PipPipPipPipPipPipPipPip
  • 654 messages

Posté 22 January 2015 - 15:33 PM

Super ! Content que tu sois debloque :)

#12 draad

  • Members
  • PipPipPipPipPipPipPipPip
  • 654 messages

Posté 22 January 2015 - 16:41 PM

Un warning en passant, je viens de me rendre compte que sur certains devices Android, il y a une barre de menu android qui apparrait et prends une partie de l'ecran (et qui vient donc fausser mes calcul de taille d'ecran disponible). Je n'ai pas encore trouve de solution propre pour gerer ce cas precis. A prendre en compte si tu souhaite publier sur android aussi.

#13 archiroc

    Ceinture Noire

  • Members
  • PipPipPipPipPipPipPip
  • 259 messages

Posté 22 January 2015 - 17:11 PM

Yo Draad !

C'est une mise jour surcouche HTC ou Android, j'sais pas.
Mais en effet, sur Darkness par exemple apparait désormais la bande menu.

Différentes applis propose au fur et à mesure une mise à jour qui efface la bande.
Plus qu'a trouver la méthode.

#14 draad

  • Members
  • PipPipPipPipPipPipPipPip
  • 654 messages

Posté 22 January 2015 - 17:28 PM

J'ai vu trainer un ANE qui permet de faire ca, mais j'suis pas sur que ce soit la bonne solution de passer outre cette barre. Il vaudrait peut-etre mieu conserver la barre et dimensionner l'appli en la prenant en compte.

#15 philippeonline

    Ceinture Marron

  • Members
  • PipPipPipPipPipPip
  • 102 messages

Posté 22 January 2015 - 18:16 PM

Hello,

Cette approche là prend en compte le System Chrome lorsqu'il est visible. (c'est le nom donné il me semble pour la barre de menu en question).


[SWF(frameRate="60", width="1024", height="768", backgroundColor="0x000000")]

// create a suitable viewport for the screen size
var viewPort:Rectangle = RectangleUtil.fit(
new Rectangle(0, 0, stageWidth, stageHeight),
new Rectangle(0, 0, stage.fullScreenWidth, stage.fullScreenHeight),
ScaleMode.SHOW_ALL, iOS);

myStarling = new Starling(Game, stage, viewPort);

myStarling.stage.stageWidth = stageWidth;
myStarling.stage.stageHeight = stageHeight;


Il est aussi possible de la masquer grâce aux fichier XML du projet:

<!-- The type of system chrome to use (either "standard" or "none"). Optional. Default standard. -->
<!-- <systemChrome></systemChrome> -->

<!-- Whether the window is transparent. Only applicable when systemChrome is none. Optional. Default false. -->
<!-- <transparent></transparent> -->


J'ai testé ça marche, même si la masquer ne me semble pas non plus être une bonne idée !



1 utilisateur(s) li(sen)t ce sujet

0 membre(s), 1 invité(s), 0 utilisateur(s) anonyme(s)

authorised training centre

Centre de Formation Mediabox - Adobe et Apple Authorised Training Center.

Déclaré auprès de la Direction du Travail et de la Formation Professionnelle

Mediabox : SARL au capital de 62.000€ - Numéro d'activité : 11 75 44555 75 - SIRET : 49371646800035

MEDIABOX, 23, rue de Bruxelles, 75009 PARIS

FFP