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:
Song Minjae
2016-02-10 21:27:50 +09:00
parent 954076d944
commit 224ba8f6be
63 changed files with 1163 additions and 482 deletions

View 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)

66
res/books/hangul_test.txt Normal file
View File

@@ -0,0 +1,66 @@
낮에는 따사로운 인간적인 여자
커피 한잔의 여유를 아는 품격 있는 여자
밤이 오면 심장이 뜨거워지는 여자
그런 반전 있는 여자
나는 사나이
낮에는 너만큼 따사로운 그런 사나이
커피 식기도 전에 원샷 때리는 사나이
밤이 오면 심장이 터져버리는 사나이
그런 사나이
아름다워 사랑스러워
그래 너 hey 그래 바로 너 hey
아름다워 사랑스러워
그래 너 hey 그래 바로 너 hey
지금부터 갈 데까지 가볼까
오빤 강남스타일
강남스타
오빤 강남스타일
강남스타일
오빤 강남스타일
Eh- Sexy Lady
오빤 강남스타일
Eh- Sexy Lady
오오오오
정숙해 보이지만 놀 땐 노는 여자
이때다 싶으면 묶었던 머리 푸는 여자
가렸지만 웬만한 노출보다 야한 여자
그런 감각적인 여자
나는 사나이
점잖아 보이지만 놀 땐 노는 사나이
때가 되면 완전 미쳐버리는 사나이
근육보다 사상이 울퉁불퉁한 사나이
그런 사나이
아름다워 사랑스러워
그래 너 hey 그래 바로 너 hey
아름다워 사랑스러워
그래 너 hey 그래 바로 너 hey
지금부터 갈 데까지 가볼까
오빤 강남스타일
강남스타일
오빤 강남스타일
강남스타일
오빤 강남스타일
Eh- Sexy Lady
오빤 강남스타일
Eh- Sexy Lady
오오오오
뛰는 놈 그 위에 나는 놈
baby baby 나는 뭘 좀 아는 놈
뛰는 놈 그 위에 나는 놈
baby baby 나는 뭘 좀 아는 놈
You know what I'm saying
오빤 강남스타일
Eh- Sexy Lady
오빤 강남스타일
Eh- Sexy Lady
오빤 강남스타일

38
res/books/isl_test.txt Normal file
View File

@@ -0,0 +1,38 @@
Sjá snjóinn glitra á fjallinu í nótt, ekkert fótspor hér að sjá
Eitt einsemdar konungsríki, og ég virðist, drottningin
Vindurinn gnauðar eins og ólgan inni í mér
Gat ei byrgt það inni en ég reyndi samt
Hleyp þeim ei inn lát þau ei sjá
Vertu góða stelpan sem þú varst
Feldu, bældu, seg þeim ei frá
En þau vita það þá
Þetta er nóg, þetta er nóg. Get ei lengur haldið í mér
Þetta er nóg, þetta er nóg. Ég sný burt og skelli á eftir mér
Mig varðar ei, hvað þau segja við því
Látið geysa storm, kuldinn hann hefur ei háð mér neitt
Það er merkilegt hvað fjarlægð, gerir allt svo ofursmátt
Og hræðslan sem hafði tökin, virðist missa allan mátt
Ég þarf að sjá hvað ég get gert, og reyná verk mín umtalsvert
Og boð og bönn ei halda mér
Ég er frjáls
Þetta er nóg, þetta er nóg. Uppi í himni eins og vindablær
Þetta er nóg, komið nóg. Og tár mín enginn sér fær
Hér ég stend, og hér ég verð
Látið geysa storm
Minn máttur þyrlast gegnum loftið niðrá jörð
Mín sál er hringiða úr frosnum brotamyndum gjörð
Ein hugsun kristalla sem ískalt sprengigos
Ég aldrei aftur sný, það var sem eitt sinn var
Þetta er nóg, þetta er nóg. Og ég rís eins og morgunsól
Þetta er nóg, þetta er nóg. Þessi þæga stelpa fór
Hér ég stend, ein um bjartan dag
Látið geysa storm
Kuldinn hann hefur ei háð mér neitt

29
res/books/kana_test.txt Normal file
View File

