Sprites

Übersicht BlitzBasic Beginners-Corner

Neue Antwort erstellen

N0X

Betreff: Sprites

BeitragFr, Jan 22, 2010 14:27
Antworten mit Zitat
Benutzer-Profile anzeigen
Hi!
Ich möchte Sprites vom Bildschirm herunterfallen lassen. (Schnee)
Wie mache ich das?

Hier mal mein Ansatz:
Code: [AUSKLAPPEN]
   If snowZeit < MilliSecs() Then
      snowZeit = MilliSecs() +310
      s.snow = New snow
      s\gfx$ = LoadSprite("gfx\snow.png")
      s\x#   = Rnd(0,GraphicsWidth())
   EndIf
   PositionEntity s\gfx$,EntityX(piv),s\y#,EntityZ(cam)


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

Midimaster

BeitragFr, Jan 22, 2010 14:47
Antworten mit Zitat
Benutzer-Profile anzeigen
Also die optimale Reihenfolge wäre:

1.
SchneeflockeBild nur 1x laden
FlockenBild%=LoadImage("...

2.
Eine ganze Menge (zum Test mal 100) Schneeflocken-Typ-Elemente erzeugen, aber nicht das Bild selbst mit reinnehmen, sondern nur den Pointer Bild%, Das Veteilen über Rand() auch in der Y-Achse machen aber die Werte -600 bis 0 nehmen. Kein Timer nötig!

SchneeFlocke\Bild% = FlockenBild

3. Animation in der Repeat/Until-Schleife
Für alle 100 Objekte die Entitiy bewegen, Welt neu zeichnen, Objekte die unten angekommen sind gleich wieder oben reinstellen.

Noobody

BeitragFr, Jan 22, 2010 15:05
Antworten mit Zitat
Benutzer-Profile anzeigen
Zuerst mal würde ich S\Gfx als Integer angeben und nicht als String (einfach das $ wegmachen, dann ist es automatisch Int), da LoadSprite ja eine Zahl zurückgibt und keinen Text. In Blitz ist das zwar nicht direkt falsch, aber es ist leicht verwirrend, wenn bei PositionEntity plötzlich ein String angegeben wird Razz

Bei deinem Problem kommt es nun ganz drauf an, wie du deinen Schnee haben willst. Falls er auf dem Bildschirm von oben nach unten rieseln soll, hängst du die Sprites am besten mit einem Pivot an die Kamera und stellst es per EntityOrder so ein, das die Sprites als letztes gerendert werden sollen (dann werden sie nicht von der Landschaft verdeckt). In der Hauptschleife bewegst du die Sprites dann einfach langsam nach unten und leicht nach links oder nach rechts (dafür ist MoveEntity geeignet; für die links-rechts-Bewegung nimmst du am besten Sin oder Cos). Sobald sie am unteren Bildschirmrand sind, setzt du sie wieder nach oben.

Falls du die Schneeflocken aber frei in der Landschaft schwebend haben willst, wird es ein wenig komplizierter. Da musst du die 3D-Koordinaten zufällig setzen und die Scheeflocke dann ebenfalls in der Hauptschleife nach unten bewegen; für die X- und Z-Achse wäre dann eine Kombination aus Sin und Cos hübsch. Sobald die Schneeflocke unter dem Gelände ist (bei einem Terrain überprüfst du das mit TerrainY, bei einem Mesh mit LinePick und PickedY), setzt du sie wieder irgendwo über die Kamera.

Du wirst aber bald feststellen, dass Sprites in B3D sehr, sehr langsam sind. Ohne ein Single-Surface-System wird ein ahnsehnliches Schneegestöber kaum möglich sein; im Forum gab es dieses Thema schon einige Male, vielleicht findest du dort etwas brauchbares.
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun

N0X

BeitragFr, Jan 22, 2010 15:06
Antworten mit Zitat
Benutzer-Profile anzeigen
Ok, wenn ich das Bild aber nur 1x lade, und dann eben unten "SchneeFlocke\Bild% = sprite%" schreibe, dann flackert der Schnee nur ab und zu auf. Normal? Surprised
Projekte: |Tibario| http://www.blitzforum.de/worklogs/325/ | 5%

Noobody

BeitragFr, Jan 22, 2010 15:12
Antworten mit Zitat
Benutzer-Profile anzeigen
Ja, weil man ein Sprite nur für eine einzelne Schneeflocke verwenden kann. Anders als in 2D, wo ein Bild mehrfach an verschiedenen Positionen gezeichnet werden kann, geht das bei Entities nicht. Jedes Entity hat nur eine Position und wird nur an dieser gezeichnet; will man dasselbe Objekt mehrfach zeichnen lassen, so muss man das ursprüngliche Objekt entweder neu laden oder per CopyEntity kopieren (und jede einzelne Kopie dann an den gewünschten Positionen hinstellen, versteht sich).

Daher musst du für jede Schneeflocke das Sprite neu laden. Ich bin mir nicht sicher, ob CopyEntity mit Sprites funktioniert, das könntest du mal ausprobieren. Das Sprite also nur einmal laden, aber dieses dafür für jede neue Schneeflocke kopieren (schont den Speicher).
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun

N0X

BeitragFr, Jan 22, 2010 15:44
Antworten mit Zitat
Benutzer-Profile anzeigen
So!
Ich habe alles versucht umzusetzen, allerdings weiß ich nicht wie das geht das jede einzelne Schneeflocke unabhängig von jeglichen anderen mit Cos bewegt werden kann,
kann mir da jemand helfen?

Hier mein bisheriger Code:
Code: [AUSKLAPPEN]
   Winkel1 = (Winkel1 + 2) Mod 360
   
   If snowZeit < MilliSecs() Then
      snowZeit = MilliSecs() +20
      s.snow = New snow
      s\gfx  = CopyEntity(sprite)
      s\x#   = Rnd(-1000,1000)
      s\y#   = 500
      s\z#   = Rnd(-1000,1000)
   EndIf
   For s.snow = Each snow
      s\y# = s\y#-1
      PositionEntity s\gfx$,(320 + Cos(Winkel1) * 4)-s\x#,s\y#,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
Projekte: |Tibario| http://www.blitzforum.de/worklogs/325/ | 5%

Xeres

Moderator

BeitragFr, Jan 22, 2010 16:20
Antworten mit Zitat
Benutzer-Profile anzeigen
Jede Flocke braucht da ihren eigenen Winkel (also ein Field), mit einem zufälligen Anfangswert.
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)

