Le code n'est pas propre mais je vais bosser maintenant sur l'amélioration de celui si et sur son optimisation
Code : Tout sélectionner
;- #### Animation ####
; *Animation DataSheet
; Offset | Size | Type | Description
; 0 | 2 | .w | Frames
; 2 | 1 | .b | 0 No Loop Animation / 1 Loop Animation
; 3 | 4 | * | IdSprite Frame[ 1]
; 7 | 2 | .w | Temps d'affichage en milliseconde
; 9 | 4 | * | IdSprite Frame[ 2]
; 13 | 2 | .w | Temps d'affichage en milliseconde
; 3+x*6 | 4 | * | IdSprite Frame[ x]
; 7+x*6 | 2 | .w | Temps d'affichage en milliseconde
;etc....
;Ajout d'un sprite a une animation
Procedure SetSpriteToAnimation(*Anim, IdSprite.l, Time.w)
If *Anim>0
Size.l = MemorySize(*Anim)
Else
Size.l = 3
*Anim = AllocateMemory(Size)
EndIf
*Anim = ReAllocateMemory(*Anim, Size + 6)
PokeW(*Anim, PeekW(*Anim) + 1)
PokeL(*Anim + Size, IdSprite)
PokeW(*Anim + Size + 4, Time)
ProcedureReturn *Anim
EndProcedure
;Retourne le sprite correspondant a l'image d'une Animation
Procedure.l GetSpriteFromAnimation(*Anim, Frame.w)
Location.l = 3 + Frame*6
If Location<MemorySize(*Anim)
ProcedureReturn PeekL(*Anim + Location) :
Else
ProcedureReturn #False
EndIf
EndProcedure
;Retourne le temps d'affichage d'une imge dans une animation
Procedure.l GetTimeSpriteFromAnimation(*Anim, Frame.w)
Location.l = 7 + Frame*6
If Location<MemorySize(*Anim)
ProcedureReturn PeekW(*Anim + Location) :
Else
ProcedureReturn #False
EndIf
EndProcedure
;Active ou desactive le bouclage de l'annimation
Procedure.b SetAnimationLoop(*Anim, Loop.b)
If *Anim>0
PokeB(*Anim + 2, Loop)
ProcedureReturn #True
Else
ProcedureReturn #False
EndIf
EndProcedure
;Retourne le nombre d'image dans une animation
Procedure GetFramesAnimation(*Anim)
ProcedureReturn PeekW(*Anim)
EndProcedure
;Retourne 1 si l'animation est Bouclé et 0 dans le cas contraire
Procedure.b GetAnimationLoop(*Anim)
If *Anim>0
ProcedureReturn PeekB(*Anim + 2)
EndIf
EndProcedure
;-#### Element ####
; *Element DataSheet
; Offset | Size | Type | Description
; 0 | 2 | .w | States
; 2 | 1 | .b | 0 l'animation est Global / 1 l'animation est unique
; 3 | 2 | .w | CurrentFrame / Si l'animation est Global alors on utilise cet enplassement pour connaitre l'image actuel de l'animation
; 5 | 4 | .l | Si l'animation est Global alors on utilise cet enplassement pour connaitre le prochain temps de changement d'image
; 9 | 1 | .b | 0 IdSprite / 1 *Animation State[1]
; 10 | 4 | * | IdSprite or *Animation State[1]
; 14 | 1 | .b | 0 IdSprite / 1 *Animation State[2]
; 15 | 4 | * | IdSprite or *Animation State[2]
; 9+x*5 | 1 | .b | 0 IdSprite / 1 *Animation State[x]
; 10+x*5 | 4 | * | IdSprite or *Animation State[x]
Procedure DebugElement(*Element)
Debug"__________"
Debug "Element:" + Str(*Element)
Debug "States :" + Str(PeekW(*Element)); 0 | 2 | .w | States
Debug "Animation Type :" + Str(PeekB(*Element + 2)); 2 | 1 | .b | 0 l'animation est Global / 1 l'animation est unique
Debug "CurrentFrame:" + Str(PeekW(*Element + 3)); 3 | 2 | .w | CurrentFrame / Si l'animation est Global alors on utilise cet enplassement pour connaitre l'image actuel de l'animation
Debug "NextTime:" + Str(PeekL(*Element + 3));; 5 | 4 | .l | Si l'animation est Global alors on utilise cet enplassement pour connaitre le prochain temps de changement d'image
For z = 0 To PeekW(*Element)-1
Debug "Type" + Str(z + 1) + " :" + Str(PeekB(*Element + 9*z*5)); 9 | 1 | .b | 0 IdSprite / 1 *Animation State[1]
Debug "Sprite/Anim" + Str(z + 1) + " :" + Str(PeekL(*Element + 10*z*5)); 10 | 4 | * | IdSprite or *Animation State[1]
Next
EndProcedure
;Rajoute une animation ou une image a un Element
Procedure SetStatetoElement(*Element, *Anim, IdSprite = 0)
If *Element>0 ;si l'element existe on regarde sa taille
Size.l = MemorySize(*Element)
Else ;si l'element n'existe pas on le créer
Size.l = 9
*Element = AllocateMemory(Size)
PokeB(*Element + 2, 0)
EndIf
*Element = ReAllocateMemory(*Element, Size + 5)
PokeW(*Element, PeekW(*Element) + 1) ;Ajout d'un etat
State = PeekW(*Element)-1
If *Anim>0 ; Si c'est une Animation
PokeB(*Element + 9 + State*5, 1)
PokeL(*Element + 10 + State*5, *Anim)
Else ; Si c'est un Sprite
PokeB(*Element + 9 + State*5, 0)
PokeL(*Element + 10 + State*5, IdSprite)
EndIf
ProcedureReturn *Element
EndProcedure
;position l'animation d'un element
Procedure SetFrameToElement(*Element, Frame.w)
PokeW(*Element + 3, Frame)
EndProcedure
;-#### Map ####
;*Map(Coord X, Coord Y, Level)
#MapMaxWidth = 512
#MapMaxHeight = 512
#MapMaxLevel = 4
#TILE_W=64
#TILE_H=32
Structure Map
*Element ;Pointeur vers l'element
ElementState.w ;Etat de l'element
Time.l ;Si l'animation est uniquel alors on utilise cet enplassement pour connaitre le prochain temps de changement d'image
IdScript.l ;Script lors d'un action sur cet Element
EndStructure
Global Dim Map.Map(#MapMaxWidth, #MapMaxHeight, #MapMaxLevel)
Procedure GetSpriteFromMap(X.l, Y.l, L.l)
If X<0 Or X>#MapMaxWidth Or Y<0 Or Y>#MapMaxHeight
ProcedureReturn 0
EndIf
*Element = Map(X, Y, L)\Element;
If *Element>0
State = (Map(X, Y, L)\ElementState + 1)-1
If PeekB(*Element + 9 + State*5) = 0 ;Si c'est un Sprite
ProcedureReturn PeekL(*Element + 10 + State*5);On retourne l'idsprite
Else ;Si c'est une animation
*Anim = PeekL(*Element + 10 + State*5)
If PeekB(*Element + 2) = 0 ;Si l'animation est Global
Frame.w = PeekW(*Element + 3)
If PeekL(*Element + 5) = 0 :
PokeL(*Element + 5, ElapsedMilliseconds() + GetTimeSpriteFromAnimation(*Anim, Frame))
EndIf
If ElapsedMilliseconds()>PeekL(*Element + 5);Si le temps s'est écoulé pour cette image
Frame.w + 1;on passe a l'image suivante
If Frame>GetFramesAnimation(*Anim)-1 ; si on depasse le nombre d'image du film
SetAnimationLoop(*Anim, #True)
If GetAnimationLoop(*Anim) = #True ;Si on boucle
Frame = 0
Else
Frame-1
EndIf
EndIf
SetFrameToElement(*Element, Frame);On rafraichit l'image courante
PokeL(*Element + 5, ElapsedMilliseconds() + GetTimeSpriteFromAnimation(*Anim, Frame));(On note quand est ce qu'on passera a l'image suivante
EndIf
EndIf
ProcedureReturn GetSpriteFromAnimation(*Anim, Frame.w)
EndIf
EndIf
EndProcedure
;###############################################################################
;On test
;###############################################################################
InitSprite()
InitMouse()
InitKeyboard()
OpenWindow(0, 0, 0, 640, 480, "Un écran dans une fenêtre...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0), 0, 0, 640, 480, 0, 0, 0)
;Creation d'un Element et attribution d'une animation
;Sol
CreateSprite(0, 64, 64)
StartDrawing(SpriteOutput(0))
col = RGB(115, 53, 8)
LineXY(0, 48, 32, 32, col)
LineXY(32, 32, 64, 48, col)
LineXY(64, 48, 32, 64, col)
LineXY(32, 64, 0, 48, col)
FillArea(32, 48, -1, RGB(115, 53, 8))
StopDrawing()
*ElementSol = 0
*ElementSol = SetStatetoElement(*ElementSol, 0, 0)
;Poteau
CreateSprite(11, 64, 64)
StartDrawing(SpriteOutput(11))
col = RGB(115, 53, 8)
LineXY(0, 48, 32, 32, col)
LineXY(32, 32, 64, 48, col)
LineXY(64, 48, 32, 64, col)
LineXY(32, 64, 0, 48, col)
FillArea(32, 48, -1, RGB(115, 53, 8))
LineXY(30, 48, 30, 0, #Green)
LineXY(31, 49, 31, 1, #Green)
LineXY(32, 50, 32, 2, #Green)
LineXY(33, 49, 33, 1, RGB(0, 150, 0))
LineXY(34, 48, 34, 0, RGB(0, 150, 0))
StopDrawing()
*ElementPoteau = 0
*ElementPoteau = SetStatetoElement(*ElementPoteau, 0, 11)
SaveSprite(11, "test.bmp")
;Eau
*AnimEau = 0
For z = 1 To 10
CreateSprite(z, 64, 64)
StartDrawing(SpriteOutput(z))
col = #Blue
LineXY(0, 48, 32, 32, col)
LineXY(32, 32, 64, 48, col)
LineXY(64, 48, 32, 64, col)
LineXY(32, 64, 0, 48, col)
FillArea(32, 48, -1, #Blue)
For n = 1 To 10
Line(Random(64), 32 + Random(32), Random(16), 0, RGB(100, 100, 255))
Next
StopDrawing()
*AnimEau = SetSpriteToAnimation(*AnimEau, z, 500)
Next
;creation d'une carte
*ElementEau = 0
*ElementEau = SetStatetoElement(*ElementEau, *AnimEau)
For x = 0 To 10
For y = 0 To 16
Map(x, y, 0)\Element = *ElementEau
Next
Next
Map(2, 2, 0)\Element = *ElementPoteau
Map(5, 5, 0)\Element = *ElementSol
Map(5, 6, 0)\Element = *ElementSol
Map(6, 6, 0)\Element = *ElementSol
Map(5, 7, 0)\Element = *ElementSol
;Simple render de tile
#TILE_W=64
#TILE_H=32
;Simple render de tile
Procedure.f Real2IsoX(X.l, Y.l)
ProcedureReturn X-Y
EndProcedure
Procedure.f Real2IsoY(X.l, Y.l)
ProcedureReturn (Y + X)/2
EndProcedure
Procedure Iso2RealX(X.l,Y.l)
Mx.f=(X-WindowCenterX)/#TILE_W*2
My.f=(Y-WindowCenterY)/#TILE_H
ey.f=(2*My-Mx)/2
ex.f=Mx+ey
ProcedureReturn ex
EndProcedure
Procedure Iso2RealY(X.l,Y.l)
Mx.f=(X-WindowCenterX)/#TILE_W*2
My.f=(Y-WindowCenterY)/#TILE_H
ey.f=(2*My-Mx)/2
ex.f=Mx+ey
ProcedureReturn ey
EndProcedure
Procedure InitRenderingWindows(Width,Height)
EndProcedure
Procedure DrawTile(IsoX.l,IsoY.l,Color.l)
X1 = IsoX
Y1 = IsoY - #TILE_H/2
X2 = IsoX + #TILE_W/2
Y2 = IsoY
X3 = IsoX
Y3 = IsoY + #TILE_H/2
X4 = IsoX - #TILE_W/2
Y4 = IsoY
LineXY(X1,Y1,X2,Y2,Color)
LineXY(X2,Y2,X3,Y3,Color)
LineXY(X3,Y3,X4,Y4,Color)
LineXY(X4,Y4,X1,Y1,Color)
EndProcedure
Procedure Render(PointerXReal.l, PointerYReal.l)
WindowWidth.l =520
WindowHeight.l = 300
WindowCenterX=Int(WindowWidth/2)
WindowCenterY=Int(WindowHeight/2)
WindowTileCenterX=Round(WindowCenterX/32,#PB_Round_Up )
WindowTileCenterY=Round(WindowCenterY/16,#PB_Round_Up )
UnitIso.l=32;Round(Sqr(Pow(16,2)+Pow(32,2)),#PB_Round_Down );
PointerX.l=PointerXReal/UnitIso
PointerY.l=PointerYReal/UnitIso
DeltaXReal.l = PointerXReal-PointerX*UnitIso
DeltaYReal.l = PointerYReal-PointerY*UnitIso
CreateSprite(200, WindowWidth, WindowHeight)
UseBuffer(200)
TileMapWidth=(WindowTileCenterX+WindowTileCenterY) ;Retirer le /4 c'est juste pour voir si la map est bien centré
MapWidth=WindowTileCenterX*32
For Y = 0 To TileMapWidth
For X = 0 To TileMapWidth
_X = (X*#TILE_W/2)
_Y = (Y*#TILE_H)
IsoX = (_X-_Y)+WindowCenterX-Real2IsoX(DeltaXReal,DeltaYReal)
IsoY = ((_X+_Y)/2)+WindowCenterY-Int(TileMapWidth/2)*32-Real2IsoY(DeltaXReal,DeltaYReal)
If IsoX>=-64 And IsoX<=WindowWidth+64 And IsoY>=-64 And IsoY<=WindowHeight+64
Sprite = GetSpriteFromMap(PointerX + x-WindowTileCenterX, PointerY + y-WindowTileCenterY, 0)
If Sprite> = 0 And IsSprite(Sprite)
DisplayTransparentSprite(Sprite, IsoX, IsoY-SpriteHeight(Sprite))
EndIf
EndIf
Next x
Next y
StartDrawing(SpriteOutput(200))
For Y = 0 To TileMapWidth
For X = 0 To TileMapWidth
_X = (X*#TILE_W/2)
_Y = (Y*#TILE_H)
IsoX = (_X-_Y)+WindowCenterX-Real2IsoX(DeltaXReal,DeltaYReal)
IsoY = ((_X+_Y)/2)+WindowCenterY-Int(TileMapWidth/2)*32-Real2IsoY(DeltaXReal,DeltaYReal)
If IsoX>=-64 And IsoX<=WindowWidth+64 And IsoY>=-64 And IsoY<=WindowHeight+64
DrawTile(IsoX,IsoY,RGB(255,255,255))
;Circle(IsoX,IsoY,5,#Green)
EndIf
Next x
Next y
Mx.f=(MouseX()-WindowCenterX)/#TILE_W*2
My.f=(MouseY()-WindowCenterY)/#TILE_H
ey.f=(2*My-Mx)/2
ex.f=Mx+ey
;ex=(ex-WindowTileCenterX+PointerX)
;ey=ey+PointerY
DrawTile(Real2IsoX(ex,ey)*32+WindowCenterX-Real2IsoX(DeltaXReal,DeltaYReal),Real2IsoY(ex,ey)*32+WindowCenterY-Real2IsoY(DeltaXReal,DeltaYReal),#Red)
DrawText(10, 40, "X:" + Str(ex+PointerX) + " Y:" + Str(ey+PointerY)+" PX:"+Str(PointerX)+" PY:"+Str(PointerY))
Circle(MouseX(),MouseY(),2,#Yellow)
Circle(WindowCenterX,WindowCenterY,2,#Red)
StopDrawing()
UseBuffer(-1)
DisplaySprite(200, 0, 0)
EndProcedure
Repeat
; Il est très important de traiter tous les événements restants dans la file d'attente à chaque tour
;
Repeat
Event = WindowEvent()
If Event = #PB_Event_CloseWindow
End
EndIf
Until Event = 0
ExamineMouse()
ExamineKeyboard()
ExamineMouse()
If KeyboardPushed(#PB_Key_Up) : PointerYReal + 1 : EndIf
If KeyboardPushed(#PB_Key_Down) : PointerYReal-1 : EndIf
If KeyboardPushed(#PB_Key_Left) : PointerXReal-1 : EndIf
If KeyboardPushed(#PB_Key_Right) : PointerXReal + 1 : EndIf
If KeyboardPushed(#PB_Key_Escape):End:EndIf
FlipBuffers()
ClearScreen(#Red)
render(PointerXReal, PointerYReal)
Delay(1)
ForEver