📄 funscroll.java
字号:
}
}
/**
* FunScrollAnimatedText - FunScroll Animated text class
*/
class FunScrollAnimatedText
{
// states:
static final int START = 0; // start sequence
static final int SHOW = 1; // show sequence
static final int END = 2; // end sequence
static final int DONE = 3; // done sequence
int state = START; // animate state
FunScroll appl; // FunScroll applet
FunScrollTextAttr attr; // attributes
char chars[]; // the characters
int noOfChars; // number of characters
int noOfLines = 1; // number of lines
int xPos[]; // the x positions
int yPos[]; // the y positions
boolean visible[]; // flags set to true if character visible
int delayCount = 0; // used to delay for a while
int width; // the applet width
int height; // the applet height
int textHeight; // text height
int lineHeight; // text line height
Color bg; // background color
Color fg; // foreground color
Font font; // font
int maxWidth; // max width
int sinDegree; // used for sin-wave text
int xStart; // starting X pos
int yStart; // starting Y pos
int dx; // x distance to move
int dy; // y distance to move
public FunScrollAnimatedText(FunScroll appl, String line,
Font font, Color fg, Color bg,
int dx, int dy, String delim)
{
this.appl = appl;
this.font = font;
this.fg = fg;
this.bg = bg;
this.dy = dy;
this.dx = dx;
// parse message line and init attributes
attr = new FunScrollTextAttr(line, delim);
appl.dbg("Parsed Attributes:");
appl.dbg(" msg:" + attr.msg());
appl.dbg(" startScroll:" + attr.startScroll());
appl.dbg(" endScroll:" + attr.endScroll());
appl.dbg(" showDelay:" + attr.showDelay());
appl.dbg(" endDelay:" + attr.endDelay());
appl.dbg(" style:" + attr.style());
appl.dbg("dy:" + dy + " dx:" + dx);
String msg = attr.msg();
noOfChars = msg.length();
chars = new char[noOfChars];
msg.getChars(0, noOfChars, chars, 0);
xPos = new int[noOfChars];
yPos = new int[noOfChars];
visible = new boolean[noOfChars];
FontMetrics fm = appl.getFontMetrics(font);
if (attr.style() == FunScrollTextAttr.NERVOUS ||
attr.style() == FunScrollTextAttr.SINEWAVE)
// need some extra space here!
textHeight = 4 + font.getSize();
else
textHeight = font.getSize();
lineHeight = font.getSize();
int currXPos = 0;
int currYPos = fm.getAscent();
boolean escape = false;
boolean newLine = false;
for (int i = 0; i < noOfChars; i++) {
if (escape) {
// we already have an escape character
if (chars[i] == 'n') {
// got "\n" - line break; i.e line really consists
// of more than one line
chars[i-1] = ' ';
chars[i] = ' ';
newLine = true;
}
escape = false;
}
else if (chars[i] == '\\') {
// escaped characted; wait for next character
escape = true;
}
else {
if (newLine) {
// we have a new line
noOfLines++;
textHeight += dy * 2 + font.getSize();
currXPos = fm.charsWidth(chars, 0, i);
currYPos += fm.getDescent() + fm.getAscent();
newLine = false;
}
xPos[i] = fm.charsWidth(chars, 0, i) - currXPos;
maxWidth = Math.max(maxWidth, xPos[i]);
yPos[i] = currYPos;
}
}
}
/**
* Reset array of x positions
*/
void resetX()
{
FontMetrics fm = appl.getFontMetrics(font);
int currXPos = 0;
int currYPos = yPos[0];
for (int i = 0; i < noOfChars; i++) {
if (currYPos != yPos[i]) {
// new line
currXPos = fm.charsWidth(chars, 0, i);
currYPos = yPos[i];
}
xPos[i] = fm.charsWidth(chars, 0, i) - currXPos;
}
}
/**
* Reset width and height
*/
void reset(int width, int height)
{
this.width = width;
this.height = height;
int scroll = attr.startScroll();
switch (scroll) {
case FunScrollTextAttr.NONE:
xStart = (width-maxWidth)/2;
yStart = (height-textHeight)/2;
break;
case FunScrollTextAttr.LEFT:
xStart = width-dx;
yStart = (height-textHeight)/2;
break;
case FunScrollTextAttr.RIGHT:
xStart = dx;
yStart = (height-textHeight)/2;
break;
case FunScrollTextAttr.UP:
xStart = (width-maxWidth)/2;
yStart = height;
break;
case FunScrollTextAttr.DOWN:
xStart = (width-maxWidth)/2;
yStart = 0-textHeight;
break;
}
// Reset array of x positions
resetX();
// reset state
state = START;
FunScroll.dbg("State: START");
}
/**
* Update. I.e move and paint.
*/
boolean update(Graphics g)
{
move();
paint(g);
if (state == DONE && delayCount < 0)
return true; // we are done!
else
return false;
}
/**
* Move characters
*/
void move()
{
boolean switchState = false;
int scroll = FunScrollTextAttr.NONE;
switch (state) {
case START:
// start sequence
scroll = attr.startScroll();
if (scroll == FunScrollTextAttr.NONE) {
// no animation; just switch state
switchState = true;
}
else {
// some kind of animation; check if all characters displ.
if (textDisplayed(scroll)) {
// yupp; switch state
switchState = true;
}
}
if (switchState == true) {
// switch state
updateVisible(scroll);
state = SHOW;
FunScroll.dbg("State: SHOW");
delayCount = attr.showDelay();
}
else {
// just move text (scroll)
moveText(scroll);
updateVisible(scroll);
}
break;
case SHOW:
// show sequence
if (delayCount-- < 0) {
// switch state
state = END;
FunScroll.dbg("State: END");
}
break;
case END:
// end sequence
// check if all characters still visible
if (updateVisible(attr.endScroll()) == 0 ||
attr.endScroll() == FunScrollTextAttr.NONE) {
// none visible or no end animation; switch state
state = DONE;
FunScroll.dbg("State: DONE");
delayCount = attr.endDelay();
return;
}
else {
moveText(attr.endScroll());
}
break;
case DONE:
// done sequence; just delay
delayCount--;
break;
}
}
/**
* Return true if (all) text is displayed
*/
boolean textDisplayed(int scroll)
{
switch (scroll) {
case FunScrollTextAttr.LEFT:
// scrolling left
if (maxWidth > width) {
// text is wider that applet width
if (maxWidth+xStart < width-4*dx)
return true;
}
else {
int appletMidPoint = width/2;
int textMidPoint = xStart+maxWidth/2;
if (textMidPoint <= appletMidPoint)
return true;
}
break;
case FunScrollTextAttr.RIGHT:
// scrolling right
if (maxWidth > width) {
// text is wider that applet width
if (xPos[0]+xStart > 4*dx)
return true;
}
else {
int appletMidPoint = width/2;
int textMidPoint = xStart+maxWidth/2;
if (textMidPoint >= appletMidPoint)
return true;
}
break;
case FunScrollTextAttr.UP:
// scrolling up
if (yStart <= (height-textHeight)/2)
return true;
break;
case FunScrollTextAttr.DOWN:
// scrolling down
if (yStart >= (height-textHeight)/2)
return true;
break;
}
return false;
}
/**
* update array with flags if characters are visible. Return
* number of visible characters.
*/
int updateVisible(int scroll)
{
int visibleCount = 0;
for (int i = 0; i < noOfChars; i++) {
visible[i] = (xPos[i]+xStart > 0 &&
xPos[i]+xStart < width &&
yPos[i]+yStart+lineHeight > 0 &&
yPos[i]+yStart-lineHeight < height);
if (visible[i])
visibleCount++;
}
// special treatment of explode animation
if (scroll == FunScrollTextAttr.EXPLODE) {
// if only 4 or less chars visible (per line) consider this as done
if (visibleCount <= noOfChars-(noOfLines*4))
visibleCount = 0;
}
return visibleCount;
}
void moveText(int scroll)
{
switch (scroll) {
case FunScrollTextAttr.LEFT:
xStart -= dx;
break;
case FunScrollTextAttr.RIGHT:
xStart += dx;
break;
case FunScrollTextAttr.UP:
yStart -= dy;
break;
case FunScrollTextAttr.DOWN:
yStart += dy;
break;
case FunScrollTextAttr.EXPLODE:
moveExplodeText();
break;
}
}
/**
* Move exploding text
*/
void moveExplodeText() {
int mid = noOfChars/2;
for (int i = 0; i < noOfChars; i++) {
if (i <= mid) {
// move to the left
int dist = dx*((mid - i)/2);
if (i == mid)
dist = dx;
xPos[i] -= dist;
}
else {
// move to the right
xPos[i] += dx*((i - mid)/2);
}
}
}
/**
* Paint characters
*/
void paint(Graphics g)
{
g.setFont(font);
g.setColor(fg);
int style = attr.style();
if (style == FunScrollTextAttr.SINEWAVE) {
// special handling of sine-wave text
paintSineWave(g);
}
else {
for (int i = 0; i < noOfChars; i++) {
if (visible[i]) {
switch (style) {
case FunScrollTextAttr.NERVOUS:
// paint as nervous text
drawNervousChar(g, i);
break;
default:
// paint as normal text
drawNormalChar(g, i);
}
}
}
}
}
/**
* Paint sine-wave text line
*/
void paintSineWave(Graphics g) {
int currYPos = yPos[0];
int degree = sinDegree;
for (int i = noOfChars-1; i >= 0; i--) {
if (currYPos != yPos[i]) {
// new line
currYPos = yPos[i];
degree = sinDegree;
}
if (visible[i]) {
// draw character
int sinHeight = lineHeight/3;
int y = (int) (Math.sin(degree*3.1414/180) * sinHeight);
g.drawChars(chars, i, 1, xPos[i]+xStart, yPos[i]+yStart+y);
}
degree -= 15;
if (degree <= 0)
degree = 360;
}
sinDegree -= 15;
if (sinDegree <= 0)
sinDegree = 360;
}
/**
* Draw nervous character
*/
void drawNervousChar(Graphics g, int index)
{
int x = (int)(Math.random() * 2) + xPos[index];
int y = (int)(Math.random() * 4) + yPos[index];
g.drawChars(chars, index, 1, x+xStart, y+yStart);
}
/**
* Draw normal character
*/
void drawNormalChar(Graphics g, int index)
{
g.drawChars(chars, index, 1,
xPos[index]+xStart, yPos[index]+yStart);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -