Timer innerhalb for-Schleife

Übersicht BlitzBasic Beginners-Corner

Neue Antwort erstellen

 

Eyes_Only

Betreff: Timer innerhalb for-Schleife

BeitragDo, Jan 17, 2013 23:15
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo Community,

ich habe eine Frage. Ich habe eine for-Schleife, in der durchgehend 10 Spielobjekte auf Veränderungen überprüft werden. Wenn eines der Objekte angeklickt wird, soll 1 Sekunde gewartet werden und anschließend das Objekt zur Spielfeldmitte fliegen.

Die Zeitabfrage mache ich mit Millisecs(), indem ich nach dem Mausklick eine Variable auf Millisecs() setze und dann später frage, ob Millisecs()-1000 > Zeitvariable ist.

Mein Problem ist nun, dass wenn ich den Timer einbaue, die Bewegung des angeklickten Objekts sich nach dem Timer richtet, das heißt, das Objekt sich nur alle 1 Sekunde richtung Mitte bewegt, nicht aber eine Sekunde wartet, und dann erst fliegt.

Hat jmd. eine Idee, wie ich den Timer einbauen kann, sodass er unabhängig von der Schleife läuft?

Ich hoffe das ist jetzt nicht zu abstrakt... Confused

Danke!

Pseudocode:
Code: [AUSKLAPPEN]
Repeat
   ...
   ;durchlaufe alle 10 Objekte und überprüfe Änderungen
   For I=0 To 9
      ;wenn Zustand normal, dann zeichne Bild1
      ...
      ;Wenn Objekt angeklickt und sichtbar, dann zeiche Bild2, warte 1 Sekunde und lass das Objekt zur Mitte fliegen
      If Objekt angeklickt And Objekt sichtbar Then
         DrawImage bild2...
         ;Timer abgelaufen, Flugbahnberechnung und Objekte zur Mitte fliegen
         If --- hier muss irgendwie der Timer rein --- ... Then ...
         EndIf
      EndIf
   Next
   
   ;Rechtsklickroutine;
   ...
   ;Zeichenroutine;
   ...
   ;Maus
   ...
   
   Flip
Until KeyHit(1)

Addi

BeitragDo, Jan 17, 2013 23:46
Antworten mit Zitat
Benutzer-Profile anzeigen
Du erstellst eine neue Variable (z.B. moveObj), setzt diese nach ablauf der Sekunde auf True
und überprüfst außerhalb deiner Timer-Routine, ob sie auf True ist. Wenn ja, dann bewegst du. Very Happy
BP/B3D/BMax : Lerne Java : Früher mal Lite-C : Gewinner BCC 62
 

PhillipK

BeitragFr, Jan 18, 2013 0:42
Antworten mit Zitat
Benutzer-Profile anzeigen
Addi hat recht.
Im zuge dessen solltest du dir - grade bei BlitzBasic - eine kleine updateroutine schreiben.

Diese update routine kann deine maus interaktionen übernehmen (Beispiel funktion Update() -> ruft CheckMouse() etc auf)), sofern dies noch möglich ist. Glaub mir, ist einfacher da hinterher durchzusteigen Very Happy

Ungeachtet des stils, hier meine version, wie ich es lösen würde:

- 2 Globale oder locale variablen. Eine für das objekt, eine als int für Millisecs(). Nennen wir sie moveObj und moveTime
- In der prüfung wird, falls eine änderung stattgefunden hat, gefragt, ob moveObj = null ist (im moment ist nichts am "in die mitte fliegen"). Wenn ja: moveObj = objekt_der_begierde und moveTime = millisecs()+1000
- zwischen "next" und ";Rechtsklickroutine; " kommt dann eine abfrage:
Wenn moveObj <> null (bzw <> 0) AND moveTime < Millisecs() DANN *bewegen, löschen, kitzeln* - was auch immer du machen möchtest Smile
- Vorgang abgeschlossen, ist in die mitte geflogen, wollen wir es nichtmehr bewegen oder haben wir bock auf ne änderung? alles klar ! moveObj = 0 bzw moveObj = null

