Image frame out of range
Übersicht

![]() |
SereyanneBetreff: Image frame out of range |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hi Leute,
ich habe ein Problem was die animierte Figur angeht. Hier ein Auszug aus dem Code für den Tastendruck nach oben: ElseIf KeyDown(rauf) Then If Player_Frame <10 Then Player_Frame = 10 Player_Counter = Player_Counter -1 If Player_Counter = 0 Then Player_Counter = 14 Player_Frame = Player_Frame +1 If Player_Frame = 13 Then Player_Frame = 10 EndIf So wie es da steht hab ich es für alle 4 Pfeiltasten konfiguriert, nur halt immer mit den entsprechenden Frames. Wenn ich das Spiel starte, geht auch eigentlich alles. Eigentlich. Denn wenn ich nach oben laufe und direkt danach links oder rechts drücke, läuft die Figur zwar in die grdrückte Richtung, aber die Animation bleibt die nach oben. Dann kommt der Fehler "image frame out of range" und das Spiel "crasht". Was mach ich falsch? (ich hoffe dass das Thema noch zur Beginners Corner gehört, denn ich bin eigentlich noch ein Anfänger) |
||
Dreamora |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Schalt den Debugger an, dann sagt er dir was bockt bzw. wo.
Ich würd sagen es hat mit der addition der frames zu tun und auf welches frame bei einem tastendruck das "grundframe" gesetzt wird. Aber das lässt sich einfach so nicht sagen, denn es kann alles mögliche sein, der gepostete code auf jeden fall ist zur lokalisierung "wertlos" am besten nimmst du deine framelogik, packst sie in ein neues file und testest sie mal alleine mit dem minimum von dem was nötig ist damit sie funktionieren sollte. damit kannst du das problem bedeutend schneller lokalisieren. |
||
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen. |
![]() |
Sereyanne |
![]() Antworten mit Zitat ![]() |
---|---|---|
Schade dass es da keine richtige Hilfe zu gibt.
Der Debugger ist an, was bringt mir das denn? Wo kann ich da irgendwas vernünftiges ablesen? |
||
![]() |
BladeRunnerModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
Dein Code ist nicht komplett, also keine Ahnung. Poste ihn bitte komplett unter Benutzung der Code-Tags (wenn du postest erscheinen sie unter der Smiley-Liste).
Vielleicht kann man dann mehr sagen. Allerdings wirkt das bissel was du bisher postest schon recht unstrukturiert. |
||
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 |
![]() |
Sereyanne |
![]() Antworten mit Zitat ![]() |
---|---|---|
ja was ist denn für euch ein kompletter code?
ich versuchs mal. Übrigens hab ich den code aus nem tutorial. alles was damit zu tun hat: Code: [AUSKLAPPEN] Global Magier = LoadAnimImage ("Magier4.bmp", 32, 48, 0, 14) (...) Global Player_Counter = 14, Player_Frame = 0 (...) Const rauf = 200, runter = 208, rechts = 205, links = 203, space = 57 (...) Function MoveMagier() If KeyDown(links) Then If Player_Frame <7 Then Player_Frame = 7 Player_Counter = Player_Counter -1 If Player_Counter = 0 Then Player_Counter = 14 Player_Frame = Player_Frame +1 If Player_Frame = 10 Then Player_Frame = 7 EndIf If map(Player_pos_x /32,(Player_pos_y +16) /32)=0 Then Player_pos_x = Player_pos_x -4 ; X-Position -4 If Player_pos_x =< 0 Then Player_pos_x = 1 EndIf ElseIf KeyDown(rechts) Then If Player_Frame >2 Then Player_Frame = 0 Player_Counter = Player_Counter -1 If Player_Counter = 0 Then Player_Counter = 14 Player_Frame = Player_Frame +1 If Player_Frame = 3 Then Player_Frame = 0 EndIf If map((Player_pos_x +32) /32,(Player_pos_y +16) /32)=0 Then Player_pos_x = Player_pos_x +4 If Player_pos_x => 608 Then Player_pos_x = 607 EndIf ElseIf KeyDown(rauf) Then If Player_Frame <10 Then Player_Frame = 10 Player_Counter = Player_Counter -1 If Player_Counter = 0 Then Player_Counter = 14 Player_Frame = Player_Frame +1 If Player_Frame = 13 Then Player_Frame = 10 EndIf If map((Player_pos_x +16) /32,Player_pos_y /32)=0 Then Player_pos_y = Player_pos_y -4 If Player_pos_y =< 0 Then Player_pos_y = 1 EndIf ElseIf KeyDown(runter) Then If Player_Frame <3 Then Player_Frame = 3 Player_Counter = Player_Counter -1 If Player_Counter = 0 Then Player_Counter = 14 Player_Frame = Player_Frame +1 If Player_Frame = 7 Then Player_Frame = 3 EndIf If map((Player_pos_x +16) /32,(Player_pos_y +32) /32)=0 Then Player_pos_y = Player_pos_y +4 If Player_pos_y => 448 Then Player_pos_y = 447 EndIf EndIf End Function Function DrawPlayer() DrawImage Magier, Player_pos_x, Player_pos_y, Player_Frame End Function |
||
![]() |
BladeRunnerModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
Also, der Player_counter ist schonmal unbrauchbar. Ich vermute mal dass der die Bewegung des Players verlangsamen soll. Das wird jedoch auf verschieden schnellen Rechnern auch verschieden schnell ablaufen, und kann auf modernen Maschinen irgendwann unspielbar schnell werden.
Es wäre also sinniger den player_counter durch einen ql:millisecs - Timer zu ersetzen welcher das Frame umschaltet. Dazu ist es weiterhin sinnvoll wenn jede Animationsrichtung gleich viele Schritte hat, was hier aber augenscheinlich nicht gegeben ist (14/4 gibt ja keine ganzen Zahlen). Warum ist das sinnvoller ? Weil du nun anstatt all deiner Ifs und nur noch den Timer aktuell halten musst und bei Tastendruck nur die Startrichtung änderst. Ein kleiner Pseudocode dazu Code: [AUSKLAPPEN] ;nehmen wir an, jede animation ist 4 Frames lang
const HOCH = 0, RUNTER = 4, LINKS = 8, RECHTS = 12 repeat... moving = false ;steht denn der alte holzmichel noch, ja der steht noch... if keyhit(Key_hoch) then richtung = HOCH moving = true ;jetzt lööft er endif ;analog für alle richtungen - das ist ja einfach ;) if timer <Millisecs() ;alle 100 ms wird weiteranimiert timer = millisecs() +100 ;timer resetten frame = frame +1 ;frame weiterzählen frame = frame mod 4 ;der modulo sorgt dafür das frame zwischen 0 und 3 bleibt endif if moving = false then frame = 0 ;und wenn nix gedrückt wird wird auch nichts animiert. endif drawimage player, x,y,(richtung+frame) ;et voila until ... |
||
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 |
![]() |
Sereyanne |
![]() Antworten mit Zitat ![]() |
---|---|---|
Herzlichen Dank. Werde gleich testen.
Wollte auch schon die Frage stellen, ob denn alle Animationen dieselbe Anzahl Frames haben müssen. Weil bei mir haben links und rechts 3 Frames und hoch und runter 4. Sind aber alles Beispiele, die ich so gezogen hab. Fertige Tilesets und der Code stammt ja aus dem Tutorial, deshalb peil ich nicht warum es nicht klappt oder warum es nicht sinnvoll ist. Jedenfalls danke schön! EDIT: Wie schreib ich das nun? was ist mit repeat..until? kann ich das nicht als function MovePlayer laufen lassen? Code: [AUSKLAPPEN] ;nehmen wir an, jede animation ist 4 Frames lang
const HOCH = 0, RUNTER = 4, LINKS = 8, RECHTS = 12 repeat... moving = false ;steht denn der alte holzmichel noch, ja der steht noch... if keyhit(Key_hoch) then richtung = HOCH moving = true ;jetzt lööft er endif ;analog für alle richtungen - das ist ja einfach ;) ;soll heißen: if keyhit(Key_runter) then richtung = RUNTER moving = true ;jetzt lööft er endif ;usw? if timer <Millisecs() ;alle 100 ms wird weiteranimiert timer = millisecs() +100 ;timer resetten frame = frame +1 ;frame weiterzählen frame = frame mod 4 ;der modulo sorgt dafür das frame zwischen 0 und 3 bleibt endif ;und wo kommt dieser timer hin? if moving = false then frame = 0 ;und wenn nix gedrückt wird wird auch nichts animiert. endif drawimage player, x,y,(richtung+frame) ;et voila until ... |
||
![]() |
BladeRunnerModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
Natürlich kann deine Animation unterschiedlich lang beschaffen sein, es macht halt nur alles ein wenig komplizierter.
Mein Code ist eben nur Pseudocode, also eine Art Anhalt wie man es regeln könnte. Selbstredend kanst Du das ganze auch in eine Funktion auslagern. |
||
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 |
![]() |
Sereyanne |
![]() Antworten mit Zitat ![]() |
---|---|---|
Muss ich denn den timer für jeden tastendruck neu regeln? ja oder? mit zu dem entsprechenden keyhit schreiben oder egal?
irgendwie wird meine figur mit deinem code überhaupt nicht animiert. wie geht es denn am einfachsten dass meine figur animiert wird? |
||
![]() |
BladeRunnerModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ich hab heut mal die Zeit dafür, also:
Code: [AUSKLAPPEN] Graphics 800,600
SetBuffer BackBuffer() Global player = LoadAnimImage ("anim.png",32,32,0,16) Global movetimer = MilliSecs() Const HOCH = 0, RUNTER = 4, LINKS = 8, RECHTS = 12 Global x,y Repeat ;INPUT moving = False ;steht denn der alte holzmichel noch, ja der steht noch... If KeyDown(200) Then richtung = HOCH moving = True ;jetzt lööft er EndIf If KeyDown(208) Then richtung = RUNTER moving = True ;jetzt lööft er EndIf If KeyDown(203) Then richtung = LINKS moving = True ;jetzt lööft er EndIf If KeyDown(205) Then richtung = RECHTS moving = True ;jetzt lööft er EndIf ;ANIMATIONSLOGIK If timer <MilliSecs() ;alle 100 ms wird weiteranimiert timer = MilliSecs() +100 ;timer resetten frame = frame +1 ;frame weiterzählen frame = frame Mod 4 ;der modulo sorgt dafür das frame zwischen 0 und 3 bleibt EndIf If moving = False Then frame = 0 ;und wenn nix gedrückt wird wird auch nichts animiert. EndIf ;BEWEGUNG If movetimer < MilliSecs() Then movetimer = MilliSecs() +25 ;Bewegung findet nur maximal alle 25 ms statt, sprich: maximal 40 Pixel/Sekunde If moving = True Then ;und nur wenn auch noch bewegt werden soll Select richtung Case HOCH If y >0 Then y = y-1 Case RUNTER If y < GraphicsHeight()-32 Then y = y +1 Case LINKS If x >0 Then x = x-1 Case RECHTS If x < GraphicsWidth()-32 Then x = x +1 End Select EndIf EndIf ;OUTPUT Text 320,200,x+" : "+y DrawImage player,x,y,(richtung+frame) ;et voila Flip Cls Until KeyHit(1) Die passende Datei gibt es hier: https://www.blitzforum.de/upload/file.php?id=2749 |
||
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 |
![]() |
Sereyanne |
![]() Antworten mit Zitat ![]() |
---|---|---|
wow, danke. ![]() hab gleich feierabend. vielleicht schaff ichs noch auszuprobieren, melde mich an montag wieder. herzlichen dank! |
||
![]() |
Sereyanne |
![]() Antworten mit Zitat ![]() |
---|---|---|
Herzlichen Dank, soweit ist schon mal alles ok.
Was mach ich denn jetzt, wenn mein Spieler nicht oben links in der Ecke starten soll, sondern nehmen wir mal an, vor einem Haus, er soll auf den Koordinaten x = 290, y = 250 stehen? Habs probiert mit Global Player_pos_x = 290 Global Player_pos_y = 250 komme aber so nicht voran. Die Figur wird animiert, bewegt sich aber kein Stück. Toll, oder? Hat jemand ne Idee? |
||
![]() |
BladeRunnerModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
Du setzt die Variablen die du im Drawbefehl hast zu Beginn auf den passenden Startwert. Logisch, oder ![]() |
||
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 |
![]() |
Sereyanne |
![]() Antworten mit Zitat ![]() |
---|---|---|
DrawImage Player,290,250, (richtung+frame) ;et voila ??
Wenn das ja mal so einfach wäre... Jetzt steht die Figur da wo sie soll, wird animiert, aber bewegt sich nicht.... |
||
![]() |
The_Nici |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hi,
ich würde zwei Variablen für die Playerposition nehmen. Bis jetzt zeichnest du immer an 290|250. Nun, folgendes: Code: [AUSKLAPPEN] p_x%=290 p_y%=250 Diese beiden Variablen deklarierst du ausserhalb der Mainloop. Sie stehen für die X und die y Position des Spielers. Dann in der Mainloop Code: [AUSKLAPPEN] If Keydown(203) Then p_x=p_x-1 ;Wenn Taste Links runter dann p_x-1 If Keydown(205) Then p_x=p_x+1 ;Wenn Taste runter Rechts dann p_x+1 If Keydown(200) Then p_y=p_y-1 ;Hoch If Keydown(208) Then p_y=p_y+1 ;Runter DrawImage Player, p_x,p_y,richtung+frame Die Tastencodes kannst du dir in der Englischen Dokumentation unter Command Reference -> Scancodes oder Scancodespicker anschauen. =) |
||
![]() |
BladeRunnerModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
Sereyanne hat Folgendes geschrieben: DrawImage Player,290,250, (richtung+frame) ;et voila ??
Wenn das ja mal so einfach wäre... Jetzt steht die Figur da wo sie soll, wird animiert, aber bewegt sich nicht.... Deswegen sagte ich ja Du sollst die Variablen auf den Wert setzen, nicht sie durch den Wert ersetzen ![]() |
||
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 |
![]() |
Sereyanne |
![]() Antworten mit Zitat ![]() |
---|---|---|
herzlichen dank euch allen.
was heißt denn eigentlich Const HOCH = 0, RUNTER = 4, LINKS = 8, RECHTS = 12 was bewirkt das? |
||
![]() |
BladeRunnerModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
ql:const steht für einen konstanten Wert, also eine nicht veränderbare Variable.
Das habe ich nur gemacht um die Übersichtlichkeit des Programmes zu erhöhen. Die Zahlen die ich den Variablen zuweise entsprechen den Frames ab denen die Animation dieser Richtung beginnt. So kann ich im Program dann auf leicht verständliche Weise prüfen worum es geht. Code: [AUSKLAPPEN] select richtung case RUNTER ist eben wesentlich leichter verständlich als: Code: [AUSKLAPPEN] select richtung case 4 Beides funktioniert, aber das erste ist einfach besser zu verstehen ![]() |
||
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 |
![]() |
Sereyanne |
![]() Antworten mit Zitat ![]() |
---|---|---|
aha danke. das würde dann ja bedeuten dass ich diese zahlen ändern sollte. bei mir ist das erste frame rechts, das vierte runter, das siebte links und das zehnte hoch. würde dann bedeuten:
Const HOCH = 9, RUNTER = 3, LINKS = 6, RECHTS = 0 ist doch richtig, oder? und was soll das % hinter p_x%=290? Wenn ich das weglasse ändert sich irgendwie nix. Ich krieg es aber immer noch nicht hin, das ganze in eine Funktion zu packen... hab das mal so abgeändert: Code: [AUSKLAPPEN] Graphics 640,480,32,3
SetBuffer BackBuffer() Global Magier = LoadAnimImage ("Magier.bmp",32,48,0,12) Global movetimer = MilliSecs() Const HOCH = 9, RUNTER = 3, LINKS = 6, RECHTS = 0 Global p_x%=290 Global p_y%=250 Repeat ;INPUT moving = False ;steht denn der alte holzmichel noch, ja der steht noch... If KeyDown(200) Then p_y=p_y-1 richtung = HOCH moving = True ;jetzt lööft er EndIf If KeyDown(208) Then p_y=p_y+1 richtung = RUNTER moving = True ;jetzt lööft er EndIf If KeyDown(203) Then p_x=p_x-1 richtung = LINKS moving = True ;jetzt lööft er EndIf If KeyDown(205) Then p_x=p_x+1 richtung = RECHTS moving = True ;jetzt lööft er EndIf ;ANIMATIONSLOGIK If timer <MilliSecs() ;alle 100 ms wird weiteranimiert timer = MilliSecs() +100 ;timer resetten frame = frame +1 ;frame weiterzählen frame = frame Mod 3 ;der modulo sorgt dafür das frame zwischen 0 und 3 bleibt EndIf If moving = False Then frame = 0 ;und wenn nix gedrückt wird wird auch nichts animiert. EndIf ;BEWEGUNG If movetimer < MilliSecs() Then movetimer = MilliSecs() +25 ;Bewegung findet nur maximal alle 25 ms statt, sprich: maximal 40 Pixel/Sekunde If moving = True Then ;und nur wenn auch noch bewegt werden soll Select richtung Case HOCH If y >0 Then y = y-1 Case RUNTER If y < GraphicsHeight()-32 Then y = y +1 Case LINKS If x >0 Then x = x-1 Case RECHTS If x < GraphicsWidth()-32 Then x = x +1 End Select EndIf EndIf ;OUTPUT DrawImage Magier, p_x,p_y,richtung+frame Flip Cls Until KeyHit(1) so funzt alles. aber in der funktion, wenns so aussieht: Code: [AUSKLAPPEN] Graphics 640,480,32,3
SetBuffer BackBuffer() Global Magier = LoadAnimImage ("Magier.bmp",32,48,0,12) MaskImage Magier, 255, 0, 255 Global movetimer = MilliSecs() Const HOCH = 9, RUNTER = 3, LINKS = 6, RECHTS = 0 Global p_x%=290 Global p_y%=250 Repeat MoveMagier() Flip ;Bildschirm tauschen cls Until KeyHit (1) End Function MoveMagier() ;INPUT moving = False ;steht denn der alte holzmichel noch, ja der steht noch... If KeyDown(200) Then p_y=p_y-1 richtung = HOCH moving = True ;jetzt lööft er EndIf If KeyDown(208) Then p_y=p_y+1 richtung = RUNTER moving = True ;jetzt lööft er EndIf If KeyDown(203) Then p_x=p_x-1 richtung = LINKS moving = True ;jetzt lööft er EndIf If KeyDown(205) Then p_x=p_x+1 richtung = RECHTS moving = True ;jetzt lööft er EndIf ;ANIMATIONSLOGIK If timer <MilliSecs() ;alle 100 ms wird weiteranimiert timer = MilliSecs() +100 ;timer resetten frame = frame +1 ;frame weiterzählen frame = frame Mod 3 ;der modulo sorgt dafür das frame zwischen 0 und 3 bleibt EndIf If moving = False Then frame = 0 ;und wenn nix gedrückt wird wird auch nichts animiert. EndIf ;BEWEGUNG If movetimer < MilliSecs() Then movetimer = MilliSecs() +25 ;Bewegung findet nur maximal alle 25 ms statt, sprich: maximal 40 Pixel/Sekunde If moving = True Then ;und nur wenn auch noch bewegt werden soll Select richtung Case HOCH If y >0 Then y = y-1 Case RUNTER If y < GraphicsHeight()-32 Then y = y +1 Case LINKS If x >0 Then x = x-1 Case RECHTS If x < GraphicsWidth()-32 Then x = x +1 End Select EndIf EndIf ;OUTPUT DrawImage Magier, p_x,p_y,richtung+frame End Function dann gehts nicht mehr. die figur bewegt sich, wird aber nicht gescheit animiert. |
||
![]() |
The_Nici |
![]() Antworten mit Zitat ![]() |
---|---|---|
Mach mal die frame-Variable Global und die Richtungs-Variable auch. | ||
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group