Du bist nicht angemeldet.

Werbeanzeige

1

14.04.2006, 18:23

Commander Keen Clone + Top Mapeditor!Send me your Maps!

So, mal wieder was von mir.

Nachdem ich die ganze C++ Programmierung erstmal in eine weit entferne Schublade gesteckt habe (2 Programmiersprachen gleichzeitig zu lernen war mir einfach zu viel, die Verwechslungen haben gestört) habe ich mich wieder der Programmierung in Oberon gewidmet.

Die Entscheidung liegt nahe, da die Sprache in der Schule Pflicht ist und wir bald ein Abschlussprojekt programmieren sollen.

Also habe ich angefangen mich mit Tastatur und Mauseingaben auseinander zu setzen. Dann folgten Module die Datenverarbeitung und BMP-Darstellung ermöglichten... ich habe mir sehr viele eigene Module erstellt mit denen man ganz leicht sonst schwer zu realisierende Aufgaben erledigen kann. Das war auch gut so, denn sonst wäre ich nie auf dem jetzigen Stand der Entwicklung sondern hätte wohl schon aufgegeben.

Ich möchte daher mal die Entwicklung einiger Programme von mir zeigen..

Die Anfänge: Verarbeitung von Usereingaben
Drawmouse.exe : Die Maus malt einfach auf dem Fenster. Es ist möglich über die 3 Maustasten die 3 Farbwerte (RGB) einzeln anzusteuern.

http://img395.imageshack.us/my.php?image=17fv.gif

Draw.exe : Eine simple WASD Steuerung ermöglicht es gerade Linien auf dem Bildschirm zu malen... auch hier über R, G und B die RGB Steuerung ;)

http://img395.imageshack.us/my.php?image=20rs.gif

--> http://img320.imageshack.us/my.php?image=neubitmap7fh.gif

Desweiteren spielte ich mit Dateierstellung und Verarbeitung herum. In Oberon ist es von Haus aus nicht möglich, Integerdaten zu speichern und wieder auszulesen. Daher werden Integerwerte als String gespeichert, dann Ziffer für Ziffer als Char in einem Array zwischengespeichert, diese Ziffern über Asciicode in echte Integer umgewandelt (IF Ascii = xx THEN Integer := x). Somit hatte ich ein Array voller Ziffern. Was bringt einem das bei Highscoreberechnungen? Nicht viel. Von daher habe ich mir einen Algorithmus überlegt, der die einzelnen Ziffern je mit 1, 10, 100, 1000 fortlaufend multipliziert und dann addiert. Letztendlich hatte ich es doch tatsächlich geschafft, den Bonus aus einer Datei auszulesen und ihn zum Highscore hinzuzufügen :D

Daraus entstanden dann 2 erste Module. Zum einen ColorFct und FileFct.
Hier könnt ihr mal die dazu entstande Dokumentation lesen (ist noch nicht ganz fertig, vor allem zum Schluss hin):

http://www.computerpannen.com/informatik/Dokumentation.doc

Nun, über diese ganze Vorarbeit entstand mein erstes "Spiel" auf das ich besonders Stolz bin.

CommanderKeen.exe
Eigentlich total simpel, aber für mich war es nunmal ein riesen Erfolg. Ich hatte es geschafft, CommanderKeen über den Bildschirm laufen zu lassen! Zwar kann man nur nach rechts und links, es existiert kein Levelsystem oder Ähnliches, aber wie schon gesagt... :-D

Tatsache ist, dass das mit den Animationen usw. gar nicht so einfach war / ist. Vorallem ist es blöd, dass Keen sich noch bewegt, wenn man die Taste schon losgelassen hat (weil er die Animation einmal durchlaufen muss). Daher war ich froh das ich es geschafft hatte, dass er sich nur 1-2 PX bewegt wenn man die Taste ganz kurz drückt. Ihr könnt euch das Ganze mal anschauen, ich denke mein Problem wird schnell klar. Bis jetzt habe ich es auch nicht geschafft dies zu verbessern.

