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

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