@@ -0,0 +1,29 @@
せかいいち みんなの にんきもの
それは かのじょの こと アシュリー
ひとめ みれば だれもが ふりむく
あたりまえ アシュリーだもん
せかいじゅう みんなが あこがれる
それは かのじょの こと アシュリー
アシュリー さまの まほうは さいこう
こんやも パーティーよ
なわ ぶな ぬー わらいの じゅもん
じお いら うん なんの じゅもん
いお でぃ えむ おぼえ られない
ああ いや たいくつ
せかいいち みんなの にんきもの
それは かのじょの こと アシュリー
アシュリー さまの まほうは さいこう
こわい もの なしよ
よぞらの うみ あまたの ほし
いつも ひとりきり
みんなと なかよく したいの
どうしたら いいの
せかいいち みんなの にんきもの
それは かのじょの こと アシュリー
アシュリー さまの まほうは さいこう
こんやも パーティーよ

View File

@@ -0,0 +1,31 @@
The snow glows white on the mountain tonight, not a footprint to be seen
Un royaume de solitude, ma place est là pour toujours
Der Wind, er heult so wie der Sturm ganz tief in mir
Het werd mij te veel, hoe ik mijn best ook deed
[han logographics not supported]
Visa ingenting, vad du än gör, allt är förstört
ありの ままの すがた みせるのよ
Libre soy, libre soy, ¡libertad sin vuelta atrás!
Wszystkim wbrew na ten gest mnie stać
Jöjjön száz orkán, és közben a szívemen ül a jég
Desde la distancia, ¡qué pequeño todo es!
I les pors que em dominaven per sempre han fugit
Non è un difetto, è una virtù! e non la fermerò mai più,
내 맘대로 자유롭게 살래!
Сад је крај, сад је крај На крилима ветра сам
[han logographics not supported]
Estou aqui, e vou ficar! Venha a tempestade
Kuasaku buat hidup bercelaru
Подвластны мне мороз и лёд, ну что за дивный дар
Og som krystaller står en tanke ganske klar
Ще спра да бъда аз на миналото в плен
La den gå, la den gå, jeg skal stige lik solen nå
[thai language not supported]
Je suis là, comme je l'ai rêvé
En de storm raast door! De vrieskou, daar zat ik toch al niet mee

View File

