Mehrere Gegner in einem Type

Übersicht BlitzBasic Beginners-Corner

Neue Antwort erstellen

N0X

Betreff: Mehrere Gegner in einem Type

BeitragSo, Jan 24, 2010 14:10
Antworten mit Zitat
Benutzer-Profile anzeigen
Hi!
Ich habe einen Type (enemy) der alle Gegnerarten etc. handelt.
Jetzt habe ich aber das Problem, dass sobald ich 2 verschiedene Gegnerarten erstelle, das Programm auf eine CPU-Auslastung von bis zu 50% gelangt. (Bei einem DualCore, mit 2x 3.0 GhZ)
Was kann da schief gelaufen sein?

Code: [AUSKLAPPEN]
;Variablen, Konstanten, Types etc.
Const PLY=1,MAP=2
Global cursor_frame,tmrSparks,roo,snowZeit,enemyTime
Global TrittZeit,fov#=90,zoom#=1

Type snow
   Field x#,y#,z#
   Field gfx
   Field AngleAdd#
End Type

Type enemy
   Field id$,picked
   Field x#,y#,z#
   Field yaw
   Field mesh
   Field timer,st_timer,richtung,stopp
   ;;;
   Field health%,exxp%
End Type

;----------------------------------------------------------------------------------------------|
;Haupt-Teil
Graphics3D 1024,768,32,2
SetBuffer BackBuffer()
timer = CreateTimer(60)

;----------------------------------------------------------------------------------------------|
;3D Ressourcen
Global piv    = CreatePivot()
Global cam    = CreateCamera(piv)
Global player = LoadAnimMesh("models\dwarf1.b3d")
Global map1   = LoadMesh("models\map001.3ds")

Global gegner = LoadAnimMesh("models\dwarf2.b3d")
Global horse  = LoadMesh("models\horse.3ds")

;----------------------------------------------------------------------------------------------|
;2D Ressourcen
Global cursor = LoadAnimImage("gfx\cursor.png",32,32,0,12):MaskImage(cursor,0,0,0)
Global sprite = LoadSprite("gfx\snow.png")

;----------------------------------------------------------------------------------------------|
;Sounds
Global laufe    = LoadSound("sfx\go1.wav")
Global enemyRun = LoadSound("sfx\go2.wav")

;----------------------------------------------------------------------------------------------|
;Einstellungen, Positionieren etc.
ScaleEntity(player,.2,.2,.2)
PositionEntity(player,0,2,-50)

ScaleEntity(gegner,.7,.7,.7)

ScaleEntity(horse,.2,.2,.2)

EntityType(player,PLY)
EntityType(map1,MAP)

ExtractAnimSeq(player,2,14)
ExtractAnimSeq(player,16,26)
ExtractAnimSeq(player,112,180)

ExtractAnimSeq(gegner,2,14)

;----------------------------------------------------------------------------------------------|
;Gegner
For i = 0 To 2
   e.enemy = New enemy
   e\x#    = Rnd(-1000,1000)
   e\y#    = 0
   e\z#    = Rnd(100,300)
   e\yaw   = Rnd(-90,90)
   e\mesh  = CopyEntity(gegner)
   e\exxp% = 120
   e\id$   = "Riese"
   EntityPickMode(e\mesh,2)
Next

For i = 0 To 2
   e.enemy = New enemy
   e\x#    = Rnd(-1000,1000)
   e\y#    = 0
   e\z#    = Rnd(100,300)
   e\yaw   = Rnd(-90,90)
   e\mesh  = CopyEntity(horse)
   e\exxp% = 50
   e\id$   = "Pferd"
   EntityPickMode(e\mesh,2)
Next