(Ich denke der Fehler liegt beim Sleepbefehl der immer dann eintritt wenn ein Bild gezeigt wurde und das nächste gezeigt werden soll, dann schläft die Anwendung ja... ich weiß echt nicht wie ich das realisieren soll :/ )

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
PROCEDURE WalkRight();
VAR check, check2: BOOLEAN;
  temp: INTEGER;
BEGIN
 
    (* Jedes Bild wird 6 mal gezeichnet
       Dabei werden Forschleifen zur Schrittweisen Erhöhung der
       X-Koordinate verwendet! *)
      check := C.KeyPressed();
 
      IF check = FALSE THEN m := m + 2; 
      FOR temp := 0 TO 15 BY 2 DO 
        C.Clear(); (* Vorheriges Bild löschen! *)
        CFct.Picture("r0.BMP", m, 0, 10); (* Zeichne das Bild für XXms *)
        IF m > 768 THEN m := 768; END;
      END;
      check2 := TRUE;
      END;

      check := C.KeyPressed();
      
      IF check = TRUE THEN 
      FOR j := m TO (m+15) BY 2 DO 
        C.Clear(); (* Vorheriges Bild löschen! *) 
        CFct.Picture("r0.BMP", j, 0, 10); (* Zeichne das Bild für XXms *)
        IF m > 768 THEN m := (m+16); END;
      END;
       
      FOR k := j TO (j+15) BY 2 DO
        C.Clear();
        IF k > 768 THEN k := (j+15); END;
        CFct.Picture("r1.BMP", k, 0, 10);
      END;
      END; 
      
      IF check = TRUE THEN
      FOR l := k TO (k+15) BY 2 DO
        C.Clear();
        CFct.Picture("r2.BMP", l, 0, 10);
        IF l > 768 THEN l := (k+16); END;
      END;
      END;
    
      IF check = TRUE THEN
      FOR m := l TO (l+15) BY 2 DO
        C.Clear();
        CFct.Picture("r1.BMP", m, 0, 10);
        IF m > 768 THEN m := (l+16); END;
      END;
      END;
 
    C.Clear(); 
    CFct.Picture("r.BMP", m, 0, 0); (* Keen bleibt stehen *)
  
END WalkRight;


Syntax für

Quellcode

1
CFct.Picture : (Dateiname, x, y, Sleepzeit)



http://img213.imageshack.us/my.php?image=neubitmap68zv.jpg

Jumpnrun.exe
Also habe ich mich neu rangesetzt. Diesmal mit einem Array als Levelsystem. Es entstand eine erste "richtige Engine":

Das 20x20 Array wird mit den Werten aus Map1.txt, Map2.txt fortlaufend gefüllt. Man kann Springen, Punkte bekommen, Kollisionsabfrage funktioniert usw. Da war ich dann auch wieder sehr stolz drauf... das Ganze sah so aus:

http://img377.imageshack.us/my.php?image=neubitmap67jp.jpg

Die Steuerung:

Q = Nach oben links springen
W = Nach oben springen
E = Nach oben rechts springen
A = Nach links laufen
D = Nach rechts laufen

Oberon kann leider nicht 2 Tastenanschläge gleichzeitig verarbeiten... und falls doch weiß ich nicht wie... das Problem ist es ja im Prinzip 2 Prozeduren gleichzeitig ablaufen zu lassen?! Ich steig einfach nicht dahinter :D

Naja... ich habe das dann in Grafik umgewandelt. Und zwar in BMP's. Jedes Feld war eine kleine 16x16 BMP... und die Framerate war... seeeehr niedrig.. ui... ^^

Somit habe ich die 16x16 BMP's in Programmieranweisungen umwandeln müssen -> es war wieder rasend schnell :)

Für diese BMP:

http://img213.imageshack.us/img213/9307/punkt4gm.png

