Basic Univers
; Little scrolling engine by Andre Guerreiro (byo)
; It's very simple and the code is a mess so if you can
; give me hints on easier approaches, I'd gladly appreciate it. :)

; Oh, and Purebasic rules!
;==========================================================


; Declaration of the things (procedures) to come!
Declare Init()
Declare DeInit()
Declare DrawMini()

; Some constants for the basic stuff as ScreenWidth and ScreenHeight for speed
#sW = 640
#sH = 480

; Enumerating images
Enumeration
 #map
 #mini
EndEnumeration

; Let's include images in the executables the PB traditional way
DataSection
 map:
  IncludeBinary "map.jpg"
 mini:
  IncludeBinary "mini.jpg"
EndDataSection

; Variables that will be there til the end
Global mouseX1, mouseX2, mouseY1, mouseY2
Global map, mini, mapX, mapY, scrollSpeed, miniX, miniY, miniW, miniH
Global MiniSelectable, miniMouseX1, miniMouseY1
Global mapW, mapH

; Every initialization before the loop is done inside this procedure
; for easy reading.
Init()

; The famous loop
Repeat
 ExamineKeyboard()
 ExamineMouse()
 
 ; I'm not sure if this is working or not. Tell me if it's not, please.
 ReleaseMouse(1 - IsScreenActive())
 
 ; Our way out of the program by pressing ESC
 If KeyboardPushed(#PB_Key_Escape)
  Exit = #True
 EndIf
 
 ; Captures the mouse inside the minimap and moves the map according to its location.
 ; My math is ugly so please help me improve, commenting what you're doing cause I
 ; suck at math. It's just about proportion and location.
 If MouseButton(#PB_MouseButton_Left)
  If(MouseX() >= miniX) And(MouseX() < miniX + miniW) And(MouseY() >= miniY) And(MouseY() < miniY + miniH)
   If MB_Left <> 2
    mapX = -((MouseX()-#sW/20)- miniX)*20 -#sW/2
    mapY = -((MouseY()-#sH/20)- miniY)*20 -#sH/2
    If mapX > 0 : mapX = 0 : EndIf
    If mapY > 0 : mapY = 0 : EndIf
    If mapX < - ImageWidth(#map)+#sW : mapX = - ImageWidth(#map)+#sW : EndIf
    If mapY < - ImageHeight(#map)+#sH : mapY = - ImageHeight(#map)+#sH : EndIf
   EndIf
  Else
   ; Thanks to Joakim Christiansen for this next little workaround routine
   ; while there is no MouseDown() native event.
   If MB_Left = 0
    MB_Left = 1
   Else
    MB_Left = 2
   EndIf
  EndIf
 Else
  If MB_Left = 3
   MB_Left = 0
  ElseIf MB_Left = 2
   MB_Left = 3
  EndIf
 EndIf
 
 ; This is where we draw everything.
 StartDrawing(ScreenOutput())
 DrawImage(ImageID(#map), mapX, mapY)
 DrawMini()
 DrawingMode(#PB_2DDrawing_Transparent)
 DrawText(miniX + miniW + 5, miniY + 5, "This is a little scrolling demo with minimap made by byo (Andre Guerreiro)", #White)
 DrawText(miniX + miniW + 5, miniY + 18, "Use the arrow keys or the mouse to scroll. You can drag a selectable region", #White)
 DrawText(miniX + miniW + 5, miniY + 31, "by holding the left mouse button. Sorry for the messy code.", #White)
 DrawText(miniX + miniW + 5, miniY + 60, "Click on the minimap and you'll get to the point selected by the mouse", #White)
 StopDrawing()
 
 ; Let's capture the left mouse button and create a selecion region if it's down.
 ; 0 is UP, 1 is PRESSED, 2 is DOWN, 3 is RELEASED
 Select MB_left
  Case 0
   FlipBuffers()
  Case 1
   mouseX1 = MouseX()
   mouseY1 = MouseY()
   miniMouseX1 = mouseX1
   miniMouseY1 = mouseY1
  Case 2
   mouseX2 = MouseX() - mouseX1
   mouseY2 = MouseY() - mouseY1
   
   StartDrawing(ScreenOutput())
   Line(mouseX1, mouseY1, mouseX2, 0, #Green)
   Line(mouseX1, mouseY1, 0, mouseY2, #Green)
   Line(MouseX(), mouseY1, 0, mouseY2, #Green)
   Line(mouseX1, mouseY1 + mouseY2, mouseX2, 0, #Green)
   DrawMini()
   StopDrawing()
   
   FlipBuffers()
  Case 3
   MB_Left = 0
 EndSelect
 
 ; Scrolling the map if the mouse it's on the 4 edges of the screen or if the
 ; player touches the arrow keys.
 If(MouseX() = 0) Or(KeyboardPushed(#PB_Key_Left))
  mapX + scrollSpeed
  If mapX > 0
   mapX = 0
  Else
   mouseX1 + scrollSpeed
  EndIf
 EndIf
 If(MouseY() = 0) Or(KeyboardPushed(#PB_Key_Up))
  mapY + scrollSpeed
  If mapY > 0
   mapY = 0
  Else
   mouseY1 + scrollSpeed
  EndIf
 EndIf
 If(MouseX() = #sW - 1) Or(KeyboardPushed(#PB_Key_Right))
  mapX - scrollSpeed
  If mapX < - ImageWidth(#map)+#sW
   mapX = - ImageWidth(#map)+#sW
  Else
   mouseX1 - scrollSpeed
  EndIf
 EndIf
 If(MouseY() = #sH - 1) Or(KeyboardPushed(#PB_Key_Down))
  mapY - scrollSpeed
  If mapY < - ImageHeight(#map)+#sH
   mapY = - ImageHeight(#map)+#sH
  Else
   mouseY1 - scrollSpeed
  EndIf
 EndIf
 
 ; This is required for dealing with the window events behind the screen
 ; Thanks to netmaestro.
 While WindowEvent() : Wend
Until Exit
; End of our confused loop.

; A little routine for freeing stuff inside variables.
DeInit()



Procedure Init()
 InitSprite()
 
 OpenWindow(0, #PB_Ignore, #PB_Ignore, #sW, #sH, "byo game", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget)
 OpenWindowedScreen(WindowID(0), 0, 0, #sW, #sH, #False, 0, 0)
 
 ClearScreen(#Black)
 StartDrawing(ScreenOutput())
 DrawingMode(#PB_2DDrawing_Transparent)
 DrawText(#sW - 100, #sH - 40, "LOADING...", #White)
 StopDrawing()
 
 FlipBuffers()
 
 InitKeyboard()
 InitMouse()
 
 ShowCursor_(#True)
 MouseLocate(#sW/2, #sH/2)
 
 UseJPEGImageDecoder()
 
 
 scrollSpeed = 10
 mapX = 0 : mapY = 0
 mapW = 2400 : mapW = 2760
 miniX = 4 : miniY = #sH - 142
 miniW = 120 : miniH = 138
 
 CatchImage(#map, ?map)
 CatchImage(#mini, ?mini)
 
EndProcedure

Procedure DeInit()
 FreeImage(#map)
 FreeImage(#mini)
EndProcedure

Procedure DrawMini()
 posX = miniX - mapX/20
 posY = miniY - mapY/20
 posW =(#sW/20)- 1
 posH =(#sH/20)- 1

 DrawImage(ImageID(#mini), miniX, miniY)
 Line(posX, posY, posW, 0, #White)
 Line(posX, posY, 0, posH, #White)
 Line(posX, posY +(posH), posW, 0, #White)
 Line(posX +(posW), posY, 0, posH + 1, #White)
EndProcedure