;----------------------------------------------------------------------------------------------|
;Haupt-Schleife
Collisions PLY,MAP,2,2
While Not KeyHit(1)
   WaitTimer(timer)
   Cls
   
   move()
   makeSnow()
   updateEnemys()
   initZoom(0.2)
   initPick()
   
   ;----------------------------------------------------------------------------------------------|
   RenderWorld()
      For e.enemy = Each enemy
         Text 10,140,"Picked: "+e\picked
         If e\picked = 1 Then
            Text 100,10,"Gegner: "+e\id$
         EndIf
      Next
   UpdateWorld()
   Flip 0
Wend
End
;----------------------------------------------------------------------------------------------|
Function move()
   TranslateEntity(player,0,-.1,0)
   PositionEntity piv,EntityX(player),EntityY(player),EntityZ(player)
   
   If EntityPitch(piv)=0 Then RotateEntity piv,0,EntityYaw(piv),EntityRoll(piv)
   If EntityPitch(piv)=80 Then RotateEntity piv,80,EntityYaw(piv),EntityRoll(piv)
   
   If KeyDown(16) Then
      RotateEntity piv,EntityPitch(piv),EntityYaw(piv)+2,0
   EndIf
   If KeyDown(18) Then
      RotateEntity piv,EntityPitch(piv),EntityYaw(piv)-2,0
   EndIf
   
   If KeyDown(17) Then
      RotateEntity player,0,EntityYaw(piv),0
      MoveEntity player,0,0,1
      If Not Animating(player)
         Animate(player,1,.3,1)
      EndIf
      If TrittZeit < MilliSecs() Then
         TrittZeit = MilliSecs() +310
         PlaySound(laufe)
      EndIf
   EndIf
   If KeyDown(31) Then
      RotateEntity player,0,EntityYaw(piv),0
      MoveEntity player,0,0,-1
      If Not Animating(player)
         Animate(player,1,-.3,1)
      EndIf
      If TrittZeit < MilliSecs() Then
         TrittZeit = MilliSecs() +310
         PlaySound(laufe)
      EndIf
   EndIf
   If KeyDown(30) Then
      MoveEntity player,-1,0,0
      If Not Animating(player)
         Animate(player,1,.3,1)
      EndIf
      If TrittZeit < MilliSecs() Then
         TrittZeit = MilliSecs() +310
         PlaySound(laufe)
      EndIf
   EndIf
   If KeyDown(32) Then
      MoveEntity player,1,0,0
      If Not Animating(player)
         Animate(player,1,.3,1)
      EndIf
      If TrittZeit < MilliSecs() Then
         TrittZeit = MilliSecs() +310
         PlaySound(laufe)
      EndIf
   EndIf
   
   If KeyDown(57) Then
      If Not Animating(player) Then
         Animate(player,1,.3,3)
      EndIf
   EndIf
   
   If Not (KeyDown(17) Or KeyDown(31) Or KeyDown(30) Or KeyDown(32) Or KeyDown(57)) Then
      Animate(player,0)
   EndIf
End Function

