Page 1 sur 1
[R] Rotation image, GDIPlus
Posté : dim. 15 mai 2011 19:58
par matwachich
Je fais appel à vous, chers Autoitien(ne)s!
Un problème de GDIPlus, car je développe ces jours-ci un moteur d'affichage 2D.
Au fait, mon moteur est basé sur les Images de GDIPlus, je les charge et je les colle sur le graphique de la fenêtre.
J'aimerai pourvoir faire tourner ces images (sprites), pour ne pas avoir à créer des sprites sheet énormes contenant toutes les direction de mon personnage!
Je tâtonne du coté des Matrice (_GDIPlus_MatrixCreate), mais le problème c'est que si je fais un MatrixRotate, bah le positionnement du sprite est faussé, car le repère à tourné lui aussi.
J'ai essayé d'ajouter MatrixTranslate, croyant que ça contrera le décalage de MatrixRotate, sans succès.
Je vous donne mon script d'exemple, sur lequel je fais mes tests.
Une idée???
► Afficher le texte
Code : Tout sélectionner
#include <GDIPlus.au3>
Opt("GUIOnEventMode", 1)
Opt("MouseCoordMode", 2)
Global Const $width = 600, $height = 400 ; Modifiez comme bon vous semble
Global $hImg, $ImgW, $ImgH
$hWnd = GUICreate("Test GDIPlus", $width, $height) ; La fenètre
GUISetOnEvent(-3, "_exit")
GUISetState(@SW_SHOW)
Global $USER32_DLL = DllOpen("user32.dll") ; Utile pour les _isPressed()
_GDIPlus_Startup() ; Let's go!
$hGraphic = _GDIPlus_GraphicsCreateFromHWND($hWnd) ; Alors, ces 3 fonctions, j'ai pas très bien compris ce qu'elle font
$hBitmap = _GDIPlus_BitmapCreateFromGraphics($width, $height, $hGraphic); précisement, alors je me contente de les utilisé comme je vois dans
$hBuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap) ; les scripts de pros!
;~ ; Je sais juste que $hBuffer sera le parametre des fonctions de dessins
_GDIPlus_GraphicsSetSmoothingMode($hBuffer, 2) ; ca, c'est pour l'anti-aliasing
$hImg = _GDIPlus_ImageLoadFromFile("C:\Users\Mat\Desktop\GDIPlus\Archives\gimp.png") ; On charge l'image
$ImgW = _GDIPlus_ImageGetWidth($hImg) ; Et on récupere ses dimensions
$ImgH = _GDIPlus_ImageGetHeight($hImg) ;
$matrix = _GDIPlus_MatrixCreate()
;_GDIPlus_MatrixRotate($matrix, 45) ; La rotation
While 1
_GDIPlus_GraphicsClear($hBuffer, 0xFFFFFFFF) ; On vide le buffer, en lui donnant une couleur blanche
$mos = MouseGetPos()
;_GDIPlus_MatrixTranslate($matrix, $mos[0], $mos[1]) ; quand j'ai essayé d'ajouter MatrixTranslate
; Si vous décommentez cette ligne, il faut que la ligne 39 soit commenté, et la 40 et 44 décommenté
_GDIPlus_GraphicsSetTransform($hBuffer, $matrix)
_GDIPlus_GraphicsDrawImage($hBuffer, $hImg, $mos[0]-64, $mos[1]-64)
_GDIPlus_GraphicsDrawImage($hBuffer, $hImg, -64, -64)
; ---
; ##########
;_GDIPlus_MatrixTranslate($matrix, -1 * $mos[0], -1 * $mos[1]) ; réinitialiser la matrice
_GDIPlus_GraphicsDrawImageRect($hGraphic, $hBitmap, 0, 0, $width, $height) ; On copy le graphique $hBuffer dans $hBitmap
Sleep(10)
; ---
WEnd
Func _exit() ; Fonction de sortie (nétoyage des ressources)
_GDIPlus_MatrixDispose($matrix)
_GDIPlus_ImageDispose($hImg)
_GDIPlus_GraphicsDispose($hBuffer)
_GDIPlus_BitmapDispose($hBitmap)
_GDIPlus_GraphicsDispose($hGraphic)
_GDIPlus_Shutdown()
Exit
EndFunc
Re: [..] Rotation image, GDIPlus
Posté : dim. 15 mai 2011 22:27
par jchd
Je suis une quiche en GDI plus ou pas, mais voici comment je tourne les images qu'il me faut tourner.
C'est un extrait de code brut de décoffrage, je te laisse zieuter l'aide de chaque fonction, t'es un grand garçon.
Code : Tout sélectionner
[spoiler=]Global Enum _
$RotateNoneFlipNone = 0, _
$Rotate180FlipXY = $RotateNoneFlipNone, _
$Rotate90FlipNone = 1, _
$Rotate270FlipXY = $Rotate90FlipNone, _
$Rotate180FlipNone = 2, _
$Rotate270FlipNone = 3, _
$RotateNoneFlipX = 4, _
$Rotate180FlipY = $RotateNoneFlipX, _
$Rotate90FlipX = 5, _
$Rotate270FlipY = $Rotate90FlipX, _
$Rotate180FlipX = 6, _
$RotateNoneFlipY = $Rotate180FlipX, _
$RotateNoneFlipXY = $Rotate180FlipX, _
$Rotate90FlipY = 7, _
$Rotate270FlipX = $Rotate90FlipY, _
$Rotate90FlipXY = $Rotate90FlipY
Local $hImage = _GDIPlus_ImageLoadFromFile($sFileName)
DllCall($ghGDIPDll, "int", "GdipImageRotateFlip", "hwnd", $hImage, "long", $Rotate90FlipNone)
Local $iIW = _GDIPlus_ImageGetWidth($hImage)
Local $iIH = _GDIPlus_ImageGetHeight($hImage)
Local $Result = _GDIPlus_BitmapLockBits($hImage, 0, 0, $iIW, $iIH, $GDIP_ILMREAD, $GDIP_PXF24RGB)
;Get the returned values of _GDIPlus_BitmapLockBits
Local $Scan0 = DllStructGetData($Result, "Scan0")
[/spoiler]
Pour la suite, j'ai besoin ici d'une structure pour accéder aux rangées de pixels RGB dans une structure, mais vois comment tu emploies le graphique pour tes propres besoins.
Maintenant si tu as vraiment besoin d'une fonction la plus générique possible pour la transformation de tes sprites, tu es en effet contraint de te farcir le calcul de la matrice idoine. C'est de la géométrie 2D bête.
Re: [..] Rotation image, GDIPlus
Posté : lun. 16 mai 2011 02:10
par matwachich
Merci pour la réponse.
J'ai déjà vu la fonction GdipImageRotateFlip, et c'est pas ce que je cherche, elle ne me permet pas de faire une rotation à angle libre.
J'ai pensé à utilisé la fonction _GDIPlus_DrawImagePoints, mais je pense que ça sera lent.
Ce que j'aurai aimé, c'est d'exploiter les matrice, mais quand je fait une rotation à ma matrice, toutes les coordonnées sont faussées.
Je vais essayé tout de même d'exploiter _GDIPlus_DrawImagePoints
Re: [..] Rotation image, GDIPlus
Posté : lun. 16 mai 2011 10:45
par jchd
Laisse tomber les machins compliqués.
Essaye ça et ajuste pour obtenir l'effet souhaité.
► Afficher le texte
Code : Tout sélectionner
#include <GDIPlus.au3>
Opt("GUIOnEventMode", 1)
Opt("MouseCoordMode", 2)
Global Const $Pi = 3.1415926
Global $rotdeg = 30
Global $rotrad
Global Const $width = 1024, $height = 1024 ; Modifiez comme bon vous semble
Global $hImg, $ImgW, $ImgH
$hWnd = GUICreate("Test GDIPlus", $width, $height) ; La fenètre
GUISetOnEvent(-3, "_exit")
GUISetState(@SW_SHOW)
Global $USER32_DLL = DllOpen("user32.dll") ; Utile pour les _isPressed()
_GDIPlus_Startup() ; Let's go!
$hGraphic = _GDIPlus_GraphicsCreateFromHWND($hWnd) ; Alors, ces 3 fonctions, j'ai pas très bien compris ce qu'elle font
$hBitmap = _GDIPlus_BitmapCreateFromGraphics($width, $height, $hGraphic); précisement, alors je me contente de les utilisé comme je vois dans
$hBuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap) ; les scripts de pros!
;~ ; Je sais juste que $hBuffer sera le parametre des fonctions de dessins
_GDIPlus_GraphicsSetSmoothingMode($hBuffer, 2) ; ca, c'est pour l'anti-aliasing
$hImg = _GDIPlus_ImageLoadFromFile("C:\Users\Mat\Desktop\GDIPlus\Archives\gimp.png") ; On charge l'image
$ImgW = _GDIPlus_ImageGetWidth($hImg) ; Et on récupere ses dimensions
$ImgH = _GDIPlus_ImageGetHeight($hImg) ;
AdlibRegister("_ElleTourne", 50) ; je lui fait tourner la tête
While 1
_GDIPlus_GraphicsClear($hBuffer, 0xFFFFFFFF) ; On vide le buffer, en lui donnant une couleur blanche
$mos = MouseGetPos()
$matrix = _GDIPlus_MatrixCreate()
_GDIPlus_MatrixRotate($matrix, $rotdeg) ; La rotation en degré
_GDIPlus_MatrixTranslate($matrix, $mos[0] * Cos(-$rotrad) - $mos[1] * Sin(-$rotrad), $mos[0] * Sin(-$rotrad) + $mos[1] * Cos(-$rotrad))
_GDIPlus_GraphicsSetTransform($hBuffer, $matrix)
_GDIPlus_GraphicsDrawImage($hBuffer, $hImg, -64, -64)
_GDIPlus_GraphicsDrawImageRect($hGraphic, $hBitmap, 0, 0, $width, $height) ; On copy le graphique $hBuffer dans $hBitmap
Sleep(10)
WEnd
Func _ElleTourne()
$rotdeg += 1
$rotrad = 2 * $Pi / 360 * $rotdeg
EndFunc
Func _exit() ; Fonction de sortie (libération des ressources)
AdlibUnRegister("_ElleTourne")
_GDIPlus_MatrixDispose($matrix)
_GDIPlus_ImageDispose($hImg)
_GDIPlus_GraphicsDispose($hBuffer)
_GDIPlus_BitmapDispose($hBitmap)
_GDIPlus_GraphicsDispose($hGraphic)
_GDIPlus_Shutdown()
Exit
EndFunc
Re: [..] Rotation image, GDIPlus
Posté : lun. 16 mai 2011 16:27
par matwachich
C'est parfait!!!
Il y avait un autre problème, c'est que la matrice est appliqué à toutes les images que je colle dans le buffer, mais j'ai trouvé la solution:
Il suffit de créer un autre buffer!
Comme cela:
► Afficher le texte
Code : Tout sélectionner
#include <GDIPlus.au3>
Opt("GUIOnEventMode", 1)
Opt("MouseCoordMode", 2)
Global Const $Pi = 3.1415926
Global $rotdeg = 30
Global $rotrad
Global Const $width = 600, $height = 600 ; Modifiez comme bon vous semble
Global $hImg, $ImgW, $ImgH
$hWnd = GUICreate("Test GDIPlus", $width, $height) ; La fenètre
GUISetOnEvent(-3, "_exit")
GUISetState(@SW_SHOW)
Global $USER32_DLL = DllOpen("user32.dll") ; Utile pour les _isPressed()
_GDIPlus_Startup() ; Let's go!
$hGraphic = _GDIPlus_GraphicsCreateFromHWND($hWnd) ; Alors, ces 3 fonctions, j'ai pas très bien compris ce qu'elle font
$hBitmap = _GDIPlus_BitmapCreateFromGraphics($width, $height, $hGraphic); précisement, alors je me contente de les utilisé comme je vois dans
$hBuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap) ; les scripts de pros!
$hBuffer2 = _GDIPlus_ImageGetGraphicsContext($hBitmap) ; les scripts de pros!
;~ ; Je sais juste que $hBuffer sera le parametre des fonctions de dessins
_GDIPlus_GraphicsSetSmoothingMode($hBuffer, 2) ; ca, c'est pour l'anti-aliasing
$hImg = _GDIPlus_ImageLoadFromFile("kaniner.jpg") ; On charge l'image
$ImgW = _GDIPlus_ImageGetWidth($hImg) ; Et on récupere ses dimensions
$ImgH = _GDIPlus_ImageGetHeight($hImg) ;
AdlibRegister("_ElleTourne", 50) ; je lui fait tourner la tête
While 1
_GDIPlus_GraphicsClear($hBuffer, 0xFFFFFFFF) ; On vide le buffer, en lui donnant une couleur blanche
_GDIPlus_GraphicsClear($hBuffer2, 0xFFFFFFFF) ; On vide le buffer, en lui donnant une couleur blanche
$mos = MouseGetPos()
$matrix = _GDIPlus_MatrixCreate()
_GDIPlus_MatrixRotate($matrix, $rotdeg) ; La rotation en degré
_GDIPlus_MatrixTranslate($matrix, $mos[0] * Cos(-$rotrad) - $mos[1] * Sin(-$rotrad), $mos[0] * Sin(-$rotrad) + $mos[1] * Cos(-$rotrad))
_GDIPlus_GraphicsSetTransform($hBuffer, $matrix)
_GDIPlus_GraphicsDrawImage($hBuffer2, $hImg, $mos[0] - ($ImgW / 2), $mos[1] - ($ImgH / 2))
_GDIPlus_GraphicsDrawImage($hBuffer, $hImg, $ImgW / -2, $ImgH / -2)
_GDIPlus_GraphicsDrawImageRect($hGraphic, $hBitmap, 0, 0, $width, $height) ; On copy le graphique $hBuffer dans $hBitmap
Sleep(10)
WEnd
Func _ElleTourne()
$rotdeg += 1
$rotrad = 2 * $Pi / 360 * $rotdeg
EndFunc
Func _exit() ; Fonction de sortie (libération des ressources)
AdlibUnRegister("_ElleTourne")
_GDIPlus_MatrixDispose($matrix)
_GDIPlus_ImageDispose($hImg)
_GDIPlus_GraphicsDispose($hBuffer)
_GDIPlus_GraphicsDispose($hBuffer2)
_GDIPlus_BitmapDispose($hBitmap)
_GDIPlus_GraphicsDispose($hGraphic)
_GDIPlus_Shutdown()
Exit
EndFunc
Reste à savoir si créer à chaque fois un nouveau buffer pour chaque sprite ne sera pas trop lourd???
Je sais, je sais tlem, je vais testé! mais si quelqu'un a déjà la réponse...
En tout cas, si c'est trop lourd, je vais créer 2 types de sprites:
- ceux qui tournent, qui auront leur propre buffer
- ceux qui ne tournent pas, qui seront collés sur le buffer principal
Merci!
Re: [R] Rotation image, GDIPlus
Posté : lun. 16 mai 2011 18:44
par jchd
Des plans superposés à un décor ? Mais c'est ainsi que Walt Disney travaillait

