首先看下效果圖:html
黑色底部背景,文字的可顯示區域。紅色爲滾動的文字。java
預備知識:git
https://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/scenes/scene2d/Actor.html api
咱們用了Actor中的,clipBegin和clipEnd緩存
裁剪方法,相似截圖,給一個矩形區域,僅繪製矩形區域內的內容。mvc
這裏面有個注意事項就是,在clipbegin()以前,須要調用batch.flush()。目的是讓以前加入舞臺的Actor進行繪製,若是不加就會致使以前的Actor不被繪製。框架
batch.flush(); clipBegin();
滾動的實現,咱們直接用的是MoveByAction。ide
使用方法:測試
// 設置速度,寬度,文字,文字顏色 CHMarqueeText marqueeText = new CHMarqueeText.Builder().setMoveSpeed(100).setMarqueeWidth(100) .setText("測試跑馬燈效果超長文本顯示1234567890結束了。").setTextColor(Color.RED).build(); addActor(marqueeText); marqueeText.setPosition(100, 560);
代碼展現:ui
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二次封裝快速開發框架):