So ... tada

... das ganze mit Zoomfaktor und ich denke mal,
auch für schwächere Grafikkarten. Durch #PB_Sprite_Memory werden
alle Grafiken in den RAM-Speicher geladen, aber wehe es hat wer nicht
genug RAM.
Benötigter RAM:
Kaeru Gaman hat geschrieben:
400x500x500x32bit = 381,5 MB
bei #WidthoutAA = 1 werden auch die 4 Grafiken, welche für das zoomen
benutzt werden in den RAM geladen. Wenn mich nicht alles teuscht wäre
die Berechnung dann folgende: 800 x 600 x 32 = 14,65 MB
Beim Zoomen müsste der Wert dann Quadratisch zum Zoomfaktor
steigen. Ich habs mit meiner Geforce 7600 über den Zoom von 1100%
geschaft: 800 x 600 x 32 x 11² = 1772 MB
Aber die FPS gehen sofort beim rauszoomen runter -.-, am Ende sinds
2-3 FPS ...
PB-BUG:
Naja, genug Mathe ... Bei mir ergibt
Code:
If Zoom >= #ZoomStep
selbst bei gleichen Werten ein nicht eintrehten des Ereignisses, wodurch
man dann plötzlich eine 1 an der letzten Stelle hat -.-
Selbst das * 100 und dann mit Int() arbeiten hat nicht funktioniert.
Edit:kleine optimierung des Ramverbrauchs.
Die 4 Ausschnitte werden nun fürs Rauszoomen nacheinander Berechnet,
dadurch sinkt der RAM-Verbrauch erheblich. (Rechnung mach ich
vielleicht später zu) Max. auf 1250% zoomen, das ist die ganze Karte