Re: [R] Rotation image, GDIPlus
Posté : lun. 16 mai 2011 22:32
par matwachich
Ok!
Mais j'aimerai reformuler ma question:
- Est ce que, si je fais ça:
Code : Tout sélectionner
$hGraphic = _GDIPlus_GraphicsCreateFromHWND($hWnd)
$hBitmap = _GDIPlus_BitmapCreateFromGraphics($width, $height, $hGraphic)
$hBufferPrincipal = _GDIPlus_ImageGetGraphicsContext($hBitmap)
...
$hBufferDeSprite1 = _GDIPlus_ImageGetGraphicsContext($hBitmap)
$hBufferDeSprite2 = _GDIPlus_ImageGetGraphicsContext($hBitmap)
$hBufferDeSprite3 = _GDIPlus_ImageGetGraphicsContext($hBitmap)
$hBufferDeSprite4 = _GDIPlus_ImageGetGraphicsContext($hBitmap)
$hBufferDeSprite5 = _GDIPlus_ImageGetGraphicsContext($hBitmap)
$hBufferDeSprite6 = _GDIPlus_ImageGetGraphicsContext($hBitmap)
...
$hBufferDeSpriteX = _GDIPlus_ImageGetGraphicsContext($hBitmap)
Ca ne va pas alourdir le script???
En sachant que la création d'un Buffer de Sprite n'est faite qu'une seul fois, lors de la création du sprite, et pas à chaque 'collage' du sprite sur l'écran.
PS: Je rappel que c'est pour pouvoir faire tourner un sprite indépendamment des autres éléments de la scène
Re: [R] Rotation image, GDIPlus
Posté : mar. 17 mai 2011 07:42
par Yogui
j'arrive un peu après la guerre mais le sujet avait déjà été abordé ici :
http://autoitscript.fr/forum/viewtopic.php?f=3&t=5491
au pire ça peu aider un peu

Re: [R] Rotation image, GDIPlus
Posté : mar. 17 mai 2011 09:45
par jchd
Si chaque buffer ne fait que la taille du sprite, je ne vois pas de problème. Après ça sera à toi de gérer correctement l'ordre des plans pour que le rendu final soit conforme à ce que tu souhaites.
J'ai vu une fois un "package" physiks (je crois, ou un nom approchant) venant du forum allemand, qui fait une animation (2D) époustouflante (pour de l'AutoIt). Si je retrouve le lien je te le poste.
Tiens, voilà déjà
un lien sur un fil gavé de GDI AutoIt, dont le phusic engine cité.
Re: [R] Rotation image, GDIPlus
Posté : mar. 17 mai 2011 11:27
par matwachich
c'est peut être
ça le phisik engin
Quand au lien sur le forum anglais, j'ai déjà téléchargé plus de la moitié des script, c'est justement eux qui m'ont pousser à éplucher de plus près GDI+!
Re: [R] Rotation image, GDIPlus
Posté : mar. 17 mai 2011 11:39
par jchd
Oui c'est bien ça. (En allemand, un y se prononce u)
La motié de tout ça ! Gourmand, va !
Bonne chasse, il y a de quoi faire.