musste dieser Code her: (tolle Arbeit...)

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
PROCEDURE DisplayPunkt*(newx, newy: INTEGER);
BEGIN
  
  (* Hintergrund *)
  C.SetForeColor(168,168,168);
  C.Bar(1+newx,1+newy,16+newx,16+newy,1);
  
  CFct.Color(0,15);
  C.Bar(3+newx,7+newy,14+newx,14+newy,1);
  
  C.Bar(13+newx,8+newy,14+newx,9+newy,1);  
  C.Bar(14+newx,10+newy,15+newx,11+newy,1);
  C.Bar(13+newx,12+newy,14+newx,13+newy,1);
  
  C.SetForeColor(252,84,84);
  C.Bar(4+newx,7+newy,13+newx,14+newy,1);
  C.Line(6+newx,6+newy,9+newx,6+newy,1);
  C.Line(6+newx,15+newy,9+newx,15+newy,1);
  C.Line(3+newx,8+newy,3+newx,13+newy,1);
  C.Line(2+newx,10+newy,2+newx,11+newy,1);
  
  CFct.Color(0,15);
  C.Line(4+newx,12+newy,5+newx,12+newy,2);
  C.Line(5+newx,13+newy,6+newx,13+newy,2);
  C.Bar(8+newx,2+newy,9+newx,5+newy,2);
  
  C.Line(7+newx,1+newy,11+newx,1+newy,1);
  C.Line(7+newx,2+newy,7+newx,5+newy,1);
  C.Line(11+newx,2+newy,11+newx,5+newy,1);
  C.Line(6+newx,16+newy,11+newx,16+newy,1);
  
  C.Line(4+newx,15+newy,5+newx,15+newy,1);
  C.Line(12+newx,15+newy,13+newx,15+newy,1);
  C.Line(4+newx,6+newy,5+newx,6+newy,1);
  C.Line(12+newx,6+newy,13+newx,6+newy,1);
  
  C.Line(2+newx,8+newy,2+newx,9+newy,1);
  C.Line(2+newx,12+newy,2+newx,13+newy,1);
  C.Line(15+newx,8+newy,15+newx,9+newy,1);
  C.Line(15+newx,12+newy,15+newx,13+newy,1);  
  
  C.Line(1+newx,10+newy,1+newx,11+newy,1);
  C.Line(16+newx,10+newy,16+newx,11+newy,1);
  C.Dot(6+newx,5+newy,1);
  
  C.SetForeColor(84,84,84);
  C.Line(10+newx,2+newy,10+newx,5+newy,1);
  
  C.SetForeColor(168,0,0);
  C.Line(10+newx,6+newy,11+newx,6+newy,1);
  C.Line(10+newx,15+newy,11+newx,15+newy,1);
  C.Line(12+newx,7+newy,13+newx,7+newy,1);
  C.Line(12+newx,14+newy,13+newx,14+newy,1);
  
  C.Bar(13+newx,8+newy,14+newx,9+newy,1);
  C.Bar(14+newx,10+newy,15+newx,11+newy,1);
  C.Bar(13+newx,12+newy,14+newx,13+newy,1);
  
END DisplayPunkt;


Als ich fast alle BMP's umgewandelt hatte war die Framerate auch wieder in Ordnung. Das hier ist rausgekommen:

http://img213.imageshack.us/my.php?image=neubitmap69hi.jpg

Als nächstes müssen jetzt KI-Bewegungen, Animation usw. mit rein. Und da ist wieder der Knackpunkt. WIE? Eine Animation kann ich nur abspielen wenn sie nicht zu schnell läuft. Damit sie nicht zu schnell läuft muss ich zwischendurch immer Sleep-Befehle ausführen. 2 Animationen gleichzeitig sind somit unmöglich?! Ich würde mich da echt über Hilfe freuen. John91 hat schonmal was von Timern erzählt... allerdings hab ich da keine Ahnung von. Das einzige was ich kann ist die Sekundenzahl vom System auslesen ^^. Aber Sekundenpausen wären wieder zu langsam...

