 |
Das deutsche QBasic- und FreeBASIC-Forum Für euch erreichbar unter qb-forum.de, fb-forum.de und freebasic-forum.de!
|
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
MisterD

Anmeldungsdatum: 10.09.2004 Beiträge: 3071 Wohnort: bei Darmstadt
|
Verfasst am: 25.11.2005, 22:54 Titel: |
|
|
tilli hat Folgendes geschrieben: | Code: | while inkey$="": wend |
|
groooooßer Fehler.. das gibt ne endlosschleife!
Code: | while inkey$<>"": wend |
so muss sein. _________________ "It is practically impossible to teach good programming to students that have had a prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration."
Edsger W. Dijkstra |
|
Nach oben |
|
 |
Eastler_dart

Anmeldungsdatum: 25.09.2005 Beiträge: 177 Wohnort: Baden-Würtemberg + Sachsen
|
Verfasst am: 26.11.2005, 00:38 Titel: |
|
|
ZUM PORSCHE:
Dachte immer, ich bin der einzigste auf dieser Welt, der erst dann nen anderen (schnelleren) PC holt, wenn der bisherige wirklich zu langsam ist.
Hm. Man sollte der Werbung doch nicht zuviel Sachverständnis zutrauen.
-grins-
ZU LINUX:
hab ich mittlerweile auch getestet, auch dort ist die eins kaum auf ne Zwei zu verbiegen (SuSe-Linux 8.2 auf dem 200MMX, sowohl nur Konsole als auch in nem Konsole-Fenster unter KDE).
ZUM FEHLER:
hatte gedacht, mit dem Leeren des Tastaturpuffers mit der DO-Loop-Schleife bis Inkey$ leer ist wäre der Fehler weg?
War der Meinung, Fehler behoben, nur noch die Sorge, ob der Anwender das Prog an der Schleife zum stehen zwingen kann
Hatte doch die Zeitschleife testweise auf Tastendrücken abgeändert, dann liefs bei mir super mit Taschenrechner auf Spacetaste für Dauerfeuer (mit der Inkey$-Leerungsschleife drin). Hm.
Aber in meinem Test war nix von
WHILE Threadcontrol=1......WEND !!!
drin. Auch war es keine SUB.
Hm. Also, die TastaturSub wird solange/sooft durchlaufen, bis Threadcontrol nicht mehr 1 ist !!
zu MisterD:
Bienchen nur so wirds leer
Zu Tilli:
So wie du das aufführst, hat ich das ja auch gesehen.
Die Fragestellung war, wenn man mit MisterD's oder meiner
Tastaturleerungsroutine arbeitet, kann der Endanwender des
Programmes mittels Dauerfeuer auf ner Taste den Programm-
Ablauf anhalten, weil Inkey$ nicht leer wird.
Klar, du hast super begründet, was ich vermutet hatte,
nein, das kann der Endanwender nicht.
So eine Leerungsschleife einbauen ist ungefährlich in der Beziehung.
Zu ProggerX-Listing:
Wollte dein letztes, komplettes Listing an mein FreeBasic014
verfüttern, der findet aber die DLL nicht.
Dabei wollte ich nur die Thread-Geschichte austesten.
Hab kurzerhand ein eigenes Thread-Test-Prog erstellt,
um in das Thema mal reinzuschnüffeln.
Ist eine unheimlich Zeitkritische Sache, mit Threads zu arbeiten.
Hatte eine wüste Anzeige in meinem Prog, obwohl Hauptprogramm
und parallel dazu laufender UhrAnzeigeThread sauber per
Locate die Anzeigen auf dem Monitor positionieren sollten.
Da die Beiden Programmteile gleichzeitig laufen, kommt das
Setzen des Cursors per Locate und die Anzeige selber zeitlich
so weit auseinander, das dazwischen der Thread schon seine
uhranzeige an dieser Stelle bringt.
Drum komm ich hier erst mal zu dem kurzen Schluß:
Mit Threads ne Tastaturabfrage für ein Spiel wie die Stämme
zu erstellen, scheint mir wie mit Kanonen auf Spatzen zu schießen.
Zu viel Aufwand ohne wirklichen Sinn.
Der User sitzt doch vor dem Spiel, überlegt ne Sekunde, was er
mit seinem Gold machen will und drückt dann eine Taste, je nach dem.
Warum dazu die allerletzte tausendstel Sekunde herausgekitzelt
werden soll (Thread und Multikey) ist mir schleierhaft.
DAS EIGENTLICHE PROBLEM:
wie grad beschrieben, läuft deine Tastaturabfrage als Thread.
Thread heißt (hab nachgelesen), daß deine Tastaturabfrage
gleichzeitig mit dem Hauptprogramm abläuft.
Somit könnten deine benannten Abstürze/Fehler daraus kommen,
daß der Thread grad zu dem Zeitpunkt an deinen Variablen Werte ändert,
wenn dein Hauptprogramm dies ebenfalls grad macht (wurschtel wurschtel). Schätze mal, für einen Thread muß ganz genau überlegt
werden, auf welche Variablen eine solche Schleife zugreifen darf.
Was mir weiterhin auffällt. Eigentlich sollte in der zuletzt geposteten Version die Tastaturabfrage gar nicht laufen. Sie ist eingeschlossen in den Schleifenconstrukt: WHILE threadcontrol=1 ...... WEND
Und threadcontrol wird als Byte mit Wert 0 erstellt !
Erst wenn die Hauptschleife beendet wird, wird threadcontrol auf 1 gesetzt,
sodaß die While-Bedingung erfüllt wäre und die Tastaturkontrolle arbeiten dürfte.
An der Stelle, wo threadcontrol auf 1 gesetzt wird, beginnt das Programmende. Und dazu wäre es notwendig, threadcontrol auf 0 (und nicht auf 1) zu setzen. Nur so wird der Thread auch beendet.
Meine Schlußfolgerungen daraus lauten:
1) Wenn du dein Betriebssystem frisch hochfährst und dann dein Programm startest, wird es wohl keine Tastatureingaben annehmen. (Bitte testen, ob das so ist)
2) Wenn du dein Programm beendest, wird der Tastaturthread vermutlich NICHT beendet, (da threadcontrol auf 1 steht).
3) Wenn du das Programm mehrfach beendest und wieder neu startest, ist stark zu vermuten, daß dadurch mehrere (alte und der jeweils neue) Threads im Arbeitsspeicher laufen.
Um diese (vermuteten) Fehlerquellen auszuschließen, ändere in deinem Programm bitte folgendes:
A) bei: DIM SHARED as byte threadcontrol den Anfangswert auf 1 setzen (=1)
B) beim Programmende (bisher threadcontrol=1) threadcontrol=0 eintragen
C)Windows runterfahren (um übrig gebliebene, noch laufende Threads zu töten), neu starten, Programm compilieren und testen.
Sollten immer noch Abstürze auftreten, wird es wohl an den zeitkritischen Stellen beim Variablenzugriff liegen. Weiß nicht, ob ich dir dabei wirklich helfen kann, bestimmt sind hier noch mehr schlaue Köpfe, die sich damit dann auskennen.
Halte uns mit dem Werdegang deines Programmes auf dem Laufenden. Ist wirklich interessant.
Viel Spaß noch, Eastler _________________ Kaum macht mans richtig, schon geht's |
|
Nach oben |
|
 |
