Problem mit Erzeugung mehrerer Entities

Übersicht BlitzBasic Allgemein

Neue Antwort erstellen

 

ZaRaK

Betreff: Problem mit Erzeugung mehrerer Entities

BeitragMo, Okt 24, 2011 10:28
Antworten mit Zitat
Benutzer-Profile anzeigen
Hi,
ich möchte ein kleines Weltraumspiel schreiben, in dem es darum geht Raumschiffe zu bauen und Planeten zu erobern.

Mein Problem ist, dass ich aktuell jeden Planeten einzeln erstelle und anspreche,
was ggfl. später bei größeren Karten mit mehr Planeten umständlich werden könnte.
Kann ich per Schleife irgendwie eine gewisse Anzahl von Planeten erzeugen die auch separat ansprechbar sind?

Und was mir auch aufgefallen ist, nach mehrmaligem hin und her schicken der Raumschiffe, bleibt das Programm stehen, woran kann das liegen?

Linksklick auf ersten Planeten = Planet auswählen
Rechtsklick auf zweiten Planeten = Raumschiffe entsenden

Schonmal vielen Dank im voraus!

Code: [AUSKLAPPEN]
Graphics3D 800,600

SetBuffer BackBuffer()
Global auswahl=0,klick=0,flotte=0,kollision=False

cam=CreateCamera()
CameraViewport cam,0,0,800,600

;licht, start, ziel, schiffe
light=CreateLight()
start=CreateCube()
ScaleMesh start,.01,.01,.01
ziel=CreateCube()
ScaleMesh ziel,.01,.01,.01
schiffe=CreateCone()
RotateMesh schiffe,90,0,0
ScaleEntity schiffe,.2,.2,.2

;planeten
planet1=CreateSphere()
PositionEntity planet1,-5,0,10
EntityPickMode planet1,2

planet2=CreateSphere()
PositionEntity planet2,5,0,10
EntityPickMode planet2,2

;baumenü
Global menu=CreateSprite()
RotateEntity menu,0,0,90




While Not KeyHit(1)

TurnEntity planet1,.1,.2,.3
TurnEntity planet2,.1,.1,.1

If MouseHit(1) Then klick=1 CameraPick(cam,MouseX(),MouseY())
If MouseHit(2) Then klick=2 CameraPick(cam,MouseX(),MouseY())


;planet 1 auswählen
If Not flotte=1
   If auswahl=0 And klick=1
      If PickedEntity()
         Baumenue()
         PositionEntity start, PickedX(),PickedY(),PickedZ()+.1
         EntityColor PickedEntity(),255,0,0
         auswahl=1
      EndIf
   EndIf
EndIf

;planet 2 auswhählen
If auswahl=1 And klick=2
   If PickedEntity()
      PositionEntity ziel, PickedX(),PickedY(),PickedZ()+.1
      PositionEntity schiffe,EntityX(start),EntityY(start),EntityZ(start)
      EntityColor PickedEntity(),0,255,0
      ShowEntity schiffe
      auswahl=0
      klick=0
      EntityColor PickedEntity(),0,255,0
      flotte=1
   EndIf
EndIf