Übrigens kann man mit Oberon auch die WINAPI nutzen. Ich weiß zwar nicht wie, habs auch noch nie gemacht, aber es geht :huhu:

Und dann hier noch das Packet mit all den Programmen usw:
http://www.computerpannen.com/informatik/sammlung/jumpnrun.rar

oder die Files einzeln:

http://www.computerpannen.com/informatik/sammlung/
(CommanderKeen.Exe benötigt die ganzen l012 und r012 BMP's)
(JumpnRun.Exe benötigt figurl, figurr, garg und ziel.bmp sowie die einzelnen Mapx.txt (je nach Bedarf...))
(draw.exe und drawmouse.exe sind unabhänig)

--> Alle Programme benötigen die dortigen DLL's!

dbGAMES

Treue Seele

Beiträge: 323

Wohnort: Frankfurt

Beruf: Student

  • Private Nachricht senden

2

14.04.2006, 18:55

da ich selber gerne commander keen gespielt habe hoffe ich dass du irgendwann ein richtig gutes spiel hinbekommst.
wo hast du eigentlich die grafiken her? aus dem spiel kopiert, oder gibts da ne seite im internet? und warum gibt es immer ein scrollbares fenster?

3

14.04.2006, 19:04

Keen ist mein Lieblingsspiel :D

Die Grafiken bekommt man aus dem Spiel über ein gewisses Verfahren heraus... wenn du willst kann ich dir welche geben, ich weiß ja, das du son Spritekünstler bist ;p
Die meisten sind auch so bearbeitet das man sie schon sehr gut verwenden kann.

Das gute ist das es alles Shareware is beim ersten Teil. Hab natürlich trotzdem alle Grafiken ;) --> PN

Scrollbares Fenster ist halt diese Programmiersprache... man kanns wegmachen durch maximieren --> gibt nen Befehl das es gleich maximiert ist. Ich bin grad auf der Suche danach. Einen hatte ich schon gefunden, aber dann stürzt einfach alles ab ^^

Anonymous

unregistriert

4

14.04.2006, 19:05

Keen rulz! Bis auf der letzte Teil, der war ein Drama :(

Aber Daumen hoch! Hau rein ;)

5

14.04.2006, 19:13

Zitat von »"nix da"«

Keen rulz! Bis auf der letzte Teil, der war ein Drama :(

Aber Daumen hoch! Hau rein ;)


Keen Dreams? Ja, der war ein Drama. Falls du aber die 6 meintest, dann droh ich dir hiermit, der war doch genial ;p

Nix Da... könntest du mir vielleicht einen Lösungsansatz geben, wie man diese Animationen ohne Sleepbefehl realisieren kann?

Anonymous

unregistriert

6

14.04.2006, 19:34

DarkRage
Na klar meine ich Dreams ;)

Wie das mit Zeithandling geht findest Du auf meiner Internetseite:
http://www.germangamedev.de/index.php?site=article&id=17
Infos für die Errechnung der Deltazeit sind in der Klasse 'manager'.

Mit der Deltazeit kann man viele feine Dinge anstellen.

Zu Deinem Animationsproblem:
Überlegen wir mal was wir an Daten haben:
- Wir haben eine Animation, mit hmn sagen wir 4 Frames.
- Wir haben für alle Frames der Animation eine selbe Anzeigezeit, die aussagt wann der nächste Frame kommen soll. Sagen wir mal hmn... 250 Millisekunden
- Wir haben nun die maximale Laufzeit der Animation: num_frames * frame_time = 1000 Millisekunden.
- Wir haben die Deltazeit (Zeit seit dem vergangenen Frame in Millisekunden)

Recht alles :)

Das einzigste was wir noch brauchen ist die Möglichkeit zu wissen "Hey, jetzt der nächste Frame - bitte". Dazu merken wir uns einfach die vergangene Zeit seit dem das Objekt existiert, nennen wir es mal passed_time. Dafür müssen wir uns auch merken auf welchem Frame wir grade stehen, sagen wir mit: curr_frame

