Arkano3d - Arkanoid Clone in 3D

Spiele, Demos, Grafikzeug und anderes unterhaltendes.
Benutzeravatar
Makke
Beiträge: 156
Registriert: 24.08.2011 18:00
Computerausstattung: AMD Ryzen 7 5700X - AMD Radeon RX 6800 XT - 32 GB DDR4 SDRAM
Wohnort: Ruhrpott
Kontaktdaten:

Arkano3d - Arkanoid Clone in 3D

Beitrag von Makke »

Hallo zusammen,

ich beschäftige mich seit einiger Zeit mit den 3D Features von Purebasic, einiges an Testzeit ist für 3D Kollisionen usw. draufgegangen. Im Laufe der Zeit habe ich dann mal angefangen ein ganz simples Spiel mit Namen Arkanoid, einige kennen das vielleicht noch, zu programmieren.

Es gibt keine zusätzlichen Grafik oder Modelldateien (dementsprechend simpel sieht es auch aus), alles mit Purebasic erschaffen. Es gibt auch nur 5 Level, insgesamt finde ich das Spielprinzip unter 3D Bedingungen ziemlich schwer.

Ich habe es unter Windows mit Purebasic 5.11 32-bit geschrieben. Wenn man die Compilereinstellungen auf OpenGL setzt funktioniert es auch, es könnte somit auch unter Linux und MacOS laufen, habe aber keine Möglichkeit das zu testen. Für jegliche Tips, Anregungen und vor allem Fehlermeldungen bin ich dankbar.

Nun aber viel Spaß beim anschauen.

Ich musste den Code leider auf zwei Beiträge aufsplitten, also bitte den gesamten Code (aus Beitrag 1 und 2) in eine Datei kopieren

Code: Alles auswählen

;- ARKANO3D, an Arkanoid clone in 3D
;- written in Purebasic 5.11 in 2013 by Makke

EnableExplicit

;- CONSTANTS

;--- Sprites
Enumeration 
  #Spr_ScreenShot
  #Spr_SwitchBlend
  #Spr_SwitchFinish
  #Spr_SwitchScore
  #Spr_SwitchBalls
  #Spr_SwitchTime
  #Spr_SwitchContinue
EndEnumeration

;--- Textures
Enumeration 
  #Tex_Paddle
  #Tex_PaddleBuild
  #Tex_Ball
  #Tex_BallTarget
  #Tex_BallTarget01
  #Tex_BallTarget02
  #Tex_BallTarget03
  #Tex_BallTarget04
  #Tex_BallTarget05
  #Tex_BallTouch
  #Tex_BallTouch01
  #Tex_BallTouch02
  #Tex_BallTouch03
  #Tex_BallTouch04
  #Tex_BallTouch05
  #Tex_BallTouch06
  #Tex_BallTouch07
  #Tex_BallTouch08
  #Tex_BallTouch09
  #Tex_BallTouch10
  #Tex_Room01
  #Tex_Room02
  #Tex_Room03
  #Tex_Block01
  #Tex_Block02
  #Tex_Block03
  #Tex_Block04
  #Tex_Block05
  #Tex_Block06
  #Tex_Block07
  #Tex_Block08
  #Tex_Block01Ani01
  #Tex_Block01Ani02
  #Tex_Block01Ani03
  #Tex_Block01Ani04
  #Tex_Block01Ani05
  #Tex_Block02Ani01
  #Tex_Block02Ani02
  #Tex_Block02Ani03
  #Tex_Block02Ani04
  #Tex_Block02Ani05
  #Tex_Block03Ani01
  #Tex_Block03Ani02
  #Tex_Block03Ani03
  #Tex_Block03Ani04
  #Tex_Block03Ani05
  #Tex_Block04Ani01
  #Tex_Block04Ani02
  #Tex_Block04Ani03
  #Tex_Block04Ani04
  #Tex_Block04Ani05
  #Tex_Block05Ani01
  #Tex_Block05Ani02
  #Tex_Block05Ani03
  #Tex_Block05Ani04
  #Tex_Block05Ani05
  #Tex_Block06Ani01
  #Tex_Block06Ani02
  #Tex_Block06Ani03
  #Tex_Block06Ani04
  #Tex_Block06Ani05
  #Tex_Block07Ani01
  #Tex_Block07Ani02
  #Tex_Block07Ani03
  #Tex_Block07Ani04
  #Tex_Block07Ani05
  #Tex_Block08Ani01
  #Tex_Block08Ani02
  #Tex_Block08Ani03
  #Tex_Block08Ani04
  #Tex_Block08Ani05
  #Tex_Bonus01
  #Tex_Bonus02
  #Tex_Bonus03
  #Tex_Bonus04
  #Tex_Bonus05
  #Tex_Scoreboard
EndEnumeration

;--- Materials
Enumeration 
  #Mat_Paddle
  #Mat_PaddleBuild
  #Mat_Ball
  #Mat_BallTarget
  #Mat_BallTarget01
  #Mat_BallTarget02
  #Mat_BallTarget03
  #Mat_BallTarget04
  #Mat_BallTarget05
  #Mat_BallTouch
  #Mat_BallTouch01
  #Mat_BallTouch02
  #Mat_BallTouch03
  #Mat_BallTouch04
  #Mat_BallTouch05
  #Mat_BallTouch06
  #Mat_BallTouch07
  #Mat_BallTouch08
  #Mat_BallTouch09
  #Mat_BallTouch10
  #Mat_Room01
  #Mat_Room02
  #Mat_Room03
  #Mat_Block01
  #Mat_Block02
  #Mat_Block03
  #Mat_Block04
  #Mat_Block05
  #Mat_Block06
  #Mat_Block07
  #Mat_Block08
  #Mat_Block01Ani01
  #Mat_Block01Ani02
  #Mat_Block01Ani03
  #Mat_Block01Ani04
  #Mat_Block01Ani05
  #Mat_Block02Ani01
  #Mat_Block02Ani02
  #Mat_Block02Ani03
  #Mat_Block02Ani04
  #Mat_Block02Ani05
  #Mat_Block03Ani01
  #Mat_Block03Ani02
  #Mat_Block03Ani03
  #Mat_Block03Ani04
  #Mat_Block03Ani05
  #Mat_Block04Ani01
  #Mat_Block04Ani02
  #Mat_Block04Ani03
  #Mat_Block04Ani04
  #Mat_Block04Ani05
  #Mat_Block05Ani01
  #Mat_Block05Ani02
  #Mat_Block05Ani03
  #Mat_Block05Ani04
  #Mat_Block05Ani05
  #Mat_Block06Ani01
  #Mat_Block06Ani02
  #Mat_Block06Ani03
  #Mat_Block06Ani04
  #Mat_Block06Ani05
  #Mat_Block07Ani01
  #Mat_Block07Ani02
  #Mat_Block07Ani03
  #Mat_Block07Ani04
  #Mat_Block07Ani05
  #Mat_Block08Ani01
  #Mat_Block08Ani02
  #Mat_Block08Ani03
  #Mat_Block08Ani04
  #Mat_Block08Ani05
  #Mat_Bonus01
  #Mat_Bonus02
  #Mat_Bonus03
  #Mat_Bonus04
  #Mat_Bonus05
  #Mat_Scoreboard
EndEnumeration

;--- Meshes
Enumeration 
  #Msh_Paddle
  #Msh_PaddleBuildSph
  #Msh_PaddleBuildCyl01
  #Msh_PaddleBuildCyl02
  #Msh_Ball
  #Msh_BallTarget
  #Msh_BallTouch
  #Msh_RoomLF
  #Msh_RoomRT
  #Msh_RoomTP
  #Msh_RoomBT
  #Msh_RoomFR
  #Msh_Block
  #Msh_Bonus
  #Msh_Scoreboard
EndEnumeration

;--- Entities
Enumeration 
  #Ent_Paddle
  #Ent_PaddleBuildSph01
  #Ent_PaddleBuildSph02
  #Ent_PaddleBuildSph03
  #Ent_PaddleBuildSph04
  #Ent_PaddleBuildCyl01
  #Ent_PaddleBuildCyl02
  #Ent_PaddleBuildCyl03
  #Ent_PaddleBuildCyl04
  #Ent_Ball
  #Ent_BallTarget
  #Ent_BallTouch
  #Ent_RoomLF
  #Ent_RoomRT
  #Ent_RoomTP
  #Ent_RoomBT
  #Ent_RoomFR
  #Ent_Scoreboard
EndEnumeration

;--- Nodes
Enumeration 
  #Nod_Paddle
EndEnumeration

;--- Camera & Lights
Enumeration 
  #Cam_Main
  #Cam_Ball
  #Cam_Overview
  #Lgt_Paddle
  #Lgt_RoomRL
  #Lgt_RoomRR
  #Lgt_RoomTL
  #Lgt_RoomTR
EndEnumeration


#Obj_Paddle = - 1 << 1
#Obj_Wall   = - 1 << 2
#Obj_Block  = - 1 << 3

#Pos_Paddle_X   = 0
#Pos_Paddle_Y   = 0
#Pos_Paddle_Z   = 0
#Size_Paddle_X  = 200
#Size_Paddle_Y  = 100
#Size_Paddle_Z  = 10
#Size_Ball_Radi = 25
#Size_Block_X   = 200
#Size_Block_Y   = 100
#Size_Block_Z   = 100

;- STRUCTURES

Structure fVector3D
  x.f
  y.f
  z.f
EndStructure

Structure Box3D
  h.i
  hMat.i
  hit.i
  bonus.i
  Array p.fVector3D(7)
EndStructure

Structure MaterialAnimation
  hMat.i
  hEnt.i
  change.f
  steps.i
  singlestep.f
  count.f
EndStructure

Structure SingleBillboard
  h.i
  d.fVector3D
EndStructure

Structure BillBoardAnimation
  hGroup.i
  hMat.i
  change.f
  steps.i
  singlestep.f
  count.f
  List bills.SingleBillboard()
EndStructure

;- VARIABLES

