Introduction au nouveau système de cartes de tuiles Unity


La familiarité avec le système de tuiles Unity 2D offre une excellente occasion de gagner du temps aux développeurs indépendants et aux studios de jeux pour prototyper et créer des jeux 2D de haute qualité.

Sans ce système, vous pouvez passer des jours, voire des semaines, à écrire votre propre système de cartes de tuiles ou à traiter celui de quelqu'un d'autre. Et ce n'est que de la programmation, mais qu'en est-il de l'éditeur de carte de tuiles?

Le nouveau système est gratuit et est intégré directement dans l'éditeur Unity. Il fournit de nombreuses fonctionnalités que nous couvrirons dans ce tutoriel.

Dans cet article, nous allons utiliser un simple jeu 2D en mosaïque pour découvrir ce qui suit:

  • Fonctionnement des cartes tuiles.
  • Comment activer les cartes de tuiles dans Unity et personnaliser la grille.
  • Comment ajouter des images-objets à un projet, les convertir en tuiles, puis les ajouter à la palette de tuiles.
  • Comment utiliser les outils de l'éditeur de tuiles pour créer des niveaux.
  • Comment trier les tuiles et les placer dans différentes couches.
  • Comment ajouter des tuiles de physique Unity.
  • Comment colorer dynamiquement les carreaux.
  • Comment changer les tuiles préfabriquées en utilisant du code et une logique natifs.
  • Comment ajouter vos propres extensions et scripts de cartes de tuiles au projet.

Ouais, la liste était super. Mais n'ayez pas peur - lorsque nous commencerons à comprendre, vous comprendrez rapidement à quel point ces outils sont simples.

Remarque: ce didacticiel suppose que vous maîtrisez bien l'éditeur Unity. Si vous pensez que vous ne le connaissez pas, le didacticiel Introduction à Unity contient tout ce dont vous avez besoin pour apprendre ce didacticiel. De plus, vous avez besoin de la version Unity 2017.3 ou supérieure.

Qu'est-ce qu'un jeu de tuiles?


Un jeu de tuiles 2D est un jeu dans lequel les niveaux ou les zones de jeu sont constitués de nombreuses petites tuiles (tuiles) qui forment ensemble une grille de tuiles. Parfois, les différences entre les tuiles peuvent être évidentes, et parfois elles semblent solides et indiscernables pour les joueurs.

La collection de tuiles dans le jeu est appelée un jeu de tuiles, et chaque tuile est généralement un sprite, une partie d'une feuille de sprites. Si vous souhaitez mieux gérer les feuilles de sprites, nous avons un tutoriel qui décrit les feuilles de sprites Unity.

Comme vous pouvez le voir dans ce tutoriel, les tuiles sont généralement des carrés. Mais ils peuvent prendre une autre forme - des rectangles, des parallélogrammes ou des hexagones. Dans les jeux, une vue de dessus ou de côté est généralement utilisée, mais parfois dans les jeux de tuiles, 2.5D est également utilisé.

Peut-être connaissez-vous déjà les deux jeux les plus populaires qui utilisent le système de cartes de tuiles: Starbound et Terraria .



Se rendre au travail


Téléchargez le matériel du projet pour ce didacticiel et décompressez le fichier .zip.

Lancez l'éditeur Unity et chargez le projet Rayzor-starter à partir des matériaux de projet déballés.

Voici avec quoi vous travaillerez dans ce projet:


  • Cinemachine / Gizmos: Unity Cinemachine est ajouté uniquement pour implémenter une caméra facile à utiliser qui suit le lecteur.
  • Palettes: dans ce dossier, nous stockons nos propres palettes de tuiles.
  • Préfabriqués: quelques préfabriqués préfabriqués que nous utilisons plus tard dans le jeu.
  • Scènes: ici, nous allons ouvrir et enregistrer des scènes.
  • Scripts: quelques scripts simples pour contrôler le mouvement du joueur, la logique de la collision des pièges et gagner / perdre dans le jeu. Ce dossier contient également les scripts Unity Tilemap du référentiel Github Unity 2D Extras , que nous utiliserons plus tard.
  • Sfx: sons pour le jeu.
  • Sprites: sprites 2D à partir desquels nous allons créer des palettes de tuiles. Ils sont tirés d'un pack de grottes et de donjons pour roguelike . L'auteur du pack est kenney.nl.

