Small Basic: Tableaux de Sprites (fr-FR)
Cet article décrit l'utilisation des tableaux de sprites dans un programme Small Basic. Un sprite est une image qui se déplace dans un jeu graphique, ils peuvent représenter des aliens par exemple.
Souvent nous avons besoins de plusieurs copies de sprites qui vont et viennent lorsque le jeu s'exécute, et il est conseillé des stocker dans des tableaux. Cet article propose quelques explications et suggestions sur les moyens de contrôler dynamiquement les sprites efficacement.
Chargement des images de sprite
L'image d'un sprite se trouve dans un fichier (par exemple. jpg ou png). Ce fichier peut un fichier local sur votre PC ou socker en ligne sous forme d'URL. Si il est local alors vous devrez partager les images avec votre jeu dans un téléchargement zip, aussi il peut être préférable d'héberger le fichier sur le Web quand c'est possible.
Il est généralement préférable de créer un sprite avec une bordure transparente et en choisissant soigneusement la largeur et la hauteur en pixels.
Une fois que le sprite est créé, il est plus efficace de le charger qu'une seule fois dans votre programme en utilisant la méthode ImageList, et habituellement on fait cela avant que le jeu ne démarre car il peut prendre du temps à télécharger. L'image chargée peut être utilisée plusieurs fois pour avoir de multiple copies du sprite. Le code suivant est un exemple de chargement de l'image d'un sprite à partir d'une URL et test qu'il s'affiche correctement.
sprite = ImageList.LoadImage("http://litdev.co.uk/game_images/football.png")
Shapes.AddImage(sprite)
Sprite d'un Ballon de Football
Tableaux de sprites
Maintenant nous pouvons créer un tableau avec plusieurs copies du sprite, en utilisant l'image chargée, par exemple.
spriteImage = ImageList.LoadImage("http://litdev.co.uk/game_images/football.png")
numSprite = 10
For i = 1 To numSprite
sprite[i] = Shapes.AddImage(spriteImage)
EndFor
Les sprites apparaissent tous par dessus les autres et nous ne pouvons pas encore faire grand chose avec.
Propriétés de Sprite
Les sprites sont des images, mais dans un jeu ils peuvent avoir d'autres propriétés comme la position, le statut, la vélocité et autres. Nous avons besoin de stocker ces informations pour chaque sprites dans des tableaux. Il y a plusieurs méthodes pour faire ça, mais ici nous proposons d'enregistrer toutes les informations d'un sprite dans un tableau et d'avoir un tableau de ce tableau de sprite - pour être précis un tableau à deux dimensions.
Les tableaux dans Small Basic peuvent être lents, mais sont nous gardons le nombre d'éléments à son minimum, cette méthode des avantages. Elle permettra également d'améliorer votre programmation en maintenant les données logiquement associées ensembles et permettre plus facilement la création et la suppression d'un sprite.
Le code ci-dessous est structuré avec des sous-routines, créant plusieurs sprites, les positionnant de manière aléatoire, puis les déplaçant. Nous pouvons avoir des sprites qui pivotent ou d'autres caractéristiques enregistrées dans les tableaux spriteData.
gw = 600
gh = 600
GraphicsWindow.Width = gw
GraphicsWindow.Height = gh
CreateSprites()
' Boucle du jeu
While ("True")
start = Clock.ElapsedMilliseconds
UpdateSprites()
delay = 20 - (Clock.ElapsedMilliseconds - start)
If (delay > 0) Then
Program.Delay(delay)
EndIf
EndWhile
Sub CreateSprites
spriteImage = ImageList.LoadImage("http://litdev.co.uk/game_images/football.png")
'Les dimensions utilisées pour le sprite sont la moitié de la hauteur et de la largeur
spriteWidth = ImageList.GetWidthOfImage(spriteImage)/2
spriteHeight = ImageList.GetHeightOfImage(spriteImage)/2
numSprite = 10
For i = 1 To numSprite
spriteData["image"] = Shapes.AddImage(spriteImage)
spriteData["Xpos"] = spriteWidth + Math.GetRandomNumber(gw-2*spriteWidth)
spriteData["Ypos"] = spriteHeight + Math.GetRandomNumber(gh-2*spriteHeight)
spriteData["Xvel"] = Math.GetRandomNumber(11)-6
spriteData["Yvel"] = Math.GetRandomNumber(11)-6
sprites[i] = spriteData
EndFor
EndSub
Sub UpdateSprites
For i = 1 To numSprite
spriteData = sprites[i] ' récupère le tableau du sprite en cours
'Repositionne le centre du sprite
spriteData["Xpos"] = spriteData["Xpos"] + spriteData["Xvel"]
spriteData["Ypos"] = spriteData["Ypos"] + spriteData["Yvel"]
'Rebondi contre les murs
If (spriteData["Xpos"] < spriteWidth) Then
spriteData["Xpos"] = spriteWidth
spriteData["Xvel"] = -spriteData["Xvel"]
ElseIf (spriteData["Xpos"] > gw-spriteWidth) Then
spriteData["Xpos"] = gw-spriteWidth
spriteData["Xvel"] = -spriteData["Xvel"]
EndIf
If (spriteData["Ypos"] < spriteHeight) Then
spriteData["Ypos"] = spriteHeight
spriteData["Yvel"] = -spriteData["Yvel"]
ElseIf (spriteData["Ypos"] > gh-spriteHeight) Then
spriteData["Ypos"] = gh-spriteHeight
spriteData["Yvel"] = -spriteData["Yvel"]
EndIf
'Déplace le centre du sprite
Shapes.Move(spriteData["image"],spriteData["Xpos"]-spriteWidth,spriteData["Ypos"]-spriteHeight)
sprites[i] = spriteData 'enregistre le tableaux modifié du sprite (il peut avoir été modifié)
EndFor
EndSub
Ce code peut sembler plus long que nécessaire, mais enregistrer toutes les données d'un sprite dans un tableau et ainsi d'avoir un tableau de sprites et une manière efficace de procéder si vous voulez créer et détruire des sprites pendant le jeu.
Recycler les sprites
Nous avons souvent besoin que les sprites apparaissent et disparaissent. L'une des méthodes pour le faire est de recycler les sprites à partir d'un "pool", en les activant et les utilisant que c'est nécessaire. C'est très bien par exemple pour les tirs de balles ou de missiles, quand nous avons besoin uniquement d'un nombre limité à l'écran en même temps.
L'exemple qui suit tire des missiles lorsqu'un bouton de la souris est cliqué. Une nouvelle propriété "Status" est définie dans spriteData qui est utilisée pour indiquer si le missile est actif ou pas. Les missiles inactifs sont masqués et ils ne sont affichés à l'écran que lorsqu'ils actif.
gw = 600
gh = 600
GraphicsWindow.Width = gw
GraphicsWindow.Height = gh
GraphicsWindow.MouseDown = OnMouseDown
CreateSprites()
'Boucle de jeu
While ("True")
start = Clock.ElapsedMilliseconds
If (mouseDown) Then
FireMissile()
mouseDown = "False"
EndIf
UpdateSprites()
delay = 20 - (Clock.ElapsedMilliseconds - start)
If (delay > 0) Then
Program.Delay(delay)
EndIf
EndWhile
Sub CreateSprites
spriteImage = ImageList.LoadImage("http://litdev.co.uk/game_images/missile.png")
'Les dimensions utilisées pour le sprite sont la moitié de la hauteur et de la largeur
spriteWidth = ImageList.GetWidthOfImage(spriteImage)/2
spriteHeight = ImageList.GetHeightOfImage(spriteImage)/2
numSprite = 50
For i = 1 To numSprite
spriteData["image"] = Shapes.AddImage(spriteImage)
spriteData["Xpos"] = spriteWidth + Math.GetRandomNumber(gw-2*spriteWidth)
spriteData["Ypos"] = gh-spriteHeight
spriteData["Xvel"] = 0
spriteData["Yvel"] = -5
spriteData["Status"] = 0
Shapes.HideShape(spriteData["image"])
sprites[i] = spriteData
EndFor
EndSub
Sub UpdateSprites
For i = 1 To numSprite
spriteData = sprites[i] 'récupère le tableau du sprite en cours
If (spriteData["Status"] = 1) Then
'Repositionne le centre du sprite
spriteData["Xpos"] = spriteData["Xpos"] + spriteData["Xvel"]
spriteData["Ypos"] = spriteData["Ypos"] + spriteData["Yvel"]
'Déplace le centre du sprite
Shapes.Move(spriteData["image"],spriteData["Xpos"]-spriteWidth,spriteData["Ypos"]-spriteHeight)
'Ce sprite n'est plus utile ?
If (spriteData["Ypos"] < -spriteHeight) Then
spriteData["Status"] = 0
Shapes.HideShape(spriteData["image"])
EndIf
sprites[i] = spriteData 'enregistre le tableau modifié du sprite (il peut avoir été modifié)
EndIf
EndFor
EndSub
Sub FireMissile
For i = 1 To numSprite
spriteData = sprites[i] 'récupère le tableau du sprite courant
If (spriteData["Status"] = 0) Then
spriteData["Status"] = 1
Shapes.ShowShape(spriteData["image"])
spriteData["Xpos"] = GraphicsWindow.MouseX
spriteData["Ypos"] = gh-spriteHeight
sprites[i] = spriteData 'enregistre le tableau modifié du sprite (il peut avoir été modifié)
i = numSprite 'Fin de la boucle
EndIf
EndFor
EndSub
Sub OnMouseDown
mouseDown = "True"
EndSub
Supprimer des sprites
Ajouter et supprimer des sprites pendant le jeu peut être nécessaire dans certains cas, par exemple lorsque nous ne savons quelle image il va avoir avant d'en avoir besoin où lorsque le nombre de sprite ne peut pas être facilement géré par un pool de taille fixe. Cependant, le pool de sprites reste la meilleure approche la plupart du temps.
- Un sprite peut être supprimé si on est certain qu'on en aura plus besoins. En plus de devoir supprimer le tableau de données du sprite, il est nécessaire de supprimer la "forme" du sprite (Shapes.Remove). Si le nombre de formes de sprite non supprimés augmente, votre programme va ralentir considérablement.
- Pour supprimer des éléments dans un tableau nous devons affecter la valeur "". Toutefois, si nous supprimons les items d'un tableau, l'indexation de ce tableau ne sera plus séquentielle (1, 2, 3 ...) et nous devrons utiliser Array.GetAllIndices pour obtenir les indices actuels.
- Pour ajouter des sprites dans un tableau nous aurons besoin d'utiliser un index inutilisé ou nous risquons d'écraser un sprite existant.
Avec ces points à l'esprits, voici le code ajoutant et supprimant des sprites dans le tableau de missiles quand c'est nécessaire, pour comparer avec la méthode "pool".
gw = 600
gh = 600
GraphicsWindow.Width = gw
GraphicsWindow.Height = gh
GraphicsWindow.MouseDown = OnMouseDown
CreateSprites()
'Boucle de jeu
While ("True")
start = Clock.ElapsedMilliseconds
If (mouseDown) Then
FireMissile()
mouseDown = "False"
EndIf
UpdateSprites()
delay = 20 - (Clock.ElapsedMilliseconds - start)
If (delay > 0) Then
Program.Delay(delay)
EndIf
EndWhile
Sub CreateSprites
spriteImage = ImageList.LoadImage("http://litdev.co.uk/game_images/missile.png")
'Les dimensions utilisées pour le sprite sont la moitié de la hauteur et de la largeur
spriteWidth = ImageList.GetWidthOfImage(spriteImage)/2
spriteHeight = ImageList.GetHeightOfImage(spriteImage)/2
sprites = ""
nextSprite = 1
EndSub
Sub UpdateSprites
spriteIndices = Array.GetAllIndices(sprites)
For i = 1 To Array.GetItemCount(spriteIndices)
index = spriteIndices[i] 'index du sprite courant
spriteData = sprites[index] 'récupére le tableau du sprite courant
'Repositionne le centre du sprite
spriteData["Xpos"] = spriteData["Xpos"] + spriteData["Xvel"]
spriteData["Ypos"] = spriteData["Ypos"] + spriteData["Yvel"]
'Déplace le centre du sprite
Shapes.Move(spriteData["image"],spriteData["Xpos"]-spriteWidth,spriteData["Ypos"]-spriteHeight)
'Ce sprite est terminé ?
If (spriteData["Ypos"] < -spriteHeight) Then
Shapes.Remove(spriteData["image"])
Sprites[index] = ""
Else
sprites[index] = spriteData 'enregistre le tableau modifié du sprite (il peut avoir changé)
EndIf
EndFor
EndSub
Sub FireMissile
spriteData["image"] = Shapes.AddImage(spriteImage)
spriteData["Xpos"] = GraphicsWindow.MouseX
spriteData["Ypos"] = gh-spriteHeight
spriteData["Xvel"] = 0
spriteData["Yvel"] = -5
sprites[nextSprite] = spriteData
nextSprite = nextSprite+1
EndSub
Sub OnMouseDown
mouseDown = "True"
EndSub
Conclusion
Bien que cet article et plutôt orienté manipulation des tableaux de sprite, les méthodes utilisées dans le dernier exemple correspondent réellement à de bonnes techniques générales à étudier pour améliorer votre programmation. Elles vous permettrons de mieux passer à votre prochain langage après le Small Basic, où vous rencontrerez certainement des notions de classes et de collections.
- Garder toutes les données liées ensemble et créer des tableaux ou des listes de ces données si vous avez besoin d'en avoir des copies multiples.
- Utiliser des sous-routines pour exécuter des tâches spécifiques.
- Garder systématiquement une trace de où et quand vous créez et supprimez des données. En général, cette discipline donnera des résultats plus rapide, une plus faible maintenance et un code plus efficace avec moins de bugs qui seront plus faciles à détecter et à corriger.
Comme dernière suggestion, si la vitesse des tableaux Small Basic devient un facteur limitant, alors des méthodes d'extensions peuvent être utilisées pour améliorer les performances, par exemple l'objet LDList de l'extension LitDev (en-US) pour Small Basic. L'objet LDList est décrit dans cet* *article TechNet (en-US).
Voir Aussi
- Small Basic: Graphismes Dynamiques
- Small Basic - Les Bases : Les Tableaux
- Small Basic: List Extension (en-US)
- How do you get an image for your program? (article Blog) (en-US)
Autres Langues
- Article original : Small Basic: Sprite Arrays (en-US)