Jetzt schreibst Du Dir eine Klasse. (Achtung nur alles ausm Kopf gemacht)

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class animation
{
public:
    animation (void) : num_frames_(4), frame_time_(250), passed_time_(0) {}

    void draw (long x, long y, unsigned long delta)
    {
            // Zeitzähler erhöhen

        passed_time_ += delta;

            // Frame ausrechnen den wir jetzt haben:

        curr_frame = passed_time_ / num_frame_;

            // Zeitzähler ordentlich halten ;) Darf also nicht größer als die Maximale Zeit werden

        if (passed_time_ > num_frames * passed_time)
            passed_time_ = num_frames * passed_time;

            // Frame jetzt anzeigen

        blablabla;        
    }
private:
    unsigned long curr_frame_;
    unsigned long num_frames_;
    unsigned long frame_time_;
    unsigned long passed_time_;
};

Easy? Easy! ;)

babelfish

Alter Hase

Beiträge: 1 225

Wohnort: Schweiz

Beruf: Informatiker

  • Private Nachricht senden

7

14.04.2006, 19:47

Ja, die Beispiel-programme sind recht gut gelungen.

Ich fand es beim Jump&Run einfach Schade dass man gar nix machen konnte...
Da habe ich ein wenig mit der Map rumgespielt }> :angel: :sleep:
Da erkennt man auch einige Features die schon drinnen sind ;p

Ich kannte Commander Keen leider nicht,
hab die guten Zeiten wohl verpasst, hatte nur mal schnell ein Level gespielt um zu schauen was das ist,
bin aber doch eher der Super Mario Typ :roll:

naja, mach was aus dem Projekt :)

8

14.04.2006, 20:58

Also erstmal zum Fortschritt:
Pfeiltasten funktionieren (allerdings gehen 2 Pfeiltasten gleichzeitig immernoch nicht.. is einfach nich drin).

Credits werden bald eingebaut (Scrolltext ^^)
Und am Anfang wird noch nen Menü kommen... auch mit ein paar Einstellungen...

<-- Das ist erstmal das was einfach ist und was ich noch kann ^^.

babelfish
Was für Features denn? ^^ Klar kann man was machen... Punkte sammeln *g*.

nix da
Ja, die Daten haben wir alle. Soweit komm ich mit. Auch die Klasse die du hier stehen hast verstehe ich, so hab ichs mir auch überlegt.

Das ganze Problem ist immernoch, wie ich in Oberon rausbekommen soll wieviel Zeit seit dem Anzeigen des Frames vergangen ist.

Mir fehlt im Prinzip sowas hier:

C-/C++-Quelltext

1
2
        // Timer Initialisieren

    oldTime_ = currTime_ = ::timeGetTime(); 


Das einzige was ich gefunden hab für Oberon ist die Systemzeit. Theoretisch könnte ich das jetzt auch so weiter darauf aufbauen... aber die Sekunden sind zu ungenau, ich brauch Millisekunden und möglichst relativ gesehen, also nicht von der Systemzeit... somit weiß ich nicht weiter... auch fehlt (glaub ich) diese Objektorientierung in Oberon. Ich weiß das es Pointer gibt, aber nicht wie man sie verwendet, dazu kommen wir erst noch.

Mhpf ich bin grad echt so auf dem: "Bahnhof...., 5 Minuten Verspätung für den ICE nach Hirnwindung"-Tripp..

Anonymous

unregistriert

9

14.04.2006, 21:32

Tipp: Guck Dir die run-Methode des managers an. Dort wird die Deltazeit errechnet ;)

babelfish

Alter Hase

Beiträge: 1 225

Wohnort: Schweiz

Beruf: Informatiker

  • Private Nachricht senden

10

15.04.2006, 00:01

nunja,
so wie du es abgesperrt hattest konnte man nur springen ;)
musste ja testen ob man noch andere Sachen machen konnte ;p

Werbeanzeige