Spieleentwicklung für Android 101

  • Antworten:33
  • OffenNicht stickyNicht beantwortet

30.11.2010 20:03:57 via Website

Hi Dominic,

in letzter Zeit habe ich mich nicht mehr um OpenGL gekümmert. Das ist mir derzeit doch ein bisschen zu mächtig.
Habe mal deinen Vorschlag versucht. Hat aber nicht geklappt.

Gruß
Duckemai

27.01.2011 09:37:38 via Website

Schaut gut aus. Habs mir mal ausgedruckt für in den Zug.

Hab noch keinen Plan von der Programmiersprache die Andorid nutzt aber das wird schon. Code zur Zeit in PHP/JS etc. kenn mich auch ein wenig mit C# aus. MIt 3D modelling auch und hab selbst schon mit XNA mal n Pong gemacht und sonst nbissl über das thema gelesen. Ich denke, dass soltle ich packen. ^^

Hab auch schon ne Idee die ich umsetzen will. Wird n kleiens 2D Spiel. Werd das mal parallel machen zum Tutorial. :P

— geändert am 27.01.2011 09:38:23

Aktuelle Artikel aus unserem Magazin

10.02.2011 18:53:26 via Website

Hallo Mario,
ich finde den Artikel top, habe ihn heute erst entdeckt.
Werde mich morgen mal damit beschäftigen.
Möchte gerne ein eigenes Spiel für Android schreiben
und mir sicherlich auch einmal dein Buch ansehen.

Viele Grüße
N.A.

10.03.2011 19:52:22 via Website

Hi Leute,

der Artikel ist jetzt schon knapp ein Jahr alt. Dementsprechend hab ich quasi zur Feier mal über den SVN Stand geschaut und alle kleinen und größeren Bugs behoben und auf verschiedenen Geräten getestet. Das Dingens sollte jetzt wie erwartet tun. Also einfach aktuellen SVN Stand saugen und loslegen.

Danke auch nochmal an Antonia die den Artikel geradegebogen hat. <3 Antonia!

Frage ans AndroidPit Team: wisst ihr was für einen Traffic der Artikel generiert? Würd mich zwecks Statistik interessieren.

Ciao,
Mario

12.01.2012 22:48:50 via Website

Hallo,

zu allererst möchte ich Mario für dieses gelungene Tutorial Danken.
Du hast Dir damit echt viel Arbeit gemacht und hast Dir auch viel Mühe gegeben - Hut ab -_-

Ich habe den Quellcode runtergeladen und nach Eclipse importiert.
Leider bekomme ich 60 Fehler angezeigt. (Siehe Unten)

Die Fehler lassen sich in 2 Kategorien aufteilen.
1. Solche bei denen vorgeschlagen wird, @Override zu entfernen
2. Bei diesen kann man @Override entfernen oder eine entsprechende Methode in der Super-Klasse anlegen.

Wo es ging habe ich eine (leere) Methode in der Super-Klasse angelegt. Bei den anderen habe ich @Override entfernt.
Damit lässt sich das Projekt kompilieren. Wenn ich es im Simulator sarten will, dreht sich die Anzeige in Querformat aber sonst passiert nicht weiter.

Was habe ich falsch gemacht? Anscheinend hat niemand sonst soein Problem breichtet.

Vielen Dank,
Thorsten