Progger_X Mr. Lagg
Anmeldungsdatum: 24.11.2004 Beiträge: 784 Wohnort: Leipzig
|
Verfasst am: 26.11.2005, 00:44 Titel: |
|
|
Na ja, nee, der Spieler baut dann ja meinentwegen 100 krieger auf einmal, dafür muss er 100 Durchläufe die Taste gedrückt halten. Ansonsten wäre das alles recht schwer.
Ich gehe jetzt schlafen, die Fehlersuche mach ich morgen. Nur ein was fällt mir noch ein, was mich interresieren würde: wenn ich das mit Maussteuerung mache, und dann 1 rotes viereck 0,0-200,200, und wenn man dort drauf klickt, dann wird das ausgeführt, das eben für alle Befehle, würde das dann ohne größere probleme gehen? |
|
Nach oben |
|
 |
Eastler_dart

Anmeldungsdatum: 25.09.2005 Beiträge: 177 Wohnort: Baden-Würtemberg + Sachsen
|
Verfasst am: 26.11.2005, 01:38 Titel: |
|
|
klar gibt es für die Maussteuerung mögliche Lösungen.
Genauso, wie es die für die Tastatur gibt.
Schwierig wird das nur, wenn diese Abfragen wirklich als Thread laufen sollen.
Tastatur ohne Thread = viel einfacher und für deinen Zweck ausreichend.
Maus ohne Thread = sogar zusätzlich zur Tastatur möglich.
Der User kann klicken oder tippen, ganz wie er es wünscht.
Viel Spaß beim grübeln. Morgen Abend schau ich wieder rein
Euer Eastler _________________ Kaum macht mans richtig, schon geht's |
|
Nach oben |
|
 |