... eine Beschränkung mach ich da jetzt extra für nicht rein.
So, jetzt aber der Code ... ist nicht besonders Übersichtlich, aber es ist
viel zu Spät um weiter drann zu arbeiten ... vielleicht irgend wann die
Tage mal wieder:
Code:
EnableExplicit
;die Größe des Fensters kann nach belieben verändert werden
#ScreenWidth = 800
#ScreenHeight = 600
;Startposition auf der Map
#StartX = 3000 ; >= 0 Und < 10000 - #ScreenWidth * Zoom
#StartY = 1000 ; >= 0 Und < 10000 - #ScreenHeight * Zoom
#WidthoutAA = 0 ; 0 oder 1 -> ein- oder ausschalten des AA
;WICHTIG!!!!
;bei ausgeschalteter AA werden die großen Grafiken in den
;Hauptspeicher gelegt!
#ScrollArea = 20 ;in Pixel
Global ScrollSpeed.f=0.1 ;pro Millisekunde (bei 100% Zoomfaktor)
Global Zoom.f = 1.0 ;in Prozent
#ZoomStep = 0.1 ;in Prozent
; ----------------------------------------------------------------------
; ----------------------------------------------------------------------
;ab hier beginnt das Programm selber, Änderungen auf eigene Gefahr *lol*
#MapWidth = 20
#MapHeight = 20
#TileWidth = 500
#TileHeight = 500
Global Sprite_LU.l, Sprite_RU.l, Sprite_LD.l, Sprite_RD.l
Global Dim Map(#MapWidth - 1, #MapHeight - 1)
Macro DisplayMapScene()
TileX = Abs(Int(X / #TileWidth))
TileY = Abs(Int(Y / #TileHeight))
For DisplayX = X % #TileWidth To Width-1 Step #TileWidth
For DisplayY = Y % #TileHeight To Height-1 Step #TileHeight
DisplaySprite(Map(TileX, TileY), DisplayX, DisplayY)
TileY + 1
Next
TileY = Abs(Int(Y / #TileHeight))
TileX + 1
Next
EndMacro
Macro ResizeError(Text)
CloseScreen():MessageRequester("ResizeSprite - Error", Text):End
EndMacro
;folgende Prozedur ist für das Zoomen nötig, aber nicht von mir:
; 02 Nov 2004 10:54:59 © by Stefan - deutsches PB-Forum
; http://forums.purebasic.com/german/viewtopic.php?t=605&start=0#DDBLT_WAIT=16777216
#DDBLT_WAIT=16777216
Structure PB_Sprite
Sprite.l
Width.w
Height.w
Depth.w
Mode.w
FileName.l
RealWidth.w
RealHeight.w
ClipX.w
ClipY.w
EndStructure
Procedure ResizeSprite(Sprite,Width,Height);Gibt bei Fehlern 0 zurück.
Protected *Sprite.PB_Sprite, *DDS.IDirectDrawSurface7, *DD.IDirectDraw7
Protected *DDS2.IDirectDrawSurface7, rect.rect, DDSD.l
If Width<=0 Or Height<=0:ProcedureReturn 0:EndIf
*Sprite.PB_Sprite=IsSprite(Sprite)
If *Sprite=0:ResizeError("Not a pb-sprite!"):EndIf
*DDS.IDirectDrawSurface7=*Sprite\Sprite
If *DDS=0:ResizeError("Not enought memory!"):EndIf
*DDS\GetDDInterface(@*DD.IDirectDraw7)
If *DD=0:ResizeError("GetInterface() faild!"):EndIf
DDSD=AllocateMemory(124)
If DDSD=0:ResizeError("Not enought memory!"):EndIf
PokeL(DDSD,124)
If *DDS\GetSurfaceDesc(DDSD):FreeMemory(DDSD):ResizeError("GetSurfaceDesc() faild!"):EndIf
PokeL(DDSD+8,Height)
PokeL(DDSD+12,Width)
If *DD\CreateSurface(DDSD,@*DDS2.IDirectDrawSurface7,0):FreeMemory(DDSD):ResizeError("CreateSurface() faild!"):EndIf
rect\left=0
rect\right=Width
rect\top=0
rect\bottom=Height
If *DDS2\Blt(rect,*DDS,0,#DDBLT_WAIT,0):FreeMemory(DDSD):*DDS\Release():ResizeError("Blt() faild!"):EndIf
FreeMemory(DDSD)
*DDS\Release()
*Sprite\Sprite=*DDS2
*Sprite\Width=Width
*Sprite\Height=Height
*Sprite\RealWidth=Width
*Sprite\RealHeight=Height
*Sprite\ClipX=0
*Sprite\ClipY=0
ProcedureReturn *DDS2
EndProcedure
; --------------------------------------------
;zeichnet die Karte an der aktuellen Position mit dem aktuellen Zoomfaktor
Procedure DisplayMap(X, Y, Width, Height)
Protected MapX.l, MapY.l, TileX.l, TileY.l, DisplayX.l, DisplayY.l
;größer als 1
If Zoom > 1
Width / 2
Height / 2
MapX = -X
MapY = -Y
;Ausschnitt links oben
ResizeSprite(Sprite_LU, Width, Height) ;Sprites auf die richtige Größe bringen
X = MapX
Y = MapY
UseBuffer(Sprite_LU);Karte auf die angepassten Sprites zeichnen
DisplayMapScene()
ResizeSprite(Sprite_LU, #ScreenWidth/2, #ScreenHeight/2);Sprites wieder an den Screen anpassen
;Ausschnitt rechts oben
ResizeSprite(Sprite_RU, Width, Height)
X = MapX - Width
Y = MapY
UseBuffer(Sprite_RU)
DisplayMapScene()
ResizeSprite(Sprite_RU, #ScreenWidth/2, #ScreenHeight/2)
;Ausschnitt links unten
ResizeSprite(Sprite_LD, Width, Height)
X = MapX
Y = MapY - Height
UseBuffer(Sprite_LD)
DisplayMapScene()
ResizeSprite(Sprite_LD, #ScreenWidth/2, #ScreenHeight/2)
;Ausschnitt rechts oben
ResizeSprite(Sprite_RD, Width, Height)
X = MapX - Width
Y = MapY - Height
UseBuffer(Sprite_RD)
DisplayMapScene()
ResizeSprite(Sprite_RD, #ScreenWidth/2, #ScreenHeight/2)
UseBuffer(-1)
;Sprites wieder an den Screen anpassen
ResizeSprite(Sprite_LU, #ScreenWidth/2, #ScreenHeight/2)
ResizeSprite(Sprite_RU, #ScreenWidth/2, #ScreenHeight/2)
ResizeSprite(Sprite_LD, #ScreenWidth/2, #ScreenHeight/2)
ResizeSprite(Sprite_RD, #ScreenWidth/2, #ScreenHeight/2)
;Sprites auf den Screen zeichnen
DisplaySprite(Sprite_LU, 0, 0)
DisplaySprite(Sprite_RU, #ScreenWidth/2, 0)
DisplaySprite(Sprite_LD, 0, #ScreenHeight/2)
DisplaySprite(Sprite_RD, #ScreenWidth/2, #ScreenHeight/2)
ElseIf Zoom = 1
X = -X
Y = -Y
DisplayMapScene()
Else ; Zoom < 1
X = -X
Y = -Y
ResizeSprite(Sprite_LU, Width, Height)
UseBuffer(Sprite_LU)
DisplayMapScene()
UseBuffer(-1)
ResizeSprite(Sprite_LU, #ScreenWidth, #ScreenHeight)
DisplaySprite(Sprite_LU, 0, 0)
EndIf
EndProcedure
;Gibt ein Sprite mit der übergebenen Szene zurück
Procedure CreateScene(X, Y, Width, Height, Mode=0)
Protected Sprite, TileX.l, TileY.l, DisplayX.l, DisplayY.l
If X > 0 : X * -1 : EndIf
If Y > 0 : Y * -1 : EndIf
If -X > #TileWidth * #MapWidth - #ScreenWidth
ProcedureReturn #False
ElseIf -Y > #TileHeight * #MapHeight - #ScreenHeight
ProcedureReturn #False
EndIf
Sprite = CreateSprite(#PB_Any, Width, Height, Mode)
If Not Sprite : ProcedureReturn #False : EndIf
UseBuffer(Sprite)
TileX = Abs(Int(X / #TileWidth))
TileY = Abs(Int(Y / #TileHeight))
For DisplayX = X % #TileWidth To Width-1 Step #TileWidth
For DisplayY = Y % #TileHeight To Height-1 Step #TileHeight
DisplaySprite(Map(TileX, TileY), DisplayX, DisplayY)
TileY + 1
Next
TileY = Abs(Int(Y / #TileHeight))
TileX + 1
Next
UseBuffer(-1)
ProcedureReturn Sprite
EndProcedure
; -------------------------------------------------------------
InitSprite()
InitKeyboard()
InitMouse()
UsePNGImageDecoder()
If Not OpenScreen(#ScreenWidth, #ScreenHeight, 32, "")
MessageRequester("Error", "Can't open screen! (" + Str(#ScreenWidth) + " X " + Str(#ScreenHeight))
End
EndIf
;laden der Grafiken
Define X.l, Y.l, i.l, Text$
x = 0
y = 0
For i = 0 To 399
ExamineKeyboard()
If KeyboardPushed(#PB_Key_All) <> #False : End : EndIf
Map(x, y) = LoadSprite(#PB_Any, "Pic" + RSet(Str(i+1), 3, "0") + ".png", #PB_Sprite_Memory)
If Not Map(X, Y)
CloseScreen()
MessageRequester("Error", "Can't load sprite " + RSet(Str(i+1), 3, "0") + "!")
End
EndIf
x + 1
If x >= 20 : y + 1 : x = 0 : EndIf
Text$ = StrF((i+1) / 400 * 100, 0) + "%"
StartDrawing(ScreenOutput())
DrawingMode(#PB_2DDrawing_Default)
Box(#ScreenWidth/2 - 103, #ScreenHeight/2 - 11, 206, 22, RGB(113, 2, 0))
Box(#ScreenWidth/2 - 100, #ScreenHeight/2 - 7, ((i+1)/2), 14, RGB(162, 3, 0))
DrawingMode(#PB_2DDrawing_Transparent | #PB_2DDrawing_XOr)
DrawText(#ScreenWidth/2 - TextWidth(Text$)/2, #ScreenHeight/2 - TextHeight(Text$)/2, Text$, $f0f0f0f0)
StopDrawing()
FlipBuffers()
Next
Define.l Sprite, Timer
Define.f MapX, MapY
MapX = #StartX
MapY = #StartY
Sprite = CreateScene(MapX, MapY, #ScreenWidth, #ScreenHeight, #PB_Sprite_Memory)
Timer = ElapsedMilliseconds()
Repeat
ExamineKeyboard()
If KeyboardPushed(#PB_Key_All) <> #False : End : EndIf
ClearScreen(0)
StartSpecialFX()
DisplayTranslucentSprite(Sprite, 0, 0, 255 * (ElapsedMilliseconds() - Timer) / 5000)
StopSpecialFX()
FlipBuffers()
Until Timer + 1000 <= ElapsedMilliseconds()
FreeSprite(Sprite)
Define.l LoopTime, MapX, MapY, FPSCounter, FPS, FPSTimer
Timer = ElapsedMilliseconds()
Sprite_LU = CreateScene(0, 0, #ScreenWidth/2, #ScreenHeight/2, #WidthoutAA * #PB_Sprite_Memory)
Sprite_RU = CreateScene(#ScreenWidth/2, 0, #ScreenWidth/2, #ScreenHeight/2, #WidthoutAA * #PB_Sprite_Memory)
Sprite_LD = CreateScene(0, #ScreenHeight/2, #ScreenWidth/2, #ScreenHeight/2, #WidthoutAA * #PB_Sprite_Memory)
Sprite_RD = CreateScene(#ScreenWidth/2, #ScreenHeight/2, #ScreenWidth/2, #ScreenHeight/2, #WidthoutAA * #PB_Sprite_Memory)
MouseLocate(#ScreenWidth/2, #ScreenHeight/2)
Repeat
;Mausereignisse
ExamineMouse()
;bewegen in der Umgebung indem die Maus an den Rand bewegt wird
If MouseX() < #ScrollArea
If MouseY() < #ScrollArea
MapX = MapX - LoopTime * ScrollSpeed/2
MapY = MapY - LoopTime * ScrollSpeed/2
If MapY < 0 : MapY = 0 : EndIf
ElseIf MouseY() > #ScreenHeight - #ScrollArea
MapX = MapX - LoopTime * ScrollSpeed/2
MapY = MapY + LoopTime * ScrollSpeed/2
If MapY > #TileHeight * #MapHeight - #ScreenHeight * Zoom : MapY = #TileHeight * #MapHeight - #ScreenHeight * Zoom : EndIf
Else
MapX = MapX - LoopTime * ScrollSpeed
EndIf
If MapX < 0 : MapX = 0 : EndIf
ElseIf MouseX() > #ScreenWidth - #ScrollArea
If MouseY() < #ScrollArea
MapX = MapX + LoopTime * ScrollSpeed/2
MapY = MapY - LoopTime * ScrollSpeed/2
If MapY < 0 : MapY = 0 : EndIf
ElseIf MouseY() > #ScreenHeight - #ScrollArea
MapX = MapX + LoopTime * ScrollSpeed/2
MapY = MapY + LoopTime * ScrollSpeed/2
If MapY > #TileHeight * #MapHeight - #ScreenHeight * Zoom: MapY = #TileHeight * #MapHeight - #ScreenHeight * Zoom : EndIf
Else
MapX = MapX + LoopTime * ScrollSpeed
EndIf
If MapX > #TileWidth * #MapWidth - #ScreenWidth * Zoom : MapX = #TileWidth * #MapWidth - #ScreenWidth * Zoom : EndIf
ElseIf MouseY() < #ScrollArea
MapY = MapY - LoopTime * ScrollSpeed
If MapY < 0 : MapY = 0 : EndIf
ElseIf MouseY() > #ScreenHeight - #ScrollArea
MapY = MapY + LoopTime * ScrollSpeed
If MapY > #TileHeight * #MapHeight - #ScreenHeight * Zoom : MapY = #TileHeight * #MapHeight - #ScreenHeight * Zoom : EndIf
EndIf
;Zoomfaktor per Mausrad
i = -MouseWheel()
While i
If i > 0
;-PB-BUG
;If Int(Zoom*100) >= Int(#ZoomStep*100)
If Zoom >= #ZoomStep
ScrollSpeed * (1 + #ZoomStep)
Zoom + #ZoomStep
MapX - #ZoomStep/2 * #ScreenWidth
MapY - #ZoomStep/2 * #ScreenHeight
Else
ScrollSpeed * (1 + #ZoomStep/10)
Zoom + #ZoomStep/10
MapX - #ZoomStep/20 * #ScreenWidth
MapY - #ZoomStep/20 * #ScreenHeight
EndIf
If MapX < 0 : MapX = 0 : EndIf
If MapY < 0 : MapY = 0 : EndIf
If MapY > #TileHeight * #MapHeight - #ScreenHeight * Zoom : MapY = #TileHeight * #MapHeight - #ScreenHeight * Zoom : EndIf
If MapX > #TileWidth * #MapWidth - #ScreenWidth * Zoom : MapX = #TileWidth * #MapWidth - #ScreenWidth * Zoom : EndIf
i - 1
ElseIf i < 0
If Zoom > #ZoomStep
ScrollSpeed / (1 + #ZoomStep)
Zoom - #ZoomStep
MapX + #ZoomStep/2 * #ScreenWidth
MapY + #ZoomStep/2 * #ScreenHeight
ElseIf Zoom > #ZoomStep/10
ScrollSpeed / (1 + #ZoomStep / 10)
Zoom - #ZoomStep/10
MapX + #ZoomStep/20 * #ScreenWidth
MapY + #ZoomStep/20 * #ScreenHeight
EndIf
i + 1
EndIf
Wend
;Karte anzeigen
DisplayMap(MapX, MapY, #ScreenWidth * Zoom, #ScreenHeight * Zoom)
FPSCounter + 1
If ElapsedMilliseconds() >= FPSTimer + 1000 : FPS = FPSCounter : FPSCounter = 0 : FPSTimer = ElapsedMilliseconds() : EndIf
;GUI
StartDrawing(ScreenOutput())
DrawingMode(1)
DrawText(5, 5, "FPS: " + Str(FPS))
DrawText(75, 5, "Zoom: " + Str(Zoom * 100) + " %")
Circle(MouseX(), MouseY(), 2, $FFFFFF)
StopDrawing()
FlipBuffers()
;Zeitberechnung
LoopTime = ElapsedMilliseconds() - Timer
Timer = ElapsedMilliseconds()
;Tastatur, per Any-Key aus dem ganzen raus gehen
ExamineKeyboard()
Until KeyboardPushed(#PB_Key_All) <> #False
Ach ja, gesteuert wird mit der Maus. Das heißt an die Ränder bewegen
oder das Mausrad benutzten zum zoomen. Eigentlich wollt ich noch das
Scrollen beschleunigen, wenn man dem Rand näher kommt, aber keine
Zeit^^
Ok, Tastatur ist auch drinne, aber nur für die Any-Key ... zum beenden.
Also ... viel Spaß damit
Wichtig:
Benutzung des Programmes nur für private Zwecke. Die benötigten Bilder
dürfen nicht mit dem obigen Code weiter verbreitet werden, sofern diese
durch ein Copyright geschützt sind, so wie es für die Grafiken der
verlinkten Seite dieses Threads der Fall ist!
MFG PMV