Code: Alles auswählen
;
; -------------------------------------------------------------------------------
;
; PureBasic - Irrlicht
;
; Von 0 auf 100 (c) 2008 - TFT
;
; Part 009
;
; -------------------------------------------------------------------------------
;
; In allen Parts sind die Komentare des vorherigen Parts gelöscht. Und der Code
; soweit gerafft. Das die Übersichtlichkeit nicht all zu arg leidet. Die Neuen
; Code segmente sind mit ;--- gekenzeichnet. Das Procedure Fenster zeigt die
; entsprechenden Sprungmarken.
;
; So .... wir haben ein Object .... wir haben Schüsse. Jetzt müssen wir noch darauf
; reagieren. Das nennt sich Colisionerkennung. Wie immer gibt es zwei möglichkeiten.
; Und wir werden Später auch die Irrlicht eigene Colisions erkennung nutzen..
;
; Wir werden die Schüsse und den Cube mit einer SphereToSphere colision ausstatten.
; Das ist ein einfacher weg. Den wir im ersten durchlauf auch nicht weiter ver-
; komplizieren. Dazu werden wir dem Cube eine Strucktur verpassen. So wie wir es
; mit den schüssen gemacht haben. Dort wird eine ObjectRadius Variable gehalten. Das
; gleiche machen wir bei den Schüssen. Dann berechnen wir den Abstand der Schüsse
; zu dem Cube, ziehen beide Radien ab und erkenne eine Colision wenn das ergebniss
; kleiner/gleich 0 ist. Um das ganze etwas zu veranschaulichen. machen wir einen
; Counter der die Treffer zählt.
;
; Und damit wir sehen wo die Schüsse einschlagen. Werden wir noch etwas Optischen Effect
; hinzupacken. Damit sich die unterschiedliche FPS Raten nicht optisch bemerkbar machen
; müssen wir einen Alpha wert erzeugen. Um Frame unabhängig zu sein.
;
; Es handelt sich hir um eine sehr ungenaue und einfache art der Colisions erkennung.
; Aber für das erste Arcade Game sollte es reichen.
XIncludeFile "Irr3DRequester.pb"
Irr3DRequester(#IRR3DREQ_SKIP)
neustart:
ScrX.l=irr3DRequesterSetting\videomode\dimension\width
ScrY.l=irr3DRequesterSetting\videomode\dimension\height
LeftMouseBotonDown.l=0
RigtMouseBotonDown.l=0
*camera.irr_camera = IrrAddCamera( 0,0,0, 0,0,1 )
*camerapivot.irr_node = IrrAddEmptySceneNode()
IrrAddChildToParent(*camera,*camerapivot)
IrrSetCameraClipDistance(*Camera,10000)
IrrSetCameraNearValue(*Camera,0.1)
;--- Struktur änderung
Structure NodeListe
*node.irr_node
visible.l
ColRadius.f
*Move_animator.irr_animator
*Turn_animator.irr_animator
EndStructure
NewList schuss_liste.NodeListe()
;--- Cube Liste einführen
NewList cube_liste.NodeListe()
AddElement(cube_liste())
cube_liste()\node=IrrAddCubeSceneNode(1)
cube_liste()\visible=0
;--- Colisions Radius Cube
cube_liste()\ColRadius=0.60
*CubeTexture.irr_texture = IrrGetTexture( "test.bmp" )
*CubeBlank.irr_texture = IrrGetTexture( "blank.bmp" )
IrrSetNodePosition(cube_liste()\node,0,0,6)
IrrSetNodeMaterialFlag( cube_liste()\node, #IRR_EMF_LIGHTING, #IRR_Off )
IrrSetNodeMaterialTexture( cube_liste()\node, *CubeBlank, 0 )
IrrSetNodeMaterialFlag( cube_liste()\node, #IRR_EMF_BACK_FACE_CULLING, #IRR_OFF)
IrrSetNodeMaterialType( cube_liste()\node, #IRR_EMT_TRANSPARENT_ADD_COLOR)
cube_liste()\Turn_animator = IrrAddRotationAnimator(cube_liste()\node, 1,0.5,0)
*BitmapFont = IrrGetFont ( "bitmapfont.bmp" )
Restore ObjectData
Read a.l
Read b.l
Read Pfad.s
Dim verts.IRR_VERT(a)
Dim indices.w(b*3)
Restore ObjectPoint
For i=0 To a-1
Read mx.f
Read my.f
Read mz.f
Read tx.f
Read ty.f
vc.l = $00FFFFFF
verts(i)\X = mx
verts(i)\Y = my
verts(i)\Z = mz
verts(i)\texture_x = tx
verts(i)\texture_y = ty
verts(i)\vcolor = vc
Next
Restore PointToTriangle
For i=0 To (b*3)-1
Read p.l
indices(i) = p
Next
*schuss_mesh.irr_mesh = IrrCreateMesh( "TestMesh", a, @verts(0), b*3, @indices(0))
*SchussTexture.irr_texture = IrrGetTexture( Pfad.s )
DataSection
Objectdata:
;; Anzahl Punkte,Anzahl Dreiecke, Texture
Data.l 16,8
Data.s "fire.bmp"
ObjectPoint:
;; x,y,z,tex_x,tex_y,v_col
Data.f -1 , 0 , -1 , 0 , 0
Data.f -1 , 0 , 1 , 0 , 1
Data.f 1 , 0 , 1 , 1 , 1
Data.f 1 , 0 , -1 , 1 , 0
Data.f -0.7 , 0.7 , -1 , 0 , 0
Data.f -0.7 , 0.7 , 1 , 0 , 1
Data.f 0.7 , -0.7 , 1 , 1 , 1
Data.f 0.7 , -0.7 , -1 , 1 , 0
Data.f 0 , -1 , -1 , 0 , 0
Data.f 0 , -1 , 1 , 0 , 1
Data.f 0 , 1 , 1 , 1 , 1
Data.f 0 , 1 , -1 , 1 , 0
Data.f -0.7 , -0.7 , -1 , 0 , 0
Data.f -0.7 , -0.7 , 1 , 0 , 1
Data.f 0.7 , 0.7 , 1 , 1 , 1
Data.f 0.7 , 0.7 , -1 , 1 , 0
PointToTriangle:
;; p0,p1,p2 , rechts herum
Data.l 0,1,2
Data.l 2,3,0
Data.l 4,5,6
Data.l 6,7,4
Data.l 8,9,10
Data.l 10,11,8
Data.l 12,13,14
Data.l 14,15,12
EndDataSection
;--- Make Mesh 2
Restore ObjectData2
Read a.l
Read b.l
Read Pfad.s
Dim verts.IRR_VERT(a)
Dim indices.w(b*3)
Restore ObjectPoint2
For i=0 To a-1
Read mx.f
Read my.f
Read mz.f
Read tx.f
Read ty.f
vc.l = $00FFFFFF
verts(i)\X = mx
verts(i)\Y = my
verts(i)\Z = mz
verts(i)\texture_x = tx
verts(i)\texture_y = ty
verts(i)\vcolor = vc
Next
Restore PointToTriangle2
For i=0 To (b*3)-1
Read p.l
indices(i) = p
Next
*explosion_mesh.irr_mesh = IrrCreateMesh( "TestMesh", a, @verts(0), b*3, @indices(0))
*explosionTexture.irr_texture = IrrGetTexture( Pfad.s )
;--- Explosions Liste
NewList explosion_liste.NodeListe()
DataSection
Objectdata2:
;; Anzahl Punkte,Anzahl Dreiecke, Texture
Data.l 12,6
Data.s "spark.bmp"
ObjectPoint2:
;; x,y,z,tex_x,tex_y,v_col
Data.f -1 , 0 , -1 , 0 , 0
Data.f -1 , 0 , 1 , 0 , 1
Data.f 1 , 0 , 1 , 1 , 1
Data.f 1 , 0 , -1 , 1 , 0
Data.f -1 , -1 , 0 , 0 , 0
Data.f -1 , 1 , 0 , 0 , 1
Data.f 1 , 1 , 0 , 1 , 1
Data.f 1 , -1 , 0 , 1 , 0
Data.f 0 , -1 , -1 , 0 , 0
Data.f 0 , -1 , 1 , 0 , 1
Data.f 0 , 1 , 1 , 1 , 1
Data.f 0 , 1 , -1 , 1 , 0
PointToTriangle2:
;; p0,p1,p2 , rechts herum
Data.l 0,1,2
Data.l 2,3,0
Data.l 4,5,6
Data.l 6,7,4
Data.l 8,9,10
Data.l 10,11,8
EndDataSection
;---
Repeat
;--- Alpha für FPS berechnung
;
; Leider ist diese methode nicht genau genug. Aber für unsere Zwecke
; im Moment ausreichend. Benutz man diesen Alpha wert für Bewegung oder Rotation.
; wird man ein ruckeln feststellen. Das kommt von der ungenauigkeit. Es gibt
; unter Windows auch einen Besseren Timer. Den werden wir zu einem Späteren Zeitpunkt
; verwenden.
el.l=ElapsedMilliseconds()
If fpst.l<el.l
fpst.l=el.l+1000
fpsl.l=fps.l
fps.l=0
alpha.f=(1000/fpsl)
EndIf
fps.l=fps.l+1
;---
If IrrRunning()=0
en=1
EndIf
While IrrKeyEventAvailable()
*KeyEvent.irr_key_event = IrrReadKeyEvent()
Select *KeyEvent\key
Case #IRR_KEY_ESCAPE
en=1
Case #IRR_KEY_F12
ResetList(schuss_liste())
ForEach schuss_liste()
IrrRemoveAnimator(schuss_liste()\node,schuss_liste()\move_animator)
IrrRemoveAnimator(schuss_liste()\node,schuss_liste()\turn_animator)
IrrRemoveNode(schuss_liste()\node)
DeleteElement(schuss_liste())
Next
IrrStop()
Irr3DRequester(#IRR3DREQ_REQUESTER)
Goto neustart
EndSelect
Wend
LeftMouseBotonHit.l=0
RigtMouseBotonHit.l=0
WheelHit.l=0
While IrrMouseEventAvailable()
*MouseEvent.irr_mouse_event = IrrReadMouseEvent()
Select *MouseEvent\action
Case #IRR_EMIE_MOUSE_MOVED
MouseSpeedX.l=MouseX.l-*MouseEvent\X
MouseSpeedY.l=MouseY.l-*MouseEvent\Y
MouseX.l= *MouseEvent\X
MouseY.l= *MouseEvent\Y
Case #IRR_EMIE_MOUSE_WHEEL
;--- Mousrad
WheelHit.l=*MouseEvent\wheel
Case #IRR_EMIE_LMOUSE_PRESSED_DOWN
LeftMouseBotonDown.l=1
LeftMouseBotonHit.l=1
Case #IRR_EMIE_LMOUSE_LEFT_UP
LeftMouseBotonDown.l=0
Case #IRR_EMIE_RMOUSE_PRESSED_DOWN
RigtMouseBotonDown.l=1
RigtMouseBotonHit.l=1
Case #IRR_EMIE_RMOUSE_LEFT_UP
RigtMouseBotonDown.l=0
EndSelect
Wend
If LeftMouseBotonDown.l=1
If schuss_interval_timer.l<ElapsedMilliseconds()
schuss_interval_timer.l=ElapsedMilliseconds()+100
AddElement(schuss_liste())
schuss_liste()\node=IrrAddMeshToScene(*schuss_mesh)
schuss_liste()\visible=0
;--- Colisions Radius Schuss
schuss_liste()\ColRadius=0.05
IrrSetNodeMaterialFlag( schuss_liste()\node, #IRR_EMF_LIGHTING, #IRR_Off )
IrrSetNodeMaterialTexture( schuss_liste()\node, *CubeBlank, 0 )
IrrSetNodeMaterialFlag( schuss_liste()\node, #IRR_EMF_BACK_FACE_CULLING, #IRR_Off)
IrrSetNodeMaterialType( schuss_liste()\node, #IRR_EMT_TRANSPARENT_ADD_COLOR)
nx.f=((ScrX.l/2*-1)+MouseX)/600.0
ny.f=((ScrY.l/2)-MouseY)/600.0
IrrSetNodePosition(schuss_liste()\node,nx.f,ny.f,0)
schuss_liste()\Move_animator=IrrAddFlyStraightAnimator(schuss_liste()\node,nx.f,ny.f,0,nx.f,ny.f,30,5000,0)
schuss_liste()\Turn_animator=IrrAddRotationAnimator(schuss_liste()\node,0,0,10)
IrrSetNodeScale(schuss_liste()\node,0.1,0.1,0.3)
EndIf
EndIf
;--- Entfernung zum Cube
; hier kann mit dem Mouserad die entfernung zum rotierenden Cube
; geändert werden. Damit man die einschüsse und den Effect besser sehen kann.
If WheelHit.l<>0
IrrGetNodePosition(*CameraPivot,@x.f,@y.f,@z.f)
IrrSetNodePosition(*CameraPivot,x.f,y.f,z.f+(WheelHit.l/10.))
IrrGetNodePosition(*CameraPivot,@x.f,@y.f,@z.f)
IrrSetCameraTarget(*Camera,x.f,y.f,z.f+1)
EndIf
IrrBeginScene(0, 0, 55 )
IrrDrawScene()
;--- Draw Counter
Irr2DFontDraw ( *BitmapFont, " Treffer = "+Str(Counter.l), 4, 4, 0, 0 )
IrrEndScene()
Delay(1)
ResetList(schuss_liste())
ForEach schuss_liste()
IrrGetNodePosition(schuss_liste()\node,@sx.f,@sy.f,@sz.f)
If sz.f>20.0
IrrRemoveAnimator(schuss_liste()\node,schuss_liste()\move_animator)
IrrRemoveNode(schuss_liste()\node)
DeleteElement(schuss_liste())
Else
If schuss_liste()\visible=0
IrrSetNodeMaterialTexture( schuss_liste()\node, *SchussTexture, 0 )
IrrSetNodeMaterialType( schuss_liste()\node, #IRR_EMT_TRANSPARENT_ADD_COLOR)
schuss_liste()\visible=1
Else
;--- Colisions Berechnung
; Die Variablen sx und cx enthalten die actuellen Positionen von schuss
; und cube.
IrrGetNodePosition(cube_liste()\node,@cx.f,@cy.f,@cz.f)
; und nun etwas Mathe. Als erstes benötigen wir die Absolute entfernung
; in x/y/z ohne - !!! ABS() funktioniert nur mit Float Zahlen richtig !!!
ex.f=Abs(cx.f-sx.f)
ey.f=Abs(cy.f-sy.f)
ez.f=Abs(cz.f-sz.f)
; Wir werden dazu den Satzt des Pytagoras verwenden. Kennt jeder aus
; der Schule.
c1.f=Sqr((ex.f*ex.f)+Sqr((ey.f*ey.f)+(ez.f*ez.f)))-cube_liste()\ColRadius-schuss_liste()\ColRadius
; In c1 befindet sich nun die Entfernung zum Cube abzüglich der ColRadien
If c1.f<=0
; Wenn c1<= 0 dann ligt eine Colision vor
counter.l=counter.l+1
;--- Schuss Löschen
IrrRemoveAnimator(schuss_liste()\node,schuss_liste()\move_animator)
IrrRemoveNode(schuss_liste()\node)
DeleteElement(schuss_liste())
;--- Explosion einfügen
AddElement(explosion_liste())
;--- !!! Forsicht Falle 7 !!!
;
; Da zur koreckten anzeige einer Node nach dem Positionieren
; ein IrrDraw() nötig ist. Aber dieser teil erst nach IrrDraw() eingeleitet wird
; sowie die zwischen erzeugen und anzeigen kein IrrDrw() liegt. Muss der Counter
; visible auf -1 gestellt werden
explosion_liste()\visible=-1
explosion_liste()\node=IrrAddMeshToScene(*explosion_mesh)
IrrSetNodeScale(explosion_liste()\node,0.2,0.2,0.2)
IrrSetNodePosition(explosion_liste()\node,sx.f,sy.f,sz.f)
IrrSetNodeMaterialFlag( explosion_liste()\node, #IRR_EMF_LIGHTING, #IRR_Off )
IrrSetNodeMaterialTexture( explosion_liste()\node, *CubeBlank, 0 )
IrrSetNodeMaterialFlag( explosion_liste()\node, #IRR_EMF_BACK_FACE_CULLING, #IRR_On)
IrrSetNodeMaterialType( explosion_liste()\node, #IRR_EMT_TRANSPARENT_ADD_COLOR)
EndIf
;---
EndIf
EndIf
Next
;--- Explosions Anim und check
ResetList(explosion_liste())
ForEach explosion_liste()
If explosion_liste()\visible=0
IrrSetNodeMaterialTexture( explosion_liste()\node, *explosionTexture, 0 )
explosion_liste()\visible=1
ElseIf explosion_liste()\visible=-1
explosion_liste()\visible=0
ElseIf explosion_liste()\visible=1
IrrGetNodeScale(explosion_liste()\node,@x.f,@y.f,@z.f)
If x.f<0.01
IrrRemoveNode(explosion_liste()\node)
DeleteElement(explosion_liste())
Else
;--- FPS unabhängige Animation
anim.f=0.001*alpha.f
IrrSetNodeScale(explosion_liste()\node,x.f-anim.f,y.f-anim.f,z.f-anim.f)
EndIf
EndIf
Next
;---
If cube_liste()\visible=0
cube_liste()\visible=1
IrrSetNodeMaterialTexture( cube_liste()\node, *CubeTexture, 0 )
IrrSetNodeMaterialType( cube_liste()\node, #IRR_EMT_TRANSPARENT_ADD_COLOR)
EndIf
Until en=1
IrrStop()
End