Progger_X Mr. Lagg
Anmeldungsdatum: 24.11.2004 Beiträge: 784 Wohnort: Leipzig
|
Verfasst am: 26.11.2005, 16:57 Titel: |
|
|
Hallo!
Mal alles wegeditiert, weil ich's jetzt mit Maus hab:
Code: | '$INCLUDE: "SDL/SDL_NET.bi"
DECLARE SUB Connect(socket as tcpsocket,nummer)
OPTION EXPLICIT
TYPE spielereigenschaften
gold AS integer
goldmiene AS integer
krieger AS integer
wall AS integer
angreifen AS integer
END TYPE
DIM SHARED spieler(5) AS spielereigenschaften
SCREEN 18,8,3,0
COLOR 1,7
CLS
DIM sockclient AS tcpsocket
DIM SHARED nummer AS integer, gegi AS integer
Connect(sockclient,nummer)
IF nummer=1 THEN gegi=2 ELSE gegi=1
spieler(1).goldmiene=1
spieler(2).goldmiene=1
spieler(1).krieger=50
spieler(2).krieger=50
spieler(1).wall=2
spieler(2).wall=2
DIM nachricht AS string
DIM t#
t#=TIMER
DIM SHARED e AS integer
DIM SHARED dummy AS string
DIM zahler AS integer
DIM gold AS integer
DIM krieger AS integer
DIM gm AS integer
DIM angr AS integer
DIM vert AS integer
DIM wall AS integer
DIM angreifen AS integer
DIM attbild(5878 ) AS ubyte
DIM gmbild(5878 ) AS ubyte
DIM kriegerbild(5878 ) AS ubyte
DIM wallbild(5878 ) AS ubyte
BLOAD "att.bmp", VARPTR(attbild(0))
BLOAD "gm.bmp", VARPTR(gmbild(0))
BLOAD "krieger.bmp", VARPTR(kriegerbild(0))
BLOAD "wall.bmp", VARPTR(wallbild(0))
SETMOUSE (1,1,1)
DIM x AS integer, y AS integer, button AS integer
WHILE e=0
IF TIMER-t#>1 THEN
GOSUB senden
t#=TIMER
END IF
GOSUB maus
GOSUB bildschirm
GOSUB tasten
SLEEP 30
WEND
END
maus:
GETMOUSE(x,y,,button)
IF button=1 THEN
IF y<40 AND spieler(nummer).goldmiene*spieler(nummer).goldmiene<spieler(nummer).gold THEN
spieler(nummer).gold=spieler(nummer).gold-spieler(nummer).goldmiene*spieler(nummer).goldmiene
spieler(nummer).goldmiene=spieler(nummer).goldmiene+1
END IF
IF y>40 AND y<80 AND spieler(nummer).gold>10 THEN
spieler(nummer).gold=spieler(nummer).gold-10
spieler(nummer).krieger=spieler(nummer).krieger+1
END IF
IF y>80 AND y<120 AND spieler(nummer).wall*spieler(nummer).wall<spieler(nummer).gold THEN
spieler(nummer).gold=spieler(nummer).gold-spieler(nummer).wall*spieler(nummer).wall
spieler(nummer).wall=spieler(nummer).wall+1
END IF
IF y>120 AND spieler(nummer).krieger>0 THEN
spieler(nummer).angreifen=1
END IF
END IF
RETURN
bildschirm:
SCREENLOCK
CLS
LOCATE 12,1
PRINT spieler(nummer).angreifen
PRINT spieler(gegi).angreifen
PRINT "Gold(1): "+STR$(spieler(1).gold)
PRINT "Goldmiene(1): "+STR$(spieler(1).goldmiene)+" Kosten einer neuen Miene: "+_
STR$(spieler(1).goldmiene*spieler(1).goldmiene)+" Gold"
PRINT "Krieger(1): "+STR$(spieler(1).krieger)
PRINT "Wall(1): "+STR$(spieler(1).wall)
PRINT "Gold(2): "+STR$(spieler(2).gold)
PRINT "Goldmiene(2): "+STR$(spieler(2).goldmiene)+_
" Kosten einer neuen Miene: " + STR$(spieler(2).goldmiene*spieler(2).goldmiene)+" Gold"
PRINT "Krieger(2): "+STR$(spieler(2).krieger)
PRINT "Wall(2): "+STR$(spieler(2).wall) +_
" Kosten eines neuen Walls: " + STR$(spieler(2).wall*spieler(2).wall)+" Gold"
IF spieler(nummer).goldmiene*spieler(nummer).goldmiene<spieler(nummer).gold THEN
PRINT "Goldmiene Bauen=1"
PUT (1,1), gmbild, PSET
END IF
IF spieler(nummer).gold>10 THEN
PRINT "Söldner anwerben=2"
PUT (1,40), kriegerbild, PSET
END IF
IF spieler(nummer).gold>1000 THEN
PRINT "100 Söldner anwerben=3"
END IF
IF spieler(nummer).wall*spieler(nummer).wall<spieler(nummer).gold THEN
PRINT "Wall Bauen=4"
PUT (1,80), wallbild, PSET
END IF
IF spieler(nummer).krieger>0 AND spieler(nummer).angreifen<>1 THEN
PRINT "Angreifen = 5"
PUT (1,120), attbild, PSET
END IF
IF spieler(nummer).angreifen=1 THEN
PRINT "Angriff läuft...."
END IF
PRINT nachricht
SCREENUNLOCK
RETURN
senden:
nachricht=""
zahler=0
spieler(nummer).gold=spieler(nummer).gold+spieler(nummer).goldmiene*5
gold=spieler(nummer).gold
gm=spieler(nummer).goldmiene
krieger=spieler(nummer).krieger
wall=spieler(nummer).wall
angreifen=spieler(nummer).angreifen
SDLNET_TCP_SEND(sockclient, @gold,LEN(gold))
SDLNET_TCP_SEND(sockclient, @gm,LEN(gm))
SDLNET_TCP_SEND(sockclient, @krieger,LEN(krieger))
SDLNET_TCP_SEND(sockclient, @wall,LEN(wall))
SDLNET_TCP_SEND(sockclient, @angreifen,LEN(angreifen))
SDLNET_TCP_RECV(sockclient, @gold,LEN(gold))
SDLNET_TCP_RECV(sockclient, @gm,LEN(gm))
SDLNET_TCP_RECV(sockclient, @krieger,LEN(krieger))
SDLNET_TCP_RECV(sockclient, @wall,LEN(wall))
SDLNET_TCP_RECV(sockclient, @angreifen,LEN(angreifen))
spieler(gegi).gold=gold
spieler(gegi).goldmiene=gm
spieler(gegi).krieger=krieger
spieler(gegi).wall=wall
spieler(gegi).angreifen=angreifen
IF spieler(gegi).angreifen<>spieler(nummer).angreifen THEN
IF spieler(nummer).angreifen=1 THEN
angr=nummer
vert=gegi
END IF
IF spieler(gegi).angreifen=1 THEN
angr=gegi
vert=nummer
END IF
IF spieler(angr).krieger>spieler(vert).wall*spieler(vert).krieger THEN
nachricht="Der Angreifer gewann"
spieler(angr).gold=spieler(angr).gold+spieler(vert).gold
spieler(vert).gold=0
spieler(angr).krieger=spieler(angr).krieger-spieler(vert).krieger*spieler(vert).wall
spieler(vert).krieger=0
END IF
IF spieler(angr).krieger<spieler(vert).wall*spieler(vert).krieger THEN
nachricht="Der Verteidiger gewann"
spieler(vert).krieger=CINT((spieler(vert).krieger*spieler(vert).wall-spieler(angr).krieger)/spieler(vert).wall)
spieler(angr).krieger=0
END IF
END IF
IF spieler(gegi).angreifen=1 AND spieler(nummer).angreifen=1 THEN
nachricht="Beide griffen an, waren in der gegnerischen Stadt und plünderten sie"
gold=spieler(gegi).gold
spieler(gegi).gold=spieler(nummer).gold
spieler(nummer).gold=gold
END IF
spieler(1).angreifen=0
spieler(2).angreifen=0
RETURN
tasten:
IF MULTIKEY(&h02) AND spieler(nummer).goldmiene*spieler(nummer).goldmiene<spieler(nummer).gold THEN
spieler(nummer).gold=spieler(nummer).gold-spieler(nummer).goldmiene*spieler(nummer).goldmiene
spieler(nummer).goldmiene=spieler(nummer).goldmiene+1
END IF
IF MULTIKEY(&H03) AND spieler(nummer).gold>10 THEN
spieler(nummer).gold=spieler(nummer).gold-10
spieler(nummer).krieger=spieler(nummer).krieger+1
END IF
IF MULTIKEY(&H04) AND spieler(nummer).gold>1000 THEN
spieler(nummer).gold=spieler(nummer).gold-1000
spieler(nummer).krieger=spieler(nummer).krieger+100
END IF
IF MULTIKEY(&H05) AND spieler(nummer).wall*spieler(nummer).wall<spieler(nummer).gold THEN
spieler(nummer).gold=spieler(nummer).gold-spieler(nummer).wall*spieler(nummer).wall
spieler(nummer).wall=spieler(nummer).wall+1
END IF
IF MULTIKEY(&H06) AND spieler(nummer).krieger>0 THEN
spieler(nummer).angreifen=1
END IF
IF MULTIKEY(&H01) THEN e=1
DO
dummy$=INKEY$
LOOP UNTIL INKEY$=""
RETURN
SUB Connect(socket as tcpsocket,nummer)
DIM dummy AS string
IF SDLNet_Init() <> 0 THEN
PRINT "Fehler"
SLEEP
END
END IF
PRINT "1-Server"
PRINT "2-Client"
DO
dummy$=INKEY$
nummer=VAL(dummy$)
IF dummy$=CHR$(27) THEN END
LOOP UNTIL nummer=1 OR nummer=2
DIM sock AS tcpsocket'Socket einstellen
DIM sockclient AS tcpsocket
DIM ip AS ipaddress'Variable IP vom Typ IP Addresse
DIM zahler AS integer
IF nummer=1 THEN
SDLNet_Write32( INADDR_ANY, @ip.host )
SDLNet_Write16( 5678, @ip.port )
sock = SDLNet_TCP_Open( @ip )'TCP Verbindung öffnen, in den Socket schreiben
zahler=1
PRINT "Warte auf Client..."
WHILE sockclient = NULL
IF INKEY$=CHR$(27) THEN END
sockclient = SDLNet_TCP_Accept( sock )
SLEEP 5
WEND
END IF
IF nummer=2 THEN
DIM host AS string
INPUT "IP Addresse des Hostes: ", host$
SDLNet_ResolveHost( @ip, host$, 5678 )
sockclient = SDLNet_TCP_Open( @ip )
END IF
socket=sockclient
END SUB
|
Das geht ja erstmal so ganz gut...leider habe ich nur folgende Grafiken:
http://thefight.koolhost.de/Grafiken.zip
Weiß jemand, woher ich ordentliche Grafiken dafür bekomme?
Ach ja, und das Problem mit den Tasten gibt's immer noch. Hab ich mit dem Inkey weg machen was falsch gemacht? |
|
Nach oben |
|
 |
