Einzelne Partikel unabhängig von einander bewegen

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
NeoRon
Beiträge: 67
Registriert: 22.03.2013 18:56

Einzelne Partikel unabhängig von einander bewegen

Beitrag von NeoRon »

Hallo liebes PB Forum,

ich hatte mein Problem schon einmal in der Vergangenheit gelöst.
Doch ich komme nicht mehr auf die logische Lösung.

Wenn ich in eine Richtung Partikel schieße und dann in die andere Richtung schieße bewegen sich alle Partikel die zuvor abgeschossen wurden mit.
Ich will aber das jeder Partikel in die Richtung fliegt in der er abgeschossen wurde und sich unabhängig der anderen verhält.

Wie kann man das denn nochmal lösen.
Hier ist der relevante Code.

Code: Alles auswählen


  If Weapon\Is_Shoot = 1
    ADDShoot(#SPRITE_PLAYER_SHOOT, 1, player\PositionX+145, player\PositionY-33, 400, Shoot_Act_List()\flightangle)
  EndIf


Procedure UpdateMove()
  
  Static OldTime.i
  Protected Time.i, Factor.f
  
  If OldTime = 0: OldTime = ElapsedMilliseconds(): EndIf
  
  Time = ElapsedMilliseconds()
  Factor = (Time - OldTime ) * 0.001
  
  ForEach Shoot_Act_List()
    
    Shoot_Act_List()\flightangle = Weapon\rotation
    
    Shoot_Act_List()\x - Shoot_Act_List()\speed * Sin( Radian( Shoot_Act_List()\flightangle ) ) * Factor
    Shoot_Act_List()\y + Shoot_Act_List()\speed * Cos( Radian( Shoot_Act_List()\flightangle ) ) * Factor
    
  Next 
  
  OldTime = ElapsedMilliseconds()
  
EndProcedure


  ForEach Shoot_Act_List()
    
    If Shoot_Act_List()\Sprite_Shoot = #SPRITE_PLAYER_SHOOT And Shoot_Act_List()\ID = 1 
      RotateSprite(Shoot_Act_List()\Sprite_Shoot, Shoot_Act_List()\flightangle - 180, #PB_Absolute)
      DisplayTransparentSprite(Shoot_Act_List()\Sprite_Shoot, Shoot_Act_List()\x, Shoot_Act_List()\y)
    EndIf
  Next


  Procedure ADDShoot(Sprite_Shoot, ID.i, x.i, y.i, speed.i, direction.f)
    AddElement(Shoot_Act_List())
    With Shoot_Act_List()
      \Sprite_Shoot = Sprite_Shoot
      \ID = ID
      \x = x
      \y = y
      \speed = speed
      \direction = direction
    EndWith
  EndProcedure



Danke und Grüße
Manuel
The World is Cyber
Benutzeravatar
man-in-black
Beiträge: 362
Registriert: 21.08.2006 17:39

Re: Einzelne Partikel unabhängig von einander bewegen

Beitrag von man-in-black »

Hi,

dein Problem liegt in dieser Zeile:

Code: Alles auswählen

Shoot_Act_List()\flightangle = Weapon\rotation
Du überschreibst bei jedem "Update" die gespeicherte Orientierung der Schüsse mit der aktuellen Ausrichtung deiner Waffe.
Kein Wunder, wenn sich ALLE deine Schüsse immer nach der Waffe richten.

Abgesehen davon verstehe ich nicht, wieso du die Ausrichtung der Schüsse speicherst, aber nicht verwendest:
(soll heißen der Wert taucht in UpdateMove() nicht auf)

Code: Alles auswählen

\direction = direction
Und was ich gar nicht nachvollziehen kann ist das Hinzufügen deiner Schüsse. Wieso holst du dir die Ausrichtung der Schüsse
aus der Ausrichtung des vorherigen Schusses, wenn du doch die Drehung der Waffe abspeichern solltest?!

Code: Alles auswählen

ADDShoot(#SPRITE_PLAYER_SHOOT, 1, player\PositionX+145, player\PositionY-33, 400, Shoot_Act_List()\flightangle)
sollte eigt so heißen:
ADDShoot(#SPRITE_PLAYER_SHOOT, 1, player\PositionX+145, player\PositionY-33, 400, Weapon\rotation)
Fazit, ändere den letzten Parameter von ADDShoot() und nutze statt "\flightangle" "\direction" in UpdateMove().
Mag sein, dass ich deinen Code missverstanden habe, aber für das richtige Verständnis wäre ein lauffähiger Code angebracht. ;)

PS: klingt etwas tadelnder als es sollte :D

MFG
MIB
(hab alles, kann alles, weiß alles!!^^)

Bild
Benutzeravatar
NeoRon
Beiträge: 67
Registriert: 22.03.2013 18:56

Re: Einzelne Partikel unabhängig von einander bewegen

Beitrag von NeoRon »

Oh man Danke!

was fürn dummen Logik fehler ich hatte.
Hab noch nicht so ganz den Überblick gehabt.

Danke für deine guten Ansatzpunkte!!!
Habs gelöst.

Hier der Korregierte Code:

Code: Alles auswählen

Procedure Control_Player_Weaapon()
  
  ;//---------------------------Player Weapon-----------------------
  ;//Start Speed  
  If weapon\Is_Rot = 1 Or weapon\dir = 1 
    weapon\Shall_Rot + weapon\Is_Rot
  EndIf
  If weapon\Is_Rot = -1 Or weapon\dir = -1 
    weapon\Shall_Rot - weapon\Is_Rot
  EndIf
  
  ;// Rotate Weapon
  If weapon\Is_Rot = 1 Or weapon\Dir = 1
    weapon\rotation + weapon\Shall_Rot
  EndIf
  If weapon\Is_Rot = -1 Or weapon\Dir = -1
    weapon\rotation - weapon\Shall_Rot
  EndIf
  
  ;// Max Speed Weapon
  If weapon\Shall_Rot => 1
    weapon\Shall_Rot = 1
  EndIf
  
  ;// Set Direction Weapon
  If weapon\dir = -1 And weapon\Shall_Speed =< 0
    weapon\dir = 0
  EndIf
  If weapon\dir = 1 And weapon\Shall_Speed =< 0
    weapon\dir = 0
  EndIf  
  
  ;// MAX Weapon Bewegung 
  If weapon\rotation => 240 
    weapon\rotation = 240
  EndIf
  If weapon\rotation =< 120
    weapon\rotation = 120
  EndIf
  
  ;// MAX Weapon Is_Rot
  If weapon\rotation => 240
    weapon\Is_Rot = 0
  ElseIf weapon\rotation =< 120
    weapon\Is_Rot = 0
  EndIf
  
EndProcedure


Procedure UpdateMove_Shoot()
  
  ;//Zeitgesteuert
  Static OldTime.i
  Protected Time.i, Factor.f
  
  If OldTime = 0: OldTime = ElapsedMilliseconds(): EndIf
  
  Time = ElapsedMilliseconds()
  Factor = (Time - OldTime ) * 0.001
  
    ;//---------------------------Player Shoot-----------------------  
  ;// Start Shoot
  If Weapon\Is_Shoot = 1
    ADDShoot(#SPRITE_PLAYER_SHOOT, 1, player\PositionX+145, player\PositionY-33, 400, weapon\rotation)
  EndIf
  
  ;//Schuss in Richtungswinkel
  ForEach Shoot_Act_List()

    Shoot_Act_List()\x - Shoot_Act_List()\speed * Sin( Radian( Shoot_Act_List()\flightangle ) ) * Factor
    Shoot_Act_List()\y + Shoot_Act_List()\speed * Cos( Radian( Shoot_Act_List()\flightangle ) ) * Factor

  Next 
  
  OldTime = ElapsedMilliseconds()
  
    Debug "flightangle " +Str(Shoot_Act_List()\flightangle ) 
    Debug "rotate weapon " +Str(weapon\rotation ) 
  
EndProcedure


  ;// Display Player Shoot
  ForEach Shoot_Act_List()
    
    If Shoot_Act_List()\Sprite_Shoot = #SPRITE_PLAYER_SHOOT And Shoot_Act_List()\ID = 1 
      RotateSprite(Shoot_Act_List()\Sprite_Shoot, Shoot_Act_List()\flightangle - 180, #PB_Absolute)
      DisplayTransparentSprite(Shoot_Act_List()\Sprite_Shoot, Shoot_Act_List()\x, Shoot_Act_List()\y)
    EndIf
  Next


  Procedure ADDShoot(Sprite_Shoot, ID.i, x.i, y.i, speed.i, flightangle.f)
    AddElement(Shoot_Act_List())
    With Shoot_Act_List()
      \Sprite_Shoot = Sprite_Shoot
      \ID = ID
      \x = x
      \y = y
      \speed = speed
      \flightangle = flightangle
    EndWith
  EndProcedure
The World is Cyber
SilverSurfer
Beiträge: 32
Registriert: 14.06.2015 10:23

Re: Einzelne Partikel unabhängig von einander bewegen

Beitrag von SilverSurfer »

Hallo Manuel, habe dir mal ein kleines Demo gemacht......

Hoffe es hilft dir....

Code: Alles auswählen

EnableExplicit
;***************************************************************************
;* 
;* 
;* 
;*     Coded By: Klaus Wilke
;*     PB 5.31/ September 2015
;***************************************************************************
#ScreenW = 1024
#ScreenH = 768
#FPS     = 1000/60

  If InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0 Or InitSound() = 0
    MessageRequester("Error", "Can't open screen & sprite environment!", 0)
    End
  EndIf
  
  If  OpenWindow( 0, 0, 0, #ScreenW, #ScreenH, "A screen in a window...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered ) = 0
    MessageRequester( "Error", "Can`t open Window !", 0 )
  EndIf
     
  If  OpenWindowedScreen( WindowID(0), 0, 0, #ScreenW, #ScreenH ) = 0
       MessageRequester( "Error", "Can`t open WindowScreen !", 0 )
  EndIf
  
  Global GameTimer.i, Event.i, SpriteWeapon.i, WeaponRotate.i, Weapon_X.i = 512, Weapon_Y.i = 384
  Global Exit.b = #False
  ; Hier malen wir unsere Kanone
  
  ClearScreen( 0 )
  
  StartDrawing( ScreenOutput() )
  
  Box( 10, 63 - 10, 117, 20, $FFFFFF )
  DrawingMode( #PB_2DDrawing_Outlined )
  Box( 0, 63 - 10, 10, 20, $FFFFFF)
  StopDrawing()
  
  SpriteWeapon = GrabSprite( #PB_Any, 0, 0, 128, 128, #PB_Sprite_AlphaBlending )
  
  Structure attrib
    
    sprite.i
    x.f
    y.f
    angle.f
    speed.f
    
  EndStructure
  
  Global NewList Shot.attrib()
  
  ; mit dieser Procedure kannst du den Drehpunkt verlagern, dafür zuständig ist CenterX und CenterY.
  ; Sind beide 0 liegt der Drehpunkt in der Mitte des Sprites.
  
  Procedure DisplayTransformSprite(Sprite.i, X.f, Y.f, Width.f, Height.f, angle.f, CenterX.f=0, CenterY.f=0, Transparency=255)
  
  Protected Sin.f = Sin(Radian(angle)), Cos.f = Cos(Radian(angle))
  TransformSprite(Sprite, X + Cos*(-Width*0.5-CenterX) - Sin*(-Height*0.5-CenterY), Y + Sin*(-Width*0.5-CenterX) + Cos*(-Height*0.5-CenterY), X + Cos*( Width*0.5-CenterX) - Sin*(-Height*0.5-CenterY), Y + Sin*( Width*0.5-CenterX) + Cos*(-Height*0.5-CenterY), X + Cos*( Width*0.5-CenterX) - Sin*( Height*0.5-CenterY), Y + Sin*( Width*0.5-CenterX) + Cos*( Height*0.5-CenterY), X + Cos*(-Width*0.5-CenterX) - Sin*( Height*0.5-CenterY), Y + Sin*(-Width*0.5-CenterX) + Cos*( Height*0.5-CenterY))
  DisplayTransparentSprite(Sprite, 0, 0, Transparency)
  
EndProcedure

Procedure UpdateMove()
  
  Protected Factor.f
  Static OldTime.i
  
  If OldTime = 0 : OldTime = ElapsedMilliseconds(): EndIf
  
  Factor = ( ElapsedMilliseconds() - OldTime ) * 0.001  
  
  ForEach Shot()
    
    With Shot()
      
      \x + Cos( Radian( \angle ) ) * \speed * Factor
      \y + Sin( Radian( \angle ) ) * \speed * Factor
      
      If \x > 1023 + 5 Or \x < - 5 Or \y > 767 + 5 Or \y < - 5; prüfen ob die Kugel aus dem Bild ist
        
        DeleteElement( Shot() )
        
      EndIf
      
    EndWith
    
  Next
  
  OldTime = ElapsedMilliseconds()
  
EndProcedure

Procedure CreateShot()
  
  AddElement( Shot() )
  
  With Shot()
    
    \x = Weapon_X + Cos( Radian( WeaponRotate ) ) * 128; Schuss an die Spitze der
    \y = Weapon_Y + Sin( Radian( WeaponRotate ) ) * 128; Kanone setzen
    \angle = WeaponRotate; Winkel der Kanone speichern, da das die Richtung ist in der die Kugel fliegen soll    
    \speed = 300
    
  EndWith
  
EndProcedure

  Procedure UpdateScreen()
    
    ClearScreen(RGB(0, 0, 0))
   
    StartDrawing( ScreenOutput() )
    
    DrawingMode( #PB_2DDrawing_Outlined )
    
    Circle( Weapon_X, Weapon_Y, 50, $00FF00 )
    Circle( Weapon_X, Weapon_Y, 2, $0000FF )
    
    ForEach Shot()
       
       With Shot()
         
         Circle( \x, \y, 5, $FFFFFF )
         
       EndWith
       
     Next
    
    StopDrawing()
    
    DisplayTransformSprite( SpriteWeapon, Weapon_X, Weapon_Y, 128, 128, WeaponRotate, -64, 0, 255 )

     FlipBuffers() 
    
  EndProcedure
  
  Procedure UpdateKeyboard()
   
    ExamineKeyboard()
    
    If KeyboardPushed( #PB_Key_Right )
      
      WeaponRotate + 1
      If WeaponRotate > 359: WeaponRotate = 0:EndIf
      
    EndIf
    
    If KeyboardPushed( #PB_Key_Left )
      
      WeaponRotate - 1
      If WeaponRotate < 0: WeaponRotate = 359:EndIf
      
    EndIf
    
    If KeyboardReleased( #PB_Key_Space )
      
      CreateShot()
      
    EndIf
    
    If KeyboardPushed( #PB_Key_Escape )
      
      Exit = #True
      
    EndIf
    
  EndProcedure
  
  Repeat
   
    Repeat
      
      Event = WindowEvent()
      
      Select Event 
          
        Case #PB_Event_CloseWindow
          
          End 
          
      EndSelect
      
    Until Event = 0
  
    If ElapsedMilliseconds() >= GameTimer
      
      UpdateScreen()
      UpdateKeyboard()
      UpdateMove()
      
      GameTimer = ElapsedMilliseconds() + #FPS 
      
    EndIf
    
    Delay(0)   
    
  Until Exit = #True
  
  End
  
  CloseScreen()
  

Benutzeravatar
NeoRon
Beiträge: 67
Registriert: 22.03.2013 18:56

Re: Einzelne Partikel unabhängig von einander bewegen

Beitrag von NeoRon »

Danke Klaus!

Die Demo werde ich mir mal zu Herzen nehmen.

Versuche Sie nachzuvollziehen und eine eigene Demo daraus zu basteln und hoffe ich lerne daraus, was es bestimmt macht,
um mein Coden zu verbessern.

Grüße
Manuel
The World is Cyber
Antworten