;--- Application Desc
Define AppName.s     = "ARKANO3D"
Define AppMajor.i    = 0
Define AppMinor.i    = 1
Define AppVersion.s  = Str(AppMajor)+"."+Str(AppMinor)+"."+Str(#PB_Editor_BuildCount)
Define AppDuration.i = ElapsedMilliseconds()
Define AppLogging.i  = #False
Define AppLogFile.s  = LCase(AppName)+".log"
Define AppConfFile.s = LCase(AppName)+".conf"

;--- Environment
Define.i hLog, FullScreen, WindowWidth, WindowHeight, WindowEvt, DoLoop, DoScreenshot, ViewCam, BallLocked, BallTouched, ShadowsEnabled, MaterialFilter, MaterialAniMax, AntiAlias
Define.i BlockWidth, BlockHeight, BlockDepth, LevelAreaX, LevelAreaY, LevelAreaZ
Define.i PlayerScore, PlayerBalls, PlayerTime, PlayerLevel, PlayerLevelstart, LevelSwitch

;--- Positions
Define.fVector3D Pos_Cam, Pos_Pad, Pos_Ball, Dir_Ball

;--- Lists
NewList Ent_Blocks.Box3D()
NewList BallTouchAnim.MaterialAnimation()
NewList BlockAnim.BillBoardAnimation()

Dim RoomBox.fVector3D(7)

;- PROCEDURES (Declare)
Declare.s FormatTime(Miliseconds.i)
Declare LogIt(Text.s)
Declare MainMenu()
Declare CalcRoomPoints()
Declare CreateTextures()
Declare CreateMaterials()
Declare CreateMeshes()
Declare CreateEntities()
Declare CreateScoreBoard()
Declare NewBall()
Declare CreateNewLevel(LevelNo.i)
Declare LevelFinished()
Declare CreateLights()
Declare ShowActionCam()
Declare ShowTouchAnim()
Declare ShowBlockDestroyAnim()
Declare BallBall_Collision(*Ball1.fVector3D, *Ball2.fVector3D, Radi1.i, Radi2.i)
Declare BallBlock_Collision(*box.Box3D, *point.fVector3D)
Declare MovePaddel()
Declare MoveBall()
Declare MoveBallTarget()
Declare SaveSettings()

;- MACROS
Macro PrintV(v)
  Debug "x="+StrF(v\x,1)+", y="+StrF(v\y,1)+", z="+StrF(v\z,1)
EndMacro

Macro Do(Status, Error, EndProgram = #True)
  If Not Status
    LogIt("Error")
    CompilerIf #PB_Compiler_Debugger
      Debug "ERROR: " + Error
    CompilerElse
      MessageRequester("ERROR", Error)
    CompilerEndIf
    CompilerIf EndProgram
      End
    CompilerEndIf
  EndIf
EndMacro

;- START MAIN
Select UCase(ProgramParameter())
  Case "LOG"
    hLog = CreateFile(#PB_Any, AppLogFile)
    If IsFile(hLog)
      WriteStringN(hLog, "[" + FormatTime(ElapsedMilliseconds()-AppDuration) + "]" + Space(2) + AppName+" v"+AppVersion+" log file")
      CloseFile(hLog)
      AppLogging = #True
    EndIf
EndSelect

FullScreen = #True

If AppLogging
  Do(InitEngine3D(#PB_Engine3D_DebugLog), "Can not init 3D Engine")
Else
  Do(InitEngine3D(), "Can not init 3D Engine")
EndIf
Do(InitSprite(), "Can not init Sprite")
Do(InitKeyboard(), "Can not init Keyboard")
Do(InitMouse(), "Can not init Mouse")
Do(InitSound(), "Can not init Sound")
Do(ExamineDesktops(), "Can not find Desktops")
If FullScreen
  WindowWidth  = DesktopWidth(0)
  WindowHeight = DesktopHeight(0)
  Do(OpenScreen(WindowWidth, WindowHeight, DesktopDepth(0), AppName, #PB_Screen_SmartSynchronization), "Can not open screen")
  AntialiasingMode(#PB_AntialiasingMode_x4)
  LogIt("finished hardware initialization, opened screen with "+Str(WindowWidth)+"x"+Str(WindowHeight)+" px")
Else
  WindowWidth  = DesktopWidth(0)/1.5
  WindowHeight = DesktopHeight(0)/1.5
  Do(OpenWindow(0, 0, 0, WindowWidth, WindowHeight, AppName, #PB_Window_ScreenCentered|#PB_Window_SystemMenu), "Can not open window")
  Do(OpenWindowedScreen(WindowID(0), 0, 0, WindowWidth, WindowHeight, 0, 0, 0, #PB_Screen_SmartSynchronization), "Can not open screen")
  LogIt("finished hardware initialization, opened screen in a window with "+Str(WindowWidth)+"x"+Str(WindowHeight)+" px")
EndIf


If ShadowsEnabled
  WorldShadows(#PB_Shadow_Additive) : LogIt("enabled world shadows")
EndIf

CalcRoomPoints()

BlockWidth  = Round(WindowWidth / 10, #PB_Round_Down)
BlockHeight = BlockWidth / 2
BlockDepth  = BlockHeight
LevelAreaX  = (-WindowWidth / 2) + (BlockWidth/2)
LevelAreaY  = ((WindowHeight - (BlockHeight * 5)) / 2) - (BlockHeight/2)
LevelAreaZ  = Round((WindowWidth + WindowHeight) / 4, #PB_Round_Down) * -3
LogIt("calculated Level Area, Blocksize: "+Str(BlockWidth)+"x"+Str(BlockHeight)+"x"+Str(BlockDepth)+", Level start point: "+Str(LevelAreaX)+","+Str(LevelAreaY)+","+Str(LevelAreaZ))

CreateTextures() : CreateMaterials() : CreateMeshes(); : CreateEntities()

MainMenu()

CreateEntities()

PlayerLevel = 1

NewBall() : CreateNewLevel(PlayerLevel) : CreateScoreBoard()

CreateLights()

CreateCamera(#Cam_Main, 0, 0, 100, 100)
If FullScreen
  MoveCamera(#Cam_Main, 0, 0, 1250, #PB_Absolute)
Else
  MoveCamera(#Cam_Main, 0, 0, 850, #PB_Absolute)
EndIf

LogIt("created main camera")

ShowActionCam()

FlipBuffers()

;- LOOP
DoLoop = #True
Repeat
  
  ; catch all window events
  If FullScreen = 0
    Repeat
    
      WindowEvt = WindowEvent()
      
      Select WindowEvt
      
        Case #PB_Event_CloseWindow
          DoLoop = #False
          
      EndSelect
         
    Until WindowEvt = 0
  EndIf

  ; catch keystrokes
  If ExamineKeyboard()
    
    If KeyboardPushed(#PB_Key_Escape)
      DoLoop = #False
    EndIf
    
    If KeyboardReleased(#PB_Key_F1)
      ShowActionCam()
    ElseIf KeyboardReleased(#PB_Key_F12)
      DoScreenshot = #True
    EndIf
    
    ; Cheat Commands
    If KeyboardReleased(#PB_Key_Pad1)
      Debug "Level skip"
      LevelFinished()
    EndIf

  EndIf
  
  If ExamineMouse()
    
    If MouseButton(#PB_MouseButton_Left) And BallLocked
      BallLocked = #False
    EndIf
    
    MovePaddel()
    
  EndIf
  
  MoveBall()
  
  MoveBallTarget()
  
  ShowTouchAnim()
  
  ShowBlockDestroyAnim()
  
  CreateScoreBoard()
  
  LightLookAt(#Lgt_RoomRL, EntityX(#Ent_Ball), EntityY(#Ent_Ball), EntityZ(#Ent_Ball))
  LightLookAt(#Lgt_RoomRR, EntityX(#Ent_Ball), EntityY(#Ent_Ball), EntityZ(#Ent_Ball))
  LightLookAt(#Lgt_RoomTL, EntityX(#Ent_Ball), EntityY(#Ent_Ball), EntityZ(#Ent_Ball))
  LightLookAt(#Lgt_RoomTR, EntityX(#Ent_Ball), EntityY(#Ent_Ball), EntityZ(#Ent_Ball))
  
  ; render world
  RenderWorld()
  
  If DoScreenshot
    GrabSprite(#Spr_ScreenShot, 0, 0, WindowWidth, WindowHeight)
    SaveSprite(#Spr_ScreenShot, LCase(AppName)+".bmp")
    FreeSprite(#Spr_ScreenShot)
    DoScreenshot = #False
    LogIt("saved Screenshot")
  EndIf
  
  FlipBuffers() 

Until DoLoop = #False

;- END
LogIt("closed by user")
SaveSettings()
End

;- PROCEDURES
;--- Helper
Procedure.s FormatTime(Miliseconds.i)
  Protected.i h, m, s
  h = Int(Miliseconds / 1000 / 60 / 60) : Miliseconds - h * 1000 * 60 * 60
  m = Int(Miliseconds / 1000 / 60)      : Miliseconds - m * 1000 * 60
  s = Int(Miliseconds / 1000)           : Miliseconds - s * 1000
  ProcedureReturn RSet(Str(h), 2, "0")+":"+RSet(Str(m), 2, "0")+":"+RSet(Str(s), 2, "0")+"."+RSet(Str(Miliseconds), 3, "0")
EndProcedure

Procedure LogIt(Text.s)
  Shared hLog, AppDuration, AppLogging, AppLogFile
  Shared AppName
  If AppLogging
    hLog = OpenFile(#PB_Any, AppLogFile)
    If IsFile(hLog)
      While Eof(hLog) = 0
        ReadString(hLog)
      Wend
      WriteStringN(hLog, "[" + FormatTime(ElapsedMilliseconds()-AppDuration) + "]" + Space(2) + Text)
      CloseFile(hLog)
    EndIf
  EndIf
EndProcedure

Procedure LoadSettings()
  Shared AppConfFile, AppLogging, FullScreen, WindowWidth, WindowHeight, ShadowsEnabled, MaterialFilter, MaterialAniMax, AntiAlias, ViewCam
  Protected.i hf = ReadFile(#PB_Any, AppConfFile)
  If IsFile(hf)
    ReadCharacter(hf)
    ReadCharacter(hf)
    ReadCharacter(hf)
    AppLogging = ReadByte(hf)
    FullScreen = ReadByte(hf)
    AntiAlias  = ReadByte(hf)
    ReadWord(hf)
    ReadWord(hf)
    ShadowsEnabled = ReadByte(hf)
    MaterialFilter = ReadByte(hf)
    MaterialAniMax = ReadByte(hf)
    ViewCam        = ReadByte(hf)
    CloseFile(hf)
    LogIt("settings loaded")
  Else
    LogIt("Can not load/find settings file")
  EndIf
EndProcedure

Procedure SaveSettings()
  Shared AppConfFile, AppLogging, FullScreen, WindowWidth, WindowHeight, ShadowsEnabled, MaterialFilter, MaterialAniMax, AntiAlias, ViewCam
  Protected.i hf = CreateFile(#PB_Any, AppConfFile)
  If IsFile(hf)
    WriteCharacter(hf, $41)
    WriteCharacter(hf, $33)
    WriteCharacter(hf, $44)
    WriteByte(hf, AppLogging)
    WriteByte(hf, FullScreen)
    WriteByte(hf, AntiAlias)
    WriteWord(hf, WindowWidth)
    WriteWord(hf, WindowHeight)
    WriteByte(hf, ShadowsEnabled)
    WriteByte(hf, MaterialFilter)
    WriteByte(hf, MaterialAniMax)
    WriteByte(hf, ViewCam)
    WriteWord(hf, 0)
    CloseFile(hf)
    LogIt("settings saved")
  Else
    LogIt("Can not create Settings file")
  EndIf
EndProcedure

;--- Vector Math
Procedure VectorSub(*v1.fVector3D, *v2.fVector3D, *result.fVector3D)
  *result\x = *v1\x - *v2\x
  *result\y = *v1\y - *v2\y
  *result\z = *v1\z - *v2\z
EndProcedure

Procedure VectorCross(*v1.fVector3D, *v2.fVector3D, *result.fVector3D)
  *result\x = *v1\y * *v2\z - *v1\z * *v2\y
  *result\y = *v1\z * *v2\x - *v1\x * *v2\z
  *result\z = *v1\x * *v2\y - *v1\y * *v2\x
EndProcedure

Procedure.f VectorDot(*v1.fVector3D, *v2.fVector3D)
  ProcedureReturn (*v1\x * *v2\x) + (*v1\y * *v2\y) + (*v1\z * *v2\z)
EndProcedure

Procedure VectorNormalize(*v1.fVector3D)
  Protected length.f = Sqr((*v1\x * *v1\x) + (*v1\y * *v1\y) + (*v1\z * *v1\z))
  *v1\x = *v1\x / length
  *v1\y = *v1\y / length
  *v1\z = *v1\z / length
EndProcedure

;--- Calc Environment
Procedure CalcRoomPoints()
  
  ;   7--------6
  ;   /|      /
  ;  / |     /|
  ; /  |    / |
  ;4--------5 |
  ; |  |   |  |
  ; | 3|---|--/2
  ; | /    | /
  ; |/     |/
  ;0--------1    
  
  Shared RoomBox()
  
  Protected maxWidth.i  = ScreenWidth(); * 2
  Protected maxHeight.i = ScreenHeight(); * 2
  Protected maxDepth.i  = maxWidth + maxHeight
  
  Protected.fVector3D center
  
  center\x = #Pos_Paddle_X
  center\y = #Pos_Paddle_Y
  center\z = #Pos_Paddle_Z - maxDepth / 2
  
  RoomBox(0)\x = center\x - maxWidth / 2
  RoomBox(0)\y = center\y - maxHeight / 2
  RoomBox(0)\z = center\z + maxDepth / 2
  
  RoomBox(1)\x = center\x + maxWidth / 2
  RoomBox(1)\y = center\y - maxHeight / 2
  RoomBox(1)\z = center\z + maxDepth / 2
  
  RoomBox(2)\x = center\x + maxWidth / 2
  RoomBox(2)\y = center\y - maxHeight / 2
  RoomBox(2)\z = center\z - maxDepth / 2
  
  RoomBox(3)\x = center\x - maxWidth / 2
  RoomBox(3)\y = center\y - maxHeight / 2
  RoomBox(3)\z = center\z - maxDepth / 2
  
  RoomBox(4)\x = center\x - maxWidth / 2
  RoomBox(4)\y = center\y + maxHeight / 2
  RoomBox(4)\z = center\z + maxDepth / 2
  
  RoomBox(5)\x = center\x + maxWidth / 2
  RoomBox(5)\y = center\y + maxHeight / 2
  RoomBox(5)\z = center\z + maxDepth / 2
  
  RoomBox(6)\x = center\x + maxWidth / 2
  RoomBox(6)\y = center\y + maxHeight / 2
  RoomBox(6)\z = center\z - maxDepth / 2
  
  RoomBox(7)\x = center\x - maxWidth / 2
  RoomBox(7)\y = center\y + maxHeight / 2
  RoomBox(7)\z = center\z - maxDepth / 2
  
  LogIt("calculated RoomBox, size = "+Str(maxWidth)+"x"+Str(maxHeight)+"x"+Str(maxDepth))
  
EndProcedure

Procedure CalcBlockPoints(point.i, x.i, y.i, z.i, *p.fVector3D)
  Shared BlockWidth, BlockHeight, BlockDepth
  ;   7--------6
  ;   /|      /
  ;  / |     /|
  ; /  |    / |
  ;4--------5 |
  ; |  |   |  |
  ; | 3|---|--/2
  ; | /    | /
  ; |/     |/
  ;0--------1    
  Select point
    Case 0
      *p\x = x - BlockWidth/2
      *p\y = y - BlockHeight/2
      *p\z = z + BlockDepth/2
    Case 1
      *p\x = x + BlockWidth/2
      *p\y = y - BlockHeight/2
      *p\z = z + BlockDepth/2
    Case 2
      *p\x = x + BlockWidth/2
      *p\y = y - BlockHeight/2
      *p\z = z - BlockDepth/2
    Case 3
      *p\x = x - BlockWidth/2
      *p\y = y - BlockHeight/2
      *p\z = z - BlockDepth/2
    Case 4
      *p\x = x - BlockWidth/2
      *p\y = y + BlockHeight/2
      *p\z = z + BlockDepth/2
    Case 5
      *p\x = x + BlockWidth/2
      *p\y = y + BlockHeight/2
      *p\z = z + BlockDepth/2
    Case 6
      *p\x = x + BlockWidth/2
      *p\y = y + BlockHeight/2
      *p\z = z - BlockDepth/2
    Case 7
      *p\x = x - BlockWidth/2
      *p\y = y + BlockHeight/2
      *p\z = z - BlockDepth/2
  EndSelect
EndProcedure

Procedure LevelFinished()
  
  Shared FullScreen, WindowWidth, WindowHeight, BallLocked, PlayerScore, PlayerBalls, PlayerTime, PlayerLevel,  LevelSwitch
  
  Protected.b doBlend, switchLoop
  Protected.i n, hFont01, hFont02, blendWidth, finishHeight, scoreHeight, ballsHeight, timeHeight, contHeight, animSprite, finishY, scoreY, ballsY, timeY, contY
  Protected.s txtFinish, txtScore, txtBalls, txtTime, txtCont
  
  PlayerTime  = ElapsedMilliseconds() - PlayerTime
  
  doBlend    = #True
  switchLoop = #True
  hFont01    = LoadFont(#PB_Any, "Comic Sans MS", 36, #PB_Font_Bold|#PB_Font_Italic|#PB_Font_HighQuality)
  hFont02    = LoadFont(#PB_Any, "Comic Sans MS", 24, #PB_Font_Bold|#PB_Font_HighQuality)
  blendWidth = WindowWidth
  
  txtFinish = "You finished level "+Str(PlayerLevel)+" !"
  txtScore  = "Score "+RSet(Str(PlayerScore), 5, "0")
  txtBalls  = "Balls "+RSet(Str(PlayerBalls), 5, "0")
  If PlayerLevel < 5
    txtTime   = "Time "+FormatTime(PlayerTime)
    txtCont   = "press a key to continue ..."
  Else
    txtTime   = "Congratiulations you finished Arkano3d"
    txtCont   = "press a key to exit ..."
  EndIf
  
  finishHeight = WindowHeight / 4
  scoreHeight  = WindowHeight / 2
  ballsHeight  = scoreHeight + 50
  timeHeight   = ballsHeight + 50
  contHeight   = timeHeight + 100
  
  finishY      = -105
  scoreY       = -55
  ballsY       = -55
  timeY        = -55
  contY        = -55
  
  animSprite = 1
  
  PlayerLevel + 1
  BallLocked  = #True
  LevelSwitch = #True
  
  CreateSprite(#Spr_SwitchBlend, WindowWidth, WindowHeight)
  TransparentSpriteColor(#Spr_SwitchBlend, RGB(255,255,255))
  
  CreateSprite(#Spr_SwitchFinish, WindowWidth, 100)
  TransparentSpriteColor(#Spr_SwitchFinish, RGB(0,0,0))
  StartDrawing(SpriteOutput(#Spr_SwitchFinish))
  DrawingMode(#PB_2DDrawing_Transparent)
  DrawingFont(FontID(hFont01))
  DrawText(WindowWidth/2-TextWidth(txtFinish)/2, 0, txtFinish, RGB(128,255,0))
  StopDrawing()
  
  CreateSprite(#Spr_SwitchScore, WindowWidth, 50)
  TransparentSpriteColor(#Spr_SwitchScore, RGB(0,0,0))
  StartDrawing(SpriteOutput(#Spr_SwitchScore))
  DrawingMode(#PB_2DDrawing_Transparent)
  DrawingFont(FontID(hFont02))
  DrawText(WindowWidth/2-TextWidth(txtScore)/2, 0, txtScore, RGB(255,255,0))
  StopDrawing()
  
  CreateSprite(#Spr_SwitchBalls, WindowWidth, 50)
  TransparentSpriteColor(#Spr_SwitchBalls, RGB(0,0,0))
  StartDrawing(SpriteOutput(#Spr_SwitchBalls))
  DrawingMode(#PB_2DDrawing_Transparent)
  DrawingFont(FontID(hFont02))
  DrawText(WindowWidth/2-TextWidth(txtBalls)/2, 0, txtBalls, RGB(255,255,0))
  StopDrawing()
  
  CreateSprite(#Spr_SwitchTime, WindowWidth, 50)
  TransparentSpriteColor(#Spr_SwitchTime, RGB(0,0,0))
  StartDrawing(SpriteOutput(#Spr_SwitchTime))
  DrawingMode(#PB_2DDrawing_Transparent)
  DrawingFont(FontID(hFont02))
  DrawText(WindowWidth/2-TextWidth(txtTime)/2, 0, txtTime, RGB(255,255,0))
  StopDrawing()
  
  CreateSprite(#Spr_SwitchContinue, WindowWidth, 50)
  TransparentSpriteColor(#Spr_SwitchContinue, RGB(0,0,0))
  StartDrawing(SpriteOutput(#Spr_SwitchContinue))
  DrawingMode(#PB_2DDrawing_Transparent)
  DrawingFont(FontID(hFont02))
  DrawText(WindowWidth/2-TextWidth(txtCont)/2, 0, txtCont, RGB(255,255,0))
  StopDrawing()
  
  Repeat
    
    If FullScreen = 0
      While WindowEvent() <> 0 : Wend
    EndIf
    
    If ExamineKeyboard()
      
      If KeyboardReleased(#PB_Key_All)
        switchLoop = #False
      EndIf
      
    EndIf
    
    If ExamineMouse() : EndIf
    
    If doBlend
      StartDrawing(SpriteOutput(#Spr_SwitchBlend))
      Box(0, 0, WindowWidth, WindowHeight, RGB(0,0,0))
      Circle(WindowWidth/2, WindowHeight/2, blendWidth/2, RGB(255,255,255))
      StopDrawing()
      blendWidth - 32
      If blendWidth <= 0
        StartDrawing(SpriteOutput(#Spr_SwitchBlend))
        Box(0, 0, WindowWidth, WindowHeight, RGB(0,0,0))
        StopDrawing()
        doBlend = #False
      EndIf
    EndIf
    
    If doBlend = #False And animSprite <= 5
      Select animSprite
        Case 1
          finishY + 5
          If finishY >= finishHeight
            animSprite + 1
          EndIf
        Case 2
          scoreY + 10
          If ScoreY >= scoreHeight
            animSprite + 1
          EndIf
        Case 3
          ballsY + 10
          If ballsY >= ballsHeight
            animSprite + 1
          EndIf
        Case 4
          timeY + 10
          If timeY >= timeHeight
            animSprite + 1
          EndIf
        Case 5
          contY + 10
          If contY >= contHeight
            animSprite + 1
          EndIf
      EndSelect
    EndIf
    
    DisplayTransparentSprite(#Spr_SwitchBlend, 0, 0)
    DisplayTransparentSprite(#Spr_SwitchFinish, WindowWidth/2-SpriteWidth(#Spr_SwitchFinish)/2, finishY)
    DisplayTransparentSprite(#Spr_SwitchScore, WindowWidth/2-SpriteWidth(#Spr_SwitchScore)/2, scoreY)
    DisplayTransparentSprite(#Spr_SwitchBalls, WindowWidth/2-SpriteWidth(#Spr_SwitchBalls)/2, ballsY)
    DisplayTransparentSprite(#Spr_SwitchTime, WindowWidth/2-SpriteWidth(#Spr_SwitchTime)/2, timeY)
    DisplayTransparentSprite(#Spr_SwitchContinue, WindowWidth/2-SpriteWidth(#Spr_SwitchContinue)/2, contY)
    
    FlipBuffers()
    
  Until switchLoop = #False
  
  For n = #Spr_SwitchBlend To #Spr_SwitchContinue
    FreeSprite(n)
  Next
  
  If PlayerLevel <= 5
    CreateNewLevel(PlayerLevel)
    PlayerBalls - 1 : NewBall()
    LogIt("Level finished, time "+FormatTime(PlayerTime))
  Else
    LogIt("Game finished")
    End
  EndIf
  
EndProcedure

;--- Creation: Textures, Materials, Meshes, Entities ...
Procedure CreateTextures()
  
  Protected.i n, x, y
  
  CreateTexture(#Tex_Room01, 256, 256)
  StartDrawing(TextureOutput(#Tex_Room01))
  Box(0, 0, 128, 128, RGB(32, 32, 192))
  Box(128, 128, 128, 128, RGB(32, 32, 192))
  Box(128, 0, 128, 128, RGB(0, 191, 255))
  Box(0, 128, 128, 128, RGB(0, 191, 255))
  StopDrawing()
  
  CreateTexture(#Tex_Room02, 256, 256)
  StartDrawing(TextureOutput(#Tex_Room02))
  Box(0, 0, 256, 256, RGB(32, 32, 192))
  Box(113, 0, 30, 256, RGB(0, 191, 255))
  Box(0, 113, 256, 30, RGB(0, 191, 255))
  StopDrawing()
  
  CreateTexture(#Tex_Room03, 32, 32)
  StartDrawing(TextureOutput(#Tex_Room03))
  Box(0, 0, 32, 32, RGB(64, 64, 64))
  Plot(0, 0, RGB(0, 255, 0))
  Plot(0, 31, RGB(0, 255, 0))
  Plot(31, 0, RGB(0, 255, 0))
  Plot(31, 31, RGB(0, 255, 0))
  DrawText((32-TextWidth("?"))/2, (32-TextHeight("?"))/2, "?", RGB(0, 255, 0), RGB(64, 64, 64))
  StopDrawing()
  
  CreateTexture(#Tex_Paddle, 256, 256)
  ;StartDrawing(TextureOutput(#Tex_Paddle))
  ;RoundBox(0, 0, 256, 256, 8, 16, RGB(255, 0, 0))
  ;RoundBox(5, 10, 246, 236, 16, 32, RGB(245, 245, 0))
  ;StopDrawing()
  StartDrawing(TextureOutput(#Tex_Paddle))
  Box(0, 0, 256, 256, RGB(255,255,0))
  For y = 0 To 8
    For x = 0 To 16
      ;Circle(x * 16, y * 16, 7, RGB(0,0,0))
      RoundBox(x*16, y*32, 14, 30, 6, 6, RGB(0,0,0))
    Next
  Next
  StopDrawing()
  
  CreateTexture(#Tex_PaddleBuild, 256, 256)
  StartDrawing(TextureOutput(#Tex_PaddleBuild))
  Box(0, 0, 256, 256, RGB(0, 0, 0))
  DrawingMode(#PB_2DDrawing_Gradient)      
  BackColor(RGB(192, 192, 192))
  FrontColor(RGB(64, 64, 64))
  CircularGradient(128, 128, 128)     
  Box(0, 0, 256, 256)
  StopDrawing()

  CreateTexture(#Tex_Ball, 256, 256)
  StartDrawing(TextureOutput(#Tex_Ball))
  Box(0, 0, 256, 256, RGB(0, 0, 0))
  DrawingMode(#PB_2DDrawing_Gradient)      
  BackColor(RGB(192, 192, 192))
  FrontColor(RGB(64, 64, 64))
  CircularGradient(128, 128, 128)     
  Box(0, 0, 256, 256)
  StopDrawing()
    
  CreateTexture(#Tex_BallTarget, 128, 128)
  StartDrawing(TextureOutput(#Tex_BallTarget))
  Box(0, 0, 128, 128, RGB(0, 0, 0))
  Circle(64, 64, 56, RGB(0, 255, 0))
  Circle(64, 64, 48, RGB(0, 0, 0))
  StopDrawing()
  
  For n = #Tex_BallTarget05 To #Tex_BallTarget01 Step -1
    CreateTexture(n, 128, 128)
    StartDrawing(TextureOutput(n))
    Box(0, 0, 128, 128, RGB(0, 0, 0))
    Circle(64, 64, 56, RGB((255 - (n-#Tex_BallTarget01)) * 45, 0, 0))
    Circle(64, 64, 48, RGB(0, 0, 0))
    StopDrawing()
  Next
  
  CreateTexture(#Tex_BallTouch, 128, 128)
  StartDrawing(TextureOutput(#Tex_BallTouch))
  Box(0, 0, 128, 128, RGB(0, 0, 0))
  DrawingMode(#PB_2DDrawing_Gradient)      
  BackColor(RGB(255, 255, 0))
  FrontColor(RGB(0, 0, 0))
  CircularGradient(64, 64, 64)
  Circle(64, 64, 64)
  StopDrawing()
  
  For n = #Tex_BallTouch01 To #Tex_BallTouch10
    CreateTexture(n, 128, 128)
    StartDrawing(TextureOutput(n))
    Box(0, 0, 128, 128, RGB(0, 0, 0))
    DrawingMode(#PB_2DDrawing_Gradient)      
    BackColor(RGB((255-(n-#Tex_BallTouch01))*25, (255-(n-#Tex_BallTouch01))*25, 0))
    FrontColor(RGB(0, 0, 0))
    CircularGradient(64, 64, 64)
    Circle(64, 64, 64)
    StopDrawing()
  Next
  
  CreateTexture(#Tex_Block01, 256, 256)
  StartDrawing(TextureOutput(#Tex_Block01))
  Box(0, 0, 256, 256, RGB(0, 100, 0))
  DrawingMode(#PB_2DDrawing_Gradient)      
  BackColor(RGB(34, 139, 34))
  FrontColor(RGB(127, 255, 0))
  CircularGradient(128, 128, 120)     
  Box(10, 10, 236, 236)
  StopDrawing()
  
  CreateTexture(#Tex_Block02, 256, 256)
  StartDrawing(TextureOutput(#Tex_Block02))
  Box(0, 0, 256, 256, RGB(255, 215, 0))
  DrawingMode(#PB_2DDrawing_Gradient)      
  BackColor(RGB(255, 215, 0))
  FrontColor(RGB(255, 255, 0))
  CircularGradient(128, 128, 120)     
  Box(10, 10, 236, 236)
  StopDrawing()
  
  CreateTexture(#Tex_Block03, 256, 256)
  StartDrawing(TextureOutput(#Tex_Block03))
  Box(0, 0, 256, 256, RGB(128, 0, 0))
  DrawingMode(#PB_2DDrawing_Gradient)      
  BackColor(RGB(128, 0, 0))
  FrontColor(RGB(255, 0, 0))
  CircularGradient(128, 128, 120)     
  Box(10, 10, 236, 236)
  StopDrawing()
  
  CreateTexture(#Tex_Block04, 256, 256)
  StartDrawing(TextureOutput(#Tex_Block04))
  Box(0, 0, 256, 256, RGB(72, 61, 139))
  DrawingMode(#PB_2DDrawing_Gradient)      
  BackColor(RGB(72, 61, 139))
  FrontColor(RGB(147, 112, 219))
  CircularGradient(128, 128, 120)     
  Box(10, 10, 236, 236)
  StopDrawing()
  
  CreateTexture(#Tex_Block05, 256, 256)
  StartDrawing(TextureOutput(#Tex_Block05))
  Box(0, 0, 256, 256, RGB(255, 69, 0))
  DrawingMode(#PB_2DDrawing_Gradient)      
  BackColor(RGB(255, 69, 0))
  FrontColor(RGB(255, 160, 122))
  CircularGradient(128, 128, 120)     
  Box(10, 10, 236, 236)
  StopDrawing()
  
  CreateTexture(#Tex_Block06, 256, 256)
  StartDrawing(TextureOutput(#Tex_Block06))
  Box(0, 0, 256, 256, RGB(0, 139, 139))
  DrawingMode(#PB_2DDrawing_Gradient)      
  BackColor(RGB(0, 139, 139))
  FrontColor(RGB(127, 255, 212))
  CircularGradient(128, 128, 120)     
  Box(10, 10, 236, 236)
  StopDrawing()
  
  CreateTexture(#Tex_Block07, 256, 256)
  StartDrawing(TextureOutput(#Tex_Block07))
  Box(0, 0, 256, 256, RGB(0, 139, 139))
  DrawingMode(#PB_2DDrawing_Gradient)      
  BackColor(RGB(0, 0, 139))
  FrontColor(RGB(0, 191, 255))
  CircularGradient(128, 128, 120)     
  Box(10, 10, 236, 236)
  StopDrawing()
  
  CreateTexture(#Tex_Block08, 256, 256)
  StartDrawing(TextureOutput(#Tex_Block08))
  Box(0, 0, 256, 256, RGB(192, 192, 192))
  Box(3, 3, 250, 250, RGB(139, 0, 0))
  Box(61, 0, 6, 64, RGB(192, 192, 192))
  Box(125, 0, 6, 64, RGB(192, 192, 192))
  Box(189, 0, 6, 64, RGB(192, 192, 192))
  Box(0, 61, 256, 6, RGB(192, 192, 192))
  Box(29, 64, 6, 64, RGB(192, 192, 192))
  Box(93, 64, 6, 64, RGB(192, 192, 192))
  Box(157, 64, 6, 64, RGB(192, 192, 192))
  Box(221, 64, 6, 64, RGB(192, 192, 192))
  Box(0, 125, 256, 6, RGB(192, 192, 192))
  Box(61, 128, 6, 64, RGB(192, 192, 192))
  Box(125, 128, 6, 64, RGB(192, 192, 192))
  Box(189, 128, 6, 64, RGB(192, 192, 192))
  Box(0, 189, 256, 6, RGB(192, 192, 192))
  Box(29, 192, 6, 64, RGB(192, 192, 192))
  Box(93, 192, 6, 64, RGB(192, 192, 192))
  Box(157, 192, 6, 64, RGB(192, 192, 192))
  Box(221, 192, 6, 64, RGB(192, 192, 192))
  StopDrawing()
  
  For n = #Tex_Block01Ani01 To #Tex_Block01Ani05
    CreateTexture(n, 64, 64)
    StartDrawing(TextureOutput(n))
    Box(0, 0, 64, 64, RGB(0,0,0))
    Box(16, 16, 32, 32, RGB((128-(n-#Tex_Block01Ani01))*12, (255-(n-#Tex_Block01Ani01))*25, 0))
    StopDrawing()
  Next
  
  For n = #Tex_Block02Ani01 To #Tex_Block02Ani05
    CreateTexture(n, 64, 64)
    StartDrawing(TextureOutput(n))
    Box(0, 0, 64, 64, RGB(0,0,0))
    Box(16, 16, 32, 32, RGB((255-(n-#Tex_Block02Ani01))*25, (255-(n-#Tex_Block02Ani01))*25, 0))
    StopDrawing()
  Next
  
  For n = #Tex_Block03Ani01 To #Tex_Block03Ani05
    CreateTexture(n, 64, 64)
    StartDrawing(TextureOutput(n))
    Box(0, 0, 64, 64, RGB(0,0,0))
    Box(16, 16, 32, 32, RGB((255-(n-#Tex_Block03Ani01))*25, 0, 0))
    StopDrawing()
  Next
  
  For n = #Tex_Block04Ani01 To #Tex_Block04Ani05
    CreateTexture(n, 64, 64)
    StartDrawing(TextureOutput(n))
    Box(0, 0, 64, 64, RGB(0,0,0))
    Box(16, 16, 32, 32, RGB((128-(n-#Tex_Block04Ani01))*12, (128-(n-#Tex_Block04Ani01))*12, (255-(n-#Tex_Block04Ani01))*25))
    StopDrawing()
  Next
  
  For n = #Tex_Block05Ani01 To #Tex_Block05Ani05
    CreateTexture(n, 64, 64)
    StartDrawing(TextureOutput(n))
    Box(0, 0, 64, 64, RGB(0,0,0))
    Box(16, 16, 32, 32, RGB((255-(n-#Tex_Block05Ani01))*25, (160-(n-#Tex_Block05Ani01))*20, (128-(n-#Tex_Block05Ani01))*12))
    StopDrawing()
  Next
  
  For n = #Tex_Block06Ani01 To #Tex_Block06Ani05
    CreateTexture(n, 64, 64)
    StartDrawing(TextureOutput(n))
    Box(0, 0, 64, 64, RGB(0,0,0))
    Box(16, 16, 32, 32, RGB((128-(n-#Tex_Block06Ani01))*12, (255-(n-#Tex_Block06Ani01))*25, (210-(n-#Tex_Block06Ani01))*20))
    StopDrawing()
  Next
  
  For n = #Tex_Block07Ani01 To #Tex_Block07Ani05
    CreateTexture(n, 64, 64)
    StartDrawing(TextureOutput(n))
    Box(0, 0, 64, 64, RGB(0,0,0))
    Box(16, 16, 32, 32, RGB(0, (191-(n-#Tex_Block07Ani01))*15, (255-(n-#Tex_Block07Ani01))*25))
    StopDrawing()
  Next
  
  For n = #Tex_Block08Ani01 To #Tex_Block08Ani05
    CreateTexture(n, 64, 64)
    StartDrawing(TextureOutput(n))
    Box(0, 0, 64, 64, RGB(0,0,0))
    Box(16, 16, 32, 32, RGB((128-(n-#Tex_Block08Ani01))*12, 0, 0))
    StopDrawing()
  Next
  
  LogIt("created Textures")
  
EndProcedure

Procedure CreateMaterials()
  
  Shared MaterialFilter, MaterialAniMax
  
  Protected.i n
  
  CreateMaterial(#Mat_Room01, TextureID(#Tex_Room01))
    MaterialDepthWrite(#Mat_Room01, #True)
    MaterialShadingMode(#Mat_Room01, #PB_Material_Phong)
    MaterialFilteringMode(#Mat_Room01, #PB_Material_Anisotropic, 4)
    
  CreateMaterial(#Mat_Room02, TextureID(#Tex_Room02))
    MaterialDepthWrite(#Mat_Room02, #True)
    MaterialShadingMode(#Mat_Room02, #PB_Material_Phong)
    MaterialFilteringMode(#Mat_Room02, #PB_Material_Anisotropic, 4)
    
  CreateMaterial(#Mat_Room03, TextureID(#Tex_Room03))
    RotateMaterial(#Mat_Room03, 180, #PB_Absolute)
    MaterialDepthWrite(#Mat_Room03, #True)
    MaterialShadingMode(#Mat_Room03, #PB_Material_Phong)
    MaterialFilteringMode(#Mat_Room03, #PB_Material_Anisotropic, 4)
  
  CreateMaterial(#Mat_Paddle, TextureID(#Tex_Paddle))
    MaterialBlendingMode(#Mat_Paddle, #PB_Material_Add)
    MaterialShadingMode(#Mat_Paddle, #PB_Material_Phong)
    MaterialFilteringMode(#Mat_Paddle, #PB_Material_Anisotropic, 4)
    
  CreateMaterial(#Mat_PaddleBuild, TextureID(#Tex_PaddleBuild))
    SetMaterialColor(#Mat_PaddleBuild, #PB_Material_DiffuseColor, RGB(102, 102, 102))
    SetMaterialColor(#Mat_PaddleBuild, #PB_Material_SpecularColor, RGB(198, 198, 198))
    MaterialShininess(#Mat_PaddleBuild, 77)
    MaterialShadingMode(#Mat_PaddleBuild, #PB_Material_Phong)
    MaterialFilteringMode(#Mat_PaddleBuild, #PB_Material_Anisotropic, 4)
    
  CreateMaterial(#Mat_Ball, TextureID(#Tex_Ball))
    SetMaterialColor(#Mat_Ball, #PB_Material_DiffuseColor, RGB(102, 102, 102))
    SetMaterialColor(#Mat_Ball, #PB_Material_SpecularColor, RGB(198, 198, 198))
    MaterialShininess(#Mat_Ball, 77)
    MaterialShadingMode(#Mat_Ball, #PB_Material_Phong)
    MaterialFilteringMode(#Mat_Ball, #PB_Material_Anisotropic, 4)
    
  CreateMaterial(#Mat_BallTarget, TextureID(#Tex_BallTarget))
    MaterialBlendingMode(#Mat_BallTarget, #PB_Material_Add)
    MaterialShadingMode(#Mat_BallTarget, #PB_Material_Phong)
    MaterialFilteringMode(#Mat_BallTarget, #PB_Material_Anisotropic, 4)
    
  For n = #Mat_BallTarget01 To #Mat_BallTarget05
    
    CreateMaterial(n, TextureID(n))
      MaterialBlendingMode(n, #PB_Material_Add)
      MaterialShadingMode(n, #PB_Material_Phong)
      MaterialFilteringMode(n, #PB_Material_Anisotropic, 4)
    
  Next
    
  CreateMaterial(#Mat_BallTouch, TextureID(#Tex_BallTouch))
    MaterialBlendingMode(#Mat_BallTouch, #PB_Material_Add)
    MaterialShadingMode(#Mat_BallTouch, #PB_Material_Phong)
    MaterialFilteringMode(#Mat_BallTouch, #PB_Material_Anisotropic, 4)
    
  For n = #Mat_BallTouch01 To #Mat_BallTouch10
    
    CreateMaterial(n, TextureID(n))
      MaterialBlendingMode(n, #PB_Material_Add)
      MaterialShadingMode(n, #PB_Material_Phong)
      MaterialFilteringMode(n, #PB_Material_Anisotropic, 4)
      
  Next
    
  CreateMaterial(#Mat_Block01, TextureID(#Tex_Block01))
    MaterialDepthWrite(#Mat_Block01, #True)
    MaterialShadingMode(#Mat_Block01, #PB_Material_Phong)
    MaterialFilteringMode(#Mat_Block01, #PB_Material_Anisotropic, 4)
    
  CreateMaterial(#Mat_Block02, TextureID(#Tex_Block02))
    MaterialDepthWrite(#Mat_Block02, #True)
    MaterialShadingMode(#Mat_Block02, #PB_Material_Phong)
    MaterialFilteringMode(#Mat_Block02, #PB_Material_Anisotropic, 4)
    
  CreateMaterial(#Mat_Block03, TextureID(#Tex_Block03))
    MaterialDepthWrite(#Mat_Block03, #True)
    MaterialShadingMode(#Mat_Block03, #PB_Material_Phong)
    MaterialFilteringMode(#Mat_Block03, #PB_Material_Anisotropic, 4)
    
  CreateMaterial(#Mat_Block04, TextureID(#Tex_Block04))
    MaterialDepthWrite(#Mat_Block04, #True)
    MaterialShadingMode(#Mat_Block04, #PB_Material_Phong)
    MaterialFilteringMode(#Mat_Block04, #PB_Material_Anisotropic, 4)
    
  CreateMaterial(#Mat_Block05, TextureID(#Tex_Block05))
    MaterialDepthWrite(#Mat_Block05, #True)
    MaterialShadingMode(#Mat_Block05, #PB_Material_Phong)
    MaterialFilteringMode(#Mat_Block05, #PB_Material_Anisotropic, 4)
    
  CreateMaterial(#Mat_Block06, TextureID(#Tex_Block06))
    MaterialDepthWrite(#Mat_Block06, #True)
    MaterialShadingMode(#Mat_Block06, #PB_Material_Phong)
    MaterialFilteringMode(#Mat_Block06, #PB_Material_Anisotropic, 4)
    
  CreateMaterial(#Mat_Block07, TextureID(#Tex_Block07))
    MaterialDepthWrite(#Mat_Block07, #True)
    MaterialShadingMode(#Mat_Block07, #PB_Material_Phong)
    MaterialFilteringMode(#Mat_Block07, #PB_Material_Anisotropic, 4)
    
  CreateMaterial(#Mat_Block08, TextureID(#Tex_Block08))
    MaterialDepthWrite(#Mat_Block08, #True)
    MaterialShadingMode(#Mat_Block08, #PB_Material_Phong)
    MaterialFilteringMode(#Mat_Block08, #PB_Material_Anisotropic, 4)
    
  For n = #Mat_Block01Ani01 To #Mat_Block01Ani05
    CreateMaterial(n, TextureID(n))
    RotateMaterial(n, 0.05, #PB_Relative)
    DisableMaterialLighting(n, #True)
    MaterialBlendingMode(n, #PB_Material_Add)
  Next
    
  For n = #Mat_Block02Ani01 To #Mat_Block02Ani05
    CreateMaterial(n, TextureID(n))
    RotateMaterial(n, 0.05, #PB_Relative)
    DisableMaterialLighting(n, #True)
    MaterialBlendingMode(n, #PB_Material_Add)
  Next
  
  For n = #Mat_Block03Ani01 To #Mat_Block03Ani05
    CreateMaterial(n, TextureID(n))
    RotateMaterial(n, 0.05, #PB_Relative)
    DisableMaterialLighting(n, #True)
    MaterialBlendingMode(n, #PB_Material_Add)
  Next
  
  For n = #Mat_Block04Ani01 To #Mat_Block04Ani05
    CreateMaterial(n, TextureID(n))
    RotateMaterial(n, 0.05, #PB_Relative)
    DisableMaterialLighting(n, #True)
    MaterialBlendingMode(n, #PB_Material_Add)
  Next
  
  For n = #Mat_Block05Ani01 To #Mat_Block05Ani05
    CreateMaterial(n, TextureID(n))
    RotateMaterial(n, 0.05, #PB_Relative)
    DisableMaterialLighting(n, #True)
    MaterialBlendingMode(n, #PB_Material_Add)
  Next
  
  For n = #Mat_Block06Ani01 To #Mat_Block06Ani05
    CreateMaterial(n, TextureID(n))
    RotateMaterial(n, 0.05, #PB_Relative)
    DisableMaterialLighting(n, #True)
    MaterialBlendingMode(n, #PB_Material_Add)
  Next
  
  For n = #Mat_Block07Ani01 To #Mat_Block07Ani05
    CreateMaterial(n, TextureID(n))
    RotateMaterial(n, 0.05, #PB_Relative)
    DisableMaterialLighting(n, #True)
    MaterialBlendingMode(n, #PB_Material_Add)
  Next
  
  For n = #Mat_Block08Ani01 To #Mat_Block08Ani05
    CreateMaterial(n, TextureID(n))
    RotateMaterial(n, 0.05, #PB_Relative)
    DisableMaterialLighting(n, #True)
    MaterialBlendingMode(n, #PB_Material_Add)
  Next
  
  LogIt("created Materials")
    
EndProcedure

Procedure CreateMeshes()
  
  Protected maxWidth.i  = ScreenWidth(); * 2
  Protected maxHeight.i = ScreenHeight(); * 2
  Protected maxDepth.i  = maxWidth + maxHeight
  
  CreatePlane(#Msh_RoomFR, maxWidth, maxHeight, 1, 1, 10, 10)
  CreatePlane(#Msh_RoomLF, maxDepth, maxHeight, 1, 1, 10, 10)
  CreatePlane(#Msh_RoomRT, maxDepth, maxHeight, 1, 1, 10, 10)
  CreatePlane(#Msh_RoomTP, maxWidth, maxDepth, 1, 1, 10, 10)
  CreatePlane(#Msh_RoomBT, maxWidth, maxDepth, 1, 1, 10, 10)
  
  CreateCube(#Msh_Paddle, 1)
  CreateSphere(#Msh_PaddleBuildSph, 7.5, 16, 16)
  CreateCylinder(#Msh_PaddleBuildCyl01, 5, #Size_Paddle_X)
  CreateCylinder(#Msh_PaddleBuildCyl02, 5, #Size_Paddle_Y)
  
  CreateSphere(#Msh_Ball, #Size_Ball_Radi, 32, 32)
  CreatePlane(#Msh_BallTarget, 128, 128, 1, 1, 1 ,1)
  CreatePlane(#Msh_BallTouch, 128, 128, 1, 1, 1 ,1)
  
  CreateCube(#Msh_Block, 1)
  
  LogIt("created Meshes")
  
EndProcedure

Procedure CreateEntities()
  
  Protected maxWidth.i  = ScreenWidth(); * 2
  Protected maxHeight.i = ScreenHeight(); * 2
  Protected maxDepth.i  = maxWidth + maxHeight
  
  CreateEntity(#Ent_RoomFR, MeshID(#Msh_RoomFR), MaterialID(#Mat_Room01), 0, 0, -maxDepth)
  RotateEntity(#Ent_RoomFR, 90, 0, 0, #PB_Absolute)
  
  CreateEntity(#Ent_RoomLF, MeshID(#Msh_RoomLF), MaterialID(#Mat_Room01), -maxWidth/2, 0, -maxDepth/2)
  RotateEntity(#Ent_RoomLF, 90, 0, 270, #PB_Absolute)
  
  CreateEntity(#Ent_RoomRT, MeshID(#Msh_RoomRT), MaterialID(#Mat_Room01), maxWidth/2, 0, -maxDepth/2)
  RotateEntity(#Ent_RoomRT, 90, 0, 90, #PB_Absolute)
  
  CreateEntity(#Ent_RoomTP, MeshID(#Msh_RoomTP), MaterialID(#Mat_Room01), 0, maxHeight/2, -maxDepth/2)
  RotateEntity(#Ent_RoomTP, 180, 180, 0, #PB_Absolute)
  
  CreateEntity(#Ent_RoomBT, MeshID(#Msh_RoomBT), MaterialID(#Mat_Room01), 0, -maxHeight/2, -maxDepth/2)
  
  CreateEntity(#Ent_Paddle, MeshID(#Msh_Paddle), MaterialID(#Mat_Paddle), #Pos_Paddle_X, #Pos_Paddle_Y, #Pos_Paddle_Z)
  ScaleEntity(#Ent_Paddle, #Size_Paddle_X, #Size_Paddle_Y, #Size_Paddle_Z, #PB_Absolute)
  
  CreateEntity(#Ent_PaddleBuildCyl01, MeshID(#Msh_PaddleBuildCyl01), MaterialID(#Mat_PaddleBuild))
  MoveEntity(#Ent_PaddleBuildCyl01, #Pos_Paddle_X, #Pos_Paddle_Y + #Size_Paddle_Y/2, #Pos_Paddle_Z + 5, #PB_Absolute)
  RotateEntity(#Ent_PaddleBuildCyl01, 0, 0, 90, #PB_Absolute)
  
  CreateEntity(#Ent_PaddleBuildCyl02, MeshID(#Msh_PaddleBuildCyl01), MaterialID(#Mat_PaddleBuild))
  MoveEntity(#Ent_PaddleBuildCyl02, #Pos_Paddle_X, #Pos_Paddle_Y - #Size_Paddle_Y/2, #Pos_Paddle_Z + 5, #PB_Absolute)
  RotateEntity(#Ent_PaddleBuildCyl02, 0, 0, 90, #PB_Absolute)
  
  CreateEntity(#Ent_PaddleBuildCyl03, MeshID(#Msh_PaddleBuildCyl02), MaterialID(#Mat_PaddleBuild))
  MoveEntity(#Ent_PaddleBuildCyl03, #Pos_Paddle_X - #Size_Paddle_X/2, #Pos_Paddle_Y, #Pos_Paddle_Z + 5, #PB_Absolute)
  
  CreateEntity(#Ent_PaddleBuildCyl04, MeshID(#Msh_PaddleBuildCyl02), MaterialID(#Mat_PaddleBuild))
  MoveEntity(#Ent_PaddleBuildCyl04, #Pos_Paddle_X + #Size_Paddle_X/2, #Pos_Paddle_Y, #Pos_Paddle_Z + 5, #PB_Absolute)
  
  CreateEntity(#Ent_PaddleBuildSph01, MeshID(#Msh_PaddleBuildSph), MaterialID(#Mat_PaddleBuild))
  MoveEntity(#Ent_PaddleBuildSph01, #Pos_Paddle_X - #Size_Paddle_X/2, #Pos_Paddle_Y + #Size_Paddle_Y/2, #Pos_Paddle_Z + 5, #PB_Absolute)
  
  CreateEntity(#Ent_PaddleBuildSph02, MeshID(#Msh_PaddleBuildSph), MaterialID(#Mat_PaddleBuild))
  MoveEntity(#Ent_PaddleBuildSph02, #Pos_Paddle_X + #Size_Paddle_X/2, #Pos_Paddle_Y + #Size_Paddle_Y/2, #Pos_Paddle_Z + 5, #PB_Absolute)
  
  CreateEntity(#Ent_PaddleBuildSph03, MeshID(#Msh_PaddleBuildSph), MaterialID(#Mat_PaddleBuild))
  MoveEntity(#Ent_PaddleBuildSph03, #Pos_Paddle_X - #Size_Paddle_X/2, #Pos_Paddle_Y - #Size_Paddle_Y/2, #Pos_Paddle_Z + 5, #PB_Absolute)
  
  CreateEntity(#Ent_PaddleBuildSph04, MeshID(#Msh_PaddleBuildSph), MaterialID(#Mat_PaddleBuild))
  MoveEntity(#Ent_PaddleBuildSph04, #Pos_Paddle_X + #Size_Paddle_X/2, #Pos_Paddle_Y - #Size_Paddle_Y/2, #Pos_Paddle_Z + 5, #PB_Absolute)
  
  CreateNode(#Nod_Paddle, #Pos_Paddle_X, #Pos_Paddle_Y, #Pos_Paddle_Z)
  AttachNodeObject(#Nod_Paddle, EntityID(#Ent_Paddle))
  AttachNodeObject(#Nod_Paddle, EntityID(#Ent_PaddleBuildCyl01))
  AttachNodeObject(#Nod_Paddle, EntityID(#Ent_PaddleBuildCyl02))
  AttachNodeObject(#Nod_Paddle, EntityID(#Ent_PaddleBuildCyl03))
  AttachNodeObject(#Nod_Paddle, EntityID(#Ent_PaddleBuildCyl04))
  AttachNodeObject(#Nod_Paddle, EntityID(#Ent_PaddleBuildSph01))
  AttachNodeObject(#Nod_Paddle, EntityID(#Ent_PaddleBuildSph02))
  AttachNodeObject(#Nod_Paddle, EntityID(#Ent_PaddleBuildSph03))
  AttachNodeObject(#Nod_Paddle, EntityID(#Ent_PaddleBuildSph04))
  
  LogIt("created Entities")
  
EndProcedure

Procedure CreateLights()
  
  Static.i lf, rt, tp, bt, fr, init
  
  Protected.i color = RGB(255, 255, 255)
  
  If Not init
    lf = -ScreenWidth()/2
    rt = ScreenWidth()/2
    tp = ScreenHeight()/2
    bt = -ScreenHeight()/2
    fr = (ScreenWidth() + ScreenHeight()) * -1
    init = #True
  EndIf
  
  CreateLight(#Lgt_RoomRL, color, lf, 0, 0, #PB_Light_Directional)
  CreateLight(#Lgt_RoomRR, color, rt, 0, 0, #PB_Light_Directional)
  CreateLight(#Lgt_RoomTL, color, lf, 0, fr, #PB_Light_Directional)
  CreateLight(#Lgt_RoomTR, color, rt, 0, fr, #PB_Light_Directional)
  
  ;CreateLight(#Lgt_Paddle, RGB(255, 255, 255), 0, 0, -600, #PB_Light_Directional)
  ;LightDirection(#Lgt_Paddle, 0, 0, -1)
  
  LogIt("created lights")

EndProcedure

Procedure CreateScoreBoard()
  
  Shared WindowWidth, WindowHeight, PlayerBalls, PlayerScore
  
  Static.i lastScore, lastBalls
  
  Protected.i hFont1
  Protected.s balls, score
  
  If lastScore = PlayerScore And lastBalls = PlayerBalls
    ProcedureReturn 0
  EndIf
  
  balls = "balls " + RSet(Str(PlayerBalls), 5, "0")
  score = "score " + RSet(Str(PlayerScore), 5, "0")
  
  If IsTexture(#Tex_Scoreboard)
    FreeTexture(#Tex_Scoreboard)
  EndIf
  
  hFont1 = LoadFont(#PB_Any, "Comic Sans MS", 28, #PB_Font_Bold|#PB_Font_HighQuality)
  CreateTexture(#Tex_Scoreboard, 256, 256)
  StartDrawing(TextureOutput(#Tex_Scoreboard))
  DrawingMode(#PB_2DDrawing_Transparent)
  Box(0, 0, 256, 256, RGB(0,0,0))
  DrawingFont(FontID(hFont1))
  DrawText(256-TextWidth(score), 0, score, RGB(255, 215, 0))
  DrawText(256-TextWidth(balls), TextHeight(balls)+20, balls, RGB(255, 215, 0))
  StopDrawing()
  
  If IsMaterial(#Mat_Scoreboard)
    FreeMaterial(#Mat_Scoreboard)
  EndIf
  
  CreateMaterial(#Mat_Scoreboard, TextureID(#Tex_Scoreboard))
  MaterialBlendingMode(#Mat_Scoreboard, #PB_Material_Add)
  MaterialShadingMode(#Mat_Scoreboard, #PB_Material_Phong)
  MaterialFilteringMode(#Mat_Scoreboard, #PB_Material_Anisotropic, 4)
  
  If Not IsMesh(#Msh_Scoreboard)
    CreatePlane(#Msh_Scoreboard, 256, 256, 1, 1, 1, 1)
  EndIf
  
  If IsEntity(#Ent_Scoreboard)
    SetEntityMaterial(#Ent_Scoreboard, MaterialID(#Mat_Scoreboard))
  Else
    CreateEntity(#Ent_Scoreboard, MeshID(#Msh_Scoreboard), MaterialID(#Mat_Scoreboard), -WindowWidth/3, WindowHeight/5, #Pos_Paddle_Z)
    RotateEntity(#Ent_Scoreboard, 90, 150, 60, #PB_Absolute)
  EndIf
  
  lastScore = PlayerScore
  lastBalls = PlayerBalls
  
EndProcedure

Procedure NewBall()
  
  Shared Dir_Ball
  Shared BallLocked, PlayerBalls, PlayerLevelstart, PlayerTime
  
  If IsEntity(#Ent_Ball)
    FreeEntity(#Ent_Ball)
  EndIf
  
  CreateEntity(#Ent_Ball, MeshID(#Msh_Ball), MaterialID(#Mat_Ball), #Pos_Paddle_X, #Pos_Paddle_Y, #Pos_Paddle_Z - #Size_Ball_Radi)
  
  Dir_Ball\x = 0.25
  Dir_Ball\y = 0
  Dir_Ball\z = -1 
  
  BallLocked = #True
  
  PlayerBalls + 1
  If PlayerLevelstart = 0
    PlayerTime = ElapsedMilliseconds()
    PlayerLevelstart = 1
  EndIf
  
  LogIt("created new Ball")
  
EndProcedure

Procedure CreateNewLevel(LevelNo.i)
  
  Shared Ent_Blocks()
  Shared BlockWidth, BlockHeight, BlockDepth, LevelAreaX, LevelAreaY, LevelAreaZ
  
  Static.i lf, rt, tp, bt, fr, init
  
  Protected.i type, bgmat, material, x, y, z, n
  
  If Not init
    lf = -ScreenWidth()/2
    rt = ScreenWidth()/2
    tp = ScreenHeight()/2
    bt = -ScreenHeight()/2
    fr = (ScreenWidth() + ScreenHeight()) * -1
    init = #True
  EndIf
  
  If ListSize(Ent_Blocks()) > 0
    ForEach Ent_Blocks()
      If IsEntity(Ent_Blocks()\h)
        FreeEntity(Ent_Blocks()\h)
      EndIf
    Next
    ClearList(Ent_Blocks())
  EndIf
  
  Select LevelNo
    Case 0 : Restore Level00
    Case 1 : Restore Level01
    Case 2 : Restore Level02
    Case 3 : Restore Level03
    Case 4 : Restore Level04
    Case 5 : Restore Level05
  EndSelect
  
  Read bgmat
  Select bgmat
    Case 1 : material = MaterialID(#Mat_Room01)
    Case 2 : material = MaterialID(#Mat_Room02)
    Case 3 : material = MaterialID(#Mat_Room03)
  EndSelect
  
  SetEntityMaterial(#Ent_RoomBT, material)
  SetEntityMaterial(#Ent_RoomFR, material)
  SetEntityMaterial(#Ent_RoomLF, material)
  SetEntityMaterial(#Ent_RoomRT, material)
  SetEntityMaterial(#Ent_RoomTP, material)
  
  For z = 0 To 4
    For y = 0 To 4
      For x = 0 To 9
        Read type
        Select type
          Case 1 : material = #Mat_Block01
          Case 2 : material = #Mat_Block02
          Case 3 : material = #Mat_Block03
          Case 4 : material = #Mat_Block04
          Case 5 : material = #Mat_Block05
          Case 6 : material = #Mat_Block06
          Case 7 : material = #Mat_Block07
          Case 8 : material = #Mat_Block08
        EndSelect
        If type > 0
          AddElement(Ent_Blocks())
          Ent_Blocks()\h = CreateEntity(#PB_Any, MeshID(#Msh_Block), MaterialID(material), LevelAreaX+(x*BlockWidth), LevelAreaY-(y*BlockHeight), LevelAreaZ+(z*BlockDepth), #Obj_Block)
          ScaleEntity(Ent_Blocks()\h, BlockWidth, BlockHeight, BlockDepth, #PB_Absolute)
          Ent_Blocks()\hit = 1
          Ent_Blocks()\hmat = material
          Ent_Blocks()\bonus = Random(10)
          For n = 0 To 7
            CalcBlockPoints(n, EntityX(Ent_Blocks()\h), EntityY(Ent_Blocks()\h), EntityZ(Ent_Blocks()\h), Ent_Blocks()\p(n))
          Next
        EndIf
      Next
    Next
  Next
  
  LogIt("created Level "+Str(LevelNo)+", has "+Str(ListSize(Ent_Blocks()))+" blocks")
  
EndProcedure

Procedure MainMenu()
  
  Shared AppVersion, FullScreen, WindowWidth, WindowHeight, BlockWidth, BlockHeight, BlockDepth
  
  Protected.i x, y, cam, ball, change, speed, fontvb, fontb, tex1, tex2, tex3, tex4
  Protected.s txt_logo, txt_start, txt_end
  Protected.b menuLoop = #True
  
  NewList blocks.i()
  
  speed = 8
  
  txt_logo  = "A R K A N O 3 D"
  txt_start = "press SPACE to start"
  txt_end   = "press CTRL+X to quit"
  
  fontvb = LoadFont(#PB_Any, "Comic Sans MS", 48, #PB_Font_Bold|#PB_Font_HighQuality)
  fontb  = LoadFont(#PB_Any, "Comic Sans MS", 28, #PB_Font_Bold|#PB_Font_HighQuality)
  
  tex1 = CreateSprite(#PB_Any, 128, 32)
  TransparentSpriteColor(tex1, 0)
  StartDrawing(SpriteOutput(tex1))
  DrawText(0, SpriteHeight(tex1)-TextHeight(AppVersion), "Version " + AppVersion, RGB(255,255,255), 0)
  StopDrawing()
  
  tex2 = CreateSprite(#PB_Any, WindowWidth, 128)
  TransparentSpriteColor(tex2, 0)
  StartDrawing(SpriteOutput(tex2))
  DrawingFont(FontID(fontvb))
  DrawText((SpriteWidth(tex2)-TextWidth(txt_logo))/2, SpriteHeight(tex2)-TextHeight(txt_logo), txt_logo, RGB(255,255,255), 0)
  StopDrawing()
  
  tex3 = CreateSprite(#PB_Any, WindowWidth, 64)
  TransparentSpriteColor(tex3, 0)
  StartDrawing(SpriteOutput(tex3))
  DrawingFont(FontID(fontb))
  DrawText((SpriteWidth(tex3)-TextWidth(txt_start))/2, SpriteHeight(tex3)-TextHeight(txt_start), txt_start, RGB(255,255,0), 0)
  StopDrawing()
  
  tex4 = CreateSprite(#PB_Any, WindowWidth, 64)
  TransparentSpriteColor(tex4, 0)
  StartDrawing(SpriteOutput(tex4))
  DrawingFont(FontID(fontb))
  DrawText((SpriteWidth(tex4)-TextWidth(txt_end))/2, SpriteHeight(tex4)-TextHeight(txt_end), txt_end, RGB(255,255,0), 0)
  StopDrawing()
  
  For y = 0 To 10
    For x = -0.5 To 0.5
      AddElement(blocks())
      blocks() = CreateEntity(#PB_Any, MeshID(#Msh_Block), MaterialID(Random(#Mat_Block07, #Mat_Block01)), (x * BlockWidth), -BlockHeight, y * -BlockDepth)
      ScaleEntity(blocks(), BlockWidth, BlockHeight, BlockDepth)
    Next
  Next
  
  ball = CreateEntity(#PB_Any, MeshID(#Msh_Ball), MaterialID(#Mat_Ball), 0, 0, 8 * -BlockDepth)
  
  Fog(RGB(0,0,0), 128, 5*BlockDepth, 10*BlockDepth)
  
  cam = CreateCamera(#PB_Any, 0, 0, 100, 100)
  LogIt("created Mainmenu")
  
  Repeat
    
    If FullScreen = 0
      While WindowEvent() <> 0 : Wend
    EndIf
    
    If ExamineKeyboard()
      
      If KeyboardPushed(#PB_Key_LeftControl) And KeyboardReleased(#PB_Key_X)
        LogIt("closed by user")
        End
      ElseIf KeyboardReleased(#PB_Key_Space)
        menuLoop = #False
      EndIf
      
    EndIf
    
    If ExamineMouse() : EndIf
    
    change + speed
    If change >= BlockDepth
      change = 0
      FirstElement(blocks())
      FreeEntity(blocks()) : DeleteElement(blocks(), 1)
      FreeEntity(blocks()) : DeleteElement(blocks(), 1)
      FreeEntity(blocks()) : DeleteElement(blocks(), 1)
      LastElement(blocks())
      For x = -0.5 To 0.5
        AddElement(blocks())
        blocks() = CreateEntity(#PB_Any, MeshID(#Msh_Block), MaterialID(Random(#Mat_Block07, #Mat_Block01)), (x * BlockWidth), -BlockHeight, 10 * -BlockDepth)
        ScaleEntity(blocks(), BlockWidth, BlockHeight, BlockDepth)
      Next
    EndIf
    
    ForEach blocks()
      MoveEntity(blocks(), 0, 0, speed, #PB_Relative)
    Next
    
    RotateEntity(ball, -speed, 0, 0, #PB_Relative)
    
    RenderWorld()
    
    DisplayTransparentSprite(tex2, 0, 50) ; logo
    
    DisplayTransparentSprite(tex3, 0, WindowHeight/2)
    DisplayTransparentSprite(tex4, 0, WindowHeight/2+SpriteHeight(tex3))
    
    DisplayTransparentSprite(tex1, 0, WindowHeight-SpriteHeight(tex1))
    
    FlipBuffers()
    
  Until menuLoop = #False
  
  FreeSprite(tex1)
  FreeSprite(tex2)
  FreeSprite(tex3)
  FreeSprite(tex4)
  ForEach blocks()
    FreeEntity(blocks())
  Next
  ClearList(blocks())
  FreeEntity(ball)
  Fog(0, 0, 0, 0)
  FreeCamera(cam)
  
EndProcedure

---
Windows 11 (64 bit)
Benutzeravatar
Makke
Beiträge: 156
Registriert: 24.08.2011 18:00
Computerausstattung: AMD Ryzen 7 5700X - AMD Radeon RX 6800 XT - 32 GB DDR4 SDRAM
Wohnort: Ruhrpott
Kontaktdaten:

Re: Arkano3d - Arkanoid Clone in 3D

Beitrag von Makke »

Hier der zweite Teil des Codes:

Code: Alles auswählen

;--- Movement & Animations
Procedure ShowActionCam()
  
  Shared ViewCam, Dir_Ball
  
  Protected maxWidth.i  = ScreenWidth(); * 2
  Protected maxHeight.i = ScreenHeight(); * 2
  Protected maxDepth.i  = maxWidth + maxHeight
  
  If ViewCam = 0 ; overview cam
    
    If IsCamera(#Cam_Ball)
      FreeCamera(#Cam_Ball)
    EndIf
    CreateCamera(#Cam_Overview, 80, 65, 12, 35)
    MoveCamera(#Cam_Overview, 0, maxHeight*4, -maxDepth/2, #PB_Absolute)
    RotateCamera(#Cam_Overview, -90, 0, 0, #PB_Absolute)
    LogIt("switched to Overview camera")
    ViewCam = 1
    
  Else ; ball cam
    
    If IsCamera(#Cam_Overview)
      FreeCamera(#Cam_Overview)
    EndIf
    CreateCamera(#Cam_Ball, 80, 65, 20, 35)
    MoveCamera(#Cam_Ball, EntityX(#Ent_Ball), EntityY(#Ent_Ball), EntityZ(#Ent_Ball), #PB_Absolute)
    CameraDirection(#Cam_Ball, Dir_Ball\x, Dir_Ball\y, Dir_Ball\z)
    LogIt("switched to Ball camera")
    ViewCam = 0
    
  EndIf
  
EndProcedure

Procedure MovePaddel()
  
  Static.i lf, rt, tp, bt, init
  Protected MouseMoveX.i = MouseDeltaX()
  Protected MouseMoveY.i = MouseDeltaY()
  Protected x.i = EntityX(#Ent_Paddle)
  Protected y.i = EntityY(#Ent_Paddle)
  
  If Not init
    lf = -ScreenWidth()/2
    rt = ScreenWidth()/2
    tp = ScreenHeight()/2
    bt = -ScreenHeight()/2
    init = #True
  EndIf
  
  If x-#Size_Paddle_X/2 <= lf And MouseMoveX < 0
    
    ;MoveEntity(#Ent_Paddle, 0, -MouseMoveY * 0.5, 0, #PB_Relative)
    MoveNode(#Nod_Paddle, 0, -MouseMoveY * 0.5, 0, #PB_Relative)
    ProcedureReturn 1
    
  ElseIf x+#Size_Paddle_X/2 >= rt And MouseMoveX > 0
    
    ;MoveEntity(#Ent_Paddle, 0, -MouseMoveY * 0.5, 0, #PB_Relative)
    MoveNode(#Nod_Paddle, 0, -MouseMoveY * 0.5, 0, #PB_Relative)
    ProcedureReturn 2
    
  EndIf
  
  If y+#Size_Paddle_Y/2 >= tp And MouseMoveY < 0
    
    ;MoveEntity(#Ent_Paddle, MouseMoveX * 0.5, 0, 0, #PB_Relative)
    MoveNode(#Nod_Paddle, MouseMoveX * 0.5, 0, 0, #PB_Relative)
    ProcedureReturn 3
    
  ElseIf y-#Size_Paddle_Y/2 <= bt And MouseMoveY > 0
    
    ;MoveEntity(#Ent_Paddle, MouseMoveX * 0.5, 0, 0, #PB_Relative)
    MoveNode(#Nod_Paddle, MouseMoveX * 0.5, 0, 0, #PB_Relative)
    ProcedureReturn 4
    
  EndIf
  
  ;MoveEntity(#Ent_Paddle, MouseMoveX * 0.5, -MouseMoveY * 0.5, 0, #PB_Relative)
  MoveNode(#Nod_Paddle, MouseMoveX * 0.5, -MouseMoveY * 0.5, 0, #PB_Relative)
  If IsLight(#Lgt_Paddle)
    MoveLight(#Lgt_Paddle, EntityX(#Ent_Paddle), EntityY(#Ent_Paddle), EntityZ(#Ent_Paddle)-100, #PB_Absolute)
  EndIf
    
EndProcedure

Procedure ShowTouchAnim()
  
  Shared BallTouchAnim()

  ForEach BallTouchAnim()
    
    BallTouchAnim()\count + BallTouchAnim()\singlestep
    
    If BallTouchAnim()\count >= BallTouchAnim()\change
      
      BallTouchAnim()\count = 0
      BallTouchAnim()\steps - 1
      BallTouchAnim()\hMat  + 1
      
      If BallTouchAnim()\steps = 0
        
        FreeEntity(BallTouchAnim()\hEnt)
        DeleteElement(BallTouchAnim())
        
      Else
        
        SetEntityMaterial(BallTouchAnim()\hEnt, MaterialID(BallTouchAnim()\hMat))
        
      EndIf
      
    EndIf
    
  Next
  
EndProcedure

Procedure AddTouchAnim(Side.i)
  
  Shared BallTouchAnim()
  
  AddElement(BallTouchAnim())
  BallTouchAnim()\steps      = 10 ; how many materials ?
  BallTouchAnim()\singlestep = 2
  BallTouchAnim()\change     = Engine3DFrameRate(#PB_Engine3D_Current) / BallTouchAnim()\steps
  BallTouchAnim()\count      = 0
  BallTouchAnim()\hMat       = #Mat_BallTouch01 ; first material in a row
  BallTouchAnim()\hEnt       = CreateEntity(#PB_Any, MeshID(#Msh_BallTouch), MaterialID(BallTouchAnim()\hMat), EntityX(#Ent_Ball), EntityY(#Ent_Ball), EntityZ(#Ent_Ball))
  
  Select Side
    Case 1 : RotateEntity(BallTouchAnim()\hEnt, 90, 0, 270, #PB_Absolute) ; left
    Case 2 : RotateEntity(BallTouchAnim()\hEnt, 90, 0, 90, #PB_Absolute) ; right
    Case 3 : RotateEntity(BallTouchAnim()\hEnt, 180, 0, 0, #PB_Absolute) ; top
    Case 4 : ; bottom
    Case 5 : RotateEntity(BallTouchAnim()\hEnt, 90, 0, 0, #PB_Absolute) ; rear
  EndSelect
  
EndProcedure

Procedure ShowBlockDestroyAnim()
  
  Shared BlockAnim()
  
  Protected.i moveBills
  
  If ListSize(BlockAnim()) = 0
    ProcedureReturn 0
  EndIf
  
  ForEach BlockAnim()
    
    BlockAnim()\count + BlockAnim()\singlestep
    
    If BlockAnim()\count >= BlockAnim()\change
      
      BlockAnim()\count = 0
      BlockAnim()\steps - 1
      BlockAnim()\hMat  + 1
      
      If BlockAnim()\steps = 0
        ClearBillboards(BlockAnim()\hGroup)
        FreeBillboardGroup(BlockAnim()\hGroup)
        ClearList(BlockAnim()\bills())
        DeleteElement(BlockAnim())
        Continue
      Else
        BillboardGroupMaterial(BlockAnim()\hGroup, MaterialID(BlockAnim()\hMat))
      EndIf
      
    EndIf
    
    ForEach BlockAnim()\bills()
      MoveBillboard(BlockAnim()\bills()\h, BlockAnim()\hGroup, BlockAnim()\bills()\d\x, BlockAnim()\bills()\d\y, BlockAnim()\bills()\d\z)
    Next
    
  Next
  
EndProcedure  

Procedure AddBlockDestroyAnim(hMaterial.i, x.i, y.i, z.i)
  
  Shared BlockAnim()
  Shared BlockWidth, BlockHeight
  
  Protected.i n
  
  AddElement(BlockAnim())
  BlockAnim()\steps      = 5 ; how many materials ?
  BlockAnim()\singlestep = 1
  BlockAnim()\change     = Engine3DFrameRate(#PB_Engine3D_Current) / BlockAnim()\steps
  BlockAnim()\count      = 0
  
  Select hMaterial
    Case #Mat_Block01 : BlockAnim()\hMat = #Mat_Block01Ani01
    Case #Mat_Block02 : BlockAnim()\hMat = #Mat_Block02Ani01
    Case #Mat_Block03 : BlockAnim()\hMat = #Mat_Block03Ani01
    Case #Mat_Block04 : BlockAnim()\hMat = #Mat_Block04Ani01
    Case #Mat_Block05 : BlockAnim()\hMat = #Mat_Block05Ani01
    Case #Mat_Block06 : BlockAnim()\hMat = #Mat_Block06Ani01
    Case #Mat_Block07 : BlockAnim()\hMat = #Mat_Block07Ani01
    Case #Mat_Block08 : BlockAnim()\hMat = #Mat_Block08Ani01
  EndSelect
  
  BlockAnim()\hGroup = CreateBillboardGroup(#PB_Any, MaterialID(BlockAnim()\hMat), BlockWidth/10, BlockHeight/10, x, y, z)
  
  For n = 0 To 50
    AddElement(BlockAnim()\bills())
    BlockAnim()\bills()\h = n
    BlockAnim()\bills()\d\x = (Random(20)-10) / 10 ; this is the direction of the billboard
    BlockAnim()\bills()\d\y = (Random(20)-10) / 10
    BlockAnim()\bills()\d\z = (Random(20)-10) / 10
    AddBillboard(n, BlockAnim()\hGroup, 0, 0, 0)
  Next
  
EndProcedure

Procedure MoveBall()
  
  Shared Ent_Blocks()
  Shared Dir_Ball
  Shared BallLocked, BallTouched, PlayerScore
  
  Static.i speed = 20
  Static.i lf, rt, tp, bt, fr, init
  
  Protected.fVector3D ball, paddle
  Protected.i blockSide, camSlide, counter, collide
  Protected.f oldZ = Dir_Ball\z
  
  If Not init
    lf = -ScreenWidth()/2
    rt = ScreenWidth()/2
    tp = ScreenHeight()/2
    bt = -ScreenHeight()/2
    fr = (ScreenWidth() + ScreenHeight()) * -1
    init = #True
  EndIf
  
  ball\x = EntityX(#Ent_Ball)
  ball\y = EntityY(#Ent_Ball)
  ball\z = EntityZ(#Ent_Ball)
  
  paddle\x = EntityX(#Ent_Paddle)
  paddle\y = EntityY(#Ent_Paddle)
  paddle\z = EntityZ(#Ent_Paddle)
  
  ; collide with left or right wall
  If ball\x-#Size_Ball_Radi <= lf 
    Dir_Ball\x * -1
    AddTouchAnim(1)
  EndIf
  If ball\x+#Size_Ball_Radi >= rt
    Dir_Ball\x * -1
    AddTouchAnim(2)
  EndIf
  
  ; collide with top or bottom wall
  If ball\y+#Size_Ball_Radi >= tp 
    Dir_Ball\y * -1
    AddTouchAnim(3)
  EndIf
  If ball\y-#Size_Ball_Radi <= bt
    Dir_Ball\y * -1
    AddTouchAnim(4)
  EndIf
  
  ; collide with front wall
  If ball\z-#Size_Ball_Radi <= fr
    Dir_Ball\z * -1
    AddTouchAnim(5)
    camSlide = #True
  EndIf
  
  ; collide with paddle
  If ball\z-#Size_Ball_Radi >= paddle\z-#Size_Paddle_Z/2 
    If ball\x >= paddle\x-#Size_Paddle_X/2 And ball\x <= paddle\x+#Size_Paddle_X/2 And ball\y <= paddle\y+#Size_Paddle_Y/2 And ball\y >= paddle\y-#Size_Paddle_Y/2
      Dir_Ball\x = paddle\x / #Size_Paddle_X/4 * -1
      Dir_Ball\y = paddle\y / #Size_Paddle_Y/4 * -1
      Dir_Ball\z * -1
      camSlide = #True
    EndIf
  EndIf
  
  ; ball is out
  If ball\z >= #Pos_Paddle_Z + 50
    NewBall()
    ;Debug "Ball Out"
  EndIf
  
  ; collide with  blocks
  ForEach Ent_Blocks()
    
    blockSide = BallBlock_Collision(Ent_Blocks(), ball)
    
    If Not collide
      Select blockSide
        Case 1 : Dir_Ball\y * -1 : collide = #True
        Case 2 : Dir_Ball\y * -1 : collide = #True
        Case 3 : Dir_Ball\z * -1 : collide = #True
        Case 4 : Dir_Ball\z * -1 : collide = #True
        Case 5 : Dir_Ball\x * -1 : collide = #True
        Case 6 : Dir_Ball\x * -1 : collide = #True
      EndSelect
    EndIf
      
    If blockSide
      AddBlockDestroyAnim(Ent_Blocks()\hMat, EntityX(Ent_Blocks()\h), EntityY(Ent_Blocks()\h), EntityZ(Ent_Blocks()\h))
      FreeEntity(Ent_Blocks()\h)
      DeleteElement(Ent_Blocks())
      PlayerScore + 100
    EndIf
      
  Next
  
  ; level finished ?
  If ListSize(Ent_Blocks()) = 0
    LevelFinished()
  EndIf

  ; move ball
  If BallLocked
    MoveEntity(#Ent_Ball, paddle\x, paddle\y, paddle\z - #Size_Ball_Radi, #PB_Absolute)
  Else
    MoveEntity(#Ent_Ball, Dir_Ball\x * speed, Dir_Ball\y * speed, Dir_Ball\z * speed)
    RotateEntity(#Ent_Ball, Dir_Ball\x * speed, Dir_Ball\y * speed, 0, #PB_Relative)
    If IsCamera(#Cam_Ball)
      MoveCamera(#Cam_Ball, EntityX(#Ent_Ball), EntityY(#Ent_Ball), EntityZ(#Ent_Ball), #PB_Absolute)
      If camSlide
        While counter <= 180
          counter + 1
          RotateCamera(#Cam_Ball, 1, 0, 0, #PB_Relative)
        Wend
      EndIf
      CameraDirection(#Cam_Ball, Dir_Ball\x, Dir_Ball\y, Dir_Ball\z)
    EndIf
  EndIf
  
  ProcedureReturn 0
  
EndProcedure

Procedure MoveBallTarget()
  
  Shared Dir_Ball
  Shared BallLocked
  
  Static.i lf, rt, tp, bt, ln, init
  
  Protected.f length, x, y, z
  
  If Not init
    lf = -ScreenWidth()/2 + 64
    rt = ScreenWidth()/2 - 64
    tp = ScreenHeight()/2 - 64
    bt = -ScreenHeight()/2 + 64
    ln = (ScreenWidth() + ScreenHeight())
    init = #True
  EndIf
  
  If BallLocked
    If IsEntity(#Ent_BallTarget)
      FreeEntity(#Ent_BallTarget)
    EndIf
    ProcedureReturn 0
  EndIf
  
  If Not IsEntity(#Ent_BallTarget)
    CreateEntity(#Ent_BallTarget, MeshID(#Msh_BallTarget), MaterialID(#Mat_BallTarget))
    RotateEntity(#Ent_BallTarget, 90, 0, 0, #PB_Absolute)
  EndIf
  
  length = #Pos_Paddle_Z - EntityZ(#Ent_Ball)
  
  If length < ln/5*1
    SetEntityMaterial(#Ent_BallTarget, MaterialID(#Mat_BallTarget01))
  ElseIf length < ln/5*2
    SetEntityMaterial(#Ent_BallTarget, MaterialID(#Mat_BallTarget02))
  ElseIf length < ln/5*3
    SetEntityMaterial(#Ent_BallTarget, MaterialID(#Mat_BallTarget03))
  ElseIf length < ln/5*4
    SetEntityMaterial(#Ent_BallTarget, MaterialID(#Mat_BallTarget04))
  Else
    SetEntityMaterial(#Ent_BallTarget, MaterialID(#Mat_BallTarget05))
  EndIf
  
  x = EntityX(#Ent_Ball) + length * Dir_Ball\x
  y = EntityY(#Ent_Ball) + length * -Dir_Ball\y
  z = 0
  
  If x < lf
    x = lf
  ElseIf x > rt
    x = rt
  EndIf
  
  If y < bt
    y = bt
  ElseIf y > tp
    y = tp
  EndIf
  
  MoveEntity(#Ent_BallTarget, x, y, z, #PB_Absolute)
  RotateEntity(#Ent_BallTarget, 0, 1 , 0, #PB_Relative)
  
EndProcedure

;--- Collision Detection
;Quelle: http://www.neobrothers.de/oldpage1/tutorials/3dcollision.html
Procedure BallBall_Collision(*Ball1.fVector3D, *Ball2.fVector3D, Radi1.i, Radi2.i)
  If (Pow(*Ball1\x - *Ball2\x,2) + Pow(*Ball1\y - *Ball2\y,2) + Pow(*Ball1\z - *Ball2\z,2)) < Pow(Radi1 + Radi2,2)
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
EndProcedure

Procedure BallBlock_Collision(*box.Box3D, *point.fVector3D)
  
  Protected.i side = 0
  Protected.f dot, minDot
  Protected.fVector3D normal, result1, result2, result3
  
  ; bottom
  VectorSub(*box\p(1), *box\p(0), result1)
  VectorSub(*box\p(2), *box\p(0), result2)
  VectorCross(result1, result2, normal)
  VectorNormalize(normal)
  VectorSub(*point, *box\p(0), result3)
  dot = VectorDot(normal, result3)
  If dot <= -#Size_Ball_Radi
    ProcedureReturn 0
  Else
    minDot = dot
    side = 1
  EndIf
  
  ; top
  VectorSub(*box\p(6), *box\p(4), result1)
  VectorSub(*box\p(5), *box\p(4), result2)
  VectorCross(result1, result2, normal)
  VectorNormalize(normal)
  VectorSub(*point, *box\p(4), result3)
  dot = VectorDot(normal, result3)
  If dot <= -#Size_Ball_Radi
    ProcedureReturn 0
  Else
    If dot < minDot
      minDot = dot
      side = 2
    EndIf
  EndIf
  
  ; front
  VectorSub(*box\p(6), *box\p(2), result1)
  VectorSub(*box\p(3), *box\p(2), result2)
  VectorCross(result1, result2, normal)
  VectorNormalize(normal)
  VectorSub(*point, *box\p(2), result3)
  dot = VectorDot(normal, result3)
  If dot <= -#Size_Ball_Radi
    ProcedureReturn 0
  Else
    If dot < minDot
      minDot = dot
      side = 3
    EndIf
  EndIf
  
  ; rear
  VectorSub(*box\p(4), *box\p(0), result1)
  VectorSub(*box\p(1), *box\p(0), result2)
  VectorCross(result1, result2, normal)
  VectorNormalize(normal)
  VectorSub(*point, *box\p(0), result3)
  dot = VectorDot(normal, result3)
  If dot <= -#Size_Ball_Radi
    ProcedureReturn 0
  Else
    If dot < minDot
      minDot = dot
      side = 4
    EndIf
  EndIf

  ; right
  VectorSub(*box\p(5), *box\p(1), result1)
  VectorSub(*box\p(2), *box\p(1), result2)
  VectorCross(result1, result2, normal)
  VectorNormalize(normal)
  VectorSub(*point, *box\p(1), result3)
  dot = VectorDot(normal, result3)
  If dot <= -#Size_Ball_Radi
    ProcedureReturn 0
  Else
    If dot < minDot
      minDot = dot
      side = 5
    EndIf
  EndIf
  
  ; left
  VectorSub(*box\p(3), *box\p(0), result1)
  VectorSub(*box\p(4), *box\p(0), result2)
  VectorCross(result1, result2, normal)
  VectorNormalize(normal)
  VectorSub(*point, *box\p(0), result3)
  dot = VectorDot(normal, result3)
  If dot <= -#Size_Ball_Radi
    ProcedureReturn 0
  Else
    If dot < minDot
      minDot = dot
      side = 6
    EndIf
  EndIf

  ProcedureReturn side
  
EndProcedure
;- DATA
DataSection
  Level00:
  Data.i 3 ; Background 1-3
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; x=1-10, y=1, z=5 ; creation begins at the farest left-top point
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; x=1-10, y=2, z=5 
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; x=1-10, y=3, z=5 
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; x=1-10, y=4, z=5 
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; x=1-10, y=5, z=5 
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; x=1-10, y=1, z=4 
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; x=1-10, y=2, z=4 
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; x=1-10, y=3, z=4 
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; x=1-10, y=4, z=4 
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; x=1-10, y=5, z=4 
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; x=1-10, y=1, z=3 
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; x=1-10, y=2, z=3 
  Data.i 1, 1, 2, 2, 3, 3, 4, 4, 5, 5 ; x=1-10, y=3, z=3 
  Data.i 0, 0, 6, 6, 7, 7, 8, 8, 0, 0 ; x=1-10, y=4, z=3 
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; x=1-10, y=5, z=3 
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; x=1-10, y=1, z=2 
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; x=1-10, y=2, z=2 
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; x=1-10, y=3, z=2 
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; x=1-10, y=4, z=2 
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; x=1-10, y=5, z=2 
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; x=1-10, y=1, z=1 
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; x=1-10, y=2, z=1 
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; x=1-10, y=3, z=1 
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; x=1-10, y=4, z=1 
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; x=1-10, y=5, z=1 
  Level01:
  Data.i 1
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  Data.i 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
  Data.i 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
  Data.i 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
  Data.i 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
  Data.i 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
  Data.i 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
  Data.i 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
  Data.i 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
  Data.i 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
  Data.i 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
  Data.i 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
  Data.i 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
  Data.i 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
  Data.i 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
  Data.i 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  Level02:
  Data.i 1
  Data.i 6, 6, 6, 6, 6, 6, 6, 6, 6, 6
  Data.i 6, 6, 6, 6, 6, 6, 6, 6, 6, 6
  Data.i 6, 6, 6, 6, 6, 6, 6, 6, 6, 6
  Data.i 6, 6, 6, 6, 6, 6, 6, 6, 6, 6
  Data.i 6, 6, 6, 6, 6, 6, 6, 6, 6, 6
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  Data.i 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
  Data.i 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
  Data.i 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  Data.i 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  Data.i 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
  Data.i 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
  Data.i 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  Data.i 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
  Data.i 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
  Data.i 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
  Data.i 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
  Data.i 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
  Level03:
  Data.i 1
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  Data.i 0, 0, 0, 0, 5, 5, 0, 0, 0, 0
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  Data.i 0, 0, 0, 0, 4, 4, 0, 0, 0, 0
  Data.i 0, 0, 0, 4, 4, 4, 4, 0, 0, 0
  Data.i 0, 0, 0, 0, 4, 4, 0, 0, 0, 0
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  Data.i 0, 0, 0, 0, 3, 3, 0, 0, 0, 0
  Data.i 0, 0, 0, 3, 3, 3, 3, 0, 0, 0
  Data.i 0, 0, 3, 3, 3, 3, 3, 3, 0, 0
  Data.i 0, 0, 0, 3, 3, 3, 3, 0, 0, 0
  Data.i 0, 0, 0, 0, 3, 3, 0, 0, 0, 0
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  Data.i 0, 0, 0, 0, 2, 2, 0, 0, 0, 0
  Data.i 0, 0, 0, 2, 2, 2, 2, 0, 0, 0
  Data.i 0, 0, 0, 0, 2, 2, 0, 0, 0, 0
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  Data.i 0, 0, 0, 0, 1, 1, 0, 0, 0, 0
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  Data.i 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  Level04:
  Data.i 2
  Data.i 0, 0, 0, 0, 1, 1, 0, 0, 0, 0
  Data.i 0, 0, 0, 1, 0, 0, 1, 0, 0, 0
  Data.i 0, 0, 1, 0, 0, 0, 0, 1, 0, 0
  Data.i 0, 1, 0, 0, 0, 0, 0, 0, 1, 0
  Data.i 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
  Data.i 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
  Data.i 0, 2, 0, 0, 0, 0, 0, 0, 2, 0
  Data.i 0, 0, 2, 0, 0, 0, 0, 2, 0, 0
  Data.i 0, 0, 0, 2, 0, 0, 2, 0, 0, 0
  Data.i 0, 0, 0, 0, 2, 2, 0, 0, 0, 0
  Data.i 0, 0, 0, 0, 3, 3, 0, 0, 0, 0
  Data.i 0, 0, 0, 3, 0, 0, 3, 0, 0, 0
  Data.i 0, 0, 3, 0, 0, 0, 0, 3, 0, 0
  Data.i 0, 3, 0, 0, 0, 0, 0, 0, 3, 0
  Data.i 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
  Data.i 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
  Data.i 0, 4, 0, 0, 0, 0, 0, 0, 4, 0
  Data.i 0, 0, 4, 0, 0, 0, 0, 4, 0, 0
  Data.i 0, 0, 0, 4, 0, 0, 4, 0, 0, 0
  Data.i 0, 0, 0, 0, 4, 4, 0, 0, 0, 0
  Data.i 0, 0, 0, 0, 5, 5, 0, 0, 0, 0
  Data.i 0, 0, 0, 5, 0, 0, 5, 0, 0, 0
  Data.i 0, 0, 5, 0, 0, 0, 0, 5, 0, 0
  Data.i 0, 5, 0, 0, 0, 0, 0, 0, 5, 0
  Data.i 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
  Level05:
  Data.i 2
  Data.i 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
  Data.i 1, 0, 0, 0, 0, 0, 0, 0, 0, 1
  Data.i 1, 0, 5, 0, 5, 5, 0, 5, 0, 1
  Data.i 1, 0, 0, 0, 0, 0, 0, 0, 0, 1
  Data.i 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
  Data.i 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
  Data.i 2, 0, 0, 0, 0, 0, 0, 0, 0, 2
  Data.i 2, 0, 4, 0, 4, 4, 0, 4, 0, 2
  Data.i 2, 0, 0, 0, 0, 0, 0, 0, 0, 2
  Data.i 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
  Data.i 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
  Data.i 3, 0, 0, 0, 0, 0, 0, 0, 0, 3
  Data.i 3, 0, 3, 0, 3, 3, 0, 3, 0, 3
  Data.i 3, 0, 0, 0, 0, 0, 0, 0, 0, 3
  Data.i 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
  Data.i 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
  Data.i 4, 0, 0, 0, 0, 0, 0, 0, 0, 4
  Data.i 4, 0, 2, 0, 2, 2, 0, 2, 0, 4
  Data.i 4, 0, 0, 0, 0, 0, 0, 0, 0, 4
  Data.i 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
  Data.i 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
  Data.i 5, 0, 0, 0, 0, 0, 0, 0, 0, 5
  Data.i 5, 0, 1, 0, 1, 1, 0, 1, 0, 5
  Data.i 5, 0, 0, 0, 0, 0, 0, 0, 0, 5
  Data.i 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
EndDataSection
---
Windows 11 (64 bit)
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Arkano3d - Arkanoid Clone in 3D

Beitrag von ts-soft »

:allright:
Spitze, läuft auch unter Linux mit 64-Bit einwandfrei!

Gruß
Thomas
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
Andre
PureBasic Team
Beiträge: 1754
Registriert: 11.09.2004 16:35
Computerausstattung: MacBook Core2Duo mit MacOS 10.6.8
Lenovo Y50 i7 mit Windows 10
Wohnort: Saxony / Deutscheinsiedel
Kontaktdaten:

Re: Arkano3d - Arkanoid Clone in 3D

Beitrag von Andre »

Schade, auf MacOS (wo OpenGL ja der Standard sein und daher nicht als Subsystem eingestellt werden müsste) gibt es offenbar Probleme mit der Tastatursteuerung. Nach dem Startbildschirm und Drücken von <Space> hängt das Programm fest.

Außerdem hab ich die Zeile mit #PB_Editor_BuildCount deaktivieren müssen (=> Bug-Report im engl. Forum), da diese offenbar auf MacOS (bisher) nicht unterstützt wird.
Bye,
...André
(PureBasicTeam::Docs - PureArea.net | Bestellen:: PureBasic | PureVisionXP)
Benutzeravatar
HeX0R
Beiträge: 2954
Registriert: 10.09.2004 09:59
Computerausstattung: AMD Ryzen 7 5800X
96Gig Ram
NVIDIA GEFORCE RTX 3060TI/8Gig
Win10 64Bit
G19 Tastatur
2x 24" + 1x27" Monitore
Glorious O Wireless Maus
PB 3.x-PB 6.x
Oculus Quest 2
Kontaktdaten:

Re: Arkano3d - Arkanoid Clone in 3D

Beitrag von HeX0R »

Andre hat geschrieben:Außerdem hab ich die Zeile mit #PB_Editor_BuildCount deaktivieren müssen (=> Bug-Report im engl. Forum), da diese offenbar auf MacOS (bisher) nicht unterstützt wird.
Hast du diese Konstante denn überhaupt in den Compiler-Optionen aktiviert?
Wenn nicht, kennt sie PB auch nicht.
Benutzeravatar
Sicro
Beiträge: 955
Registriert: 11.08.2005 19:08
Kontaktdaten:

Re: Arkano3d - Arkanoid Clone in 3D

Beitrag von Sicro »

Hallo Makke,

dein Spiel werde ich mir morgen mal ansehen.

Beim überfliegen deines Codes ist mir gerade ein Fehler aufgefallen:
Makke hat geschrieben:For x = -0.5 To 0.5
For-Next-Schleifen unterstützen keine Kommazahlen. Deine Schleife ist also das Gleiche wie:

Code: Alles auswählen

For x = -1 To 1
Bild
Warum OpenSource eine Lizenz haben sollte :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (Syntax-Farbschema) :: RegEx-Engine (kompiliert RegExes zu NFA/DFA)
Manjaro Xfce x64 (Hauptsystem) :: Windows 10 Home (VirtualBox) :: Neueste PureBasic-Version
Benutzeravatar
Andre
PureBasic Team
Beiträge: 1754
Registriert: 11.09.2004 16:35
Computerausstattung: MacBook Core2Duo mit MacOS 10.6.8
Lenovo Y50 i7 mit Windows 10
Wohnort: Saxony / Deutscheinsiedel
Kontaktdaten:

Re: Arkano3d - Arkanoid Clone in 3D

Beitrag von Andre »

HeX0R hat geschrieben: Hast du diese Konstante denn überhaupt in den Compiler-Optionen aktiviert?
Wenn nicht, kennt sie PB auch nicht.
Upps, peinlich... :oops: Nee, hatte ich nicht. Das kommt davon, wenn man eine Funktion das erste Mal nutzt und nix zum wie weiß... sorry! (habe Bug-Report im engl. Forum entsprechend ergänzt)

Unabhängig davon besteht natürlich leider das Hauptproblem mit der Steuerung + anschl. Aufhänger noch...
Bye,
...André
(PureBasicTeam::Docs - PureArea.net | Bestellen:: PureBasic | PureVisionXP)
Benutzeravatar
Makke
Beiträge: 156
Registriert: 24.08.2011 18:00
Computerausstattung: AMD Ryzen 7 5700X - AMD Radeon RX 6800 XT - 32 GB DDR4 SDRAM
Wohnort: Ruhrpott
Kontaktdaten:

Re: Arkano3d - Arkanoid Clone in 3D

Beitrag von Makke »

Andre hat geschrieben:Schade, auf MacOS (wo OpenGL ja der Standard sein und daher nicht als Subsystem eingestellt werden müsste) gibt es offenbar Probleme mit der Tastatursteuerung. Nach dem Startbildschirm und Drücken von <Space> hängt das Programm fest.

Außerdem hab ich die Zeile mit #PB_Editor_BuildCount deaktivieren müssen (=> Bug-Report im engl. Forum), da diese offenbar auf MacOS (bisher) nicht unterstützt wird.
@Andre: Sorry, aber MacOS habe ich nicht verfügbar, ich habe bei einem virtuellen Desktop mit Linux festgestellt, das #PB_Key_All offensichtlich Probleme bereitet. Was sagt denn der Debugger ? Oder kommt eine Fehlermeldung ?

@Sicro: Danke für den Hinweis, das war mir nicht bewusst und komischerweise meckert PB das auch nicht an.
---
Windows 11 (64 bit)
Benutzeravatar
Sicro
Beiträge: 955
Registriert: 11.08.2005 19:08
Kontaktdaten:

Re: Arkano3d - Arkanoid Clone in 3D

Beitrag von Sicro »

Makke hat geschrieben:@Sicro: Danke für den Hinweis, das war mir nicht bewusst und komischerweise meckert PB das auch nicht an.

Code: Alles auswählen

For x = -0.5 To 0.5
Deine Variable "x" ist als Ganzzahl-Typ definiert. Übergibst du der Variable eine Kommazahl, wird diese gerundet. Der Compiler meckert erst, wenn du die Variable mit einem Kommazahl-Typ definierst, denn dann würde die For-Next-Schleife wirklich die Kommazahl lesen.
Bild
Warum OpenSource eine Lizenz haben sollte :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (Syntax-Farbschema) :: RegEx-Engine (kompiliert RegExes zu NFA/DFA)
Manjaro Xfce x64 (Hauptsystem) :: Windows 10 Home (VirtualBox) :: Neueste PureBasic-Version
Antworten