Function updateEnemys()
   For e.enemy = Each enemy
      PositionEntity e\mesh,e\x#,e\y#,e\z#
      RotateEntity e\mesh,0,e\yaw,0
      
      If e\timer < MilliSecs() Then
         e\timer = MilliSecs() +Rnd(6000,10000)
         e\richtung=Rnd(0,3)
         e\stopp=0
      EndIf
      If e\st_timer < MilliSecs() Then
         e\st_timer = MilliSecs() +Rnd(4000,8000)
         e\stopp = 1
      EndIf
      If e\stopp=0
         If e\richtung=0 Then
            e\x#=e\x#-.5
            If enemyTime < MilliSecs() Then
               enemyTime = MilliSecs() +840
               PlaySound(enemyRun)
            EndIf
            If e\id$ = "Riese" Then
               If Not Animating(e\mesh) Then
                  If EntityYaw(e\mesh)>=0 Then
                     Animate(e\mesh,1,.1,1)
                  EndIf
                  If EntityYaw(e\mesh)<=0 Then
                     Animate(e\mesh,1,-.1,1)
                  EndIf
               EndIf
            EndIf
         EndIf
         If e\richtung=1 Then
            e\z#=e\z#-.5
            If enemyTime < MilliSecs() Then
               enemyTime = MilliSecs() +840
               PlaySound(enemyRun)
            EndIf
            If e\id$ = "Riese" Then
               If Not Animating(e\mesh) Then
                  Animate(e\mesh,1,.1,1)
               EndIf
            EndIf
         EndIf
         If e\richtung=2 Then
            e\x#=e\x#+.5
            If enemyTime < MilliSecs() Then
               enemyTime = MilliSecs() +840
               PlaySound(enemyRun)
            EndIf
            If e\id$ = "Riese" Then
               If Not Animating(e\mesh) Then
                  Animate(e\mesh,1,.1,1)
               EndIf
            EndIf
         EndIf
         If e\richtung=3 Then
            e\z#=e\z#+.5
            If enemyTime < MilliSecs() Then
               enemyTime = MilliSecs() +840
               PlaySound(enemyRun)
            EndIf
            If e\id$ = "Riese" Then
               If Not Animating(e\mesh) Then
                  Animate(e\mesh,1,.1,1)
               EndIf
            EndIf
         EndIf
      Else
         If e\id$ = "Riese" Then
            Animate(e\mesh,0)
         EndIf
      EndIf
      
      If e\z#<=0.0 Then e\z#=0.0
   Next
End Function