The method dispose() of type GameOverScreen must override a superclass method GameOverScreen.java /android-gamedev/src/com/badlogic/gamedev/spaceinvaders/screens line 131 Java Problem
The method dispose() of type StartScreen must override a superclass method StartScreen.java /android-gamedev/src/com/badlogic/gamedev/spaceinvaders/screens line 130 Java Problem
The method explosion() of type GameLoop must override a superclass method GameLoop.java /android-gamedev/src/com/badlogic/gamedev/spaceinvaders/screens line 77 Java Problem
The method isDone() of type GameOverScreen must override a superclass method GameOverScreen.java /android-gamedev/src/com/badlogic/gamedev/spaceinvaders/screens line 83 Java Problem
The method isDone() of type StartScreen must override a superclass method StartScreen.java /android-gamedev/src/com/badlogic/gamedev/spaceinvaders/screens line 82 Java Problem
The method mainLoopIteration(GameActivity, GL10) of type BackgroundSample must override a superclass method BackgroundSample.java /android-gamedev/src/com/badlogic/gamedev/samples line 55 Java Problem
The method mainLoopIteration(GameActivity, GL10) of type CameraSample must override a superclass method CameraSample.java /android-gamedev/src/com/badlogic/gamedev/samples line 45 Java Problem
The method mainLoopIteration(GameActivity, GL10) of type ColorSample must override a superclass method ColorSample.java /android-gamedev/src/com/badlogic/gamedev/samples line 48 Java Problem
The method mainLoopIteration(GameActivity, GL10) of type ColorSample2 must override a superclass method ColorSample2.java /android-gamedev/src/com/badlogic/gamedev/samples line 69 Java Problem
The method mainLoopIteration(GameActivity, GL10) of type InputSample must override a superclass method InputSample.java /android-gamedev/src/com/badlogic/gamedev/samples line 20 Java Problem
The method mainLoopIteration(GameActivity, GL10) of type LightSample must override a superclass method LightSample.java /android-gamedev/src/com/badlogic/gamedev/samples line 54 Java Problem
The method mainLoopIteration(GameActivity, GL10) of type MD2Sample must override a superclass method MD2Sample.java /android-gamedev/src/com/badlogic/gamedev/samples line 56 Java Problem
The method mainLoopIteration(GameActivity, GL10) of type MeshSample must override a superclass method MeshSample.java /android-gamedev/src/com/badlogic/gamedev/samples line 42 Java Problem
The method mainLoopIteration(GameActivity, GL10) of type MultipleObjectsSample must override a superclass method MultipleObjectsSample.java /android-gamedev/src/com/badlogic/gamedev/samples line 67 Java Problem
The method mainLoopIteration(GameActivity, GL10) of type MusicSample must override a superclass method MusicSample.java /android-gamedev/src/com/badlogic/gamedev/samples line 49 Java Problem
The method mainLoopIteration(GameActivity, GL10) of type ObjSample must override a superclass method ObjSample.java /android-gamedev/src/com/badlogic/gamedev/samples line 54 Java Problem
The method mainLoopIteration(GameActivity, GL10) of type OrthoSample must override a superclass method OrthoSample.java /android-gamedev/src/com/badlogic/gamedev/samples line 33 Java Problem
The method mainLoopIteration(GameActivity, GL10) of type PerspectiveSample must override a superclass method PerspectiveSample.java /android-gamedev/src/com/badlogic/gamedev/samples line 45 Java Problem
The method mainLoopIteration(GameActivity, GL10) of type SoundSample must override a superclass method SoundSample.java /android-gamedev/src/com/badlogic/gamedev/samples line 47 Java Problem
The method mainLoopIteration(GameActivity, GL10) of type SpaceInvaders must override a superclass method SpaceInvaders.java /android-gamedev/src/com/badlogic/gamedev/spaceinvaders line 90 Java Problem
The method mainLoopIteration(GameActivity, GL10) of type TextSample must override a superclass method TextSample.java /android-gamedev/src/com/badlogic/gamedev/samples line 34 Java Problem
The method mainLoopIteration(GameActivity, GL10) of type TextureMeshSample must override a superclass method TextureMeshSample.java /android-gamedev/src/com/badlogic/gamedev/samples line 56 Java Problem
The method mainLoopIteration(GameActivity, GL10) of type TextureSample must override a superclass method TextureSample.java /android-gamedev/src/com/badlogic/gamedev/samples line 90 Java Problem
The method mainLoopIteration(GameActivity, GL10) of type TransformationSample must override a superclass method TransformationSample.java /android-gamedev/src/com/badlogic/gamedev/samples line 54 Java Problem
The method mainLoopIteration(GameActivity, GL10) of type TriangleSample must override a superclass method TriangleSample.java /android-gamedev/src/com/badlogic/gamedev/samples line 55 Java Problem
The method mainLoopIteration(GameActivity, GL10) of type ZBufferSample must override a superclass method ZBufferSample.java /android-gamedev/src/com/badlogic/gamedev/samples line 45 Java Problem
The method onAccuracyChanged(Sensor, int) of type GameActivity must override a superclass method GameActivity.java /android-gamedev/src/com/badlogic/gamedev/tools line 262 Java Problem
The method onDrawFrame(GL10) of type GameActivity must override a superclass method GameActivity.java /android-gamedev/src/com/badlogic/gamedev/tools line 173 Java Problem
The method onSensorChanged(SensorEvent) of type GameActivity must override a superclass method GameActivity.java /android-gamedev/src/com/badlogic/gamedev/tools line 272 Java Problem
The method onSurfaceChanged(GL10, int, int) of type GameActivity must override a superclass method GameActivity.java /android-gamedev/src/com/badlogic/gamedev/tools line 187 Java Problem
The method onSurfaceCreated(GL10, EGLConfig) of type GameActivity must override a superclass method GameActivity.java /android-gamedev/src/com/badlogic/gamedev/tools line 197 Java Problem
The method onTouch(View, MotionEvent) of type GameActivity must override a superclass method GameActivity.java /android-gamedev/src/com/badlogic/gamedev/tools line 232 Java Problem
The method render(GL10, GameActivity) of type GameLoop must override a superclass method GameLoop.java /android-gamedev/src/com/badlogic/gamedev/spaceinvaders/screens line 41 Java Problem
The method render(GL10, GameActivity) of type GameOverScreen must override a superclass method GameOverScreen.java /android-gamedev/src/com/badlogic/gamedev/spaceinvaders/screens line 96 Java Problem
The method render(GL10, GameActivity) of type StartScreen must override a superclass method StartScreen.java /android-gamedev/src/com/badlogic/gamedev/spaceinvaders/screens line 95 Java Problem
The method setup(GameActivity, GL10) of type BackgroundSample must override a superclass method BackgroundSample.java /android-gamedev/src/com/badlogic/gamedev/samples line 30 Java Problem
The method setup(GameActivity, GL10) of type CameraSample must override a superclass method CameraSample.java /android-gamedev/src/com/badlogic/gamedev/samples line 24 Java Problem
The method setup(GameActivity, GL10) of type ColorSample must override a superclass method ColorSample.java /android-gamedev/src/com/badlogic/gamedev/samples line 26 Java Problem
The method setup(GameActivity, GL10) of type ColorSample2 must override a superclass method ColorSample2.java /android-gamedev/src/com/badlogic/gamedev/samples line 26 Java Problem
The method setup(GameActivity, GL10) of type InputSample must override a superclass method InputSample.java /android-gamedev/src/com/badlogic/gamedev/samples line 26 Java Problem
The method setup(GameActivity, GL10) of type LightSample must override a superclass method LightSample.java /android-gamedev/src/com/badlogic/gamedev/samples line 24 Java Problem
The method setup(GameActivity, GL10) of type MD2Sample must override a superclass method MD2Sample.java /android-gamedev/src/com/badlogic/gamedev/samples line 34 Java Problem
The method setup(GameActivity, GL10) of type MeshSample must override a superclass method MeshSample.java /android-gamedev/src/com/badlogic/gamedev/samples line 29 Java Problem
The method setup(GameActivity, GL10) of type MultipleObjectsSample must override a superclass method MultipleObjectsSample.java /android-gamedev/src/com/badlogic/gamedev/samples line 41 Java Problem
The method setup(GameActivity, GL10) of type MusicSample must override a superclass method MusicSample.java /android-gamedev/src/com/badlogic/gamedev/samples line 31 Java Problem
The method setup(GameActivity, GL10) of type ObjSample must override a superclass method ObjSample.java /android-gamedev/src/com/badlogic/gamedev/samples line 34 Java Problem
The method setup(GameActivity, GL10) of type OrthoSample must override a superclass method OrthoSample.java /android-gamedev/src/com/badlogic/gamedev/samples line 24 Java Problem
The method setup(GameActivity, GL10) of type PerspectiveSample must override a superclass method PerspectiveSample.java /android-gamedev/src/com/badlogic/gamedev/samples line 24 Java Problem
The method setup(GameActivity, GL10) of type SoundSample must override a superclass method SoundSample.java /android-gamedev/src/com/badlogic/gamedev/samples line 29 Java Problem
The method setup(GameActivity, GL10) of type SpaceInvaders must override a superclass method SpaceInvaders.java /android-gamedev/src/com/badlogic/gamedev/spaceinvaders line 72 Java Problem
The method setup(GameActivity, GL10) of type TextSample must override a superclass method TextSample.java /android-gamedev/src/com/badlogic/gamedev/samples line 26 Java Problem
The method setup(GameActivity, GL10) of type TextureMeshSample must override a superclass method TextureMeshSample.java /android-gamedev/src/com/badlogic/gamedev/samples line 30 Java Problem
The method setup(GameActivity, GL10) of type TextureSample must override a superclass method TextureSample.java /android-gamedev/src/com/badlogic/gamedev/samples line 33 Java Problem
The method setup(GameActivity, GL10) of type TransformationSample must override a superclass method TransformationSample.java /android-gamedev/src/com/badlogic/gamedev/samples line 24 Java Problem
The method setup(GameActivity, GL10) of type TriangleSample must override a superclass method TriangleSample.java /android-gamedev/src/com/badlogic/gamedev/samples line 33 Java Problem
The method setup(GameActivity, GL10) of type ZBufferSample must override a superclass method ZBufferSample.java /android-gamedev/src/com/badlogic/gamedev/samples line 24 Java Problem
The method shot() of type GameLoop must override a superclass method GameLoop.java /android-gamedev/src/com/badlogic/gamedev/spaceinvaders/screens line 83 Java Problem
The method update(GameActivity) of type GameLoop must override a superclass method GameLoop.java /android-gamedev/src/com/badlogic/gamedev/spaceinvaders/screens line 47 Java Problem
The method update(GameActivity) of type GameOverScreen must override a superclass method GameOverScreen.java /android-gamedev/src/com/badlogic/gamedev/spaceinvaders/screens line 89 Java Problem
The method update(GameActivity) of type StartScreen must override a superclass method StartScreen.java /android-gamedev/src/com/badlogic/gamedev/spaceinvaders/screens line 88 Java Problem

