Projekt GlowJump

Autor: Christian Balaguer Jehle, UI08b

Abgabe: 8. Mai 2011

Für das Miniprojekt im Fach Multimedia, habe ich mich vom für Smartphones bekannten Doodle Jump inspirieren lassen. Da es bis jetzt noch keinen Port des Spiels auf Flash gibt, entschied ich mich, das Spielprinzip zu übernehmen und und meine eigenen Grafiken drumrumzubauen.

Ziel des Spiels ist es Mr. Glow mithilfe der Plattformen in die Höhe zu katapultieren. Je höher Mr. Glow springt, desto höher der Highscore. Aber aufgepasst! Nicht jede Plattform verhält sich gleich! Manche katapultieren Mr. Glow in unsägliche Höhe und andere können sein Gewicht nicht tragen und stürzen ein.

Projektbericht

Projektziele

"In diesem Miniprojekt sollen Sie Ihre der Flash- und Action-Script-Grundkenntnisse sowie der Kenntnisse über den Entwurf und Organisation einer MM-Produktion an einem grösseren MMProjekt selbständig anwenden".

Projektorganisation

Bei meinem Flash MiniProjekt habe ich folgende Tools verwendet:

  • Adobe Flash
  • Adobe Flash Builder
  • Adobe Illustrator (Grafiken)
  • Adobe Dreamweaver (Website)
  • Audacity (Sounds)
  • Microsoft Visio (Klassendiagramm)

Spielstruktur

Film

Der Hauptfilm besteht aus einem einzigen leeren Frame, wobei ich Rückblendend sagen muss, dass es besser gewesen wäre 2 Frames zu haben. Im einen alle Grafiken für die Spielauswahl und im anderen dann das Spiel selbst.

Der Movieclip der Plattform beinhaltet alle Grafiken und Animationen für die verschiedenen Plattformen und ist der umfangreichste Movieclip meines Projekts.

Code

Die 4 wichtigsten Klassen sind Main.as als Hauptklasse, die Platform.as, die Player.as und die Globals.as in der alle Spielkonstanten gespeichert sind.

Lösungsansätze

Spielgeschwindigkeit

Die Spielschwierigkeit ist normalerweise Frameraten-abhängig. Ein Spieler mit einem langsamen Computer der die Frames langsamer abarbeitet, hat mehr Zeit zu reagieren. Um dies zu unterbinden und das Spiel Frameraten-unabhängig zu programmieren, habe ich folgenden Code implementiert.

                            private var lastTime:Number;
                            lastTime = new Date().getTime();
                            
                            private function gameLoop(event:Event):void {
                                var now:Number = new Date().getTime();
                                var delta:Number = now - lastTime;
                                lastTime = now;
                            }
                        

Das delta, also die Zeit die zwischen dem Aufruf von gameLoop() vergeht, wird im Code mit den wichtigsten Spielvariablen multipliziert.

  • PLAYER_GRAVITY * delta
  • getCurrentJumpPower() * delta
  • PLAYER_XSPEED * delta
  • PLATFORM_XSPEED * delta

Schwerkraft

Der Spieler startet mit einer Sprungkraft von 0. Bei jedem onEnterFrame-Event werden nun die momentane Sprungkraft und gravity * delta addiert. Das heisst, dass die y-Koordinate zuerst immer grösser wird und sich der Spieler nach unten bewegt. Stösst der Spieler auf eine Plattform wird seine momentane Sprungkraft auf PLAYER_MAX_JUMP_POWER (-0.6) gesetzt. Solange seine Sprungkraft im Minusbereich liegt, bewegt sich der Spieler nach oben. Nachdem von der Minuszahl die Schwerkraft so oft abgezogen wurde, dass sie wieder 0 ist, bleibt der Spieler stehen und fällt wieder runter.

					for each(var player:Player in players) {
						player.setCurrentJumpPower(player.getCurrentJumpPower() + Globals.PLAYER_GRAVITY * delta);
					}
				

Hit-Testing

Um sauberes Hit-Testing durchzuführen, musste ich auf die von Flash verfügbaren Methoden verzichten. Mit hitTestObject ist es möglich, dass ein Objekt das andere überlagert. Für mein Spiel wollte ich aber, dass der spieler exakt auf der Plattform abspringt. Deshalb habe ich das Hit-Testing von Hand durchgeführt.

                        for each(var player:Player in players) {
							var newYPos:Number = player.y + player.getCurrentJumpPower() * delta;
							for each(var platform:Platform in platforms) {
								if(platform.visible && player.x > platform.x - 15 && player.x < platform.x + platform.width + 15 && player.y < platform.y && newYPos > platform.y){
									
									switch(platform.getType()) {
										case Globals.PLATFORM_BOOST:
											newYPos = platform.y;
											player.setCurrentJumpPower(Globals.PLAYER_BOOST_JUMP_POWER);
											break;
										case Globals.PLATFORM_BREAKABLE:
											platform.play();
											break;
										case Globals.PLATFORM_DISAPPEAR:
											newYPos = platform.y;
											player.setCurrentJumpPower(Globals.PLAYER_MAX_JUMP_POWER);
											platform.visible = false;
											break;
										default:
											newYPos = platform.y;
											player.setCurrentJumpPower(Globals.PLAYER_MAX_JUMP_POWER);
											break;
									}
									
								}
							}
						}
                    