;flotte schicken
If flotte=1   
   If kollision=False
      vx#=EntityX(ziel)-EntityX(schiffe)
      vy#=EntityY(ziel)-EntityY(schiffe)
      vz#=EntityZ(ziel)-EntityZ(schiffe)
      AlignToVector(schiffe,vx#,vy#,vz#,3,1)      
      MoveEntity schiffe,0.0,0.0,0.04
      
      ;flotte erreicht ziel
      If EntityDistance(ziel,schiffe)<0.1
         kollision=True
         flotte=0
         HideEntity schiffe
      EndIf   
   EndIf
   kollision=False
EndIf


UpdateWorld
RenderWorld
Text 0,0,"klick: "+klick
Text 0,15,"auswahl: "+auswahl
Text 0,30,"vx: "+vx#
Text 0,45,"vy: "+vy#
Text 0,60,"flotte: "+flotte
Text 0,75,"menü x: "+EntityX(menu)
Text 0,90,"menü y: "+EntityY(menu)
Flip
Wend
End



Function Baumenue()
   PositionEntity menu,EntityX(PickedEntity()),EntityY(PickedEntity())+1.5,EntityZ(PickedEntity())
   ScaleSprite menu,1,.5
End Function

ToeB

BeitragMo, Okt 24, 2011 10:42
Antworten mit Zitat
Benutzer-Profile anzeigen
Da helfen Types!

Einfach die Planeten unter einem Type zusammen fassen, dort die benötigten Variablen (Field) reinschreiben (bspw. für das Planeten Mesh).

Am besten suchst du dir da mal Tutorials zu raus!

mfg ToeB
Religiöse Kriege sind Streitigkeiten erwachsener Männer darum, wer den besten imaginären Freund hat.
Race-Project - Das Rennspiel der etwas anderen Art
SimpleUDP3.0 - Neuste Version der Netzwerk-Bibliothek
Vielen Dank an dieser Stelle nochmal an Pummelie, welcher mir einen Teil seines VServers für das Betreiben meines Masterservers zur verfügung stellt!
 

ZaRaK

BeitragMo, Okt 24, 2011 11:21
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich hab das ganze jetzt mal so versucht, allerdings werden keine Spheres erzeugt.
Woran kann das liegen?

Meiner logik nach habe ich dem Type planet die leeren werte px,py und pz gegeben.
Diese werden in der For schleife mit werten gefüllt, also Koordinaten zugewiesen und
in der Function anschließend an den entsprechenden Koordinaten erstellt.

Was hab ich hierbei nicht begriffen?


Type liegt ganz oben im Code.
Die For Schleife vor While not Keyhit(1).
Die Function am Ende des Codes.
Die Function Planeten() wird nach While not Keyhit(1) aufgerufen.

Code: [AUSKLAPPEN]
Type planet
   Field px#
   Field py#
   Field pz#
End Type


For i=0 To 2
   p.planet=New planet
   p\px#=Rnd(10)
   p\py#=Rnd(10)
   p\pz#=10
Next


Function Planeten()
   For p.planet=Each planet
      CreateSphere()
   Next
End Function
 

PhillipK

BeitragMo, Okt 24, 2011 11:23
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich hab leider nicht viel ahnung von BB, aber was ich so lese ist das schon richtig.

Allerdings: Die Sphere solltest du direkt als Field mit ins Type setzen. Ausserdem fehlt eine positionierung - werden sie vielleicht erzeugt und landen alle an 0,0,0 ?
 

ZaRaK

BeitragMo, Okt 24, 2011 11:40
Antworten mit Zitat
Benutzer-Profile anzeigen
Die Sphere direkt als Field zu deklarieren geht, glaube ich, nicht.
Zumindest wüsste ich nicht, wie ich dieses Field dann abrufen könnte.

Die Positionierung, also die Koordinaten, werden in der For Schleife mir Rnd(10) deklariert (wenn ich das so richtig verstanden habe).
Jede Sphere müsste/sollte auf der X und Y Achse also irgendwo zwischen 0 und 10 liegen.

Die Kamera liegt über 0,0.
Würden die Spheres dort landen, würde ich das sehen, daran kann es also nicht liegen.
Die Koordinaten lasse ich mir auch als Text anzeigen, welche aber unverändert bei 0 stehen.
 

mDave

BeitragMo, Okt 24, 2011 12:02
Antworten mit Zitat
Benutzer-Profile anzeigen
Tag,
Du müsstest die Spheren ja dann erstmal irgendwo positionieren, im Moment befinden sie sich an der Position 0,0,0 ;kein Wunder, dass Du sie nicht sehen kannst.

Der Spaß könnte so aussehen:
Code: [AUSKLAPPEN]
Type planet
   Field px#
   Field py#
   Field pz#
   Field mesh%
End Type


For i=0 To 2
   p.planet=New planet
   p\px#=Rnd(10)
   p\py#=Rnd(10)
   p\pz#=10
   p\mesh%=CreateSphere()
   PositionEntity p\mesh%,p\px#,p\py#,p\pz#
Next


Die Funktion Planeten() solltest du übrigens nicht in der Hauptschleife lassen, denn so werden ständig weitere Spheres gemacht und das Programm wird somit nach einiger Zeit immer langsamer.
 

PhillipK

BeitragMo, Okt 24, 2011 12:03
Antworten mit Zitat
Benutzer-Profile anzeigen
Nunjut, da muss jemand drübergucken ,der mehr ahnung von Types unter BB hat.

Warum es allerdings nicht gehen soll, eine sphere als field abzulegen, ist mir schleierhaft.

BlitzBasic: [AUSKLAPPEN]
Type planet
Field px#
Field py#
Field pz#
Field mesh%
End Type


For i=0 To 2 ;schleife von 0 bis 2.
p.planet=New planet ;neues Objekt erschafftn
p\px#=Rnd(10) ;koordinaten zufällig setzen
p\py#=Rnd(10)
p\pz#=10
p\mesh = CreateSphere() ;mesh erstellen

PositionEntity(p\mesh, p\px,p\py,p\pz,1) ;mesh an die zufalls-position setzen.
Next


Wie gesagt, ich weiß nur ein bisschen was über Types in bb, durch andere quellcodes. Selbst habe ich nie welche benutzt (bin vorher auf blitzmax umgestiegen Smile )
Aber so oder so ähnlich sollte es funktionieren.

EDIT:
Loool Very Happy
Da war ich wohl n tucken zu langsam. Aber das ich dann noch einen fast identischen code daraus forme, wie mDave das getan hat, lässt mich laut lachen^^
 

ZaRaK

BeitragMo, Okt 24, 2011 12:38
Antworten mit Zitat
Benutzer-Profile anzeigen
Ach so geht das.
Vielen Dank! Very Happy
Jetz klappt es wunderbar.

Mein Denkfehler war wohl der, dass ich dachte, man könne die Sphere nur in der Function erzeugen.
 

PhillipK

BeitragMo, Okt 24, 2011 12:42
Antworten mit Zitat
Benutzer-Profile anzeigen
Erzeugen geht immer.

Grade für viele planeten ist es allerdings wichtig, das du dir das Mesh hälst.
Ein "Mesh" unter BB wird, wie vieles andere auch, als integer (bzw integer-pointer?) übergeben. DH mit dem field mesh% kannst du dir das Mesh "greifbar" halten.

Das wird grade dann wichtig, wenn du Kollisionen genauer unter die Lupe nehmen möchtest, oder auch zb einen Mond um einen Planten kreisen lassen willst.

Dann mal viel glück beim einbauen =)
 