@@ -1,16 +1,16 @@
᛭ᚱᛂᚴᛋ᛬ᛏᛂᛁᚢᛋ᛬ᚴᚢᛂ᛭
᛭ᚱᛂᚴᛋ᛬ᛏᛂᛁᚢᛋ᛬ᚴᚢᛂ᛭
᛬ᚱᚴᛋ᛬ᛋᛏ᛬ᛋᚢ᛬ᚾᛒᚢᛏᛚᚢᛋ᛬
᛬ᚱᚴᛋ᛬ᛋᚢᚼᚾᚢ᛬ᚢᛚᚾᛏᚢ᛬
᛬ᛏᚢᛋᛁᚢ᛬ᚴᚢᛏᚢᚱ᛬ᛒᚱᚴᛋᛏ᛬
᛫ᛋᚢᚼᚾᚢᛋ᛬ᚬᛁ᛬ᚴᚾᛁᛏᚢᛏ᛫
᛬ᚴᛂᛁᛏᚱ᛬ᛏᛘ᛬ᚱᛂᚴᛘ᛬ᚢᛂᚢᚴᛂᛏ᛬
᛫ᛁᛅᚴᛂᛋᚢ᛬ᛏᛂᛁᚢᛘ᛬ᚢᛂᚱᚢᚾᛘ᛫
᛬ᚢᛒᚢ᛬ᚱᛂᚴᛋ᛬ᛏᛂᛁᚢᛘ᛬ᚢᛂᚱᚢᚾᚢᛘ᛬ᛋᛂᛋᚢᛚᛂ᛬ᚾᚢ᛬ᛏᛂᛁᚢᛘ᛬ᛁᛅᚴᛂᛏᚢ᛬
᛫ᚴᛚᚢᛏᛁ᛬ᛘᛁ᛬ᛒᛏᛂᚱ᛬ᚢᛂᚱᚢᚾᛂ᛫
᛬ᛏᛂᛁᚢᛋ᛬ᚢᛂᚱᚢᚾᛋ᛬ᛏᛁᚢᛂᛋ᛬ᚾᛘᛏᛅ᛬ᚴᚢᛅᛏ᛬
᛬ᚱᚴᛋ᛬ᛋᛏ᛬ᛋᚢ᛬ᚾᛒᚢᛏᛚᚢᛋ᛬
᛬ᚱᚴᛋ᛬ᛋᚢᚼᚾᚢ᛬ᚢᛚᚾᛏᚢ᛬
᛬ᛏᚢᛋᛁᚢ᛬ᚴᚢᛏᚢᚱ᛬ᛒᚱᚴᛋᛏ᛬
᛫ᛋᚢᚼᚾᚢᛋ᛬ᚬᛁ᛬ᚴᚾᛁᛏᚢᛏ᛫
᛬ᚴᛂᛁᛏᚱ᛬ᛏᛘ᛬ᚱᛂᚴᛘ᛬ᚢᛂᚢᚴᛂᛏ᛬
᛫ᛁᛅᚴᛂᛋᚢ᛬ᛏᛂᛁᚢᛘ᛬ᚢᛂᚱᚢᚾᛘ᛫
᛬ᚢᛒᚢ᛬ᚱᛂᚴᛋ᛬ᛏᛂᛁᚢᛘ᛬ᚢᛂᚱᚢᚾᚢᛘ᛬ᛋᛂᛋᚢᛚᛂ᛬ᚾᚢ᛬ᛏᛂᛁᚢᛘ᛬ᛁᛅᚴᛂᛏᚢ᛬
᛫ᚴᛚᚢᛏᛁ᛬ᛘᛁ᛬ᛒᛏᛂᚱ᛬ᚢᛂᚱᚢᚾᛂ᛫
᛬ᛏᛂᛁᚢᛋ᛬ᚢᛂᚱᚢᚾᛋ᛬ᛏᛁᚢᛂᛋ᛬ᚾᛘᛏᛅ᛬ᚴᚢᛅᛏ᛬
᛫ᚴᚢᛁᛏ᛬ᚢᛂᛚᛋᛁ᛫
᛫ᛋᚢᚼᚾᚢᛘ᛬ᚢᛂᛚᛘᛁ᛫
᛫ᛏᚢᛏ᛬ᛂᛋᛏᚢ᛫
᛬ᚢᛂᚢᚴᛂᛏ᛬ᛚᛂᚢᚴᚢᛋ᛬ᛏᛂᛁᚢᛋ᛬ᚢᛂᚱᚢᚾᛋ᛬
᛬ᚾᚢ᛬ᚱᛂᚴᛋ᛬ᛒᛏᚾᛁ᛬ᛋᚢᚼᚾᚢᛘ᛬ᚴᛂᚴᚢᚾᛂ᛬
᛬ᚢᛂᚢᚴᛂᛏ᛬ᛚᛂᚢᚴᚢᛋ᛬ᛏᛂᛁᚢᛋ᛬ᚢᛂᚱᚢᚾᛋ᛬
᛬ᚾᚢ᛬ᚱᛂᚴᛋ᛬ᛒᛏᚾᛁ᛬ᛋᚢᚼᚾᚢᛘ᛬ᚴᛂᚴᚢᚾᛂ᛬

Binary file not shown.

After

Width:  |  Height:  |  Size: 305 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
res/graphics/fonts/kana.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 45 KiB

View File

@@ -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;
}
}

View 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;
}
}

View 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;
}
}

View File

@@ -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;
}

View File

@@ -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"

View File

@@ -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;
}

View File

@@ -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();

View File

@@ -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;
}
}

View File

@@ -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;

View File

@@ -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);

View File

@@ -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 {

View File

@@ -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.

View 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");
}
}

View 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) {

View File

@@ -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));
}

View File

@@ -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);
}
}

View 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)

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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();

View File

@@ -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;

View File

@@ -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());

View File

@@ -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++){

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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();
}

View File

@@ -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.

View File

@@ -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();
}