29.04.2012 05:21:09 via Website

Die @Override-Fehler bekommst du weg indem du mit Java6 kompilierst und auch das Compliance-Level des Compilers in Eclipse auf Version 1.6 stellst. (Windows > Preferences > Java > Compiler)

— geändert am 29.04.2012 05:21:37

23.06.2012 18:15:38 via Website

Hallo und Danke für das Tutorial,

nachdem ich mich eingelesen habe, habe ich versucht das TriangleSample nachzubauen.
Ich bekomme aber nur einen schwarzen Bildschirm angezeigt. Auch beim Verwenden der
Sourcen aus dem Tutorial tut sich nichts.
Hat jemand einen Denkanstoß für mich?

LG Chris

28.08.2012 23:45:03 via Website

Hallo, ich melde mich auch mal zu Wort.
Ich studiere informatik im 3. Semester, mache Android-programmierung aus Spaß nebenbei.
Habe viel mit Flash spiele programmiert, in java nur kleinkram gemacht aber auch schonmal mit XNA Gamestudio (C++) n kleines Spiel geschrieben, daher wusste ich auch was Draw-calls sind und wie man mit der mainloopiteration umgeht.
In Flash war das ganze so oder so frame-basiert, allerdings musste man sich um das zeichnen von objekten keinen Kopf machen, man erstellt sie in flash, wenn man es ausführt sind sie auf dem Bildschirm. Jedes grafische objekt kann man wie ein java-objekt ansprechen und auf attribute wie koordinaten, alpha, drehung zugreifen und diese manipulieren. Für spiele eine sehr einfache sprache, aber auch ziemlich unperformant.
Genug von mir.