ZaRaK

BeitragMo, Okt 24, 2011 13:25
Antworten mit Zitat
Benutzer-Profile anzeigen
Soweit funktioniet alles Smile
Danke nochmal für die Hilfe!

Kamerasteuerung mit WASD
Zoomen mit Mausrad
Linksklick = Startplanet wählen
Rechtsklick = Zielplanet wählen

Falls ihr es euch nochmal ansehen wollt, hier der Code:

Code: [AUSKLAPPEN]
Type planet
   Field px#
   Field py#
   Field pz#
   Field mesh%
End Type

Graphics3D 800,600

SetBuffer BackBuffer()
Global auswahl=0,klick=0,flotte=0,kollision=False,zoomen=0,zentrum#=50,anzahl=10

cam=CreateCamera()
CameraViewport cam,0,0,800,600
PositionEntity cam,zentrum#/2,zentrum#/2,-10

;licht, start, ziel, schiffe
light=CreateLight()
start=CreateCube()
ScaleMesh start,.01,.01,.01
PositionEntity start,0,0,-25
ziel=CreateCube()
ScaleMesh ziel,.01,.01,.01
PositionEntity ziel,0,0,-25
schiffe=CreateCone()
RotateMesh schiffe,90,0,0
PositionEntity schiffe,0,0,-25
ScaleEntity schiffe,.2,.2,.2

