Hello, this is Hokkaido of students. Basically, I have a little development experience on Android, and the languages I think I can use are Java and C #. Thank you. When I tried to make something like an RPG on Android, I got a little stuck with the method of displaying text character by character on SurfaceView, so I will write it so that I do not forget it. I think there are many mistakes, but please forgive me.
--Ideal for animations, games that require drawing performance, complex graphics, and drawing content that is constantly updated. --It is possible to draw on threads other than the main thread, but be careful about exclusive processing between threads. --Access to the Surface is done via the Surface Holder interface.
Create a class dedicated to graphics and put drawing instructions in it.
Graphics.java
//constructor
public Graphics(int w, int h, SurfaceHolder holder) {
this.holder = holder;
this.holder.setFormat(PixelFormat.RGBA_8888);
this.holder.setFixedSize(w, h);
paint = new Paint();
paint.setAntiAlias(true);
}
public Canvas getCanvas() {
return canvas;
}
//Lock
public void lock() {
canvas = holder.lockCanvas();
if (canvas == null) return;
canvas.translate(originX, originY);
}
//unlock
public void unlock() {
if (canvas == null) return;
holder.unlockCanvasAndPost(canvas);
}
//Specifying the drawing origin
public void setOrigin(int x, int y) {
originX = x;
originY = y;
}
//Get the X coordinate of the drawing origin
public int getOriginX() {
return originX;
}
//Get the Y coordinate of the drawing origin
public int getOriginY() {
return originY;
}
//Color specification
public void setColor(int color) {
paint.setColor(color);
}
//Specify font size
public void setTextSize(int fontSize) {
paint.setTextSize(fontSize);
}
//Get font metrics
public Paint.FontMetrics getFontMetrics() {
return paint.getFontMetrics();
}
//Get character width
public int measureText(String string) {
return (int)paint.measureText(string);
}
//Drawing a filled rectangle
public void fillRect(int x, int y, int w, int h) {
if (canvas == null) return;
paint.setStyle(Paint.Style.FILL);
canvas.drawRect(new Rect(x, y, x+w, y+h), paint);
}
//Bitmap drawing
public void drawBitmap(Bitmap bitmap, int x, int y) {
if (canvas == null) return;
int w = bitmap.getWidth();
int h = bitmap.getHeight();
Rect src = new Rect(0, 0, w, h);
Rect dst = new Rect(x, y, x+w, y+h);
canvas.drawBitmap(bitmap, src, dst, null);
}
//Bitmap drawing
public void drawBitmap(Bitmap bitmap, Rect src, Rect dst) {
if (canvas == null) return;
canvas.drawBitmap(bitmap, src, dst, null);
}
//Drawing a string
public void drawText(String string, int x, int y) {
if (canvas == null) return;
canvas.drawText(string, x, y, paint);
}
Then, create a class that inherits SurfaceView and set it in Activity. (It will be a little longer)
IndexActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new RPGView(this, storyNum));
}
RPGView.java
public RPGView(Activity activity, int story) {
super(activity);
holder = getHolder();
holder.addCallback(this);
//Graphics generation
g = new Graphics(dw, H, holder);
g.setOrigin((dw - W) / 2, 0);
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
thread = null;
}
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
thread = new Thread(this);
thread.start();
}
@Override
public void run() {
while (thread != null) {
//Program main loop Drawing process here
//sleep
key = KEY_NONE;
sleep(200);
}
}
After that, I will write the drawing process in the main loop of the thread. (What are you doing?)
The View is updated every time in the SurfaceView thread, so I added the string one character at a time and it worked.
RPGView.java
//Drawing the dialogue screen
private void talk(String message, Bitmap bitmap, String who) {
int color = Color.rgb(0, 0, 0);
if (bitmap != null) {
g.lock();
g.setColor(color);
g.fillRect(0, 0, W, H);
g.getCanvas().translate(0, 0);
g.fillRect(0, 0, realX, realY);
g.getCanvas().translate((dspW - W) / 2, 0);
g.drawBitmap(bitmap, 0, 0);
g.setColor(Color.rgb(255, 255, 255));
g.fillRect((W - 504) / 2, H - 122, 504, 104);
g.setColor(color);
g.fillRect((W - 500) / 2, H - 120, 500, 100);
//Line breaks for TODO characters! !! !! !!
g.setColor(Color.rgb(255, 255, 255));
g.setTextSize(25);
if (message.length() > 18) {
String message1 = message.substring(0, 18);
String message2 = message.substring(18);
g.drawText(message1, (W - 500) / 2 + 25, 370 - (int) g.getFontMetrics().top);
g.drawText(message2, (W - 500) / 2 + 10, 410 - (int) g.getFontMetrics().top);
} else {
g.drawText(message,
(W - 500) / 2 + 25, 370 - (int) g.getFontMetrics().top);
}
g.unlock();
}
}
If you call this method from the loop and pass the text with one more character ...
RPGView.java
String text = "AIUEO";
if (moji_count == text.length() || moji_count == 9999) {
talk(text, background, null);
moji_count = 9999;
} else {
talk(text.substring(0, moji_count), background, null);
moji_count++;
}
I was able to do it character by character. You can display it at just the right speed by putting it to sleep for a short time.
-Basics of Android Surface View
Recommended Posts