Function initZoom(zoomSpeed#)
   mz=MouseZSpeed()
   If mz>0 Then
      zoom# = zoom#+zoomSpeed#
   EndIf
   If mz<0 Then
      zoom# = zoom#-zoomSpeed#
   EndIf
   If zoom#<=0.8 Then zoom#=0.8
   If zoom#>=5.0 Then zoom#=5.0
   
   CameraZoom(cam,zoom#)
End Function

Function makeSnow()
   Winkel1 = (Winkel1 + 3) Mod 360

   s.snow = New snow
   s\gfx  = CopyEntity(sprite)
   s\x#   = Rnd(0,600)
   s\y#   = 500
   s\z#   = Rnd(-500,500)
   s\AngleAdd# = Rnd(0,360)
   
   For s.snow = Each snow
      s\y# = s\y#-1
      PositionEntity s\gfx$,EntityX(piv)-((320 + Cos(Winkel1 + s\AngleAdd#) * 4)-s\x#),s\y#,EntityZ(piv)-s\z#;EntityX(piv)-s\x#,s\y#,EntityZ(piv)-s\z#
      If s\y# <= 0 Then
         FreeEntity s\gfx
         Delete s.snow
      EndIf
   Next
End Function

Function initPick()
   mh  = MouseHit(1)
   mxx = MouseX()
      myy = MouseY()
      entity = CameraPick(cam,mxx,myy)
      For e.enemy = Each enemy
      If mh Then
            If entity = e\mesh
            e\picked = 1
             EntityColor e\mesh,0,255,0
          Else
            e\picked = 0
            EntityColor e\mesh,255,255,255
          EndIf
      EndIf
   Next
End Function


Mfg,
N0X
Projekte: |Tibario| http://www.blitzforum.de/worklogs/325/ | 5%

Midimaster

BeitragSo, Jan 24, 2010 14:29
Antworten mit Zitat
Benutzer-Profile anzeigen
Du könntest, um festzustellen, wo die Performance runtergeht, einzelne Teile an- und abschalten. Ein Durchlauf darf etwa 16 msec dauern. Das kannst Du mit einer Variablen StoppZeit% messen. Nun machst du verschiedene Messungen und schaltest dabei immer einen Teil aus. Wenn Du Pech hast, dauert jeder Teil etwa 2msec, dann summiert sich das ganze halt auf 16. Wenn du Glück bei der Suche hast ist eine Aktion dabei die mehr als 10msec verbrät. Dann kannst Du dort mit Verbesserungen einsetzen.


Ausschalten kannst Du Funktionen durch auskommentieren: move() -> ;move.

Es gibt mehrere mögliche Quellen in deinem Code. Das CLS könnte unnötig sein, teste es einmal ohne. die Textausgabe Text 10,140,"Picked: "+e\picked würde ich zum Test auch mal kurz abschalten wollen. Der Schnee ist sicherlich rechenintensiv.

Wenn alles nix hilft, könntest Du den TIMER zur Not auf 30 stellen: timer = CreateTimer(30)



BlitzBasic: [AUSKLAPPEN]
While Not KeyHit(1)
WaitTimer(timer)
StoppZeit=MilliSecs()
Cls

move()
;---------versuche den Schnee abzuschalten--------------------------|

;makeSnow()
updateEnemys()
initZoom(0.2)
initPick()

;----------------------------------------------------------------------------------------------|
RenderWorld()
For e.enemy = Each enemy
Text 10,140,"Picked: "+e\picked
If e\picked = 1 Then
Text 100,10,"Gegner: "+e\id$
EndIf
Next
UpdateWorld()
DebugLog "Zeitverbrauch: " + (MilliSecs() - StopZeit)
Flip 0
Wend
End

N0X

BeitragSo, Jan 24, 2010 15:15
Antworten mit Zitat
Benutzer-Profile anzeigen
Gut, liegt hauptsächlich an der "updateEnemys()" Funktion.
Ich lasse die ja auch animieren, nur hat das 2.Modell keine Animation.
Deswegen auch die "If e\id$ = "Riese"" abfrage.
Hm, und ich lasse noch "EntityYaw" von den Modellen überprüfen, damit die Animation der Modelle dem entsprechend angepasst werden kann. (Rückwärts, Vorwärts)
Wie kann ich das alles beibehalten und die Performance trotzdem erhöhen?

Mfg,
N0X

Code: [AUSKLAPPEN]
Function updateEnemys()
   For e.enemy = Each enemy
      PositionEntity e\mesh,e\x#,e\y#,e\z#
      RotateEntity e\mesh,0,e\yaw,0
      
      If e\timer < MilliSecs() Then
         e\timer = MilliSecs() +Rnd(6000,10000)
         e\richtung=Rnd(0,3)
         e\stopp=0
      EndIf
      If e\st_timer < MilliSecs() Then
         e\st_timer = MilliSecs() +Rnd(4000,8000)
         e\stopp = 1
      EndIf
      If e\stopp=0
         If e\richtung=0 Then
            e\x#=e\x#-.5
            If enemyTime < MilliSecs() Then
               enemyTime = MilliSecs() +840
               PlaySound(enemyRun)
            EndIf
            If e\id$ = "Riese" Then
               If Not Animating(e\mesh) Then
                  If EntityYaw(e\mesh)>=0 Then
                     Animate(e\mesh,1,.1,1)
                  EndIf
                  If EntityYaw(e\mesh)<=0 Then
                     Animate(e\mesh,1,-.1,1)
                  EndIf
               EndIf
            EndIf
         EndIf
         If e\richtung=1 Then
            e\z#=e\z#-.5
            If enemyTime < MilliSecs() Then
               enemyTime = MilliSecs() +840
               PlaySound(enemyRun)
            EndIf
            If e\id$ = "Riese" Then
               If Not Animating(e\mesh) Then
                  Animate(e\mesh,1,.1,1)
               EndIf
            EndIf
         EndIf
         If e\richtung=2 Then
            e\x#=e\x#+.5
            If enemyTime < MilliSecs() Then
               enemyTime = MilliSecs() +840
               PlaySound(enemyRun)
            EndIf
            If e\id$ = "Riese" Then
               If Not Animating(e\mesh) Then
                  Animate(e\mesh,1,.1,1)
               EndIf
            EndIf
         EndIf
         If e\richtung=3 Then
            e\z#=e\z#+.5
            If enemyTime < MilliSecs() Then
               enemyTime = MilliSecs() +840
               PlaySound(enemyRun)
            EndIf
            If e\id$ = "Riese" Then
               If Not Animating(e\mesh) Then
                  Animate(e\mesh,1,.1,1)
               EndIf
            EndIf
         EndIf
      Else
         If e\id$ = "Riese" Then
            Animate(e\mesh,0)
         EndIf
      EndIf
      
      If e\z#<=0.0 Then e\z#=0.0
   Next
End Function
Projekte: |Tibario| http://www.blitzforum.de/worklogs/325/ | 5%

Xeres

Moderator

BeitragSo, Jan 24, 2010 15:48
Antworten mit Zitat
Benutzer-Profile anzeigen
Du rufst sehr oft Millisecs() auf - Funktionen, deren werte du Oft benutzt, kannst du in Variablen zwischenspeichern. Einmal ms = Millisecs() in der Hauptschleife könnte vielleicht helfen.
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)

Midimaster

BeitragSo, Jan 24, 2010 16:25
Antworten mit Zitat
Benutzer-Profile anzeigen
nox
was heißt denn "hauptsächlich"? Wieviele msec zeigt Dir die Hauptschleife an, wenn alles läuft und wieviele, wenn du UpdateEnemys() ausschaltest? Bitte Zahlen liefern...

Und um wieviele (gleichzeitig sichtbare) Gegner handelt es sich durchschnittlich?

N0X

BeitragSo, Jan 24, 2010 17:13
Antworten mit Zitat
Benutzer-Profile anzeigen
Also:
Ohne makeSnow(), ca. Code: [AUSKLAPPEN]
25-30
(mit ungefähr 15 sichtbaren Gegnern), 1 (mit keinen angezeigten Gegnern)
Ohne makeSnow() und initPick(), max. Code: [AUSKLAPPEN]
10


Also ist da irgendwas schlecht in der initPick-Funktion.

//EDIT:
Ich habe die initPick()-Funktion nochmal ein bisschen verändert, aber an den 30 MilliSecs() hat sich nix verändert. Sad

Hier nochmal die Funktion:
Code: [AUSKLAPPEN]
Function initPick()
   mh  = MouseHit(1)
   mxx = MouseX()
      myy = MouseY()
      entity = CameraPick(cam,mxx,myy)
      For e.enemy = Each enemy
         If entity = e\mesh
         e\picked = 1
       Else
         e\picked = 0
       EndIf
   Next
End Function


//EDIT2:
Je mehr Pferde ich erstelle (2.Gegnerart), desto mehr geht das Programm auf Lasten der CPU. Vielleicht liegt es an dem Modell?

Also das Pferdemodell hat Code: [AUSKLAPPEN]
32.190 Poly's
.
Ich weiß nicht ob das viel ist. (?!) Confused
Projekte: |Tibario| http://www.blitzforum.de/worklogs/325/ | 5%
 

mDave

BeitragSo, Jan 24, 2010 18:46
Antworten mit Zitat
Benutzer-Profile anzeigen
Sehr viel.

Nicdel

BeitragSo, Jan 24, 2010 19:08
Antworten mit Zitat
Benutzer-Profile anzeigen
Viel zu viel. Höchstens 1000 Polys, sonst läufts später gar nicht mehr.
Desktop: Intel Pentium 4 2650 Mhz, 2 GB RAM, ATI Radeon HD 3850 512 MB, Windows XP
Notebook: Intel Core i7 720 QM 1.6 Ghz, 4 GB DDR3 RAM, nVidia 230M GT, Windows 7

Midimaster

BeitragSo, Jan 24, 2010 19:17
Antworten mit Zitat
Benutzer-Profile anzeigen
für die InitPick() gibt es diese Lösung, um weniger Performance zu verbrauchen:

Es ist ja anzunehmen, dass das Ergebnis, welches Pferd aktuell gepickt ist, sich nicht 60x pro Sekunde ändert. Deshalb:

1. Rufe diese Funktion schon bloss 10x pro Sekunde auf.


2. Viel wichtiger: Merke Dir in LastPick% welche Entity zuletzt gepickt war und reagiere nicht mit dem Einfärben, wenn es wieder die gleiche Entity ist.


Beispielcode symbolisch:

BlitzBasic: [AUSKLAPPEN]

; zwei neue Variable, die das Aufrufen der InitPick() auf ein Minimun reduzieren sollen.
Global PickZeit%, LastEntity%


Function initPick()
If PickZeit < MilliSecs() Then
; nur noch aufrufen, wenm 100msec vergangen sind
PickZeit=MilliSecs()+100

If MouseHit(1) Then
;ob "gedrückte Maus" frühzeitiger abfragen

mxx = MouseX()
myy = MouseY()
Entity = CameraPick(cam,mxx,myy)
If (Entity <> LastPick ) And (Entity > 0 ) Then
; nur noch aufrufen, wenn Maus auf was zeigt und das auch nicht das gleiche wie beim letzten Mal war

If LastEntity>0 Then
; altes Entity Entfärben
EntityColor LastEntity,255,255,255
EndIf
For e.enemy = Each enemy
If entity = e\mesh
EntityColor e\mesh,0,255,0
LastEntity=Entity
; merken, welches Entity gerade grün wurde und gleich raus
Return
EndIf
Next
ElseIf LastEntity > 0 Then
; wenn Maus nirgndwohin zeigt, Entity wieder entfärben
EntityColor LastEntity,255,255,255
LastEntity = 0
EndIf
EndIf
End Function
  • Zuletzt bearbeitet von Midimaster am So, Jan 24, 2010 23:39, insgesamt einmal bearbeitet

N0X

BeitragSo, Jan 24, 2010 19:22
Antworten mit Zitat
Benutzer-Profile anzeigen
Ok, danke, es lag wirklich nur an den blöden Pferden ^^
Ich habe mir einfach mal selbst ein Modell erstellt. (Mit 93 Poly's, aber kein Pferd ^^)
Jetzt läuft's super! Smile

Mfg,
N0X

//EDIT:
Gute Idee, Midimaster!
Aber irgendwas funktioniert da nicht ganz richtig. Confused Besser gesagt, bei mir färbt sich nix.
Projekte: |Tibario| http://www.blitzforum.de/worklogs/325/ | 5%

Midimaster

BeitragSo, Jan 24, 2010 23:49
Antworten mit Zitat
Benutzer-Profile anzeigen
Also, den Code, den ich dir geschrieben hatte, lief nicht fehlerfrei, er sollte dir nur einen neuen Weg aufzeigen. War also mehr als Pseudocode gedacht.

Jetzt hab ich ihn dir verbessert, vielleicht läuft er jetzt ja...außerdem ist er jetzt kommentiert. Das könnte Dir auch als Vorlage für ähnliche Performance-Probleme dienen. Strategie: Befehle, die wenig Rechenzeit benötigen nach vorne verlegen. Bei dir : MouseHit(), Außerdem musst du ja nicht immer wieder herausfinden, welches Pferd zur Zeit gefärbt ist, merk es dir einfach und benutze diese Information im Bedarfsfall.

Auch wichtig: Funktionen mittels RETURN sofort abbrechen, wenn bereits alles gefunden/erledigt wurde.

Deine Lösung Pferde raus ist ja wohl nicht der Hipp. Mein Tipp: Polygone von 32.000 auf 1000-3000 reduzieren. Dann sieht das Pferd noch nach Pferd aus und es läuft schon ziemlich flott. 20msec->2msec

Neue Antwort erstellen


Übersicht BlitzBasic Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group