;baumenü
Global menu=CreateSprite()
RotateEntity menu,0,0,90
PositionEntity menu,0,0,-25


For i=1 To anzahl
   p.planet=New planet
   p\px#=Rnd(zentrum#)
   p\py#=Rnd(zentrum#)
   p\pz#=10
   p\mesh%=CreateSphere()
   PositionEntity p\mesh%,p\px#,p\py#,p\pz#
   EntityPickMode p\mesh%,2
Next



While Not KeyHit(1)


;kamera, wasd
If KeyDown(17) Then MoveEntity cam,0,.1*-(EntityZ(cam)/10),0
If KeyDown(31) Then MoveEntity cam,0,-.1*-(EntityZ(cam)/10),0
If KeyDown(32) Then MoveEntity cam,.1*-(EntityZ(cam)/10),0,0
If KeyDown(30) Then MoveEntity cam,-.1*-(EntityZ(cam)/10),0,0


;kamera, zoom
mausrad=MouseZSpeed()
If mausrad<>0 Then MoveEntity(cam,0,0,mausrad*2)

If EntityZ(cam)<=-30
   PositionEntity cam,EntityX(cam),EntityY(cam),-30
EndIf
If EntityZ(cam)>=-2
   PositionEntity cam,EntityX(cam),EntityY(cam),-2
EndIf


;klicken
If MouseHit(1) Then klick=1 CameraPick(cam,MouseX(),MouseY())
If MouseHit(2) Then klick=2 CameraPick(cam,MouseX(),MouseY())


;planet START auswählen
If Not flotte=1
   If auswahl=0 And klick=1
      If PickedEntity()
         Baumenue()
         PositionEntity start, PickedX(),PickedY(),PickedZ()+.1
         EntityColor PickedEntity(),255,0,0
         auswahl=1
      EndIf
   EndIf
EndIf

;planet ZIEL auswhählen
If auswahl=1 And klick=2
   If PickedEntity()
      PositionEntity ziel, PickedX(),PickedY(),PickedZ()+.1
      PositionEntity schiffe,EntityX(start),EntityY(start),EntityZ(start)
      EntityColor PickedEntity(),0,255,0
      ShowEntity schiffe
      auswahl=0
      klick=0
      EntityColor PickedEntity(),0,255,0
      flotte=1
   EndIf
EndIf

