首先看下效果图:
黑色底部背景,文字的可显示区域。红色为滚动的文字。
预备知识:
https://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/scenes/scene2d/Actor.html
我们用了Actor中的,clipBegin和clipEnd
裁剪方法,类似截图,给一个矩形区域,仅绘制矩形区域内的内容。
这里面有个注意事项就是,在clipbegin()之前,需要调用batch.flush()。目的是让之前加入舞台的Actor进行绘制,如果不加就会导致之前的Actor不被绘制。
batch.flush(); clipBegin();
滚动的实现,我们直接用的是MoveByAction。
使用方法:
// 设置速度,宽度,文字,文字颜色 CHMarqueeText marqueeText = new CHMarqueeText.Builder().setMoveSpeed(100).setMarqueeWidth(100) .setText("测试跑马灯效果超长文本显示1234567890结束了。").setTextColor(Color.RED).build(); addActor(marqueeText); marqueeText.setPosition(100, 560);
代码展示:
package com.oahcfly.chgame.core.ui; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.Batch; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.scenes.scene2d.actions.Actions; import com.oahcfly.chgame.core.freefont.FreeFont; import com.oahcfly.chgame.core.freefont.FreeLabel; import com.oahcfly.chgame.core.helper.CHPixmapHelper; import com.oahcfly.chgame.core.mvc.CHActor; /** * 跑马灯 * @author haocao * */ public class CHMarqueeText extends CHActor { // 文本Label private FreeLabel label; private Texture bgTexture; public void setMarqueeTextParams (String text, Color textColor, int width, int moveSpeed) { stoped = false; label = FreeFont.getLabel(textColor, text); // 设置透明背景 Color alphaColor = new Color(Color.BLACK); alphaColor.a = 0.2f; bgTexture = CHPixmapHelper.createRectangleTexture(alphaColor, width, 20 + FreeFont.getBitmapFont().getSize()); setBgTexture(bgTexture); setClipRectangle(new Rectangle(0, 0, width, getHeight())); // float moveDistance = Math.max(0, label.getWidth() - width); float duration = Math.max(0, 12 - 3 * moveSpeed / 100f); if (label.getWidth() > width) { label.addAction(Actions.repeat(-1, Actions.sequence(Actions.moveBy(-label.getWidth(), 0, duration), Actions.run(new Runnable() { @Override public void run () { // 从尾部重新开始 label.setX(getRight()); } }), Actions.moveBy(-label.getWidth() - width, 0, duration)))); } } @Override public void drawAfterBg (Batch batch) { if (label.getX() == 0) { // 设置初始坐标 label.setX(getX()); } label.draw(batch, 1); // 随着action的执行,坐标会发生变化,在这里进行赋值更新 label.setPosition(label.getX(), getY() + 5f); } @Override public void act (float delta) { if (!stoped) { label.act(delta); } super.act(delta); } public FreeLabel getLabel () { return label; } @Override public boolean remove () { if (bgTexture != null) { bgTexture.dispose(); } return super.remove(); } private boolean stoped; public void stopMarquee () { stoped = true; } public void resumeMarquee () { stoped = false; } public static class Builder { private String text; private Color textColor; private int marqueeWidth; private int moveSpeed = 50; public Builder setText (String text) { this.text = text; return this; } public Builder setTextColor (Color textColor) { this.textColor = textColor; return this; } public Builder setMarqueeWidth (int marqueeWidth) { this.marqueeWidth = marqueeWidth; return this; } /** * 范围【0~100】越大速度越快 * @param moveSpeed * @return */ public Builder setMoveSpeed (int moveSpeed) { this.moveSpeed = moveSpeed > 100 ? 100 : moveSpeed < 0 ? 0 : moveSpeed; return this; } public CHMarqueeText build () { CHMarqueeText chMarqueeText = CHActor.obtain(CHMarqueeText.class); chMarqueeText.setMarqueeTextParams(text, textColor, marqueeWidth, moveSpeed); return chMarqueeText; } } }
关联的CHActor代码:
package com.oahcfly.chgame.core.mvc; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.Batch; import com.badlogic.gdx.graphics.g2d.Sprite; import com.badlogic.gdx.graphics.g2d.TextureAtlas.AtlasRegion; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.scenes.scene2d.Actor; import com.badlogic.gdx.utils.Align; import com.badlogic.gdx.utils.Pool; import com.badlogic.gdx.utils.Pool.Poolable; import com.badlogic.gdx.utils.Pools; import com.oahcfly.chgame.core.Chao; /** <pre> * 二次封装的actor * * date: 2014-12-11 * </pre> * * @author caohao */ public class CHActor extends Actor implements Poolable { private int tag; private Texture bgTexture; private TextureRegion bgTextureRegion; public CHActor () { } @Override public void draw (Batch batch, float parentAlpha) { boolean clipok = false; // 开始裁剪 if (clipRectangle != null) { batch.flush(); // 绘制之前添加的元素,如果不添加此处代码,后面的裁剪会导致之前的纹理也会被裁剪 clipok = clipBegin(getX() + clipRectangle.x, getY() + clipRectangle.y, clipRectangle.width, clipRectangle.height); } Color color = getColor(); batch.setColor(color.r, color.g, color.b, color.a); float x = getX(); float y = getY(); float scaleX = getScaleX(); float scaleY = getScaleY(); float width = getWidth(); float height = getHeight(); if (bgTexture != null) { batch.draw(bgTexture, x, y, getOriginX(), getOriginY(), getWidth(), getHeight(), scaleX, scaleY, getRotation(), 0, 0, (int)width, (int)height, false, false); } if (bgTextureRegion != null) { if (bgTextureRegion instanceof Sprite) { Sprite sprite = (Sprite)bgTextureRegion; sprite.setColor(batch.getColor()); sprite.setOrigin(getOriginX(), getOriginY()); sprite.setPosition(x, y); sprite.setScale(scaleX, scaleY); sprite.setSize(width, height); sprite.setRotation(getRotation()); sprite.draw(batch); } else { batch.draw(bgTextureRegion, x, y, getOriginX(), getOriginY(), width, height, scaleX, scaleY, getRotation()); } } // 绘制完背景后进行其他内容绘制 drawAfterBg(batch); // 提交裁剪内容 if (clipok) { batch.flush(); clipEnd(); } } public void drawAfterBg (Batch batch) { }; public void setBgTexture (Texture bgTexture) { this.bgTexture = bgTexture; if (bgTexture != null) { setSize(bgTexture.getWidth(), bgTexture.getHeight()); } setOrigin(Align.center); } /** <pre> * 使用缓存池 * * date: 2015-1-3 * </pre> * * @author caohao * @return */ @SuppressWarnings("unchecked") public static <T extends CHActor> T obtain (Class<T> type) { Pool<CHActor> pool = (Pool<CHActor>)Pools.get(type); CHActor actor = pool.obtain(); actor.setBgTexture(null); return (T)actor; } public static CHActor obtain () { return obtain(CHActor.class); } @Override public void reset () { this.bgTexture = null; this.bgTextureRegion = null; clipRectangle = null; setScale(1); setRotation(0); clear(); setUserObject(null); this.setColor(new Color(1, 1, 1, 1)); setStage(null); setParent(null); setVisible(true); setName(null); setOrigin(Align.center); setPosition(0, 0); } public Texture getBgTexture () { return bgTexture; } public TextureRegion getBgTextureRegion () { return bgTextureRegion; } public void setBgTextureRegion (TextureRegion textureRegion) { this.bgTextureRegion = textureRegion; if (bgTextureRegion != null) { if (bgTextureRegion instanceof Sprite) { Sprite sprite = (Sprite)bgTextureRegion; setSize(sprite.getWidth(), sprite.getHeight()); } else if (bgTextureRegion instanceof AtlasRegion) { AtlasRegion atlasRegion = (AtlasRegion)bgTextureRegion; bgTextureRegion = Chao.plistCenter.createSprite(atlasRegion); Sprite sprite = (Sprite)bgTextureRegion; setSize(sprite.getWidth(), sprite.getHeight()); } else { setSize(bgTextureRegion.getRegionWidth(), bgTextureRegion.getRegionHeight()); } } setOrigin(Align.center); } @Override public boolean remove () { boolean remove = super.remove(); if (remove) { Pools.free(this); } return remove; } public int getTag () { return tag; } public void setTag (int tag) { this.tag = tag; } private Rectangle clipRectangle; /** * 设置裁剪矩形,范围为当前Actor的显示区域即:(0,0)~(w,h) * @param rectangle */ public void setClipRectangle (Rectangle rectangle) { this.clipRectangle = rectangle; } }
欢迎关注CHGame框架(基于Libgdx二次封装快速开发框架):
https://git.oschina.net/oahcfly/CHGame.git