Update DEV Beta21-P3

This commit is contained in:
LingASDJ 2023-02-28 23:47:35 +08:00
parent f960b0bf76
commit 355b5330fa
25 changed files with 878 additions and 358 deletions

View File

@ -38,48 +38,48 @@ import java.nio.FloatBuffer;
import java.util.HashMap;
public class RenderedText extends Image {
private BitmapFont font = null;
private int size;
private String text;
public RenderedText( ) {
text = null;
}
public RenderedText( int size ){
text = null;
this.size = size;
}
public RenderedText(String text, int size){
this.text = text;
this.size = size;
measure();
}
public void text( String text ){
this.text = text;
measure();
}
public String text(){
return text;
}
public void size( int size ){
this.size = size;
measure();
}
private synchronized void measure(){
if (Thread.currentThread().getName().equals("SHPD Actor Thread")){
if (Thread.currentThread().getName().equals("CAPD Actor Thread")){
throw new RuntimeException("Text measured from the actor thread!");
}
if ( text == null || text.equals("") ) {
text = "";
width=height=0;
@ -88,23 +88,31 @@ public class RenderedText extends Image {
} else {
visible = true;
}
font = Game.platform.getFont(size, text, true, true);
font = Game.platform.getFont(size, text, true, true, false);
if (font != null){
GlyphLayout glyphs = new GlyphLayout( font, text);
for (char c : text.toCharArray()) {
BitmapFont.Glyph g = font.getData().getGlyph(c);
if (g == null || (g.id != c)){
String toException = text;
if (toException.length() > 30){
toException = toException.substring(0, 30) + "...";
font = Game.platform.getFont(size, text, true, true, true);
for (char c1 : text.toCharArray()) {
BitmapFont.Glyph g1 = font.getData().getGlyph(c1);
if (g1 == null || (g1.id != c1)){
String toException = text;
if (toException.length() > 30){
toException = toException.substring(0, 30) + "...";
}
font = Game.platform.getFont(size, text, true, true, false);
Game.reportException(new Throwable("font file " + font.toString() + " could not render " + c + " from string: " + toException));
}
}
Game.reportException(new Throwable("font file " + font.toString() + " could not render " + c + " from string: " + toException));
break;
}
}
//We use the xadvance of the last glyph in some cases to fix issues
// with fullwidth punctuation marks in some asian scripts
BitmapFont.Glyph lastGlyph = font.getData().getGlyph(text.charAt(text.length()-1));
@ -113,15 +121,15 @@ public class RenderedText extends Image {
} else {
width = glyphs.width;
}
//this is identical to l.height in most cases, but we force this for consistency.
height = Math.round(size*0.75f);
renderedHeight = glyphs.height;
}
}
private float renderedHeight = 0;
@Override
protected void updateMatrix() {
super.updateMatrix();
@ -130,9 +138,9 @@ public class RenderedText extends Image {
Matrix.translate(matrix, 0, Math.round(height - renderedHeight));
}
}
private static TextRenderBatch textRenderer = new TextRenderBatch();
@Override
public synchronized void draw() {
if (font != null) {
@ -146,7 +154,7 @@ public class RenderedText extends Image {
//can interface with the freetype font generator
//some copypasta from BitmapText here
private static class TextRenderBatch implements Batch {
//this isn't as good as only updating once, like with BitmapText
// but it skips almost all allocations, which is almost as good
private static RenderedText textBeingRendered = null;
@ -156,7 +164,7 @@ public class RenderedText extends Image {
@Override
public void draw(Texture texture, float[] spriteVertices, int offset, int count) {
Visual v = textBeingRendered;
FloatBuffer toOpenGL;
if (buffers.containsKey(count/20)){
toOpenGL = buffers.get(count/20);
@ -165,54 +173,54 @@ public class RenderedText extends Image {
toOpenGL = Quad.createSet(count / 20);
buffers.put(count/20, toOpenGL);
}
for (int i = 0; i < count; i += 20){
vertices[0] = spriteVertices[i+0];
vertices[1] = spriteVertices[i+1];
vertices[2] = spriteVertices[i+3];
vertices[3] = spriteVertices[i+4];
vertices[4] = spriteVertices[i+5];
vertices[5] = spriteVertices[i+6];
vertices[6] = spriteVertices[i+8];
vertices[7] = spriteVertices[i+9];
vertices[8] = spriteVertices[i+10];
vertices[9] = spriteVertices[i+11];
vertices[10] = spriteVertices[i+13];
vertices[11] = spriteVertices[i+14];
vertices[12] = spriteVertices[i+15];
vertices[13] = spriteVertices[i+16];
vertices[14] = spriteVertices[i+18];
vertices[15] = spriteVertices[i+19];
toOpenGL.put(vertices);
}
((Buffer)toOpenGL).position(0);
NoosaScript script = NoosaScript.get();
texture.bind();
com.watabou.glwrap.Texture.clear();
script.camera( v.camera() );
script.uModel.valueM4( v.matrix );
script.lighting(
v.rm, v.gm, v.bm, v.am,
v.ra, v.ga, v.ba, v.aa );
script.drawQuadSet( toOpenGL, count/20 );
}
//none of these functions are needed, so they are stubbed
@Override
public void begin() { }
@ -252,4 +260,4 @@ public class RenderedText extends Image {
public boolean isDrawing() { return false; }
public void dispose() { }
}
}
}

View File

@ -33,7 +33,6 @@ import com.badlogic.gdx.scenes.scene2d.ui.TextArea;
import com.badlogic.gdx.scenes.scene2d.ui.TextField;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.utils.Align;
import com.badlogic.gdx.utils.viewport.ScreenViewport;
import com.badlogic.gdx.utils.viewport.Viewport;
import com.watabou.glscripts.Script;
import com.watabou.glwrap.Blending;
@ -74,7 +73,7 @@ public class TextInput extends Component {
skin = new Skin(FileUtils.getFileHandle(Files.FileType.Internal, "gdx/textfield.json"));
TextField.TextFieldStyle style = skin.get(TextField.TextFieldStyle.class);
style.font = Game.platform.getFont(size, "", false, false);
style.font = Game.platform.getFont(size, "", false, false,false);
style.background = null;
textField = multiline ? new TextArea("", style) : new TextField("", style);
textField.setProgrammaticChangeEvents(true);
@ -84,7 +83,7 @@ public class TextInput extends Component {
textField.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
BitmapFont f = Game.platform.getFont(size, textField.getText(), false, false);
BitmapFont f = Game.platform.getFont(size, textField.getText(), false, false,false);
TextField.TextFieldStyle style = textField.getStyle();
if (f != style.font){
style.font = f;

View File

@ -21,9 +21,9 @@
package com.watabou.utils;
import static com.watabou.utils.DeviceCompat.isDebug;
import com.badlogic.gdx.Application;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.PixmapPacker;
@ -31,13 +31,12 @@ import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
import com.watabou.noosa.Game;
import java.util.HashMap;
import java.util.regex.Pattern;
public abstract class PlatformSupport {
public abstract void updateDisplaySize();
public void logd( String message ) {
if (isDebug()) Gdx.app.log("DEBUG", message);
}
public abstract void updateSystemUI();
public abstract boolean connectedToUnmeteredNetwork();
@ -47,26 +46,48 @@ public abstract class PlatformSupport {
Gdx.input.vibrate( millis );
}
public void setHonorSilentSwitch( boolean value ){
//does nothing by default
}
public boolean openURI( String uri ){
return Gdx.net.openURI( uri );
}
//TODO should consider spinning this into its own class, rather than platform support getting ever bigger
protected static HashMap<FreeTypeFontGenerator, HashMap<Integer, BitmapFont>> fonts;
protected static FreeTypeFontGenerator fallbackFontGenerator;
//splits on newlines, underscores, and chinese/japaneses characters
protected static Pattern regularsplitter = Pattern.compile(
"(?<=\n)|(?=\n)|(?<=_)|(?=_)|(?<=\\\\)|(?=\\\\)|" +
"(?<=[^\\x00-\\xff])|(?=[^\\x00-\\xff])|" +
"(?<=\\p{InHiragana})|(?=\\p{InHiragana})|" +
"(?<=\\p{InKatakana})|(?=\\p{InKatakana})|" +
"(?<=\\p{InHangul_Syllables})|(?=!\\p{InHangul_Syllables})|" +
"(?<=\\p{InCJK_Unified_Ideographs})|(?=\\p{InCJK_Unified_Ideographs})|" +
"(?<=\\p{InCJK_Symbols_and_Punctuation})|(?=\\p{InCJK_Symbols_and_Punctuation})" +
"(?<=\\p{InHalfwidth_and_Fullwidth_Forms})|(?=\\p{InHalfwidth_and_Fullwidth_Forms})");
//additionally splits on words, so that each word can be arranged individually
protected static Pattern regularsplitterMultiline = Pattern.compile(
"(?<= )|(?= )|(?<=\n)|(?=\n)|(?<=_)|(?=_)|(?<=\\\\)|(?=\\\\)|" +
"(?<=[^\\x00-\\xff])|(?=[^\\x00-\\xff])|" +
"(?<=\\p{InHiragana})|(?=\\p{InHiragana})|" +
"(?<=\\p{InKatakana})|(?=\\p{InKatakana})|" +
"(?<=\\p{InHangul_Syllables})|(?=!\\p{InHangul_Syllables})|" +
"(?<=\\p{InCJK_Unified_Ideographs})|(?=\\p{InCJK_Unified_Ideographs})|" +
"(?<=\\p{InCJK_Symbols_and_Punctuation})|(?=\\p{InCJK_Symbols_and_Punctuation})" +
"(?<=\\p{InHalfwidth_and_Fullwidth_Forms})|(?=\\p{InHalfwidth_and_Fullwidth_Forms})");
protected int pageSize;
protected PixmapPacker packer;
protected boolean systemfont;
public abstract void setupFontGenerators(int pageSize, boolean systemFont );
protected abstract FreeTypeFontGenerator getGeneratorForString( String input );
public abstract String[] splitforTextBlock( String text, boolean multiline );
public String[] splitforTextBlock(String text, boolean multiline) {
if (multiline) {
return regularsplitterMultiline.split(text);
} else {
return regularsplitter.split(text);
}
}
public void resetGenerators(){
resetGenerators( true );
@ -113,8 +134,8 @@ public abstract class PlatformSupport {
//flipped is needed because Shattered's graphics are y-down, while GDX graphics are y-up.
//this is very confusing, I know.
public BitmapFont getFont(int size, String text, boolean flipped, boolean border) {
FreeTypeFontGenerator generator = getGeneratorForString(text);
public BitmapFont getFont(int size, String text, boolean flipped, boolean border, boolean fallback) {
FreeTypeFontGenerator generator = fallback ? fallbackFontGenerator : getGeneratorForString(text);
if (generator == null){
return null;
@ -145,7 +166,7 @@ public abstract class PlatformSupport {
BitmapFont font = generator.generateFont(parameters);
font.getData().missingGlyph = font.getData().getGlyph('<27>');
fonts.get(generator).put(key, font);
} catch ( Exception e ){
} catch ( Exception e ) {
Game.reportException(e);
return null;
}
@ -154,4 +175,70 @@ public abstract class PlatformSupport {
return fonts.get(generator).get(key);
}
}
public void setHonorSilentSwitch( boolean value ){
//does nothing by default
}
public boolean supportsFullScreen(){
switch (Gdx.app.getType()){
case Android:
//Android 4.4+ supports hiding UI via immersive mode
return Gdx.app.getVersion() >= 19;
case iOS:
//iOS supports hiding UI via drawing into the gesture safe area
return Gdx.graphics.getSafeInsetBottom() != 0;
default:
//TODO implement functionality for other platforms here
return true;
}
}
public boolean isAndroid() {
return Gdx.app.getType() == Application.ApplicationType.Android;
}
public boolean isiOS() {
return Gdx.app.getType() == Application.ApplicationType.iOS;
}
public boolean isDesktop() {
return Gdx.app.getType() == Application.ApplicationType.Desktop;
}
public boolean hasHardKeyboard() {
return Gdx.input.isPeripheralAvailable(Input.Peripheral.HardwareKeyboard);
}
public boolean isDebug() {
return Game.version.contains("INDEV");
}
public boolean isSnapshot() {
return Game.version.contains("SNAPSHOT");
}
public boolean openURI( String URI ) {
return Gdx.net.openURI(URI);
}
public void log( String tag, String message ){
Gdx.app.log( tag, message );
}
public void debug( String message ) {
if (isDebug()) Gdx.app.log("DEBUG", message);
}
public void setClipboardContents( String str ) {
Gdx.app.getClipboard().setContents( str );
}
public String getClipboardContents() {
return Gdx.app.getClipboard().getContents();
}
public boolean isClipboardEmpty() {
return !Gdx.app.getClipboard().hasContents();
}
}

View File

@ -46,7 +46,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class AndroidPlatformSupport extends PlatformSupport {
public void updateDisplaySize(){
if (SPDSettings.landscape() != null) {
AndroidGame.instance.setRequestedOrientation( SPDSettings.landscape() ?
@ -55,10 +55,10 @@ public class AndroidPlatformSupport extends PlatformSupport {
}
GLSurfaceView view = (GLSurfaceView) ((AndroidGraphics)Gdx.graphics).getView();
if (view.getMeasuredWidth() == 0 || view.getMeasuredHeight() == 0)
return;
Game.dispWidth = view.getMeasuredWidth();
Game.dispHeight = view.getMeasuredHeight();
@ -71,40 +71,40 @@ public class AndroidPlatformSupport extends PlatformSupport {
Game.dispWidth = Game.dispHeight;
Game.dispHeight = tmp;
}
float dispRatio = Game.dispWidth / (float)Game.dispHeight;
float renderWidth = dispRatio > 1 ? PixelScene.MIN_WIDTH_L : PixelScene.MIN_WIDTH_P;
float renderHeight = dispRatio > 1 ? PixelScene.MIN_HEIGHT_L : PixelScene.MIN_HEIGHT_P;
//force power saver in this case as all devices must run at at least 2x scale.
if (Game.dispWidth < renderWidth*2 || Game.dispHeight < renderHeight*2)
SPDSettings.put( SPDSettings.KEY_POWER_SAVER, true );
if (SPDSettings.powerSaver() && fullscreen){
int maxZoom = (int)Math.min(Game.dispWidth/renderWidth, Game.dispHeight/renderHeight);
renderWidth *= Math.max( 2, Math.round(1f + maxZoom*0.4f));
renderHeight *= Math.max( 2, Math.round(1f + maxZoom*0.4f));
if (dispRatio > renderWidth / renderHeight){
renderWidth = renderHeight * dispRatio;
} else {
renderHeight = renderWidth / dispRatio;
}
final int finalW = Math.round(renderWidth);
final int finalH = Math.round(renderHeight);
if (finalW != Game.width || finalH != Game.height){
AndroidGame.instance.runOnUiThread(new Runnable() {
@Override
public void run() {
view.getHolder().setFixedSize(finalW, finalH);
}
});
}
} else {
AndroidGame.instance.runOnUiThread(new Runnable() {
@ -115,16 +115,16 @@ public class AndroidPlatformSupport extends PlatformSupport {
});
}
}
public void updateSystemUI() {
AndroidGame.instance.runOnUiThread(new Runnable() {
@SuppressLint("NewApi")
@Override
public void run() {
boolean fullscreen = Build.VERSION.SDK_INT < Build.VERSION_CODES.N
|| !AndroidGame.instance.isInMultiWindowMode();
if (fullscreen){
AndroidGame.instance.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN | WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
@ -132,23 +132,21 @@ public class AndroidPlatformSupport extends PlatformSupport {
AndroidGame.instance.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN | WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
if (SPDSettings.fullscreen()) {
AndroidGame.instance.getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY );
} else {
AndroidGame.instance.getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE );
}
if (SPDSettings.fullscreen()) {
AndroidGame.instance.getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY );
} else {
AndroidGame.instance.getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE );
}
}
});
}
@Override
@SuppressWarnings("deprecation")
public boolean connectedToUnmeteredNetwork() {
@ -160,26 +158,28 @@ public class AndroidPlatformSupport extends PlatformSupport {
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
return activeNetwork != null && activeNetwork.isConnectedOrConnecting() &&
(activeNetwork.getType() == ConnectivityManager.TYPE_WIFI
|| activeNetwork.getType() == ConnectivityManager.TYPE_WIMAX
|| activeNetwork.getType() == ConnectivityManager.TYPE_BLUETOOTH
|| activeNetwork.getType() == ConnectivityManager.TYPE_ETHERNET);
|| activeNetwork.getType() == ConnectivityManager.TYPE_WIMAX
|| activeNetwork.getType() == ConnectivityManager.TYPE_BLUETOOTH
|| activeNetwork.getType() == ConnectivityManager.TYPE_ETHERNET);
}
}
/* FONT SUPPORT */
//droid sans / roboto, or a custom pixel font, for use with Latin and Cyrillic languages
private static FreeTypeFontGenerator basicFontGenerator;
//droid sans / nanum gothic / noto sans, for use with Korean
private static FreeTypeFontGenerator KRFontGenerator;
//droid sans / noto sans, for use with Simplified Chinese
private static FreeTypeFontGenerator SCFontGenerator;
//droid sans / noto sans, for use with Traditional Chinese
private static FreeTypeFontGenerator TCFontGenerator;
//droid sans / noto sans, for use with Japanese
private static FreeTypeFontGenerator JPFontGenerator;
//special logic for handling korean android 6.0 font oddities
private static boolean koreanAndroid6OTF = false;
@Override
public void setupFontGenerators(int pageSize, boolean systemfont) {
//don't bother doing anything if nothing has changed
@ -191,16 +191,23 @@ public class AndroidPlatformSupport extends PlatformSupport {
resetGenerators(false);
fonts = new HashMap<>();
basicFontGenerator = KRFontGenerator = SCFontGenerator = JPFontGenerator = null;
if (systemfont && Gdx.files.absolute("/system/fonts/Roboto-Regular.ttf").exists()) {
basicFontGenerator = KRFontGenerator = SCFontGenerator = TCFontGenerator = JPFontGenerator = fallbackFontGenerator = null;
if (Gdx.files.absolute("/system/fonts/Roboto-Regular.ttf").exists()) {
basicFontGenerator = new FreeTypeFontGenerator(Gdx.files.absolute("/system/fonts/Roboto-Regular.ttf"));
} else if (systemfont && Gdx.files.absolute("/system/fonts/DroidSans.ttf").exists()){
} else if (Gdx.files.absolute("/system/fonts/DroidSans.ttf").exists()){
basicFontGenerator = new FreeTypeFontGenerator(Gdx.files.absolute("/system/fonts/DroidSans.ttf"));
} else {
basicFontGenerator = new FreeTypeFontGenerator(Gdx.files.internal("fonts/pixel_font.ttf"));
}
if (!systemfont) {
if (basicFontGenerator == null) {
basicFontGenerator = fallbackFontGenerator = new FreeTypeFontGenerator(Gdx.files.internal("fonts/pixel_font.ttf"));
}
else {
fallbackFontGenerator = basicFontGenerator;
basicFontGenerator = new FreeTypeFontGenerator(Gdx.files.internal("fonts/pixel_font.ttf"));
}
}
//android 7.0+. all asian fonts are nicely contained in one spot
if (Gdx.files.absolute("/system/fonts/NotoSansCJK-Regular.ttc").exists()) {
//typefaces are 0-JP, 1-KR, 2-SC, 3-TC.
@ -209,15 +216,19 @@ public class AndroidPlatformSupport extends PlatformSupport {
case JAPANESE:
typeFace = 0;
break;
// case KOREAN:
// typeFace = 1;
// break;
case HARDCHINESE:
case CHINESE:
default:
typeFace = 2;
}
KRFontGenerator = SCFontGenerator = JPFontGenerator = new FreeTypeFontGenerator(Gdx.files.absolute("/system/fonts/NotoSansCJK-Regular.ttc"), typeFace);
//otherwise we have to go over a few possibilities.
KRFontGenerator = SCFontGenerator = TCFontGenerator = JPFontGenerator = new FreeTypeFontGenerator(Gdx.files.absolute("/system/fonts/NotoSansCJK-Regular.ttc"), typeFace);
//otherwise we have to go over a few possibilities.
} else {
//Korean font generators
if (Gdx.files.absolute("/system/fonts/NanumGothic.ttf").exists()){
KRFontGenerator = new FreeTypeFontGenerator(Gdx.files.absolute("/system/fonts/NanumGothic.ttf"));
@ -225,19 +236,26 @@ public class AndroidPlatformSupport extends PlatformSupport {
KRFontGenerator = new FreeTypeFontGenerator(Gdx.files.absolute("/system/fonts/NotoSansKR-Regular.otf"));
koreanAndroid6OTF = true;
}
//Chinese font generators
//Simplified Chinese font generators
if (Gdx.files.absolute("/system/fonts/NotoSansSC-Regular.otf").exists()){
SCFontGenerator = new FreeTypeFontGenerator(Gdx.files.absolute("/system/fonts/NotoSansSC-Regular.otf"));
} else if (Gdx.files.absolute("/system/fonts/NotoSansHans-Regular.otf").exists()){
SCFontGenerator = new FreeTypeFontGenerator(Gdx.files.absolute("/system/fonts/NotoSansHans-Regular.otf"));
}
//Traditional Chinese font generators
if (Gdx.files.absolute("/system/fonts/NotoSansTC-Regular.otf").exists()){
TCFontGenerator = new FreeTypeFontGenerator(Gdx.files.absolute("/system/fonts/NotoSansTC-Regular.otf"));
} else if (Gdx.files.absolute("/system/fonts/NotoSansHant-Regular.otf").exists()){
TCFontGenerator = new FreeTypeFontGenerator(Gdx.files.absolute("/system/fonts/NotoSansHant-Regular.otf"));
}
//Japaneses font generators
if (Gdx.files.absolute("/system/fonts/NotoSansJP-Regular.otf").exists()){
JPFontGenerator = new FreeTypeFontGenerator(Gdx.files.absolute("/system/fonts/NotoSansJP-Regular.otf"));
}
//set up a fallback generator for any remaining fonts
FreeTypeFontGenerator fallbackGenerator;
if (Gdx.files.absolute("/system/fonts/DroidSansFallback.ttf").exists()){
@ -246,62 +264,67 @@ public class AndroidPlatformSupport extends PlatformSupport {
//no fallback font, just set to null =/
fallbackGenerator = null;
}
if (KRFontGenerator == null) KRFontGenerator = fallbackGenerator;
if (SCFontGenerator == null) SCFontGenerator = fallbackGenerator;
if (TCFontGenerator == null) TCFontGenerator = fallbackGenerator;
if (JPFontGenerator == null) JPFontGenerator = fallbackGenerator;
}
if (!systemfont) {
switch (SPDSettings.language()) {
case CHINESE:
fallbackFontGenerator = SCFontGenerator;
break;
case HARDCHINESE:
fallbackFontGenerator = TCFontGenerator;
break;
case JAPANESE:
fallbackFontGenerator = JPFontGenerator;
break;
}
KRFontGenerator = SCFontGenerator = TCFontGenerator = JPFontGenerator = new FreeTypeFontGenerator(Gdx.files.internal("fonts/fusion_pixel.ttf"));
}
if (basicFontGenerator != null) fonts.put(basicFontGenerator, new HashMap<>());
if (KRFontGenerator != null) fonts.put(KRFontGenerator, new HashMap<>());
if (SCFontGenerator != null) fonts.put(SCFontGenerator, new HashMap<>());
if (TCFontGenerator != null) fonts.put(TCFontGenerator, new HashMap<>());
if (JPFontGenerator != null) fonts.put(JPFontGenerator, new HashMap<>());
if (fallbackFontGenerator != null) fonts.put(fallbackFontGenerator, new HashMap<>());
//would be nice to use RGBA4444 to save memory, but this causes problems on some gpus =S
packer = new PixmapPacker(pageSize, pageSize, Pixmap.Format.RGBA8888, 1, false);
}
private static Matcher KRMatcher = Pattern.compile("\\p{InHangul_Syllables}").matcher("");
private static Matcher SCMatcher = Pattern.compile("\\p{InCJK_Unified_Ideographs}|\\p{InCJK_Symbols_and_Punctuation}|\\p{InHalfwidth_and_Fullwidth_Forms}").matcher("");
private static Matcher CNMatcher = Pattern.compile("\\p{InCJK_Unified_Ideographs}|\\p{InCJK_Symbols_and_Punctuation}|\\p{InHalfwidth_and_Fullwidth_Forms}").matcher("");
private static Matcher JPMatcher = Pattern.compile("\\p{InHiragana}|\\p{InKatakana}").matcher("");
@Override
protected FreeTypeFontGenerator getGeneratorForString( String input ){
if (KRMatcher.reset(input).find()){
return KRFontGenerator;
} else if (SCMatcher.reset(input).find()){
return SCFontGenerator;
} else if (CNMatcher.reset(input).find()){
switch (SPDSettings.language()) {
case CHINESE:
default:
return SCFontGenerator;
case HARDCHINESE:
return TCFontGenerator;
}
} else if (JPMatcher.reset(input).find()){
return JPFontGenerator;
} else {
return basicFontGenerator;
}
}
//splits on newlines, underscores, and chinese/japaneses characters
private Pattern regularsplitter = Pattern.compile(
"(?<=\n)|(?=\n)|(?<=_)|(?=_)|" +
"(?<=\\p{InHiragana})|(?=\\p{InHiragana})|" +
"(?<=\\p{InKatakana})|(?=\\p{InKatakana})|" +
"(?<=\\p{InCJK_Unified_Ideographs})|(?=\\p{InCJK_Unified_Ideographs})|" +
"(?<=\\p{InCJK_Symbols_and_Punctuation})|(?=\\p{InCJK_Symbols_and_Punctuation})|" +
"(?<=\\p{InHalfwidth_and_Fullwidth_Forms})|(?=\\p{InHalfwidth_and_Fullwidth_Forms})");
//additionally splits on words, so that each word can be arranged individually
private Pattern regularsplitterMultiline = Pattern.compile(
"(?<= )|(?= )|(?<=\n)|(?=\n)|(?<=_)|(?=_)|" +
"(?<=\\p{InHiragana})|(?=\\p{InHiragana})|" +
"(?<=\\p{InKatakana})|(?=\\p{InKatakana})|" +
"(?<=\\p{InCJK_Unified_Ideographs})|(?=\\p{InCJK_Unified_Ideographs})|" +
"(?<=\\p{InCJK_Symbols_and_Punctuation})|(?=\\p{InCJK_Symbols_and_Punctuation})|" +
"(?<=\\p{InHalfwidth_and_Fullwidth_Forms})|(?=\\p{InHalfwidth_and_Fullwidth_Forms})");
//splits on each non-hangul character. Needed for weird android 6.0 font files
private Pattern android6KRSplitter = Pattern.compile(
"(?<= )|(?= )|(?<=\n)|(?=\n)|(?<=_)|(?=_)|" +
private static Pattern android6KRSplitter = Pattern.compile(
"(?<= )|(?= )|(?<=\n)|(?=\n)|(?<=_)|(?=_)|(?<=\\\\)|(?=\\\\)|" +
"(?!\\p{InHangul_Syllables})|(?<!\\p{InHangul_Syllables})");
@Override
public String[] splitforTextBlock(String text, boolean multiline) {
if (koreanAndroid6OTF && getGeneratorForString(text) == KRFontGenerator){
@ -312,5 +335,20 @@ public class AndroidPlatformSupport extends PlatformSupport {
return regularsplitter.split(text);
}
}
}
@Override
public boolean isAndroid() {
return true;
}
@Override
public boolean isiOS() {
return false;
}
@Override
public boolean isDesktop() {
return false;
}
}

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 797 B

After

Width:  |  Height:  |  Size: 797 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

@ -1253,10 +1253,10 @@ actors.hero.heroclass.warrior_desc_item=蕾零安洁初始携带一枚可以贴
actors.hero.heroclass.warrior_desc_loadout=蕾零安洁初始携带一把_破损的短剑。_这把武器的直接近战伤害是所有初始武器中最高的。\n\n蕾零安洁初始携带_三块石子。_石子可以扔出攻击远处造成一定的少量伤害。\n\n蕾零安洁初始携带一个可以收纳各种药水并保护药水瓶不被冻碎的_药水架。_
actors.hero.heroclass.warrior_desc_misc=蕾零安洁每次食用食物时都能恢复少量生命值。\n\n蕾零安洁开局鉴定的物品有\n- 鉴定卷轴\n- 治疗药水\n- 盛怒卷轴
actors.hero.heroclass.warrior_desc_subclasses=在击杀第二个Boss后可以选择一种专精。蕾零安洁可以在两种专精中二选一
actors.hero.heroclass.warrior_story=剧情故事待补充
actors.hero.heroclass.huntress_story=剧情故事待补充
actors.hero.heroclass.rogue_story=剧情故事待补充
actors.hero.heroclass.mage_story=剧情故事待补充
actors.hero.heroclass.warrior_story=剧情故事待补充-123
actors.hero.heroclass.huntress_story=剧情故事待补充-456
actors.hero.heroclass.rogue_story=剧情故事待补充-789
actors.hero.heroclass.mage_story=剧情故事待补充-101112
actors.hero.heroclass.mage=茉莉伊洛
actors.hero.heroclass.mage_unlock=茉莉伊洛精通各类法杖并在开局时持有一根_独特的魔杖_。\n\n_在一局游戏中使用两张升级卷轴_以解锁茉莉伊洛。

View File

@ -257,7 +257,7 @@ scenes.guidescene.page_9=当你完成了一些特殊挑战后0层的四个基
scenes.guidescene.title_10=未完待续
scenes.guidescene.page_10=感谢你阅读这篇指南,它可能并不完善。但应该能帮助你。\n\n同时这只是上半段的结束。请期待下半段的更新。
scenes.thanksscene.code=编码致谢:\n-REN(夜临2作者)\n-Alexstrasza(注解作者)\n-SmuJB(诅咒作者)\n-Tianscar(碳作者)\n-TrashBoxbodylev(经验作者)
scenes.thanksscene.code=编码致谢:\n-REN(夜临2作者)\n-Alexstrasza(注解作者)\n-SmuJB(诅咒作者)\n-Tianscar(碳作者)\n-TrashBoxbodylev(经验作者)
scenes.thanksscene.test=\n\n测试致谢\n-CodenameE\n-熊猫头\n-迷茫\n-小狐狸\n-摘希\n-ZIOM-ObSir\n-坏猫猫\n-不是史神\n-月鸾\n-口水猫
scenes.thanksscene.music=\n\n音乐致谢\n-Prohonor\n-泰拉瑞亚
scenes.thanksscene.art=\n\n美术致谢\n-被子\n-冷群怪\n-REN\n-Daniel Clan\n-奈亚子-\nTianScar\n-ObSir\n-Nxhy

Binary file not shown.

View File

@ -100,6 +100,9 @@ public class Assets {
public static final String BANNERS = "interfaces/banners.png";
public static final String MENUTITLE = "interfaces/menutitle.png";
public static final String TWOYEARS = "interfaces/2years.png";
//圣诞节
public static final String BANNERSSD = "interfaces/banners_sd.png";
@ -122,6 +125,8 @@ public class Assets {
public static final String SURFACE = "interfaces/surface.png";
public static final String NEW_MENU = "interfaces/go-surface.png";
public static final String LOADING_GOLD = "interfaces/loading_gold.png";
public static final String LOADING_SEWERS = "interfaces/loading_sewers.png";
public static final String LOADING_PRISON = "interfaces/loading_prison.png";
@ -155,7 +160,7 @@ public class Assets {
public static final String THEME = "music/theme.ogg";
public static final String GO = "music/Open.ogg";
public static final String SHOP = "music/shop.ogg";
public static final String THEME_1 = "music/theme.ogg";
public static final String THEME_1 = "music/newtheme.ogg";
public static final String THEME_2 = "music/theme.ogg";
public static final String SEWERS_1 = "music/Level1.ogg";

View File

@ -152,9 +152,6 @@ public class RedDragon extends NPC {
@Override
public void call() {
switch (Quest.type) {
//豺狼炼药长老
//豺狼萨满长老
//FLAME-C02
case 1:
default:
GameScene.show(new WndQuest(RedDragon.this, Messages.get(RedDragon.this,
@ -174,13 +171,9 @@ public class RedDragon extends NPC {
int newPos = -1;
for (int i = 0; i < 10; i++) {
int Click = 1;
if (3 == 3) {
Click = 1 + 10;
AlarmTrap Waring = new AlarmTrap();
Waring.pos = super.pos;
Waring.activate();
}
AlarmTrap Waring = new AlarmTrap();
Waring.pos = super.pos;
Waring.activate();
newPos = Dungeon.level.randomRespawnCell( this );
if (newPos != -1) {
break;

View File

@ -59,6 +59,7 @@ public class WarHammer extends MeleeWeapon {
Buff.prolong(defender, Vertigo.class, 12f+level);
Buff.prolong(defender, Terror.class, 12f+level);
Buff.affect(defender, Burning.class).reignite(defender,5f+level);
//Over Level 3,Not Debuff
if(Random.Float()<0.65f && level <3) {
Buff.affect(attacker, Vulnerable.class, 6f);
}

View File

@ -36,7 +36,6 @@ import com.watabou.noosa.Group;
import com.watabou.noosa.Image;
import com.watabou.noosa.PointerArea;
import com.watabou.noosa.ui.Component;
import com.watabou.utils.DeviceCompat;
public class AboutScene extends PixelScene {

View File

@ -21,94 +21,207 @@
package com.shatteredpixel.shatteredpixeldungeon.scenes;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import static com.shatteredpixel.shatteredpixeldungeon.ui.Icons.RENAME_OFF;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Badges;
import com.shatteredpixel.shatteredpixeldungeon.Chrome;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.GamesInProgress;
import com.shatteredpixel.shatteredpixeldungeon.Rankings;
import com.shatteredpixel.shatteredpixeldungeon.SPDAction;
import com.shatteredpixel.shatteredpixeldungeon.SPDSettings;
import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass;
import com.shatteredpixel.shatteredpixeldungeon.journal.Journal;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.PinkLingSprite;
import com.shatteredpixel.shatteredpixeldungeon.effects.Fireball;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
import com.shatteredpixel.shatteredpixeldungeon.ui.ActionIndicator;
import com.shatteredpixel.shatteredpixeldungeon.ui.Archs;
import com.shatteredpixel.shatteredpixeldungeon.ui.ExitButton;
import com.shatteredpixel.shatteredpixeldungeon.ui.IconButton;
import com.shatteredpixel.shatteredpixeldungeon.ui.Icons;
import com.shatteredpixel.shatteredpixeldungeon.ui.RenderedTextBlock;
import com.shatteredpixel.shatteredpixeldungeon.ui.StyledButton;
import com.shatteredpixel.shatteredpixeldungeon.ui.RedButton;
import com.shatteredpixel.shatteredpixeldungeon.ui.Window;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndChallenges;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndHeroInfo;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndKeyBindings;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndMessage;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndStartGame;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndTextInput;
import com.watabou.gltextures.SmartTexture;
import com.watabou.gltextures.TextureCache;
import com.watabou.glwrap.Matrix;
import com.watabou.glwrap.Quad;
import com.watabou.input.GameAction;
import com.watabou.input.PointerEvent;
import com.watabou.noosa.Camera;
import com.watabou.noosa.ColorBlock;
import com.watabou.noosa.Game;
import com.watabou.noosa.Group;
import com.watabou.noosa.Image;
import com.watabou.noosa.NoosaScript;
import com.watabou.noosa.PointerArea;
import com.watabou.noosa.TextureFilm;
import com.watabou.noosa.Visual;
import com.watabou.utils.DeviceCompat;
import com.watabou.utils.GameMath;
import com.watabou.utils.Point;
import com.watabou.utils.Random;
import java.util.ArrayList;
import java.nio.Buffer;
import java.nio.FloatBuffer;
import java.util.Calendar;
public class HeroSelectScene extends PixelScene {
private Image background;
private RenderedTextBlock prompt;
private static HeroClass[] heroClasses = new HeroClass[] {
HeroClass.WARRIOR,
HeroClass.MAGE,
HeroClass.ROGUE,
HeroClass.HUNTRESS
};
private static int heroClassIndex = 0;
private static void addHeroClassIndex(int add) {
heroClassIndex = heroClassIndex + add;
if (heroClassIndex >= heroClasses.length) heroClassIndex -= heroClasses.length;
else if (heroClassIndex < 0) heroClassIndex += heroClasses.length;
}
private static HeroClass heroClass() {
return heroClasses[heroClassIndex];
}
private static final int FRAME_WIDTH = 88;
private static final int FRAME_HEIGHT = 125;
private static final int FRAME_MARGIN_TOP = 9;
private static final int FRAME_MARGIN_X = 4;
private static final int BUTTON_HEIGHT = 20;
private static final int SKY_WIDTH = 80;
private static final int SKY_HEIGHT = 112;
private static final int NSTARS = 100;
private static final int NCLOUDS = 5;
private Camera viewport;
private Avatar a;
private RedButton startBtn;
private Image frame;
//fading UI elements
private ArrayList<StyledButton> heroBtns = new ArrayList<>();
private StyledButton startBtn;
private IconButton infoButton;
private IconButton challengeButton;
private IconButton btnExit;
@Override
public void create() {
super.create();
Dungeon.hero = null;
Badges.loadGlobal();
Journal.loadGlobal();
background = new Image(HeroClass.WARRIOR.splashArt()){
@Override
public void update() {
if (rm > 1f){
rm -= Game.elapsed;
gm = bm = rm;
} else {
rm = gm = bm = 1;
}
// Music.INSTANCE.playTracks(
// new String[]{Assets.Music.THEME},
// new float[]{1},
// false);
uiCamera.visible = false;
int w = Camera.main.width;
int h = Camera.main.height;
Archs archs = new Archs();
archs.setSize( w, h );
add( archs );
float vx = align((w - SKY_WIDTH) / 2f);
float vy = align((h - SKY_HEIGHT - BUTTON_HEIGHT) / 2f);
Point s = Camera.main.cameraToScreen( vx, vy );
viewport = new Camera( s.x, s.y, SKY_WIDTH, SKY_HEIGHT, defaultZoom );
Camera.add( viewport );
Group window = new Group();
window.camera = viewport;
add( window );
boolean dayTime =
Calendar.getInstance().get(Calendar.HOUR_OF_DAY) < 18 && Calendar.getInstance().get(Calendar.HOUR_OF_DAY) > 7;
Sky sky = new Sky( Calendar.getInstance().get(Calendar.HOUR_OF_DAY)) ;
sky.scale.set( SKY_WIDTH, SKY_HEIGHT );
window.add( sky );
if (!dayTime) {
for (int i=0; i < NSTARS; i++) {
float size = Random.Float();
ColorBlock star = new ColorBlock( size, size, 0xFFFFFFFF );
star.x = Random.Float( SKY_WIDTH ) - size / 2;
star.y = Random.Float( SKY_HEIGHT ) - size / 2;
star.am = size * (1 - star.y / SKY_HEIGHT);
window.add( star );
}
};
background.scale.set(Camera.main.height/background.height);
background.x = (Camera.main.width - background.width())/2f;
background.y = (Camera.main.height - background.height())/2f;
background.visible = false;
PixelScene.align(background);
add(background);
if (background.x > 0){
Image fadeLeft = new Image(TextureCache.createGradient(0xFF000000, 0x00000000));
fadeLeft.x = background.x-2;
fadeLeft.scale.set(4, background.height());
add(fadeLeft);
Image fadeRight = new Image(fadeLeft);
fadeRight.x = background.x + background.width() + 2;
fadeRight.y = background.y + background.height();
fadeRight.angle = 180;
add(fadeRight);
}
startBtn = new StyledButton(Chrome.Type.GREY_BUTTON_TR, ""){
float range = SKY_HEIGHT * 2 / 3;
for (int i=0; i < NCLOUDS; i++) {
Cloud cloud = new Cloud( (NCLOUDS - 1 - i) * (range / NCLOUDS) + Random.Float( range / NCLOUDS ), dayTime );
window.add( cloud );
}
int nPatches = (int)(sky.width() / GrassPatch.WIDTH + 1);
for (int i=0; i < nPatches * 4; i++) {
GrassPatch patch = new GrassPatch( (i - 0.75f) * GrassPatch.WIDTH / 4, SKY_HEIGHT + 1, dayTime );
patch.brightness( dayTime ? 0.7f : 0.4f );
window.add( patch );
}
a = new Avatar( heroClass() );
// Removing semitransparent contour
a.am = 2; a.aa = -1;
a.x = (SKY_WIDTH - a.width) / 2;
a.y = SKY_HEIGHT - a.height;
align(a);
window.add( a );
window.add( new PointerArea( a ) {
protected void onClick( PointerEvent event ) {
if (GamesInProgress.selectedClass == null) return;
HeroClass cl = GamesInProgress.selectedClass;
if( cl.isUnlocked() ) ShatteredPixelDungeon.scene().addToFront(new WndHeroInfo(cl));
else ShatteredPixelDungeon.scene().addToFront( new WndMessage(cl.unlockMsg()));
}
} );
for (int i=0; i < nPatches; i++) {
GrassPatch patch = new GrassPatch( (i - 0.5f) * GrassPatch.WIDTH, SKY_HEIGHT, dayTime );
patch.brightness( dayTime ? 1.0f : 0.8f );
window.add( patch );
}
frame = new Image( Assets.Interfaces.NEW_MENU );
frame.frame( FRAME_WIDTH + GrassPatch.WIDTH*4, 0, FRAME_WIDTH, FRAME_HEIGHT );
frame.x = vx - FRAME_MARGIN_X;
frame.y = vy - FRAME_MARGIN_TOP;
add( frame );
if (dayTime) {
a.brightness( 1.2f );
} else {
frame.hardlight( 0xDDEEFF );
}
startBtn = new RedButton( "" ) {
@Override
protected void onClick() {
super.onClick();
@ -126,18 +239,28 @@ public class HeroSelectScene extends PixelScene {
Game.switchScene( InterlevelScene.class );
}
}
public void enable( boolean value ) {
active = value;
text.alpha( value ? 1.0f : 0.3f );
icon.alpha( value ? 1.0f : 0.3f );
}
};
startBtn.icon(Icons.get(Icons.ENTER));
startBtn.setSize(80, 21);
startBtn.setPos((Camera.main.width - startBtn.width())/2f, (Camera.main.height - HeroBtn.HEIGHT + 2 - startBtn.height()));
add(startBtn);
startBtn.visible = false;
add( startBtn );
infoButton = new IconButton(Icons.get(Icons.INFO)){
@Override
protected void onClick() {
super.onClick();
ShatteredPixelDungeon.scene().addToFront(new WndHeroInfo(GamesInProgress.selectedClass));
if (GamesInProgress.selectedClass == null) return;
HeroClass cl = GamesInProgress.selectedClass;
if( cl.isUnlocked() ) ShatteredPixelDungeon.scene().addToFront(new WndHeroInfo(cl));
else ShatteredPixelDungeon.scene().addToFront( new WndMessage(cl.unlockMsg()));
}
@Override
public GameAction keyAction() {
return SPDAction.HERO_INFO;
}
@Override
@ -145,38 +268,22 @@ public class HeroSelectScene extends PixelScene {
return Messages.titleCase(Messages.get(WndKeyBindings.class, "hero_info"));
}
};
infoButton.visible = false;
infoButton.setSize(21, 21);
add(infoButton);
HeroClass[] classes = HeroClass.values();
int btnWidth = HeroBtn.MIN_WIDTH;
int curX = (Camera.main.width - btnWidth * classes.length)/2;
if (curX > 0){
btnWidth += Math.min(curX/(classes.length/2), 15);
curX = (Camera.main.width - btnWidth * classes.length)/2;
}
int heroBtnleft = curX;
for (HeroClass cl : classes){
HeroBtn button = new HeroBtn(cl);
button.setRect(curX, Camera.main.height-HeroBtn.HEIGHT+3, btnWidth, HeroBtn.HEIGHT);
curX += btnWidth;
add(button);
heroBtns.add(button);
}
challengeButton = new IconButton(
Icons.get( SPDSettings.challenges() > 0 ? Icons.CHALLENGE_ON :Icons.CHALLENGE_OFF)){
@Override
protected void onClick() {
ShatteredPixelDungeon.scene().addToFront(new WndChallenges(SPDSettings.challenges(), true) {
public void onBackPressed() {
super.onBackPressed();
icon(Icons.get(SPDSettings.challenges() > 0 ? Icons.CHALLENGE_ON : Icons.CHALLENGE_OFF));
}
} );
if (DeviceCompat.isDebug() || Badges.isUnlocked(Badges.Badge.VICTORY)) {
ShatteredPixelDungeon.scene().addToFront(new WndChallenges(SPDSettings.challenges(), true) {
public void onBackPressed() {
super.onBackPressed();
icon(Icons.get(SPDSettings.challenges() > 0 ? Icons.CHALLENGE_ON : Icons.CHALLENGE_OFF));
}
} );
}
else ShatteredPixelDungeon.scene().addToFront( new WndMessage( Messages.get(HeroSelectScene.class, "challenges_unlock") ));
}
@Override
@ -192,148 +299,414 @@ public class HeroSelectScene extends PixelScene {
return Messages.titleCase(Messages.get(WndChallenges.class, "title"));
}
};
challengeButton.setRect(heroBtnleft + 16, Camera.main.height-HeroBtn.HEIGHT-16, 21, 21);
challengeButton.visible = false;
challengeButton.setRect(startBtn.left() + 16, Camera.main.height- BUTTON_HEIGHT-16, 21, 21);
if (DeviceCompat.isDebug() || Badges.isUnlocked(Badges.Badge.VICTORY)){
add(challengeButton);
} else {
add(challengeButton);
if (!(DeviceCompat.isDebug() || Badges.isUnlocked(Badges.Badge.VICTORY))){
Dungeon.challenges = 0;
SPDSettings.challenges(0);
}
setSelectedHero();
IconButton prevBtn = new IconButton( Icons.get(Icons.LEFTBUTTON) ) {
{
width = 20;
height = 20;
}
@Override
protected void onClick() {
super.onClick();
addHeroClassIndex(-1);
setSelectedHero();
}
@Override
protected String hoverText() {
return Messages.titleCase(Messages.get(WndKeyBindings.class, "prev"));
}
@Override
public GameAction keyAction() {
return GameAction.NONE;
}
};
prevBtn.setSize( BUTTON_HEIGHT, BUTTON_HEIGHT );
prevBtn.setPos( frame.x - BUTTON_HEIGHT - FRAME_MARGIN_X, frame.y + frame.height / 2 - BUTTON_HEIGHT / 2f);
PixelScene.align(prevBtn);
add( prevBtn );
IconButton nextBtn = new IconButton( Icons.get(Icons.RIGHTBUTTON) ) {
{
width = 20;
height = 20;
}
@Override
protected void onClick() {
super.onClick();
addHeroClassIndex(1);
setSelectedHero();
}
@Override
protected String hoverText() {
return Messages.titleCase(Messages.get(WndKeyBindings.class, "next"));
}
@Override
public GameAction keyAction() {
return GameAction.NONE;
}
};
nextBtn.setSize( BUTTON_HEIGHT, BUTTON_HEIGHT );
nextBtn.setPos( frame.x + frame.width + FRAME_MARGIN_X, frame.y + frame.height / 2 - BUTTON_HEIGHT / 2f);
PixelScene.align(nextBtn);
add( nextBtn );
IconButton Telnetsc = new IconButton(new ItemSprite(ItemSpriteSheet.ARTIFACT_SPELLBOOK, null)){
@Override
protected void onClick() {
HeroClass cl = heroClass();
GamesInProgress.selectedClass = cl;
a.heroClass(cl);
ShatteredPixelDungeon.scene().addToFront(new WndMessage(Messages.get(cl, cl.name() + "_story")));
}
};
Telnetsc.setSize( BUTTON_HEIGHT, BUTTON_HEIGHT );
Telnetsc.setPos( frame.x + frame.width + FRAME_MARGIN_X, frame.y + frame.height - BUTTON_HEIGHT);
add(Telnetsc);
IconButton DevMode = new IconButton(Icons.get(Icons.WARNING)){
@Override
protected void onClick() {
//
}
};
DevMode.setSize( BUTTON_HEIGHT, BUTTON_HEIGHT );
DevMode.setPos( frame.x + frame.width + FRAME_MARGIN_X, frame.y-14+ frame.height-14 - BUTTON_HEIGHT);
add(DevMode);
IconButton Rename = new IconButton(Icons.get(Icons.RENAME_OFF)){
@Override
protected void onClick() {
if(!Badges.isUnlocked(Badges.Badge.BOSS_SLAIN_1)){
Game.runOnRenderThread(() -> ShatteredPixelDungeon.scene().add(new WndTextInput(Messages.get(WndStartGame.class,"custom_name"),
Messages.get(WndStartGame.class, "custom_name_desc")+SPDSettings.heroName(),
SPDSettings.heroName(), 20,
false, Messages.get(WndStartGame.class,"custom_name_set"),
Messages.get(WndStartGame.class,"custom_name_clear")){
@Override
public void onSelect(boolean name, String str) {
if (name) {
SPDSettings.heroName(str);
} else {
SPDSettings.heroName("");
}
icon(Icons.get(SPDSettings.heroName().equals("") ? RENAME_OFF : Icons.RENAME_ON));
}
}));
} else {
ShatteredPixelDungeon.scene().addToFront(new WndMessage("击败圣境密林_任意Boss后_解锁重命名功能"));
}
}
};
Rename.setSize( BUTTON_HEIGHT, BUTTON_HEIGHT );
Rename.setPos( frame.x + frame.width + FRAME_MARGIN_X, frame.y-38+ frame.height-38- BUTTON_HEIGHT);
add(Rename);
IconButton EverDayGo = new IconButton(new Image(new PinkLingSprite())) {
@Override
protected void onClick() {
if(!Badges.isUnlocked(Badges.Badge.BOSS_SLAIN_1)){
Game.runOnRenderThread(() -> ShatteredPixelDungeon.scene().add(new WndTextInput(Messages.get(WndStartGame.class,"custom_name"),
Messages.get(WndStartGame.class, "custom_name_desc")+SPDSettings.heroName(),
SPDSettings.heroName(), 20,
false, Messages.get(WndStartGame.class,"custom_name_set"),
Messages.get(WndStartGame.class,"custom_name_clear")){
@Override
public void onSelect(boolean name, String str) {
if (name) {
SPDSettings.heroName(str);
} else {
SPDSettings.heroName("");
}
icon(Icons.get(SPDSettings.heroName().equals("") ? RENAME_OFF : Icons.RENAME_ON));
}
}));
} else {
ShatteredPixelDungeon.scene().addToFront(new WndMessage("获得_衪人之遇_徽章后解锁每日挑战。"));
}
}
};
EverDayGo.setSize( BUTTON_HEIGHT, BUTTON_HEIGHT );
EverDayGo.setPos( frame.x + frame.width + FRAME_MARGIN_X, frame.y-51+ frame.height-51- BUTTON_HEIGHT);
add(EverDayGo);
btnExit = new ExitButton();
btnExit.setPos( Camera.main.width - btnExit.width(), 0 );
add( btnExit );
btnExit.visible = !SPDSettings.intro() || Rankings.INSTANCE.totalNumber > 0;
if (landscape()) {
prompt = PixelScene.renderTextBlock(Messages.get(this, "title"), 12);
prompt.hardlight(Window.TITLE_COLOR);
prompt.setPos( (Camera.main.width - prompt.width())/2f, (Camera.main.height - HeroBtn.HEIGHT - prompt.height() - 4));
PixelScene.align(prompt);
add(prompt);
} else {
Image title = new Image(Assets.Interfaces.MENUTITLE, 0, 0, 126, 34);
PointerArea fadeResetter = new PointerArea(0, 0, Camera.main.width, Camera.main.height){
@Override
public boolean onSignal(PointerEvent event) {
resetFade();
return false;
}
};
add(fadeResetter);
resetFade();
//float topRegion = Math.max(title.height/2, 20f);
if (GamesInProgress.selectedClass != null){
setSelectedHero(GamesInProgress.selectedClass);
title.setPos(frame.x - frame.width / 5f + FRAME_MARGIN_X / 5f, frame.y + frame.height / 8 - BUTTON_HEIGHT - 45);
placeTorch(title.x - 8, title.y + 42);
placeTorch(title.x + 132, title.y + 42);
add(title);
Image twotitle = new Image(Assets.Interfaces.TWOYEARS, 0, 0, 126, 34);
//float topRegion = Math.max(title.height/2, 20f);
twotitle.setPos(frame.x - frame.width / 5f + FRAME_MARGIN_X / 5f, frame.y + frame.height / 4 - BUTTON_HEIGHT - 40);
add(twotitle);
}
fadeIn();
}
private void setSelectedHero(HeroClass cl){
private void placeTorch( float x, float y ) {
Fireball fb2 = new Fireball();
fb2.setPos( x, y );
add( fb2 );
}
@Override
public void destroy() {
Camera.remove( viewport );
super.destroy();
}
private void setSelectedHero() {
HeroClass cl = heroClass();
GamesInProgress.selectedClass = cl;
a.heroClass(cl);
background.texture( cl.splashArt() );
background.visible = true;
background.hardlight(1.5f,1.5f,1.5f);
prompt.visible = false;
startBtn.visible = true;
startBtn.text(Messages.titleCase(cl.title()));
startBtn.textColor(Window.TITLE_COLOR);
startBtn.setSize(startBtn.reqWidth() + 8, 21);
startBtn.setPos((Camera.main.width - startBtn.width())/2f, startBtn.top());
startBtn.textColor(Window.WHITE);
startBtn.setSize(Math.max(startBtn.reqWidth() + 8, SKY_WIDTH - FRAME_MARGIN_X * 2), BUTTON_HEIGHT);
startBtn.setPos( (Camera.main.width - startBtn.width())/2f, frame.y + frame.height + FRAME_MARGIN_X );
PixelScene.align(startBtn);
startBtn.enable( cl.isUnlocked() );
infoButton.visible = true;
infoButton.setPos(startBtn.right(), startBtn.top());
challengeButton.visible = true;
challengeButton.setPos(startBtn.left()-challengeButton.width(), startBtn.top());
}
private float uiAlpha;
@Override
public void update() {
super.update();
btnExit.visible = !SPDSettings.intro() || Rankings.INSTANCE.totalNumber > 0;
//do not fade when a window is open
for (Object v : members){
if (v instanceof Window) resetFade();
public void onBackPressed() {
ShatteredPixelDungeon.switchScene(TitleScene.class);
}
private static class Sky extends Visual {
private static final int[] day = {0xFF4488FF, 0xFFCCEEFF};
private static final int[] night = {0xFF001155, 0xFF335980};
private static final int[][] gradients = new int[][] {
{ 0xff012459, 0xff001322 },
{ 0xff003972, 0xff001322 },
{ 0xff003972, 0xff001322 },
{ 0xff004372, 0xff00182b },
{ 0xff004372, 0xff011d34 },
{ 0xff016792, 0xff00182b },
{ 0xff07729f, 0xff042c47 },
{ 0xff12a1c0, 0xff07506e },
{ 0xff74d4cc, 0xff1386a6 },
{ 0xffefeebc, 0xff61d0cf },
{ 0xfffee154, 0xffa3dec6 },
{ 0xfffdc352, 0xffe8ed92 },
{ 0xffffac6f, 0xffffe467 },
{ 0xfffda65a, 0xffffe467 },
{ 0xfffd9e58, 0xffffe467 },
{ 0xfff18448, 0xffffd364 },
{ 0xfff06b7e, 0xfff9a856 },
{ 0xffca5a92, 0xfff4896b },
{ 0xff5b2c83, 0xffd1628b },
{ 0xff371a79, 0xff713684 },
{ 0xff28166b, 0xff45217c },
{ 0xff192861, 0xff372074 },
{ 0xff040b3c, 0xff233072 },
{ 0xff040b3c, 0xff012459 },
};
private SmartTexture texture;
private FloatBuffer verticesBuffer;
public Sky( int hour ) {
super( 0, 0, 1, 1 );
texture = TextureCache.createGradient( gradients[hour] );
float[] vertices = new float[16];
verticesBuffer = Quad.create();
vertices[2] = 0.25f;
vertices[6] = 0.25f;
vertices[10] = 0.75f;
vertices[14] = 0.75f;
vertices[3] = 0;
vertices[7] = 1;
vertices[11] = 1;
vertices[15] = 0;
vertices[0] = 0;
vertices[1] = 0;
vertices[4] = 1;
vertices[5] = 0;
vertices[8] = 1;
vertices[9] = 1;
vertices[12] = 0;
vertices[13] = 1;
((Buffer)verticesBuffer).position( 0 );
verticesBuffer.put( vertices );
}
if (GamesInProgress.selectedClass != null) {
if (uiAlpha > 0f){
uiAlpha -= Game.elapsed/4f;
@Override
public void draw() {
super.draw();
NoosaScript script = NoosaScript.get();
texture.bind();
script.camera( camera() );
script.uModel.valueM4( matrix );
script.lighting(
rm, gm, bm, am,
ra, ga, ba, aa );
script.drawQuad( verticesBuffer );
}
}
private static class Cloud extends Image {
private static int lastIndex = -1;
public Cloud( float y, boolean dayTime ) {
super( Assets.Interfaces.SURFACE );
int index;
do {
index = Random.Int( 3 );
} while (index == lastIndex);
switch (index) {
case 0:
frame( 88, 0, 49, 20 );
break;
case 1:
frame( 88, 20, 49, 22 );
break;
case 2:
frame( 88, 42, 50, 18 );
break;
}
float alpha = GameMath.gate(0f, uiAlpha, 1f);
for (StyledButton b : heroBtns){
b.alpha(alpha);
lastIndex = index;
this.y = y;
scale.set( 1 - y / SKY_HEIGHT );
x = Random.Float( SKY_WIDTH + width() ) - width();
speed.x = scale.x * (dayTime ? +8 : -8);
if (dayTime) {
tint( 0xCCEEFF, 1 - scale.y );
} else {
rm = gm = bm = +3.0f;
ra = ga = ba = -2.1f;
}
startBtn.alpha(alpha);
btnExit.icon().alpha(alpha);
challengeButton.icon().alpha(alpha);
infoButton.icon().alpha(alpha);
}
}
private void resetFade(){
//starts fading after 4 seconds, fades over 4 seconds.
uiAlpha = 2f;
}
@Override
protected void onBackPressed() {
if (btnExit.visible){
ShatteredPixelDungeon.switchScene(TitleScene.class);
} else {
super.onBackPressed();
}
}
private class HeroBtn extends StyledButton {
private HeroClass cl;
private static final int MIN_WIDTH = 20;
private static final int HEIGHT = 24;
HeroBtn ( HeroClass cl ){
super(Chrome.Type.GREY_BUTTON_TR, "");
this.cl = cl;
icon(new Image(cl.spritesheet(), 0, 90, 12, 15));
}
@Override
public void update() {
super.update();
if (cl != GamesInProgress.selectedClass){
if (!cl.isUnlocked()){
icon.brightness(0.1f);
} else {
icon.brightness(0.6f);
}
} else {
icon.brightness(1f);
}
}
@Override
protected void onClick() {
super.onClick();
if( !cl.isUnlocked() ){
ShatteredPixelDungeon.scene().addToFront( new WndMessage(cl.unlockMsg()));
} else if (GamesInProgress.selectedClass == cl) {
ShatteredPixelDungeon.scene().add(new WndHeroInfo(cl));
} else {
setSelectedHero(cl);
if (speed.x > 0 && x > SKY_WIDTH) {
x = -width();
} else if (speed.x < 0 && x < -width()) {
x = SKY_WIDTH;
}
}
}
}
private static class Avatar extends Image {
private static final int WIDTH = 24;
private static final int HEIGHT = 32;
public Avatar( HeroClass cl ) {
super( Assets.Sprites.AVATARS );
frame( new TextureFilm( texture, WIDTH, HEIGHT ).get( cl.ordinal() ) );
}
public void heroClass( HeroClass cl ) {
frame( new TextureFilm( texture, WIDTH, HEIGHT ).get( cl.ordinal() ) );
}
}
private static class GrassPatch extends Image {
public static final int WIDTH = 16;
public static final int HEIGHT = 14;
private float tx;
private float ty;
private double a = Random.Float( 5 );
private double angle;
private boolean forward;
public GrassPatch( float tx, float ty, boolean forward ) {
super( Assets.Interfaces.SURFACE );
frame( 88 + Random.Int( 4 ) * WIDTH, 60, WIDTH, HEIGHT );
this.tx = tx;
this.ty = ty;
this.forward = forward;
}
@Override
public void update() {
super.update();
a += Random.Float( Game.elapsed * 5 );
angle = (2 + Math.cos( a )) * (forward ? +0.2 : -0.2);
scale.y = (float)Math.cos( angle );
x = tx + (float)Math.tan( angle ) * width;
y = ty - scale.y * height;
}
@Override
protected void updateMatrix() {
super.updateMatrix();
Matrix.skewX( matrix, (float)(angle / Matrix.G2RAD) );
}
}
}

View File

@ -35,7 +35,6 @@ import com.shatteredpixel.shatteredpixeldungeon.ui.Icons;
import com.shatteredpixel.shatteredpixeldungeon.ui.RenderedTextBlock;
import com.shatteredpixel.shatteredpixeldungeon.ui.Window;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndGameInProgress;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndStartGame;
import com.watabou.noosa.BitmapText;
import com.watabou.noosa.Camera;
import com.watabou.noosa.Image;
@ -266,9 +265,18 @@ public class StartScene extends PixelScene {
@Override
//old select scene like good,I don't like new select scene.
// protected void onClick() {
// if (newGame) {
// ShatteredPixelDungeon.scene().add( new WndStartGame(slot));
// } else {
// ShatteredPixelDungeon.scene().add( new WndGameInProgress(slot));
// }
// }
protected void onClick() {
if (newGame) {
ShatteredPixelDungeon.scene().add( new WndStartGame(slot));
GamesInProgress.selectedClass = null;
GamesInProgress.curSlot = slot;
ShatteredPixelDungeon.switchScene(HeroSelectScene.class);
} else {
ShatteredPixelDungeon.scene().add( new WndGameInProgress(slot));
}

View File

@ -35,7 +35,6 @@ import com.watabou.noosa.Camera;
import com.watabou.noosa.Image;
import com.watabou.noosa.NinePatch;
import com.watabou.noosa.ui.Component;
import com.watabou.utils.DeviceCompat;
public class SupporterScene extends PixelScene {

View File

@ -49,8 +49,8 @@ import com.watabou.noosa.Game;
import com.watabou.noosa.Group;
import com.watabou.noosa.Image;
import com.watabou.noosa.NoosaScript;
import com.watabou.noosa.TextureFilm;
import com.watabou.noosa.PointerArea;
import com.watabou.noosa.TextureFilm;
import com.watabou.noosa.Visual;
import com.watabou.noosa.audio.Music;
import com.watabou.utils.Point;

View File

@ -28,6 +28,7 @@ import com.watabou.utils.ColorMath;
import com.watabou.utils.DeviceCompat;
import com.watabou.utils.GameMath;
import com.watabou.utils.Point;
import com.watabou.utils.Random;
import java.util.Date;
@ -37,11 +38,10 @@ public class TitleScene extends PixelScene {
@Override
public void create() {
super.create();
Music.INSTANCE.play( Assets.Music.THEME, true );
Music.INSTANCE.play(Random.Float() < 0.6f ? Assets.Music.THEME : Assets.Music.THEME_1, true);
uiCamera.visible = false;

View File

@ -45,6 +45,8 @@ public enum Icons {
MAGE,
ROGUE,
HUNTRESS,
LEFTBUTTON,
RIGHTBUTTON,
//grey icons, mainly used for buttons, spacing for 16x16
EXIT,
@ -160,6 +162,12 @@ public enum Icons {
case HUNTRESS:
icon.frame( icon.texture.uvRectBySize( 64, 16, 16, 16 ) );
break;
case LEFTBUTTON:
icon.frame( icon.texture.uvRectBySize( 80, 16, 9, 9 ) );
break;
case RIGHTBUTTON:
icon.frame( icon.texture.uvRectBySize( 97, 16, 9, 9 ) );
break;
case EXIT:
icon.frame( icon.texture.uvRectBySize( 0, 32, 15, 11 ) );

View File

@ -124,15 +124,17 @@ public class DesktopPlatformSupport extends PlatformSupport {
fonts = new HashMap<>();
if (systemfont) {
basicFontGenerator = asianFontGenerator = new FreeTypeFontGenerator(Gdx.files.internal("fonts/droid_sans.ttf"));
basicFontGenerator = asianFontGenerator = fallbackFontGenerator = new FreeTypeFontGenerator(Gdx.files.internal("fonts/droid_sans.ttf"));
} else {
basicFontGenerator = new FreeTypeFontGenerator(Gdx.files.internal("fonts/pixel_font.ttf"));
asianFontGenerator = new FreeTypeFontGenerator(Gdx.files.internal("fonts/droid_sans.ttf"));
asianFontGenerator = new FreeTypeFontGenerator(Gdx.files.internal("fonts/fusion_pixel.ttf"));
fallbackFontGenerator = new FreeTypeFontGenerator(Gdx.files.internal("fonts/droid_sans.ttf"));
}
fonts.put(basicFontGenerator, new HashMap<>());
fonts.put(asianFontGenerator, new HashMap<>());
fonts.put(fallbackFontGenerator, new HashMap<>());
packer = new PixmapPacker(pageSize, pageSize, Pixmap.Format.RGBA8888, 1, false);
}