001package squidpony.squidgrid.gui.gdx; 002 003import com.badlogic.gdx.Gdx; 004import com.badlogic.gdx.graphics.Color; 005import com.badlogic.gdx.graphics.g2d.Batch; 006import com.badlogic.gdx.graphics.g2d.TextureRegion; 007import com.badlogic.gdx.math.MathUtils; 008import com.badlogic.gdx.scenes.scene2d.Actor; 009import com.badlogic.gdx.scenes.scene2d.Group; 010import com.badlogic.gdx.scenes.scene2d.actions.Actions; 011import com.badlogic.gdx.utils.Align; 012import squidpony.IColorCenter; 013import squidpony.panel.IColoredString; 014import squidpony.panel.ISquidPanel; 015import squidpony.squidgrid.Direction; 016import squidpony.squidmath.Coord; 017import squidpony.squidmath.StatefulRNG; 018 019import java.util.*; 020 021/** 022 * Displays text and images in a grid pattern. Supports basic animations. 023 * 024 * Grid width and height settings are in terms of number of cells. Cell width and height 025 * are in terms of number of pixels. 026 * 027 * When text is placed, the background color is set separately from the foreground character. When moved, only the 028 * foreground character is moved. 029 * 030 * @author Eben Howard - http://squidpony.com - howard@squidpony.com 031 */ 032public class SquidPanel extends Group implements ISquidPanel<Color> { 033 034 public float DEFAULT_ANIMATION_DURATION = 0.12F; 035 protected int animationCount = 0; 036 protected Color defaultForeground = Color.WHITE; 037 protected IColorCenter<Color> scc; 038 protected final int cellWidth, cellHeight; 039 protected int gridWidth, gridHeight, gridOffsetX = 0, gridOffsetY = 0; 040 protected final String[][] contents; 041 protected final Color[][] colors; 042 protected Color lightingColor = SColor.WHITE; 043 protected final TextCellFactory textFactory; 044 protected float xOffset, yOffset; 045 protected LinkedHashSet<AnimatedEntity> animatedEntities; 046 protected boolean distanceField = false; 047 048 /** 049 * Creates a bare-bones panel with all default values for text rendering. 050 * 051 * @param gridWidth the number of cells horizontally 052 * @param gridHeight the number of cells vertically 053 */ 054 public SquidPanel(int gridWidth, int gridHeight) { 055 this(gridWidth, gridHeight, new TextCellFactory().defaultSquareFont()); 056 } 057 058 /** 059 * Creates a panel with the given grid and cell size. Uses a default square font. 060 * 061 * @param gridWidth the number of cells horizontally 062 * @param gridHeight the number of cells vertically 063 * @param cellWidth the number of horizontal pixels in each cell 064 * @param cellHeight the number of vertical pixels in each cell 065 */ 066 public SquidPanel(int gridWidth, int gridHeight, int cellWidth, int cellHeight) { 067 this(gridWidth, gridHeight, new TextCellFactory().defaultSquareFont().width(cellWidth).height(cellHeight)); 068 } 069 070 /** 071 * Builds a panel with the given grid size and all other parameters determined by the factory. Even if sprite images 072 * are being used, a TextCellFactory is still needed to perform sizing and other utility functions. 073 * 074 * If the TextCellFactory has not yet been initialized, then it will be sized at 12x12 px per cell. If it is null 075 * then a default one will be created and initialized. 076 * 077 * @param gridWidth the number of cells horizontally 078 * @param gridHeight the number of cells vertically 079 * @param factory the factory to use for cell rendering 080 */ 081 public SquidPanel(int gridWidth, int gridHeight, TextCellFactory factory) { 082 this(gridWidth, gridHeight, factory, DefaultResources.getSCC()); 083 } 084 085 /** 086 * Builds a panel with the given grid size and all other parameters determined by the factory. Even if sprite images 087 * are being used, a TextCellFactory is still needed to perform sizing and other utility functions. 088 * 089 * If the TextCellFactory has not yet been initialized, then it will be sized at 12x12 px per cell. If it is null 090 * then a default one will be created and initialized. 091 * 092 * @param gridWidth the number of cells horizontally 093 * @param gridHeight the number of cells vertically 094 * @param factory the factory to use for cell rendering 095 * @param center 096 * The color center to use. Can be {@code null}, but then must be set later on with 097 * {@link #setColorCenter(IColorCenter)}. 098 */ 099 public SquidPanel(int gridWidth, int gridHeight, TextCellFactory factory, IColorCenter<Color> center) { 100 this(gridWidth, gridHeight, factory, center, 0f, 0f); 101 } 102 103 /** 104 * Builds a panel with the given grid size and all other parameters determined by the factory. Even if sprite images 105 * are being used, a TextCellFactory is still needed to perform sizing and other utility functions. 106 * 107 * If the TextCellFactory has not yet been initialized, then it will be sized at 12x12 px per cell. If it is null 108 * then a default one will be created and initialized. 109 * 110 * @param gridWidth the number of cells horizontally 111 * @param gridHeight the number of cells vertically 112 * @param factory the factory to use for cell rendering 113 * @param center 114 * The color center to use. Can be {@code null}, but then must be set later on with 115 * {@link #setColorCenter(IColorCenter)}. 116 */ 117 public SquidPanel(int gridWidth, int gridHeight, TextCellFactory factory, IColorCenter<Color> center, 118 float xOffset, float yOffset) { 119 this.gridWidth = gridWidth; 120 this.gridHeight = gridHeight; 121 if(center == null) 122 scc = DefaultResources.getSCC(); 123 else 124 scc = center; 125 126 if (factory == null) { 127 textFactory = new TextCellFactory(); 128 } 129 else 130 textFactory = factory; 131 if (!textFactory.initialized()) { 132 textFactory.initByFont(); 133 } 134 135 cellWidth = MathUtils.round(textFactory.actualCellWidth); 136 cellHeight = MathUtils.round(textFactory.actualCellHeight); 137 138 contents = new String[gridWidth][gridHeight]; 139 colors = new Color[gridWidth][gridHeight]; 140 for (int i = 0; i < gridWidth; i++) { 141 Arrays.fill(colors[i], scc.filter(Color.CLEAR)); 142 } 143 144 145 int w = gridWidth * cellWidth; 146 int h = gridHeight * cellHeight; 147 this.xOffset = xOffset; 148 this.yOffset = yOffset; 149 setSize(w, h); 150 animatedEntities = new LinkedHashSet<>(); 151 } 152 153 /** 154 * Places the given characters into the grid starting at 0,0. 155 * 156 * @param chars 157 */ 158 public void put(char[][] chars) { 159 put(0, 0, chars); 160 } 161 162 @Override 163 public void put(/* @Nullable */char[][] chars, Color[][] foregrounds) { 164 if (chars == null) { 165 /* Only colors to put */ 166 final int width = foregrounds.length; 167 final int height = width == 0 ? 0 : foregrounds[0].length; 168 for (int x = 0; x < width; x++) { 169 for (int y = 0; y < height; y++) 170 put(x, y, foregrounds[x][y]); 171 } 172 } else 173 put(0, 0, chars, foregrounds); 174 } 175 176 public void put(char[][] chars, int[][] indices, ArrayList<Color> palette) { 177 put(0, 0, chars, indices, palette); 178 } 179 180 public void put(int xOffset, int yOffset, char[][] chars) { 181 put(xOffset, yOffset, chars, defaultForeground); 182 } 183 184 public void put(int xOffset, int yOffset, char[][] chars, Color[][] foregrounds) { 185 for (int x = xOffset; x < xOffset + chars.length; x++) { 186 for (int y = yOffset; y < yOffset + chars[0].length; y++) { 187 if (x >= 0 && y >= 0 && x < gridWidth && y < gridHeight) {//check for valid input 188 put(x, y, chars[x - xOffset][y - yOffset], foregrounds[x - xOffset][y - yOffset]); 189 } 190 } 191 } 192 } 193 194 public void put(int xOffset, int yOffset, char[][] chars, int[][] indices, ArrayList<Color> palette) { 195 for (int x = xOffset; x < xOffset + chars.length; x++) { 196 for (int y = yOffset; y < yOffset + chars[0].length; y++) { 197 if (x >= 0 && y >= 0 && x < gridWidth && y < gridHeight) {//check for valid input 198 put(x, y, chars[x - xOffset][y - yOffset], palette.get(indices[x - xOffset][y - yOffset])); 199 } 200 } 201 } 202 } 203 204 public void put(int xOffset, int yOffset, Color[][] foregrounds) { 205 for (int x = xOffset; x < xOffset + foregrounds.length; x++) { 206 for (int y = yOffset; y < yOffset + foregrounds[0].length; y++) { 207 if (x >= 0 && y >= 0 && x < gridWidth && y < gridHeight) {//check for valid input 208 put(x, y, '\0', foregrounds[x - xOffset][y - yOffset]); 209 } 210 } 211 } 212 } 213 214 public void put(int xOffset, int yOffset, int[][] indices, ArrayList<Color> palette) { 215 for (int x = xOffset; x < xOffset + indices.length; x++) { 216 for (int y = yOffset; y < yOffset + indices[0].length; y++) { 217 if (x >= 0 && y >= 0 && x < gridWidth && y < gridHeight) {//check for valid input 218 put(x, y, '\0', palette.get(indices[x - xOffset][y - yOffset])); 219 } 220 } 221 } 222 } 223 224 public void put(int xOffset, int yOffset, char[][] chars, Color foreground) { 225 for (int x = xOffset; x < xOffset + chars.length; x++) { 226 for (int y = yOffset; y < yOffset + chars[0].length; y++) { 227 if (x >= 0 && y >= 0 && x < gridWidth && y < gridHeight) {//check for valid input 228 put(x, y, chars[x - xOffset][y - yOffset], foreground); 229 } 230 } 231 } 232 } 233 234 /** 235 * Puts the given string horizontally with the first character at the given offset. 236 * 237 * Does not word wrap. Characters that are not renderable (due to being at negative offsets or offsets greater than 238 * the grid size) will not be shown but will not cause any malfunctions. 239 * 240 * Will use the default color for this component to draw the characters. 241 * 242 * @param xOffset the x coordinate of the first character 243 * @param yOffset the y coordinate of the first character 244 * @param string the characters to be displayed 245 */ 246 public void put(int xOffset, int yOffset, String string) { 247 put(xOffset, yOffset, string, defaultForeground); 248 } 249 250 @Override 251 public void put(int xOffset, int yOffset, IColoredString<? extends Color> cs) { 252 int x = xOffset; 253 for (IColoredString.Bucket<? extends Color> fragment : cs) { 254 final String s = fragment.getText(); 255 final Color color = fragment.getColor(); 256 put(x, yOffset, s, color == null ? getDefaultForegroundColor() : scc.filter(color)); 257 x += s.length(); 258 } 259 } 260 261 @Override 262 public void put(int xOffset, int yOffset, String string, Color foreground) { 263 if (string.length() == 1) { 264 put(xOffset, yOffset, string.charAt(0), foreground); 265 } 266 else 267 { 268 char[][] temp = new char[string.length()][1]; 269 for (int i = 0; i < string.length(); i++) { 270 temp[i][0] = string.charAt(i); 271 } 272 put(xOffset, yOffset, temp, foreground); 273 } 274 } 275 public void put(int xOffset, int yOffset, String string, Color foreground, float colorMultiplier) { 276 if (string.length() == 1) { 277 put(xOffset, yOffset, string.charAt(0), foreground, colorMultiplier); 278 } 279 else 280 { 281 char[][] temp = new char[string.length()][1]; 282 for (int i = 0; i < string.length(); i++) { 283 temp[i][0] = string.charAt(i); 284 } 285 put(xOffset, yOffset, temp, foreground, colorMultiplier); 286 } 287 } 288 289 public void put(int xOffset, int yOffset, char[][] chars, Color foreground, float colorMultiplier) { 290 for (int x = xOffset; x < xOffset + chars.length; x++) { 291 for (int y = yOffset; y < yOffset + chars[0].length; y++) { 292 if (x >= 0 && y >= 0 && x < gridWidth && y < gridHeight) {//check for valid input 293 put(x, y, chars[x - xOffset][y - yOffset], foreground, colorMultiplier); 294 } 295 } 296 } 297 } 298 299 /** 300 * Puts the given string horizontally or optionally vertically, with the first character at the given offset. 301 * 302 * Does not word wrap. Characters that are not renderable (due to being at negative offsets or offsets greater than 303 * the grid size) will not be shown but will not cause any malfunctions. 304 * 305 * Will use the default color for this component to draw the characters. 306 * 307 * @param xOffset the x coordinate of the first character 308 * @param yOffset the y coordinate of the first character 309 * @param string the characters to be displayed 310 * @param vertical true if the text should be written vertically, from top to bottom 311 */ 312 public void placeVerticalString(int xOffset, int yOffset, String string, boolean vertical) { 313 put(xOffset, yOffset, string, defaultForeground, vertical); 314 } 315 316 /** 317 * Puts the given string horizontally or optionally vertically, with the first character at the given offset. 318 * 319 * Does not word wrap. Characters that are not renderable (due to being at negative offsets or offsets greater than 320 * the grid size) will not be shown but will not cause any malfunctions. 321 * 322 * @param xOffset the x coordinate of the first character 323 * @param yOffset the y coordinate of the first character 324 * @param string the characters to be displayed 325 * @param foreground the color to draw the characters 326 * @param vertical true if the text should be written vertically, from top to bottom 327 */ 328 public void put(int xOffset, int yOffset, String string, Color foreground, boolean vertical) { 329 if (vertical) { 330 put(xOffset, yOffset, new char[][]{string.toCharArray()}, foreground); 331 } else { 332 put(xOffset, yOffset, string, foreground); 333 } 334 } 335 336 /** 337 * Erases the entire panel, leaving only a transparent space. 338 */ 339 public void erase() { 340 for (int i = 0; i < contents.length; i++) { 341 Arrays.fill(contents[i], "\0"); 342 Arrays.fill(colors[i], Color.CLEAR); 343 /* 344 for (int j = 0; j < contents[i].length; j++) { 345 contents[i][j] = "\0"; 346 colors[i][j] = Color.CLEAR; 347 } 348 */ 349 } 350 } 351 352 @Override 353 public void clear(int x, int y) { 354 put(x, y, Color.CLEAR); 355 } 356 357 @Override 358 public void put(int x, int y, Color color) { 359 put(x, y, '\0', color); 360 } 361 362 public void put(int x, int y, Color color, float colorMultiplier) { 363 put(x, y, '\0', color, colorMultiplier); 364 } 365 366 @Override 367 public void put(int x, int y, char c) { 368 put(x, y, c, defaultForeground); 369 } 370 371 /** 372 * Takes a unicode codepoint for input. 373 * 374 * @param x 375 * @param y 376 * @param code 377 */ 378 public void put(int x, int y, int code) { 379 put(x, y, code, defaultForeground); 380 } 381 382 public void put(int x, int y, int c, Color color) { 383 put(x, y, String.valueOf(Character.toChars(c)), color); 384 } 385 386 public void put(int x, int y, int index, ArrayList<Color> palette) { 387 put(x, y, palette.get(index)); 388 } 389 390 public void put(int x, int y, char c, int index, ArrayList<Color> palette) { 391 put(x, y, c, palette.get(index)); 392 } 393 394 /** 395 * Takes a unicode codepoint for input. 396 * 397 * @param x 398 * @param y 399 * @param c 400 * @param color 401 */ 402 @Override 403 public void put(int x, int y, char c, Color color) { 404 if (x < 0 || x >= gridWidth || y < 0 || y >= gridHeight) { 405 return;//skip if out of bounds 406 } 407 contents[x][y] = String.valueOf(c); 408 colors[x][y] = scc.filter(color); 409 } 410 411 /** 412 * @throws UnsupportedOperationException 413 * If the backing {@link IColorCenter} isn't an instance of 414 * {@link SquidColorCenter}. 415 */ 416 public void put(int x, int y, char c, Color color, float colorMultiplier) { 417 if (x < 0 || x >= gridWidth || y < 0 || y >= gridHeight) { 418 return;//skip if out of bounds 419 } 420 contents[x][y] = String.valueOf(c); 421 if (!(scc instanceof SquidColorCenter)) 422 throw new UnsupportedOperationException("This method required the color center to be a " 423 + SquidColorCenter.class.getSimpleName()); 424 colors[x][y] = ((SquidColorCenter) scc).lerp(color, lightingColor, colorMultiplier); 425 } 426 427 @Override 428 public int cellWidth() { 429 return cellWidth; 430 } 431 432 @Override 433 public int cellHeight() { 434 return cellHeight; 435 } 436 437 @Override 438 public int gridHeight() { 439 return gridHeight; 440 } 441 442 @Override 443 public int gridWidth() { 444 return gridWidth; 445 } 446 447 /** 448 * @return The {@link TextCellFactory} backing {@code this}. 449 */ 450 public TextCellFactory getTextCellFactory() { 451 return textFactory; 452 } 453 454 /** 455 * Sets the size of the text in this SquidPanel (but not the size of the cells) to the given width and height in 456 * pixels (which may be stretched by viewports later on, if your program uses them). 457 * @param wide the width of a glyph in pixels 458 * @param high the height of a glyph in pixels 459 * @return this for chaining 460 */ 461 public SquidPanel setTextSize(int wide, int high) 462 { 463 textFactory.tweakHeight(high).tweakWidth(wide).initBySize(); 464 //textFactory.setSmoothingMultiplier((3f + Math.max(cellWidth * 1f / wide, cellHeight * 1f / high)) / 4f); 465 return this; 466 } 467 468 @Override 469 public void draw (Batch batch, float parentAlpha) { 470 /*if(batch.isDrawing()) { 471 batch.end(); 472 batch.begin(); 473 }*/ 474 textFactory.configureShader(batch); 475 Color tmp; 476 477 for (int x = gridOffsetX; x < gridWidth; x++) { 478 for (int y = gridOffsetY; y < gridHeight; y++) { 479 tmp = scc.filter(colors[x][y]); 480 textFactory.draw(batch, contents[x][y], tmp, xOffset + /*- getX() + */1f * x * cellWidth, 481 yOffset + /*- getY() + */1f * (gridHeight - y) * cellHeight + 1f); 482 } 483 } 484 super.draw(batch, parentAlpha); 485 for(AnimatedEntity ae : animatedEntities) 486 { 487 ae.actor.act(Gdx.graphics.getDeltaTime()); 488 } 489 } 490 491 /** 492 * Draws one AnimatedEntity, specifically the Actor it contains. Batch must be between start() and end() 493 * @param batch Must have start() called already but not stop() yet during this frame. 494 * @param parentAlpha This can be assumed to be 1.0f if you don't know it 495 * @param ae The AnimatedEntity to draw; the position to draw ae is stored inside it. 496 */ 497 public void drawActor(Batch batch, float parentAlpha, AnimatedEntity ae) 498 { 499 ae.actor.draw(batch, parentAlpha); 500 } 501 502 @Override 503 public void setDefaultForeground(Color defaultForeground) { 504 this.defaultForeground = defaultForeground; 505 } 506 507 @Override 508 public Color getDefaultForegroundColor() { 509 return defaultForeground; 510 } 511 512 public AnimatedEntity getAnimatedEntityByCell(int x, int y) { 513 for(AnimatedEntity ae : animatedEntities) 514 { 515 if(ae.gridX == x && ae.gridY == y) 516 return ae; 517 } 518 return null; 519 } 520 521 /** 522 * Create an AnimatedEntity at position x, y, using the char c in the given color. 523 * @param x 524 * @param y 525 * @param c 526 * @param color 527 * @return 528 */ 529 public AnimatedEntity animateActor(int x, int y, char c, Color color) 530 { 531 return animateActor(x, y, false, String.valueOf(c), color); 532 /* 533 Actor a = textFactory.makeActor("" + c, color); 534 a.setName("" + c); 535 a.setPosition(x * cellWidth + getX(), (gridHeight - y - 1) * cellHeight - textFactory.getDescent() + getY()); 536 537 AnimatedEntity ae = new AnimatedEntity(a, x, y); 538 animatedEntities.add(ae); 539 return ae; 540 */ 541 } 542 543 /** 544 * Create an AnimatedEntity at position x, y, using the char c in the given color. If doubleWidth is true, treats 545 * the char c as the left char to be placed in a grid of 2-char cells. 546 * @param x 547 * @param y 548 * @param doubleWidth 549 * @param c 550 * @param color 551 * @return 552 */ 553 public AnimatedEntity animateActor(int x, int y, boolean doubleWidth, char c, Color color) 554 { 555 return animateActor(x, y, doubleWidth, String.valueOf(c), color); 556 /* 557 Actor a = textFactory.makeActor("" + c, color); 558 a.setName("" + c); 559 if(doubleWidth) 560 a.setPosition(x * 2 * cellWidth + getX(), (gridHeight - y - 1) * cellHeight - textFactory.getDescent() + getY()); 561 else 562 a.setPosition(x * cellWidth + getX(), (gridHeight - y - 1) * cellHeight - textFactory.getDescent() + getY()); 563 564 AnimatedEntity ae = new AnimatedEntity(a, x, y, doubleWidth); 565 animatedEntities.add(ae); 566 return ae; 567 */ 568 } 569 570 /** 571 * Create an AnimatedEntity at position x, y, using the String s in the given color. 572 * @param x 573 * @param y 574 * @param s 575 * @param color 576 * @return 577 */ 578 public AnimatedEntity animateActor(int x, int y, String s, Color color) 579 { 580 return animateActor(x, y, false, s, color); 581 /* 582 Actor a = textFactory.makeActor(s, color); 583 a.setName(s); 584 a.setPosition(x * cellWidth + getX(), (gridHeight - y - 1) * cellHeight - textFactory.getDescent() + getY()); 585 586 AnimatedEntity ae = new AnimatedEntity(a, x, y); 587 animatedEntities.add(ae); 588 return ae; 589 */ 590 } 591 592 /** 593 * Create an AnimatedEntity at position x, y, using the String s in the given color. If doubleWidth is true, treats 594 * the String s as starting in the left cell of a pair to be placed in a grid of 2-char cells. 595 * @param x 596 * @param y 597 * @param doubleWidth 598 * @param s 599 * @param color 600 * @return 601 */ 602 public AnimatedEntity animateActor(int x, int y, boolean doubleWidth, String s, Color color) 603 { 604 Actor a = textFactory.makeActor(s, color); 605 a.setName(s); 606 a.setPosition(adjustX(x, doubleWidth), adjustY(y)); 607 /* 608 if(doubleWidth) 609 a.setPosition(x * 2 * cellWidth + getX(), (gridHeight - y - 1) * cellHeight - textFactory.getDescent() + getY()); 610 else 611 a.setPosition(x * cellWidth + getX(), (gridHeight - y - 1) * cellHeight - textFactory.getDescent() + getY()); 612 */ 613 AnimatedEntity ae = new AnimatedEntity(a, x, y, doubleWidth); 614 animatedEntities.add(ae); 615 return ae; 616 } 617 /** 618 * Create an AnimatedEntity at position x, y, using the String s in the given color. If doubleWidth is true, treats 619 * the String s as starting in the left cell of a pair to be placed in a grid of 2-char cells. 620 * @param x 621 * @param y 622 * @param doubleWidth 623 * @param s 624 * @param colors 625 * @return 626 */ 627 public AnimatedEntity animateActor(int x, int y, boolean doubleWidth, String s, Collection<Color> colors) 628 { 629 Actor a = textFactory.makeActor(s, colors); 630 a.setName(s); 631 a.setPosition(adjustX(x, doubleWidth), adjustY(y)); 632 /* 633 if(doubleWidth) 634 a.setPosition(x * 2 * cellWidth + getX(), (gridHeight - y - 1) * cellHeight - textFactory.getDescent() + getY()); 635 else 636 a.setPosition(x * cellWidth + getX(), (gridHeight - y - 1) * cellHeight - textFactory.getDescent() + getY()); 637 */ 638 AnimatedEntity ae = new AnimatedEntity(a, x, y, doubleWidth); 639 animatedEntities.add(ae); 640 return ae; 641 } 642 /** 643 * Create an AnimatedEntity at position x, y, using the String s in the given color. If doubleWidth is true, treats 644 * the String s as starting in the left cell of a pair to be placed in a grid of 2-char cells. 645 * @param x 646 * @param y 647 * @param doubleWidth 648 * @param s 649 * @param colors 650 * @param loopTime 651 * @return 652 */ 653 public AnimatedEntity animateActor(int x, int y, boolean doubleWidth, String s, Collection<Color> colors, float loopTime) 654 { 655 Actor a = textFactory.makeActor(s, colors, loopTime); 656 a.setName(s); 657 a.setPosition(adjustX(x, doubleWidth), adjustY(y)); 658 /* 659 if(doubleWidth) 660 a.setPosition(x * 2 * cellWidth + getX(), (gridHeight - y - 1) * cellHeight - textFactory.getDescent() + getY()); 661 else 662 a.setPosition(x * cellWidth + getX(), (gridHeight - y - 1) * cellHeight - textFactory.getDescent() + getY()); 663 */ 664 AnimatedEntity ae = new AnimatedEntity(a, x, y, doubleWidth); 665 animatedEntities.add(ae); 666 return ae; 667 } 668 669 /** 670 * Create an AnimatedEntity at position x, y, using the char c with a color looked up by index in palette. 671 * @param x 672 * @param y 673 * @param c 674 * @param index 675 * @param palette 676 * @return 677 */ 678 public AnimatedEntity animateActor(int x, int y, char c, int index, ArrayList<Color> palette) 679 { 680 return animateActor(x, y, c, palette.get(index)); 681 } 682 683 /** 684 * Create an AnimatedEntity at position x, y, using the String s with a color looked up by index in palette. 685 * @param x 686 * @param y 687 * @param s 688 * @param index 689 * @param palette 690 * @return 691 */ 692 public AnimatedEntity animateActor(int x, int y, String s, int index, ArrayList<Color> palette) 693 { 694 return animateActor(x, y, s, palette.get(index)); 695 } 696 697 /** 698 * Create an AnimatedEntity at position x, y, using a TextureRegion with no color modifications, which will be 699 * stretched to fit one cell. 700 * @param x 701 * @param y 702 * @param texture 703 * @return 704 */ 705 public AnimatedEntity animateActor(int x, int y, TextureRegion texture) 706 { 707 return animateActor(x, y, false, texture, Color.WHITE); 708 /* 709 Actor a = textFactory.makeActor(texture, Color.WHITE); 710 a.setName(""); 711 a.setPosition(x * cellWidth + getX(), (gridHeight - y - 1) * cellHeight - textFactory.getDescent() + getY()); 712 713 AnimatedEntity ae = new AnimatedEntity(a, x, y); 714 animatedEntities.add(ae); 715 return ae; 716 */ 717 } 718 719 /** 720 * Create an AnimatedEntity at position x, y, using a TextureRegion with the given color, which will be 721 * stretched to fit one cell. 722 * @param x 723 * @param y 724 * @param texture 725 * @param color 726 * @return 727 */ 728 public AnimatedEntity animateActor(int x, int y, TextureRegion texture, Color color) 729 { 730 return animateActor(x, y, false, texture, color); 731 /* 732 Actor a = textFactory.makeActor(texture, color); 733 a.setName(""); 734 a.setPosition(x * cellWidth + getX(), (gridHeight - y - 1) * cellHeight - textFactory.getDescent() + getY()); 735 736 AnimatedEntity ae = new AnimatedEntity(a, x, y); 737 animatedEntities.add(ae); 738 return ae; 739 */ 740 } 741 742 /** 743 * Create an AnimatedEntity at position x, y, using a TextureRegion with no color modifications, which will be 744 * stretched to fit one cell, or two cells if doubleWidth is true. 745 * @param x 746 * @param y 747 * @param doubleWidth 748 * @param texture 749 * @return 750 */ 751 public AnimatedEntity animateActor(int x, int y, boolean doubleWidth, TextureRegion texture) 752 { 753 return animateActor(x, y, doubleWidth, texture, Color.WHITE); 754 /* 755 Actor a = textFactory.makeActor(texture, Color.WHITE, (doubleWidth ? 2 : 1) * cellWidth, cellHeight); 756 757 a.setName(""); 758 if(doubleWidth) 759 a.setPosition(x * 2 * cellWidth + getX(), (gridHeight - y - 1) * cellHeight - textFactory.getDescent() + getY()); 760 else 761 a.setPosition(x * cellWidth + getX(), (gridHeight - y - 1) * cellHeight - textFactory.getDescent() + getY()); 762 763 AnimatedEntity ae = new AnimatedEntity(a, x, y, doubleWidth); 764 animatedEntities.add(ae); 765 return ae; 766 */ 767 } 768 769 /** 770 * Create an AnimatedEntity at position x, y, using a TextureRegion with the given color, which will be 771 * stretched to fit one cell, or two cells if doubleWidth is true. 772 * @param x 773 * @param y 774 * @param doubleWidth 775 * @param texture 776 * @param color 777 * @return 778 */ 779 public AnimatedEntity animateActor(int x, int y, boolean doubleWidth, TextureRegion texture, Color color) { 780 Actor a = textFactory.makeActor(texture, color, (doubleWidth ? 2 : 1) * cellWidth, cellHeight); 781 a.setName(""); 782 a.setPosition(adjustX(x, doubleWidth), adjustY(y)); 783 /* 784 if (doubleWidth) 785 a.setPosition(x * 2 * cellWidth + getX(), (gridHeight - y - 1) * cellHeight - textFactory.getDescent() + getY()); 786 else 787 a.setPosition(x * cellWidth + getX(), (gridHeight - y - 1) * cellHeight - textFactory.getDescent() + getY()); 788 */ 789 AnimatedEntity ae = new AnimatedEntity(a, x, y, doubleWidth); 790 animatedEntities.add(ae); 791 return ae; 792 } 793 794 /** 795 * Create an AnimatedEntity at position x, y, using a TextureRegion with no color modifications, which, if and only 796 * if stretch is true, will be stretched to fit one cell, or two cells if doubleWidth is true. If stretch is false, 797 * this will preserve the existing size of texture. 798 * @param x 799 * @param y 800 * @param doubleWidth 801 * @param stretch 802 * @param texture 803 * @return 804 */ 805 public AnimatedEntity animateActor(int x, int y, boolean doubleWidth, boolean stretch, TextureRegion texture) 806 { 807 Actor a = (stretch) 808 ? textFactory.makeActor(texture, Color.WHITE, (doubleWidth ? 2 : 1) * cellWidth, cellHeight) 809 : textFactory.makeActor(texture, Color.WHITE, texture.getRegionWidth(), texture.getRegionHeight()); 810 a.setName(""); 811 a.setPosition(adjustX(x, doubleWidth), adjustY(y)); 812 /* 813 if(doubleWidth) 814 a.setPosition(x * 2 * cellWidth + getX(), (gridHeight - y - 1) * cellHeight - textFactory.getDescent() + getY()); 815 else 816 a.setPosition(x * cellWidth + getX(), (gridHeight - y - 1) * cellHeight - textFactory.getDescent() + getY()); 817 */ 818 AnimatedEntity ae = new AnimatedEntity(a, x, y, doubleWidth); 819 animatedEntities.add(ae); 820 return ae; 821 } 822 823 /** 824 * Create an AnimatedEntity at position x, y, using a TextureRegion with the given color, which, if and only 825 * if stretch is true, will be stretched to fit one cell, or two cells if doubleWidth is true. If stretch is false, 826 * this will preserve the existing size of texture. 827 * @param x 828 * @param y 829 * @param doubleWidth 830 * @param stretch 831 * @param texture 832 * @param color 833 * @return 834 */ 835 public AnimatedEntity animateActor(int x, int y, boolean doubleWidth, boolean stretch, TextureRegion texture, Color color) { 836 837 Actor a = (stretch) 838 ? textFactory.makeActor(texture, color, (doubleWidth ? 2 : 1) * cellWidth, cellHeight) 839 : textFactory.makeActor(texture, color, texture.getRegionWidth(), texture.getRegionHeight()); 840 a.setName(""); 841 a.setPosition(adjustX(x, doubleWidth), adjustY(y)); 842 /* 843 if (doubleWidth) 844 a.setPosition(x * 2 * cellWidth + getX(), (gridHeight - y - 1) * cellHeight - textFactory.getDescent() + getY()); 845 else 846 a.setPosition(x * cellWidth + getX(), (gridHeight - y - 1) * cellHeight - textFactory.getDescent() + getY()); 847 */ 848 AnimatedEntity ae = new AnimatedEntity(a, x, y, doubleWidth); 849 animatedEntities.add(ae); 850 return ae; 851 } 852 853 /** 854 * Created an Actor from the contents of the given x,y position on the grid. 855 * @param x 856 * @param y 857 * @return 858 */ 859 public Actor cellToActor(int x, int y) 860 { 861 return cellToActor(x, y, false); 862 } 863 864 /** 865 * Created an Actor from the contents of the given x,y position on the grid. 866 * @param x 867 * @param y 868 * @param doubleWidth 869 * @return 870 */ 871 public Actor cellToActor(int x, int y, boolean doubleWidth) 872 { 873 if(contents[x][y] == null || contents[x][y].equals("")) 874 return null; 875 876 Actor a = textFactory.makeActor(contents[x][y], scc.filter(colors[x][y])); 877 a.setName(contents[x][y]); 878 a.setPosition(adjustX(x, doubleWidth) - getX() * 2, adjustY(y) - getY() * 2); // - textFactory.lineHeight * 0.25f 879 880 /* 881 if(doubleWidth) 882 a.setPosition(x * 2 * cellWidth + getX(), (gridHeight - y - 1) * cellHeight - textFactory.getDescent() + getY()); 883 else 884 a.setPosition(x * cellWidth + getX(), (gridHeight - y - 1) * cellHeight - textFactory.getDescent() + getY()); 885 */ 886 887 addActor(a); 888 889 //contents[x][y] = ""; 890 return a; 891 } 892 893 public float adjustX(float x, boolean doubleWidth) 894 { 895 if(doubleWidth) 896 return x * 2 * cellWidth + getX(); 897 else 898 return x * cellWidth + getX(); 899 } 900 901 public float adjustY(float y) 902 { 903 return (gridHeight - y - 1) * cellHeight + getY() + 1; // - textFactory.lineHeight //textFactory.lineTweak * 3f 904 //return (gridHeight - y - 1) * cellHeight + textFactory.getDescent() * 3 / 2f + getY(); 905 } 906 907 /* 908 public void startAnimation(Actor a, int oldX, int oldY) 909 { 910 Coord tmp = Coord.get(oldX, oldY); 911 912 tmp.x = Math.round(a.getX() / cellWidth); 913 tmp.y = gridHeight - Math.round(a.getY() / cellHeight) - 1; 914 if(tmp.x >= 0 && tmp.x < gridWidth && tmp.y > 0 && tmp.y < gridHeight) 915 { 916 } 917 } 918 */ 919 public void recallActor(Actor a) 920 { 921 animationCount--; 922 int x = Math.round((a.getX() - getX()) / cellWidth), 923 y = gridHeight - (int)((a.getY() - getY()) / cellHeight) - 1; 924 if(x < 0 || y < 0 || x >= contents.length || y >= contents[x].length) 925 return; 926 contents[x][y] = a.getName(); 927 removeActor(a); 928 } 929 public void recallActor(AnimatedEntity ae) 930 { 931 if(ae.doubleWidth) 932 ae.gridX = Math.round((ae.actor.getX() - getX()) / (2 * cellWidth)); 933 else 934 ae.gridX = Math.round((ae.actor.getX() - getX()) / cellWidth); 935 ae.gridY = gridHeight - (int)((ae.actor.getY() - getY()) / cellHeight) - 1; 936 ae.animating = false; 937 animationCount--; 938 } 939 940 /** 941 * Start a bumping animation in the given direction that will last duration seconds. 942 * @param ae an AnimatedEntity returned by animateActor() 943 * @param direction 944 * @param duration a float, measured in seconds, for how long the animation should last; commonly 0.12f 945 */ 946 public void bump(final AnimatedEntity ae, Direction direction, float duration) 947 { 948 final Actor a = ae.actor; 949 final float x = adjustX(ae.gridX, ae.doubleWidth), 950 y = adjustY(ae.gridY); 951 // ae.gridX * cellWidth + (int)getX(), 952 // (gridHeight - ae.gridY - 1) * cellHeight - 1 + (int)getY(); 953 if(a == null || ae.animating) return; 954 duration = clampDuration(duration); 955 animationCount++; 956 ae.animating = true; 957 a.addAction(Actions.sequence( 958 Actions.moveToAligned(x + (direction.deltaX / 3F) * ((ae.doubleWidth) ? 2F : 1F), y + direction.deltaY / 3F, 959 Align.center, duration * 0.35F), 960 Actions.moveToAligned(x, y, Align.bottomLeft, duration * 0.65F), 961 Actions.delay(duration, Actions.run(new Runnable() { 962 @Override 963 public void run() { 964 recallActor(ae); 965 } 966 })))); 967 968 } 969 /** 970 * Start a bumping animation in the given direction that will last duration seconds. 971 * @param x 972 * @param y 973 * @param direction 974 * @param duration a float, measured in seconds, for how long the animation should last; commonly 0.12f 975 */ 976 public void bump(int x, int y, Direction direction, float duration) 977 { 978 final Actor a = cellToActor(x, y); 979 if(a == null) return; 980 duration = clampDuration(duration); 981 animationCount++; 982 float nextX = adjustX(x, false), nextY = adjustY(y); 983 /* 984 x *= cellWidth; 985 y = (gridHeight - y - 1); 986 y *= cellHeight; 987 y -= 1; 988 x += getX(); 989 y += getY(); 990 */ 991 a.addAction(Actions.sequence( 992 Actions.moveToAligned(nextX + direction.deltaX / 3F, nextY + direction.deltaY / 3F, 993 Align.center, duration * 0.35F), 994 Actions.moveToAligned(nextX, nextY, Align.bottomLeft, duration * 0.65F), 995 Actions.delay(duration, Actions.run(new Runnable() { 996 @Override 997 public void run() { 998 recallActor(a); 999 } 1000 })))); 1001 1002 } 1003 1004 /** 1005 * Starts a bumping animation in the direction provided. 1006 * 1007 * @param x 1008 * @param y 1009 * @param direction 1010 */ 1011 public void bump(int x, int y, Direction direction) { 1012 bump(x, y, direction, DEFAULT_ANIMATION_DURATION); 1013 } 1014 /** 1015 * Starts a bumping animation in the direction provided. 1016 * 1017 * @param location 1018 * @param direction 1019 */ 1020 public void bump(Coord location, Direction direction) { 1021 bump(location.x, location.y, direction, DEFAULT_ANIMATION_DURATION); 1022 } 1023 /** 1024 * Start a movement animation for the object at the grid location x, y and moves it to newX, newY over a number of 1025 * seconds given by duration (often 0.12f or somewhere around there). 1026 * @param ae an AnimatedEntity returned by animateActor() 1027 * @param newX 1028 * @param newY 1029 * @param duration 1030 */ 1031 public void slide(final AnimatedEntity ae, int newX, int newY, float duration) 1032 { 1033 final Actor a = ae.actor; 1034 final float nextX = adjustX(newX, ae.doubleWidth), nextY = adjustY(newY); 1035 //final int nextX = newX * cellWidth * ((ae.doubleWidth) ? 2 : 1) + (int)getX(), nextY = (gridHeight - newY - 1) * cellHeight - 1 + (int)getY(); 1036 if(a == null || ae.animating) return; 1037 duration = clampDuration(duration); 1038 animationCount++; 1039 ae.animating = true; 1040 a.addAction(Actions.sequence( 1041 Actions.moveToAligned(nextX, nextY, Align.bottomLeft, duration), 1042 Actions.delay(duration, Actions.run(new Runnable() { 1043 @Override 1044 public void run() { 1045 recallActor(ae); 1046 } 1047 })))); 1048 } 1049 1050 /** 1051 * Start a movement animation for the object at the grid location x, y and moves it to newX, newY over a number of 1052 * seconds given by duration (often 0.12f or somewhere around there). 1053 * @param x 1054 * @param y 1055 * @param newX 1056 * @param newY 1057 * @param duration 1058 */ 1059 public void slide(int x, int y, int newX, int newY, float duration) 1060 { 1061 final Actor a = cellToActor(x, y); 1062 if(a == null) return; 1063 duration = clampDuration(duration); 1064 animationCount++; 1065 float nextX = adjustX(newX, false), nextY = adjustY(newY); 1066 1067 /* 1068 newX *= cellWidth; 1069 newY = (gridHeight - newY - 1); 1070 newY *= cellHeight; 1071 newY -= 1; 1072 x += getX(); 1073 y += getY(); 1074 */ 1075 a.addAction(Actions.sequence( 1076 Actions.moveToAligned(nextX, nextY, Align.bottomLeft, duration), 1077 Actions.delay(duration, Actions.run(new Runnable() { 1078 @Override 1079 public void run() { 1080 recallActor(a); 1081 } 1082 })))); 1083 } 1084 /** 1085 * Starts a movement animation for the object at the given grid location at the default speed. 1086 * 1087 * @param start 1088 * @param end 1089 */ 1090 public void slide(Coord start, Coord end) { 1091 slide(start.x, start.y, end.x, end.y, DEFAULT_ANIMATION_DURATION); 1092 } 1093 1094 /** 1095 * Starts a movement animation for the object at the given grid location at the default speed for one grid square in 1096 * the direction provided. 1097 * 1098 * @param start 1099 * @param direction 1100 */ 1101 public void slide(Coord start, Direction direction) { 1102 slide(start.x, start.y, start.x + direction.deltaX, start.y + direction.deltaY, DEFAULT_ANIMATION_DURATION); 1103 } 1104 1105 /** 1106 * Starts a sliding movement animation for the object at the given location at the provided speed. The duration is 1107 * how many seconds should pass for the entire animation. 1108 * 1109 * @param start 1110 * @param end 1111 * @param duration 1112 */ 1113 public void slide(Coord start, Coord end, float duration) { 1114 slide(start.x, start.y, end.x, end.y, duration); 1115 } 1116 1117 /** 1118 * Starts an wiggling animation for the object at the given location for the given duration in seconds. 1119 * 1120 * @param ae an AnimatedEntity returned by animateActor() 1121 * @param duration 1122 */ 1123 public void wiggle(final AnimatedEntity ae, float duration) { 1124 1125 final Actor a = ae.actor; 1126 final float x = adjustX(ae.gridX, ae.doubleWidth), y = adjustY(ae.gridY); 1127 //final int x = ae.gridX * cellWidth * ((ae.doubleWidth) ? 2 : 1) + (int)getX(), y = (gridHeight - ae.gridY - 1) * cellHeight - 1 + (int)getY(); 1128 if(a == null || ae.animating) 1129 return; 1130 duration = clampDuration(duration); 1131 ae.animating = true; 1132 animationCount++; 1133 StatefulRNG gRandom = DefaultResources.getGuiRandom(); 1134 a.addAction(Actions.sequence( 1135 Actions.moveToAligned(x + (gRandom.nextFloat() - 0.5F) * cellWidth * 0.4f, 1136 y + (gRandom.nextFloat() - 0.5F) * cellHeight * 0.4f, 1137 Align.bottomLeft, duration * 0.2F), 1138 Actions.moveToAligned(x + (gRandom.nextFloat() - 0.5F) * cellWidth * 0.4f, 1139 y + (gRandom.nextFloat() - 0.5F) * cellHeight * 0.4f, 1140 Align.bottomLeft, duration * 0.2F), 1141 Actions.moveToAligned(x + (gRandom.nextFloat() - 0.5F) * cellWidth * 0.4f, 1142 y + (gRandom.nextFloat() - 0.5F) * cellHeight * 0.4f, 1143 Align.bottomLeft, duration * 0.2F), 1144 Actions.moveToAligned(x + (gRandom.nextFloat() - 0.5F) * cellWidth * 0.4f, 1145 y + (gRandom.nextFloat() - 0.5F) * cellHeight * 0.4f, 1146 Align.bottomLeft, duration * 0.2F), 1147 Actions.moveToAligned(x, y, Align.bottomLeft, duration * 0.2F), 1148 Actions.delay(duration, Actions.run(new Runnable() { 1149 @Override 1150 public void run() { 1151 recallActor(ae); 1152 } 1153 })))); 1154 } 1155 /** 1156 * Starts an wiggling animation for the object at the given location for the given duration in seconds. 1157 * 1158 * @param x 1159 * @param y 1160 * @param duration 1161 */ 1162 public void wiggle(int x, int y, float duration) { 1163 final Actor a = cellToActor(x, y); 1164 if(a == null) return; 1165 duration = clampDuration(duration); 1166 animationCount++; 1167 float nextX = adjustX(x, false), nextY = adjustY(y); 1168 /* 1169 x *= cellWidth; 1170 y = (gridHeight - y - 1); 1171 y *= cellHeight; 1172 y -= 1; 1173 x += getX(); 1174 y += getY(); 1175 */ 1176 StatefulRNG gRandom = DefaultResources.getGuiRandom(); 1177 a.addAction(Actions.sequence( 1178 Actions.moveToAligned(nextX + (gRandom.nextFloat() - 0.5F) * cellWidth * 0.4f, 1179 nextY + (gRandom.nextFloat() - 0.5F) * cellHeight * 0.4f, 1180 Align.bottomLeft, duration * 0.2F), 1181 Actions.moveToAligned(nextX + (gRandom.nextFloat() - 0.5F) * cellWidth * 0.4f, 1182 nextY + (gRandom.nextFloat() - 0.5F) * cellHeight * 0.4f, 1183 Align.bottomLeft, duration * 0.2F), 1184 Actions.moveToAligned(nextX + (gRandom.nextFloat() - 0.5F) * cellWidth * 0.4f, 1185 nextY + (gRandom.nextFloat() - 0.5F) * cellHeight * 0.4f, 1186 Align.bottomLeft, duration * 0.2F), 1187 Actions.moveToAligned(nextX + (gRandom.nextFloat() - 0.5F) * cellWidth * 0.4f, 1188 nextY + (gRandom.nextFloat() - 0.5F) * cellHeight * 0.4f, 1189 Align.bottomLeft, duration * 0.2F), 1190 Actions.moveToAligned(nextX, nextY, Align.bottomLeft, duration * 0.2F), 1191 Actions.delay(duration, Actions.run(new Runnable() { 1192 @Override 1193 public void run() { 1194 recallActor(a); 1195 } 1196 })))); 1197 } 1198 1199 /** 1200 * Starts a tint animation for {@code ae} for the given {@code duration} in seconds. 1201 * 1202 * @param ae an AnimatedEntity returned by animateActor() 1203 * @param color 1204 * @param duration 1205 */ 1206 public void tint(final AnimatedEntity ae, Color color, float duration) { 1207 final Actor a = ae.actor; 1208 if(a == null) 1209 return; 1210 duration = clampDuration(duration); 1211 ae.animating = true; 1212 animationCount++; 1213 Color ac = scc.filter(a.getColor()); 1214 a.addAction(Actions.sequence( 1215 Actions.color(color, duration * 0.3f), 1216 Actions.color(ac, duration * 0.7f), 1217 Actions.delay(duration, Actions.run(new Runnable() { 1218 @Override 1219 public void run() { 1220 recallActor(ae); 1221 } 1222 })))); 1223 } 1224 1225 /** 1226 * Like {@link #tint(int, int, Color, float)}, but waits for {@code delay} 1227 * (in seconds) before performing it. 1228 */ 1229 public void tint(float delay, int x, int y, Color color, float duration) { 1230 final Actor a = cellToActor(x, y); 1231 if(a == null) 1232 return; 1233 duration = clampDuration(duration); 1234 animationCount++; 1235 1236 Color ac = scc.filter(a.getColor()); 1237 if(delay > 0) 1238 a.addAction(Actions.sequence( 1239 Actions.delay(delay), 1240 Actions.color(color, duration * 0.3f), 1241 Actions.color(ac, duration * 0.7f), 1242 Actions.delay(0.0f, Actions.run(new Runnable() { 1243 @Override 1244 public void run() { 1245 recallActor(a); 1246 } 1247 })))); 1248 else 1249 a.addAction(Actions.sequence( 1250 Actions.color(color, duration * 0.3f), 1251 Actions.color(ac, duration * 0.7f), 1252 Actions.delay(0.0f, Actions.run(new Runnable() { 1253 @Override 1254 public void run() { 1255 recallActor(a); 1256 } 1257 })))); 1258 /* 1259 Actions.run(new Runnable() { 1260 @Override 1261 public void run() { 1262 recallActor(a); 1263 } 1264 }) 1265 */ 1266 /*Actions.run(new Runnable() { 1267 @Override 1268 public void run() { 1269 recallActor(a); 1270 } 1271 })*/ 1272 } 1273 1274 /** 1275 * Starts a tint animation for the object at {@code (x,y)} for the given 1276 * {@code duration} (in seconds). 1277 */ 1278 public final void tint(int x, int y, Color color, float duration) { 1279 tint(0f, x, y, color, duration); 1280 } 1281 1282 /** 1283 * Fade the cell at {@code (x,y)} to {@code color}. Contrary to 1284 * {@link #tint(int, int, Color, float)}, this action does not restore the 1285 * cell's color at the end of its execution. This is for example useful to 1286 * fade the game screen when the rogue dies. 1287 * 1288 * @param x 1289 * @param y 1290 * @param color 1291 * The color at the end of the fadeout. 1292 * @param duration 1293 * The fadeout's duration. 1294 */ 1295 public void fade(int x, int y, Color color, float duration) { 1296 final Actor a = cellToActor(x, y); 1297 if (a == null) 1298 return; 1299 duration = clampDuration(duration); 1300 animationCount++; 1301 final Color c = scc.filter(color); 1302 a.addAction(Actions.sequence(Actions.color(c, duration), Actions.run(new Runnable() { 1303 @Override 1304 public void run() { 1305 recallActor(a); 1306 } 1307 }))); 1308 } 1309 1310 @Override 1311 public boolean hasActiveAnimations() { 1312 return animationCount != 0; 1313 } 1314 1315 public LinkedHashSet<AnimatedEntity> getAnimatedEntities() { 1316 return animatedEntities; 1317 } 1318 1319 public void removeAnimatedEntity(AnimatedEntity ae) 1320 { 1321 animatedEntities.remove(ae); 1322 } 1323 1324 @Override 1325 public ISquidPanel<Color> getBacker() { 1326 return this; 1327 } 1328 1329 /** 1330 * @return The current color center. Never {@code null}. 1331 */ 1332 public IColorCenter<Color> getColorCenter() { 1333 return scc; 1334 } 1335 1336 /** 1337 * Use this method if you use your own {@link IColorCenter} and want this 1338 * panel not to allocate its own colors (or fill 1339 * {@link DefaultResources#getSCC()} but instead to the provided center. 1340 * 1341 * @param scc 1342 * The color center to use. Should not be {@code null}. 1343 * @return {@code this} 1344 * @throws NullPointerException 1345 * If {@code scc} is {@code null}. 1346 */ 1347 @Override 1348 public SquidPanel setColorCenter(IColorCenter<Color> scc) { 1349 if (scc == null) 1350 /* Better fail now than later */ 1351 throw new NullPointerException( 1352 "The color center should not be null in " + getClass().getSimpleName()); 1353 this.scc = scc; 1354 return this; 1355 } 1356 1357 public String getAt(int x, int y) 1358 { 1359 if(contents[x][y] == null) 1360 return ""; 1361 return contents[x][y]; 1362 } 1363 public Color getColorAt(int x, int y) 1364 { 1365 return colors[x][y]; 1366 } 1367 1368 public Color getLightingColor() { 1369 return lightingColor; 1370 } 1371 1372 public void setLightingColor(Color lightingColor) { 1373 this.lightingColor = lightingColor; 1374 } 1375 1376 protected float clampDuration(float duration) { 1377 if (duration < 0.02f) 1378 return 0.02f; 1379 else 1380 return duration; 1381 } 1382 1383 /** 1384 * The X offset that the whole panel's internals will be rendered at. 1385 * @return the current offset in cells along the x axis 1386 */ 1387 public int getGridOffsetX() { 1388 return gridOffsetX; 1389 } 1390 1391 /** 1392 * Sets the X offset that the whole panel's internals will be rendered at. 1393 * @param gridOffsetX the requested offset in cells; should be less than gridWidth 1394 */ 1395 public void setGridOffsetX(int gridOffsetX) { 1396 if(gridOffsetX < gridWidth) 1397 this.gridOffsetX = gridOffsetX; 1398 } 1399 1400 /** 1401 * The Y offset that the whole panel's internals will be rendered at. 1402 * @return the current offset in cells along the y axis 1403 */ 1404 public int getGridOffsetY() { 1405 return gridOffsetY; 1406 } 1407 1408 /** 1409 * Sets the Y offset that the whole panel's internals will be rendered at. 1410 * @param gridOffsetY the requested offset in cells; should be less than gridHeight 1411 */ 1412 public void setGridOffsetY(int gridOffsetY) { 1413 if(gridOffsetY < gridHeight) 1414 this.gridOffsetY = gridOffsetY; 1415 1416 } 1417 1418 /** 1419 * The number of cells along the x-axis that will be rendered of this panel. 1420 * @return the number of cells along the x-axis that will be rendered of this panel 1421 */ 1422 public int getGridWidth() { 1423 return gridWidth; 1424 } 1425 1426 /** 1427 * Sets the number of cells along the x-axis that will be rendered of this panel to gridWidth. 1428 * @param gridWidth the requested width in cells 1429 */ 1430 public void setGridWidth(int gridWidth) { 1431 this.gridWidth = gridWidth; 1432 } 1433 1434 /** 1435 * The number of cells along the y-axis that will be rendered of this panel 1436 * @return the number of cells along the y-axis that will be rendered of this panel 1437 */ 1438 public int getGridHeight() { 1439 return gridHeight; 1440 } 1441 1442 /** 1443 * Sets the number of cells along the y-axis that will be rendered of this panel to gridHeight. 1444 * @param gridHeight the requested height in cells 1445 */ 1446 public void setGridHeight(int gridHeight) { 1447 this.gridHeight = gridHeight; 1448 } 1449 1450 /** 1451 * Sets the position of the actor's bottom left corner. 1452 * 1453 * @param x 1454 * @param y 1455 */ 1456 @Override 1457 public void setPosition(float x, float y) { 1458 super.setPosition(x, y); 1459 setBounds(x, y, getWidth(), getHeight()); 1460 } 1461 1462 public float getxOffset() { 1463 return xOffset; 1464 } 1465 1466 public void setOffsetX(float xOffset) { 1467 this.xOffset = xOffset; 1468 } 1469 1470 public float getyOffset() { 1471 return yOffset; 1472 } 1473 1474 public void setOffsetY(float yOffset) { 1475 this.yOffset = yOffset; 1476 } 1477 1478 public void setOffsets(float x, float y) { 1479 xOffset = x; 1480 yOffset = y; 1481 } 1482}