Ich finde dein Tutorial sehr gut, für Android-einsteiger die Java-grund- oder erweiterte Kenntnisse haben ist es optimal.

Es gibt noch immer ein paar kleine Schreibfehler in Tutorial und im Code, die man aber gerne überliest, da es um den Inhalt geht.
Allerdings folgendes :
du hast manchmal Textur-bla geschrieben, statt Texture-bla. Im Code ist es nun richtig, aber wenn man Codestücke aus dem Tutorial selbst entnimmt, gibt es hier noch Fehler, aber nicht weiter schlimm, da kommt man schon drauf.

Einzig wirklich störend :
[[http://code.google.com/p/android-gamedev/source/browse/trunk/src/com/badlogic/gamedev/samples/TexturSample.java http://code.google.com/p/android-gamedev/source/browse/trunk/src/com/badlogic/gamedev/samples/TexturSample.java]
- hier wurde der Dateiname verbessert auf "texture" aber die links verweisen auf "textur" - man hat erst den Eindruck die Datei wurde gelöscht.
Da die Leser deines Tutorials alles programmierer sein werden, werden die meisten darauf kommen, ein "e" in den Link einzufügen oder im SVN manuell rumzuklicken...
Wäre trotzdem hilfreich das auszubessern.
Mir ist außerdem aufgefallen, dass das Spiel crasht wenn man die Invaders so nah kommen lässt, dass man kollidiert. Invader und Schiff explodieren, danach stürzt das Spiel ab. Da wird wohl eine Exception nicht abgefangen. Falls du noch eine 1.2 des Spiels rausbringst, wäre das eine Kleinigkeit die man ausbessern könnte.

Ich möchte nicht meckern, im Gegenteil, ich will nur nett gemeinte, hilfreiche Tipps geben. Nochmal : Sehr gute Arbeit bei dem Tutorial.

Nun zu meinem Anliegen : Du hast alles im Einzelnen erklärt und dann nochmal am Beispiel von Droid-Invaders, sehr gut verständlich.
Falls einem Droid-Invaders auf einen Schlag zu viel Information ist liest man alles Stück für Stück und kann auch alles im einzelnen ausprobieren.

Ich habe mit 2 Dreiecken angefangen die die Spieler präsentieren (schreibe ein Bluetooth-multiplayer spiel, bei dem jeder einen Spieler bewegt, aber beide personen beide spieler sehen, wie bei nem Fight-spiel auf ner Konsole ) und nun Meshes (2D) und Texturen geladen, funktioniert prächtig, transparenz in .png-bildern habe ich auch hinbekommen.

Ich nutze die USB-Debug funktion, dann kann ich auf dem Handy testen und trotztdem die Logcat einsehen, die ich vorher nur im Emulator sehen konnte. Trotdem wäre irgendwann text wichtig, fps nicht überlebensnotwendig, aber Spielernamen etc (dynamisch, je nachdem wer connected, daher kann ich die namen nicht direkt als textur speichern und aus assets laden...) würde ich schon gern einfügen.

Nun hast du ein Textexample geschrieben, funktioniert wunderbar, aber wenn ich das zusammen mit den Render-funktionen meiner spieler-meshes (da liegen dann texturen drauf) oder auch nur die meiner Dreiecke verwende, sehe ich nichts mehr.

Ich kann in meiner Klasse den Textexamplecode einfügen, wenn es das einzige ist was ich rendere geht es, wenn ich text UND spieler rendere geht es nicht, ich sehe dann gar nichts. Nur text oder nur spieler würden mich auf Z-order tippen lassen, aber sobald ich beides rendere habe ich einen schwarzen bildschirm.
Genauer habe ich folgendes beobachtet: Ich starte die app, die Spieler flackern ca 1 Frame auf und dann ist es schwarz.

Ich bin nun kurz davor (da texturen prima klappen) den Europäischen zeichensatz in kleine meshes, bestehend aus 2 Dreiecken die ein Viereck bilden (hast du ja im Beitrag über Texte/Glyphen erklärt) zu teilen und glyphen draus zu machen. wenn ich dann "HAHA" ausgeben will "puzzele" ich mit 4 Glyphen nebeneinander...

Aber so in etwa hast du das, wie es scheint, in der Texture-klasse gemacht. (Ich habe übrigens bemerkt, dass du keine neue Textur erstellt, wenn setText einen Text setzen will, der schonmal gesetzt wurde, falls man mache ausgaben öfter macht. Das spart performance, hier sieht man wieder, dass dein Tutorial durch und durch sehr sauber ist. Gute Arbeit!)

Nun tippe ich, dass du beim aufruf von Text.render() irgendeinen state der openGL-maschine verstellst, und nicht zurückänderst.
Nur so kann ICH mir erklären, dass ich Spielertextur 1 Frame aufleuchtet und dann verschwindet.

Warum dann nichtmal der Text sichtbar ist, verstehe ich allerdings nicht.

Ich habe sehr viel in deinem Tutorial gelernt, allerdings komme ich hier echt nicht weiter. In Droid-Invaders benutzt du gar keinen Text, wenn ich es richitig gesehen habe, du hast eine Game-over textur und sonst keinen Text.

...Wobei, jetzt fällt mir ein, dass ich beim Probespielen gesehen habe, dass am Ende der Score angezeigt wird... Ich werde mir das nochmal ansehen...

Vielleicht antwortest du ja auch, aber bevor du das tust, möchte ich DIR eine Frage beantworten.

Du hast nach Traffic gefragt, ich sehe hier allerdings keine Antwort.

Wie oft dieser Thread aufgerufen wurde, weis ich nicht, aber aus der Download-sektion bei http://code.google.com kann man entnehmen, dass:
android-gamedev.apk - 1363 mal runtergeladen wurde.
android-gamedev-1.1.apk - 4495 mal runtergeladen wurde.

Daran kannst du abschätzen wie populär dein Tutorial ist :)

Alles in Allem möchte ich nochmal ein Lob aussprechen. Ich fänd aber ein Beispiel "Wie render ich Text zusammen mit anderen Objekten wie Meshes" ergänzend zum Text-example sehr gut. Vielleicht kann ich das auch Droid-invaders entnehmen, aber vielleicht geht es ja mehreren wie mir.

Mit freundlichen Grüßen

— geändert am 29.08.2012 08:41:00

11.09.2012 23:24:17 via Website

Da ist ein kleiner Fehler in der Font-Klasse.

Im TextSample wird die Kamera verschoben, sodass der Text mittig zu sehen ist.

Die von Herrn Zechner geschriebene Funktion setPosition(x,y) funktioniert nicht ganz.

Genaugenommen liegt der Fehler in rebuild(), hier werden alle Ecken der 2 Dreiecke
(die zusammen das Viereck der glyphe ergeben) um posX und posY verschoben, allerdings nicht die letzte Ecke.

Verwendet man setPosition() verzerrt sich immer eines der 2 Dreiecke, da eine Ecke auf der Grundposition hängen bleibt.
Und das nunmal bei jeder glyphe, was dann so aussieht:


zur Lösung einfach in der Font-klasse bei dem letzten "Vertex" Aufruf in der Rebuild() funktion die Stelle "y" auf "posY + y" ändern.

Zur besseren Erklärung, siehe Bild: (Hier seht ihr den Codeausschnitt aus Font.java, aus der Rebuild() Funktion.)
Bild

der richtige Font-code sieht so aus:
[quote][code]package Your.Package;

import java.util.HashMap;

import javax.microedition.khronos.opengles.GL10;

import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.Paint.FontMetrics;
import android.graphics.Paint.Style;
import superStressFighter.core.Mesh.PrimitiveType;
import superStressFighter.core.Texture.TextureFilter;
import superStressFighter.core.Texture.TextureWrap;


public class Font
{
public class Rectangle
{
public float x;
public float y;
public float width;
public float height;

public Rectangle( )
{
x = 0;
y = 0;
width = 0;
height = 0;
}

public Rectangle( float x, float y, float width, float height )
{
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
}


/**
* A FontStyle defines the style of a font
* @author mzechner
*
*/
public enum FontStyle
{
Plain,
Bold,
Italic,
BoldItalic
}

/** glyph hashmap **/
private final HashMap<Character, Glyph> glyphs = new HashMap<Character, Glyph>( );
/** current position in glyph texture to write the next glyph to **/
private int glyphX = 0;
private int glyphY = 0;
private Typeface font;
private Paint paint;
private FontMetrics metrics;
private final Texture texture;

public Font(GL10 gl, String fontName, int size, FontStyle style)
{
this.texture = new Texture( gl, 256, 256, TextureFilter.Nearest, TextureFilter.Nearest, TextureWrap.ClampToEdge, TextureWrap.ClampToEdge );
font = Typeface.create( fontName, getFontStyle( style ) );
paint = new Paint( );
paint.setTypeface(font);
paint.setTextSize(size);
paint.setAntiAlias(false);
metrics = paint.getFontMetrics();
}

public Font(GL10 gl, AssetManager assets, String file, int size, FontStyle style)
{
this.texture = new Texture( gl, 256, 256, TextureFilter.Nearest, TextureFilter.Nearest, TextureWrap.ClampToEdge, TextureWrap.ClampToEdge );
font = Typeface.createFromAsset( assets, file );
paint = new Paint( );
paint.setTypeface(font);
paint.setTextSize(size);
paint.setAntiAlias(false);
metrics = paint.getFontMetrics();
}

private int getFontStyle( FontStyle style )
{
if( style == FontStyle.Bold )
return Typeface.BOLD;
if( style == FontStyle.BoldItalic )
return Typeface.BOLD_ITALIC;
if( style == FontStyle.Italic )
return Typeface.ITALIC;
if( style == FontStyle.Plain )
return Typeface.NORMAL;

return Typeface.NORMAL;
}

public int getGlyphAdvance(char character) {
float[] width = new float[1];
paint.getTextWidths( "" + character, width );
return (int)(Math.ceil(width[0]));
}

public Object getGlyphBitmap(char character) {
Rect rect = new Rect();
paint.getTextBounds( "" + character, 0, 1, rect );
Bitmap bitmap = Bitmap.createBitmap( rect.width()==0?1:rect.width() + 5, getLineHeight(), Bitmap.Config.ARGB_8888 );
Canvas g = new Canvas( bitmap );
paint.setColor(0x00000000);
paint.setStyle(Style.FILL);
g.drawRect( new Rect( 0, 0, rect.width() + 5, getLineHeight()), paint);
paint.setColor(0xFFFFFFFF);
g.drawText( "" + character, 0, -metrics.ascent, paint );
return bitmap;
}

public int getLineGap() {
return (int)(Math.ceil(metrics.leading));
}

public int getLineHeight() {
return (int)Math.ceil(Math.abs(metrics.ascent) + Math.abs(metrics.descent));
}

public int getStringWidth(String text)
{
Rect rect = new Rect();
paint.getTextBounds(text, 0, text.length(), rect);
return rect.width();
}

Rect tmpRect = new Rect();
public void getGlyphBounds(char character, Rectangle rect) {
paint.getTextBounds( "" + character, 0, 1, tmpRect );
rect.width = tmpRect.width() + 5;
rect.height = getLineHeight();
}

/**
* Creates a new text run
* @return The new text run
*/
public Text newText( GL10 gl )
{
return new Text(gl);
}

/**
* @return The glyph texture
*/
protected Texture getTexture( )
{
return texture;
}

/**
* Returns the glyph for the given character
* @param character The character
* @return The glyph of the character
*/
protected Glyph getGlyph( char character )
{
Glyph glyph = glyphs.get(character);
if( glyph == null )
{
glyph = createGlyph(character);
glyphs.put( character, glyph );
}
return glyph;
}

private Glyph createGlyph( char character )
{
Object bitmap = getGlyphBitmap( character );
Rectangle rect = new Rectangle( );
getGlyphBounds( character, rect );

if( glyphX + rect.width >= 256)
{
glyphX = 0;
glyphY += getLineGap() + getLineHeight();
}

texture.draw( bitmap, glyphX, glyphY );

Glyph glyph = new Glyph( getGlyphAdvance( character ), (int)rect.width, (int)rect.height, glyphX / 256.0f, glyphY / 256.0f, rect.width / 256.0f, rect.height / 256.0f );
glyphX += rect.width;
return glyph;
}


private class Glyph
{
public int advance;
public int width;
@SuppressWarnings("unused")
public int height;
public float u;
public float v;
public float uWidth;
public float vHeight;

public Glyph( int advance, int width, int height, float u, float v, float uWidth, float vHeight )
{
this.advance = advance;
this.width = width;
this.height = height;
this.u = u;
this.v = v;
this.uWidth = uWidth;
this.vHeight = vHeight;
}
}

/**
* A textrun is a mesh that holds the glyphs
* of the given string formated to fit the
* rectangle and alignment.
*
* @author mzechner
*
*/
public class Text
{
private GL10 gl;
private Mesh mesh;
private String text = "";
private int width;
private int height;
private HorizontalAlign hAlign;
private VerticalAlign vAlign;
@SuppressWarnings("unused")
private boolean wordWrap = false;
private String[] lines;
private int[] widths;
private float posX, posY;

protected Text( GL10 gl )
{
this.gl = gl;
}

public void setTextArea( int width, int height )
{
this.width = width;
this.height = height;
}

public void setHorizontalAlign( HorizontalAlign hAlign )
{
this.hAlign = hAlign;
}

public void setVerticalAlign( VerticalAlign vAlign )
{
this.vAlign = vAlign;
}

public void setText( String text )
{
if( this.text.equals( text ) )
return;

if( text == null )
text = "";

this.text = text;
this.lines = text.split( "\n" );
this.widths = new int[lines.length];
for( int i = 0; i < lines.length; i++ )
widths[i] = getStringWidth( lines[i] );
rebuild( );
}

public void setPosition( float x, float y )
{
posX = x;
posY = y;
rebuild( );
}

private void rebuild( )
{
if( mesh == null )
mesh = new Mesh( gl, 6 * text.length(), false, true, false );

if( mesh.getMaximumVertices() / 6 < text.length() )
{
mesh = new Mesh( gl, 6 * text.length(), false, true, false );
}

mesh.reset();
int lineHeight = getLineHeight();
for( int i = 0; i < lines.length; i++ )
{
String line = lines[i];
int x = 0;
int y = height;

if( hAlign == HorizontalAlign.Left )
x = 0;
if( hAlign == HorizontalAlign.Center )
x = width / 2 - widths[i] / 2;
if( hAlign == HorizontalAlign.Right )
x = width - widths[i];

if( vAlign == VerticalAlign.Top )
y = height;
if( vAlign == VerticalAlign.Center )
y = height / 2 + lines.length * (getLineHeight() + getLineGap()) / 2;
if( vAlign == VerticalAlign.Bottom )
y = lines.length * (getLineHeight() + getLineGap());

y -= i * (getLineHeight() + getLineGap());

for( int j = 0; j < line.length(); j++ )
{
Glyph glyph = getGlyph( line.charAt(j) );
mesh.texCoord( glyph.u, glyph.v );
mesh.vertex( posX + x, posY + y, 0 );
mesh.texCoord( glyph.u + glyph.uWidth, glyph.v );
mesh.vertex( posX + x + glyph.width, posY + y, 0 );
mesh.texCoord( glyph.u + glyph.uWidth, glyph.v + glyph.vHeight );
mesh.vertex( posX + x + glyph.width, posY + y - lineHeight, 0 );
mesh.texCoord( glyph.u + glyph.uWidth, glyph.v + glyph.vHeight );
mesh.vertex( posX + x + glyph.width, posY + y - lineHeight, 0 );
mesh.texCoord( glyph.u, glyph.v + glyph.vHeight );
mesh.vertex( posX + x, posY + y - lineHeight, 0 );
mesh.texCoord( glyph.u, glyph.v );
mesh.vertex( posX + x, posY + y, 0 );
x += glyph.advance;
}
}
}

public void render( )
{
if( mesh == null ){
return;
}

texture.bind();
mesh.render(PrimitiveType.Triangles);
}

public void dispose( )
{
if( mesh != null )
mesh.dispose();
}
}

/**
* Horizontal text alignement
* @author mzechner
*
*/
public enum HorizontalAlign
{
Left,
Center,
Right
}

/**
* Vertical text alignement
* @author mzechner
*/
public enum VerticalAlign
{
Top,
Center,
Bottom
}

public void dispose() {
texture.dispose();
}
}[/code][/quote]


Das mit dem Text habe ich jetzt nämlich hinbekommen, da ich mich mehr mit GLU.Ortho2D ausseinandergesetzt habe, die Koordinaten waren dann anders und so musste ich eh einiges ändern, nun geht es. :)

mit freundlichen Grüßen

— geändert am 11.09.2012 23:27:54

17.07.2013 20:07:07 via Website

Ein Thread über Spieleentwicklung für Android und niergendwo wird die "Unity 3d"-Engine erwähnt?
Sie ermöglicht es nicht nur sein Spiel für Android zu entwickeln, sondern auch für iOS, PC, Linux, etc.

— geändert am 17.07.2013 20:07:39

02.02.2014 08:51:32 via Website

Tutorial: Spielentwicklung 101

Zunächst einmal vielen Dank für dieses gute Tut!
Du beschreibst darin Deine 10jährige Erfahrung mit der Erstellung kleinerer und größerer Spiele. Ich überlege ernsthaft App-Games zu produzieren. Die Voraussetzungen bzw. Programmiererfahrung habe ich. Ich würde gerne wissen, ob damit auch seinen Lebensunterhalt verdienen kann?

Schönen Gruß?