2016-07-16 4 views
0

Je suis en train de créer un jeu de tuiles 2d et je me demande si les tuiles doivent bouger ou le personnage?Dois-je déplacer les tuiles ou le joueur dans un monde de tuiles 2d?

Je pose cette question parce que j'ai déjà créé le "2d tile map" mais il fonctionne trop lentement, et je ne peux pas le réparer. J'ai tout essayé maintenant et le résultat est que je reçois 30 fps.

La raison pour laquelle il fonctionne trop lentement est parce que toutes les 1ms avec une minuterie, les tuiles sont en cours de redessin. Mais je ne peux pas comprendre comment résoudre ce problème.

Si quelqu'un pouvait m'aider, je l'apprécierais vraiment!

Voici comment je fais la carte:

 public void makeBoard() 
    { 
     for (int i = 0; i < tileArray.GetLength(0); i++) 
     { 
      for (int j = 0; j < tileArray.GetLength(1); j++) 
      { 
       tileArray[i, j] = new Tile() { xPos = j * 50, yPos = i * 50 }; 
      } 
     } 
    } 

Ici, je redessine 1ms ou plus les tuiles et sprites:

 private void Wereld_Paint_1(object sender, PaintEventArgs e) 
    { 
     //label1.Text = k++.ToString(); 
     using (Graphics grap = Graphics.FromImage(bmp)) 
     { 
      for (int i = 0; i < tileArray.GetLength(0); i++) 
      { 
       for (int j = 0; j < tileArray.GetLength(1); j++) 
       { 
        grap.DrawImage(tileArray[i, j].tileImage, j * 50, i * 50, 50, 50); 
       } 
      } 
      grap.DrawImage(player.movingObjectImage, player.xPos, player.yPos, 50, 50); 
      grap.DrawImage(enemyGoblin.movingObjectImage, enemyGoblin.xPos, enemyGoblin.yPos, 50, 50); 

      groundPictureBox.Image = bmp; 
      // grap.Dispose(); 

     } 
    } 

C'est la minuterie avec un spécifique intervalle:

 private void UpdateTimer_Tick(object sender, EventArgs e) 
    { 
     if(player.Update()==true) // true keydown event is fired 
     { 
      this.Invalidate(); 
     } 
     label1.Text = lastFrameRate.ToString(); // for fps rate show 
     CalculateFrameRate(); // for fps rate show 
    } 
+0

les tuiles Le seul inconvénient qui sont censés apparaître à l'écran et utiliser un appareil photo pour vous aider à dessiner des choses: http://stackoverflow.com/questions/9997006/slick2d-and-jbox2d-how- to-draw? answertab = votes # tab-top – user3814613

+0

@ user3814613 Tout d'abord, merci pour votre commentaire! Je ne comprends pas vraiment ce que vous dites. Je dois redessiner toutes les tuiles parce que je veux que les tuiles se déplacent ainsi il semblerait que le joueur marche autour du "monde". En outre, je n'ai jamais utilisé la fonction de caméra et je ne sais pas par où commencer. –

+0

Avez-vous lu le message qui était lié dans ce commentaire? Si vous aviez, vous n'auriez pas à dire * je ne saurais pas par où commencer *. Les gens fournissent des liens vers d'autres questions pour aider; ce n'est pas très agréable de les ignorer après qu'ils aient fait le travail pour le trouver pour vous. –

Répondre

1

Comme mentionné dans les commentaires, votre concept est erroné. Alors, voici juste un simple résumé de la façon de faire cette tâche:

  1. carte de tuile est statique

    Du point de vue fonctionnel n'a pas d'importance si le joueur se déplace ou la carte, mais du point de vue de la performance le nombre de tuiles est énormément plus grand que le nombre de joueurs si le joueur en mouvement est plus rapide.

    Pour centrer le lecteur ou suivre les vues, vous devez également déplacer l'appareil photo.

  2. rendu

    Repeindre toutes 1ms est fou et très probablement impossible sur les ordinateurs de nos jours si vous avez complexité moyenne de la scène. La vision humaine ne peut pas le détecter de toute façon, donc il ne sert à rien de repeindre plus que 25-40 fps. La seule raison pour des besoins plus élevés de fps est d'être synchronisé avec le rafraîchissement de votre moniteur pour éviter les artefacts de ligne de balayage (Oui même les lignes de balayage d'utilisation d'affichage à cristaux liquides réutilisent). Pour avoir plus de fps alors le taux de rafraichissement de votre moniteur est inutile (beaucoup de fps s'y opposent mais notre perception est ce qu'elle est, peu importe ce qu'ils disent ...).

    De toute façon, si votre rendu a pris plus de 1ms (ce qui est plus que probable) alors votre minuteur est vissé car il devrait être tiré plusieurs fois avant que le premier gestionnaire s'arrête. Cela provoque généralement des ralentissements massifs dus à des problèmes de synchronisation, de sorte que le fps résultant est généralement encore plus petit que le moteur de rendu pourrait fournir. Alors, comment remédier à cela?

    1. intervalle défini timer-20ms ou plus
    2. ajouter bool _redraw=false et l'utiliser pour redessiner uniquement lorsque vous devez repeindre l'écran.Donc, sur toute action comme le mouvement du joueur, le mouvement de la caméra ou le tour, le changement d'animation le règle sur true
    3. le gestionnaire d'événement timer interne n'appelle votre repeint que si _redraw==true et le place à false par la suite.

    Cela augmentera considérablement les performances. Même si votre repeindre prendra plus de temps que l'intervalle de la minuterie, ce sera beaucoup plus rapide que votre approche actuelle.

    Pour éviter le scintillement, utiliser Retour tampon.

  3. appareil photo et la coupure

    Votre carte est très probablement beaucoup plus grand que l'écran donc il n'y a pas de point de repeindre toutes les tuiles. Vous pouvez regarder la caméra comme un moyen de sélectionner la bonne partie de votre carte. Si votre jeu n'utilise pas de rotations, vous n'avez besoin que de position et peut être zoom/scale. Si vous voulez des rotations, alors les matrices 2D homogènes 3x3 sont le chemin.

    Soit suppose que vous avez seulement la position (pas de zoom ou de rotation), vous pouvez utiliser ces transformations:

    screen_x=world_x-camera_x 
    screen_y=world_y-camera_y 
    
    world_x=screen_x+camera_x 
    world_y=screen_y+camera_y 
    

    si camera est votre position de vue de la caméra, world est vous position de tuiles dans la grille de carte et screen est le position sur l'écran. Si vous avez indexes de votre tuile dans la carte, alors multipliez-les par la taille de la tuile en pixels pour obtenir les coordonnées world. Pour sélectionner uniquement les mosaïques visibles, vous devez obtenir les positions de coin de votre écran, les convertir en coordonnées mondiales, puis en index sur la carte et enfin restituer uniquement les mosaïques dans le rectangle formé par ces points dans votre carte + une certaine marge d'erreur (par exemple, rendre 1 rectangle élargi de tuiles dans toutes les directions). De cette façon, le rendu sera indépendant de la taille de votre carte. Ce processus est appelé écrêtage.