In diesem Code-Abschnitt wird die nächste Position die ein Spieler einnehmen wird errechnet und hit-tested. Liegt die zukünftige y-Koordinate eines Spielers innerhalb einer Plattform, wird die y-Koordinate auf die des oberen Rands der Plattform gesetzt. Somit stelle ich sicher, dass der Spieler nie die Plattform überlagert und der Absprung sauber aussieht.

Scrolling

Springt ein Spieler an den oberen Bildschirmrand, muss der Viewport des Spiels mitgescrollt werden. Das Scrolling bezieht sich stets auf den obersten Spieler. Damit ich nicht jede einzelne Plattform einzeln scrollen muss, werden alle zu scrollenden Elemente dem MovieClip gameContainer hinzugefügt. So muss ich beim Scrollen lediglich die y-Koordinate des GameContainers setzen.

Plattformverteilung

Die Verteilung der Plattformen im Spiel geschieht automatisch. Beim ersten Start des Spiels werden 11 Plattformen generiert und dem GameContainer hinzugefügt. 10 davon sind sichtbar. 1 liegt 100px über dem oberen Bildschirmrand und dient als Reserve um ein weiches Scrolling zu garantieren. Hätte ich diese 11. Plattform nicht, würde man während dem Scrollen merken, dass die Plattformen die unten rausfallen, oben in veränderter Form wieder platziert werden. Womit ich schon beim nächsten Schritt wäre: Fällt eine Plattform während dem Scrolling aus dem unteren Bildschirmrand, wird sie in veränderter Form nach oben gesetzt. Hierbei muss aber garantiert sein, dass mindestens jede 3. Plattform erklimmbar ist, da das Spiel sondst nicht mehr erklimmbar ist.

Den ganzen Vorgang der Plattformverteilung habe ich hierzu mit Warscheinlichkeiten gelöst.

					var prob:Number = Math.random();
					if(probability <= 0.7) {
						if(prob <= 0.1) {
							p.setType(Globals.PLATFORM_BOOST);
						} else if(prob <= 0.25) {
							p.setType(Globals.PLATFORM_DISAPPEAR);
						} else if(prob <= 0.4) {
							p.setType(Globals.PLATFORM_BREAKABLE);
						} else if(prob <= 0.6) {
							if(Math.random() <= 0.5) {
								p.setType(Globals.PLATFORM_MOVING_LR);
							} else {
								p.setType(Globals.PLATFORM_MOVING_RL);
							}
						} else if(prob <= 0.8 ){
							p.setType(Globals.PLATFORM_SOLID);
						} else {
							p.visible = false;
						}
						probability += 0.35;
					} else {
						var prob2:Number = Math.random();
						if(prob2 <= 0.7) {
							p.setType(Globals.PLATFORM_SOLID);
						} else {
							if(Math.random() <= 0.5) {
								p.setType(Globals.PLATFORM_MOVING_LR);
							} else {
								p.setType(Globals.PLATFORM_MOVING_RL);
							}
						}
						probability = 0.35;
					}
					

probability ist bei Spielbeginn 0.35. Da ich nach der ersten if-Abfrage 0.35 dazuzähle, kann diese Abfrage maximal 2 Mal ausgeführt werden, was so viel heisst, dass 2 unerklimmbare Plattformen gezeichnet werden dürfen, biss der Code dann in den else-Teil fällt, wo eine solide oder bewegliche Plattform gezeichnet wird.

Kurze Zusammenfassing: Jede 3. Plattform ist entweder solid oder beweglich. Dazwischen sind alle Plattformtype oder keine Plattform erlaubt.

Möglichkeiten zur Erweiterung von GlowJump

  • Weitere Plattformen
  • Gegnern ausweichen
  • Gegner abschiessen
  • Highscore History
  • Hintergrund-Animation
  • Steigender Schwierigkeitsgrad
  • Collision-Detection bei den Spielern (2P)

Quellen

Einzig die Sound-Effekte und Loops wurden nicht von mir erstellt, sondern habe ich von Flashkit.com, wobei ich Pausen am Trackanfang und die Lautstärke mit Audacity normalisiert habe.

Das Spiel