;flotte schicken
If flotte=1   
   If kollision=False
      vx#=EntityX(ziel)-EntityX(schiffe)
      vy#=EntityY(ziel)-EntityY(schiffe)
      vz#=EntityZ(ziel)-EntityZ(schiffe)
      AlignToVector(schiffe,vx#,vy#,vz#,3,1)      
      MoveEntity schiffe,0.0,0.0,0.04
      
      ;flotte erreicht ziel
      If EntityDistance(ziel,schiffe)<0.1
         kollision=True
         flotte=0
         HideEntity schiffe
      EndIf   
   EndIf
   kollision=False
EndIf


UpdateWorld
RenderWorld
Text 0,0,"klick: "+klick
Text 0,15,"auswahl: "+auswahl
Text 0,30,"vx: "+vx#
Text 0,45,"vy: "+vy#
Text 0,60,"flotte: "+flotte
Text 0,75,"menü x: "+EntityX(menu)
Text 0,90,"menü y: "+EntityY(menu)
Text 0,105,"cam x: "+EntityX(cam)
Text 0,120,"cam y: "+EntityY(cam)
Text 0,135,"cam z: "+EntityZ(cam)
Flip
Wend
End



Function Baumenue()
   PositionEntity menu,EntityX(PickedEntity()),EntityY(PickedEntity())+1.5,EntityZ(PickedEntity())
   ScaleSprite menu,1,.5
End Function

skey-z

BeitragMo, Okt 24, 2011 14:53
Antworten mit Zitat
Benutzer-Profile anzeigen
Was mir noch aufgefallen ist, du speicherst eigentlich nur Mausrad in einer Variablen,
das gleiche solltest du auch mit allen Tasten und Maustasten machen, die du benötigst.

if mousehit(1) Then klick=1
if mousehit(2) then klick=2

funktioniert zwar auch und geht schon in die richtige Richtung, aber du musst dann auch in jedem Schleifendurchlauf klick wieder auf 0 setzen.
Hier ist es einfacher:

md1 = mousehit(1)
md2 = mousehit(2)

zu schreiben, und dann nicht auf 'if klick=zahl', sondern einfach nur auf 'if md1 then' bzw 'if md2 then' zu prüfen.

genauso bei MouseX() und Mousey().

Spätestens wenn du ein zweites mal die Funktion Mousehit(1) aufrufst und diese im gleichen Schleifendurchlauf schon geprüft wurde, wird ein falsches Ergebnis geliefert, da der Puffer bei jedem Aufruf geleert wird.

Bei MouseX() und MouseY() ist es auch schneller, da die Funktion nur einmal aufgerufen werden muss und dann dauerhaft in einem Schleifendurchlauf zur Verfügung steht, als wenn du jedes mal die Funktion an sich aufrufst.

OK, zugegeben ist es jetzt vielleicht nicht so einfach beschrieben, aber ich muss leider gleich wieder zur Arbeit, schaue dir einfach mal ein paar Tutorials oder Codes hier im Forum an, da siehst du nochmal in praktischen Beispielen, wie man es umsetzen kann.
Awards:
Coffee's Monatswettbewerb Feb. 08: 1. Platz
BAC#57: 2. Platz
Twitter
 

PhillipK

BeitragMo, Okt 24, 2011 15:52
Antworten mit Zitat
Benutzer-Profile anzeigen
Dann greife ich Ske-Z's intention einmal auf und beschreibe es etwas ausführlicher.

Grundsätzlich sollte man sich benötigte tastenabfragen etc speichern. Dh, einmal am anfang des Mainloops jede Taste / Maustaste / Position abfragen, die du auf jedenfall einmal oder mehrmals im Hauptprogramm (pro schleifendurchlauf//frame) brauchst.

BlitzBasic: [AUSKLAPPEN]
Global LMB%
Global RMB%
Global LMD%
Global RMD%
Global mX%
Global mY%

While 1
Cls

; Hilfsvariablen
lmb = MouseHit(1)
rmb = MouseHit(2)
lmd = MouseDown(1)
rmd = MouseDown(2)
mx = MouseX()
my = MouseY()

;"Hauptprogramm" - WARNUNG: Totaler schrott. soll nur die "einfachheit" der abfragen demonstrieren.
If lmd Then Line mx,my,mx+20,my+20
If rmd Then Line mx-20, my, mx, my


;noch ein bisschen code, keine ahnugn was da so passieren könnte :D
If Not lmb Then Text 5,5, "Hallo Welt!"
If rmb Then Text 5, 20, "Rechte mausetaste wurde gedrückt.

If mx < 40 And my < 40 And rmb Then Exit

Flip 1
Wend


Zugegeben, das beispiel ist schrott.
Aber: Jeder aufruf von MouseDown() etc ist ein sprung den dein Programm macht. Es ist zwar nicht merklich, wenn du es 2-3x aufrufst, aber dennoch ist es ebenso schöner mit variablen zu arbeiten, als auch sicherer.

Ske-Z hats richtig gesagt - mehrmaliges aufrufen von MouseHit() etc wird immer null zurückliefern.
Es kann ärgerlich sein, wenn man eine neue Funktion testen möchte und diese aus schier unerfindlichem grunde nicht geht - dabei liegt es nur daran, das die abfrage nicht funktioniert hat.

PS: Für faule -> aussagekräftige, aber kurze variablennamen sind weniger schreibarbeit Wink
LMB = Left Mouse Button (hit - abfrage)
LMD = Left Mouse Button Down (down - abfrage)

mX = Mouse X

verständlich, aber kürzer wie jedesmal die funktionsnamen zu schreiben Smile Smile

Neue Antwort erstellen


Übersicht BlitzBasic Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group