Je recommande fortement de regarder ces liées AQ s:

La démo dans les QAs liés utilisent uniquement GDI et l'accès direct des pixels bitmaps sous forme win32 application afin que vous puissiez comparer les performances avec votre code (ils devraient être similaires) et modifier votre code jusqu'à ce qu'il se comporte comme se doit.

+0

Tout d'abord, merci pour toute votre aide:) J'ai fait l'étape 2 complètement mais je n'ai pas besoin de passer à l'étape 3 maintenant. J'ai une idée de comment faire ça. Mais tout d'abord, je voulais me débarrasser de 30 fps p/s. Avez-vous des conseils pour atteindre environ 50/60 fps avec dessiner la carte complète toutes les 20ms? Je ne fais que dessiner la carte aussi grande que l'écran, donc aucun carreau ne sort de l'extérieur. Plus tard, je vais mettre en œuvre le reste ... Merci pour votre temps! –

+0

@MYil dans le premier QA lié est aussi mon code source pour la démo qui est assez rapide. Sans voir comment vous rendre est difficile de dire où est le goulot d'étranglement ... comment rendes-tu les sprites? ou avez-vous juste des carreaux (pas de transparence ou de masques)? de toute façon faussement codé le rendu gfx peut être douloureusement lent ... – Spektre

+0

Merci pour votre réponse! Oke, essayez d'être aussi clair que possible:) J'ai un tableau 2d rempli de tuiles. Ces carreaux sont des classes et dans ces classes il y a une image. Cette image est d'environ 1 Ko. Je repeindre avec une invalide toutes les 1ms (ou 20ms, donne la même performance) les images à un bitmap. et peignez cela sur une grande image. La taille de l'image est aussi grande que la taille de l'image. Le redessin est effectué chaque fois que j'appuie sur un événement de clavier. Ensuite, la minuterie ouvrira la méthode de mouvement dans la classe sprite et la fera bouger. Permettez-moi de placer une partie de mon code, accrocher :) –

1

Est-ce que vous écrivez vous-même l'implémentation de la tuile? Probablement le problème est qu'à chaque image vous dessinez toutes les tuiles.

Les moteurs 2D avec des carreaux de défilement doivent dessiner des carreaux sur un sprite plus grand que l'écran, puis dessiner ce sprite autour de laquelle est une opération rapide (vous devez spécifier la langue que vous utilisez afin de donner un indice comment faire en fait que rapide - essentiellement une mémoire vidéo accélérée blit, mais chaque langue a son chemin pour y arriver)

enter image description here

quand la frontière de ce super-sprite est plus proche de la frontière de l'écran que un seuil (généralement une demi-tuile), le plus grand sprite est redessiné autour de la position actuelle - mais il n'y a pas besoin de dessiner toutes les tuiles là-dessus! commencez à copier le supersprite sur ce sprite recentré et il vous suffit de dessiner les tuiles manquantes du supersprite précédent en raison du décalage.

enter image description here

+1

oublié de mentionner cela dans ma réponse au début. donc +1. btw c'est ce qu'on appelle la mise en mémoire tampon ou double buffering au lieu de super sprite ... Ma compréhension est que super sprite est utilisé pour combiner des couches de sprites pour améliorer les performances des animations sur la base de carreaux et non comme écran d'ombre ... – Spektre

+0

back/double buffering a une signification précise et il a un tampon arrière qui est dessiné à chaque frame et permuté pour le buffer avant - ici vous construisez une feuille préfiltrée, que vous pouvez copier sur le tampon arrière ou avant - donc c'est orthogonal - mais l'idée est similaire, avoir la carte graphique pousser le plus de pixel au lieu du cpu –

+0

Hmm je pense que vous avez raison l'écran d'ombre de défilement ne correspond pas exactement à la facture ... – Spektre