Création de jeux


Ouvrez la scène du jeu depuis le dossier Scènes .

Cliquez sur le bouton Lecture dans l'éditeur pour lancer le jeu. Dans la fenêtre de jeu , déplacez le héros avec les touches WASD ou les «flèches».

GIF

Pendant que le héros se promène dans le fond apparemment sans fin de la caméra avec la couleur # 00000, perdu dans le vide.

Pour résoudre ce problème, nous avons besoin d'outils de tuiles 2D pour créer des niveaux et des mécanismes de jeu intéressants.

Connaître la palette de carreaux


Dans l'éditeur, cliquez sur Fenêtre -> Palette de tuiles pour ouvrir la fenêtre Palette de tuiles 2D.


Cette fenêtre sera votre meilleur ami lorsque vous travaillerez sur des jeux de tuiles dans Unity.

  1. Cette série d'icônes fournit des outils de base pour manipuler les tuiles, dessiner et supprimer
  2. Ce sélecteur vous permet de créer différentes palettes qui peuvent être perçues comme des palettes de dessin, dans lesquelles nous plaçons les "couleurs", et dans ce cas - des tuiles.
  3. Ce sélecteur vous permet de créer des pinceaux avec différents comportements. Vous pouvez ajouter vos propres pinceaux, dont le comportement est différent du pinceau par défaut (par exemple, dessiner des carreaux préfabriqués avec des fonctionnalités supplémentaires)

Cliquez sur Créer une nouvelle palette et nommez la palette RoguelikeCave . Ne modifiez pas les options de grille et de cellule.


Cliquez sur Créer et choisissez d'enregistrer la nouvelle palette dans le dossier Assets \ Palettes du projet. Dans ce document, créez un nouveau dossier RoguelikeCave .

Maintenant, la structure des dossiers de votre projet devrait ressembler à ceci:


Dans la fenêtre de l'éditeur de palette de tuiles , RoguelikeCave doit être sélectionné; à ce stade, nous n'avons toujours pas de tuiles:


Comment un artiste peut-il créer ses chefs-d'œuvre s'il n'a pas de matériaux?

Sans fermer la fenêtre Tile Palette, sélectionnez le dossier de projet Sprites / roguelike-cave-pack et développez l'actif roguelikeDungeon transparent.png . Sélectionnez ensuite tous les sprites dans cette feuille de sprites: sélectionnez le premier sprite, maintenez la touche Maj et sélectionnez le dernier sprite.

Faites glisser tous les sprites sélectionnés dans la fenêtre RoguelikeCave de la palette de tuiles:

GIF

Faites glisser et déposez les images-objets dans la fenêtre de la palette de tuiles et sélectionnez un emplacement pour stocker les ressources dans Unity.

Créez un nouveau dossier Tiles dans Assets / Palettes / RoguelikeCave et sélectionnez ce dossier comme emplacement de stockage:


Unity générera un élément de tuile pour chaque sprite ajouté à partir de la feuille de sprite. Attendez la fin du processus, puis augmentez la taille de la fenêtre de la palette de tuiles et admirez les rangées égales de belles nouvelles tuiles situées dans la palette RoguelikeCave:


Répétez le processus ci-dessus pour créer une palette de tuiles à l'aide de la fenêtre Palette de tuiles , mais cette fois nommez la nouvelle palette RoguelikeCustom .

Placez la nouvelle palette dans un nouveau dossier. Nommez le dossier RoguelikeCustom et déplacez-le dans le dossier Assets / Palettes du projet.

Cette fois, en utilisant le processus décrit ci-dessus, utilisez les sprites de la feuille Assets / Sprites / roguelike-custom / roguelike-normal-cutdown-sheet.png pour remplir les tuiles de la nouvelle palette. Créez un dossier Tuiles dans le dossier de la palette RoguelikeCustom et déplacez-y les ressources de tuiles:


Réjouissez-vous pour vous-même, maintenant vous connaissez la magie de la création d'une palette de carreaux!


Tile Map Mesh


Ouvrez le menu GameObject en haut de l'éditeur Unity (ou la barre de menus Unity si vous utilisez MacOS), cliquez sur Objet 2D puis sur Tilemap pour créer une nouvelle grille Tilemap:


