mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-11 22:31:52 +09:00
ground hit detection and adjust player position accordingly (it's working at least)
Former-commit-id: be639eeeac82b35aae145540ede5e0b1f3b02d01 Former-commit-id: 4d214a5160cd80955909da238c3991ede5488ca6
This commit is contained in:
@@ -1,48 +0,0 @@
|
||||
package com.Torvald.ColourUtil;
|
||||
|
||||
import org.newdawn.slick.Color;
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 16-01-23.
|
||||
*/
|
||||
public class Col12 {
|
||||
|
||||
private short data;
|
||||
|
||||
/**
|
||||
* Create new Col12 format
|
||||
* @param data 0x000-0xFFF, in RGB
|
||||
*/
|
||||
public Col12(int data) {
|
||||
this.data = (short) data;
|
||||
}
|
||||
|
||||
public Color create(int i) {
|
||||
if (i > 0xFFF || i < 0) {
|
||||
throw new IllegalArgumentException("Colour range: #000 - #FFF");
|
||||
}
|
||||
int r = (i & 0xF00) >> 8;
|
||||
int g = (i & 0x0F0) >> 4;
|
||||
int b = i & 0x00F;
|
||||
|
||||
return new Color(
|
||||
(r << 4) | r
|
||||
, (g << 4) | g
|
||||
, (b << 4) | b
|
||||
);
|
||||
}
|
||||
|
||||
public byte[] toByteArray() {
|
||||
byte[] ret = new byte[3];
|
||||
int r = (data & 0xF00) >> 8;
|
||||
int g = (data & 0x0F0) >> 4;
|
||||
int b = data & 0x00F;
|
||||
|
||||
ret[0] = (byte) ((r << 4) | r);
|
||||
ret[1] = (byte) ((g << 4) | g);
|
||||
ret[2] = (byte) ((b << 4) | b);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
73
src/com/Torvald/ColourUtil/Col256.java
Normal file
73
src/com/Torvald/ColourUtil/Col256.java
Normal file
@@ -0,0 +1,73 @@
|
||||
package com.Torvald.ColourUtil;
|
||||
|
||||
import org.newdawn.slick.Color;
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 16-02-07.
|
||||
*
|
||||
* 3-3-2 256 colour RGB
|
||||
*/
|
||||
public class Col256 {
|
||||
|
||||
private byte data;
|
||||
|
||||
/**
|
||||
* Create new Col256 format.
|
||||
* @param data 0x00-0xFF
|
||||
*/
|
||||
public Col256(int data) {
|
||||
this.data = (byte) data;
|
||||
}
|
||||
|
||||
public Col256(int r, int g, int b) {
|
||||
if (r > 7 || g > 7 || b > 3) {
|
||||
throw new IllegalArgumentException("Colour range: RG: 0-7, B:0-4");
|
||||
}
|
||||
|
||||
data = (byte) (r << 5 | g << 2 | b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Col256 colour and convert it to Slick Color
|
||||
* @param i
|
||||
* @return
|
||||
*/
|
||||
public Color create(int i) {
|
||||
if (i > 0xFF || i < 0) {
|
||||
throw new IllegalArgumentException("Colour range: #00 - #FF");
|
||||
}
|
||||
int r = (i & 0b11100000) >> 5;
|
||||
int g = (i & 0b00011100) >> 2;
|
||||
int b = i & 0b00000011;
|
||||
|
||||
return create(r, g, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Col256 colour and convert it to Slick Color
|
||||
* @return
|
||||
*/
|
||||
public Color create(int r, int g, int b) {
|
||||
if (r > 7 || g > 7 || b > 3) {
|
||||
throw new IllegalArgumentException("Colour range: RG: 0-7, B:0-4");
|
||||
}
|
||||
|
||||
int[] colIndex3 = {0, 36, 73, 109, 146, 182, 219, 255};
|
||||
int[] colIndex2 = {0, 85, 170, 255};
|
||||
|
||||
return new Color(
|
||||
colIndex3[r]
|
||||
, colIndex3[g]
|
||||
, colIndex2[b]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve raw RGB value
|
||||
* @return 0bRRRGGGBB
|
||||
*/
|
||||
public byte getByte() {
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
79
src/com/Torvald/ColourUtil/Col4096.java
Normal file
79
src/com/Torvald/ColourUtil/Col4096.java
Normal file
@@ -0,0 +1,79 @@
|
||||
package com.Torvald.ColourUtil;
|
||||
|
||||
import org.newdawn.slick.Color;
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 16-01-23.
|
||||
*
|
||||
* 12-bit RGB
|
||||
*/
|
||||
public class Col4096 {
|
||||
|
||||
private short data;
|
||||
|
||||
/**
|
||||
* Create new Col4096 format.
|
||||
* @param data 0xARGB
|
||||
*/
|
||||
public Col4096(int data) {
|
||||
this.data = (short) data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Col4096 colour and convert it to Slick Color
|
||||
* @param i
|
||||
* @return
|
||||
*/
|
||||
public Color create(int i) {
|
||||
if (i > 0xFFF) {
|
||||
int a = (i & 0xF000) >> 12;
|
||||
int r = (i & 0x0F00) >> 8;
|
||||
int g = (i & 0x00F0) >> 4;
|
||||
int b = i & 0x000F;
|
||||
|
||||
return new Color(
|
||||
(r << 4) | r
|
||||
, (g << 4) | g
|
||||
, (b << 4) | b
|
||||
, (a << 4) | a
|
||||
);
|
||||
}
|
||||
else {
|
||||
int r = (i & 0xF00) >> 8;
|
||||
int g = (i & 0x0F0) >> 4;
|
||||
int b = i & 0x00F;
|
||||
|
||||
return new Color(
|
||||
(r << 4) | r
|
||||
, (g << 4) | g
|
||||
, (b << 4) | b
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert to 3 byte values, for raster imaging.
|
||||
* @return byte[RR, GG, BB] e.g. 0x4B3 -> 0x44, 0xBB, 0x33
|
||||
*/
|
||||
public byte[] toByteArray() {
|
||||
byte[] ret = new byte[3];
|
||||
int r = (data & 0xF00) >> 8;
|
||||
int g = (data & 0x0F0) >> 4;
|
||||
int b = data & 0x00F;
|
||||
|
||||
ret[0] = (byte) ((r << 4) | r);
|
||||
ret[1] = (byte) ((g << 4) | g);
|
||||
ret[2] = (byte) ((b << 4) | b);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve raw ARGB value
|
||||
* @return 0xARGB
|
||||
*/
|
||||
public short getShort() {
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,6 +15,8 @@ public class GameFontBase implements Font {
|
||||
static SpriteSheet runicSheet;
|
||||
static SpriteSheet extASheet;
|
||||
static SpriteSheet extASheetEF;
|
||||
static SpriteSheet kanaSheet;
|
||||
static SpriteSheet cjkPunct;
|
||||
|
||||
static final int JUNG_COUNT = 21;
|
||||
static final int JONG_COUNT = 28;
|
||||
@@ -24,7 +26,8 @@ public class GameFontBase implements Font {
|
||||
static final int W_LATIN_WIDE = 9; // width of regular letters, including m
|
||||
static final int W_LATIN_NARROW = 5; // width of letter f, t, i, l
|
||||
static final int H = 20;
|
||||
static final int H_CJK = 16;
|
||||
static final int H_HANGUL = 16;
|
||||
static final int H_KANA = 20;
|
||||
|
||||
static final int SHEET_ASCII_EM = 0;
|
||||
static final int SHEET_ASCII_EF = 1;
|
||||
@@ -32,6 +35,8 @@ public class GameFontBase implements Font {
|
||||
static final int SHEET_RUNIC = 3;
|
||||
static final int SHEET_EXTA_EM = 4;
|
||||
static final int SHEET_EXTA_EF = 5;
|
||||
static final int SHEET_KANA = 6;
|
||||
static final int SHEET_CJK_PUNCT = 7;
|
||||
|
||||
static SpriteSheet[] sheetKey;
|
||||
static final Character[] asciiEFList = {
|
||||
@@ -47,12 +52,20 @@ public class GameFontBase implements Font {
|
||||
* Runic letters list used for game. The set is
|
||||
* Younger Futhark + Medieval rune 'e' + Punct + Runic Almanac
|
||||
*
|
||||
* BEWARE OF SIMILAR-LOOKING RUNES, especially:
|
||||
*
|
||||
* * Algiz ᛉ instead of Maðr ᛘ
|
||||
*
|
||||
* * Short-Twig Hagall ᚽ instead of Runic Letter E ᛂ
|
||||
*
|
||||
* * Runic Letter OE ᚯ instead of Óss ᚬ
|
||||
*
|
||||
* Examples:
|
||||
* ᛭ᛋᛁᚴᚱᛁᚦᛦ᛭
|
||||
* ᛭ᛂᛚᛋᛅ᛭ᛏᚱᚢᛏᚾᛁᚾᚴᚢᚾᛅ᛬ᛅᚱᚾᛅᛏᛅᛚᛋ
|
||||
*/
|
||||
static final Character[] runicList = {
|
||||
'ᚠ','ᚢ','ᚦ','ᚯ','ᚱ','ᚴ','ᚼ','ᚾ','ᛁ','ᛅ','ᛋ','ᛏ','ᛒ','ᛘ','ᛚ','ᛦ'
|
||||
'ᚠ','ᚢ','ᚦ','ᚬ','ᚱ','ᚴ','ᚼ','ᚾ','ᛁ','ᛅ','ᛋ','ᛏ','ᛒ','ᛘ','ᛚ','ᛦ'
|
||||
,'ᛂ','᛬','᛫','᛭','ᛮ','ᛯ','ᛰ'
|
||||
};
|
||||
|
||||
@@ -90,6 +103,14 @@ public class GameFontBase implements Font {
|
||||
return (c >= 0x100 && c < 0x180);
|
||||
}
|
||||
|
||||
private boolean isKana(char c) {
|
||||
return (c >= 0x3040 && c < 0x3100);
|
||||
}
|
||||
|
||||
private boolean isCJKPunct(char c) {
|
||||
return (c >= 0x3000 && c < 0x3040);
|
||||
}
|
||||
|
||||
private int asciiEFindexX(char c) {
|
||||
return (Arrays.asList(asciiEFList).indexOf(c) % 16);
|
||||
}
|
||||
@@ -114,6 +135,22 @@ public class GameFontBase implements Font {
|
||||
return (Arrays.asList(runicList).indexOf(c) / 16);
|
||||
}
|
||||
|
||||
private int kanaIndexX(char c) {
|
||||
return (c - 0x3040) % 16;
|
||||
}
|
||||
|
||||
private int kanaIndexY(char c) {
|
||||
return (c - 0x3040) / 16;
|
||||
}
|
||||
|
||||
private int cjkPunctIndexX(char c) {
|
||||
return (c - 0x3000) % 16;
|
||||
}
|
||||
|
||||
private int cjkPunctIndexY(char c) {
|
||||
return (c - 0x3000) / 16;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWidth(String s) {
|
||||
int len = 0;
|
||||
@@ -122,7 +159,7 @@ public class GameFontBase implements Font {
|
||||
switch (getSheetType(c)) {
|
||||
case SHEET_ASCII_EF:
|
||||
len += W_LATIN_NARROW; break;
|
||||
case SHEET_HANGUL:
|
||||
case SHEET_HANGUL: case SHEET_KANA: case SHEET_CJK_PUNCT:
|
||||
len += W_CJK_DRAW; break;
|
||||
default:
|
||||
len += W_LATIN_WIDE;
|
||||
@@ -159,7 +196,7 @@ public class GameFontBase implements Font {
|
||||
Math.round(x
|
||||
+ getWidth(s.substring(0, i))
|
||||
)
|
||||
, Math.round((H - H_CJK) + y)
|
||||
, Math.round((H - H_HANGUL) / 2 + y + 1)
|
||||
, hanPos[0]
|
||||
, hanPos[1]
|
||||
);
|
||||
@@ -200,20 +237,37 @@ public class GameFontBase implements Font {
|
||||
sheetX = (ch - 0x100) % 16;
|
||||
sheetY = (ch - 0x100) / 16;
|
||||
break;
|
||||
case SHEET_KANA:
|
||||
sheetX = kanaIndexX(ch);
|
||||
sheetY = kanaIndexY(ch);
|
||||
break;
|
||||
case SHEET_CJK_PUNCT:
|
||||
sheetX = cjkPunctIndexX(ch);
|
||||
sheetY = cjkPunctIndexY(ch);
|
||||
break;
|
||||
default:
|
||||
sheetX = ch % 16;
|
||||
sheetY = ch / 16;
|
||||
break;
|
||||
}
|
||||
|
||||
sheetKey[prevInstance].renderInUse(
|
||||
Math.round(x
|
||||
+ getWidth(s.substring(0, i))
|
||||
)
|
||||
, Math.round(y)
|
||||
, sheetX
|
||||
, sheetY
|
||||
);
|
||||
try {
|
||||
sheetKey[prevInstance].renderInUse(
|
||||
Math.round(x
|
||||
+ getWidth(s.substring(0, i))
|
||||
)
|
||||
, Math.round(y)
|
||||
, sheetX
|
||||
, sheetY
|
||||
);
|
||||
}
|
||||
catch (ArrayIndexOutOfBoundsException e) {
|
||||
System.out.println("char: '" + ch + "' (" + String.valueOf((int) ch) + ")");
|
||||
System.out.println("sheet: " + prevInstance);
|
||||
System.out.println("sheetX: " + sheetX);
|
||||
System.out.println("sheetY: " + sheetY);
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -229,6 +283,8 @@ public class GameFontBase implements Font {
|
||||
else if (isRunic(c)) return SHEET_RUNIC;
|
||||
else if (isExtA(c)) return SHEET_EXTA_EM;
|
||||
else if (isExtAEF(c)) return SHEET_EXTA_EF;
|
||||
else if (isKana(c)) return SHEET_KANA;
|
||||
else if (isCJKPunct(c)) return SHEET_CJK_PUNCT;
|
||||
else return SHEET_ASCII_EM;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ public class GameFontBlack extends GameFontBase {
|
||||
|
||||
hangulSheet = new SpriteSheet(
|
||||
"./res/graphics/fonts/han_atlas_black.png"
|
||||
, W_CJK, H_CJK
|
||||
, W_CJK, H_HANGUL
|
||||
);
|
||||
asciiSheet = new SpriteSheet(
|
||||
"./res/graphics/fonts/ascii_majuscule_black.png"
|
||||
|
||||
@@ -12,7 +12,7 @@ public class GameFontWhite extends GameFontBase {
|
||||
|
||||
hangulSheet = new SpriteSheet(
|
||||
"./res/graphics/fonts/han_atlas.png"
|
||||
, W_CJK, H_CJK
|
||||
, W_CJK, H_HANGUL
|
||||
);
|
||||
asciiSheet = new SpriteSheet(
|
||||
"./res/graphics/fonts/ascii_majuscule.png"
|
||||
@@ -34,6 +34,14 @@ public class GameFontWhite extends GameFontBase {
|
||||
"./res/graphics/fonts/LatinExtA_ef.png"
|
||||
, W_LATIN_NARROW, H
|
||||
);
|
||||
kanaSheet = new SpriteSheet(
|
||||
"./res/graphics/fonts/kana.png"
|
||||
, W_CJK, H_KANA
|
||||
);
|
||||
cjkPunct = new SpriteSheet(
|
||||
"./res/graphics/fonts/cjkpunct.png"
|
||||
, W_CJK, H_KANA
|
||||
);
|
||||
|
||||
SpriteSheet[] shk = {
|
||||
asciiSheet
|
||||
@@ -42,6 +50,8 @@ public class GameFontWhite extends GameFontBase {
|
||||
, runicSheet
|
||||
, extASheet
|
||||
, extASheetEF
|
||||
, kanaSheet
|
||||
, cjkPunct
|
||||
};
|
||||
sheetKey = shk;
|
||||
}
|
||||
|
||||
@@ -13,17 +13,17 @@ import java.util.Random;
|
||||
* @author Numerical Recipes
|
||||
*/
|
||||
|
||||
public class HighQualityRandom extends Random {
|
||||
public class HQRNG extends Random {
|
||||
|
||||
//private Lock l = new ReentrantLock();
|
||||
private long u;
|
||||
private long v = 4101842887655102017L;
|
||||
private long w = 1;
|
||||
|
||||
public HighQualityRandom() {
|
||||
public HQRNG() {
|
||||
this(System.nanoTime());
|
||||
}
|
||||
public HighQualityRandom(long seed) {
|
||||
public HQRNG(long seed) {
|
||||
//l.lock();
|
||||
u = seed ^ v;
|
||||
nextLong();
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.Torvald.Terrarum.Actors;
|
||||
|
||||
import com.Torvald.Rand.HighQualityRandom;
|
||||
import com.Torvald.Rand.HQRNG;
|
||||
import com.Torvald.Terrarum.MapDrawer.MapDrawer;
|
||||
import com.Torvald.Terrarum.Terrarum;
|
||||
import com.Torvald.spriteAnimation.SpriteAnimation;
|
||||
@@ -35,7 +35,9 @@ public class ActorWithBody implements Actor, Visible, Glowing {
|
||||
private @NotNull float veloX, veloY;
|
||||
private final float VELO_HARD_LIMIT = 10000;
|
||||
|
||||
private boolean grounded = false;
|
||||
boolean grounded = false;
|
||||
boolean walledLeft = false;
|
||||
boolean walledRight = false;
|
||||
|
||||
SpriteAnimation sprite;
|
||||
@Nullable SpriteAnimation spriteGlow;
|
||||
@@ -55,7 +57,8 @@ public class ActorWithBody implements Actor, Visible, Glowing {
|
||||
private float scale = 1;
|
||||
private float mass = 1f;
|
||||
|
||||
private static int TSIZE = MapDrawer.TILE_SIZE;
|
||||
private static final int TSIZE = MapDrawer.TILE_SIZE;
|
||||
private static final int AUTO_CLIMB_RATE = TSIZE / 4;
|
||||
|
||||
/**
|
||||
* Gravitational Constant G. Load from GameMap.
|
||||
@@ -69,6 +72,11 @@ public class ActorWithBody implements Actor, Visible, Glowing {
|
||||
private float gravitation;
|
||||
private final float DRAG_COEFF = 1f;
|
||||
|
||||
private final int CONTACT_AREA_TOP = 0;
|
||||
private final int CONTACT_AREA_RIGHT = 1;
|
||||
private final int CONTACT_AREA_BOTTOM = 2;
|
||||
private final int CONTACT_AREA_LEFT = 3;
|
||||
|
||||
/**
|
||||
* A constant to make falling faster so that the game is more playable
|
||||
*/
|
||||
@@ -77,10 +85,19 @@ public class ActorWithBody implements Actor, Visible, Glowing {
|
||||
long referenceID;
|
||||
|
||||
public ActorWithBody() {
|
||||
referenceID = new HighQualityRandom(0x7E22A211AAL).nextLong();
|
||||
referenceID = new HQRNG(0x7E22A211AAL).nextLong();
|
||||
actorValue = new ActorValue();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param w
|
||||
* @param h
|
||||
* @param tx +: translate drawn sprite to LEFT.
|
||||
* @param ty +: translate drawn sprite to DOWN.
|
||||
* @see ActorWithBody#drawBody(GameContainer, Graphics)
|
||||
* @see ActorWithBody#drawGlow(GameContainer, Graphics)
|
||||
*/
|
||||
public void setHitboxDimension(int w, int h, int tx, int ty) {
|
||||
baseHitboxH = h;
|
||||
baseHitboxW = w;
|
||||
@@ -131,17 +148,16 @@ public class ActorWithBody implements Actor, Visible, Glowing {
|
||||
if (veloY > VELO_HARD_LIMIT) veloY = VELO_HARD_LIMIT;
|
||||
|
||||
// Set 'next' positions to fiddle with
|
||||
updateNextHitbox(delta_t);
|
||||
|
||||
if (!playerNoClip()) {
|
||||
updateNextHitboxY();
|
||||
updateVerticalPos();
|
||||
updateHitboxY();
|
||||
|
||||
updateNextHitboxX();
|
||||
updateHorizontalPos();
|
||||
updateHitboxX();
|
||||
}
|
||||
|
||||
// Apply previous fiddling
|
||||
updateHitbox();
|
||||
|
||||
|
||||
/**
|
||||
* clamp position
|
||||
*/
|
||||
@@ -156,87 +172,6 @@ public class ActorWithBody implements Actor, Visible, Glowing {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawGlow(GameContainer gc, Graphics g) {
|
||||
if (visible && spriteGlow != null) {
|
||||
if (!sprite.flippedHorizontal()) {
|
||||
spriteGlow.render(g
|
||||
, Math.round(hitbox.getPosX() - (hitboxTranslateX * scale))
|
||||
, Math.round(hitbox.getPosY() - hitboxTranslateY * scale)
|
||||
- (baseSpriteHeight - baseHitboxH) * scale
|
||||
+ 1
|
||||
, scale
|
||||
);
|
||||
}
|
||||
else {
|
||||
spriteGlow.render(g
|
||||
, Math.round(hitbox.getPosX() - scale)
|
||||
, Math.round(hitbox.getPosY() - hitboxTranslateY * scale)
|
||||
- (baseSpriteHeight - baseHitboxH) * scale
|
||||
+ 1
|
||||
, scale
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawBody(GameContainer gc, Graphics g) {
|
||||
if (visible) {
|
||||
if (!sprite.flippedHorizontal()) {
|
||||
sprite.render(g
|
||||
, Math.round(hitbox.getPosX() - (hitboxTranslateX * scale))
|
||||
, Math.round(hitbox.getPosY() - hitboxTranslateY * scale)
|
||||
- (baseSpriteHeight - baseHitboxH) * scale
|
||||
+ 1
|
||||
, scale
|
||||
);
|
||||
}
|
||||
else {
|
||||
sprite.render(g
|
||||
, Math.round(hitbox.getPosX() - scale)
|
||||
, Math.round(hitbox.getPosY() - hitboxTranslateY * scale)
|
||||
- (baseSpriteHeight - baseHitboxH) * scale
|
||||
+ 1
|
||||
, scale
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateGlowSprite(GameContainer gc, int delta_t) {
|
||||
if (spriteGlow != null) {
|
||||
spriteGlow.update(delta_t);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBodySprite(GameContainer gc, int delta_t) {
|
||||
sprite.update(delta_t);
|
||||
}
|
||||
|
||||
boolean collideBottomAndAdjusted() {
|
||||
// noclip off?
|
||||
int feetTileX = clampWtile(Math.round((nextHitbox.getPointedX()) / TSIZE));
|
||||
int feetTileY = clampHtile(FastMath.floor(nextHitbox.getPointedY() / TSIZE));
|
||||
|
||||
if (feetTileX < 0) feetTileX = 0;
|
||||
if (feetTileY < 0) feetTileY = 0;
|
||||
|
||||
int feetTile = Terrarum.game.map.getTileFromTerrain(feetTileX, feetTileY);
|
||||
|
||||
if (feetTile != 0) {
|
||||
nextHitbox.setPositionYFromPoint(
|
||||
feetTileY * TSIZE
|
||||
);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply gravitation to the every falling body (unless not levitating)
|
||||
*
|
||||
@@ -266,37 +201,338 @@ public class ActorWithBody implements Actor, Visible, Glowing {
|
||||
}
|
||||
|
||||
private void updateVerticalPos() {
|
||||
if (collideBottomAndAdjusted()) {
|
||||
if (collidedBottomAndAdjusted()) {
|
||||
grounded = true;
|
||||
veloY = 0;
|
||||
}
|
||||
else {
|
||||
grounded = false;
|
||||
}
|
||||
|
||||
if (collidedTopAndAdjusted()) {
|
||||
veloY = 0;
|
||||
}
|
||||
}
|
||||
|
||||
boolean collidedBottomAndAdjusted() {
|
||||
if (getContactArea(CONTACT_AREA_BOTTOM, 0, 1) == 0) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* seemingly adjusted and one pixel below has ground
|
||||
*
|
||||
* seemingly adjusted: adjustHitBottom sets position one pixel above the ground
|
||||
* (stepping on ground in-game look, as the sprite render is one pixel offseted to Y)
|
||||
*/
|
||||
else if (getContactArea(CONTACT_AREA_BOTTOM, 0, 1) > 0
|
||||
&& getContactArea(CONTACT_AREA_BOTTOM, 0, 0) == 0) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
adjustHitBottom();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
boolean collidedTopAndAdjusted() {
|
||||
if (getContactArea(CONTACT_AREA_TOP, 0, -1) == 0) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* seemingly adjusted and one pixel below has ground
|
||||
*
|
||||
* seemingly adjusted: adjustHitBottom sets position one pixel above the ground
|
||||
* (stepping on ground in-game look, as the sprite render is one pixel offseted to Y)
|
||||
*/
|
||||
else if (getContactArea(CONTACT_AREA_TOP, 0, -1) > 0
|
||||
&& getContactArea(CONTACT_AREA_TOP, 0, 0) == 0) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
adjustHitTop();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private void updateHorizontalPos() {
|
||||
|
||||
if (collidedRightAndAdjusted()) { // treat as 'event--collided right'
|
||||
veloX = 0;
|
||||
walledRight = true;
|
||||
}
|
||||
else if (collidedLeftAndAdjusted()) { // treat as 'event--collided left'
|
||||
veloX = 0;
|
||||
walledLeft = true;
|
||||
}
|
||||
else {
|
||||
walledRight = false;
|
||||
walledLeft = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void updateNextHitbox(int delta_t) {
|
||||
boolean collidedRightAndAdjusted() {
|
||||
if (getContactArea(CONTACT_AREA_RIGHT, 1, 0) == 0) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* seemingly adjusted and one pixel below has ground
|
||||
*
|
||||
* seemingly adjusted: adjustHitBottom sets position one pixel above the ground
|
||||
* (stepping on ground in-game look, as the sprite render is one pixel offseted to Y)
|
||||
*/
|
||||
else if (getContactArea(CONTACT_AREA_RIGHT, 1, 0) > 0
|
||||
&& getContactArea(CONTACT_AREA_RIGHT, 0, 0) == 0) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
adjustHitRight();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
boolean collidedLeftAndAdjusted() {
|
||||
if (getContactArea(CONTACT_AREA_LEFT, -1, 0) == 0) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* seemingly adjusted and one pixel below has ground
|
||||
*
|
||||
* seemingly adjusted: adjustHitBottom sets position one pixel above the ground
|
||||
* (stepping on ground in-game look, as the sprite render is one pixel offseted to Y)
|
||||
*/
|
||||
else if (getContactArea(CONTACT_AREA_LEFT, -1, 0) > 0
|
||||
&& getContactArea(CONTACT_AREA_LEFT, 0, 0) == 0) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
adjustHitLeft();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private void updateNextHitboxX() {
|
||||
nextHitbox.set(
|
||||
hitbox.getPosX() + veloX
|
||||
, hitbox.getPosY()
|
||||
, baseHitboxW * scale
|
||||
, baseHitboxH * scale
|
||||
);
|
||||
}
|
||||
|
||||
private void updateNextHitboxY() {
|
||||
nextHitbox.set(
|
||||
hitbox.getPosX()
|
||||
, hitbox.getPosY() + veloY
|
||||
, baseHitboxW * scale
|
||||
, baseHitboxH * scale
|
||||
);
|
||||
}
|
||||
|
||||
private void updateHitbox() {
|
||||
private void updateHitboxX() {
|
||||
hitbox.set(
|
||||
nextHitbox.getPosX()
|
||||
, hitbox.getPosY()
|
||||
, baseHitboxW * scale
|
||||
, baseHitboxH * scale
|
||||
);
|
||||
}
|
||||
|
||||
private void updateHitboxY() {
|
||||
hitbox.set(
|
||||
hitbox.getPosX()
|
||||
, nextHitbox.getPosY()
|
||||
, baseHitboxW * scale
|
||||
, baseHitboxH * scale
|
||||
);
|
||||
}
|
||||
|
||||
private void adjustHitBottom() {
|
||||
int tY = 0;
|
||||
int contactArea = getContactArea(CONTACT_AREA_BOTTOM, 0, 0);
|
||||
for (int lim = 0; lim < TSIZE; lim++) {
|
||||
/**
|
||||
* get contact area and move up and get again.
|
||||
* keep track of this value, and some point they will be set as lowest
|
||||
* and become static. The very point where the value first became lowest
|
||||
* is the value what we want.
|
||||
*/
|
||||
int newContactArea = getContactArea(CONTACT_AREA_BOTTOM, 0, -lim);
|
||||
|
||||
if (newContactArea < contactArea) {
|
||||
tY = -lim;
|
||||
}
|
||||
contactArea = newContactArea;
|
||||
}
|
||||
nextHitbox.setPositionYFromPoint(FastMath.ceil(nextHitbox.getPointedY() + tY));
|
||||
}
|
||||
|
||||
private void adjustHitTop() {
|
||||
int tY = 0;
|
||||
int contactArea = getContactArea(CONTACT_AREA_TOP, 0, 0);
|
||||
for (int lim = 0; lim < TSIZE; lim++) {
|
||||
/**
|
||||
* get contact area and move up and get again.
|
||||
* keep track of this value, and some point they will be set as lowest
|
||||
* and become static. The very point where the value first became lowest
|
||||
* is the value what we want.
|
||||
*/
|
||||
int newContactArea = getContactArea(CONTACT_AREA_TOP, 0, lim);
|
||||
|
||||
if (newContactArea < contactArea) {
|
||||
tY = lim;
|
||||
}
|
||||
contactArea = newContactArea;
|
||||
}
|
||||
nextHitbox.setPositionYFromPoint(FastMath.floor(nextHitbox.getPointedY() + tY));
|
||||
}
|
||||
|
||||
private void adjustHitRight() {
|
||||
int tX = 0;
|
||||
int contactArea = getContactArea(CONTACT_AREA_RIGHT, 0, 0);
|
||||
for (int lim = 0; lim < TSIZE; lim++) {
|
||||
/**
|
||||
* get contact area and move up and get again.
|
||||
* keep track of this value, and some point they will be set as lowest
|
||||
* and become static. The very point where the value first became lowest
|
||||
* is the value what we want.
|
||||
*/
|
||||
int newContactArea = getContactArea(CONTACT_AREA_RIGHT, -lim, 0);
|
||||
|
||||
if (newContactArea < contactArea) {
|
||||
tX = -lim;
|
||||
}
|
||||
contactArea = newContactArea;
|
||||
}
|
||||
//nextHitbox.setPositionYFromPoint(nextHitbox.getPointedX() + tX);
|
||||
nextHitbox.set(
|
||||
FastMath.ceil(nextHitbox.getPosX() + tX)
|
||||
, nextHitbox.getPosY()
|
||||
, nextHitbox.getWidth()
|
||||
, nextHitbox.getHeight()
|
||||
);
|
||||
}
|
||||
|
||||
private void adjustHitLeft() {
|
||||
int tX = 0;
|
||||
int contactArea = getContactArea(CONTACT_AREA_LEFT, 0, 0);
|
||||
for (int lim = 0; lim < TSIZE; lim++) {
|
||||
/**
|
||||
* get contact area and move up and get again.
|
||||
* keep track of this value, and some point they will be set as lowest
|
||||
* and become static. The very point where the value first became lowest
|
||||
* is the value what we want.
|
||||
*/
|
||||
int newContactArea = getContactArea(CONTACT_AREA_LEFT, lim, 0);
|
||||
|
||||
if (newContactArea < contactArea) {
|
||||
tX = lim;
|
||||
}
|
||||
contactArea = newContactArea;
|
||||
}
|
||||
//nextHitbox.setPositionYFromPoint(nextHitbox.getPointedX() + tX);
|
||||
nextHitbox.set(
|
||||
FastMath.floor(nextHitbox.getPosX() + tX)
|
||||
, nextHitbox.getPosY()
|
||||
, nextHitbox.getWidth()
|
||||
, nextHitbox.getHeight()
|
||||
);
|
||||
}
|
||||
|
||||
private int getContactArea(int side, int translateX, int translateY) {
|
||||
int contactAreaCounter = 0;
|
||||
for (int i = 0
|
||||
; i < Math.round((side % 2 == 0) ? nextHitbox.getWidth() : nextHitbox.getHeight())
|
||||
; i++) {
|
||||
// set tile positions
|
||||
int tileX = 0, tileY = 0;
|
||||
if (side == CONTACT_AREA_BOTTOM) {
|
||||
tileX = div16(Math.round(nextHitbox.getHitboxStart().getX()) + i + translateX);
|
||||
tileY = div16(FastMath.floor(nextHitbox.getHitboxEnd().getY()) + translateY);
|
||||
}
|
||||
else if (side == CONTACT_AREA_TOP) {
|
||||
tileX = div16(Math.round(nextHitbox.getHitboxStart().getX()) + i + translateX);
|
||||
tileY = div16(FastMath.ceil(nextHitbox.getHitboxStart().getY()) + translateY);
|
||||
}
|
||||
else if (side == CONTACT_AREA_RIGHT) {
|
||||
tileX = div16(FastMath.floor(nextHitbox.getHitboxEnd().getX()) + translateX);
|
||||
tileY = div16(Math.round(nextHitbox.getHitboxStart().getY()) + i + translateY);
|
||||
}
|
||||
else if (side == CONTACT_AREA_LEFT) {
|
||||
tileX = div16(FastMath.ceil(nextHitbox.getHitboxStart().getX()) + translateX);
|
||||
tileY = div16(Math.round(nextHitbox.getHitboxStart().getY()) + i + translateY);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException(String.valueOf(side) + ": Wrong side input");
|
||||
}
|
||||
|
||||
// evaluate
|
||||
if (Terrarum.game.map.getTileFromTerrain(tileX, tileY) > 0) {
|
||||
contactAreaCounter += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return contactAreaCounter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawGlow(GameContainer gc, Graphics g) {
|
||||
if (visible && spriteGlow != null) {
|
||||
if (!sprite.flippedHorizontal()) {
|
||||
spriteGlow.render(g
|
||||
, (hitbox.getPosX() - (hitboxTranslateX * scale))
|
||||
, (hitbox.getPosY() + (hitboxTranslateY * scale))
|
||||
- (baseSpriteHeight - baseHitboxH) * scale
|
||||
+ 1
|
||||
, scale
|
||||
);
|
||||
}
|
||||
else {
|
||||
spriteGlow.render(g
|
||||
, (hitbox.getPosX() - scale)
|
||||
, (hitbox.getPosY() + (hitboxTranslateY * scale))
|
||||
- (baseSpriteHeight - baseHitboxH) * scale
|
||||
+ 1
|
||||
, scale
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawBody(GameContainer gc, Graphics g) {
|
||||
if (visible) {
|
||||
if (!sprite.flippedHorizontal()) {
|
||||
sprite.render(g
|
||||
, (hitbox.getPosX() - (hitboxTranslateX * scale))
|
||||
, (hitbox.getPosY() + (hitboxTranslateY * scale))
|
||||
- (baseSpriteHeight - baseHitboxH) * scale
|
||||
+ 1
|
||||
, scale
|
||||
);
|
||||
}
|
||||
else {
|
||||
sprite.render(g
|
||||
, (hitbox.getPosX() - scale)
|
||||
, (hitbox.getPosY() + (hitboxTranslateY * scale))
|
||||
- (baseSpriteHeight - baseHitboxH) * scale
|
||||
+ 1
|
||||
, scale
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateGlowSprite(GameContainer gc, int delta_t) {
|
||||
if (spriteGlow != null) {
|
||||
spriteGlow.update(delta_t);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBodySprite(GameContainer gc, int delta_t) {
|
||||
sprite.update(delta_t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getRefID() {
|
||||
return referenceID;
|
||||
@@ -360,12 +596,14 @@ public class ActorWithBody implements Actor, Visible, Glowing {
|
||||
}
|
||||
|
||||
private static int div16(int x) {
|
||||
if (x < 0) { throw new IllegalArgumentException("Positive integer only!"); }
|
||||
if (x < 0) { throw new IllegalArgumentException("div16: Positive integer only:"
|
||||
+ String.valueOf(x)); }
|
||||
return (x & 0x7FFF_FFFF) >> 4;
|
||||
}
|
||||
|
||||
private static int mod16(int x) {
|
||||
if (x < 0) { throw new IllegalArgumentException("Positive integer only!"); }
|
||||
if (x < 0) { throw new IllegalArgumentException("mod16: Positive integer only:"
|
||||
+ String.valueOf(x)); }
|
||||
return x & 0b1111;
|
||||
}
|
||||
|
||||
@@ -421,6 +659,14 @@ public class ActorWithBody implements Actor, Visible, Glowing {
|
||||
return grounded;
|
||||
}
|
||||
|
||||
public boolean isWalledLeft() {
|
||||
return walledLeft;
|
||||
}
|
||||
|
||||
public boolean isWalledRight() {
|
||||
return walledRight;
|
||||
}
|
||||
|
||||
public int getBaseHitboxW() {
|
||||
return baseHitboxW;
|
||||
}
|
||||
@@ -452,4 +698,8 @@ public class ActorWithBody implements Actor, Visible, Glowing {
|
||||
public void setUpdate(boolean update) {
|
||||
this.update = update;
|
||||
}
|
||||
|
||||
private int clampMulOfTSize(float v) {
|
||||
return (Math.round(v) / TSIZE) * TSIZE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.Torvald.Terrarum.Actors;
|
||||
|
||||
import com.Torvald.Rand.Fudge3;
|
||||
import com.Torvald.Rand.HighQualityRandom;
|
||||
import com.Torvald.Rand.HQRNG;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import org.newdawn.slick.SlickException;
|
||||
@@ -67,7 +67,7 @@ public class CreatureBuildFactory {
|
||||
for (String s : elemSet) {
|
||||
float baseValue = jsonObject.get(s).getAsFloat();
|
||||
// roll fudge dice and get value [-3, 3] as [0, 6]
|
||||
int varSelected = new Fudge3().create(new HighQualityRandom()).roll() + 3;
|
||||
int varSelected = new Fudge3().create(new HQRNG()).roll() + 3;
|
||||
// get multiplier from json. Assuming percentile
|
||||
int multiplier = jsonObject.get(s + "variable").getAsJsonArray().get(varSelected).getAsInt();
|
||||
float realValue = baseValue * multiplier / 100f;
|
||||
|
||||
@@ -52,7 +52,7 @@ public class PBFSigrid {
|
||||
|
||||
p.actorValue.set("name", "Sigrid");
|
||||
|
||||
p.setHitboxDimension(20, 47, 7, 0);
|
||||
p.setHitboxDimension(17, 47, 9, 0);
|
||||
|
||||
p.inventory = new ActorInventory((int) p.actorValue.get("encumbrance"), true);
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.Torvald.Terrarum.Actors;
|
||||
|
||||
import com.Torvald.Terrarum.Game;
|
||||
import com.Torvald.Terrarum.GameControl.EnumKeyFunc;
|
||||
import com.Torvald.Terrarum.GameControl.KeyMap;
|
||||
import com.Torvald.Terrarum.Terrarum;
|
||||
@@ -8,12 +7,16 @@ import com.Torvald.spriteAnimation.SpriteAnimation;
|
||||
import com.jme3.math.FastMath;
|
||||
import com.sun.istack.internal.NotNull;
|
||||
import com.sun.istack.internal.Nullable;
|
||||
import org.lwjgl.input.Controller;
|
||||
import org.lwjgl.input.Controllers;
|
||||
import org.newdawn.slick.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 15-12-31.
|
||||
*/
|
||||
public class Player extends ActorWithBody implements Controllable, Pocketed {
|
||||
public class Player extends ActorWithBody implements Controllable, Pocketed, Serializable {
|
||||
|
||||
@Nullable public Controllable vehicleRiding;
|
||||
|
||||
@@ -21,7 +24,7 @@ public class Player extends ActorWithBody implements Controllable, Pocketed {
|
||||
int walkPowerCounter = 0;
|
||||
private final int WALK_FRAMES_TO_MAX_ACCEL = 6;
|
||||
|
||||
public float readonly_totalX = 0;
|
||||
public float readonly_totalX = 0, readonly_totalY = 0;
|
||||
|
||||
boolean jumping = false;
|
||||
|
||||
@@ -42,6 +45,9 @@ public class Player extends ActorWithBody implements Controllable, Pocketed {
|
||||
|
||||
public final long PLAYER_REF_ID = 0x51621D;
|
||||
|
||||
private final float AXIS_POSMAX = 1.0f;
|
||||
private final int GAMEPAD_JUMP = 5;
|
||||
|
||||
/**
|
||||
* Creates new Player instance with empty elements (sprites, actorvalue, etc.). <br />
|
||||
*
|
||||
@@ -73,34 +79,74 @@ public class Player extends ActorWithBody implements Controllable, Pocketed {
|
||||
* FastMath.pow(super.getScale(), 3));
|
||||
}
|
||||
|
||||
private void walkHorizontal(boolean left) {
|
||||
readonly_totalX = super.getVeloX()
|
||||
/**
|
||||
*
|
||||
* @param left (even if the game is joypad controlled, you must give valid value)
|
||||
* @param absAxisVal (set AXIS_POSMAX if keyboard controlled)
|
||||
*/
|
||||
private void walkHorizontal(boolean left, float absAxisVal) {
|
||||
if ((!super.isWalledLeft() && left) || (!super.isWalledRight() && !left)) {
|
||||
readonly_totalX = super.getVeloX()
|
||||
+
|
||||
actorValue.getAsFloat("accel")
|
||||
* actorValue.getAsFloat("accelmult")
|
||||
* FastMath.sqrt(super.getScale())
|
||||
* applyAccelRealism(walkPowerCounter)
|
||||
* (left ? -1 : 1)
|
||||
* absAxisVal;
|
||||
|
||||
super.setVeloX(readonly_totalX);
|
||||
|
||||
if (walkPowerCounter < WALK_FRAMES_TO_MAX_ACCEL) {
|
||||
walkPowerCounter += 1;
|
||||
}
|
||||
|
||||
// Clamp veloX
|
||||
super.setVeloX(
|
||||
absClamp(super.getVeloX()
|
||||
, actorValue.getAsFloat("speed")
|
||||
* actorValue.getAsFloat("speedmult")
|
||||
* FastMath.sqrt(super.getScale())
|
||||
)
|
||||
);
|
||||
|
||||
// Heading flag
|
||||
if (left)
|
||||
walkHeading = LEFT;
|
||||
else
|
||||
walkHeading = RIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param up (even if the game is joypad controlled, you must give valid value)
|
||||
* @param absAxisVal (set AXIS_POSMAX if keyboard controlled)
|
||||
*/
|
||||
private void walkVertical(boolean up, float absAxisVal) {
|
||||
readonly_totalY = super.getVeloY()
|
||||
+
|
||||
actorValue.getAsFloat("accel")
|
||||
* actorValue.getAsFloat("accelmult")
|
||||
* FastMath.sqrt(super.getScale())
|
||||
* applyAccelRealism(walkPowerCounter)
|
||||
* (left ? -1 : 1);
|
||||
* (up ? -1 : 1)
|
||||
* absAxisVal;
|
||||
|
||||
super.setVeloX(readonly_totalX);
|
||||
super.setVeloY(readonly_totalY);
|
||||
|
||||
if (walkPowerCounter < WALK_FRAMES_TO_MAX_ACCEL) {
|
||||
walkPowerCounter += 1;
|
||||
}
|
||||
|
||||
// Clamp veloX
|
||||
super.setVeloX(
|
||||
absClamp(super.getVeloX()
|
||||
, actorValue.getAsFloat("speed")
|
||||
* actorValue.getAsFloat("speedmult")
|
||||
* FastMath.sqrt(super.getScale())
|
||||
));
|
||||
|
||||
// Heading flag
|
||||
if (left)
|
||||
walkHeading = LEFT;
|
||||
else
|
||||
walkHeading = RIGHT;
|
||||
super.setVeloY(
|
||||
absClamp(super.getVeloY()
|
||||
, actorValue.getAsFloat("speed")
|
||||
* actorValue.getAsFloat("speedmult")
|
||||
* FastMath.sqrt(super.getScale())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -130,30 +176,6 @@ public class Player extends ActorWithBody implements Controllable, Pocketed {
|
||||
return 0.5f + 0.5f * -FastMath.cos(10 * x / (WALK_FRAMES_TO_MAX_ACCEL * FastMath.PI));
|
||||
}
|
||||
|
||||
private void walkVertical(boolean up) {
|
||||
super.setVeloY(super.getVeloY()
|
||||
+
|
||||
actorValue.getAsFloat("accel")
|
||||
* actorValue.getAsFloat("accelmult")
|
||||
* FastMath.sqrt(super.getScale())
|
||||
* applyAccelRealism(walkPowerCounter)
|
||||
* (up ? -1 : 1)
|
||||
);
|
||||
|
||||
if (walkPowerCounter < WALK_FRAMES_TO_MAX_ACCEL) {
|
||||
walkPowerCounter += 1;
|
||||
}
|
||||
|
||||
// Clamp veloX
|
||||
super.setVeloY(
|
||||
absClamp(super.getVeloY()
|
||||
, actorValue.getAsFloat("speed")
|
||||
* actorValue.getAsFloat("speedmult")
|
||||
* FastMath.sqrt(super.getScale())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private void walkHStop() {
|
||||
if (super.getVeloX() > 0) {
|
||||
super.setVeloX(super.getVeloX()
|
||||
@@ -232,94 +254,137 @@ public class Player extends ActorWithBody implements Controllable, Pocketed {
|
||||
}
|
||||
|
||||
public void processInput(Input input) {
|
||||
Controller gamepad = null;
|
||||
float axisX = 0, axisY = 0, axisRX = 0, axisRY = 0;
|
||||
if (Terrarum.hasController) {
|
||||
gamepad = Controllers.getController(0);
|
||||
axisX = gamepad.getAxisValue(0);
|
||||
axisY = gamepad.getAxisValue(1);
|
||||
axisRX = gamepad.getAxisValue(2);
|
||||
axisRY = gamepad.getAxisValue(3);
|
||||
|
||||
if (Math.abs(axisX) < Terrarum.CONTROLLER_DEADZONE) axisX = 0;
|
||||
if (Math.abs(axisY) < Terrarum.CONTROLLER_DEADZONE) axisY = 0;
|
||||
if (Math.abs(axisRX) < Terrarum.CONTROLLER_DEADZONE) axisRX = 0;
|
||||
if (Math.abs(axisRY) < Terrarum.CONTROLLER_DEADZONE) axisRY = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* L-R stop
|
||||
*/
|
||||
// ↑F, ↑S
|
||||
if (!isFuncDown(input, EnumKeyFunc.MOVE_LEFT)
|
||||
&& !isFuncDown(input, EnumKeyFunc.MOVE_RIGHT)) {
|
||||
walkHStop();
|
||||
prevHMoveKey = KEY_NULL;
|
||||
if (Terrarum.hasController) {
|
||||
if (axisX == 0) {
|
||||
walkHStop();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// ↑F, ↑S
|
||||
if (!isFuncDown(input, EnumKeyFunc.MOVE_LEFT)
|
||||
&& !isFuncDown(input, EnumKeyFunc.MOVE_RIGHT)) {
|
||||
walkHStop();
|
||||
prevHMoveKey = KEY_NULL;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* U-D stop
|
||||
*/
|
||||
// ↑E
|
||||
// ↑D
|
||||
if (isNoClip()
|
||||
&&!isFuncDown(input, EnumKeyFunc.MOVE_UP)
|
||||
&& !isFuncDown(input, EnumKeyFunc.MOVE_DOWN)) {
|
||||
walkVStop();
|
||||
prevVMoveKey = KEY_NULL;
|
||||
if (Terrarum.hasController) {
|
||||
if (axisY == 0) {
|
||||
walkVStop();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// ↑E
|
||||
// ↑D
|
||||
if (isNoClip()
|
||||
&& !isFuncDown(input, EnumKeyFunc.MOVE_UP)
|
||||
&& !isFuncDown(input, EnumKeyFunc.MOVE_DOWN)) {
|
||||
walkVStop();
|
||||
prevVMoveKey = KEY_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Left/Right movement
|
||||
*/
|
||||
|
||||
// ↑F, ↓S
|
||||
if (isFuncDown(input, EnumKeyFunc.MOVE_RIGHT)
|
||||
&& !isFuncDown(input, EnumKeyFunc.MOVE_LEFT)) {
|
||||
walkHorizontal(false);
|
||||
prevHMoveKey = KeyMap.getKeyCode(EnumKeyFunc.MOVE_RIGHT);
|
||||
if (Terrarum.hasController) {
|
||||
if (axisX != 0) {
|
||||
walkHorizontal(axisX < 0, AXIS_POSMAX);
|
||||
}
|
||||
}
|
||||
// ↓F, ↑S
|
||||
else if (isFuncDown(input, EnumKeyFunc.MOVE_LEFT)
|
||||
&& !isFuncDown(input, EnumKeyFunc.MOVE_RIGHT)) {
|
||||
walkHorizontal(true);
|
||||
prevHMoveKey = KeyMap.getKeyCode(EnumKeyFunc.MOVE_LEFT);
|
||||
}
|
||||
// ↓F, ↓S
|
||||
else if (isFuncDown(input, EnumKeyFunc.MOVE_LEFT)
|
||||
&& isFuncDown(input, EnumKeyFunc.MOVE_RIGHT)) {
|
||||
if (prevHMoveKey == KeyMap.getKeyCode(EnumKeyFunc.MOVE_LEFT)) {
|
||||
walkHorizontal(false);
|
||||
else {
|
||||
// ↑F, ↓S
|
||||
if (isFuncDown(input, EnumKeyFunc.MOVE_RIGHT)
|
||||
&& !isFuncDown(input, EnumKeyFunc.MOVE_LEFT)) {
|
||||
walkHorizontal(false, AXIS_POSMAX);
|
||||
prevHMoveKey = KeyMap.getKeyCode(EnumKeyFunc.MOVE_RIGHT);
|
||||
}
|
||||
else if (prevHMoveKey == KeyMap.getKeyCode(EnumKeyFunc.MOVE_RIGHT)) {
|
||||
walkHorizontal(true);
|
||||
// ↓F, ↑S
|
||||
else if (isFuncDown(input, EnumKeyFunc.MOVE_LEFT)
|
||||
&& !isFuncDown(input, EnumKeyFunc.MOVE_RIGHT)) {
|
||||
walkHorizontal(true, AXIS_POSMAX);
|
||||
prevHMoveKey = KeyMap.getKeyCode(EnumKeyFunc.MOVE_LEFT);
|
||||
}
|
||||
// ↓F, ↓S
|
||||
else if (isFuncDown(input, EnumKeyFunc.MOVE_LEFT)
|
||||
&& isFuncDown(input, EnumKeyFunc.MOVE_RIGHT)) {
|
||||
if (prevHMoveKey == KeyMap.getKeyCode(EnumKeyFunc.MOVE_LEFT)) {
|
||||
walkHorizontal(false, AXIS_POSMAX);
|
||||
prevHMoveKey = KeyMap.getKeyCode(EnumKeyFunc.MOVE_RIGHT);
|
||||
}
|
||||
else if (prevHMoveKey == KeyMap.getKeyCode(EnumKeyFunc.MOVE_RIGHT)) {
|
||||
walkHorizontal(true, AXIS_POSMAX);
|
||||
prevHMoveKey = KeyMap.getKeyCode(EnumKeyFunc.MOVE_LEFT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Up/Down movement
|
||||
*/
|
||||
|
||||
if (noClip) {
|
||||
// ↑E
|
||||
// ↓D
|
||||
if (isFuncDown(input, EnumKeyFunc.MOVE_DOWN)
|
||||
&& !isFuncDown(input, EnumKeyFunc.MOVE_UP)) {
|
||||
walkVertical(false);
|
||||
prevVMoveKey = KeyMap.getKeyCode(EnumKeyFunc.MOVE_DOWN);
|
||||
if (Terrarum.hasController) {
|
||||
if (axisY != 0) {
|
||||
walkVertical(axisY > 0, AXIS_POSMAX);
|
||||
}
|
||||
}
|
||||
// ↓E
|
||||
// ↑D
|
||||
else if (isFuncDown(input, EnumKeyFunc.MOVE_UP)
|
||||
&& !isFuncDown(input, EnumKeyFunc.MOVE_DOWN)) {
|
||||
walkVertical(true);
|
||||
prevVMoveKey = KeyMap.getKeyCode(EnumKeyFunc.MOVE_UP);
|
||||
}
|
||||
// ↓E
|
||||
// ↓D
|
||||
else if (isFuncDown(input, EnumKeyFunc.MOVE_UP)
|
||||
&& isFuncDown(input, EnumKeyFunc.MOVE_DOWN)) {
|
||||
if (prevVMoveKey == KeyMap.getKeyCode(EnumKeyFunc.MOVE_UP)) {
|
||||
walkVertical(false);
|
||||
else {
|
||||
// ↑E
|
||||
// ↓D
|
||||
if (isFuncDown(input, EnumKeyFunc.MOVE_DOWN)
|
||||
&& !isFuncDown(input, EnumKeyFunc.MOVE_UP)) {
|
||||
walkVertical(false, AXIS_POSMAX);
|
||||
prevVMoveKey = KeyMap.getKeyCode(EnumKeyFunc.MOVE_DOWN);
|
||||
}
|
||||
else if (prevVMoveKey == KeyMap.getKeyCode(EnumKeyFunc.MOVE_DOWN)) {
|
||||
walkVertical(true);
|
||||
// ↓E
|
||||
// ↑D
|
||||
else if (isFuncDown(input, EnumKeyFunc.MOVE_UP)
|
||||
&& !isFuncDown(input, EnumKeyFunc.MOVE_DOWN)) {
|
||||
walkVertical(true, AXIS_POSMAX);
|
||||
prevVMoveKey = KeyMap.getKeyCode(EnumKeyFunc.MOVE_UP);
|
||||
}
|
||||
// ↓E
|
||||
// ↓D
|
||||
else if (isFuncDown(input, EnumKeyFunc.MOVE_UP)
|
||||
&& isFuncDown(input, EnumKeyFunc.MOVE_DOWN)) {
|
||||
if (prevVMoveKey == KeyMap.getKeyCode(EnumKeyFunc.MOVE_UP)) {
|
||||
walkVertical(false, AXIS_POSMAX);
|
||||
prevVMoveKey = KeyMap.getKeyCode(EnumKeyFunc.MOVE_DOWN);
|
||||
}
|
||||
else if (prevVMoveKey == KeyMap.getKeyCode(EnumKeyFunc.MOVE_DOWN)) {
|
||||
walkVertical(true, AXIS_POSMAX);
|
||||
prevVMoveKey = KeyMap.getKeyCode(EnumKeyFunc.MOVE_UP);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Jump control
|
||||
*/
|
||||
if (isFuncDown(input, EnumKeyFunc.JUMP)) {
|
||||
if (isFuncDown(input, EnumKeyFunc.JUMP)
|
||||
|| (Terrarum.hasController && gamepad.isButtonPressed(GAMEPAD_JUMP))) {
|
||||
if (!noClip) {
|
||||
if (super.isGrounded()) {
|
||||
jumping = true;
|
||||
@@ -327,7 +392,7 @@ public class Player extends ActorWithBody implements Controllable, Pocketed {
|
||||
}
|
||||
}
|
||||
else {
|
||||
walkVertical(true);
|
||||
walkVertical(true, AXIS_POSMAX);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
package com.Torvald.Terrarum.Actors;
|
||||
|
||||
|
||||
import com.Torvald.Rand.Fudge3;
|
||||
import com.Torvald.Rand.HighQualityRandom;
|
||||
import com.google.gson.*;
|
||||
import org.newdawn.slick.SlickException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 16-02-03.
|
||||
|
||||
34
src/com/Torvald/Terrarum/ConsoleCommand/CatStdout.java
Normal file
34
src/com/Torvald/Terrarum/ConsoleCommand/CatStdout.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package com.Torvald.Terrarum.ConsoleCommand;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 16-02-10.
|
||||
*/
|
||||
public class CatStdout implements ConsoleCommand {
|
||||
@Override
|
||||
public void execute(String[] args) {
|
||||
|
||||
Echo echo = new Echo();
|
||||
|
||||
if (args.length == 1) {
|
||||
printUsage();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Files.lines(FileSystems.getDefault().getPath(args[1])).forEach(echo::execute);
|
||||
}
|
||||
catch (IOException e) {
|
||||
echo.execute("CatStdout: could not read file -- IOException");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printUsage() {
|
||||
new Echo().execute("usage: cat 'path/to/text/file");
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ public class CommandDict {
|
||||
dict.put("setlocale", new SetLocale());
|
||||
dict.put("zoom", new Zoom());
|
||||
dict.put("teleport", new TeleportPlayer());
|
||||
dict.put("cat", new CatStdout());
|
||||
}
|
||||
|
||||
public static ConsoleCommand getCommand(String commandName) {
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
package com.Torvald.Terrarum.ConsoleCommand;
|
||||
|
||||
import com.Torvald.ColourUtil.Col12;
|
||||
import com.Torvald.ColourUtil.Col4096;
|
||||
import com.Torvald.Terrarum.Terrarum;
|
||||
import com.Torvald.Terrarum.Game;
|
||||
import org.newdawn.slick.Color;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.*;
|
||||
@@ -51,7 +49,7 @@ public class ExportMap implements ConsoleCommand {
|
||||
private static final byte WATER = (byte) 239;
|
||||
private static final byte LAVA = (byte) 255;
|
||||
|
||||
private Hashtable<Byte, Col12> colorTable = new Hashtable<>();
|
||||
private Hashtable<Byte, Col4096> colorTable = new Hashtable<>();
|
||||
|
||||
@Override
|
||||
public void execute(String[] args) {
|
||||
@@ -61,7 +59,7 @@ public class ExportMap implements ConsoleCommand {
|
||||
mapData = new byte[Terrarum.game.map.width * Terrarum.game.map.height * 3];
|
||||
|
||||
for (byte tile : Terrarum.game.map.getLayerTerrain()) {
|
||||
byte[] colArray = colorTable.getOrDefault(tile, new Col12(0xFFF))
|
||||
byte[] colArray = colorTable.getOrDefault(tile, new Col4096(0xFFF))
|
||||
.toByteArray();
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
@@ -121,34 +119,34 @@ public class ExportMap implements ConsoleCommand {
|
||||
}
|
||||
|
||||
private void buildColorTable() {
|
||||
colorTable.put(AIR, new Col12(0xCEF));
|
||||
colorTable.put(STONE, new Col12(0x887));
|
||||
colorTable.put(DIRT, new Col12(0x763));
|
||||
colorTable.put(GRASS, new Col12(0x251));
|
||||
colorTable.put(AIR, new Col4096(0xCEF));
|
||||
colorTable.put(STONE, new Col4096(0x887));
|
||||
colorTable.put(DIRT, new Col4096(0x763));
|
||||
colorTable.put(GRASS, new Col4096(0x251));
|
||||
|
||||
colorTable.put(COPPER, new Col12(0x6A8));
|
||||
colorTable.put(IRON, new Col12(0xC75));
|
||||
colorTable.put(GOLD, new Col12(0xCB6));
|
||||
colorTable.put(ILMENITE, new Col12(0x8AB));
|
||||
colorTable.put(AURICHALCUM, new Col12(0xD92));
|
||||
colorTable.put(COPPER, new Col4096(0x6A8));
|
||||
colorTable.put(IRON, new Col4096(0xC75));
|
||||
colorTable.put(GOLD, new Col4096(0xCB6));
|
||||
colorTable.put(ILMENITE, new Col4096(0x8AB));
|
||||
colorTable.put(AURICHALCUM, new Col4096(0xD92));
|
||||
|
||||
colorTable.put(DIAMOND, new Col12(0x9CE));
|
||||
colorTable.put(RUBY, new Col12(0xB10));
|
||||
colorTable.put(EMERALD, new Col12(0x0B1));
|
||||
colorTable.put(SAPPHIRE, new Col12(0x01B));
|
||||
colorTable.put(TOPAZ, new Col12(0xC70));
|
||||
colorTable.put(AMETHYST, new Col12(0x70C));
|
||||
colorTable.put(DIAMOND, new Col4096(0x9CE));
|
||||
colorTable.put(RUBY, new Col4096(0xB10));
|
||||
colorTable.put(EMERALD, new Col4096(0x0B1));
|
||||
colorTable.put(SAPPHIRE, new Col4096(0x01B));
|
||||
colorTable.put(TOPAZ, new Col4096(0xC70));
|
||||
colorTable.put(AMETHYST, new Col4096(0x70C));
|
||||
|
||||
colorTable.put(WATER, new Col12(0x038));
|
||||
colorTable.put(LAVA, new Col12(0xF50));
|
||||
colorTable.put(WATER, new Col4096(0x038));
|
||||
colorTable.put(LAVA, new Col4096(0xF50));
|
||||
|
||||
colorTable.put(SAND, new Col12(0xDCA));
|
||||
colorTable.put(GRAVEL, new Col12(0x664));
|
||||
colorTable.put(SAND, new Col4096(0xDCA));
|
||||
colorTable.put(GRAVEL, new Col4096(0x664));
|
||||
|
||||
colorTable.put(ICE_NATURAL, new Col12(0x9AB));
|
||||
colorTable.put(ICE_MAGICAL, new Col12(0x7AC));
|
||||
colorTable.put(ICE_FRAGILE, new Col12(0x6AF));
|
||||
colorTable.put(SNOW, new Col12(0xCDE));
|
||||
colorTable.put(ICE_NATURAL, new Col4096(0x9AB));
|
||||
colorTable.put(ICE_MAGICAL, new Col4096(0x7AC));
|
||||
colorTable.put(ICE_FRAGILE, new Col4096(0x6AF));
|
||||
colorTable.put(SNOW, new Col4096(0xCDE));
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -59,7 +59,11 @@ public class Game extends BasicGameState {
|
||||
private Shader shaderBlurH;
|
||||
private Shader shaderBlurV;
|
||||
|
||||
public Game() throws SlickException {
|
||||
public Game() throws SlickException { }
|
||||
|
||||
@Override
|
||||
public void init(GameContainer gameContainer, StateBasedGame stateBasedGame) throws
|
||||
SlickException {
|
||||
new GameController();
|
||||
KeyMap.build();
|
||||
GameController.setKeyMap(new KeyMap());
|
||||
@@ -83,7 +87,7 @@ public class Game extends BasicGameState {
|
||||
|
||||
MapGenerator.attachMap(map);
|
||||
MapGenerator.setSeed(0x51621D);
|
||||
//MapGenerator.setSeed(new HighQualityRandom().nextLong());
|
||||
//MapGenerator.setSeed(new HQRNG().nextLong());
|
||||
MapGenerator.generateMap();
|
||||
|
||||
new CommandDict();
|
||||
@@ -122,11 +126,6 @@ public class Game extends BasicGameState {
|
||||
uiContainer.add(msgtest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(GameContainer gameContainer, StateBasedGame stateBasedGame) throws
|
||||
SlickException {
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
@@ -136,6 +135,7 @@ public class Game extends BasicGameState {
|
||||
setAppTitle();
|
||||
|
||||
MapDrawer.update(gc, delta_t);
|
||||
MapCamera.update(gc, delta_t);
|
||||
|
||||
GameController.processInput(gc.getInput());
|
||||
|
||||
@@ -177,10 +177,6 @@ public class Game extends BasicGameState {
|
||||
|
||||
@Override
|
||||
public void render(GameContainer gc, StateBasedGame sbg, Graphics g) {
|
||||
// shader12BitCol.setUniformIntVariable("pixelSize", 1);
|
||||
// shader12BitCol.startShader();
|
||||
// shaderBlurH.startShader();
|
||||
// shaderBlurV.startShader();
|
||||
|
||||
drawSkybox(g);
|
||||
|
||||
@@ -190,37 +186,30 @@ public class Game extends BasicGameState {
|
||||
, -MapCamera.getCameraY() * screenZoom
|
||||
);
|
||||
|
||||
MapCamera.renderBehind(gc, g);
|
||||
|
||||
actorContainer.forEach(
|
||||
actor -> {
|
||||
if (actor instanceof Visible) {
|
||||
((Visible) actor).drawBody(gc, g);
|
||||
}
|
||||
}
|
||||
actor -> { if (actor instanceof Visible) ((Visible) actor).drawBody(gc, g); }
|
||||
);
|
||||
actorContainer.forEach(
|
||||
actor -> {
|
||||
if (actor instanceof Glowing) {
|
||||
((Glowing) actor).drawGlow(gc, g);
|
||||
}
|
||||
}
|
||||
actor -> { if (actor instanceof Glowing) ((Glowing) actor).drawGlow(gc, g); }
|
||||
);
|
||||
|
||||
MapCamera.renderFront(gc, g);
|
||||
MapDrawer.render(gc, g);
|
||||
|
||||
// Slick's MODE_COLOR_MULTIPLY is clearly broken... using GL11
|
||||
LightmapRenderer.renderLightMap();
|
||||
GL11.glEnable(GL11.GL_BLEND);
|
||||
GL11.glBlendFunc(GL11.GL_DST_COLOR, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
// draw lightmap
|
||||
setBlendModeMul();
|
||||
LightmapRenderer.draw(g);
|
||||
// draw environment colour overlay
|
||||
// MapDrawer.drawEnvOverlay(g);
|
||||
GL11.glDisable(GL11.GL_BLEND);
|
||||
g.setDrawMode(Graphics.MODE_NORMAL);
|
||||
setBlendModeNormal();
|
||||
|
||||
uiContainer.forEach(ui -> ui.render(gc, g));
|
||||
debugWindow.render(gc, g);
|
||||
consoleHandler.render(gc, g);
|
||||
//bulletin.render(gc, g);
|
||||
|
||||
GL11.glEnd();
|
||||
}
|
||||
|
||||
private Color[] getGradientColour(int timeSec) {
|
||||
@@ -282,4 +271,14 @@ public class Game extends BasicGameState {
|
||||
GradientFill skyColourFill = new GradientFill(0, 0, colourTable[0], 0, Terrarum.HEIGHT, colourTable[1]);
|
||||
g.fill(skyBox, skyColourFill);
|
||||
}
|
||||
|
||||
private void setBlendModeMul() {
|
||||
GL11.glEnable(GL11.GL_BLEND);
|
||||
GL11.glBlendFunc(GL11.GL_DST_COLOR, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
private void setBlendModeNormal() {
|
||||
GL11.glDisable(GL11.GL_BLEND);
|
||||
Terrarum.appgc.getGraphics().setDrawMode(Graphics.MODE_NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
4
src/com/Torvald/Terrarum/MISC_FEATURES
Normal file
4
src/com/Torvald/Terrarum/MISC_FEATURES
Normal file
@@ -0,0 +1,4 @@
|
||||
* Drawing
|
||||
|
||||
- Players can create their own décors (hang on wall), dresses.
|
||||
- Two looms (3-3-2 colour mode, 4096 colour mode)
|
||||
@@ -136,24 +136,31 @@ public class MapCamera {
|
||||
|
||||
// position - (WH / 2)
|
||||
cameraX = clamp(
|
||||
Math.round(player.pointedPosX() - (renderWidth / 2))
|
||||
Math.round(player.getNextHitbox().getPointedX() - (renderWidth / 2))
|
||||
, map.width * TSIZE - renderWidth
|
||||
);
|
||||
cameraY = clamp(
|
||||
Math.round(player.pointedPosY() - (renderHeight / 2))
|
||||
Math.round(player.getNextHitbox().getPointedY() - (renderHeight / 2))
|
||||
, map.height * TSIZE - renderHeight
|
||||
);
|
||||
}
|
||||
|
||||
public static void render(GameContainer gc, Graphics g) {
|
||||
public static void renderBehind(GameContainer gc, Graphics g) {
|
||||
/**
|
||||
* render to camera
|
||||
*/
|
||||
drawTiles(WALL);
|
||||
drawTiles(TERRAIN);
|
||||
setBlendModeNormal();
|
||||
drawTiles(WALL, false);
|
||||
drawTiles(TERRAIN, false);
|
||||
}
|
||||
|
||||
private static void drawTiles(int mode) {
|
||||
public static void renderFront(GameContainer gc, Graphics g) {
|
||||
setBlendModeMul();
|
||||
drawTiles(TERRAIN, true);
|
||||
setBlendModeNormal();
|
||||
}
|
||||
|
||||
private static void drawTiles(int mode, boolean drawModeTilesBlendMul) {
|
||||
int for_y_start = div16(cameraY);
|
||||
int for_x_start = div16(cameraX);
|
||||
|
||||
@@ -222,10 +229,16 @@ public class MapCamera {
|
||||
int thisTileX = nearbyTilesInfo;
|
||||
int thisTileY = thisTile;
|
||||
|
||||
|
||||
if (isBlendMul((byte) thisTile)) setBlendModeMul();
|
||||
else setBlendModeNormal();
|
||||
drawTile(TERRAIN, x, y, thisTileX, thisTileY);
|
||||
if (drawModeTilesBlendMul) {
|
||||
if (isBlendMul((byte) thisTile)) drawTile(TERRAIN, x, y, thisTileX, thisTileY);
|
||||
}
|
||||
else {
|
||||
// currently it draws all the transparent tile and colour mixes
|
||||
// on top of the previously drawn tile
|
||||
// TODO check wether it works as intended when skybox is dark
|
||||
// add instruction "if (!isBlendMul((byte) thisTile))"
|
||||
drawTile(TERRAIN, x, y, thisTileX, thisTileY);
|
||||
}
|
||||
}
|
||||
else {
|
||||
drawTile(mode, x, y, mod16(thisTile), div16(thisTile));
|
||||
@@ -236,7 +249,6 @@ public class MapCamera {
|
||||
}
|
||||
|
||||
tilesetBook[mode].endUse();
|
||||
setBlendModeNormal();
|
||||
}
|
||||
|
||||
private static int getGrassInfo(int x, int y, int from, int to) {
|
||||
|
||||
@@ -31,11 +31,9 @@ public class MapDrawer {
|
||||
}
|
||||
|
||||
public static void update(GameContainer gc, int delta_t) {
|
||||
MapCamera.update(gc, delta_t);
|
||||
}
|
||||
|
||||
public static void render(GameContainer gc, Graphics g) {
|
||||
MapCamera.render(gc, g);
|
||||
}
|
||||
|
||||
public static void drawEnvOverlay(Graphics g) {
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
package com.Torvald.Terrarum.MapGenerator;
|
||||
|
||||
import com.Torvald.Rand.HighQualityRandom;
|
||||
import com.Torvald.Rand.HQRNG;
|
||||
|
||||
public class FloatingIslandsPreset {
|
||||
|
||||
public static int presets = 5;
|
||||
|
||||
static int[][] generatePreset(HighQualityRandom random) {
|
||||
static int[][] generatePreset(HQRNG random) {
|
||||
int index = random.nextInt(presets);
|
||||
return generatePreset(index, random);
|
||||
}
|
||||
|
||||
static int[][] generatePreset(int index, HighQualityRandom random){
|
||||
static int[][] generatePreset(int index, HQRNG random){
|
||||
if (index == 0){
|
||||
return processPreset(random, FloatingIslePreset01.data, FloatingIslePreset01.w, FloatingIslePreset01.h);
|
||||
}
|
||||
@@ -30,7 +30,7 @@ public class FloatingIslandsPreset {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static int[][] processPreset(HighQualityRandom random, int[] preset, int w, int h){
|
||||
private static int[][] processPreset(HQRNG random, int[] preset, int w, int h){
|
||||
int[][] temp = new int[h][w];
|
||||
int counter = 0;
|
||||
boolean mirrored = random.nextBoolean();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.Torvald.Terrarum.MapGenerator;
|
||||
|
||||
import com.Torvald.Rand.HighQualityRandom;
|
||||
import com.Torvald.Rand.HQRNG;
|
||||
import com.Torvald.Terrarum.GameMap.GameMap;
|
||||
import com.jme3.math.FastMath;
|
||||
import com.sun.istack.internal.NotNull;
|
||||
@@ -8,7 +8,7 @@ import com.sun.istack.internal.NotNull;
|
||||
public class MapGenerator {
|
||||
|
||||
@NotNull private static GameMap map;
|
||||
private static HighQualityRandom random;
|
||||
private static HQRNG random;
|
||||
//private static float[] noiseArray;
|
||||
@NotNull private static long seed;
|
||||
@NotNull private static int width;
|
||||
@@ -93,7 +93,7 @@ public class MapGenerator {
|
||||
* Generate terrain and override attached map
|
||||
*/
|
||||
public static void generateMap() {
|
||||
random = new HighQualityRandom(seed);
|
||||
random = new HQRNG(seed);
|
||||
System.out.println("[MapGenerator] Seed: " + seed);
|
||||
|
||||
worldOceanPosition = random.nextBoolean() ? TYPE_OCEAN_LEFT : TYPE_OCEAN_RIGHT;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.Torvald.Terrarum.MapGenerator;
|
||||
|
||||
import com.Torvald.Rand.HighQualityRandom;
|
||||
import com.Torvald.Rand.HQRNG;
|
||||
import com.jme3.math.FastMath;
|
||||
|
||||
public class SimplexNoise {
|
||||
@@ -30,7 +30,7 @@ public class SimplexNoise {
|
||||
frequencys = new float[numberOfOctaves];
|
||||
amplitudes = new float[numberOfOctaves];
|
||||
|
||||
HighQualityRandom rnd = new HighQualityRandom(seed);
|
||||
HQRNG rnd = new HQRNG(seed);
|
||||
|
||||
for (int i = 0; i < numberOfOctaves; i++) {
|
||||
octaves[i] = new SimplexNoise_octave(rnd.nextInt());
|
||||
|
||||
@@ -17,7 +17,7 @@ package com.Torvald.Terrarum.MapGenerator;
|
||||
*
|
||||
*/
|
||||
|
||||
import com.Torvald.Rand.HighQualityRandom;
|
||||
import com.Torvald.Rand.HQRNG;
|
||||
|
||||
public class SimplexNoise_octave { // Simplex noise in 2D, 3D and 4D
|
||||
|
||||
@@ -64,7 +64,7 @@ public class SimplexNoise_octave { // Simplex noise in 2D, 3D and 4D
|
||||
}
|
||||
|
||||
//the random for the swaps
|
||||
HighQualityRandom rand=new HighQualityRandom(seed);
|
||||
HQRNG rand=new HQRNG(seed);
|
||||
|
||||
//the seed determines the swaps that occur between the default order and the order we're actually going to use
|
||||
for(int i=0;i<NUMBEROFSWAPS;i++){
|
||||
|
||||
@@ -7,6 +7,8 @@ import java.util.logging.Logger;
|
||||
|
||||
import com.Torvald.ImageFont.GameFontWhite;
|
||||
import com.Torvald.Terrarum.LangPack.Lang;
|
||||
import org.lwjgl.input.Controllers;
|
||||
import org.lwjgl.opengl.DisplayMode;
|
||||
import org.newdawn.slick.*;
|
||||
import org.newdawn.slick.state.StateBasedGame;
|
||||
|
||||
@@ -47,6 +49,9 @@ public class Terrarum extends StateBasedGame {
|
||||
public static final int SCENE_ID_HOME = 1;
|
||||
public static final int SCENE_ID_GAME = 3;
|
||||
|
||||
public static boolean hasController = false;
|
||||
public static final float CONTROLLER_DEADZONE = 0.1f;
|
||||
|
||||
public Terrarum(String gamename) throws SlickException {
|
||||
super(gamename);
|
||||
|
||||
@@ -62,9 +67,16 @@ public class Terrarum extends StateBasedGame {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initStatesList(GameContainer gameContainer) throws SlickException {
|
||||
public void initStatesList(GameContainer gc) throws SlickException {
|
||||
gameFontWhite = new GameFontWhite();
|
||||
|
||||
hasController = (gc.getInput().getControllerCount() > 0);
|
||||
if (hasController) {
|
||||
for (int c = 0; c < Controllers.getController(0).getAxisCount(); c++) {
|
||||
Controllers.getController(0).setDeadZone(c, CONTROLLER_DEADZONE);
|
||||
}
|
||||
}
|
||||
|
||||
game = new Game();
|
||||
addState(game);
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ public class ConsoleWindow implements UICanvas {
|
||||
else if ((key >= 2 && key <= 13)
|
||||
|| (key >= 16 && key <= 27)
|
||||
|| (key >= 30 && key <= 40)
|
||||
|| (key >= 44 && key <= 52)
|
||||
|| (key >= 44 && key <= 53)
|
||||
|| (commandInputPool.length() > 0 && key == 57)){
|
||||
commandInputPool.append(c);
|
||||
inputCursorPos += 1;
|
||||
|
||||
@@ -7,6 +7,7 @@ package com.Torvald.spriteAnimation;
|
||||
|
||||
import com.Torvald.Terrarum.Game;
|
||||
import com.Torvald.Terrarum.Terrarum;
|
||||
import com.jme3.math.FastMath;
|
||||
import org.newdawn.slick.Graphics;
|
||||
import org.newdawn.slick.Image;
|
||||
import org.newdawn.slick.SlickException;
|
||||
@@ -149,10 +150,10 @@ public class SpriteAnimation {
|
||||
|
||||
flippedImage.startUse();
|
||||
flippedImage.drawEmbedded(
|
||||
Math.round(posX * Terrarum.game.screenZoom)
|
||||
, Math.round(posY * Terrarum.game.screenZoom)
|
||||
, width * scale
|
||||
, height * scale
|
||||
FastMath.floor(posX * Terrarum.game.screenZoom)
|
||||
, FastMath.floor(posY * Terrarum.game.screenZoom)
|
||||
, FastMath.floor(width * scale)
|
||||
, FastMath.floor(height * scale)
|
||||
);
|
||||
flippedImage.endUse();
|
||||
}
|
||||
|
||||
@@ -70,8 +70,6 @@ final public class FastMath {
|
||||
public static final float DEG_TO_RAD = PI / 180.0f;
|
||||
/** A value to multiply a radian value by, to convert it to degrees. */
|
||||
public static final float RAD_TO_DEG = 180.0f / PI;
|
||||
/** A precreated random object for random numbers. */
|
||||
public static final Random rand = new Random(System.currentTimeMillis());
|
||||
|
||||
/**
|
||||
* Returns true if the number is a power of 2 (2,4,8,16...)
|
||||
@@ -655,30 +653,6 @@ final public class FastMath {
|
||||
* (m10 * det12 - m11 * det02 + m12 * det01));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a random float between 0 and 1.
|
||||
*
|
||||
* @return A random float between <tt>0.0f</tt> (inclusive) to
|
||||
* <tt>1.0f</tt> (exclusive).
|
||||
*/
|
||||
public static float nextRandomFloat() {
|
||||
return rand.nextFloat();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a random float between min and max.
|
||||
*
|
||||
* @return A random int between <tt>min</tt> (inclusive) to
|
||||
* <tt>max</tt> (inclusive).
|
||||
*/
|
||||
public static int nextRandomInt(int min, int max) {
|
||||
return (int) (nextRandomFloat() * (max - min + 1)) + min;
|
||||
}
|
||||
|
||||
public static int nextRandomInt() {
|
||||
return rand.nextInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a point from Spherical coordinates to Cartesian (using positive
|
||||
* Y as up) and stores the results in the store var.
|
||||
|
||||
@@ -22,43 +22,43 @@ import org.newdawn.slick.util.ResourceLoader;
|
||||
public class Shader {
|
||||
public static final int BRIEF = 128;
|
||||
public static final int MODERATE = 512;
|
||||
public static final int VERBOSE = 1024;
|
||||
public static final int VERBOSE = 1024;
|
||||
private static final int NOT_LOADED = -1;
|
||||
private static final String ERR_LOCATION =
|
||||
"Warning: variable %s could not be found. " +
|
||||
"Ensure the name is spelled correctly\n";
|
||||
private static int logging = MODERATE;
|
||||
|
||||
|
||||
private ShaderResourceManager srm;
|
||||
/**
|
||||
* ID of the <tt>Shader</tt>. A Shader may have programID of
|
||||
* ID of the <tt>Shader</tt>. A Shader may have programID of
|
||||
* -1 only before construction is completed, or
|
||||
* after the <tt>Shader</tt> is deleted
|
||||
*/
|
||||
private int programID = NOT_LOADED;
|
||||
private Map<String, ShaderVariable> vars = new HashMap<String, ShaderVariable>();
|
||||
|
||||
|
||||
|
||||
|
||||
private Shader(ShaderResourceManager srm,
|
||||
Collection<String> vertex,
|
||||
Collection<String> fragment)throws SlickException{
|
||||
this.srm = srm;
|
||||
StringBuilder errorMessage = new StringBuilder();
|
||||
|
||||
|
||||
programID = GL20.glCreateProgram();
|
||||
|
||||
|
||||
int[] shaderIds = new int[vertex.size() + fragment.size()];
|
||||
int index = 0;
|
||||
|
||||
|
||||
//Load Vertex Shaders
|
||||
for(String vertShader: vertex){
|
||||
for(String vertShader: vertex){
|
||||
int vsid = srm.getVertexShaderID(vertShader);
|
||||
srm.createProgramShaderDependancy(programID, vsid);
|
||||
|
||||
|
||||
//Add to shader ids array
|
||||
shaderIds[index] = vsid;
|
||||
index++;
|
||||
|
||||
|
||||
//Check for errors with shader
|
||||
if(!compiledSuccessfully(vsid)){
|
||||
errorMessage.append("Vertex Shader ");
|
||||
@@ -67,20 +67,20 @@ public class Shader {
|
||||
errorMessage.append(getShaderInfoLog(vsid));
|
||||
errorMessage.append("\n\n");
|
||||
}
|
||||
|
||||
|
||||
scanSource(vertShader);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//Load Fragment Shaders
|
||||
for(String fragShader: fragment){
|
||||
for(String fragShader: fragment){
|
||||
int fsid = srm.getFragementShaderID(fragShader);
|
||||
srm.createProgramShaderDependancy(programID, fsid);
|
||||
|
||||
//Add to shader ids array
|
||||
shaderIds[index] = fsid;
|
||||
index++;
|
||||
|
||||
|
||||
//Check for errors with shader
|
||||
if(!compiledSuccessfully(fsid)){
|
||||
errorMessage.append("Fragment Shader ");
|
||||
@@ -89,10 +89,10 @@ public class Shader {
|
||||
errorMessage.append(getShaderInfoLog(fsid));
|
||||
errorMessage.append("\n\n");
|
||||
}
|
||||
|
||||
|
||||
scanSource(fragShader);
|
||||
}
|
||||
|
||||
|
||||
//Attach shaders to program
|
||||
for(int i=0; i<index; i++){
|
||||
GL20.glAttachShader(programID, shaderIds[i]);
|
||||
@@ -104,7 +104,7 @@ public class Shader {
|
||||
errorMessage.append(getProgramInfoLog());
|
||||
errorMessage.append("\n\n");
|
||||
}
|
||||
|
||||
|
||||
if(errorMessage.length()!=0){
|
||||
errorMessage.insert(0, "Could not compile shader.\n");
|
||||
srm.removeProgram(programID);
|
||||
@@ -112,12 +112,12 @@ public class Shader {
|
||||
errorMessage.append("Stack Trace:");
|
||||
throw new SlickException(errorMessage.toString());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Factory method to create a new Shader.
|
||||
* @param vertexFileName
|
||||
@@ -131,23 +131,23 @@ public class Shader {
|
||||
l1.add(vertexFileName);
|
||||
ArrayList<String> l2 = new ArrayList<String>();
|
||||
l2.add(fragmentFileName);
|
||||
|
||||
|
||||
return new Shader(ShaderResourceManagerImpl.getSRM(),
|
||||
l1,
|
||||
l2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Reverts GL context back to the fixed pixel pipeline.<br>
|
||||
*/
|
||||
public static void forceFixedShader(){
|
||||
GL20.glUseProgram(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Sets the number of characters to be returned when printing
|
||||
* errors.</br> Suggested values are the constants
|
||||
@@ -159,8 +159,8 @@ public class Shader {
|
||||
logging = detailLevel;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Deletes this shader and unloads all free resources.</br>
|
||||
* TODO should this be called from <tt>finalise()</tt>, or is
|
||||
@@ -170,9 +170,9 @@ public class Shader {
|
||||
srm.removeProgram(programID);
|
||||
programID = NOT_LOADED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if this <tt>Shader</tt> has been deleted.</br>
|
||||
* @return true if this <tt>Shader</tt> has been deleted.</br>
|
||||
@@ -180,9 +180,9 @@ public class Shader {
|
||||
public boolean isDeleted(){
|
||||
return programID == NOT_LOADED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Activates the shader.</br>
|
||||
*/
|
||||
@@ -194,10 +194,10 @@ public class Shader {
|
||||
forceFixedShader(); //Not sure why this is necessary but it is.
|
||||
GL20.glUseProgram(programID);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//UNIFORM SETTERS
|
||||
|
||||
|
||||
|
||||
//UNIFORM SETTERS
|
||||
/**
|
||||
* Sets the value of the uniform integer Variable <tt>name</tt>.</br>
|
||||
* @param name the variable to set.
|
||||
@@ -206,28 +206,28 @@ public class Shader {
|
||||
public Shader setUniformIntVariable(String name, int value){
|
||||
return setUniformIntVariable(name, new int[]{value});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public Shader setUniformIntVariable(String name, int v0, int v1){
|
||||
return setUniformIntVariable(name, new int[]{v0, v1});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public Shader setUniformIntVariable(String name,
|
||||
int v0, int v1, int v2){
|
||||
return setUniformIntVariable(name, new int[]{v0, v1, v2});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public Shader setUniformIntVariable(String name,
|
||||
int v0, int v1, int v2, int v3){
|
||||
return setUniformIntVariable(name, new int[]{v0, v1, v2, v3});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public Shader setUniformIntVariable(String name, int[] values){
|
||||
ShaderVariable var = vars.get(name);
|
||||
if(var==null){
|
||||
@@ -238,8 +238,8 @@ public class Shader {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Sets the value of the uniform integer Variable
|
||||
* <tt>name</tt>.</br>
|
||||
@@ -249,31 +249,31 @@ public class Shader {
|
||||
public Shader setUniformFloatVariable(String name, float value){
|
||||
return setUniformFloatVariable(name, new float[]{value});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public Shader setUniformFloatVariable(String name,
|
||||
float v0, float v1){
|
||||
return setUniformFloatVariable(name, new float[]{v0, v1});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public Shader setUniformFloatVariable(String name,
|
||||
float v0, float v1, float v2){
|
||||
return setUniformFloatVariable(name, new float[]{v0, v1, v2});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public Shader setUniformFloatVariable(String name,
|
||||
float v0, float v1,
|
||||
float v2, float v3){
|
||||
return setUniformFloatVariable(name, new float[]{v0, v1, v2, v3});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public Shader setUniformFloatVariable(String name, float[] values){
|
||||
ShaderVariable var = vars.get(name);
|
||||
if(var==null){
|
||||
@@ -283,9 +283,9 @@ public class Shader {
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//TODO implement using ShaderVariable
|
||||
//TODO Test
|
||||
public Shader setUniformMatrix(String name,
|
||||
@@ -293,7 +293,7 @@ public class Shader {
|
||||
float[][] matrix){
|
||||
//Convert matrix format
|
||||
FloatBuffer matBuffer = matrixPrepare(matrix);
|
||||
|
||||
|
||||
//Get uniform location
|
||||
int location = GL20.glGetUniformLocation(programID, name);
|
||||
printError(name);
|
||||
@@ -307,12 +307,12 @@ public class Shader {
|
||||
case 4: GL20.glUniformMatrix4(location, transpose, matBuffer);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private FloatBuffer matrixPrepare(float[][] matrix){
|
||||
//Check argument validity
|
||||
if(matrix==null){
|
||||
@@ -327,7 +327,7 @@ public class Shader {
|
||||
throw new IllegalArgumentException("The matrix must have an equal number of rows and columns.");
|
||||
}
|
||||
float[] unrolled = new float[row*col];
|
||||
|
||||
|
||||
for(int i=0;i<row;i++){
|
||||
for(int j=0;j<col;j++){
|
||||
unrolled[i*col+j] = matrix[i][j];
|
||||
@@ -337,15 +337,15 @@ public class Shader {
|
||||
//TODO FloatBuffer creation here is probably broken
|
||||
return FloatBuffer.wrap(unrolled);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private void printError(String varName){
|
||||
System.err.printf(ERR_LOCATION, varName);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the shader compiled successfully.</br>
|
||||
* @param shaderID
|
||||
@@ -355,8 +355,8 @@ public class Shader {
|
||||
return GL20.glGetShader(shaderID, GL20.GL_COMPILE_STATUS)==GL11.GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the shader program linked successfully.</br>
|
||||
* @return true if the shader program linked successfully.</br>
|
||||
@@ -366,15 +366,15 @@ public class Shader {
|
||||
return true;
|
||||
// return GL20.glGetShader(programID, GL20.GL_LINK_STATUS)==GL11.GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private String getShaderInfoLog(int shaderID){
|
||||
return GL20.glGetShaderInfoLog(shaderID, logging).trim();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private String getProgramInfoLog(){
|
||||
return GL20.glGetProgramInfoLog(programID, logging).trim();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user