视觉小说的可绘制和可点击文本

Drawable and Clickable text for Visual Novel

这不是重复的。我尝试过的所有其他解决方案都已过时。

所以先看这张图

我今天在 Java 中用 eclipse 做了那个。 看起来像视觉小说。

重点是我想在屏幕上画一些文字,但不知道如何画。 一开始我只想知道:

  1. 如何在屏幕上绘制文本并更改它
  2. 使某些东西(例如图像或某些文本)可单击以移动到 下一个场景

这是我当前的代码:

package textboxes;

import java.applet.Applet;
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.net.URL;


public class test extends Applet implements Runnable, KeyListener {

private Image Image, Background;
private Image actor1, actor2;
private Image textbox;
private Graphics graphics;
private URL base;
private static testbg bg;

@Override
public void init(){
    setSize(960, 540);
    setBackground(Color.LIGHT_GRAY);
    setFocusable(true);
    Frame frame = (Frame)this.getParent().getParent();
    frame.setTitle("School Scene");
    try{
        base = getDocumentBase();
    }catch(Exception e){};

    //getImages from disk
    Background = getImage(base, "res/background.jpg"); 
    actor1 = getImage(base, "res/actor1.jpg");
    actor2 = getImage(base, "res/actor2.jpg");
    textbox = getImage(base, "res/textbox.jpg");
}

public test(){

}

@Override
public void start(){
    bg = new testbg();
Thread thread = new Thread(this);
thread.start();
}
@Override
public void keyPressed(KeyEvent arg0) {
    // TODO Auto-generated method stub

}

@Override
public void keyReleased(KeyEvent arg0) {
    // TODO Auto-generated method stub

}

@Override
public void keyTyped(KeyEvent arg0) {
    // TODO Auto-generated method stub

}

@Override
public void run() {
    bg.update();
    repaint();
    try{
        Thread.sleep(17);
    }catch(InterruptedException e){
        e.printStackTrace();
    }

}

@Override
public void update(Graphics g){
    if(Image == null){
        Image = createImage(this.getWidth(), this.getHeight());
        graphics = Image.getGraphics();
    }

    graphics.setColor(getBackground());
    graphics.fillRect(0, 0, getWidth(), getHeight());
    graphics.setColor(getForeground());
    paint(graphics);

    g.drawImage(Image, 0, 0, this);
}

@Override
public void paint(Graphics g){
    super.paint(g);

g.drawImage(Background, bg.getBgX(), bg.getBgY(), this);
g.drawImage(actor2, 40, 20, this);
g.drawImage(textbox, 80, 350, this);
}

public static testbg getBg() {
    return bg;
}

}

上面这段代码就是我所说的test.java

如果您想了解背景部分

下面这段代码就是我所说的testbg.java

package textboxes;

public class testbg {

private int bgX, bgY;

public testbg(){
    bgX = 0;
    bgY = 0;
}

public void update(){

}

public int getBgX(){
    return bgX;
}

public int getBgY(){
    return bgY;
}

public void setBgX(int bgX) {
    this.bgX = bgX;
}

public void setBgY(int bgY) {
    this.bgY = bgY;
}

}

Thanks for reading this much till the end...Now so can I know how to do it ??

至于文字,我有两种解决方案,但对于你想要的(以及我对 CG 游戏的了解),我想第一种是最好的。

第一个解决方案是我很久以前在 Whosebug 中找到的一个解决方案(抱歉,我不记得在哪里),其中包括对几个 类 的使用直接在面板中绘制。

private final String message;
private final java.awt.geom.Rectangle2D.Float aboutMessageBounds;
private final AttributedString aboutMessageAttributedString;
private final AttributedCharacterIterator paragraph;


// The LineBreakMeasurer used to line-break the paragraph.
private java.awt.font.LineBreakMeasurer lineMeasurer;
// index of the first character in the paragraph.
private final int paragraphStart;
// index of the first character after the end of the paragraph.
private final int paragraphEnd;

@Override
public void init(){

    (...)

    java.util.Hashtable<TextAttribute, Object> textAtributMap = 
                new java.util.Hashtable<TextAttribute, Object>();

    textAtributMap.put(TextAttribute.FAMILY, "Serif");
    textAtributMap.put(TextAttribute.SIZE, new Float(26.0));
    textAtributMap.put(TextAttribute.JUSTIFICATION, TextAttribute.JUSTIFICATION_FULL );
    textAtributMap.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_DEMIBOLD );
    textAtributMap.put(TextAttribute.LIGATURES, TextAttribute.LIGATURES_ON );

    message = "This is a sample of a message.";

    aboutMessageAttributedString = new AttributedString( aboutMessage, textAtributMap );
    paragraph = aboutMessageAttributedString.getIterator();
    paragraphStart = paragraph.getBeginIndex();
    paragraphEnd = paragraph.getEndIndex();

    (...)

}

@Override
protected void paintComponent( Graphics g ) {
    super.paintComponent( g ); //To change body of generated methods, choose Tools | Templates.

    Graphics2D g2 = (Graphics2D)g.create();
        try {

            g2.setRenderingHint( RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON );

            // Create a new LineBreakMeasurer from the paragraph.
            // It will be cached and re-used.
            if (lineMeasurer == null) {
                FontRenderContext frc = g2.getFontRenderContext();
                lineMeasurer = new java.awt.font.LineBreakMeasurer(paragraph, frc);
            }

            //You can scale it like I did. this part is not part of the code that I found.
            g2.scale( ratio.scaleDx, ratio.scaleDy );

            // Set break width to width of Component.
            //these were the measures I used for a something in a game;
            float breakWidth = 734.0f;
            float drawPosY = 90.0f;
            float posX0 = 30.0f;
            // Set position to the index of the first character in the paragraph.
            lineMeasurer.setPosition(paragraphStart);

            // Get lines until the entire paragraph has been displayed.
            while (lineMeasurer.getPosition() < paragraphEnd) {
                int next = lineMeasurer.nextOffset(breakWidth);

                int limit = next;
                if (limit <= message.length()) {
                    for (int i = lineMeasurer.getPosition(); i < next; ++i) {
                        char c = aboutMessage.charAt(i);
                        if (c == '\n') {
                            limit = i + 1;
                            break;
                        }
                    }
                }

                java.awt.font.TextLayout layout = lineMeasurer.nextLayout( breakWidth, limit, false );
                // Retrieve next layout. A cleverer program would also cache
                // these layouts until the component is re-sized.


                // Compute pen x position. If the paragraph is right-to-left we
                // will align the TextLayouts to the right edge of the panel.
                // Note: this won't occur for the English text in this sample.
                // Note: drawPosX is always where the LEFT of the text is placed.
                float drawPosX = layout.isLeftToRight()
                        ? posX0 : breakWidth - layout.getAdvance();
                // Move y-coordinate by the ascent of the layout.
                drawPosY += layout.getAscent();

                // Draw the TextLayout at (drawPosX, drawPosY).
                layout.draw(g2, drawPosX, drawPosY);

                // Move y-coordinate in preparation for next layout.
                drawPosY += layout.getDescent() + layout.getLeading();
            }

        } 
        finally {
            g2.dispose();
        }
}

至于第二种解决方案,您可以使用 JEditorPane 或 JTextPane。请参阅本课程的 Oracle 教程:

https://docs.oracle.com/javase/tutorial/uiswing/components/editorpane.html

希望我帮到了你。

祝你有愉快的一天。 :)