(tut mir leid, das ich null schreibe.. keine ahnung, ob das in blitzbasic existiert!)

Xeres

Moderator

BeitragFr, Jan 18, 2013 1:16
Antworten mit Zitat
Benutzer-Profile anzeigen
Da du Informationen pro Objekt speichern und verarbeiten willst, wäre ein Type klar Mittel der Wahl.
Objekte erstellen, jeden Schleifendurchlauf die aktuelle Zeit vergleichen und entsprechende Zustände setzen, die das Objekt steuern.
BlitzBasic: [AUSKLAPPEN]
Select obj\Zustand
Case WAIT
If MilliSecs() [...] Then obj\Zustand=MOVE
Case MOVE
obj\x = obj\x + 1
End Select
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

BeitragFr, Jan 18, 2013 1:36
Antworten mit Zitat
Benutzer-Profile anzeigen
also hier mal eine Lösung mit nur 1 Variaben:

BlitzBasic: [AUSKLAPPEN]
Graphics 800,600
SetBuffer BackBuffer()

;als Beispiel-Objekt ein Ball
BallX=200
BallY=200

Repeat
Cls
; bei Mausklick Timer 1sec in die Zukunft
If MouseHit(1)
Ballstart=MilliSecs()+1000
EndIf

; wenn der Timer überhaupt einen Wert hat un der aber kleiner als JETZT ist
If BallStart>0 And BallStart<MilliSecs()

; Ball bewegen
BallX=BallX+1

;wenn der Ball am Ziel ist den Timer wieder auf 0
If BallX>400
BallStart=0
EndIf
EndIf
Oval BallX,BallY,10,10
Flip 0
Until KeyHit(1)
Gewinner des BCC #53 mit "Gitarrist vs Fussballer" http://www.midimaster.de/downl...ssball.exe

BladeRunner

Moderator

BeitragFr, Jan 18, 2013 9:05
Antworten mit Zitat
Benutzer-Profile anzeigen
Auch wenn es Korinthenkackerei ist, aber dieser Code ist zumindest minimal buggy. Wenn der Timer intern umschlägt und zufällig genau eine Sekunde vorher geklickt wird wird das Objet nie bewegt, da der Timer da schon auf 0 gesetzt wird. Da ist eine Lösung mit zwei Variablen sauberer.
Ich weiss dass die Wahrscheinlichkeit das der Bug auftritt gegen null tendiert, aber solche Kleinigkeiten können großen Projekten das Genick brechen.
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92
 

Eyes_Only

BeitragFr, Jan 18, 2013 15:43
Antworten mit Zitat
Benutzer-Profile anzeigen
Also irgendwie bekomme ich es nicht so richtig unter, habe schon ne Menge durchprobiert.
Ich vermute, dass mir die for-Schleife das Leben schwer macht. Ich muss wahrscheinlich doch auf Types umsteigen, so wie Xeres gesagt hat.

Ich hänge mal das bisherige Programm dran, dann könnt ihr euch vielleicht besser vorstellen, worum es mir geht.
[EDIT: Link siehe unten]

Es soll später ein Wimmelbild werden. Jetzt für das Grundgerüst habe ich alle abstrahiert. Die Grafiken werden später entsprechend ersetzt. Nach dem eine Fliege angeklickt ist, soll eine Sekunde vergehen und sie erst dann zur Mitte fliegen...
  • Zuletzt bearbeitet von Eyes_Only am Fr, Jan 18, 2013 23:36, insgesamt 2-mal bearbeitet

Xeres

Moderator

BeitragFr, Jan 18, 2013 20:20
Antworten mit Zitat
Benutzer-Profile anzeigen
Benutze doch bitte unser eigenes Archiv - Gratis-upload Seiten mit Werbung, lahmer Verbindung und Trojanern mag doch keiner.
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)
 

Eyes_Only

BeitragFr, Jan 18, 2013 23:04
Antworten mit Zitat
Benutzer-Profile anzeigen
Ah ok, mein Fehler, hier der neue Link:

https://www.blitzforum.de/upload/file.php?id=12196

Danke Xeres.

Midimaster

BeitragFr, Jan 18, 2013 23:58
Antworten mit Zitat
Benutzer-Profile anzeigen
also es sind nur 3 Änderungen an deinem Code nötig und es ist genauso wie in meinem Bispiel beschrieben:

1. Den Timer gleich bei Mausklick auf die Zukunft setzen:
BlitzBasic: [AUSKLAPPEN]
.....
If ImagesCollide ....
obj#(I,4) = 1
PlaySound sound
obj#(I,2) = MilliSecs()+1000 ; hier eine 1000 hin


2. Das alte Bild zeichnen solange Timer=0 oder größer als "JETZT" ist
BlitzBasic: [AUSKLAPPEN]
....
;Wenn Timer = 0, dann zeichne Bild1
If (obj#(I,2)=0) Or (obj#(I,2)>MilliSecs()) Then DrawImage bild1, bg_xpos+obj#(I,0), bg_ypos+obj#(I,1)



3. Das fliegende Bild zeichen wenn timer nicht 0, aber kleiner als "JETZT"
BlitzBasic: [AUSKLAPPEN]
....
;Wenn Objekt angeklickt und sichtbar, dann zeiche Bild2 und lass das Objekt zur Mitte fliegen
If (obj#(I,2)>0) And (obj#(I,2)<MilliSecs()); And obj#(I,3) = 1 Then



Der Vorschlag von Xeres wäre gold wert. Damit wird die Lesbarkeit deutlich erhöht. Du müsstest noch nicht einmal auf deine Array verzichten, sondern kannst TYPES und ARRAYS kombinieren:

siehe mein Tutorial Types in Array https://www.blitzforum.de/foru...245#356245

Das Beispiel dort mit den Karten passt genau zu deinem Problem:

BlitzBasic: [AUSKLAPPEN]
Type ObjektTyp
Field X#
Field Y#
Field Timer%
Field Sicht%
Field Klick%
Field Zent%
End Type

Dim Obj.ObjektTyp(10)

For i=0 To 9
Obj(i) = New ObjektTyp
Next

;objekte auf Karte verteilen
For I=0 To 9
obj(I)\X = 55*(I+1);X-Pos
obj(I)\Y = Rand(1000);Y-Pos
obj(I)\Timer = 0;Timer
obj(I)\Sicht = 1;Sichtbarkeit
obj(I)\Klick = 0;angeklickt
obj(I)\Zent = 0;zentriert
Next


Du würdest die 2.Dimension los und statt der zweiten Ziffer stünde da immer eine sinnvolle Bezeichnung




Ausblick:

Wenn Du das oben noch verstanden hast, ist es nur noch ein kleiner Schritt auf Array völlig zu verzichten. Es ist nämlich so, dass in BB selbst erstellte Objekt automatisch in eine Objektliste wandern, die man bequem bei Aktionen nutzen kann, wo man alle Objekte ansprechen möchte. Ich bleibe beim obigen Beispiel:

BlitzBasic: [AUSKLAPPEN]
Type ObjektTyp
Field X#
Field Y#
Field Timer%
Field Sicht%
Field Klick%
Field Zent%
End Type

For i=0 To 9
Local obj = New ObjektTyp
obj\X = 55*(I+1);X-Pos
Next

;objekte auf Karte verteilen
For Local Obj= Each ObjektTyp
obj\Y = Rand(1000);Y-Pos
obj\Timer = 0;Timer
obj\Sicht = 1;Sichtbarkeit
obj\Klick = 0;angeklickt
obj\Zent = 0;zentriert
Next

Tatsächlich kannst du jetzt alle 10 Fliegen unter dem gleichen Namen obj ansprechen.
 

Eyes_Only

BeitragMo, Jan 21, 2013 9:00
Antworten mit Zitat
Benutzer-Profile anzeigen
Wow!!!

Vielen vielen Dank für die ganzen tollen Antworten, insbesondere an Midimaster. Smile

Ich habe immer Probleme mir das mit den Timern bzw. mit Millisecs() richtig vorzustellen. Das braucht wohl einfach ein bisschen mehr Übung...

Types sind für mich absolutes Neuland, aber ich habe mir schon die Type-Tutorials hier im Forum angeschaut und versuche daraus zu lernen.

Ich werde mein Spiel erstmal ohne Types versuchen fertig zu stellen um den Spielablauf und alles zu erlernen und möchte dann später versuchen, das Spiel mit Types umzuschreiben.

Danke für die Hilfestellung mit den Types, eure Ausführungen werden mir sicher sehr helfen. Very Happy

PSY

BeitragMo, Jan 21, 2013 17:40
Antworten mit Zitat
Benutzer-Profile anzeigen
@Midimaster

In Deinem verlinkten Typetutorial sind noch n paar Fehler (zumindest in Lektion VI, da hab ich grad reingeschaut):

Bei Schachbrett
Code: [AUSKLAPPEN]
     Feld(i) = New FeldTyp
ist nur 1-dimensional, muss aber laut Deiner Deklaration 2-dimensional sein

Bei Monopoly
1. Code: [AUSKLAPPEN]
Dim Strasse.StrassenTyp(40)
'n' zuviel


2. Code: [AUSKLAPPEN]
For i=1 To 40
   Strasse(i).Name = "Schloßallee"
   Strasse(i).KaufPreis = 40000
   Strasse(i).InGruppe = SUPER_TEUER
Next

funzt so nicht, die '.' muessen durch nen '\' ersetzt werden.

Neulinge koennten sich da die Zaehne dran ausbeissen bei der Fehlersuche, besser erst immer die Codes testen Smile


PSY
PSY LABS Games
Coders don't die, they just gosub without return

Midimaster

BeitragMo, Jan 21, 2013 19:03
Antworten mit Zitat
Benutzer-Profile anzeigen
@PSY

lieben Dank, dass Du dir die Mühe gemacht hast, die Fehler zu melden. Du hast Recht: Anfänger Tutorials müssen fehlerfrei sein. Daher bin ich jetzt sehr froh, dass Du sie gefunden hast. Ich habe es gleich in Ordnung gebracht.

an alle:

Wenn ihr weitere Fehler findet, gibt es extra schon einen Kritik-Thread zu meinen Tutorials. Da sind Fehlemeldungen und Vorschläge sehr gern gesehen: https://www.blitzforum.de/foru...hp?t=33457
Gewinner des BCC #53 mit "Gitarrist vs Fussballer" http://www.midimaster.de/downl...ssball.exe

PSY

BeitragMo, Jan 21, 2013 19:50
Antworten mit Zitat
Benutzer-Profile anzeigen
@Midimaster
Kein Ding. Wenn ich ein wenig Zeit hab, schau ich mir den Rest mal an.
Und ups, stimmt, an den Kritik-Thread kann ich mich erinnern, is lange her. Hab ewig nix gemacht und erst wieder angefangen Smile

@EYES_ONLY
Um Dir zu zeigen, wie einfach das Ganze mit Types aussehen kann (ohne Menue + Scrollen):

Code: [AUSKLAPPEN]
AppTitle "WW"

SeedRnd MilliSecs() ; zufallsgenerator fuettern

Const SCREENWIDTH   = 1024
Const SCREENHEIGHT   = 768

Graphics SCREENWIDTH,SCREENHEIGHT,32,2
SetBuffer BackBuffer()

; Bilder, Sound laden
Local lev01%    = LoadImage("Lev01.jpg")
Local bild1%   = LoadImage("alien.bmp")   : MidHandle bild1
Local bild2%   = LoadImage("alien2.bmp")   : MidHandle bild2
Local sound%   = LoadSound("soundfx20.wav")

Local mx%, my%, mh%, i%, score%=0, deltaX%, deltaY%, counter%


Type TObj
   Field x#, y#
   Field time%
   Field state%
End Type

Global obj.TObj

For i=0 To 9
   obj.TObj = New TObj
   obj\x       = 95*(i+1)   ; X-Pos
   obj\y       = Rnd(745)   ; Y-Pos
   obj\time   = 0         ; warp-timer
   obj\state   = 0         ; zustand (0 = nicht gefunden  1 = gefunden/fliegt zum mittelpunkt  2 = warped aus screen)
Next



Repeat
   
   mx = MouseX()
   my = MouseY()
   mh = MouseHit(1)
   
   DrawBlock lev01, 0, 0 ; background zeichnen
   
   counter = 0
   
   ; alle types durchgehn
   For obj.TObj = Each TObj
      
      counter = counter + 1 ; types zaehlen
      If obj\state = 0 Then DrawImage bild1, obj\x, obj\y Else DrawImage bild2, obj\x, obj\y ; je nach zustand bild1 oder bild2
      
      If Abs(obj\x - mx) + Abs(obj\y - my) < 25 And mh And obj\state = 0 ; object gerade geklickt?
         obj\state = 1
         PlaySound sound
         score = score + 10
      EndIf
      
      If obj\state = 1 ; object fliegt zum mittelpunkt
         deltaX = obj\x - SCREENWIDTH/2.0
         deltaY = obj\y - SCREENHEIGHT/2.0
         obj\x = obj\x - deltaX * 0.03
         obj\y = obj\y - deltaY * 0.03
         If Abs(deltaX)<1 And Abs(deltaY)<1 Then obj\state = 2 : obj\time = MilliSecs()
      EndIf
      
      If obj\state = 2 ; aus bildschirm warpen?
         If MilliSecs() - obj\time > 500 Then obj\y = obj\y - 4
         If obj\y < -20 Then Delete obj.TObj ; wenn object aus bildschirm geflogen, loesch es
      EndIf
      
   Next
   
   
   If counter=0 Then RuntimeError "LEVEL SOLVED!" ; keine types mehr? dann level geschafft ^^
   
   Text 0,0,score
   Flip
   
Until KeyHit(1)
End


Konstruktive Kritik an Deinem Code:
1. Unsaubere bzw. ueberhaupt keine Variablendeklarationen. Wenn Du IDEal benutzt, schalte STRICT ein (unter Compile). Wenn Du IDEal nicht benutzt, mach es Smile
2. CLS brauchste nicht, wenn Du sowieso mit DRAWBLOCK bildschirmfuellend zeichnest
3. Zufallsgenerator vergessen zu initialisieren
4. Wenn Du nen eigenen Mauszeiger benutzt, versteck den internen mit Hidepointer
5. Die Font wird nur 1x geladen, und vor allem AUSSERHALB der Hauptschleife Smile

l8er,
PSY
PSY LABS Games
Coders don't die, they just gosub without return
 

Eyes_Only

BeitragDi, Jan 22, 2013 10:02
Antworten mit Zitat
Benutzer-Profile anzeigen
Oh Mann, wie geil ist das denn... Shocked

Types sind ja echt ne tolle Sache... Der ganze Code ist viel aufgeräumter und übersichtlicher - und kürzer!

Vielen Dank PSY und Midimaster und Xeres für die Hilfe mit den Types, da kann ich eine Menge draus lernen.

Und danke für die Anmerkungen zu meinem Code, ich werde die Fehler gleich ausmerzen. Very Happy

@PSY: Ja, ich benutze IDEal. War gleich mit das erste was ich mir zugelegt habe. Strict hatte ich von vornherein an. Aber diese rote Farbe war eigentlich ganz schön, um seine Variablen wiederzufinden. Razz

Eine Sache verstehe ich noch nicht ganz:

BlitzBasic: [AUSKLAPPEN]
If Abs(obj\x - mx) + Abs(obj\y - my) < 25 And mh And obj\state = 0 ; object gerade geklickt? 


Hier machst du ja die Kollisionsabfrage Bild-Maus.
Wie funktioniert das mit den Absoluten Zahlen und wo kommt die Zahl 25 her?
 

PhillipK

BeitragDi, Jan 22, 2013 14:51
Antworten mit Zitat
Benutzer-Profile anzeigen
Abs - Absolut - sagt simpel aus, das das vorzeichen entfernt wird.
-25 wird zu 25
25 wird zu 25
-1337 wird zu 1337 Smile


In der abfrage werden 2 differenzen errechnet. von Obj X zu MX und von Obj Y zu MY. Hier wird gerne Abs verwendet, um die reihenfolge der zahlen zu missachten.
Egal ob ObjX oder MX größer ist, das ergebnis ist positiv und gibt die "absolute" differenz zwischen beiden an.
In kombination mit der abfrage "<25" ergibt das eine ziemlich simple distanz bestimmung.

Um genau zu sein wird da die "Manhatten distanz" genutzt. Eine grobe schätzung ohne viel aufwand. Die 25 ist hier ein beliebiger wert, der zb einem Radius entsprechen kann.
In diesem fall nehme ich an, des es Bild2 - breite / 2 entspricht (wahlweise auch höhe, je nachdem, welches der kleinere wert ist)

PSY

BeitragDi, Jan 22, 2013 17:27
Antworten mit Zitat
Benutzer-Profile anzeigen
Hi Eyes_Only,

kein Ding Smile
Die Farben in der IDEal kannste auch so einstellen, wie Du sie haben willst.

Ansonsten zu der Distanz: Genau wie PhilipK schon geschrieben hat.
Die 25 hab ich grob geschaetzt (~Radius Bild).

Alternativ kannste natuerlich auch den Pythagoras nehmen (wenn die Bilder rund bzw. ungefaehr quadratisch sind, so wie bei Deinen hier): a^2 + b^2 = c^2

(Abstand BildX - MausX) ^2 + (Abstand BildY - MausY) ^2 sollte <= (Radius Bild)^2 sein

Code: [AUSKLAPPEN]
If (obj\x - mx)^2 + (obj\y - my)^2 < 625 And mh And obj\state = 0




PSY
PSY LABS Games
Coders don't die, they just gosub without return
 

Eyes_Only

BeitragDi, Jan 22, 2013 18:15
Antworten mit Zitat
Benutzer-Profile anzeigen
Cool, diese Art der "Kollisionserkennung" kannte ich noch nicht. Smile

Aber die macht doch so richtig eigentlich nur Sinn, wenn die Spielobjekte rund oder quadratisch sind, oder? Bei ungleichmäßig großen Objekten, die vielleicht noch irgendwelche "Auswüchse" haben, bietet sich das doch eher nicht an. Hab ich das richtig verstanden?
 

PhillipK

BeitragDi, Jan 22, 2013 18:43
Antworten mit Zitat
Benutzer-Profile anzeigen
So in etwa, ja Smile

Das ist in dem sinne keine kollisionserkennung sondern simples vergleichen von abständen.
Das ganze kann man grob unterteilen:

- Quadrate, oder nur grobe schätzung: Abs method (Manhatten distanz bzw Metrik genannt)
- Kreise: Pythagoras
- Alle arten Rechtecke, ohne drehung: "Punkt in rechteck" prüfung:

"Wenn testX >= zielX und testX <= zielX + ZielBreite und testY >= zielY und testY <= zielY + ZielHöhe Dann"

Mit diesen drei simplen abfrage kann man so ziemlich alles testen, was man will. Ausser man extrem genaue erwartungen, zb bei einem Shooter Smile

Und wenn du irgendwelche abstrakten figuren hast, kannst du immernoch Flächeninhalte vergleichen. Aber das bedarf ein wenig Geometrie, das kriege ich mit meinem fieber grade nicht hin ,sorry Smile
 

Eyes_Only

BeitragDi, Jan 22, 2013 22:00
Antworten mit Zitat
Benutzer-Profile anzeigen
Das musst du auch nicht. Smile
Vielen Dank für deine guten Ausführungen, das muss ich mir mal in Ruhe zu Gemüte führen und dann anwenden.

Und wenn ich mal eine Frage zu den Flächeninhalten habe weiß ich ja, an wen ich mich wenden kann. Wink

Gute Besserung!

Neue Antwort erstellen


Übersicht BlitzBasic Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group