Noobody

BeitragFr, Jan 22, 2010 16:21
Antworten mit Zitat
Benutzer-Profile anzeigen
Du verpasst einfach jeder Schneeflocke ein zusätzliches Feld (z.B. AngleAdd# oder so) und setzt es beim Erstellen der Schneeflocke auf einen zufälligen Wert zwischen 0 und 360. Diesen Wert addierst du dann bei jeder Schneeflocke beim Cosinus dazu (also Cos(Winkel1 + S\AngleAdd#)).

Das sollte dann ein relativ zufälliges Bewegungsmuster geben.
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun

N0X

BeitragFr, Jan 22, 2010 16:32
Antworten mit Zitat
Benutzer-Profile anzeigen
Danke! Smile
Projekte: |Tibario| http://www.blitzforum.de/worklogs/325/ | 5%

N0X

BeitragFr, Jan 22, 2010 16:50
Antworten mit Zitat
Benutzer-Profile anzeigen
So, wenn ich jetzt meine Map vergrößere, kommt nach kurzer Zeit ein MAV.
Wie kann ich das umgehen, und nur im angezeigten Bereich den Schnee zeichnen? (Habe Nebel der Kamera an.)

Hier mein Code:
Code: [AUSKLAPPEN]
;Variablen, Konstanten, Types etc.
Global snowZeit

Type snow
   Field x#,y#,z#
   Field gfx
   Field AngleAdd#
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")

;----------------------------------------------------------------------------------------------|
;2D Ressourcen
sprite = LoadSprite("gfx\snow.png")

;----------------------------------------------------------------------------------------------|
;Haupt-Schleife
While Not KeyHit(1)
   WaitTimer(timer)
   Cls
   Winkel1 = (Winkel1 + 3) Mod 360
   nMeshD  = -MeshDepth(map1)
   
   If snowZeit < MilliSecs() Then
      snowZeit = MilliSecs() +1
      For i = 0 To 29
      s.snow = New snow
      s\gfx  = CopyEntity(sprite)
      s\x#   = Rnd(0,MeshWidth(map1))
      s\y#   = 500
      s\z#   = Rnd(nMeshD,MeshDepth(map1))
      s\AngleAdd# = Rnd(0,360)
      Next
   EndIf
   For s.snow = Each snow
      s\y# = s\y#-1
      PositionEntity s\gfx$,(320 + Cos(Winkel1 + s\AngleAdd#) * 4)-s\x#,s\y#,s\z#
      If s\y# <= 0 Then
         FreeEntity(s\gfx)
         Delete s.snow
      EndIf
   Next
   
   RenderWorld()
   UpdateWorld()
   Flip 0
Wend
End
Projekte: |Tibario| http://www.blitzforum.de/worklogs/325/ | 5%

Tankbuster

BeitragFr, Jan 22, 2010 18:04
Antworten mit Zitat
Benutzer-Profile anzeigen
Du hast es doch selbst gesagt. Wenn der Schnee auf den Boden gefallen ist, einfach an der Position der Kamera + Rnd(-100,100) auf jeder Achse positionieren. Es geht natürlich auch komplexer, aber das sollte reichen.

Außerdem musst du den Schnee und das Entity nicht zwingend löschen, sondern kannst die Schneeflocke einfach wieder oben positionieren. Das spart Performance Wink
Twitter
Download Jewel Snake!
Windows|Android

N0X

BeitragFr, Jan 22, 2010 18:18
Antworten mit Zitat
Benutzer-Profile anzeigen
Sorry, bringt nix!

//EDIT:
Hat sich erledigt.
Projekte: |Tibario| http://www.blitzforum.de/worklogs/325/ | 5%

Neue Antwort erstellen


Übersicht BlitzBasic Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group