tilli

Anmeldungsdatum: 10.09.2005 Beiträge: 73
|
Verfasst am: 26.11.2005, 22:08 Titel: |
|
|
moin,
Bezüglich: Zitat: |
Tilli:
Das soll also der Code sein, um die Tasten abzufragen, und dann soll man das in nen thread packen?
|
Antwort: nein! Das ist die Variante ohne Thread!
Man könnte allerdings eine Funktion draus machen, die ein Ergebnis liefert.
z.b.
Code: |
function tastendruck (xy as integer) as integer
dann der Code von oben mit der Rückgabe tastendruck = true oder false (-1 oder 0)
|
dann kann man recht einfach abfragen nach:
Bsp: if tastendruck(h17) then ...
--- new theme:
@MrD:
tilli hat Folgendes geschrieben:
Code:
while inkey$="": wend
groooooßer Fehler.. das gibt ne endlosschleife!
Code:
while inkey$<>"": wend
so muss sein.
Antwort:
JAIN
es ergib nicht zwangläufig eine Endlosschleife,. sondern wartet aufd Tastendruck
aber in der Tat - hatte ich in der Eile der Weile verwechselt
Bezüglich : Eastler_dart
Tastatur ohne Thread = viel einfacher und für deinen Zweck ausreichend.
@Progger_X
Weiß jemand, woher ich ordentliche Grafiken dafür bekomme?
see Gimp
CU2
Tilli |
|
Nach oben |
|
 |
|
|
Du kannst keine Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum nicht antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen.
|
|