Vous devriez voir qu'une nouvelle grille GameObject a été ajoutée à la hiérarchie des scènes. Développez-le et sélectionnez le Tilemap GameObject intégré .

Considérez ce Tilemap comme une couche (peut-être l'une des nombreuses) dans votre jeu. Vous pouvez ajouter de nouveaux objets pour créer des couches Tilemap supplémentaires.

Dans l'inspecteur, vous verrez deux composants que Unity a automatiquement ajoutés à ce GameObject:


  • Le composant Tilemap utilisé par le moteur Unity pour stocker les sprites dans le circuit marqué avec le composant Grid - dans notre cas, c'est GameObject Grid . Lorsque vous créez Tilemap pour la première fois, vous n'avez pas vraiment à vous soucier de toutes les caractéristiques techniques de la façon dont Unity communique entre tous ces composants.
  • Tilemap Renderer désigne le matériau qui sera utilisé pour le rendu des tuiles dans Tilemap. Il vous permet également de configurer les propriétés de tri de cette couche Tilemap.

Renommez GameObject Tilemap en BaseLayer .

Utilisation de divers outils de dessin de palette de tuiles


Basculez dans l'éditeur en mode Scène.

Sans fermer la palette de tuiles, sélectionnez la palette RoguelikeCave, puis sélectionnez l'outil pinceau (ou appuyez sur B ). Sélectionnez une tuile de sable comme indiqué ci-dessous:


Dans la fenêtre Scène, déplacez le curseur sur la grille à côté du lecteur. La brosse pour carreaux de sable se fixera sur la grille.

En maintenant le bouton gauche de la souris enfoncé, tracez une zone rectangulaire autour du lecteur. Il sera dessiné sur la couche Tilemap BaseLayer:

GIF

Le dessin de grandes zones peut être une tâche monotone, il existe donc un pinceau Boîte remplie qui peut être utilisé pour peindre de grandes zones. Dans la fenêtre Palette de tuiles, cliquez sur l' icône de pinceau carré (ou appuyez sur U ).

Revenez à l'éditeur et dessinez un rectangle encore plus grand autour du lecteur en appuyant sur le bouton gauche de la souris et en le maintenant enfoncé, en faisant glisser le curseur du coin supérieur gauche vers le coin inférieur droit:

GIF

Bien que nous ayons ajouté un peu de couleur au jeu, ce donjon de sable semble terne. Il est temps d'ajouter quelques détails!

Utilisez l'option de menu GameObject -> Objet 2D -> Tilemap pour créer une nouvelle couche Tilemap. Cette fois, ce sera le seul objet créé dans la hiérarchie, car nous avons déjà une grille appropriée. Renommez cette couche en DungeonFloorDecoration :


Dans la fenêtre de la palette de tuiles, basculez le Tilmap actif sur la couche DungeonFloorDecoration :


Sélectionnez l'outil pinceau ( B ), puis dessinez les objets dispersés sur la carte dans la fenêtre Scène:


Désactivez puis réactivez DungeonFloorDecoration dans la hiérarchie GameObject pour voir comment le rendu sur le Tilemap actif modifie la couche DungeonFloorDecoration, et toutes les tuiles rendues tombent sur cette nouvelle couche:

GIF

Créez à nouveau une couche Tilemap à l'aide de l' option GameObject -> Objet 2D -> Tilemap . Appelez-le Collideable . À l'avenir, nous l'utilisons pour créer des murs et des bordures.

Basculez Active Mapmap dans la fenêtre de la palette de tuiles sur Collideable . Sélectionnez l'outil pinceau ( B ), puis dessinez les tuiles suivantes pour construire un mur autour de la zone de jeu. Les zones surlignées en rouge dans l'image ci-dessous sont les nouvelles pièces à ajouter:


Jetez un œil à la capture d'écran ci-dessous de la fenêtre de la palette de tuiles pour savoir où trouver les tuiles nécessaires pour construire le mur. N'oubliez pas que vous pouvez utiliser les combinaisons CTRL-Z ou CMD-Z pour annuler l'action ou effacer les erreurs à l'aide du pinceau actuel (tout en maintenant Shift ):


Lancez le jeu dans l'éditeur et essayez de traverser le mur:

Qui a activé le mode noclip?

Vous ne vous attendiez pas à ça?

Le problème est que nous venons de dessiner les tuiles standard et n'avons pas encore appliqué l'Unité de physique magique à la couche Tilemap.

Sélectionnez GameObject Collideable et ajoutez un nouveau composant en cliquant sur le bouton Ajouter un composant dans la fenêtre Inspecteur ; Dans le champ de recherche, entrez Tilemap Collider 2D :


Ce composant a été créé spécifiquement pour les jeux de tuiles Unity 2D. Il applique simplement la forme du collisionneur physique à toutes les tuiles de la couche à laquelle il a été ajouté, sans effectuer d'autre travail.

Redémarrez le jeu et essayez de traverser le mur. Accès refusé!

GIF

Remarque: parfois, lorsque vous déplacez la caméra, vous pouvez remarquer de petites lignes noires entre certaines tuiles. Cela semble être un problème de mouvement de caméra dans les projets avec le système 2D Tilemap Unity. Vous pouvez vous en débarrasser presque complètement en désactivant l'anti-crénelage dans les paramètres graphiques. Cependant, même si cela se fait dans le cadre du projet de passation des marchés, l'effet est encore légèrement perceptible. La solution à ce problème peut être d'ajouter votre propre script de mouvement de caméra avec un décalage de pixel. Une bonne discussion de ce problème peut être trouvée ici .

Les collisions fonctionnent bien et vous pourriez penser que cela suffit. Mais pour l'instant, les collisionneurs ne sont pas optimisés efficacement. En mode Scène, effectuez un zoom avant sur une partie du mur et observez les contours des collisionneurs:


Il y a un collisionneur autour de chaque tuile. Les sections de mur centrales n'ont pas besoin de ces collisionneurs supplémentaires.

Avec GameObject Collideable sélectionné , ajoutez-y le composant Composite Collider 2D . Cela ajoutera également automatiquement RigidBody2D.

Définissez le paramètre BodyType RigidBody2D sur Statique , puis cochez la case Utilisé par composite dans le composant Tilemap Collider 2D :


Après cela, vous remarquerez que ces collisionneurs carrés inutiles au milieu des murs disparaissent.

Terminez la création des murs en les construisant et en les fermant en haut, environ 16 tuiles de haut. N'oubliez pas. que Collideable doit être sélectionné en tant que Tilmap actif de la fenêtre Palette de tuiles:


La section du donjon ne sera pas de difficulté pour notre héros sans obstacles. Nous allons maintenant commencer à travailler sur la création de la salle de la mort, complétée par de magnifiques couloirs de marbre anciens. Après avoir surmonté tous ces obstacles, le joueur recevra une récompense - une montagne d'or.

Pour dessiner ces couloirs, nous utiliserons le pinceau à carreaux spécial Rule Tile . Comme vous l'avez vu au début du didacticiel, des scripts de tuiles supplémentaires du référentiel Github Unity 2D Extras ont déjà été ajoutés au projet. L'un d'eux est Rule Tile.

La tuile de règle nous permet de définir des règles sur les tuiles à dessiner en fonction des tuiles voisines que nous avons.

Cliquez avec le bouton droit sur le dossier Prefabs du projet et sélectionnez Créer -> Mosaïque de règles (cet élément doit être en haut du menu). Nommez le nouvel élément MarbleFloorRuleTile :


Sélectionnez ce nouveau MarbleFloorRuleTile et utilisez l'inspecteur pour définir Sprite par défaut sur roguelikeDungeon_transparent_335 . Ajoutez ensuite une nouvelle règle de règle de tuilage en cliquant sur l'icône + . Sélectionnez la valeur roguelikeDungeon_transparent_339 pour Sprite de cette règle et cliquez sur tous les carrés extérieurs dans le schéma de règles afin que chacun ait une flèche verte pointant vers l'extérieur:

GIF

En utilisant l'outil pinceau de remplissage de boîte ( B ) dans la palette de tuiles et en sélectionnant la couche de base Tilemap , dessinez une section droite du mur de marbre. Il faut qu'il recouvre tout l'espace libre du sol.

Vous pouvez remarquer que lorsque nous faisons cela, le calque fermera les carreaux de mur avec des collisionneurs, car l'ordre des calques n'a pas encore été défini. Cela peut être facilement résolu en sélectionnant GameObject Collideable et en modifiant l' ordre dans la couche du composant Tilemap Renderer à une valeur plus élevée ( 5 suffira):

GIF

Revenez au dossier Prefabs du projet, ouvrez la fenêtre Tile et sélectionnez la palette RoguelikeCave, puis faites glisser MarbleFloorRuleTile vers un emplacement vide sur la palette:

GIF

Utilisez le pinceau de remplissage de boîte et dessinez quelques sections du sol en marbre dans la pièce:

GIF

Notez qu'une tuile de règle personnalisée, complètement entourée de tous les angles et faces, devient une tuile décorée (l'image-objet sélectionnée dans l'éditeur de règles de tuilage).

Ceci est un piège!


Non, nous n'ajouterons pas l'amiral Akbar au jeu en tant que personnage. Nous allons créer une brosse à carreaux pour le préfabriqué du piège, que nous utiliserons pour dessiner des pièges qui tireront avec des lames rotatives!

Créez un nouveau GameObject vide dans la hiérarchie et nommez-le ShootingTrap . Créez un enfant GameObject vide dans ShootingTrap. Nommez-le Sprite :


Sélectionnez Sprite et ajoutez-y le composant Sprite Renderer . Définissez le calque de tri sur Player et l' ordre dans le calque sur 1 afin qu'il s'affiche au-dessus du reste des calques. Sélectionnez le champ Sprite et définissez roguelikeDungeon_transparent_180 comme sprite.

Faites maintenant pivoter la transformation de l'objet Sprite de -90 dans l'axe Z :


Ensuite, revenez à GameObject ShootingTrap et ajoutez un nouveau composant à l'aide de l'inspecteur. Dans le champ de recherche, recherchez Shooting Trap et joignez ce script.

Ce script est ajouté aux fichiers de projet que vous avez téléchargés; en fait, il lance la corutine toutes les deux secondes, créant une instance préfabriquée de la lame de scie rotative (ou de tout autre préfabriqué) dans la position actuelle du piège.

Définissez le paramètre Item to Shoot Prefab du composant Shooting Trap sur Projectile (le préfabriqué se trouve dans / Assets / Prefabs ):


Relancez le jeu dans l'éditeur et utilisez le mode Scène pour trouver le piège. Elle travaille!

GIF

Faites glisser une copie de ShootingTrap de la hiérarchie vers le dossier / Assets / Prefabs du projet pour créer un préfabriqué. Supprimez ShootingTrap de la hiérarchie.

Nous utilisons un autre script de pinceau de tuiles appelé PrefabBrush pour créer un pinceau qui peut dessiner des préfabriqués sur des couches Tilemap.

Cliquez avec le bouton droit sur le dossier / Assets / Prefabs du projet et sélectionnez Créer -> Pinceau préfabriqué . Nommez l'objet PrefabBrush .

Utilisez l'inspecteur pour définir le paramètre Prefabs Size PrefabBrush sur 1 et le paramètre Element 0 sur ShootingTrap .


Créez une nouvelle couche Tilemap appelée Pièges dans la grille et ouvrez la fenêtre Palette de tuiles.

Sélectionnez le pinceau de tuile ordinaire ( B ) et utilisez le menu déroulant en bas de la fenêtre de la palette de tuiles pour sélectionner PrefabBrush . Sélectionnez Pièges à plan de mappage actifs comme calque et utilisez la fenêtre Scène pour dessiner plusieurs pièges préfabriqués le long du bord gauche de la pièce.

GIF

Développez les pièges GameObject dans la hiérarchie et testez la valeur du délai de démarrage de la prise de vue pour chaque valeur sur chaque Gameobject ShootingTrap à l'aide du script Shooting Trap dans l'inspecteur. Ajoutez 0,25 à la valeur de chaque piège, c'est-à-dire:

  • Premier ShootingTrap -> Délai de démarrage de la prise de vue = 0,1
  • Second ShootingTrap -> Délai de démarrage de la prise de vue = 0,35
  • Troisième ShootingTrap -> Shoot Start Delay = 0.6
  • Et ainsi de suite ...

Lancez le jeu et passez le test, si vous l'osez.

GIF

Objectif ultime


Le but de ce mini donjon est d'obtenir un tas d'or. La renommée et la fortune attendent ceux qui l'atteignent, évitant les lames volantes mortelles.

Créez une nouvelle couche Tilemap appelée Objectif dans la grille GameObject. Sélectionnez Objectif et modifiez la valeur de l' ordre de rendu Tilemap dans la couche à 2 :


Sans fermer la fenêtre Tile Palette, assurez-vous que PrefabBrush est toujours sélectionné. Faites en sorte que l'élément 0 fasse référence au préréglage d' objectif dans le dossier / Assets / Prefabs du projet.

Il s'agit d'un préfabriqué avec une montagne de sprite or, avec Box Collider 2D avec Is Trigger Goal.cs , une source sonore ajoutée et un script Goal.cs simple qui reproduit le son de la cible et redémarre le niveau lorsque le joueur tombe dans la zone de déclenchement.

Utilisez la brosse à carreaux standard pour dessiner une tuile préfabriquée cible en haut de la pièce derrière les pièges:


Redémarrez le jeu et essayez d'atteindre l'objectif. Lorsque vous arrivez à cette OnTriggerEnter2D() , la logique OnTriggerEnter2D() de Goal.cs , reproduisant l'effet sonore et redémarrant le niveau.


Touche finale


Maintenant, le donjon est trop léger et trop libre. Nous pouvons y ajouter du style en passant à un matériau sprite 2D qui peut répondre à la lumière.

Sélectionnez les objets Sprite Player, Goal et ShootingTrap, et demandez au Sprite Renderer Material d' utiliser SpriteLightingMaterial :


C'est un matériau avec un shader Sprite / Diffus attaché. Il permet à l'éclairage de la scène d'affecter les sprites.

Dans la grille GameObject , sélectionnez les objets BaseLayer, DungeonFloorDecoration, Collideable et Goal , puis utilisez l'inspecteur pour utiliser le matériau de rendu Tilemap SpriteLightingMaterial dans le matériau également .

Sélectionnez ensuite la lumière directionnelle dans les lumières GameObject et réduisez la lumière d' intensité à 0,3 .

Tant mieux!


De plus, vous remarquerez maintenant que le joueur porte une lumière ponctuelle , c'est-à-dire une lanterne qui brille autour de lui.

Maintenant que les sprites de la scène utilisent le bon matériau, l'éclairage Unity affecte tous les sprites environnants.

Faites glisser deux copies du préfabriqué FlickerLight depuis le dossier / Assets / Prefabs du projet dans Scene et placez-les dans GameObject Lights .

Définissez la première position préfabriquée (X: -11,25, Y: 4, Z: -1,35) et la seconde - (X: 2,75, Y: 4, Z: -1,35) .

Créez une nouvelle couche Tilemap appelée WallsAndObjects et définissez l’ ordre de rendu Tilemap Renderer Order dans Layer sur 15 . N'oubliez pas que Material utilise également SpriteLightingMaterial .

Redéfinissez le pinceau de la palette de carreaux sur le pinceau par défaut et le tilmap actif sur WallsAndObjects .

Utilisez l'outil pinceau ( B ) pour dessiner deux tuiles «lampe lumineuse» sous chacun des nouveaux FlickerLight que nous avons placés aux coins de la zone initiale:


Temps de difficulté


Voyons voir si nous pouvons encore améliorer le donjon. Utilisez la couche Tilemap WallsAndObjects pour créer des bibliothèques en haut de la salle du donjon à l'aide d'une autre palette de tuiles appelée RoguelikeCustom . Dessinez également une ou deux parties du mur fissuré.

Revenez à la couche Tilemap DungeonFloorDecoration et ajoutez plus de détails au sol en marbre, par exemple, des fissures sur plusieurs tuiles:

GIF

Félicitations, vous avez terminé votre premier mini-niveau de donjon! Par conséquent, vous devriez obtenir quelque chose de similaire:


Où aller ensuite?


Si vous avez manqué une étape, vous pouvez regarder le résultat final de ce tutoriel en ouvrant le projet Unity Rayzor-final à partir de matériaux téléchargeables.

Nous avons beaucoup appris dans ce tutoriel, mais comme pour toute autre entreprise, il y a toujours autre chose!

Il existe des scripts de pinceau de tuiles intéressants non couverts dans ce tutoriel. Lisez à leur sujet ici et réfléchissez si vous pouvez les utiliser.

Vous pouvez également apprendre à créer des tuiles animées ici .

Source: https://habr.com/ru/post/fr412765/


All Articles