Compare commits

...

48 Commits

Author SHA1 Message Date
minjaesong
af619cda79 instead of frequently accessing Java from C-side, feed everything beforehand on Java-side 2019-02-08 11:46:30 +09:00
minjaesong
78bbd9c051 wip 2019-02-04 06:26:12 +09:00
minjaesong
3f108a6ea9 quicker camera on buildingmaker 2019-02-04 01:37:31 +09:00
minjaesong
a831a4d798 fixing mouseUp on NSMenu; making pen on buildingmaker work 2019-02-03 23:53:46 +09:00
minjaesong
e3ed712a42 F3 moved to PostProcessor; palette UI for buildingmaker 2019-02-03 17:01:27 +09:00
minjaesong
daf5c02605 #12 event for world block change -- mainly meant for fixture updating itself 2019-02-02 01:58:49 +09:00
minjaesong
e8b39fc668 blocksdrawer use offsetted time_t 2019-02-02 01:08:14 +09:00
minjaesong
c20d7edb34 closing #22 2019-02-01 22:45:34 +09:00
minjaesong
28f305e76f application icons 2019-02-01 20:15:19 +09:00
minjaesong
4c3fc2352c #21, also making seasonal grasses easier on PSD 2019-02-01 18:47:02 +09:00
minjaesong
01094d49eb wall block item to use its own texture (for real) 2019-02-01 17:28:08 +09:00
minjaesong
7d3bf0eece terrain texture change by all seasons 2019-02-01 15:59:54 +09:00
minjaesong
75f128a8f7 fixed notificator UI 2019-01-31 20:54:25 +09:00
minjaesong
514f1e9012 nsmenu to invoke class with defined args; working settime on buildingmaker 2019-01-31 18:01:33 +09:00
minjaesong
60db83eddb making sure unused screen be disposed, and not breaking the app 2019-01-31 13:29:40 +09:00
minjaesong
90a7fcd4d0 fix memory leak from my ididcy; relationship w #19 needs investigation 2019-01-31 05:02:44 +09:00
minjaesong
d93c6de851 language is moved inside of options 2019-01-31 03:27:03 +09:00
minjaesong
f603b58307 adjusting disposing behavs so that we can go back and forth the ingame and titlescr 2019-01-31 00:12:38 +09:00
minjaesong
074fe2438d inventory gamemenu visual only 2019-01-29 23:37:38 +09:00
minjaesong
69e9fa4b0f 3 screens impl of inventory UI wip 2019-01-29 20:24:11 +09:00
minjaesong
9373feff34 nice try, but it crashes the gpu AND I get <1 fps :( 2019-01-29 17:35:56 +09:00
minjaesong
10c188bea7 wrong colour fixed -- Gdx.Color.toIntBits() returns ABGR, GLSL expects RGBA 2019-01-29 03:04:01 +09:00
minjaesong
cd1ad9277a gpu rendered light wip 2019-01-29 02:21:22 +09:00
minjaesong
465ed0d7a4 inventory ui won't always draw item count 2019-01-28 19:22:47 +09:00
minjaesong
bd1c1bff8a amount of fluid affects the light absorption 2019-01-27 16:58:29 +09:00
minjaesong
8ac5f1dc9e nuked fluidcodex 2019-01-27 05:09:52 +09:00
minjaesong
268907ee9d so not making new objs frequently does make it bit faster... 2019-01-27 02:09:20 +09:00
minjaesong
9937c34d25 light calc takes fluid into account 2019-01-27 00:30:56 +09:00
minjaesong
bdbb30bc58 new watch design consistent with existing UI 2019-01-24 23:46:24 +09:00
minjaesong
bdbf6cd458 new TV-safe watch UI 2019-01-24 02:32:28 +09:00
minjaesong
e4f456ffa7 gapbox toggle with F11 2019-01-23 12:45:40 +09:00
minjaesong
73a6c844c8 less intrusive gapbox colours 2019-01-23 03:52:28 +09:00
minjaesong
84ca954a26 F12 for screenshot; it's high time to care about TVs
(besides, the EBU gap is also a good guideline for placing UIs on edge)
2019-01-23 03:46:46 +09:00
minjaesong
66b18bf8c5 equipped items are drawn into their respective slot 2019-01-23 00:50:20 +09:00
minjaesong
6d0bff2879 greater number of inventory cells 2019-01-23 00:09:31 +09:00
minjaesong
14b485dc32 small number font moved to apploader 2019-01-22 23:05:29 +09:00
minjaesong
a192abd657 glsl works differently on my macbook? 2019-01-22 22:23:30 +09:00
minjaesong
0d534fd60c adding demoworld.gz 2019-01-22 21:34:00 +09:00
minjaesong
a4dabbbf37 adding gradle-wrapper.jar 2019-01-22 21:27:56 +09:00
minjaesong
450874540c initial screen size is read from the config 2019-01-22 20:56:16 +09:00
minjaesong
53c45d6829 smoothDelta is now come from Gdx's LwjglGraphics instead of AppLoader 2019-01-22 13:16:21 +09:00
minjaesong
1c839f7135 test impl kalman delta on gdx 2019-01-22 06:30:11 +09:00
minjaesong
f133406df3 copyright update 2019-01-22 05:57:38 +09:00
minjaesong
ae14026191 implementing the iconic 'lag behind' camera the right way 2019-01-22 05:46:26 +09:00
minjaesong
b9a4e0f64b game actually reads fps setting from config 2019-01-22 05:29:03 +09:00
minjaesong
aef601e9b8 some classes in sprite assembler is now internal 2019-01-22 03:51:18 +09:00
minjaesong
88db71f780 ingame will only render visible actor 2019-01-22 03:50:35 +09:00
minjaesong
ded9cb1a10 instead of dealing with delta, we'll just update multiple times, THIS TIME IN CORRECT WAY
(because it really works :p)
2019-01-22 02:59:22 +09:00
130 changed files with 3554 additions and 1177 deletions

2
.gitignore vendored
View File

@@ -14,7 +14,7 @@ Thumbs.db
# Resources that should not be tracked # Resources that should not be tracked
*.jar *.jar
assets/mods/basegame/demoworld assets/mods/basegame/demoworld
assets/mods/basegame/demoworld.gz #assets/mods/basegame/demoworld.gz
external_resource_packs.zip external_resource_packs.zip
# IntelliJ # IntelliJ

BIN
assets/appicon128.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 462 B

BIN
assets/appicon16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 366 B

BIN
assets/appicon256.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 559 B

BIN
assets/appicon32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 387 B

BIN
assets/appicon64.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 B

View File

@@ -71,7 +71,7 @@ The control is omnidirectional. In other words, \emph{not} cell-based.
\subsubsection{ISO\slash ANSI\slash JIS pedalboards} \subsubsection{ISO\slash ANSI\slash JIS pedalboards}
Your default moving around uses ESDF (qwerty)\slash FRST (colemak)\slash .OEW (dvorak) pedals for default `WASD', in order for you to provide more modifier pedals---QAZ (qwerty\slash colemak), /A; (dvorak)---that are pressed with your little finger and more comfort to some pedalboards with Topre actuators.\footnote{Writers of this book would recommend you to use pedalboard with Cherry MX Red actuators, though any decent pedalboard should be sufficient.} Your default moving around uses ESDF (qwerty)\slash FRST (colemak)\slash .OEW (dvorak) pedals for default `WASD', in order for you to provide more modifier pedals---QAZ (qwerty\slash colemak), /A; (dvorak)---that are pressed with your little finger and more comfort to some pedalboards with Topre actuators.\footnote{Writers of this book would recommend you to use pedalboard with Cherry MX Red actuators, though any decent pedalboard should be sufficient.}
\subsubsection{Joypads} \subsubsection{gamepads}
Your moving around uses left stick, and direction of the movement is \emph{not} limited to 8 directions, hence the term, “omni\-direc\-tion\-al”. Your moving around uses left stick, and direction of the movement is \emph{not} limited to 8 directions, hence the term, “omni\-direc\-tion\-al”.
\section{World} \section{World}

View File

@@ -0,0 +1,15 @@
SET basefilename=%~d1%~p1%~n1
SET inputextension=%~x1
rem inputextension should be dot-psd
rem color space must be Lab16
IF "%inputextension%" NEQ ".psd" goto fail
convert %1 -colorspace sRGB -write mpr:temp -background black -alpha Remove mpr:temp -compose Copy_Opacity -composite "%basefilename%.tga"
exit
:fail
echo "File not PSD"
pause
exit /b 1

Binary file not shown.

View File

@@ -2053,7 +2053,7 @@
}, },
{ {
"n": "MENU_LABEL_MAINMENU", "n": "MENU_LABEL_MAINMENU",
"s": "메뉴" "s": "메인 메뉴"
}, },
{ {
"n": "MENU_LABEL_MORE", "n": "MENU_LABEL_MORE",

View File

@@ -46,8 +46,8 @@
"145"; "0";"BLOCK_ICE_FRAGILE" ;"0.0508";"0.0508";"0.0508";"0.0508"; "5"; "930";"ICEI"; "1"; "0"; "1"; "0"; "0"; "0"; "N/A"; "0"; "4";"0.0000";"0.0000";"0.0000";"0.0000" "145"; "0";"BLOCK_ICE_FRAGILE" ;"0.0508";"0.0508";"0.0508";"0.0508"; "5"; "930";"ICEI"; "1"; "0"; "1"; "0"; "0"; "0"; "N/A"; "0"; "4";"0.0000";"0.0000";"0.0000";"0.0000"
"146"; "146";"BLOCK_ICE_NATURAL" ;"0.1016";"0.1016";"0.1016";"0.1016"; "35"; "930";"ICEI"; "1"; "0"; "1"; "1"; "0"; "0"; "N/A"; "0"; "4";"0.0000";"0.0000";"0.0000";"0.0000" "146"; "146";"BLOCK_ICE_NATURAL" ;"0.1016";"0.1016";"0.1016";"0.1016"; "35"; "930";"ICEI"; "1"; "0"; "1"; "1"; "0"; "0"; "N/A"; "0"; "4";"0.0000";"0.0000";"0.0000";"0.0000"
"147"; "147";"BLOCK_ICE_CLEAR_MAGICAL" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"3720";"ICEX"; "1"; "0"; "1"; "1"; "0"; "0"; "N/A"; "0"; "4";"0.0744";"0.1252";"0.2268";"0.0000" "147"; "147";"BLOCK_ICE_CLEAR_MAGICAL" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"3720";"ICEX"; "1"; "0"; "1"; "1"; "0"; "0"; "N/A"; "0"; "4";"0.0744";"0.1252";"0.2268";"0.0000"
"148"; "148";"BLOCK_GLASS_CRUDE" ;"0.0120";"0.0040";"0.0120";"0.0080"; "5";"2500";"GLAS"; "1"; "0"; "1"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000" "148"; "148";"BLOCK_GLASS_CRUDE" ;"0.0876";"0.0424";"0.0876";"0.1252"; "5";"2500";"GLAS"; "1"; "0"; "1"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"149"; "149";"BLOCK_GLASS_CLEAN" ;"0.0040";"0.0040";"0.0040";"0.0020"; "5";"2203";"GLAS"; "1"; "0"; "1"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000" "149"; "149";"BLOCK_GLASS_CLEAN" ;"0.0424";"0.0424";"0.0424";"0.0636"; "5";"2203";"GLAS"; "1"; "0"; "1"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"160"; "160";"BLOCK_PLATFORM_STONE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "5"; "N/A";"ROCK"; "0"; "1"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000" "160"; "160";"BLOCK_PLATFORM_STONE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "5"; "N/A";"ROCK"; "0"; "1"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"161"; "161";"BLOCK_PLATFORM_WOODEN" ;"0.0312";"0.0312";"0.0312";"0.0312"; "5"; "N/A";"WOOD"; "0"; "1"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000" "161"; "161";"BLOCK_PLATFORM_WOODEN" ;"0.0312";"0.0312";"0.0312";"0.0312"; "5"; "N/A";"WOOD"; "0"; "1"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"162"; "162";"BLOCK_PLATFORM_EBONY" ;"0.0312";"0.0312";"0.0312";"0.0312"; "5"; "N/A";"WOOD"; "0"; "1"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000" "162"; "162";"BLOCK_PLATFORM_EBONY" ;"0.0312";"0.0312";"0.0312";"0.0312"; "5"; "N/A";"WOOD"; "0"; "1"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
@@ -98,15 +98,15 @@
"256"; "256";"BLOCK_LANTERN_IRON_REGULAR" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"FXTR"; "0"; "0"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"1.0000";"0.6372";"0.0000";"0.0000" "256"; "256";"BLOCK_LANTERN_IRON_REGULAR" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"FXTR"; "0"; "0"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"1.0000";"0.6372";"0.0000";"0.0000"
"257"; "257";"BLOCK_SUNSTONE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"ROCK"; "1"; "0"; "0"; "0"; "0"; "2"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000" "257"; "257";"BLOCK_SUNSTONE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"ROCK"; "1"; "0"; "0"; "0"; "0"; "2"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"258"; "258";"BLOCK_DAYLIGHT_CAPACITOR" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "0"; "0"; "3"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000" "258"; "258";"BLOCK_DAYLIGHT_CAPACITOR" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "0"; "0"; "3"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"4094"; "0";"BLOCK_LAVA" ;"0.9696";"0.9696";"0.9696";"0.9696";"100";"2600";"ROCK"; "0"; "0"; "1"; "0"; "0"; "0"; "32"; "0";"16";"0.7664";"0.2032";"0.0000";"0.0000" "4096"; "0";"BLOCK_WATER" ;"0.1016";"0.0744";"0.0508";"0.0826";"100";"1000";"WATR"; "0"; "0"; "1"; "0"; "0"; "0"; "16"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"4095"; "0";"BLOCK_WATER" ;"0.1016";"0.0744";"0.0508";"0.0508";"100";"1000";"WATR"; "0"; "0"; "1"; "0"; "0"; "0"; "16"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000" "4097"; "0";"BLOCK_LAVA" ;"0.9696";"0.9696";"0.9696";"0.9696";"100";"2600";"ROCK"; "0"; "0"; "1"; "0"; "0"; "0"; "32"; "0";"16";"0.7664";"0.2032";"0.0000";"0.0000"
"-1"; "0";"BLOCK_NULL" ;"4.0000";"4.0000";"4.0000";"4.0000"; "-1";"2600";"NULL"; "0"; "0"; "1"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000" "-1"; "0";"BLOCK_NULL" ;"4.0000";"4.0000";"4.0000";"4.0000"; "-1";"2600";"NULL"; "0"; "0"; "1"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
## Notes ## ## Notes ##
# #
# Lava/Water props are left for future references, do not delete them until FluidCodex is built # # Lava/Water props are left for future references, do not delete them until FluidCodex is built #
# #
# id: Block ID # id: Block ID. ID equal to or greater than 4096 is for fluids, mainly for lighting calculation.
# drop: Drop ID # drop: Drop ID
# #
# shdr/g/b, lumr/g/b: Shade RGB/ Lum RGB. # shdr/g/b, lumr/g/b: Shade RGB/ Lum RGB.
Can't render this file because it contains an unexpected character in line 1 and column 20.

Binary file not shown.

View File

@@ -8,22 +8,22 @@
"multithread": true, "multithread": true,
"joypadkeyn": 4, "gamepadkeyn": 4,
"joypadkeyw": 1, "gamepadkeyw": 1,
"joypadkeys": 2, "gamepadkeys": 2,
"joypadkeye": 3, "gamepadkeye": 3,
"joypadlup": 4, "gamepadlup": 4,
"joypadrup": 5, "gamepadrup": 5,
"joypadldown": 6, "gamepadldown": 6,
"joypadrdown": 7, "gamepadrdown": 7,
"joypadlstickx": 0, "gamepadlstickx": 0,
"joypadlsticky": 1, "gamepadlsticky": 1,
"joypadrstickx": 2, "gamepadrstickx": 2,
"joypadrsticky": 3, "gamepadrsticky": 3,
"joypadlabelstyle": "msxb360", "gamepadlabelstyle": "msxb360",
"keyup": 33, "keyup": 33,

BIN
assets/mods/basegame/demoworld.gz LFS Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -10,5 +10,5 @@ uniform sampler2D u_texture;
void main(void) { void main(void) {
gl_FragColor = texture2D(u_texture, v_texCoords); gl_FragColor = vec4(texture2D(u_texture, v_texCoords).rgb, 1.0);
} }

108
assets/raytracelight.frag Normal file
View File

@@ -0,0 +1,108 @@
#version 120
#ifdef GL_ES
precision mediump float;
#endif
varying vec4 v_color;
varying vec2 v_texCoords;
// all 3 must have the same dimension!
// the divisor of 2 input and an output must be the same. I.e. either divide all by 4, or not.
uniform sampler2D shades;
uniform sampler2D lights;
// WARNING -- Gdx.Color.toIntBits returns ABGR, but GLSL expects RGBA. Use the function Color.toRGBA() in LightmapRenderNew
uniform sampler2D u_texture;
uniform vec2 outSize;
uniform float multiplier = 4.0; // if divided by four, put 4.0 in there
#define TRAVERSE_SIZE 128 // should be good for screen size up to 1920 for tile size of 16
vec4 sampleFrom(sampler2D from, vec2 which) {
return texture2D(from, which / outSize);
}
int traceRayCount(vec2 delta) {
vec2 absDelta = abs(delta);
int arraySize = int(max(absDelta.x, absDelta.y));
return arraySize + 1;
}
vec2[TRAVERSE_SIZE] traceRay(int arraySize, vec2 from, vec2 to) {
vec2 delta = to - from;
vec2[TRAVERSE_SIZE] returnArray;
int arri = 0;
// if the line is not vertical...
if (delta.x != 0) {
float deltaError = abs(delta.y / delta.x);
float error = 0.0;
float traceY = from.y;
for (float traceX = from.x; traceX <= to.x; traceX++) {
// plot(traceX, traceY)
returnArray[arri] = vec2(traceX, traceY);
arri = arri + 1;
error = error + deltaError;
if (error >= 0.5) {
traceY = traceY + sign(delta.y);
error = error - 1.0;
}
}
}
else {
for (float traceY = from.y; traceY <= to.y; traceY++) {
returnArray[arri] = vec2(from.x, traceY);
}
}
return returnArray;
}
void main() {
// this code will produce y-flipped image. It's your job to flip it again (e.g. using y-flipped fullscreen quad)
// Nice try, but it kills GPU :(
// reason: looks like traceRayCount() returns value greater than TRAVERSE_SIZE.
// even if I make traceRayCount() to return constant 3, I get less than 1 fps on GTX 970.
vec4 outColor = vec4(0.0,0.0,0.0,0.0);
// 1. pick a light source
for (int y = 0; y < int(outSize.y); y++) {
for (int x = 0; x < int(outSize.x); x++) {
vec2 from = vec2(x + 0.5, y + 0.5); // +0.5 is used because gl_FragCoord does
vec2 to = gl_FragCoord.xy;
vec2 delta = to - from;
int traceCount = traceRayCount(delta);
vec4 light = sampleFrom(lights, from);
// 2. get a trace path
vec2[TRAVERSE_SIZE] returnArray = traceRay(traceCount, from, to);
// 2.1 get angular darkening coefficient
vec2 unitVec = delta / max(delta.x, delta.y);
float angularDimming = sqrt(unitVec.x * unitVec.x + unitVec.y * unitVec.y);
//float angularDimming = 1.0; // TODO depends on the angle of (lightPos, gl_FragCoord.x)
// 3. traverse the light path to dim the "light"
// var "light" will be attenuated after this loop
for (int i = 0; i < traceCount; i++) {
vec4 shade = sampleFrom(shades, returnArray[i]) * angularDimming;
light = light - shade;
}
// 4. mix the incoming light into the light buffer.
outColor = max(outColor, light);
}
}
gl_FragColor = outColor * multiplier;
//gl_FragColor = vec4(0,1,0,1);
//gl_FragColor = sampleFrom(lights, gl_FragCoord.xy) * multiplier;
}

View File

@@ -87,18 +87,18 @@ void main() {
ivec2 breakageXY = getTileXY(breakage + 5); // +5 is hard-coded constant that depends on the atlas ivec2 breakageXY = getTileXY(breakage + 5); // +5 is hard-coded constant that depends on the atlas
mediump vec2 coordInTile = mod(pxCoord, tileSizeInPx) / tileSizeInPx; // 0..1 regardless of tile position in atlas vec2 coordInTile = mod(pxCoord, tileSizeInPx) / tileSizeInPx; // 0..1 regardless of tile position in atlas
// don't really need highp here; read the GLES spec // don't really need highp here; read the GLES spec
mediump vec2 singleTileSizeInUV = vec2(1) / tilesInAtlas; // constant 0.00390625 for unmodified default uniforms vec2 singleTileSizeInUV = vec2(1) / tilesInAtlas; // constant 0.00390625 for unmodified default uniforms
mediump vec2 uvCoordForTile = coordInTile * singleTileSizeInUV; // 0..0.00390625 regardless of tile position in atlas vec2 uvCoordForTile = coordInTile * singleTileSizeInUV; // 0..0.00390625 regardless of tile position in atlas
mediump vec2 uvCoordOffsetTile = tileXY * singleTileSizeInUV; // where the tile starts in the atlas, using uv coord (0..1) vec2 uvCoordOffsetTile = tileXY * singleTileSizeInUV; // where the tile starts in the atlas, using uv coord (0..1)
mediump vec2 uvCoordOffsetBreakage = breakageXY * singleTileSizeInUV; vec2 uvCoordOffsetBreakage = breakageXY * singleTileSizeInUV;
mediump vec2 finalUVCoordForTile = uvCoordForTile + uvCoordOffsetTile;// where we should be actually looking for in atlas, using UV coord (0..1) vec2 finalUVCoordForTile = uvCoordForTile + uvCoordOffsetTile;// where we should be actually looking for in atlas, using UV coord (0..1)
mediump vec2 finalUVCoordForBreakage = uvCoordForTile + uvCoordOffsetBreakage; vec2 finalUVCoordForBreakage = uvCoordForTile + uvCoordOffsetBreakage;
// blending a breakage tex with main tex // blending a breakage tex with main tex
@@ -110,7 +110,7 @@ void main() {
vec4 finalBreakage = texture2D(tilesAtlas, finalUVCoordForBreakage); vec4 finalBreakage = texture2D(tilesAtlas, finalUVCoordForBreakage);
vec4 finalColor = mix(finalTile, finalBreakage, finalBreakage.a); vec4 finalColor = vec4(mix(finalTile.rgb, finalBreakage.rgb, finalBreakage.a), finalTile.a);
gl_FragColor = colourFilter * finalColor; gl_FragColor = colourFilter * finalColor;

BIN
gradle/wrapper/gradle-wrapper.jar vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,743 @@
/*******************************************************************************
* Copyright 2011 See AUTHORS file.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package com.badlogic.gdx.backends.lwjgl;
import com.badlogic.gdx.Application;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Graphics;
import com.badlogic.gdx.graphics.Cursor.SystemCursor;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.GL30;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Pixmap.Format;
import com.badlogic.gdx.graphics.glutils.GLVersion;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.GdxRuntimeException;
import com.badlogic.gdx.utils.SharedLibraryLoader;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.ContextAttribs;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.PixelFormat;
import java.awt.*;
import java.nio.ByteBuffer;
/** An implementation of the {@link Graphics} interface based on Lwjgl.
* @author mzechner */
public class LwjglGraphics implements Graphics {
/** The suppored OpenGL extensions */
static Array<String> extensions;
static GLVersion glVersion;
GL20 gl20;
GL30 gl30;
long frameId = -1;
float deltaTime = 0;
long frameStart = 0;
int frames = 0;
int fps;
long lastTime = System.nanoTime();
Canvas canvas;
boolean vsync = false;
boolean resize = false;
LwjglApplicationConfiguration config;
BufferFormat bufferFormat = new BufferFormat(8, 8, 8, 8, 16, 8, 0, false);
volatile boolean isContinuous = true;
volatile boolean requestRendering = false;
boolean softwareMode;
boolean usingGL30;
// deltaTime kalman filter related variables
private float kalmanEstimate = 1.0f/60.0f;
private float kalmanErrorCovariance = 1.0f;
private final float kalmanErrorRate = 0.2f; // 0.2: empirical value
private final float kalmanUpdateThreshold = 0.1f;
private final float getMagnitudeDifferenceEpsilon = 0.00001f;
LwjglGraphics (LwjglApplicationConfiguration config) {
this.config = config;
}
LwjglGraphics (Canvas canvas) {
this.config = new LwjglApplicationConfiguration();
config.width = canvas.getWidth();
config.height = canvas.getHeight();
this.canvas = canvas;
}
LwjglGraphics (Canvas canvas, LwjglApplicationConfiguration config) {
this.config = config;
this.canvas = canvas;
}
public int getHeight () {
if (canvas != null)
return Math.max(1, canvas.getHeight());
else
return (int)(Display.getHeight() * Display.getPixelScaleFactor());
}
public int getWidth () {
if (canvas != null)
return Math.max(1, canvas.getWidth());
else
return (int)(Display.getWidth() * Display.getPixelScaleFactor());
}
@Override
public int getBackBufferWidth () {
return getWidth();
}
@Override
public int getBackBufferHeight () {
return getHeight();
}
public long getFrameId () {
return frameId;
}
public float getDeltaTime () {
return kalmanEstimate;
}
private void resetDeltaSmoothingHistory() {
kalmanEstimate = 1.0f/60.0f;
kalmanErrorCovariance = 1.0f;
}
// only for a > 0 && b > 0
private float getMagnitudeDifference(float a, float b) {
if (a < getMagnitudeDifferenceEpsilon || b < getMagnitudeDifferenceEpsilon) {
return (a + b) / getMagnitudeDifferenceEpsilon;
}
if (a > b) {
return a / b;
}
else {
return b / a;
}
}
private void updateKalmanRenderDelta() {
// The problem with this kalman filter is that it assumes most simplistic situation:
// 1. the actual delta (measured delta - noise) is constant (that is, not constantly increasing or something)
// 2. everything is linear
// We may need to implement Extended Kalman Filter but what is Jacobian, I suck at maths.
//
// Instead, this implementation will reset itself when difference in magnitude between
// old and new is greater than set value.
//
// It's not perfect but it works, much better than averaging.
if (getMagnitudeDifference(deltaTime, kalmanEstimate) >= 2.0) {
resetDeltaSmoothingHistory();
}
// measurement value
float observation = deltaTime;
if (observation <= kalmanUpdateThreshold) {
// time update
float priorEstimate = kalmanEstimate;
float priorError = kalmanErrorCovariance;
// measurement update
float gain = priorError / (priorError + kalmanErrorRate);
float newEstimate = priorEstimate + gain * (observation - priorEstimate);
float newError = (1.0f - gain) * priorError;
kalmanEstimate = newEstimate;
kalmanErrorCovariance = newError;
}
}
public float getRawDeltaTime () {
return deltaTime;
}
public GraphicsType getType () {
return GraphicsType.LWJGL;
}
public GLVersion getGLVersion () {
return glVersion;
}
public boolean isGL20Available () {
return gl20 != null;
}
public GL20 getGL20 () {
return gl20;
}
@Override
public void setGL20 (GL20 gl20) {
this.gl20 = gl20;
if (gl30 == null) {
Gdx.gl = gl20;
Gdx.gl20 = gl20;
}
}
@Override
public boolean isGL30Available () {
return gl30 != null;
}
@Override
public GL30 getGL30 () {
return gl30;
}
@Override
public void setGL30 (GL30 gl30) {
this.gl30 = gl30;
if (gl30 != null) {
this.gl20 = gl30;
Gdx.gl = gl20;
Gdx.gl20 = gl20;
Gdx.gl30 = gl30;
}
}
public int getFramesPerSecond () {
return fps;
}
void updateTime () {
long time = System.nanoTime();
deltaTime = (time - lastTime) / 1000000000.0f;
lastTime = time;
if (time - frameStart >= 1000000000) {
fps = frames;
frames = 0;
frameStart = time;
}
frames++;
updateKalmanRenderDelta();
}
void setupDisplay () throws LWJGLException {
if (config.useHDPI) {
System.setProperty("org.lwjgl.opengl.Display.enableHighDPI", "true");
}
if (canvas != null) {
Display.setParent(canvas);
} else {
boolean displayCreated = false;
if(!config.fullscreen) {
displayCreated = setWindowedMode(config.width, config.height);
} else {
DisplayMode bestMode = null;
for(DisplayMode mode: getDisplayModes()) {
if(mode.width == config.width && mode.height == config.height) {
if(bestMode == null || bestMode.refreshRate < this.getDisplayMode().refreshRate) {
bestMode = mode;
}
}
}
if(bestMode == null) {
bestMode = this.getDisplayMode();
}
displayCreated = setFullscreenMode(bestMode);
}
if (!displayCreated) {
if (config.setDisplayModeCallback != null) {
config = config.setDisplayModeCallback.onFailure(config);
if (config != null) {
displayCreated = setWindowedMode(config.width, config.height);
}
}
if (!displayCreated) {
throw new GdxRuntimeException("Couldn't set display mode " + config.width + "x" + config.height + ", fullscreen: "
+ config.fullscreen);
}
}
if (config.iconPaths.size > 0) {
ByteBuffer[] icons = new ByteBuffer[config.iconPaths.size];
for (int i = 0, n = config.iconPaths.size; i < n; i++) {
Pixmap pixmap = new Pixmap(Gdx.files.getFileHandle(config.iconPaths.get(i), config.iconFileTypes.get(i)));
if (pixmap.getFormat() != Format.RGBA8888) {
Pixmap rgba = new Pixmap(pixmap.getWidth(), pixmap.getHeight(), Format.RGBA8888);
rgba.drawPixmap(pixmap, 0, 0);
pixmap.dispose();
pixmap = rgba;
}
icons[i] = ByteBuffer.allocateDirect(pixmap.getPixels().limit());
icons[i].put(pixmap.getPixels()).flip();
pixmap.dispose();
}
Display.setIcon(icons);
}
}
Display.setTitle(config.title);
Display.setResizable(config.resizable);
Display.setInitialBackground(config.initialBackgroundColor.r, config.initialBackgroundColor.g,
config.initialBackgroundColor.b);
Display.setLocation(config.x, config.y);
createDisplayPixelFormat(config.useGL30, config.gles30ContextMajorVersion, config.gles30ContextMinorVersion);
initiateGL();
}
/**
* Only needed when setupDisplay() is not called.
*/
void initiateGL() {
extractVersion();
extractExtensions();
initiateGLInstances();
}
private static void extractVersion () {
String versionString = org.lwjgl.opengl.GL11.glGetString(GL11.GL_VERSION);
String vendorString = org.lwjgl.opengl.GL11.glGetString(GL11.GL_VENDOR);
String rendererString = org.lwjgl.opengl.GL11.glGetString(GL11.GL_RENDERER);
glVersion = new GLVersion(Application.ApplicationType.Desktop, versionString, vendorString, rendererString);
}
private static void extractExtensions () {
extensions = new Array<String>();
if (glVersion.isVersionEqualToOrHigher(3, 2)) {
int numExtensions = GL11.glGetInteger(GL30.GL_NUM_EXTENSIONS);
for (int i = 0; i < numExtensions; ++i)
extensions.add(org.lwjgl.opengl.GL30.glGetStringi(GL20.GL_EXTENSIONS, i));
} else {
extensions.addAll(org.lwjgl.opengl.GL11.glGetString(GL20.GL_EXTENSIONS).split(" "));
}
}
/** @return whether the supported OpenGL (not ES) version is compatible with OpenGL ES 3.x. */
private static boolean fullCompatibleWithGLES3 () {
// OpenGL ES 3.0 is compatible with OpenGL 4.3 core, see http://en.wikipedia.org/wiki/OpenGL_ES#OpenGL_ES_3.0
return glVersion.isVersionEqualToOrHigher(4, 3);
}
/** @return whether the supported OpenGL (not ES) version is compatible with OpenGL ES 2.x. */
private static boolean fullCompatibleWithGLES2 () {
// OpenGL ES 2.0 is compatible with OpenGL 4.1 core
// see https://www.opengl.org/registry/specs/ARB/ES2_compatibility.txt
return glVersion.isVersionEqualToOrHigher(4, 1) || extensions.contains("GL_ARB_ES2_compatibility", false);
}
private static boolean supportsFBO () {
// FBO is in core since OpenGL 3.0, see https://www.opengl.org/wiki/Framebuffer_Object
return glVersion.isVersionEqualToOrHigher(3, 0) || extensions.contains("GL_EXT_framebuffer_object", false)
|| extensions.contains("GL_ARB_framebuffer_object", false);
}
private void createDisplayPixelFormat (boolean useGL30, int gles30ContextMajor, int gles30ContextMinor) {
try {
if (useGL30) {
ContextAttribs context = new ContextAttribs(gles30ContextMajor, gles30ContextMinor).withForwardCompatible(false)
.withProfileCore(true);
try {
Display.create(new PixelFormat(config.r + config.g + config.b, config.a, config.depth, config.stencil,
config.samples), context);
} catch (Exception e) {
System.out.println("LwjglGraphics: OpenGL " + gles30ContextMajor + "." + gles30ContextMinor
+ "+ core profile (GLES 3.0) not supported.");
createDisplayPixelFormat(false, gles30ContextMajor, gles30ContextMinor);
return;
}
System.out.println("LwjglGraphics: created OpenGL " + gles30ContextMajor + "." + gles30ContextMinor
+ "+ core profile (GLES 3.0) context. This is experimental!");
usingGL30 = true;
} else {
Display
.create(new PixelFormat(config.r + config.g + config.b, config.a, config.depth, config.stencil, config.samples));
usingGL30 = false;
}
bufferFormat = new BufferFormat(config.r, config.g, config.b, config.a, config.depth, config.stencil, config.samples,
false);
} catch (Exception ex) {
Display.destroy();
try {
Thread.sleep(200);
} catch (InterruptedException ignored) {
}
try {
Display.create(new PixelFormat(0, 16, 8));
if (getDisplayMode().bitsPerPixel == 16) {
bufferFormat = new BufferFormat(5, 6, 5, 0, 16, 8, 0, false);
}
if (getDisplayMode().bitsPerPixel == 24) {
bufferFormat = new BufferFormat(8, 8, 8, 0, 16, 8, 0, false);
}
if (getDisplayMode().bitsPerPixel == 32) {
bufferFormat = new BufferFormat(8, 8, 8, 8, 16, 8, 0, false);
}
} catch (Exception ex2) {
Display.destroy();
try {
Thread.sleep(200);
} catch (InterruptedException ignored) {
}
try {
Display.create(new PixelFormat());
} catch (Exception ex3) {
if (!softwareMode && config.allowSoftwareMode) {
softwareMode = true;
System.setProperty("org.lwjgl.opengl.Display.allowSoftwareOpenGL", "true");
createDisplayPixelFormat(useGL30, gles30ContextMajor, gles30ContextMinor);
return;
}
throw new GdxRuntimeException("OpenGL is not supported by the video driver.", ex3);
}
if (getDisplayMode().bitsPerPixel == 16) {
bufferFormat = new BufferFormat(5, 6, 5, 0, 8, 0, 0, false);
}
if (getDisplayMode().bitsPerPixel == 24) {
bufferFormat = new BufferFormat(8, 8, 8, 0, 8, 0, 0, false);
}
if (getDisplayMode().bitsPerPixel == 32) {
bufferFormat = new BufferFormat(8, 8, 8, 8, 8, 0, 0, false);
}
}
}
}
public void initiateGLInstances () {
if (usingGL30) {
gl30 = new LwjglGL30();
gl20 = gl30;
} else {
gl20 = new LwjglGL20();
}
if (!glVersion.isVersionEqualToOrHigher(2, 0))
throw new GdxRuntimeException("OpenGL 2.0 or higher with the FBO extension is required. OpenGL version: "
+ GL11.glGetString(GL11.GL_VERSION) + "\n" + glVersion.getDebugVersionString());
if (!supportsFBO()) {
throw new GdxRuntimeException("OpenGL 2.0 or higher with the FBO extension is required. OpenGL version: "
+ GL11.glGetString(GL11.GL_VERSION) + ", FBO extension: false\n" + glVersion.getDebugVersionString());
}
Gdx.gl = gl20;
Gdx.gl20 = gl20;
Gdx.gl30 = gl30;
}
@Override
public float getPpiX () {
return Toolkit.getDefaultToolkit().getScreenResolution();
}
@Override
public float getPpiY () {
return Toolkit.getDefaultToolkit().getScreenResolution();
}
@Override
public float getPpcX () {
return (Toolkit.getDefaultToolkit().getScreenResolution() / 2.54f);
}
@Override
public float getPpcY () {
return (Toolkit.getDefaultToolkit().getScreenResolution() / 2.54f);
}
@Override
public float getDensity () {
if (config.overrideDensity != -1) return config.overrideDensity / 160f;
return (Toolkit.getDefaultToolkit().getScreenResolution() / 160f);
}
@Override
public boolean supportsDisplayModeChange () {
return true;
}
@Override
public Monitor getPrimaryMonitor () {
return new LwjglMonitor(0, 0, "Primary Monitor");
}
@Override
public Monitor getMonitor () {
return getPrimaryMonitor();
}
@Override
public Monitor[] getMonitors () {
return new Monitor[] { getPrimaryMonitor() };
}
@Override
public DisplayMode[] getDisplayModes (Monitor monitor) {
return getDisplayModes();
}
@Override
public DisplayMode getDisplayMode (Monitor monitor) {
return getDisplayMode();
}
@Override
public boolean setFullscreenMode (DisplayMode displayMode) {
org.lwjgl.opengl.DisplayMode mode = ((LwjglDisplayMode)displayMode).mode;
try {
if (!mode.isFullscreenCapable()) {
Display.setDisplayMode(mode);
} else {
Display.setDisplayModeAndFullscreen(mode);
}
float scaleFactor = Display.getPixelScaleFactor();
config.width = (int)(mode.getWidth() * scaleFactor);
config.height = (int)(mode.getHeight() * scaleFactor);
if (Gdx.gl != null) Gdx.gl.glViewport(0, 0, config.width, config.height);
resize = true;
return true;
} catch (LWJGLException e) {
return false;
}
}
/** Kindly stolen from http://lwjgl.org/wiki/index.php?title=LWJGL_Basics_5_(Fullscreen), not perfect but will do. */
@Override
public boolean setWindowedMode (int width, int height) {
if (getWidth() == width && getHeight() == height && !Display.isFullscreen()) {
return true;
}
try {
org.lwjgl.opengl.DisplayMode targetDisplayMode = null;
boolean fullscreen = false;
if (fullscreen) {
org.lwjgl.opengl.DisplayMode[] modes = Display.getAvailableDisplayModes();
int freq = 0;
for (int i = 0; i < modes.length; i++) {
org.lwjgl.opengl.DisplayMode current = modes[i];
if ((current.getWidth() == width) && (current.getHeight() == height)) {
if ((targetDisplayMode == null) || (current.getFrequency() >= freq)) {
if ((targetDisplayMode == null) || (current.getBitsPerPixel() > targetDisplayMode.getBitsPerPixel())) {
targetDisplayMode = current;
freq = targetDisplayMode.getFrequency();
}
}
// if we've found a match for bpp and frequence against the
// original display mode then it's probably best to go for this one
// since it's most likely compatible with the monitor
if ((current.getBitsPerPixel() == Display.getDesktopDisplayMode().getBitsPerPixel())
&& (current.getFrequency() == Display.getDesktopDisplayMode().getFrequency())) {
targetDisplayMode = current;
break;
}
}
}
} else {
targetDisplayMode = new org.lwjgl.opengl.DisplayMode(width, height);
}
if (targetDisplayMode == null) {
return false;
}
boolean resizable = !fullscreen && config.resizable;
Display.setDisplayMode(targetDisplayMode);
Display.setFullscreen(fullscreen);
// Workaround for bug in LWJGL whereby resizable state is lost on DisplayMode change
if (resizable == Display.isResizable()) {
Display.setResizable(!resizable);
}
Display.setResizable(resizable);
float scaleFactor = Display.getPixelScaleFactor();
config.width = (int)(targetDisplayMode.getWidth() * scaleFactor);
config.height = (int)(targetDisplayMode.getHeight() * scaleFactor);
if (Gdx.gl != null) Gdx.gl.glViewport(0, 0, config.width, config.height);
resize = true;
return true;
} catch (LWJGLException e) {
return false;
}
}
@Override
public DisplayMode[] getDisplayModes () {
try {
org.lwjgl.opengl.DisplayMode[] availableDisplayModes = Display.getAvailableDisplayModes();
DisplayMode[] modes = new DisplayMode[availableDisplayModes.length];
int idx = 0;
for (org.lwjgl.opengl.DisplayMode mode : availableDisplayModes) {
if (mode.isFullscreenCapable()) {
modes[idx++] = new LwjglDisplayMode(mode.getWidth(), mode.getHeight(), mode.getFrequency(),
mode.getBitsPerPixel(), mode);
}
}
return modes;
} catch (LWJGLException e) {
throw new GdxRuntimeException("Couldn't fetch available display modes", e);
}
}
@Override
public DisplayMode getDisplayMode () {
org.lwjgl.opengl.DisplayMode mode = Display.getDesktopDisplayMode();
return new LwjglDisplayMode(mode.getWidth(), mode.getHeight(), mode.getFrequency(), mode.getBitsPerPixel(), mode);
}
@Override
public void setTitle (String title) {
Display.setTitle(title);
}
/**
* Display must be reconfigured via {@link #setWindowedMode(int, int)} for the changes to take
* effect.
*/
@Override
public void setUndecorated (boolean undecorated) {
System.setProperty("org.lwjgl.opengl.Window.undecorated", undecorated ? "true" : "false");
}
/**
* Display must be reconfigured via {@link #setWindowedMode(int, int)} for the changes to take
* effect.
*/
@Override
public void setResizable (boolean resizable) {
this.config.resizable = resizable;
Display.setResizable(resizable);
}
@Override
public BufferFormat getBufferFormat () {
return bufferFormat;
}
@Override
public void setVSync (boolean vsync) {
this.vsync = vsync;
Display.setVSyncEnabled(vsync);
}
@Override
public boolean supportsExtension (String extension) {
return extensions.contains(extension, false);
}
@Override
public void setContinuousRendering (boolean isContinuous) {
this.isContinuous = isContinuous;
}
@Override
public boolean isContinuousRendering () {
return isContinuous;
}
@Override
public void requestRendering () {
synchronized (this) {
requestRendering = true;
}
}
public boolean shouldRender () {
synchronized (this) {
boolean rq = requestRendering;
requestRendering = false;
return rq || isContinuous || Display.isDirty();
}
}
@Override
public boolean isFullscreen () {
return Display.isFullscreen();
}
public boolean isSoftwareMode () {
return softwareMode;
}
/** A callback used by LwjglApplication when trying to create the display */
public interface SetDisplayModeCallback {
/** If the display creation fails, this method will be called. Suggested usage is to modify the passed configuration to use a
* common width and height, and set fullscreen to false.
* @return the configuration to be used for a second attempt at creating a display. A null value results in NOT attempting
* to create the display a second time */
public LwjglApplicationConfiguration onFailure (LwjglApplicationConfiguration initialConfig);
}
@Override
public com.badlogic.gdx.graphics.Cursor newCursor (Pixmap pixmap, int xHotspot, int yHotspot) {
return new LwjglCursor(pixmap, xHotspot, yHotspot);
}
@Override
public void setCursor (com.badlogic.gdx.graphics.Cursor cursor) {
if (canvas != null && SharedLibraryLoader.isMac) {
return;
}
try {
Mouse.setNativeCursor(((LwjglCursor)cursor).lwjglCursor);
} catch (LWJGLException e) {
throw new GdxRuntimeException("Could not set cursor image.", e);
}
}
@Override
public void setSystemCursor (SystemCursor systemCursor) {
if (canvas != null && SharedLibraryLoader.isMac) {
return;
}
try {
Mouse.setNativeCursor(null);
} catch (LWJGLException e) {
throw new GdxRuntimeException("Couldn't set system cursor");
}
}
private class LwjglDisplayMode extends DisplayMode {
org.lwjgl.opengl.DisplayMode mode;
public LwjglDisplayMode (int width, int height, int refreshRate, int bitsPerPixel, org.lwjgl.opengl.DisplayMode mode) {
super(width, height, refreshRate, bitsPerPixel);
this.mode = mode;
}
}
private class LwjglMonitor extends Monitor {
protected LwjglMonitor (int virtualX, int virtualY, String name) {
super(virtualX, virtualY, name);
}
}
}

View File

@@ -13,7 +13,7 @@ import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
class SpriteAnimation(val parentActor: ActorWBMovable) { class SpriteAnimation(val parentActor: ActorWBMovable) {
private lateinit var textureRegion: TextureRegionPack lateinit var textureRegion: TextureRegionPack; private set
var currentFrame = 0 var currentFrame = 0
var currentRow = 0 var currentRow = 0

View File

@@ -7,11 +7,11 @@ import java.util.*
import kotlin.collections.HashMap import kotlin.collections.HashMap
import kotlin.collections.HashSet import kotlin.collections.HashSet
data class Joint(val name: String, val position: ADPropertyObject.Vector2i) { internal data class Joint(val name: String, val position: ADPropertyObject.Vector2i) {
override fun toString() = "$name $position" override fun toString() = "$name $position"
} }
data class Skeleton(val name: String, val joints: List<Joint>) { internal data class Skeleton(val name: String, val joints: List<Joint>) {
override fun toString() = "$name=$joints" override fun toString() = "$name=$joints"
} }
@@ -22,12 +22,12 @@ data class Skeleton(val name: String, val joints: List<Joint>) {
* @param frames number of frames this animation has * @param frames number of frames this animation has
* @param skeleton list of joints to be transformed * @param skeleton list of joints to be transformed
*/ */
data class Animation(val name: String, val delay: Float, val row: Int, val frames: Int, val skeleton: Skeleton) { internal data class Animation(val name: String, val delay: Float, val row: Int, val frames: Int, val skeleton: Skeleton) {
override fun toString() = "$name delay: $delay, row: $row, frames: $frames, skeleton: ${skeleton.name}" override fun toString() = "$name delay: $delay, row: $row, frames: $frames, skeleton: ${skeleton.name}"
} }
/** Later the 'translate' can be changed so that it represents affine transformation (Matrix2d) */ /** Later the 'translate' can be changed so that it represents affine transformation (Matrix2d) */
data class Transform(val joint: Joint, val translate: ADPropertyObject.Vector2i) { internal data class Transform(val joint: Joint, val translate: ADPropertyObject.Vector2i) {
override fun toString() = "$joint transform: $translate" override fun toString() = "$joint transform: $translate"
} }
@@ -41,11 +41,11 @@ class ADProperties {
lateinit var bodyparts: List<String>; private set lateinit var bodyparts: List<String>; private set
lateinit var bodypartFiles: List<String>; private set lateinit var bodypartFiles: List<String>; private set
/** properties that are being used as skeletons (SKELETON_STAND) */ /** properties that are being used as skeletons (SKELETON_STAND) */
lateinit var skeletons: HashMap<String, Skeleton>; private set internal lateinit var skeletons: HashMap<String, Skeleton>; private set
/** properties that are recognised as animations (ANIM_RUN, ANIM)IDLE) */ /** properties that are recognised as animations (ANIM_RUN, ANIM)IDLE) */
lateinit var animations: HashMap<String, Animation>; private set internal lateinit var animations: HashMap<String, Animation>; private set
/** an "animation frame" property (ANIM_RUN_1, ANIM_RUN_2) */ /** an "animation frame" property (ANIM_RUN_1, ANIM_RUN_2) */
lateinit var transforms: HashMap<String, List<Transform>>; private set internal lateinit var transforms: HashMap<String, List<Transform>>; private set
private val reservedProps = listOf("SPRITESHEET", "EXTENSION") private val reservedProps = listOf("SPRITESHEET", "EXTENSION")
private val animMustContain = listOf("DELAY", "ROW", "SKELETON") private val animMustContain = listOf("DELAY", "ROW", "SKELETON")
@@ -56,7 +56,7 @@ class ADProperties {
var frameHeight: Int = -1; private set var frameHeight: Int = -1; private set
var originX: Int = -1; private set var originX: Int = -1; private set
var originY: Int = -1; private set var originY: Int = -1; private set
val origin: ADPropertyObject.Vector2i internal val origin: ADPropertyObject.Vector2i
get() = ADPropertyObject.Vector2i(originX, originY) get() = ADPropertyObject.Vector2i(originX, originY)
private val animFrameSuffixRegex = Regex("""_[0-9]+""") private val animFrameSuffixRegex = Regex("""_[0-9]+""")
@@ -209,11 +209,11 @@ class ADProperties {
fun toFilename(partName: String) = fun toFilename(partName: String) =
"${this.baseFilename}${partName.toLowerCase()}${this.extension}" "${this.baseFilename}${partName.toLowerCase()}${this.extension}"
fun getAnimByFrameName(frameName: String) = animations[getAnimNameFromFrame(frameName)]!! internal fun getAnimByFrameName(frameName: String) = animations[getAnimNameFromFrame(frameName)]!!
fun getFrameNumberFromName(frameName: String) = frameName.substring(frameName.lastIndexOf('_') + 1 until frameName.length).toInt() internal fun getFrameNumberFromName(frameName: String) = frameName.substring(frameName.lastIndexOf('_') + 1 until frameName.length).toInt()
fun getSkeleton(name: String) = skeletons[name]!! internal fun getSkeleton(name: String) = skeletons[name]!!
fun getTransform(name: String) = transforms[name]!! internal fun getTransform(name: String) = transforms[name]!!
private fun getAnimNameFromFrame(s: String) = s.substring(0 until s.lastIndexOf('_')) private fun getAnimNameFromFrame(s: String) = s.substring(0 until s.lastIndexOf('_'))
@@ -271,7 +271,7 @@ class ADPropertyObject(propertyRaw: String) {
} }
} }
companion object { internal companion object {
private val floatRegex = Regex("""-?[0-9]+(\.[0-9]*)?""") private val floatRegex = Regex("""-?[0-9]+(\.[0-9]*)?""")
private val ivec2Regex = Regex("""-?[0-9]+,-?[0-9]+""") private val ivec2Regex = Regex("""-?[0-9]+,-?[0-9]+""")
private val variableInputSepRegex = Regex(""" +""") private val variableInputSepRegex = Regex(""" +""")
@@ -292,7 +292,7 @@ class ADPropertyObject(propertyRaw: String) {
fun isADstring(property: String) = !isADvariable(property) fun isADstring(property: String) = !isADvariable(property)
} }
data class Vector2i(var x: Int, var y: Int) { internal data class Vector2i(var x: Int, var y: Int) {
override fun toString() = "($x, $y)" override fun toString() = "($x, $y)"
operator fun plus(other: Vector2i) = Vector2i(this.x + other.x, this.y + other.y) operator fun plus(other: Vector2i) = Vector2i(this.x + other.x, this.y + other.y)

View File

@@ -89,7 +89,7 @@ object AssembleSheetPixmap {
} }
object AssembleFrameBase { internal object AssembleFrameBase {
/** /**
* Returns joints list with tranform applied. * Returns joints list with tranform applied.
* @param skeleton list of joints * @param skeleton list of joints

View File

@@ -1,8 +1,7 @@
package net.torvald.terrarum; package net.torvald.terrarum;
import com.badlogic.gdx.ApplicationListener; import com.badlogic.gdx.*;
import com.badlogic.gdx.Gdx; import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.audio.AudioDevice; import com.badlogic.gdx.audio.AudioDevice;
import com.badlogic.gdx.backends.lwjgl.LwjglApplication; import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration; import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
@@ -16,11 +15,19 @@ import com.google.gson.JsonArray;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive; import com.google.gson.JsonPrimitive;
import net.torvald.dataclass.ArrayListMap; import net.torvald.dataclass.ArrayListMap;
import net.torvald.getcpuname.GetCpuName;
import net.torvald.terrarum.gamecontroller.KeyToggler;
import net.torvald.terrarum.imagefont.TinyAlphNum;
import net.torvald.terrarum.modulebasegame.Ingame;
import net.torvald.terrarum.modulebasegame.IngameRenderer; import net.torvald.terrarum.modulebasegame.IngameRenderer;
import net.torvald.terrarum.utils.JsonFetcher; import net.torvald.terrarum.utils.JsonFetcher;
import net.torvald.terrarum.utils.JsonWriter; import net.torvald.terrarum.utils.JsonWriter;
import net.torvald.terrarum.worlddrawer.BlocksDrawer;
import net.torvald.terrarum.worlddrawer.LightmapRenderer;
import net.torvald.terrarumsansbitmap.gdx.GameFontBase; import net.torvald.terrarumsansbitmap.gdx.GameFontBase;
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack; import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack;
import org.lwjgl.input.Controller;
import org.lwjgl.input.Controllers;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@@ -106,9 +113,26 @@ public class AppLoader implements ApplicationListener {
} }
public static final String GAME_NAME = "Terrarum"; public static final String GAME_NAME = "Terrarum";
public static final String COPYRIGHT_DATE_NAME = "Copyright 2013-2018 Torvald (minjaesong)"; public static final String COPYRIGHT_DATE_NAME = "Copyright 2013-2019 Torvald (minjaesong)";
public static String GAME_LOCALE = System.getProperty("user.language") + System.getProperty("user.country"); public static String GAME_LOCALE = System.getProperty("user.language") + System.getProperty("user.country");
public static final String systemArch = System.getProperty("os.arch");
public static String processor;
public static String processorVendor;
public static String renderer;
public static String rendererVendor;
public static final boolean is32BitJVM = !System.getProperty("sun.arch.data.model").contains("64");
public static final float TV_SAFE_GRAPHICS = 0.05f; // as per EBU recommendation (https://tech.ebu.ch/docs/r/r095.pdf)
public static final float TV_SAFE_ACTION = 0.035f; // as per EBU recommendation (https://tech.ebu.ch/docs/r/r095.pdf)
public static int getTvSafeGraphicsWidth() { return Math.round(screenW * TV_SAFE_GRAPHICS); }
public static int getTvSafeGraphicsHeight() { return Math.round(screenH * TV_SAFE_GRAPHICS); }
public static int getTvSafeActionWidth() { return Math.round(screenW * TV_SAFE_ACTION); }
public static int getTvSafeActionHeight() { return Math.round(screenH * TV_SAFE_ACTION); }
/** /**
* These languages won't distinguish regional differences (e.g. enUS and enUK, frFR and frCA) * These languages won't distinguish regional differences (e.g. enUS and enUK, frFR and frCA)
*/ */
@@ -142,9 +166,16 @@ public class AppLoader implements ApplicationListener {
private static boolean splashDisplayed = false; private static boolean splashDisplayed = false;
private static boolean postInitFired = false; private static boolean postInitFired = false;
private static boolean screenshotRequested = false; private static boolean screenshotRequested = false;
private static boolean resizeRequested = false;
private static Point2i resizeReqSize;
public static LwjglApplicationConfiguration appConfig; public static LwjglApplicationConfiguration appConfig;
public static GameFontBase fontGame; public static GameFontBase fontGame;
public static TinyAlphNum fontSmallNumbers;
/** A gamepad. Multiple gamepads may controll this single virtualised gamepad. */
public static org.lwjgl.input.Controller gamepad = null;
public static float gamepadDeadzone = 0.1f;
/** /**
* For the events depends on rendering frame (e.g. flicker on post-hit invincibility) * For the events depends on rendering frame (e.g. flicker on post-hit invincibility)
@@ -154,23 +185,52 @@ public class AppLoader implements ApplicationListener {
public static ArrayListMap debugTimers = new ArrayListMap<String, Long>(); public static ArrayListMap debugTimers = new ArrayListMap<String, Long>();
public static final int defaultW = 1110;
public static final int defaultH = 740;
public static final int minimumW = 1080;
public static final int minimumH = 720;
public static void main(String[] args) { public static void main(String[] args) {
// load configs
getDefaultDirectory();
createDirs();
readConfigJson();
try { processor = GetCpuName.getModelName(); }
catch (IOException e1) { processor = "Unknown"; }
try { processorVendor = GetCpuName.getCPUID(); }
catch (IOException e2) { processorVendor = "Unknown"; }
ShaderProgram.pedantic = false; ShaderProgram.pedantic = false;
LwjglApplicationConfiguration appConfig = new LwjglApplicationConfiguration(); LwjglApplicationConfiguration appConfig = new LwjglApplicationConfiguration();
//appConfig.useGL30 = true; // used: loads GL 3.2, unused: loads GL 4.6; what the fuck? //appConfig.useGL30 = true; // used: loads GL 3.2, unused: loads GL 4.6; what the fuck?
appConfig.vSyncEnabled = false; appConfig.vSyncEnabled = getConfigBoolean("usevsync");
appConfig.resizable = false;//true; appConfig.resizable = false;//true;
appConfig.width = 1110; // photographic ratio (1.5:1) //appConfig.width = 1110; // photographic ratio (1.5:1)
appConfig.height = 740; // photographic ratio (1.5:1) //appConfig.height = 740; // photographic ratio (1.5:1)
appConfig.backgroundFPS = 9999; appConfig.width = getConfigInt("screenwidth");
appConfig.foregroundFPS = 9999; appConfig.height = getConfigInt("screenheight");
appConfig.backgroundFPS = getConfigInt("displayfps");
appConfig.foregroundFPS = getConfigInt("displayfps");
appConfig.title = GAME_NAME; appConfig.title = GAME_NAME;
appConfig.forceExit = false; appConfig.forceExit = false;
// load app icon
int[] appIconSizes = new int[]{256,128,64,32,16};
for (int size : appIconSizes) {
String name = "assets/appicon" + size + ".png";
if (new File("./" + name).exists()) {
appConfig.addIcon(name, Files.FileType.Internal);
}
}
if (args.length == 1 && args[0].equals("isdev=true")) { if (args.length == 1 && args[0].equals("isdev=true")) {
IS_DEVELOPMENT_BUILD = true; IS_DEVELOPMENT_BUILD = true;
// safe area box
//KeyToggler.INSTANCE.forceSet(Input.Keys.F11, true);
} }
new LwjglApplication(new AppLoader(appConfig), appConfig); new LwjglApplication(new AppLoader(appConfig), appConfig);
@@ -179,6 +239,7 @@ public class AppLoader implements ApplicationListener {
private static ShaderProgram shaderBayerSkyboxFill; private static ShaderProgram shaderBayerSkyboxFill;
public static ShaderProgram shaderHicolour; public static ShaderProgram shaderHicolour;
public static ShaderProgram shaderPassthru;
public static ShaderProgram shaderColLUT; public static ShaderProgram shaderColLUT;
public static Mesh fullscreenQuad; public static Mesh fullscreenQuad;
@@ -207,23 +268,33 @@ public class AppLoader implements ApplicationListener {
Gdx.gl20.glViewport(0, 0, width, height); Gdx.gl20.glViewport(0, 0, width, height);
} }
public static final double UPDATE_RATE = 1.0 / 60.0; // TODO set it like 1/100, because apparent framerate is limited by update rate
private float loadTimer = 0f; private float loadTimer = 0f;
private final float showupTime = 100f / 1000f; private final float showupTime = 100f / 1000f;
private FrameBuffer renderFBO; private FrameBuffer renderFBO;
public static AssetManager assetManager;
@Override @Override
public void create() { public void create() {
assetManager = new AssetManager();
// set basis of draw
logoBatch = new SpriteBatch(); logoBatch = new SpriteBatch();
camera = new OrthographicCamera(((float) appConfig.width), ((float) appConfig.height)); camera = new OrthographicCamera(((float) appConfig.width), ((float) appConfig.height));
initViewPort(appConfig.width, appConfig.height); initViewPort(appConfig.width, appConfig.height);
// logo here :p
logo = new TextureRegion(new Texture(Gdx.files.internal("assets/graphics/logo_placeholder.tga"))); logo = new TextureRegion(new Texture(Gdx.files.internal("assets/graphics/logo_placeholder.tga")));
logo.flip(false, true); logo.flip(false, true);
// set GL graphics constants
shaderBayerSkyboxFill = loadShader("assets/4096.vert", "assets/4096_bayer_skyboxfill.frag"); shaderBayerSkyboxFill = loadShader("assets/4096.vert", "assets/4096_bayer_skyboxfill.frag");
shaderHicolour = loadShader("assets/4096.vert", "assets/hicolour.frag"); shaderHicolour = loadShader("assets/4096.vert", "assets/hicolour.frag");
shaderPassthru = loadShader("assets/4096.vert", "assets/passthru.frag");
shaderColLUT = loadShader("assets/4096.vert", "assets/passthru.frag"); shaderColLUT = loadShader("assets/4096.vert", "assets/passthru.frag");
fullscreenQuad = new Mesh( fullscreenQuad = new Mesh(
@@ -233,99 +304,50 @@ public class AppLoader implements ApplicationListener {
VertexAttribute.TexCoords(0) VertexAttribute.TexCoords(0)
); );
updateFullscreenQuad(appConfig.width, appConfig.height); updateFullscreenQuad(appConfig.width, appConfig.height);
// enlist suitable gamepads
try {
Controllers.create();
printdbg(this, "Available gamepads: " + Controllers.getControllerCount());
for (int x = 0; x < Controllers.getControllerCount(); x++) {
Controller gamepad = Controllers.getController(x);
printdbg(this, String.format("Gamepad #%d: %s", x + 1, gamepad.getName()));
}
}
catch (Throwable e) {
printdbg(this, "Exception occured while creating controllers -- there will be no gamepads available.");
printdbg(this, e);
} }
private static double _kalman_xhat_k = 1.0 / 60.0;
private static double _kalman_return_value = _kalman_xhat_k;
private static double _kalman_p_k = 1.0;
private static final double _kalman_R = 0.2; // 0.2: empirical value
private final double _KALMAN_UPDATE_THRE = 0.1;
/** // set up renderer info variables
* Because fuck you GDX. (No, really; take a look at LwjglGraphics.java, getDeltaTime() and rawDeltaTime() are exactly the same) renderer = Gdx.graphics.getGLVersion().getRendererString();
* @return Render delta that is smoothed out. rendererVendor = Gdx.graphics.getGLVersion().getVendorString();
*/
public static double getSmoothDelta() {
// kalman filter is calculated but not actually being used.
// below is the kalman part
return _kalman_return_value;
}
public static void resetDeltaSmoothingHistory() { // make loading list
_kalman_xhat_k = 1.0 / 60.0;
_kalman_p_k = 1.0;
} }
/** /**
* @link http://bilgin.esme.org/BitsAndBytes/KalmanFilterforDummies * @link http://bilgin.esme.org/BitsAndBytes/KalmanFilterforDummies
*/ */
private void updateKalmanRenderDelta() { private void updateKalmanRenderDelta() {
// moved to LwjglGraphics
// TODO implement nonlinear kalman filter
// kalman filter is calculated but not actually being used.
// the problem with this kalman filter is that it assumes most simplistic situation:
// 1. the actual delta (measured delta - noise) is constant
// 2. everything is linear
// we may need to implement Extended Kalman Filter but wtf is Jacobian, I suck at maths.
// Instead, the kalman filter will reset when new delta is given-value-times greater/lesser
// it's not perfect but it works.
double observation = ((double) Gdx.graphics.getRawDeltaTime());
if (getMul(observation, _kalman_return_value) >= 2.5) {
resetDeltaSmoothingHistory();
}
// measurement value
double _kalman_zed_k = observation;
if (_kalman_zed_k <= _KALMAN_UPDATE_THRE) {
// time update
double _kalman_xhatminus_k = _kalman_xhat_k;
double _kalman_pminus_k = _kalman_p_k;
// measurement update
double _kalman_gain = _kalman_pminus_k / (_kalman_pminus_k + _kalman_R);
double _kalman_xhat_kNew = _kalman_xhatminus_k + _kalman_gain * (_kalman_zed_k - _kalman_xhatminus_k);
double _kalman_p_kNew = (1.0 - _kalman_gain) * _kalman_pminus_k;
_kalman_xhat_k = _kalman_xhat_kNew;
_kalman_p_k = _kalman_p_kNew;
_kalman_return_value = _kalman_xhat_kNew;
}
}
private final double getMul_epsilon = 0.00001;
// only for a > 0 && b > 0
private double getMul(double a, double b) {
if (a < getMul_epsilon || b < getMul_epsilon) {
return a + b;
}
if (a > b) {
return a / b;
}
else {
return b / a;
}
} }
@Override @Override
public void render() { public void render() {
Gdx.gl.glDisable(GL20.GL_DITHER);
if (splashDisplayed && !postInitFired) { if (splashDisplayed && !postInitFired) {
postInitFired = true; postInitFired = true;
postInit(); postInit();
} }
// update smooth delta AFTER postInit
updateKalmanRenderDelta();
FrameBufferManager.begin(renderFBO); FrameBufferManager.begin(renderFBO);
gdxClearAndSetBlend(.094f, .094f, .094f, 0f); gdxClearAndSetBlend(.094f, .094f, .094f, 0f);
setCameraPosition(0, 0); setCameraPosition(0, 0);
@@ -365,15 +387,24 @@ public class AppLoader implements ApplicationListener {
} }
// draw the screen // draw the screen
else { else {
screen.render(((float) getSmoothDelta())); screen.render((float) UPDATE_RATE);
} }
KeyToggler.INSTANCE.update(screen instanceof Ingame);
// nested FBOs are just not a thing in GL! // nested FBOs are just not a thing in GL!
net.torvald.terrarum.FrameBufferManager.end(); net.torvald.terrarum.FrameBufferManager.end();
PostProcessor.INSTANCE.draw(camera.combined, renderFBO); PostProcessor.INSTANCE.draw(camera.combined, renderFBO);
// process resize request
if (resizeRequested) {
resizeRequested = false;
resize(resizeReqSize.getX(), resizeReqSize.getY());
}
// process screenshot request // process screenshot request
if (screenshotRequested) { if (screenshotRequested) {
screenshotRequested = false; screenshotRequested = false;
@@ -394,6 +425,11 @@ public class AppLoader implements ApplicationListener {
@Override @Override
public void resize(int width, int height) { public void resize(int width, int height) {
printdbg(this, "Resize called");
for (StackTraceElement stackTraceElement : Thread.currentThread().getStackTrace()) {
printdbg(this, stackTraceElement);
}
//initViewPort(width, height); //initViewPort(width, height);
screenW = width; screenW = width;
@@ -422,9 +458,12 @@ public class AppLoader implements ApplicationListener {
updateFullscreenQuad(screenW, screenH); updateFullscreenQuad(screenW, screenH);
printdbg(this, "Resize event"); printdbg(this, "Resize end");
}
resetDeltaSmoothingHistory(); public static void resizeScreen(int width, int height) {
resizeRequested = true;
resizeReqSize = new Point2i(Math.max(width, minimumW), Math.max(height, minimumH));
} }
@Override @Override
@@ -438,7 +477,19 @@ public class AppLoader implements ApplicationListener {
} }
IngameRenderer.INSTANCE.dispose(); IngameRenderer.INSTANCE.dispose();
if (Controllers.isCreated()) Controllers.destroy();
Terrarum.INSTANCE.dispose();
shaderBayerSkyboxFill.dispose();
shaderHicolour.dispose();
shaderColLUT.dispose();
assetManager.dispose();
fullscreenQuad.dispose();
fontGame.dispose();
fontSmallNumbers.dispose();
// delete temp files // delete temp files
new File("./tmp_wenquanyi.tga").delete(); // FIXME this is pretty much ad-hoc new File("./tmp_wenquanyi.tga").delete(); // FIXME this is pretty much ad-hoc
@@ -461,6 +512,7 @@ public class AppLoader implements ApplicationListener {
if (this.screen != null) { if (this.screen != null) {
this.screen.hide(); this.screen.hide();
this.screen.dispose();
} }
this.screen = screen; this.screen = screen;
if (this.screen != null) { if (this.screen != null) {
@@ -468,17 +520,15 @@ public class AppLoader implements ApplicationListener {
this.screen.resize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); this.screen.resize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
} }
printdbg(this, "Screen transisiton complete: " + this.screen.getClass().getCanonicalName()); System.gc();
resetDeltaSmoothingHistory(); printdbg(this, "Screen transisiton complete: " + this.screen.getClass().getCanonicalName());
} }
/**
* Init stuffs which needs GL context
*/
private void postInit() { private void postInit() {
// load configs
getDefaultDirectory();
createDirs();
readConfigJson();
textureWhiteSquare = new Texture(Gdx.files.internal("assets/graphics/ortho_line_tex_2px.tga")); textureWhiteSquare = new Texture(Gdx.files.internal("assets/graphics/ortho_line_tex_2px.tga"));
textureWhiteSquare.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest); textureWhiteSquare.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest);
@@ -486,6 +536,7 @@ public class AppLoader implements ApplicationListener {
fontGame = new GameFontBase("assets/graphics/fonts/terrarum-sans-bitmap", false, true, fontGame = new GameFontBase("assets/graphics/fonts/terrarum-sans-bitmap", false, true,
Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest, false, 256, false Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest, false, 256, false
); );
fontSmallNumbers = TinyAlphNum.INSTANCE;
audioDevice = Gdx.audio.newAudioDevice(48000, false); audioDevice = Gdx.audio.newAudioDevice(48000, false);
@@ -495,6 +546,10 @@ public class AppLoader implements ApplicationListener {
} }
BlocksDrawer.INSTANCE.getWorld(); // will initialize the BlocksDrawer by calling dummy method
LightmapRenderer.INSTANCE.hdr(0f);
printdbg(this, "PostInit done"); printdbg(this, "PostInit done");
} }
@@ -505,7 +560,7 @@ public class AppLoader implements ApplicationListener {
logoBatch.setProjectionMatrix(camera.combined); logoBatch.setProjectionMatrix(camera.combined);
} }
private void updateFullscreenQuad(int WIDTH, int HEIGHT) { private void updateFullscreenQuad(int WIDTH, int HEIGHT) { // NOT y-flipped quads!
fullscreenQuad.setVertices(new float[]{ fullscreenQuad.setVertices(new float[]{
0f, 0f, 0f, 1f, 1f, 1f, 1f, 0f, 1f, 0f, 0f, 0f, 1f, 1f, 1f, 1f, 0f, 1f,
WIDTH, 0f, 0f, 1f, 1f, 1f, 1f, 1f, 1f, WIDTH, 0f, 0f, 1f, 1f, 1f, 1f, 1f, 1f,
@@ -532,7 +587,7 @@ public class AppLoader implements ApplicationListener {
public static String configDir; public static String configDir;
public static RunningEnvironment environment; public static RunningEnvironment environment;
private void getDefaultDirectory() { private static void getDefaultDirectory() {
String OS = OSName.toUpperCase(); String OS = OSName.toUpperCase();
if (OS.contains("WIN")) { if (OS.contains("WIN")) {
operationSystem = "WINDOWS"; operationSystem = "WINDOWS";
@@ -550,11 +605,11 @@ public class AppLoader implements ApplicationListener {
operationSystem = "SOLARIS"; operationSystem = "SOLARIS";
defaultDir = System.getProperty("user.home") + "/.Terrarum"; defaultDir = System.getProperty("user.home") + "/.Terrarum";
} }
else if (System.getProperty("java.runtime.name").toUpperCase().contains("ANDROID")) { /*else if (System.getProperty("java.runtime.name").toUpperCase().contains("ANDROID")) {
operationSystem = "ANDROID"; operationSystem = "ANDROID";
defaultDir = System.getProperty("user.home") + "/.Terrarum"; defaultDir = System.getProperty("user.home") + "/.Terrarum";
environment = RunningEnvironment.MOBILE; environment = RunningEnvironment.MOBILE;
} }*/
else { else {
operationSystem = "UNKNOWN"; operationSystem = "UNKNOWN";
defaultDir = System.getProperty("user.home") + "/.Terrarum"; defaultDir = System.getProperty("user.home") + "/.Terrarum";
@@ -568,7 +623,7 @@ public class AppLoader implements ApplicationListener {
System.out.println(String.format("default directory: %s", defaultDir)); System.out.println(String.format("default directory: %s", defaultDir));
} }
private void createDirs() { private static void createDirs() {
File[] dirs = {new File(defaultSaveDir)}; File[] dirs = {new File(defaultSaveDir)};
for (File it : dirs) { for (File it : dirs) {
@@ -659,17 +714,20 @@ public class AppLoader implements ApplicationListener {
* Return config from config set. If the config does not exist, default value will be returned. * Return config from config set. If the config does not exist, default value will be returned.
* @param key * @param key
* * * *
* @return Config from config set or default config if it does not exist. * @return Config from config set or default config if it does not exist. If the default value is undefined, will return false.
* *
* @throws NullPointerException if the specified config simply does not exist.
*/ */
public static boolean getConfigBoolean(String key) { public static boolean getConfigBoolean(String key) {
try {
Object cfg = getConfigMaster(key); Object cfg = getConfigMaster(key);
if (cfg instanceof JsonPrimitive) if (cfg instanceof JsonPrimitive)
return ((JsonPrimitive) cfg).getAsBoolean(); return ((JsonPrimitive) cfg).getAsBoolean();
else else
return ((boolean) cfg); return ((boolean) cfg);
} }
catch (NullPointerException keyNotFound) {
return false;
}
}
public static int[] getConfigIntArray(String key) { public static int[] getConfigIntArray(String key) {
Object cfg = getConfigMaster(key); Object cfg = getConfigMaster(key);
@@ -714,7 +772,7 @@ public class AppLoader implements ApplicationListener {
if (config == null) { if (config == null) {
if (defaults == null) { if (defaults == null) {
throw new NullPointerException("key not found: '$key'"); throw new NullPointerException("key not found: '" + key + "'");
} }
else { else {
return defaults; return defaults;
@@ -734,13 +792,13 @@ public class AppLoader implements ApplicationListener {
// // // //
public static void printdbg(Object obj, Object message) { public static void printdbg(Object obj, Object message) {
if (IS_DEVELOPMENT_BUILD || getConfigBoolean("forcedevbuild")) { if (IS_DEVELOPMENT_BUILD) {
System.out.println("[" + obj.getClass().getSimpleName() + "] " + message.toString()); System.out.println("[" + obj.getClass().getSimpleName() + "] " + message.toString());
} }
} }
public static void printdbgerr(Object obj, Object message) { public static void printdbgerr(Object obj, Object message) {
if (IS_DEVELOPMENT_BUILD || getConfigBoolean("forcedevbuild")) { if (IS_DEVELOPMENT_BUILD) {
System.err.println("[" + obj.getClass().getSimpleName() + "] " + message.toString()); System.err.println("[" + obj.getClass().getSimpleName() + "] " + message.toString());
} }
} }
@@ -748,10 +806,36 @@ public class AppLoader implements ApplicationListener {
public static ShaderProgram loadShader(String vert, String frag) { public static ShaderProgram loadShader(String vert, String frag) {
ShaderProgram s = new ShaderProgram(Gdx.files.internal(vert), Gdx.files.internal(frag)); ShaderProgram s = new ShaderProgram(Gdx.files.internal(vert), Gdx.files.internal(frag));
if (s.getLog().contains("error C")) { if (s.getLog().toLowerCase().contains("error")) {
throw new Error(String.format("Shader program loaded with %s, %s failed:\n%s", vert, frag, s.getLog())); throw new Error(String.format("Shader program loaded with %s, %s failed:\n%s", vert, frag, s.getLog()));
} }
return s; return s;
} }
public static void measureDebugTime(String name, kotlin.jvm.functions.Function0<kotlin.Unit> block) {
if (IS_DEVELOPMENT_BUILD) {
//debugTimers.put(name, kotlin.system.TimingKt.measureNanoTime(block));
long start = System.nanoTime();
block.invoke();
debugTimers.put(name, System.nanoTime() - start);
}
}
public static void setDebugTime(String name, long value) {
if (IS_DEVELOPMENT_BUILD) {
debugTimers.put(name, value);
}
}
public static void addDebugTime(String target, String... targets) {
if (IS_DEVELOPMENT_BUILD) {
long l = 0L;
for (String s : targets) {
l += ((long) debugTimers.get(s));
}
debugTimers.put(target, l);
}
}
} }

View File

@@ -14,35 +14,36 @@ object DefaultConfig {
val jsonObject = JsonObject() val jsonObject = JsonObject()
jsonObject.addProperty("displayfps", 0) // 0: no limit, non-zero: limit jsonObject.addProperty("displayfps", 0) // 0: no limit, non-zero: limit
jsonObject.addProperty("usevsync", true) jsonObject.addProperty("usevsync", false)
jsonObject.addProperty("forcedevbuild", false) jsonObject.addProperty("screenwidth", AppLoader.defaultW)
jsonObject.addProperty("screenheight", AppLoader.defaultH)
jsonObject.addProperty("imtooyoungtodie", false) // no perma-death jsonObject.addProperty("imtooyoungtodie", false) // no perma-death
jsonObject.addProperty("language", AppLoader.getSysLang()) jsonObject.addProperty("language", AppLoader.getSysLang())
jsonObject.addProperty("notificationshowuptime", 6500) jsonObject.addProperty("notificationshowuptime", 4000)
jsonObject.addProperty("multithread", true) // experimental! jsonObject.addProperty("multithread", true) // experimental!
jsonObject.addProperty("multithreadedlight", false) // experimental! jsonObject.addProperty("multithreadedlight", false) // experimental!
// control-gamepad // control-gamepad
jsonObject.addProperty("joypadkeyn", 4) jsonObject.addProperty("gamepadkeyn", 4)
jsonObject.addProperty("joypadkeyw", 1) jsonObject.addProperty("gamepadkeyw", 1)
jsonObject.addProperty("joypadkeys", 2) jsonObject.addProperty("gamepadkeys", 2)
jsonObject.addProperty("joypadkeye", 3) // logitech indices jsonObject.addProperty("gamepadkeye", 3) // logitech indices
jsonObject.addProperty("joypadlup", 4) jsonObject.addProperty("gamepadlup", 4)
jsonObject.addProperty("joypadrup", 5) jsonObject.addProperty("gamepadrup", 5)
jsonObject.addProperty("joypadldown", 6) jsonObject.addProperty("gamepadldown", 6)
jsonObject.addProperty("joypadrdown", 7) // logitech indices jsonObject.addProperty("gamepadrdown", 7) // logitech indices
jsonObject.addProperty("joypadlstickx", 0) jsonObject.addProperty("gamepadlstickx", 0)
jsonObject.addProperty("joypadlsticky", 1) jsonObject.addProperty("gamepadlsticky", 1)
jsonObject.addProperty("joypadrstickx", 2) jsonObject.addProperty("gamepadrstickx", 2)
jsonObject.addProperty("joypadrsticky", 3) // 0-1-2-3 but sometimes 3-2-1-0 ?! what the actual fuck? jsonObject.addProperty("gamepadrsticky", 3) // 0-1-2-3 but sometimes 3-2-1-0 ?! what the actual fuck?
jsonObject.addProperty("joypadlabelstyle", "msxb360") // "nwii", "logitech", "sonyps", "msxb360", "generic" jsonObject.addProperty("gamepadlabelstyle", "msxb360") // "nwii", "logitech", "sonyps", "msxb360", "generic"

View File

@@ -464,7 +464,7 @@ class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
override fun run() { override fun run() {
var updateTries = 0 var updateTries = 0
while (ingame.updateDeltaCounter >= ingame.updateRate) { while (ingame.updateDeltaCounter >= ingame.updateRate) {
ingame.updateGame(AppLoader.getSmoothDelta().toFloat()) ingame.updateGame(AppLoader.UPDATE_RATE.toFloat())
ingame.updateDeltaCounter -= ingame.updateRate ingame.updateDeltaCounter -= ingame.updateRate
updateTries++ updateTries++
@@ -529,7 +529,7 @@ class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
while (updateDeltaCounter >= updateRate) { while (updateDeltaCounter >= updateRate) {
//updateGame(delta) //updateGame(delta)
AppLoader.debugTimers["Ingame.update"] = measureNanoTime { updateGame(delta) } AppLoader.measureDebugTime("Ingame.update") { updateGame(delta) }
updateDeltaCounter -= updateRate updateDeltaCounter -= updateRate
updateTries++ updateTries++
@@ -544,7 +544,7 @@ class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
/** RENDER CODE GOES HERE */ /** RENDER CODE GOES HERE */
//renderGame(batch) //renderGame(batch)
AppLoader.debugTimers["Ingame.render"] = measureNanoTime { renderGame(batch) } AppLoader.measureDebugTime("Ingame.render") { renderGame(batch) }
} }
protected fun updateGame(delta: Float) { protected fun updateGame(delta: Float) {
@@ -1090,7 +1090,7 @@ class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
} }
playableActorDelegate = newActor playableActorDelegate = newActor
WorldSimulator(player, AppLoader.getSmoothDelta().toFloat()) WorldSimulator(player, AppLoader.UPDATE_RATE.toFloat())
} }
private fun changePossession(refid: Int) { private fun changePossession(refid: Int) {
@@ -1107,7 +1107,7 @@ class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
// accept new delegate // accept new delegate
playableActorDelegate = PlayableActorDelegate(getActorByID(refid) as ActorHumanoid) playableActorDelegate = PlayableActorDelegate(getActorByID(refid) as ActorHumanoid)
playableActorDelegate!!.actor.collisionType = ActorWithPhysics.COLLISION_KINEMATIC playableActorDelegate!!.actor.collisionType = ActorWithPhysics.COLLISION_KINEMATIC
WorldSimulator(player, AppLoader.getSmoothDelta().toFloat()) WorldSimulator(player, AppLoader.UPDATE_RATE.toFloat())
} }
/** Send message to notifier UI and toggle the UI as opened. */ /** Send message to notifier UI and toggle the UI as opened. */

View File

@@ -17,9 +17,9 @@ class GdxColorMap {
height = pixmap.height height = pixmap.height
is2D = pixmap.height > 1 is2D = pixmap.height > 1
data = kotlin.IntArray(pixmap.width * pixmap.height, { data = kotlin.IntArray(pixmap.width * pixmap.height) {
pixmap.getPixel(it % pixmap.width, it / pixmap.width) pixmap.getPixel(it % pixmap.width, it / pixmap.width)
}) }
AppLoader.printdbg(this, "Loading colormap from ${imageFile.name()}; PixmapFormat: ${pixmap.format}; Dimension: $width x $height") AppLoader.printdbg(this, "Loading colormap from ${imageFile.name()}; PixmapFormat: ${pixmap.format}; Dimension: $width x $height")

View File

@@ -2,9 +2,11 @@ package net.torvald.terrarum
import com.badlogic.gdx.Screen import com.badlogic.gdx.Screen
import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.badlogic.gdx.graphics.g2d.SpriteBatch
import com.badlogic.gdx.utils.Queue
import net.torvald.terrarum.gameactors.Actor import net.torvald.terrarum.gameactors.Actor
import net.torvald.terrarum.gameworld.GameWorld import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
import net.torvald.terrarum.realestate.LandUtil
import net.torvald.terrarum.ui.ConsoleWindow import net.torvald.terrarum.ui.ConsoleWindow
import java.util.* import java.util.*
import java.util.concurrent.locks.Lock import java.util.concurrent.locks.Lock
@@ -45,6 +47,10 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
val actorContainer = ArrayList<Actor>(ACTORCONTAINER_INITIAL_SIZE) val actorContainer = ArrayList<Actor>(ACTORCONTAINER_INITIAL_SIZE)
val actorContainerInactive = ArrayList<Actor>(ACTORCONTAINER_INITIAL_SIZE) val actorContainerInactive = ArrayList<Actor>(ACTORCONTAINER_INITIAL_SIZE)
protected val terrainChangeQueue = Queue<BlockChangeQueueItem>()
protected val wallChangeQueue = Queue<BlockChangeQueueItem>()
protected val wireChangeQueue = Queue<BlockChangeQueueItem>()
override fun hide() { override fun hide() {
} }
@@ -96,6 +102,33 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
open fun worldSecondaryClickEnd(delta: Float) { open fun worldSecondaryClickEnd(delta: Float) {
} }
/**
* Event for triggering fixture update when something is placed/removed on the world.
* Normally only called by GameWorld.setTileTerrain
*
* Queueing schema is used to make sure things are synchronised.
*/
open fun queueTerrainChangedEvent(old: Int, new: Int, position: Long) {
val (x, y) = LandUtil.resolveBlockAddr(world, position)
terrainChangeQueue.addFirst(BlockChangeQueueItem(old, new, x, y))
}
/**
* Wall version of terrainChanged() event
*/
open fun queueWallChangedEvent(old: Int, new: Int, position: Long) {
val (x, y) = LandUtil.resolveBlockAddr(world, position)
wallChangeQueue.addFirst(BlockChangeQueueItem(old, new, x, y))
}
/**
* Wire version of terrainChanged() event
*/
open fun queueWireChangedEvent(old: Int, new: Int, position: Long) {
val (x, y) = LandUtil.resolveBlockAddr(world, position)
wireChangeQueue.addFirst(BlockChangeQueueItem(old, new, x, y))
}
/////////////////////// ///////////////////////
@@ -215,6 +248,8 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
} }
} }
data class BlockChangeQueueItem(val old: Int, val new: Int, val posX: Int, val posY: Int)
} }
inline fun Lock.lock(body: () -> Unit) { inline fun Lock.lock(body: () -> Unit) {

View File

@@ -239,7 +239,7 @@ object LoadScreen : ScreenAdapter() {
for (i in 0 until messages.elemCount) { for (i in 0 until messages.elemCount) {
Terrarum.fontGame.draw(it, Terrarum.fontGame.draw(it,
messages[i] ?: "", messages[i] ?: "",
40f, AppLoader.getTvSafeGraphicsWidth() + 16f,
80f + (messages.size - i - 1) * Terrarum.fontGame.lineHeight 80f + (messages.size - i - 1) * Terrarum.fontGame.lineHeight
) )
} }
@@ -264,7 +264,7 @@ object LoadScreen : ScreenAdapter() {
for (i in 0 until messages.elemCount) { for (i in 0 until messages.elemCount) {
Terrarum.fontGame.draw(it, Terrarum.fontGame.draw(it,
messages[i] ?: "", messages[i] ?: "",
40f, AppLoader.getTvSafeGraphicsWidth() + 16f,
80f + (messages.size - i - 1) * Terrarum.fontGame.lineHeight 80f + (messages.size - i - 1) * Terrarum.fontGame.lineHeight
) )
} }
@@ -313,7 +313,6 @@ object LoadScreen : ScreenAdapter() {
} }
override fun hide() { override fun hide() {
dispose()
} }
override fun resize(width: Int, height: Int) { override fun resize(width: Int, height: Int) {

View File

@@ -1,14 +1,18 @@
package net.torvald.terrarum package net.torvald.terrarum
import com.badlogic.gdx.Gdx import com.badlogic.gdx.Gdx
import com.badlogic.gdx.Input
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.GL20 import com.badlogic.gdx.graphics.GL20
import com.badlogic.gdx.graphics.OrthographicCamera
import com.badlogic.gdx.graphics.Texture import com.badlogic.gdx.graphics.Texture
import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.badlogic.gdx.graphics.g2d.SpriteBatch
import com.badlogic.gdx.graphics.g2d.TextureRegion
import com.badlogic.gdx.graphics.glutils.FrameBuffer import com.badlogic.gdx.graphics.glutils.FrameBuffer
import com.badlogic.gdx.graphics.glutils.ShaderProgram import com.badlogic.gdx.graphics.glutils.ShaderProgram
import com.badlogic.gdx.graphics.glutils.ShapeRenderer
import com.badlogic.gdx.math.Matrix4 import com.badlogic.gdx.math.Matrix4
import kotlin.system.measureNanoTime import net.torvald.terrarum.gamecontroller.KeyToggler
import net.torvald.terrarum.ui.BasicDebugInfoWindow
/** /**
* Must be called by the App Loader * Must be called by the App Loader
@@ -16,36 +20,71 @@ import kotlin.system.measureNanoTime
object PostProcessor { object PostProcessor {
private lateinit var batch: SpriteBatch // not nulling to save some lines of code private lateinit var batch: SpriteBatch // not nulling to save some lines of code
//private lateinit var camera: OrthographicCamera private lateinit var shapeRenderer: ShapeRenderer
private var textureRegion: TextureRegion? = null private lateinit var camera: OrthographicCamera
private lateinit var lutTex: Texture private lateinit var lutTex: Texture
private var init = false
fun reloadLUT(filename: String) { fun reloadLUT(filename: String) {
lutTex = Texture(Gdx.files.internal("assets/clut/$filename")) lutTex = Texture(Gdx.files.internal("assets/clut/$filename"))
} }
private val defaultResCol = Color(0x66ffff66)
private val safeAreaCol = Color(0xffffff66.toInt())
private val safeAreaCol2 = Color(0xffffff44.toInt())
private val debugUI = BasicDebugInfoWindow()
fun draw(projMat: Matrix4, fbo: FrameBuffer) { fun draw(projMat: Matrix4, fbo: FrameBuffer) {
if (textureRegion == null) { // init
textureRegion = TextureRegion(fbo.colorBufferTexture) if (!init) {
init = true
debugUI.setPosition(0, 0)
batch = SpriteBatch() batch = SpriteBatch()
camera = OrthographicCamera(AppLoader.screenW.toFloat(), AppLoader.screenH.toFloat())
camera.setToOrtho(true)
batch.projectionMatrix = camera.combined
shapeRenderer = ShapeRenderer()
Gdx.gl20.glViewport(0, 0, AppLoader.appConfig.width, AppLoader.appConfig.height) Gdx.gl20.glViewport(0, 0, AppLoader.appConfig.width, AppLoader.appConfig.height)
} }
debugUI.update(Gdx.graphics.deltaTime)
AppLoader.debugTimers["Renderer.PostProcessor"] = measureNanoTime { AppLoader.measureDebugTime("Renderer.PostProcessor") {
gdxClearAndSetBlend(.094f, .094f, .094f, 0f) gdxClearAndSetBlend(.094f, .094f, .094f, 0f)
postShader(projMat, fbo)
if (AppLoader.IS_DEVELOPMENT_BUILD && KeyToggler.isOn(Input.Keys.F11)) {
drawSafeArea()
}
if (KeyToggler.isOn(Input.Keys.F3)) {
if (!debugUI.isOpened && !debugUI.isOpening) debugUI.setAsOpen()
batch.inUse { debugUI.renderUI(batch, camera) }
}
else {
if (!debugUI.isClosed && !debugUI.isClosing) debugUI.setAsClose()
}
}
}
private fun postShader(projMat: Matrix4, fbo: FrameBuffer) {
val shader: ShaderProgram? = val shader: ShaderProgram? =
if (AppLoader.getConfigBoolean("fxdither")) if (AppLoader.getConfigBoolean("fxdither"))
AppLoader.shaderHicolour AppLoader.shaderHicolour
else else
null AppLoader.shaderPassthru
fbo.colorBufferTexture.bind(0) fbo.colorBufferTexture.bind(0)
@@ -58,9 +97,61 @@ object PostProcessor {
Gdx.gl.glActiveTexture(GL20.GL_TEXTURE0) // so that batch that comes next will bind any tex to it Gdx.gl.glActiveTexture(GL20.GL_TEXTURE0) // so that batch that comes next will bind any tex to it
}
private fun drawSafeArea() {
val tvSafeAreaW = AppLoader.getTvSafeGraphicsWidth().toFloat()
val tvSafeAreaH = AppLoader.getTvSafeGraphicsHeight().toFloat()
val tvSafeArea2W = AppLoader.getTvSafeActionWidth().toFloat()
val tvSafeArea2H = AppLoader.getTvSafeActionHeight().toFloat()
shapeRenderer.inUse(ShapeRenderer.ShapeType.Line) {
shapeRenderer.color = safeAreaCol2
shapeRenderer.rect(
tvSafeArea2W, tvSafeArea2H, AppLoader.screenW - 2 * tvSafeArea2W, AppLoader.screenH - 2 * tvSafeArea2H
)
shapeRenderer.color = safeAreaCol
shapeRenderer.rect(
tvSafeAreaW, tvSafeAreaH, AppLoader.screenW - 2 * tvSafeAreaW, AppLoader.screenH - 2 * tvSafeAreaH
)
shapeRenderer.color = defaultResCol
shapeRenderer.rect(
(AppLoader.screenW - AppLoader.minimumW).div(2).toFloat(),
(AppLoader.screenH - AppLoader.minimumH).div(2).toFloat(),
AppLoader.minimumW.toFloat(),
AppLoader.minimumH.toFloat()
)
}
try {
batch.inUse {
batch.color = safeAreaCol
AppLoader.fontSmallNumbers.draw(
batch, safeAreaStr,
tvSafeAreaW, tvSafeAreaH - 10
)
batch.color = defaultResCol
AppLoader.fontSmallNumbers.draw(
batch, defaultResStr,
(AppLoader.screenW - AppLoader.minimumW).div(2).toFloat(),
(AppLoader.screenH - AppLoader.minimumH).div(2).minus(10).toFloat()
)
} }
} }
catch (doNothing: NullPointerException) { }
finally {
// one-time call, caused by catching NPE before batch ends
if (batch.isDrawing) {
batch.end()
}
}
}
private val defaultResStr = "${AppLoader.minimumW}x${AppLoader.minimumH}"
private val safeAreaStr = "TV Safe Area"
/** /**
* Camera will be moved so that (newX, newY) would be sit on the top-left edge. * Camera will be moved so that (newX, newY) would be sit on the top-left edge.

View File

@@ -14,7 +14,6 @@ import com.badlogic.gdx.graphics.glutils.ShapeRenderer
import com.badlogic.gdx.utils.GdxRuntimeException import com.badlogic.gdx.utils.GdxRuntimeException
import com.jme3.math.FastMath import com.jme3.math.FastMath
import net.torvald.dataclass.CircularArray import net.torvald.dataclass.CircularArray
import net.torvald.getcpuname.GetCpuName
import net.torvald.random.HQRNG import net.torvald.random.HQRNG
import net.torvald.terrarum.AppLoader.* import net.torvald.terrarum.AppLoader.*
import net.torvald.terrarum.gameactors.Actor import net.torvald.terrarum.gameactors.Actor
@@ -74,22 +73,12 @@ object Terrarum : Screen {
get() = HEIGHT.ushr(1) get() = HEIGHT.ushr(1)
/** /**
* To be used with physics simulator * To be used with physics simulator. This is a magic number.
*/ */
val PHYS_TIME_FRAME: Double = 26.0 + (2.0 / 3.0) val PHYS_TIME_FRAME: Double = 26.0 + (2.0 / 3.0)
val PHYS_CONST_MULT: Double = 60.0 / (26.0 + (2.0 / 3.0))
val PHYS_REF_FPS: Double = 60.0
// 26.0 + (2.0 / 3.0) // lower value == faster gravity response (IT WON'T HOTSWAP!!) // 26.0 + (2.0 / 3.0) // lower value == faster gravity response (IT WON'T HOTSWAP!!)
// protip: using METER, game unit and SI unit will have same number // protip: using METER, game unit and SI unit will have same number
/**
* To be used with render, to achieve smooth frame drawing
* TARGET_INTERNAL_FPS > PHYS_TIME_FRAME for smooth frame drawing
*/
val TARGET_INTERNAL_FPS: Double = 60.0
var previousScreen: Screen? = null // to be used with temporary states like StateMonitorCheck var previousScreen: Screen? = null // to be used with temporary states like StateMonitorCheck
@@ -132,22 +121,22 @@ object Terrarum : Screen {
val fontGame: GameFontBase = AppLoader.fontGame val fontGame: GameFontBase = AppLoader.fontGame
lateinit var fontSmallNumbers: TinyAlphNum val fontSmallNumbers: TinyAlphNum = AppLoader.fontSmallNumbers
var joypadLabelStart: Char = 0xE000.toChar() // lateinit var gamepadLabelStart: Char = 0xE000.toChar() // lateinit
var joypadLableSelect: Char = 0xE000.toChar() // lateinit var gamepadLableSelect: Char = 0xE000.toChar() // lateinit
var joypadLabelNinA: Char = 0xE000.toChar() // lateinit TODO var gamepadLabelNinA: Char = 0xE000.toChar() // lateinit TODO
var joypadLabelNinB: Char = 0xE000.toChar() // lateinit TODO var gamepadLabelNinB: Char = 0xE000.toChar() // lateinit TODO
var joypadLabelNinX: Char = 0xE000.toChar() // lateinit TODO var gamepadLabelNinX: Char = 0xE000.toChar() // lateinit TODO
var joypadLabelNinY: Char = 0xE000.toChar() // lateinit TODO var gamepadLabelNinY: Char = 0xE000.toChar() // lateinit TODO
var joypadLabelNinL: Char = 0xE000.toChar() // lateinit TODO var gamepadLabelNinL: Char = 0xE000.toChar() // lateinit TODO
var joypadLabelNinR: Char = 0xE000.toChar() // lateinit TODO var gamepadLabelNinR: Char = 0xE000.toChar() // lateinit TODO
var joypadLabelNinZL: Char = 0xE000.toChar() // lateinit TODO var gamepadLabelNinZL: Char = 0xE000.toChar() // lateinit TODO
var joypadLabelNinZR: Char = 0xE000.toChar() // lateinit TODO var gamepadLabelNinZR: Char = 0xE000.toChar() // lateinit TODO
val joypadLabelLEFT = 0xE068.toChar() val gamepadLabelLEFT = 0xE068.toChar()
val joypadLabelDOWN = 0xE069.toChar() val gamepadLabelDOWN = 0xE069.toChar()
val joypadLabelUP = 0xE06A.toChar() val gamepadLabelUP = 0xE06A.toChar()
val joypadLabelRIGHT = 0xE06B.toChar() val gamepadLabelRIGHT = 0xE06B.toChar()
// 0x0 - 0xF: Game-related // 0x0 - 0xF: Game-related
// 0x10 - 0x1F: Config // 0x10 - 0x1F: Config
@@ -170,10 +159,6 @@ object Terrarum : Screen {
val STATE_ID_TOOL_NOISEGEN = 0x200 val STATE_ID_TOOL_NOISEGEN = 0x200
val STATE_ID_TOOL_RUMBLE_DIAGNOSIS = 0x201 val STATE_ID_TOOL_RUMBLE_DIAGNOSIS = 0x201
var controller: org.lwjgl.input.Controller? = null
private set
val CONTROLLER_DEADZONE = 0.1f
/** Available CPU threads */ /** Available CPU threads */
val THREADS = Runtime.getRuntime().availableProcessors() + 1 val THREADS = Runtime.getRuntime().availableProcessors() + 1
@@ -189,15 +174,6 @@ object Terrarum : Screen {
const val NAME = AppLoader.GAME_NAME const val NAME = AppLoader.GAME_NAME
val systemArch = System.getProperty("os.arch")
val processor = GetCpuName.getModelName()
val processorVendor = GetCpuName.getCPUID()
lateinit var renderer: String
lateinit var rendererVendor: String
val is32BitJVM = !System.getProperty("sun.arch.data.model").contains("64")
lateinit var shaderBlur: ShaderProgram lateinit var shaderBlur: ShaderProgram
lateinit var shaderBayer: ShaderProgram lateinit var shaderBayer: ShaderProgram
lateinit var shaderSkyboxFill: ShaderProgram lateinit var shaderSkyboxFill: ShaderProgram
@@ -233,12 +209,12 @@ object Terrarum : Screen {
println("vendor = $processorVendor") println("vendor = $processorVendor")
joypadLabelStart = when (getConfigString("joypadlabelstyle")) { gamepadLabelStart = when (getConfigString("gamepadlabelstyle")) {
"nwii" -> 0xE04B.toChar() // + mark "nwii" -> 0xE04B.toChar() // + mark
"logitech" -> 0xE05A.toChar() // number 10 "logitech" -> 0xE05A.toChar() // number 10
else -> 0xE042.toChar() // |> mark (sonyps, msxb360, generic) else -> 0xE042.toChar() // |> mark (sonyps, msxb360, generic)
} }
joypadLableSelect = when (getConfigString("joypadlabelstyle")) { gamepadLableSelect = when (getConfigString("gamepadlabelstyle")) {
"nwii" -> 0xE04D.toChar() // - mark "nwii" -> 0xE04D.toChar() // - mark
"logitech" -> 0xE059.toChar() // number 9 "logitech" -> 0xE059.toChar() // number 9
"sonyps" -> 0xE043.toChar() // solid rectangle "sonyps" -> 0xE043.toChar() // solid rectangle
@@ -248,7 +224,7 @@ object Terrarum : Screen {
// setting environment as MOBILE precedes this code // setting environment as MOBILE precedes this code
if (environment != RunningEnvironment.MOBILE) { //if (environment != RunningEnvironment.MOBILE) {
environment = try { environment = try {
Controllers.getController(0) // test if controller exists Controllers.getController(0) // test if controller exists
if (getConfigString("pcgamepadenv") == "console") if (getConfigString("pcgamepadenv") == "console")
@@ -259,7 +235,8 @@ object Terrarum : Screen {
catch (e: IndexOutOfBoundsException) { catch (e: IndexOutOfBoundsException) {
RunningEnvironment.PC RunningEnvironment.PC
} }
} //}
} }
@@ -284,11 +261,6 @@ object Terrarum : Screen {
val MINIMAL_GL_MAX_TEXTURE_SIZE = 4096 val MINIMAL_GL_MAX_TEXTURE_SIZE = 4096
override fun show() { override fun show() {
if (environment != RunningEnvironment.MOBILE) {
Gdx.gl.glDisable(GL20.GL_DITHER)
}
assetManager = AssetManager() assetManager = AssetManager()
@@ -301,10 +273,6 @@ object Terrarum : Screen {
println("GL_MAX_TEXTURE_SIZE = $GL_MAX_TEXTURE_SIZE") println("GL_MAX_TEXTURE_SIZE = $GL_MAX_TEXTURE_SIZE")
println("GL info:\n$glInfo") // debug info println("GL info:\n$glInfo") // debug info
// set up renderer info variables
renderer = Gdx.graphics.glVersion.rendererString
rendererVendor = Gdx.graphics.glVersion.vendorString
if (GL_VERSION < MINIMAL_GL_VERSION || GL_MAX_TEXTURE_SIZE < MINIMAL_GL_MAX_TEXTURE_SIZE) { if (GL_VERSION < MINIMAL_GL_VERSION || GL_MAX_TEXTURE_SIZE < MINIMAL_GL_MAX_TEXTURE_SIZE) {
// TODO notify properly // TODO notify properly
@@ -321,10 +289,7 @@ object Terrarum : Screen {
shapeRender = ShapeRenderer() shapeRender = ShapeRenderer()
fontSmallNumbers = TinyAlphNum
ShaderProgram.pedantic = false
shaderBlur = AppLoader.loadShader("assets/blur.vert", "assets/blur.frag") shaderBlur = AppLoader.loadShader("assets/blur.vert", "assets/blur.frag")
@@ -409,8 +374,8 @@ object Terrarum : Screen {
} }
override fun render(delta: Float) { override fun render(delta: Float) {
AppLoader.debugTimers["GDX.rawDelta"] = Gdx.graphics.rawDeltaTime.times(1000_000_000f).toLong() AppLoader.setDebugTime("GDX.rawDelta", Gdx.graphics.rawDeltaTime.times(1000_000_000f).toLong())
AppLoader.debugTimers["GDX.smtDelta"] = AppLoader.getSmoothDelta().times(1000_000_000f).toLong() AppLoader.setDebugTime("GDX.smtDelta", Gdx.graphics.deltaTime.times(1000_000_000f).toLong())
AppLoader.getINSTANCE().screen.render(delta) AppLoader.getINSTANCE().screen.render(delta)
} }
@@ -422,35 +387,24 @@ object Terrarum : Screen {
AppLoader.getINSTANCE().screen.resume() AppLoader.getINSTANCE().screen.resume()
} }
/** Don't call this! Call AppLoader.dispose() */
override fun dispose() { override fun dispose() {
AppLoader.getINSTANCE().screen.dispose()
fontGame.dispose()
fontSmallNumbers.dispose()
//dispose any other resources used in this level //dispose any other resources used in this level
shaderBayer.dispose() shaderBayer.dispose()
shaderSkyboxFill.dispose() shaderSkyboxFill.dispose()
shaderBlur.dispose() shaderBlur.dispose()
shaderBlendGlow.dispose() shaderBlendGlow.dispose()
ingame?.dispose()
shapeRender.dispose()
batch.dispose()
} }
override fun hide() { override fun hide() {
AppLoader.getINSTANCE().screen.hide() AppLoader.getINSTANCE().screen.hide()
} }
/** For the actual resize, call AppLoader.resize() */
override fun resize(width: Int, height: Int) { override fun resize(width: Int, height: Int) {
/*try { ingame?.resize(width, height)
AppLoader.getINSTANCE().screen.resize(width, height)
}
catch (e: NullPointerException) { }*/ // I sense circular recursion...
printdbg(this, "newsize: ${Gdx.graphics.width}x${Gdx.graphics.height} | internal: ${width}x$height") printdbg(this, "newsize: ${Gdx.graphics.width}x${Gdx.graphics.height} | internal: ${width}x$height")
} }
@@ -468,28 +422,36 @@ object Terrarum : Screen {
} }
/** Position of the cursor in the world */ /** Position of the cursor in the world */
inline val mouseX: Double val mouseX: Double
get() = WorldCamera.x + Gdx.input.x / (ingame?.screenZoom ?: 1f).toDouble() get() = WorldCamera.x + Gdx.input.x / (ingame?.screenZoom ?: 1f).toDouble()
/** Position of the cursor in the world */ /** Position of the cursor in the world */
inline val mouseY: Double val mouseY: Double
get() = WorldCamera.y + Gdx.input.y / (ingame?.screenZoom ?: 1f).toDouble() get() = WorldCamera.y + Gdx.input.y / (ingame?.screenZoom ?: 1f).toDouble()
/** Position of the cursor in the world */ /** Position of the cursor in the world */
@JvmStatic inline val mouseTileX: Int val oldMouseX: Double
get() = WorldCamera.x + (Gdx.input.x - Gdx.input.deltaX) / (ingame?.screenZoom ?: 1f).toDouble()
/** Position of the cursor in the world */
val oldMouseY: Double
get() = WorldCamera.y + (Gdx.input.y - Gdx.input.deltaY) / (ingame?.screenZoom ?: 1f).toDouble()
/** Position of the cursor in the world */
@JvmStatic val mouseTileX: Int
get() = (mouseX / FeaturesDrawer.TILE_SIZE).floorInt() get() = (mouseX / FeaturesDrawer.TILE_SIZE).floorInt()
/** Position of the cursor in the world */ /** Position of the cursor in the world */
@JvmStatic inline val mouseTileY: Int @JvmStatic val mouseTileY: Int
get() = (mouseY / FeaturesDrawer.TILE_SIZE).floorInt() get() = (mouseY / FeaturesDrawer.TILE_SIZE).floorInt()
/** Position of the cursor in the world */
@JvmStatic val oldMouseTileX: Int
get() = (oldMouseX / FeaturesDrawer.TILE_SIZE).floorInt()
/** Position of the cursor in the world */
@JvmStatic val oldMouseTileY: Int
get() = (oldMouseY / FeaturesDrawer.TILE_SIZE).floorInt()
inline val mouseScreenX: Int inline val mouseScreenX: Int
get() = Gdx.input.x get() = Gdx.input.x
inline val mouseScreenY: Int inline val mouseScreenY: Int
get() = Gdx.input.y get() = Gdx.input.y
/** Bigger than 1.0 */ /** Delta converted as it it was a FPS */
inline val updateRate: Double inline val updateRate: Double
get() = 1.0 / AppLoader.getSmoothDelta() get() = 1.0 / Gdx.graphics.deltaTime
/** Smaller than 1.0 */
val renderRate = 1.0 / TARGET_INTERNAL_FPS
val renderRateStr = TARGET_INTERNAL_FPS.toString()
/** /**
* Usage: * Usage:
* *
@@ -571,6 +533,14 @@ fun SpriteBatch.drawStraightLine(x: Float, y: Float, otherEnd: Float, thickness:
infix fun Color.mul(other: Color): Color = this.cpy().mul(other) infix fun Color.mul(other: Color): Color = this.cpy().mul(other)
infix fun Color.mulAndAssign(other: Color): Color {
this.r *= other.r
this.g *= other.g
this.b *= other.b
this.a *= other.a
return this
}
fun blendMul(batch: SpriteBatch) { fun blendMul(batch: SpriteBatch) {
@@ -657,7 +627,7 @@ object BlendMode {
} }
enum class RunningEnvironment { enum class RunningEnvironment {
PC, CONSOLE, MOBILE PC, CONSOLE//, MOBILE
} }
infix fun Color.screen(other: Color) = Color( infix fun Color.screen(other: Color) = Color(
@@ -717,6 +687,7 @@ fun Double.roundInt(): Int = Math.round(this).toInt()
fun Float.roundInt(): Int = Math.round(this) fun Float.roundInt(): Int = Math.round(this)
fun Double.abs() = Math.abs(this) fun Double.abs() = Math.abs(this)
fun Double.sqr() = this * this fun Double.sqr() = this * this
fun Float.sqr() = this * this
fun Double.sqrt() = Math.sqrt(this) fun Double.sqrt() = Math.sqrt(this)
fun Float.sqrt() = FastMath.sqrt(this) fun Float.sqrt() = FastMath.sqrt(this)
fun Int.abs() = this.absoluteValue fun Int.abs() = this.absoluteValue

View File

@@ -23,6 +23,7 @@ import net.torvald.terrarum.modulebasegame.Ingame
import net.torvald.terrarum.modulebasegame.IngameRenderer import net.torvald.terrarum.modulebasegame.IngameRenderer
import net.torvald.terrarum.modulebasegame.gameactors.HumanoidNPC import net.torvald.terrarum.modulebasegame.gameactors.HumanoidNPC
import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension
import net.torvald.terrarum.modulebasegame.gameworld.WorldTime
import net.torvald.terrarum.modulebasegame.ui.UIRemoCon import net.torvald.terrarum.modulebasegame.ui.UIRemoCon
import net.torvald.terrarum.modulebasegame.ui.UITitleRemoConYaml import net.torvald.terrarum.modulebasegame.ui.UITitleRemoConYaml
import net.torvald.terrarum.modulebasegame.weather.WeatherMixer import net.torvald.terrarum.modulebasegame.weather.WeatherMixer
@@ -129,7 +130,8 @@ class TitleScreen(val batch: SpriteBatch) : Screen {
demoWorld = ReadLayerData(FileInputStream(ModMgr.getFile("basegame", "demoworld"))) demoWorld = ReadLayerData(FileInputStream(ModMgr.getFile("basegame", "demoworld")))
// set time to summer
demoWorld.time.addTime(WorldTime.DAY_LENGTH * 32)
// construct camera nodes // construct camera nodes
val nodeCount = 100 val nodeCount = 100
@@ -198,26 +200,28 @@ class TitleScreen(val batch: SpriteBatch) : Screen {
private val introUncoverTime: Second = 0.3f private val introUncoverTime: Second = 0.3f
private var introUncoverDeltaCounter = 0f private var introUncoverDeltaCounter = 0f
private var updateDeltaCounter = 0.0 private var updateAkku = 0.0
protected val renderRate = Terrarum.renderRate
override fun render(delta: Float) { override fun render(delta: Float) {
// async update // async update and render
updateDeltaCounter += delta
if (delta < 1f / 10f) { // discard async if measured FPS <= 10 val dt = Gdx.graphics.deltaTime
var updateTries = 0 updateAkku += dt
while (updateDeltaCounter >= renderRate && updateTries < 6) {
updateScreen(delta) var i = 0L
updateDeltaCounter -= renderRate while (updateAkku >= delta) {
updateTries++ AppLoader.measureDebugTime("Ingame.update") { updateScreen(delta) }
} updateAkku -= delta
} i += 1
else {
updateScreen(delta)
} }
AppLoader.setDebugTime("Ingame.updateCounter", i)
// render? just do it anyway // render? just do it anyway
renderScreen() AppLoader.measureDebugTime("Ingame.render") { renderScreen() }
AppLoader.setDebugTime("Ingame.render-Light",
(AppLoader.debugTimers["Ingame.render"] as Long) - ((AppLoader.debugTimers["Renderer.LightTotal"] as? Long) ?: 0)
)
} }
fun updateScreen(delta: Float) { fun updateScreen(delta: Float) {

View File

@@ -6,7 +6,9 @@ import com.badlogic.gdx.graphics.Pixmap
import com.badlogic.gdx.graphics.Texture import com.badlogic.gdx.graphics.Texture
import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.terrarum.modulebasegame.ui.UIInventoryFull import net.torvald.terrarum.modulebasegame.ui.UIInventoryFull
import net.torvald.terrarum.ui.* import net.torvald.terrarum.ui.UIItem
import net.torvald.terrarum.ui.UIItemImageButton
import net.torvald.terrarum.ui.UIUtils
/** /**
* Created by minjaesong on 2017-10-20. * Created by minjaesong on 2017-10-20.
@@ -18,6 +20,12 @@ class UIItemInventoryCatBar(
override val width: Int override val width: Int
) : UIItem(parentUI) { ) : UIItem(parentUI) {
// deal with the moving position
override var oldPosX = posX
override var oldPosY = posY
private val parentInventory = parentUI
private val catIcons = parentUI.catIcons private val catIcons = parentUI.catIcons
private val catArrangement = parentUI.catArrangement private val catArrangement = parentUI.catArrangement
@@ -91,15 +99,23 @@ class UIItemInventoryCatBar(
private val underlineColour = Color(0xeaeaea_40.toInt()) private val underlineColour = Color(0xeaeaea_40.toInt())
private val underlineHighlightColour = mainButtons[0].highlightCol private val underlineHighlightColour = mainButtons[0].highlightCol
private var highlighterXPos = mainButtons[selectedIndex].posX.toDouble() private var highlighterXPos = mainButtons[selectedIndex].posX.toFloat()
private var highlighterXStart = highlighterXPos private var highlighterXStart = highlighterXPos
private var highlighterXEnd = highlighterXPos private var highlighterXEnd = highlighterXPos
private val highlighterYPos = catIcons.tileH + 4f private val highlighterYPos = catIcons.tileH + 4f
private var highlighterMoving = false private var highlighterMoving = false
private val highlighterMoveDuration: Second = 0.1f private val highlighterMoveDuration: Second = 0.15f
private var highlighterMoveTimer: Second = 0f private var highlighterMoveTimer: Second = 0f
private var transitionFired = false
/**
* 0: map, 1: inventory caticons, 2: menu
*/
var selectedPanel = 1
private set
// set up underlined indicator // set up underlined indicator
init { init {
// procedurally generate texture // procedurally generate texture
@@ -134,8 +150,8 @@ class UIItemInventoryCatBar(
highlighterXPos = UIUtils.moveQuick( highlighterXPos = UIUtils.moveQuick(
highlighterXStart, highlighterXStart,
highlighterXEnd, highlighterXEnd,
highlighterMoveTimer.toDouble(), highlighterMoveTimer,
highlighterMoveDuration.toDouble() highlighterMoveDuration
) )
if (highlighterMoveTimer > highlighterMoveDuration) { if (highlighterMoveTimer > highlighterMoveDuration) {
@@ -150,23 +166,61 @@ class UIItemInventoryCatBar(
mainButtons.forEachIndexed { index, btn -> mainButtons.forEachIndexed { index, btn ->
btn.update(delta) btn.update(delta)
if (btn.mousePushed && selectedPanel != 1) {
transitionFired = true
selectedPanel = 1
}
if (btn.mousePushed && index != selectedIndex) { if (btn.mousePushed && index != selectedIndex) {
// normal stuffs
val oldIndex = selectedIndex val oldIndex = selectedIndex
highlighterXStart = mainButtons[selectedIndex].posX.toDouble() // using old selectedIndex highlighterXStart = mainButtons[selectedIndex].posX.toFloat() // using old selectedIndex
selectedIndex = index selectedIndex = index
highlighterMoving = true highlighterMoving = true
highlighterXEnd = mainButtons[selectedIndex].posX.toDouble() // using new selectedIndex highlighterXEnd = mainButtons[selectedIndex].posX.toFloat() // using new selectedIndex
selectionChangeListener?.invoke(oldIndex, index) selectionChangeListener?.invoke(oldIndex, index)
} }
if (selectedPanel == 1) {
btn.highlighted = (index == selectedIndex) // forcibly highlight if this.highlighted != null btn.highlighted = (index == selectedIndex) // forcibly highlight if this.highlighted != null
sideButtons[0].highlighted = false
sideButtons[3].highlighted = false
}
} }
sideButtons[0].update(delta) sideButtons[0].update(delta)
sideButtons[3].update(delta) sideButtons[3].update(delta)
// more transition stuffs
if (sideButtons[0].mousePushed) {
if (selectedPanel != 0) transitionFired = true
mainButtons.forEach { it.highlighted = false }
selectedPanel = 0
parentInventory.requestTransition(0)
sideButtons[0].highlighted = true
sideButtons[3].highlighted = false
}
else if (sideButtons[3].mousePushed) {
if (selectedPanel != 2) transitionFired = true
mainButtons.forEach { it.highlighted = false }
selectedPanel = 2
parentInventory.requestTransition(2)
transitionFired = true
sideButtons[0].highlighted = false
sideButtons[3].highlighted = true
}
if (transitionFired) {
transitionFired = false
parentInventory.requestTransition(2 - selectedPanel)
}
} }
override fun render(batch: SpriteBatch, camera: Camera) { override fun render(batch: SpriteBatch, camera: Camera) {
@@ -186,11 +240,15 @@ class UIItemInventoryCatBar(
batch.drawStraightLine(posX.toFloat(), posY + height - 1f, posX + width.toFloat(), 1f, false) batch.drawStraightLine(posX.toFloat(), posY + height - 1f, posX + width.toFloat(), 1f, false)
// indicator // indicator
if (selectedPanel == 1) {
batch.color = underlineHighlightColour batch.color = underlineHighlightColour
batch.draw(underlineIndTex, (highlighterXPos - buttonGapSize / 2).toFloat().round(), posY + highlighterYPos) batch.draw(underlineIndTex, (highlighterXPos - buttonGapSize / 2).toFloat().round(), posY + highlighterYPos)
} }
}
override fun dispose() { override fun dispose() {

View File

@@ -36,6 +36,10 @@ class UIItemInventoryElem(
val drawBackOnNull: Boolean = true val drawBackOnNull: Boolean = true
) : UIItemInventoryCellBase(parentUI, posX, posY, item, amount, itemImage, quickslot, equippedSlot) { ) : UIItemInventoryCellBase(parentUI, posX, posY, item, amount, itemImage, quickslot, equippedSlot) {
// deal with the moving position
override var oldPosX = posX
override var oldPosY = posY
companion object { companion object {
val height = 48 val height = 48
val UNIQUE_ITEM_HAS_NO_AMOUNT = -1 val UNIQUE_ITEM_HAS_NO_AMOUNT = -1
@@ -194,7 +198,6 @@ class UIItemInventoryElem(
override fun dispose() { override fun dispose() {
itemImage?.texture?.dispose()
} }
override fun keyUp(keycode: Int): Boolean { override fun keyUp(keycode: Int): Boolean {

View File

@@ -33,6 +33,10 @@ class UIItemInventoryElemSimple(
val drawBackOnNull: Boolean = true val drawBackOnNull: Boolean = true
) : UIItemInventoryCellBase(parentUI, posX, posY, item, amount, itemImage, quickslot, equippedSlot) { ) : UIItemInventoryCellBase(parentUI, posX, posY, item, amount, itemImage, quickslot, equippedSlot) {
// deal with the moving position
override var oldPosX = posX
override var oldPosY = posY
companion object { companion object {
val height = UIItemInventoryElem.height val height = UIItemInventoryElem.height
} }
@@ -96,8 +100,8 @@ class UIItemInventoryElemSimple(
batch.drawStraightLine(barOffset, posY + height - thickness, barOffset + barFullLen * (item!!.durability / item!!.maxDurability), thickness, false) batch.drawStraightLine(barOffset, posY + height - thickness, barOffset + barFullLen * (item!!.durability / item!!.maxDurability), thickness, false)
} }
} }
else { // draw item count when applicable
// draw item count else if (item!!.stackable) {
val amountString = amount.toString() val amountString = amount.toString()
// highlight item count (blocks/walls) if the item is equipped // highlight item count (blocks/walls) if the item is equipped
@@ -176,7 +180,6 @@ class UIItemInventoryElemSimple(
override fun dispose() { override fun dispose() {
itemImage?.texture?.dispose()
} }
override fun keyUp(keycode: Int): Boolean { override fun keyUp(keycode: Int): Boolean {

View File

@@ -123,7 +123,10 @@ inline class Yaml(val text: String) {
val nodeString = it.drop(2) val nodeString = it.drop(2)
val nodeNameAndInvocation = nodeString.split(SEPARATOR) val nodeNameAndInvocation = nodeString.split(SEPARATOR)
val nodeName = nodeNameAndInvocation[0] val nodeName = nodeNameAndInvocation[0]
val nodeInvocation = loadClass(nodeNameAndInvocation[1]) val nodeInvocation = if (nodeNameAndInvocation.size == 2)
loadClass(nodeNameAndInvocation[1])
else
null
val nameInvokePair = nodeName to nodeInvocation val nameInvokePair = nodeName to nodeInvocation
@@ -193,5 +196,5 @@ inline class Yaml(val text: String) {
* *
*/ */
interface YamlInvokable { interface YamlInvokable {
operator fun invoke() operator fun invoke(args: Array<Any>)
} }

View File

@@ -1,6 +1,9 @@
package net.torvald.terrarum.blockproperties package net.torvald.terrarum.blockproperties
import com.badlogic.gdx.graphics.Color
import net.torvald.terrarum.AppLoader import net.torvald.terrarum.AppLoader
import net.torvald.terrarum.gameworld.FluidType
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.gameworld.MapLayer import net.torvald.terrarum.gameworld.MapLayer
import net.torvald.terrarum.gameworld.PairedMapLayer import net.torvald.terrarum.gameworld.PairedMapLayer
import net.torvald.terrarum.utils.CSVFetcher import net.torvald.terrarum.utils.CSVFetcher
@@ -72,6 +75,19 @@ object BlockCodex {
} }
} }
operator fun get(fluidType: FluidType?): BlockProp {
if (fluidType == null || fluidType.value == 0) {
return blockProps[Block.AIR]
}
try {
return blockProps[fluidType.abs() + GameWorld.TILES_SUPPORTED - 1]
}
catch (e: NullPointerException) {
throw NullPointerException("Blockprop with raw id $fluidType does not exist.")
}
}
fun getOrNull(rawIndex: Int?): BlockProp? { fun getOrNull(rawIndex: Int?): BlockProp? {
if (rawIndex == null || rawIndex == Block.NULL) { if (rawIndex == null || rawIndex == Block.NULL) {
return null return null
@@ -95,6 +111,7 @@ object BlockCodex {
prop.shadeColG = floatVal(record, "shdg") / LightmapRenderer.MUL_FLOAT prop.shadeColG = floatVal(record, "shdg") / LightmapRenderer.MUL_FLOAT
prop.shadeColB = floatVal(record, "shdb") / LightmapRenderer.MUL_FLOAT prop.shadeColB = floatVal(record, "shdb") / LightmapRenderer.MUL_FLOAT
prop.shadeColA = floatVal(record, "shduv") / LightmapRenderer.MUL_FLOAT prop.shadeColA = floatVal(record, "shduv") / LightmapRenderer.MUL_FLOAT
prop.shadeColor = Color(prop.shadeColR, prop.shadeColG, prop.shadeColB, prop.shadeColA)
prop.strength = intVal(record, "str") prop.strength = intVal(record, "str")
prop.density = intVal(record, "dsty") prop.density = intVal(record, "dsty")
@@ -103,6 +120,7 @@ object BlockCodex {
prop.lumColG = floatVal(record, "lumg") / LightmapRenderer.MUL_FLOAT prop.lumColG = floatVal(record, "lumg") / LightmapRenderer.MUL_FLOAT
prop.lumColB = floatVal(record, "lumb") / LightmapRenderer.MUL_FLOAT prop.lumColB = floatVal(record, "lumb") / LightmapRenderer.MUL_FLOAT
prop.lumColA = floatVal(record, "lumuv") / LightmapRenderer.MUL_FLOAT prop.lumColA = floatVal(record, "lumuv") / LightmapRenderer.MUL_FLOAT
prop.internalLumCol = Color(prop.lumColR, prop.lumColG, prop.lumColB, prop.lumColA)
prop.friction = intVal(record, "fr") prop.friction = intVal(record, "fr")
prop.viscosity = intVal(record, "vscs") prop.viscosity = intVal(record, "vscs")

View File

@@ -16,6 +16,7 @@ class BlockProp {
var shadeColG = 0f var shadeColG = 0f
var shadeColB = 0f var shadeColB = 0f
var shadeColA = 0f var shadeColA = 0f
lateinit var shadeColor: Color
/** /**
* @param opacity Raw RGB value, without alpha * @param opacity Raw RGB value, without alpha
@@ -39,12 +40,13 @@ class BlockProp {
var lumColG = 0f var lumColG = 0f
var lumColB = 0f var lumColB = 0f
var lumColA = 0f var lumColA = 0f
lateinit var internalLumCol: Color
/** /**
* @param luminosity * @param luminosity
*/ */
inline val luminosity: Color inline val luminosity: Color
get() = BlockPropUtil.getDynamicLumFunc(Color(lumColR, lumColG, lumColB, lumColA), dynamicLuminosityFunction) get() = BlockPropUtil.getDynamicLumFunc(internalLumCol, dynamicLuminosityFunction)
var drop: Int = 0 var drop: Int = 0

View File

@@ -4,7 +4,6 @@ import com.badlogic.gdx.Gdx
import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.Color
import com.jme3.math.FastMath import com.jme3.math.FastMath
import net.torvald.random.HQRNG import net.torvald.random.HQRNG
import net.torvald.terrarum.AppLoader
import net.torvald.terrarum.Second import net.torvald.terrarum.Second
import net.torvald.terrarum.Terrarum import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.modulebasegame.gameworld.WorldTime import net.torvald.terrarum.modulebasegame.gameworld.WorldTime
@@ -64,9 +63,9 @@ object BlockPropUtil {
internal fun dynamicLumFuncTickClock() { internal fun dynamicLumFuncTickClock() {
// FPS-time compensation // FPS-time compensation
if (Gdx.graphics.framesPerSecond > 0) { if (Gdx.graphics.framesPerSecond > 0) {
flickerFuncX += AppLoader.getSmoothDelta().toFloat() * 1000f flickerFuncX += Gdx.graphics.deltaTime * 1000f
breathFuncX += AppLoader.getSmoothDelta().toFloat() * 1000f breathFuncX += Gdx.graphics.deltaTime * 1000f
pulsateFuncX += AppLoader.getSmoothDelta().toFloat() * 1000f pulsateFuncX += Gdx.graphics.deltaTime * 1000f
} }
// flicker-related vars // flicker-related vars

View File

@@ -44,6 +44,7 @@ object CommandDict {
"kill" to KillActor, "kill" to KillActor,
"money" to MoneyDisp, "money" to MoneyDisp,
"screenshot" to TakeScreenshot, "screenshot" to TakeScreenshot,
//"resize" to ResizeScreen,
// Test codes // Test codes
"bulletintest" to SetBulletin, "bulletintest" to SetBulletin,

View File

@@ -22,7 +22,8 @@ internal object CommandInterpreter {
"help", "help",
"version", "version",
"tips", "tips",
"screenshot" "screenshot",
"resize"
) )
internal fun execute(command: String) { internal fun execute(command: String) {

View File

@@ -1,6 +1,6 @@
package net.torvald.terrarum.console package net.torvald.terrarum.console
import net.torvald.terrarum.console.ConsoleCommand import com.badlogic.gdx.Gdx
/** /**
* Created by minjaesong on 2016-01-15. * Created by minjaesong on 2016-01-15.
@@ -8,7 +8,7 @@ import net.torvald.terrarum.console.ConsoleCommand
internal object QuitApp : ConsoleCommand { internal object QuitApp : ConsoleCommand {
override fun execute(args: Array<String>) { override fun execute(args: Array<String>) {
System.exit(1) Gdx.app.exit()
} }
override fun printUsage() { override fun printUsage() {

View File

@@ -0,0 +1,30 @@
package net.torvald.terrarum.console
import net.torvald.terrarum.AppLoader
import net.torvald.terrarum.Terrarum
object ResizeScreen: ConsoleCommand {
override fun execute(args: Array<String>) {
if (args.size == 3) {
Terrarum.resize(args[1].toInt(), args[2].toInt())
}
else if (args.size == 2) {
when (args[1]) {
"720p" -> AppLoader.resizeScreen(1280,720)
"1080p" -> AppLoader.resizeScreen(1920,1080)
"default" -> AppLoader.resizeScreen(AppLoader.defaultW, AppLoader.defaultH)
else -> { printUsage(); return }
}
}
else {
printUsage(); return
}
Echo("Screen resized to ${AppLoader.screenW}x${AppLoader.screenH}")
}
override fun printUsage() {
Echo("Usage: resize [width] [height]. Minimum size is ${AppLoader.minimumW}x${AppLoader.minimumH}")
Echo("Reserved keywords: 720p, 1080p, default")
}
}

View File

@@ -29,6 +29,9 @@ object AVKey {
const val JUMPPOWER = "jumppower" const val JUMPPOWER = "jumppower"
const val JUMPPOWERBUFF = "$JUMPPOWER$BUFF" const val JUMPPOWERBUFF = "$JUMPPOWER$BUFF"
/** NOT meant for living creatures. Also, only effective when noclip=true. E.g. camera actor */
const val FRICTIONMULT = "frictionmult"
/** Int /** Int
* "Default" value of 1 000 * "Default" value of 1 000
*/ */

View File

@@ -1,7 +1,5 @@
package net.torvald.terrarum.gameactors package net.torvald.terrarum.gameactors
import com.badlogic.gdx.Input
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.spriteanimation.SpriteAnimation import net.torvald.spriteanimation.SpriteAnimation
import net.torvald.terrarum.* import net.torvald.terrarum.*
@@ -9,7 +7,6 @@ import net.torvald.terrarum.AppLoader.printdbg
import net.torvald.terrarum.blockproperties.Block import net.torvald.terrarum.blockproperties.Block
import net.torvald.terrarum.blockproperties.BlockCodex import net.torvald.terrarum.blockproperties.BlockCodex
import net.torvald.terrarum.blockproperties.BlockProp import net.torvald.terrarum.blockproperties.BlockProp
import net.torvald.terrarum.gamecontroller.KeyToggler
import net.torvald.terrarum.gameworld.BlockAddress import net.torvald.terrarum.gameworld.BlockAddress
import net.torvald.terrarum.gameworld.GameWorld import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
@@ -95,7 +92,7 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
) )
/** /**
* TODO Pixels per 1/60 seconds. * Unit: Pixels per 1/60 (or AppLoader.UPDATE_RATE) seconds.
* *
* When the engine resolves this value, the framerate must be accounted for. E.g.: * When the engine resolves this value, the framerate must be accounted for. E.g.:
* 3.0 is resolved as 3.0 if FPS is 60, but the same value should be resolved as 6.0 if FPS is 30. * 3.0 is resolved as 3.0 if FPS is 60, but the same value should be resolved as 6.0 if FPS is 30.
@@ -109,15 +106,21 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
* Acceleration: used in code like: * Acceleration: used in code like:
* veloY += 3.0 * veloY += 3.0
* +3.0 is acceleration. You __accumulate__ acceleration to the velocity. * +3.0 is acceleration. You __accumulate__ acceleration to the velocity.
*
* V for Velocity!
*/ */
internal val externalForce = Vector2(0.0, 0.0) internal val externalV = Vector2(0.0, 0.0)
@Transient private val VELO_HARD_LIMIT = 100.0 @Transient private val VELO_HARD_LIMIT = 100.0
/** /**
* Unit: Pixels per 1/60 (or AppLoader.UPDATE_RATE) seconds.
*
* for "Controllable" actors * for "Controllable" actors
*
* V for Velocity!
*/ */
var controllerMoveDelta: Vector2? = if (this is Controllable) Vector2() else null var controllerV: Vector2? = if (this is Controllable) Vector2() else null
// not sure we need this... // not sure we need this...
//var jumpable = true // this is kind of like "semaphore" //var jumpable = true // this is kind of like "semaphore"
@@ -338,7 +341,7 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
inline val feetPosTile: IntArray inline val feetPosTile: IntArray
get() = intArrayOf(hIntTilewiseHitbox.centeredX.floorInt(), hIntTilewiseHitbox.endY.floorInt()) get() = intArrayOf(hIntTilewiseHitbox.centeredX.floorInt(), hIntTilewiseHitbox.endY.floorInt())
override fun run() = update(AppLoader.getSmoothDelta().toFloat()) override fun run() = update(AppLoader.UPDATE_RATE.toFloat())
/** /**
* Add vector value to the velocity, in the time unit of single frame. * Add vector value to the velocity, in the time unit of single frame.
@@ -348,23 +351,17 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
* @param acc : Acceleration in Vector2 * @param acc : Acceleration in Vector2
*/ */
fun applyForce(acc: Vector2) { fun applyForce(acc: Vector2) {
externalForce += acc * speedMultByTile externalV += acc * speedMultByTile
} }
private val bounceDampenVelThreshold = 0.5 private val bounceDampenVelThreshold = 0.5
override fun update(fdelta: Float) { override fun update(delta: Float) {
if (isUpdate && !flagDespawn) { if (isUpdate && !flagDespawn) {
//val delta = Gdx.graphics.rawDeltaTime.toDouble()
val delta = AppLoader.getSmoothDelta()
//println("${Gdx.graphics.rawDeltaTime.toDouble()}\t${AppLoader.getSmoothDelta()}")
if (!assertPrinted) assertInit() if (!assertPrinted) assertInit()
if (sprite != null) sprite!!.update(fdelta) if (sprite != null) sprite!!.update(delta)
if (spriteGlow != null) spriteGlow!!.update(fdelta) if (spriteGlow != null) spriteGlow!!.update(delta)
// make NoClip work for player // make NoClip work for player
if (true) {//this == Terrarum.ingame!!.actorNowPlaying) { if (true) {//this == Terrarum.ingame!!.actorNowPlaying) {
@@ -381,7 +378,7 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
// Codes that modifies velocity (moveDelta and externalForce) // // Codes that modifies velocity (moveDelta and externalV) //
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
// --> Apply more forces <-- // // --> Apply more forces <-- //
@@ -396,8 +393,8 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
} }
// hard limit velocity // hard limit velocity
externalForce.x = externalForce.x.bipolarClamp(VELO_HARD_LIMIT) // displaceHitbox SHOULD use moveDelta externalV.x = externalV.x.bipolarClamp(VELO_HARD_LIMIT) // displaceHitbox SHOULD use moveDelta
externalForce.y = externalForce.y.bipolarClamp(VELO_HARD_LIMIT) externalV.y = externalV.y.bipolarClamp(VELO_HARD_LIMIT)
if (!isChronostasis) { if (!isChronostasis) {
/////////////////////////////////////////////////// ///////////////////////////////////////////////////
@@ -410,11 +407,11 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
* This body is NON-STATIC and the other body is STATIC * This body is NON-STATIC and the other body is STATIC
*/ */
if (!isNoCollideWorld) { if (!isNoCollideWorld) {
displaceHitbox(delta) displaceHitbox(delta.toDouble())
} }
else { else {
val vecSum = externalForce + (controllerMoveDelta ?: Vector2(0.0, 0.0)) val vecSum = externalV + (controllerV ?: Vector2(0.0, 0.0))
hitbox.translate(vecSum * (Terrarum.PHYS_REF_FPS * delta)) hitbox.translate(vecSum)
} }
////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////
@@ -428,7 +425,7 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
// TODO less friction for non-animating objects (make items glide far more on ice) // TODO less friction for non-animating objects (make items glide far more on ice)
// FIXME asymmetry on friction // FIXME asymmetry on friction
setHorizontalFriction(delta) // friction SHOULD use and alter externalForce setHorizontalFriction(delta) // friction SHOULD use and alter externalV
//if (isNoClip) { // TODO also hanging on the rope, etc. //if (isNoClip) { // TODO also hanging on the rope, etc.
setVerticalFriction(delta) setVerticalFriction(delta)
//} //}
@@ -470,33 +467,33 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
if (!(isWalled(hitbox, COLLIDING_LEFT) && walkX < 0) if (!(isWalled(hitbox, COLLIDING_LEFT) && walkX < 0)
|| !(isWalled(hitbox, COLLIDING_RIGHT) && walkX > 0) || !(isWalled(hitbox, COLLIDING_RIGHT) && walkX > 0)
) { ) {
moveDelta.x = externalForce.x + walkX moveDelta.x = externalV.x + walkX
} }
// decide whether to ignore walkY // decide whether to ignore walkY
if (!(isWalled(hitbox, COLLIDING_TOP) && walkY < 0) if (!(isWalled(hitbox, COLLIDING_TOP) && walkY < 0)
|| !(isWalled(hitbox, COLLIDING_BOTTOM) && walkY > 0) || !(isWalled(hitbox, COLLIDING_BOTTOM) && walkY > 0)
) { ) {
moveDelta.y = externalForce.y + walkY moveDelta.y = externalV.y + walkY
} }
} }
else { else {
if (!isWalled(hitbox, COLLIDING_LEFT) if (!isWalled(hitbox, COLLIDING_LEFT)
|| !isWalled(hitbox, COLLIDING_RIGHT) || !isWalled(hitbox, COLLIDING_RIGHT)
) { ) {
moveDelta.x = externalForce.x moveDelta.x = externalV.x
} }
// decide whether to ignore walkY // decide whether to ignore walkY
if (!isWalled(hitbox, COLLIDING_TOP) if (!isWalled(hitbox, COLLIDING_TOP)
|| !isWalled(hitbox, COLLIDING_BOTTOM) || !isWalled(hitbox, COLLIDING_BOTTOM)
) { ) {
moveDelta.y = externalForce.y moveDelta.y = externalV.y
} }
} }
}*/ }*/
fun getDrag(delta: Double, externalForce: Vector2): Vector2 { fun getDrag(delta: Float, externalForce: Vector2): Vector2 {
/** /**
* weight; gravitational force in action * weight; gravitational force in action
* W = mass * G (9.8 [m/s^2]) * W = mass * G (9.8 [m/s^2])
@@ -514,7 +511,7 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
val V: Vector2 = (W - D) / Terrarum.PHYS_TIME_FRAME * SI_TO_GAME_ACC val V: Vector2 = (W - D) / Terrarum.PHYS_TIME_FRAME * SI_TO_GAME_ACC
return V * (Terrarum.PHYS_REF_FPS * delta).sqrt() return V
// FIXME v * const, where const = 1.0 for FPS=60, sqrt(2.0) for FPS=30, etc. // FIXME v * const, where const = 1.0 for FPS=60, sqrt(2.0) for FPS=30, etc.
// this is "close enough" solution and not perfect. // this is "close enough" solution and not perfect.
@@ -535,11 +532,11 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
* *
* Apply only if not grounded; normal force is precessed separately. * Apply only if not grounded; normal force is precessed separately.
*/ */
private fun applyGravitation(delta: Double) { private fun applyGravitation(delta: Float) {
if (!isNoSubjectToGrav && !(gravitation.y > 0 && walledBottom || gravitation.y < 0 && walledTop)) { if (!isNoSubjectToGrav && !(gravitation.y > 0 && walledBottom || gravitation.y < 0 && walledTop)) {
//if (!isWalled(hitbox, COLLIDING_BOTTOM)) { //if (!isWalled(hitbox, COLLIDING_BOTTOM)) {
applyForce(getDrag(delta, externalForce)) applyForce(getDrag(delta, externalV))
//} //}
} }
} }
@@ -587,7 +584,7 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
// if not touching: // if not touching:
// do nothing // do nothing
// [Friction]: // [Friction]:
// deform vector "externalForce" // deform vector "externalV"
// if isControllable: // if isControllable:
// also alter walkX/Y // also alter walkX/Y
// translate ((nextHitbox)) hitbox by moveDelta (forces), this consumes force // translate ((nextHitbox)) hitbox by moveDelta (forces), this consumes force
@@ -637,7 +634,7 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
fun Double.modTileDelta() = this - this.modTile() fun Double.modTileDelta() = this - this.modTile()
val vectorSum = (externalForce + controllerMoveDelta) * (Terrarum.PHYS_REF_FPS * delta) val vectorSum = (externalV + controllerV)
val ccdSteps = minOf(16, (vectorSum.magnitudeSquared / TILE_SIZE.sqr()).floorInt() + 1) // adaptive val ccdSteps = minOf(16, (vectorSum.magnitudeSquared / TILE_SIZE.sqr()).floorInt() + 1) // adaptive
@@ -838,20 +835,20 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
// bounce X/Y // bounce X/Y
if (bounceX) { if (bounceX) {
externalForce.x *= elasticity externalV.x *= elasticity
controllerMoveDelta?.let { controllerMoveDelta!!.x *= elasticity } controllerV?.let { controllerV!!.x *= elasticity }
} }
if (bounceY) { if (bounceY) {
externalForce.y *= elasticity externalV.y *= elasticity
controllerMoveDelta?.let { controllerMoveDelta!!.y *= elasticity } controllerV?.let { controllerV!!.y *= elasticity }
} }
if (zeroX) { if (zeroX) {
externalForce.x = 0.0 externalV.x = 0.0
controllerMoveDelta?.let { controllerMoveDelta!!.x = 0.0 } controllerV?.let { controllerV!!.x = 0.0 }
} }
if (zeroY) { if (zeroY) {
externalForce.y = 0.0 externalV.y = 0.0
controllerMoveDelta?.let { controllerMoveDelta!!.y = 0.0 } controllerV?.let { controllerV!!.y = 0.0 }
} }
@@ -1012,11 +1009,11 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
(BlockCodex[tile].isSolid) || (BlockCodex[tile].isSolid) ||
// platforms, moving downward AND not "going down" // platforms, moving downward AND not "going down"
(this is ActorHumanoid && BlockCodex[tile].isPlatform && (this is ActorHumanoid && BlockCodex[tile].isPlatform &&
externalForce.y + (controllerMoveDelta?.y ?: 0.0) >= 0.0 && externalV.y + (controllerV?.y ?: 0.0) >= 0.0 &&
!this.isDownDown && this.axisY <= 0f) || !this.isDownDown && this.axisY <= 0f) ||
// platforms, moving downward // platforms, moving downward
(this !is ActorHumanoid && BlockCodex[tile].isPlatform && (this !is ActorHumanoid && BlockCodex[tile].isPlatform &&
externalForce.y + (controllerMoveDelta?.y ?: 0.0) >= 0.0) externalV.y + (controllerV?.y ?: 0.0) >= 0.0)
// TODO: as for the platform, only apply it when it's a feet tile // TODO: as for the platform, only apply it when it's a feet tile
@@ -1071,58 +1068,60 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
/** about stopping /** about stopping
* for about get moving, see updateMovementControl */ * for about get moving, see updateMovementControl */
private fun setHorizontalFriction(delta: Double) { private fun setHorizontalFriction(delta: Float) {
val friction = if (isNoClip) val friction = if (isNoClip)
BASE_FRICTION * BlockCodex[Block.STONE].friction.frictionToMult() BASE_FRICTION * (actorValue.getAsDouble(AVKey.FRICTIONMULT) ?: 1.0) * BlockCodex[Block.STONE].friction.frictionToMult()
else { else {
// TODO status quo if !submerged else linearBlend(feetFriction, bodyFriction, submergedRatio) // TODO status quo if !submerged else linearBlend(feetFriction, bodyFriction, submergedRatio)
BASE_FRICTION * if (grounded) feetFriction else bodyFriction BASE_FRICTION * if (grounded) feetFriction else bodyFriction
} }
if (externalForce.x < 0) { if (externalV.x < 0) {
externalForce.x += friction externalV.x += friction
if (externalForce.x > 0) externalForce.x = 0.0 // compensate overshoot if (externalV.x > 0) externalV.x = 0.0 // compensate overshoot
} }
else if (externalForce.x > 0) { else if (externalV.x > 0) {
externalForce.x -= friction externalV.x -= friction
if (externalForce.x < 0) externalForce.x = 0.0 // compensate overshoot if (externalV.x < 0) externalV.x = 0.0 // compensate overshoot
} }
if (this is Controllable) { if (this is Controllable) {
if (controllerMoveDelta!!.x < 0) { if (controllerV!!.x < 0) {
controllerMoveDelta!!.x += friction controllerV!!.x += friction
if (controllerMoveDelta!!.x > 0) controllerMoveDelta!!.x = 0.0 if (controllerV!!.x > 0) controllerV!!.x = 0.0
} }
else if (controllerMoveDelta!!.x > 0) { else if (controllerV!!.x > 0) {
controllerMoveDelta!!.x -= friction controllerV!!.x -= friction
if (controllerMoveDelta!!.x < 0) controllerMoveDelta!!.x = 0.0 if (controllerV!!.x < 0) controllerV!!.x = 0.0
} }
} }
} }
private fun setVerticalFriction(delta: Double) { private fun setVerticalFriction(delta: Float) {
val friction = if (isNoClip) val friction = if (isNoClip)
BASE_FRICTION * BlockCodex[Block.STONE].friction.frictionToMult() BASE_FRICTION * (actorValue.getAsDouble(AVKey.FRICTIONMULT) ?: 1.0) * BlockCodex[Block.STONE].friction.frictionToMult()
else else
BASE_FRICTION * bodyFriction BASE_FRICTION * bodyFriction
// TODO wall friction (wall skid) similar to setHorizintalFriction ?
if (externalForce.y < 0) {
externalForce.y += friction if (externalV.y < 0) {
if (externalForce.y > 0) externalForce.y = 0.0 // compensate overshoot externalV.y += friction
if (externalV.y > 0) externalV.y = 0.0 // compensate overshoot
} }
else if (externalForce.y > 0) { else if (externalV.y > 0) {
externalForce.y -= friction externalV.y -= friction
if (externalForce.y < 0) externalForce.y = 0.0 // compensate overshoot if (externalV.y < 0) externalV.y = 0.0 // compensate overshoot
} }
if (this is Controllable) { if (this is Controllable) {
if (controllerMoveDelta!!.y < 0) { if (controllerV!!.y < 0) {
controllerMoveDelta!!.y += friction controllerV!!.y += friction
if (controllerMoveDelta!!.y > 0) controllerMoveDelta!!.y = 0.0 if (controllerV!!.y > 0) controllerV!!.y = 0.0
} }
else if (controllerMoveDelta!!.y > 0) { else if (controllerV!!.y > 0) {
controllerMoveDelta!!.y -= friction controllerV!!.y -= friction
if (controllerMoveDelta!!.y < 0) controllerMoveDelta!!.y = 0.0 if (controllerV!!.y < 0) controllerV!!.y = 0.0
} }
} }
} }
@@ -1343,10 +1342,11 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
override fun drawBody(batch: SpriteBatch) { override fun drawBody(batch: SpriteBatch) {
if (isVisible && sprite != null) { if (isVisible && sprite != null) {
if (!KeyToggler.isOn(Input.Keys.F12)) { //if (!KeyToggler.isOn(Input.Keys.F12)) {
BlendMode.resolve(drawMode, batch) BlendMode.resolve(drawMode, batch)
drawSpriteInGoodPosition(sprite!!, batch) drawSpriteInGoodPosition(sprite!!, batch)
} /*}
// ye olde tilewiseposition debugger, we don't use it anymore.
else { else {
batch.color = Color.NAVY batch.color = Color.NAVY
val hb = intTilewiseHitbox val hb = intTilewiseHitbox
@@ -1360,7 +1360,7 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
batch.color = Color.VIOLET batch.color = Color.VIOLET
batch.fillRect(hitbox.startX.toFloat(), hitbox.startY.toFloat(), hitbox.width.toFloat(), hitbox.height.toFloat()) batch.fillRect(hitbox.startX.toFloat(), hitbox.startY.toFloat(), hitbox.width.toFloat(), hitbox.height.toFloat())
} }*/
} }
} }
@@ -1443,8 +1443,8 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
field = value field = value
if (value) { if (value) {
externalForce.zero() externalV.zero()
controllerMoveDelta?.zero() controllerV?.zero()
} }
} }

View File

@@ -46,7 +46,7 @@ import org.luaj.vm2.*
*/ */
fun composeActorObject(actor: ActorWBMovable): LuaTable { fun composeActorObject(actor: ActorWBMovable): LuaTable {
val t: LuaTable = LuaTable() val t: LuaTable = LuaTable()
val moveDelta = actor.externalForce + actor.controllerMoveDelta val moveDelta = actor.externalV + actor.controllerV
t["name"] = actor.actorValue.getAsString(AVKey.NAME).toLua() t["name"] = actor.actorValue.getAsString(AVKey.NAME).toLua()
t["startX"] = actor.hitbox.centeredX.toLua() t["startX"] = actor.hitbox.centeredX.toLua()

View File

@@ -68,6 +68,8 @@ class IngameController(val ingame: Ingame) : InputAdapter() {
///////////////////// /////////////////////
} }
private var f12Down = false
override fun keyDown(keycode: Int): Boolean { override fun keyDown(keycode: Int): Boolean {
if (ingame.canPlayerControl) { if (ingame.canPlayerControl) {
@@ -90,14 +92,19 @@ class IngameController(val ingame: Ingame) : InputAdapter() {
ingame.uiContainer.forEach { it.keyDown(keycode) } // for KeyboardControlled UIcanvases ingame.uiContainer.forEach { it.keyDown(keycode) } // for KeyboardControlled UIcanvases
// Debug UIs // Debug UIs
if (keycode == Input.Keys.F3) {
ingame.debugWindow.toggleOpening()
}
if (keycode == Input.Keys.GRAVE) { if (keycode == Input.Keys.GRAVE) {
ingame.consoleHandler.toggleOpening() ingame.consoleHandler.toggleOpening()
} }
// screenshot key
if (keycode == Input.Keys.F12 && !f12Down) {
AppLoader.requestScreenshot()
ingame.sendNotification(arrayOf("Screenshot taken", ""))
f12Down = true
println("Screenshot taken.")
}
return true return true
} }
@@ -111,6 +118,10 @@ class IngameController(val ingame: Ingame) : InputAdapter() {
ingame.uiContainer.forEach { it.keyUp(keycode) } // for KeyboardControlled UIcanvases ingame.uiContainer.forEach { it.keyUp(keycode) } // for KeyboardControlled UIcanvases
// screenshot key
if (keycode == Input.Keys.F12) f12Down = false
return true return true
} }
@@ -131,10 +142,10 @@ class IngameController(val ingame: Ingame) : InputAdapter() {
if (ingame.uiContainer.map { if ((it.isOpening || it.isOpened) && it.mouseUp) 1 else 0 }.sum() == 0) { // no UI on the mouse, right? if (ingame.uiContainer.map { if ((it.isOpening || it.isOpened) && it.mouseUp) 1 else 0 }.sum() == 0) { // no UI on the mouse, right?
if (button == AppLoader.getConfigInt("mouseprimary")) { if (button == AppLoader.getConfigInt("mouseprimary")) {
ingame.worldPrimaryClickEnd(AppLoader.getSmoothDelta().toFloat()) ingame.worldPrimaryClickEnd(AppLoader.UPDATE_RATE.toFloat())
} }
if (button == AppLoader.getConfigInt("mousesecondary")) { if (button == AppLoader.getConfigInt("mousesecondary")) {
ingame.worldSecondaryClickEnd(AppLoader.getSmoothDelta().toFloat()) ingame.worldSecondaryClickEnd(AppLoader.UPDATE_RATE.toFloat())
} }
} }
} }
@@ -172,10 +183,10 @@ class IngameController(val ingame: Ingame) : InputAdapter() {
if (ingame.uiContainer.map { if ((it.isOpening || it.isOpened) && it.mouseUp) 1 else 0 }.sum() == 0) { // no UI on the mouse, right? if (ingame.uiContainer.map { if ((it.isOpening || it.isOpened) && it.mouseUp) 1 else 0 }.sum() == 0) { // no UI on the mouse, right?
if (button == AppLoader.getConfigInt("mouseprimary")) { if (button == AppLoader.getConfigInt("mouseprimary")) {
ingame.worldPrimaryClickStart(AppLoader.getSmoothDelta().toFloat()) ingame.worldPrimaryClickStart(AppLoader.UPDATE_RATE.toFloat())
} }
if (button == AppLoader.getConfigInt("mousesecondary")) { if (button == AppLoader.getConfigInt("mousesecondary")) {
ingame.worldSecondaryClickStart(AppLoader.getSmoothDelta().toFloat()) ingame.worldSecondaryClickStart(AppLoader.UPDATE_RATE.toFloat())
} }
} }
} }

View File

@@ -3,7 +3,7 @@ package net.torvald.terrarum.gamecontroller
/** /**
* Created by minjaesong on 2016-01-15. * Created by minjaesong on 2016-01-15.
*/ */
@Deprecated("Use Gdx.Input.Keys") /*@Deprecated("Use Gdx.Input.Keys")
object DeprecatedAsFuckKey { object DeprecatedAsFuckKey {
val RETURN = 28 val RETURN = 28
@@ -90,4 +90,4 @@ object DeprecatedAsFuckKey {
val PGDN = 209 val PGDN = 209
val HOME = 199 val HOME = 199
val END = 207 val END = 207
} }*/

View File

@@ -1,29 +1,7 @@
package net.torvald.terrarum.gameworld package net.torvald.terrarum.gameworld
import net.torvald.terrarum.blockproperties.Fluid
/** /**
* Created by minjaesong on 2016-08-06. * Created by minjaesong on 2016-08-06.
*/ */
object FluidCodex {
operator fun get(type: FluidType): FluidProp { // Use BlockCodex. --Torvald, 2019-01-27
return if (type sameAs Fluid.NULL)
nullProp
else
waterProp
}
// TODO temporary, should read from CSV
val nullProp = FluidProp.getNullProp()
val waterProp = FluidProp()
init {
waterProp.shadeColR = 0.1016f
waterProp.shadeColG = 0.0744f
waterProp.shadeColB = 0.0508f
waterProp.shadeColA = 0.0508f
waterProp.density = 1000
}
}

View File

@@ -1,14 +1,9 @@
package net.torvald.terrarum.gameworld package net.torvald.terrarum.gameworld
import com.badlogic.gdx.graphics.Color
import net.torvald.terrarum.blockproperties.Block
import net.torvald.terrarum.blockproperties.BlockCodex
import net.torvald.terrarum.blockproperties.BlockPropUtil
/** /**
* Created by minjaesong on 2018-12-29. * Created by minjaesong on 2018-12-29.
*/ */
class FluidProp { /*class FluidProp {
var density: Int = 0 var density: Int = 0
@@ -45,4 +40,4 @@ class FluidProp {
return p return p
} }
} }
} }*/

View File

@@ -2,6 +2,7 @@
package net.torvald.terrarum.gameworld package net.torvald.terrarum.gameworld
import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.Color
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.blockproperties.Block import net.torvald.terrarum.blockproperties.Block
import net.torvald.terrarum.blockproperties.BlockCodex import net.torvald.terrarum.blockproperties.BlockCodex
import net.torvald.terrarum.blockproperties.Fluid import net.torvald.terrarum.blockproperties.Fluid
@@ -220,9 +221,13 @@ open class GameWorld {
fun setTileWall(x: Int, y: Int, tile: Byte, damage: Int) { fun setTileWall(x: Int, y: Int, tile: Byte, damage: Int) {
val (x, y) = coerceXY(x, y) val (x, y) = coerceXY(x, y)
val oldWall = getTileFromWall(x, y)
layerWall.setTile(x, y, tile) layerWall.setTile(x, y, tile)
layerWallLowBits.setData(x, y, damage) layerWallLowBits.setData(x, y, damage)
wallDamages.remove(LandUtil.getBlockAddr(this, x, y)) wallDamages.remove(LandUtil.getBlockAddr(this, x, y))
if (oldWall != null)
Terrarum.ingame?.queueWallChangedEvent(oldWall, tile.toUint() * PairedMapLayer.RANGE + damage, LandUtil.getBlockAddr(this, x, y))
} }
/** /**
@@ -230,6 +235,7 @@ open class GameWorld {
*/ */
fun setTileTerrain(x: Int, y: Int, tile: Byte, damage: Int) { fun setTileTerrain(x: Int, y: Int, tile: Byte, damage: Int) {
val (x, y) = coerceXY(x, y) val (x, y) = coerceXY(x, y)
val oldTerrain = getTileFromTerrain(x, y)
layerTerrain.setTile(x, y, tile) layerTerrain.setTile(x, y, tile)
layerTerrainLowBits.setData(x, y, damage) layerTerrainLowBits.setData(x, y, damage)
val blockAddr = LandUtil.getBlockAddr(this, x, y) val blockAddr = LandUtil.getBlockAddr(this, x, y)
@@ -240,11 +246,18 @@ open class GameWorld {
fluidTypes.remove(blockAddr) fluidTypes.remove(blockAddr)
} }
// fluid tiles-item should be modified so that they will also place fluid onto their respective map // fluid tiles-item should be modified so that they will also place fluid onto their respective map
if (oldTerrain != null)
Terrarum.ingame?.queueTerrainChangedEvent(oldTerrain, tile.toUint() * PairedMapLayer.RANGE + damage, LandUtil.getBlockAddr(this, x, y))
} }
fun setTileWire(x: Int, y: Int, tile: Byte) { fun setTileWire(x: Int, y: Int, tile: Byte) {
val (x, y) = coerceXY(x, y) val (x, y) = coerceXY(x, y)
val oldWire = getTileFromWire(x, y)
layerWire.setTile(x, y, tile) layerWire.setTile(x, y, tile)
if (oldWire != null)
Terrarum.ingame?.queueWireChangedEvent(oldWire, tile.toUint(), LandUtil.getBlockAddr(this, x, y))
} }
fun getTileFrom(mode: Int, x: Int, y: Int): Int? { fun getTileFrom(mode: Int, x: Int, y: Int): Int? {
@@ -412,7 +425,7 @@ open class GameWorld {
data class FluidInfo(val type: FluidType, val amount: Float) { data class FluidInfo(val type: FluidType, val amount: Float) {
/** test if this fluid should be considered as one */ /** test if this fluid should be considered as one */
fun isFluid() = type != Fluid.NULL && amount >= WorldSimulator.FLUID_MIN_MASS fun isFluid() = type != Fluid.NULL && amount >= WorldSimulator.FLUID_MIN_MASS
fun getProp() = FluidCodex[type] fun getProp() = BlockCodex[type]
override fun toString() = "Fluid type: ${type.value}, amount: $amount" override fun toString() = "Fluid type: ${type.value}, amount: $amount"
} }
@@ -443,6 +456,7 @@ open class GameWorld {
} }
infix fun Int.fmod(other: Int) = Math.floorMod(this, other) infix fun Int.fmod(other: Int) = Math.floorMod(this, other)
infix fun Long.fmod(other: Long) = Math.floorMod(this, other)
infix fun Float.fmod(other: Float) = if (this >= 0f) this % other else (this % other) + other infix fun Float.fmod(other: Float) = if (this >= 0f) this % other else (this % other) + other
inline class FluidType(val value: Int) { inline class FluidType(val value: Int) {

View File

@@ -3,10 +3,10 @@ package net.torvald.terrarum.itemproperties
import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.Color
import net.torvald.random.HQRNG import net.torvald.random.HQRNG
import net.torvald.terrarum.ItemValue import net.torvald.terrarum.ItemValue
import net.torvald.terrarum.modulebasegame.gameactors.ActorInventory
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
import net.torvald.terrarum.itemproperties.ItemCodex.ITEM_DYNAMIC import net.torvald.terrarum.itemproperties.ItemCodex.ITEM_DYNAMIC
import net.torvald.terrarum.langpack.Lang import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.modulebasegame.gameactors.ActorInventory
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
typealias ItemID = Int typealias ItemID = Int
@@ -207,28 +207,39 @@ abstract class GameItem : Comparable<GameItem>, Cloneable {
object EquipPosition { object EquipPosition {
@JvmStatic val NULL = -1 @JvmStatic val NULL = -1
@JvmStatic val ARMOUR = 0
// you can add alias to address something like LEGGINGS, BREASTPLATE, RINGS, NECKLACES, etc. // you can add alias to address something like LEGGINGS, BREASTPLATE, RINGS, NECKLACES, etc.
@JvmStatic val BODY_BACK = 1 // wings, jetpacks, etc.
@JvmStatic val BODY_BUFF2 = 2
@JvmStatic val BODY_BUFF3 = 3
@JvmStatic val BODY_BUFF4 = 4
@JvmStatic val BODY_BUFF5 = 5
@JvmStatic val BODY_BUFF6 = 6
@JvmStatic val BODY_BUFF7 = 7
@JvmStatic val BODY_BUFF8 = 8
@JvmStatic val HAND_GRIP = 9 @JvmStatic val BODY_ARMOUR = 0
@JvmStatic val HAND_GAUNTLET = 10 @JvmStatic val BODY_FOOTWEAR = 1 // wings, jetpacks, etc.
@JvmStatic val HAND_BUFF2 = 11
@JvmStatic val HAND_BUFF3 = 12
@JvmStatic val HAND_BUFF4 = 13
@JvmStatic val FOOTWEAR = 14 @JvmStatic val HEADGEAR = 2
@JvmStatic val HAND_GAUNTLET = 3
@JvmStatic val HEADGEAR = 15 @JvmStatic val HAND_GRIP = 4
@JvmStatic val TOOL_HOOKSHOT = 5
@JvmStatic val INDEX_MAX = 15 @JvmStatic val BODY_BUFF1 = 6
@JvmStatic val BODY_BUFF2 = 8
@JvmStatic val BODY_BUFF3 = 10
@JvmStatic val HAND_BUFF1 = 7
@JvmStatic val HAND_BUFF2 = 9
@JvmStatic val HAND_BUFF3 = 11
// invisible from the inventory UI
// intended for semi-permanant (de)buff (e.g. lifetime achivement, curse)
// can be done with actorvalue and some more code, but it's easier to just make
// such (de)buffs as an item.
@JvmStatic val STIGMA_1 = 12
@JvmStatic val STIGMA_2 = 13
@JvmStatic val STIGMA_3 = 14
@JvmStatic val STIGMA_4 = 15
@JvmStatic val STIGMA_5 = 16
@JvmStatic val STIGMA_6 = 17
@JvmStatic val STIGMA_7 = 18
@JvmStatic val STIGMA_8 = 19
@JvmStatic val INDEX_MAX = 19
} }
object Category { object Category {

View File

@@ -192,12 +192,38 @@ object ItemCodex {
override fun startSecondaryUse(delta: Float): Boolean { override fun startSecondaryUse(delta: Float): Boolean {
val ingame = Terrarum.ingame!! as Ingame // must be in here val ingame = Terrarum.ingame!! as Ingame // must be in here
ingame.world.setFluid(Terrarum.mouseTileX, Terrarum.mouseTileY, Fluid.WATER, 1f) ingame.world.setFluid(Terrarum.mouseTileX, Terrarum.mouseTileY, Fluid.WATER, 4f)
return true return true
} }
} }
// test lava bucket
itemCodex[9001] = object : GameItem() {
override var dynamicID: ItemID = 9001
override val originalID: ItemID = 9001
override val isUnique: Boolean = true
override val originalName: String = "Infinite Lava Bucket"
override var baseMass: Double = 1000.0
override var baseToolSize: Double? = null
override var inventoryCategory: String = "tool"
override var stackable: Boolean = false
override val isDynamic: Boolean = false
override val material: Material = Material(1,1,1,1,1,1,1,1,1,1.0)
override val equipPosition: Int = EquipPosition.HAND_GRIP
override fun startSecondaryUse(delta: Float): Boolean {
val ingame = Terrarum.ingame!! as Ingame // must be in here
ingame.world.setFluid(Terrarum.mouseTileX, Terrarum.mouseTileY, Fluid.LAVA, 4f)
return true
}
}
// read from save (if applicable) and fill dynamicItemDescription // read from save (if applicable) and fill dynamicItemDescription
@@ -233,23 +259,27 @@ object ItemCodex {
fun getItemImage(item: GameItem?): TextureRegion? { fun getItemImage(item: GameItem?): TextureRegion? {
if (item == null) return null if (item == null) return null
return getItemImage(item.originalID)
}
fun getItemImage(itemOriginalID: Int): TextureRegion {
// terrain // terrain
if (item.originalID in ITEM_TILES) { if (itemOriginalID in ITEM_TILES) {
return BlocksDrawer.tilesTerrain.get( return BlocksDrawer.tilesTerrain.get(
(item.originalID % 16) * 16, (itemOriginalID % 16) * 16,
item.originalID / 16 itemOriginalID / 16
) )
} }
// wall // wall
else if (item.originalID in ITEM_WALLS) { else if (itemOriginalID in ITEM_WALLS) {
return BlocksDrawer.tileItemWall.get( return BlocksDrawer.tileItemWall.get(
(item.originalID.minus(ITEM_WALLS.first) % 16) * 16, (itemOriginalID.minus(ITEM_WALLS.first) % 16),
(item.originalID.minus(ITEM_WALLS.first) / 16) (itemOriginalID.minus(ITEM_WALLS.first) / 16)
) )
} }
// wire // wire
else if (item.originalID in ITEM_WIRES) { else if (itemOriginalID in ITEM_WIRES) {
return BlocksDrawer.tilesWire.get((item.originalID % 16) * 16, item.originalID / 16) return BlocksDrawer.tilesWire.get((itemOriginalID % 16) * 16, itemOriginalID / 16)
} }
// TODO get it real, using originalID...? // TODO get it real, using originalID...?
else else

View File

@@ -118,7 +118,7 @@ object Lang {
// special treatment // special treatment
if (key.startsWith("MENU_LABEL_PRESS_START_SYMBOL")) if (key.startsWith("MENU_LABEL_PRESS_START_SYMBOL"))
return ret2.replace('>', Terrarum.joypadLabelStart).capitalize() return ret2.replace('>', Terrarum.gamepadLabelStart).capitalize()
return if (key.getEndTag().contains("bg")) return if (key.getEndTag().contains("bg"))
"${AppLoader.fontGame.charsetOverrideBulgarian}${ret2.capitalize()}${AppLoader.fontGame.charsetOverrideDefault}" "${AppLoader.fontGame.charsetOverrideBulgarian}${ret2.capitalize()}${AppLoader.fontGame.charsetOverrideDefault}"

View File

@@ -4,23 +4,20 @@ import com.badlogic.gdx.Gdx
import com.badlogic.gdx.InputAdapter import com.badlogic.gdx.InputAdapter
import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.terrarum.AppLoader import net.torvald.terrarum.*
import net.torvald.terrarum.IngameInstance
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.Yaml
import net.torvald.terrarum.blockproperties.Block import net.torvald.terrarum.blockproperties.Block
import net.torvald.terrarum.gameactors.* import net.torvald.terrarum.gameactors.*
import net.torvald.terrarum.gamecontroller.KeyToggler
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension
import net.torvald.terrarum.modulebasegame.gameworld.WorldTime import net.torvald.terrarum.modulebasegame.gameworld.WorldTime
import net.torvald.terrarum.modulebasegame.ui.Notification import net.torvald.terrarum.modulebasegame.ui.Notification
import net.torvald.terrarum.modulebasegame.ui.UIEditorPalette
import net.torvald.terrarum.modulebasegame.weather.WeatherMixer
import net.torvald.terrarum.ui.UICanvas import net.torvald.terrarum.ui.UICanvas
import net.torvald.terrarum.ui.UINSMenu import net.torvald.terrarum.ui.UINSMenu
import net.torvald.terrarum.worlddrawer.LightmapRenderer import net.torvald.terrarum.worlddrawer.LightmapRenderer
import net.torvald.terrarum.worlddrawer.WorldCamera import net.torvald.terrarum.worlddrawer.WorldCamera
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
import kotlin.system.measureNanoTime
/** /**
* Created by minjaesong on 2018-07-06. * Created by minjaesong on 2018-07-06.
@@ -29,24 +26,26 @@ class BuildingMaker(batch: SpriteBatch) : IngameInstance(batch) {
private val menuYaml = Yaml(""" private val menuYaml = Yaml("""
- File - File
- New - New flat ter.
- New rand. ter.
- Export… - Export…
- Export sel… - Export sel…
- Import… - Import…
- Save world - Save terrain
- Load world - Load terrain
- Exit to Title : net.torvald.terrarum.modulebasegame.YamlCommandExit
- Tool - Tool
- Pencil - Pencil : net.torvald.terrarum.modulebasegame.YamlCommandToolPencil
- Eyedropper - Eyedropper
- Select mrq. - Select mrq. : net.torvald.terrarum.modulebasegame.YamlCommandToolMarquee
- Move - Move
- Undo - Undo
- Redo - Redo
- Time - Time
- Morning - Morning : net.torvald.terrarum.modulebasegame.YamlCommandSetTimeMorning
- Noon - Noon : net.torvald.terrarum.modulebasegame.YamlCommandSetTimeNoon
- Dusk - Dusk : net.torvald.terrarum.modulebasegame.YamlCommandSetTimeDusk
- Night - Night : net.torvald.terrarum.modulebasegame.YamlCommandSetTimeNight
- Set… - Set…
- Weather - Weather
- Sunny - Sunny
@@ -72,6 +71,8 @@ class BuildingMaker(batch: SpriteBatch) : IngameInstance(batch) {
} }
} }
// set time to summer
gameWorld.time.addTime(WorldTime.DAY_LENGTH * 32)
world = gameWorld world = gameWorld
} }
@@ -81,23 +82,29 @@ class BuildingMaker(batch: SpriteBatch) : IngameInstance(batch) {
val uiToolbox = UINSMenu("Menu", 100, menuYaml) val uiToolbox = UINSMenu("Menu", 100, menuYaml)
val notifier = Notification() val notifier = Notification()
val uiPalette = UIEditorPalette()
val uiContainer = ArrayList<UICanvas>() val uiContainer = ArrayList<UICanvas>()
var currentPenMode = PENMODE_PENCIL
val blockPointingCursor = object : ActorWithBody(Actor.RenderOrder.OVERLAY) { val blockPointingCursor = object : ActorWithBody(Actor.RenderOrder.OVERLAY) {
override var referenceID: ActorID? = Terrarum.generateUniqueReferenceID(renderOrder) override var referenceID: ActorID? = Terrarum.generateUniqueReferenceID(renderOrder)
val body = TextureRegionPack(Gdx.files.internal("assets/graphics/blocks/block_markings_common.tga"), 16, 16) val body = TextureRegionPack(Gdx.files.internal("assets/graphics/blocks/block_markings_common.tga"), 16, 16)
override val hitbox = Hitbox(0.0, 0.0, 16.0, 16.0) override val hitbox = Hitbox(0.0, 0.0, 16.0, 16.0)
init { init {
this.actorValue[AVKey.LUMR] = 1.0 this.actorValue[AVKey.LUMR] = 1.0
this.actorValue[AVKey.LUMG] = 1.0 this.actorValue[AVKey.LUMG] = 1.0
} }
override fun drawBody(batch: SpriteBatch) { override fun drawBody(batch: SpriteBatch) {
batch.color = Color.YELLOW batch.color = toolCursorColour[currentPenMode]
batch.draw(body.get(0, 0), hitbox.startX.toFloat(), hitbox.startY.toFloat()) batch.draw(body.get(currentPenMode, 0), hitbox.startX.toFloat(), hitbox.startY.toFloat())
} }
override fun drawGlow(batch: SpriteBatch) { } override fun drawGlow(batch: SpriteBatch) { }
@@ -120,8 +127,15 @@ class BuildingMaker(batch: SpriteBatch) : IngameInstance(batch) {
} }
} }
protected var updateDeltaCounter = 0.0 companion object {
protected val updateRate = 1.0 / Terrarum.TARGET_INTERNAL_FPS const val PENMODE_PENCIL = 0
const val PENMODE_MARQUEE = 1
val toolCursorColour = arrayOf(
Color.YELLOW,
Color.MAGENTA
)
}
private val actorsRenderOverlay = ArrayList<ActorWithBody>() private val actorsRenderOverlay = ArrayList<ActorWithBody>()
@@ -132,12 +146,18 @@ class BuildingMaker(batch: SpriteBatch) : IngameInstance(batch) {
actorsRenderOverlay.add(blockPointingCursor) actorsRenderOverlay.add(blockPointingCursor)
uiContainer.add(uiToolbox) uiContainer.add(uiToolbox)
uiContainer.add(uiPalette)
uiContainer.add(notifier) uiContainer.add(notifier)
uiToolbox.setPosition(0, 0) uiToolbox.setPosition(0, 0)
uiToolbox.isVisible = true uiToolbox.isVisible = true
uiToolbox.invocationArgument = arrayOf(this)
uiPalette.setPosition(Terrarum.WIDTH - uiPalette.width, 0)
uiPalette.isVisible = true
notifier.setPosition( notifier.setPosition(
(Terrarum.WIDTH - notifier.width) / 2, Terrarum.HEIGHT - notifier.height) (Terrarum.WIDTH - notifier.width) / 2, Terrarum.HEIGHT - notifier.height)
@@ -154,43 +174,62 @@ class BuildingMaker(batch: SpriteBatch) : IngameInstance(batch) {
super.show() super.show()
} }
private var updateAkku = 0.0
override fun render(delta: Float) { override fun render(delta: Float) {
Gdx.graphics.setTitle(Ingame.getCanonicalTitle()) Gdx.graphics.setTitle(Ingame.getCanonicalTitle())
// ASYNCHRONOUS UPDATE AND RENDER // // ASYNCHRONOUS UPDATE AND RENDER //
val dt = Gdx.graphics.deltaTime
updateAkku += dt
// async update var i = 0L
updateDeltaCounter += delta while (updateAkku >= delta) {
if (delta < 1f / 10f) { // discard async if measured FPS <= 10 AppLoader.measureDebugTime("Ingame.update") { updateGame(delta) }
var updateTries = 0 updateAkku -= delta
while (updateDeltaCounter >= updateRate) { i += 1
updateGame(delta)
updateDeltaCounter -= updateRate
updateTries++
}
}
else {
updateGame(delta)
} }
AppLoader.setDebugTime("Ingame.updateCounter", i)
// render? just do it anyway // render? just do it anyway
renderGame() AppLoader.measureDebugTime("Ingame.render") { renderGame() }
AppLoader.setDebugTime("Ingame.render-Light",
(AppLoader.debugTimers["Ingame.render"] as Long) - ((AppLoader.debugTimers["Renderer.LightTotal"] as? Long) ?: 0)
)
} }
private fun updateGame(delta: Float) { private fun updateGame(delta: Float) {
KeyToggler.update(false) var mouseOnUI = false
WeatherMixer.update(delta, actorNowPlaying, gameWorld)
blockPointingCursor.update(delta) blockPointingCursor.update(delta)
actorNowPlaying?.update(delta) actorNowPlaying?.update(delta)
uiContainer.forEach { it.update(delta) } uiContainer.forEach {
it.update(delta)
if (it.isVisible && it.mouseUp) {
mouseOnUI = true
}
}
WorldCamera.update(world, actorNowPlaying) WorldCamera.update(world, actorNowPlaying)
// make pen work HERE
if (Gdx.input.isTouched && !mouseOnUI) {
makePenWork(Terrarum.mouseTileX, Terrarum.mouseTileY)
// TODO drag support using bresenham's algo
// for some reason it just doesn't work...
}
} }
private fun renderGame() { private fun renderGame() {
IngameRenderer(world as GameWorldExtension, actorsRenderOverlay = actorsRenderOverlay, uisToDraw = uiContainer) IngameRenderer.invoke(world as GameWorldExtension, actorsRenderOverlay = actorsRenderOverlay, uisToDraw = uiContainer)
} }
override fun resize(width: Int, height: Int) { override fun resize(width: Int, height: Int) {
@@ -198,11 +237,24 @@ class BuildingMaker(batch: SpriteBatch) : IngameInstance(batch) {
uiToolbox.setPosition(0, 0) uiToolbox.setPosition(0, 0)
notifier.setPosition( notifier.setPosition(
(Terrarum.WIDTH - notifier.width) / 2, Terrarum.HEIGHT - notifier.height) (Terrarum.WIDTH - notifier.width) / 2, Terrarum.HEIGHT - notifier.height)
println("[BuildingMaker] Resize event") println("[BuildingMaker] Resize event")
} }
override fun dispose() { override fun dispose() {
IngameRenderer.dispose() blockPointingCursor.dispose()
}
private fun makePenWork(worldTileX: Int, worldTileY: Int) {
val world = gameWorld
val palSelection = uiPalette.fore
when (currentPenMode) {
// test paint terrain layer
PENMODE_PENCIL -> {
world.setTileTerrain(worldTileX, worldTileY, palSelection)
}
}
} }
} }
@@ -232,6 +284,7 @@ class BuildingMakerController(val screen: BuildingMaker) : InputAdapter() {
return true return true
} }
// let left mouse button to paint, because that's how graphic tablets work
override fun touchDragged(screenX: Int, screenY: Int, pointer: Int): Boolean { override fun touchDragged(screenX: Int, screenY: Int, pointer: Int): Boolean {
screen.uiContainer.forEach { it.touchDragged(screenX, screenY, pointer) } screen.uiContainer.forEach { it.touchDragged(screenX, screenY, pointer) }
return true return true
@@ -260,10 +313,12 @@ class MovableWorldCamera : ActorHumanoid(0, usePhysics = false) {
actorValue[AVKey.SPEED] = 8.0 actorValue[AVKey.SPEED] = 8.0
actorValue[AVKey.SPEEDBUFF] = 1.0 actorValue[AVKey.SPEEDBUFF] = 1.0
actorValue[AVKey.ACCEL] = ActorHumanoid.WALK_ACCEL_BASE actorValue[AVKey.ACCEL] = ActorHumanoid.WALK_ACCEL_BASE
actorValue[AVKey.ACCELBUFF] = 1.0 actorValue[AVKey.ACCELBUFF] = 4.0
actorValue[AVKey.JUMPPOWER] = 0.0 actorValue[AVKey.JUMPPOWER] = 0.0
actorValue[AVKey.FRICTIONMULT] = 4.0
} }
override fun drawBody(batch: SpriteBatch) { override fun drawBody(batch: SpriteBatch) {
} }
@@ -274,3 +329,45 @@ class MovableWorldCamera : ActorHumanoid(0, usePhysics = false) {
} }
} }
class YamlCommandExit : YamlInvokable {
override fun invoke(args: Array<Any>) {
Terrarum.setScreen(TitleScreen(Terrarum.batch))
}
}
class YamlCommandSetTimeMorning : YamlInvokable {
override fun invoke(args: Array<Any>) {
(args[0] as BuildingMaker).gameWorld.time.setTimeOfToday(WorldTime.parseTime("7h00"))
}
}
class YamlCommandSetTimeNoon : YamlInvokable {
override fun invoke(args: Array<Any>) {
(args[0] as BuildingMaker).gameWorld.time.setTimeOfToday(WorldTime.parseTime("12h30"))
}
}
class YamlCommandSetTimeDusk : YamlInvokable {
override fun invoke(args: Array<Any>) {
(args[0] as BuildingMaker).gameWorld.time.setTimeOfToday(WorldTime.parseTime("18h40"))
}
}
class YamlCommandSetTimeNight : YamlInvokable {
override fun invoke(args: Array<Any>) {
(args[0] as BuildingMaker).gameWorld.time.setTimeOfToday(WorldTime.parseTime("0h30"))
}
}
class YamlCommandToolPencil : YamlInvokable {
override fun invoke(args: Array<Any>) {
(args[0] as BuildingMaker).currentPenMode = BuildingMaker.PENMODE_PENCIL
}
}
class YamlCommandToolMarquee : YamlInvokable {
override fun invoke(args: Array<Any>) {
(args[0] as BuildingMaker).currentPenMode = BuildingMaker.PENMODE_MARQUEE
}
}

View File

@@ -13,7 +13,6 @@ import net.torvald.terrarum.console.Authenticator
import net.torvald.terrarum.gameactors.Actor import net.torvald.terrarum.gameactors.Actor
import net.torvald.terrarum.gameactors.ActorWithBody import net.torvald.terrarum.gameactors.ActorWithBody
import net.torvald.terrarum.gamecontroller.IngameController import net.torvald.terrarum.gamecontroller.IngameController
import net.torvald.terrarum.gamecontroller.KeyToggler
import net.torvald.terrarum.gameworld.GameWorld import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.itemproperties.GameItem import net.torvald.terrarum.itemproperties.GameItem
import net.torvald.terrarum.modulebasegame.console.AVTracker import net.torvald.terrarum.modulebasegame.console.AVTracker
@@ -22,13 +21,10 @@ import net.torvald.terrarum.modulebasegame.gameactors.*
import net.torvald.terrarum.modulebasegame.gameactors.physicssolver.CollisionSolver import net.torvald.terrarum.modulebasegame.gameactors.physicssolver.CollisionSolver
import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension
import net.torvald.terrarum.modulebasegame.gameworld.WorldSimulator import net.torvald.terrarum.modulebasegame.gameworld.WorldSimulator
import net.torvald.terrarum.modulebasegame.imagefont.Watch7SegMain
import net.torvald.terrarum.modulebasegame.imagefont.WatchDotAlph
import net.torvald.terrarum.modulebasegame.ui.* import net.torvald.terrarum.modulebasegame.ui.*
import net.torvald.terrarum.modulebasegame.weather.WeatherMixer import net.torvald.terrarum.modulebasegame.weather.WeatherMixer
import net.torvald.terrarum.modulebasegame.worldgenerator.RoguelikeRandomiser import net.torvald.terrarum.modulebasegame.worldgenerator.RoguelikeRandomiser
import net.torvald.terrarum.modulebasegame.worldgenerator.WorldGenerator import net.torvald.terrarum.modulebasegame.worldgenerator.WorldGenerator
import net.torvald.terrarum.ui.BasicDebugInfoWindow
import net.torvald.terrarum.ui.ConsoleWindow import net.torvald.terrarum.ui.ConsoleWindow
import net.torvald.terrarum.ui.UICanvas import net.torvald.terrarum.ui.UICanvas
import net.torvald.terrarum.worlddrawer.FeaturesDrawer import net.torvald.terrarum.worlddrawer.FeaturesDrawer
@@ -36,7 +32,6 @@ import net.torvald.terrarum.worlddrawer.LightmapRenderer
import net.torvald.terrarum.worlddrawer.WorldCamera import net.torvald.terrarum.worlddrawer.WorldCamera
import java.util.* import java.util.*
import java.util.concurrent.locks.ReentrantLock import java.util.concurrent.locks.ReentrantLock
import kotlin.system.measureNanoTime
/** /**
@@ -66,6 +61,11 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
private val actorsRenderFront = ArrayList<ActorWithBody>(ACTORCONTAINER_INITIAL_SIZE) private val actorsRenderFront = ArrayList<ActorWithBody>(ACTORCONTAINER_INITIAL_SIZE)
private val actorsRenderOverlay= ArrayList<ActorWithBody>(ACTORCONTAINER_INITIAL_SIZE) private val actorsRenderOverlay= ArrayList<ActorWithBody>(ACTORCONTAINER_INITIAL_SIZE)
private var visibleActorsRenderBehind: List<ActorWithBody> = ArrayList(1)
private var visibleActorsRenderMiddle: List<ActorWithBody> = ArrayList(1)
private var visibleActorsRenderMidTop: List<ActorWithBody> = ArrayList(1)
private var visibleActorsRenderFront: List<ActorWithBody> = ArrayList(1)
private var visibleActorsRenderOverlay: List<ActorWithBody> = ArrayList(1)
//var screenZoom = 1.0f // definition moved to IngameInstance //var screenZoom = 1.0f // definition moved to IngameInstance
//val ZOOM_MAXIMUM = 4.0f // definition moved to IngameInstance //val ZOOM_MAXIMUM = 4.0f // definition moved to IngameInstance
@@ -82,7 +82,7 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
fun getCanonicalTitle() = AppLoader.GAME_NAME + fun getCanonicalTitle() = AppLoader.GAME_NAME +
" — F: ${Gdx.graphics.framesPerSecond}" + " — F: ${Gdx.graphics.framesPerSecond}" +
if (AppLoader.IS_DEVELOPMENT_BUILD) if (AppLoader.IS_DEVELOPMENT_BUILD)
"t${Terrarum.updateRateStr} / RT${Terrarum.renderRateStr})" + "F${Terrarum.updateRateStr})" +
" — M: J${Terrarum.memJavaHeap}M / N${Terrarum.memNativeHeap}M / X${Terrarum.memXmx}M" " — M: J${Terrarum.memJavaHeap}M / N${Terrarum.memNativeHeap}M / X${Terrarum.memXmx}M"
else else
"" ""
@@ -95,7 +95,6 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
lateinit var debugWindow: UICanvas
lateinit var notifier: UICanvas lateinit var notifier: UICanvas
lateinit var uiPieMenu: UICanvas lateinit var uiPieMenu: UICanvas
@@ -276,31 +275,18 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
consoleHandler.setPosition(0, 0) consoleHandler.setPosition(0, 0)
// init debug window
debugWindow = BasicDebugInfoWindow()
debugWindow.setPosition(0, 0)
// init notifier // init notifier
notifier = Notification() notifier = Notification()
notifier.setPosition( notifier.setPosition(
(Terrarum.WIDTH - notifier.width) / 2, Terrarum.HEIGHT - notifier.height) (Terrarum.WIDTH - notifier.width) / 2,
Terrarum.HEIGHT - notifier.height - AppLoader.getTvSafeGraphicsHeight()
)
// >- queue up game UIs that should pause the world -< // >- queue up game UIs that should pause the world -<
// inventory uiInventoryPlayer = UIInventoryFull(actorNowPlaying!!,
/*uiInventoryPlayer = UIInventory(player,
width = 900,
height = Terrarum.HEIGHT - 160,
categoryWidth = 210,
toggleKeyLiteral = AppLoader.getConfigInt("keyinventory")
)*/
/*uiInventoryPlayer.setPosition(
-uiInventoryPlayer.width,
70
)*/
uiInventoryPlayer = UIInventoryFull(actorNowPlaying,
toggleKeyLiteral = AppLoader.getConfigInt("keyinventory") toggleKeyLiteral = AppLoader.getConfigInt("keyinventory")
) )
uiInventoryPlayer.setPosition(0, 0) uiInventoryPlayer.setPosition(0, 0)
@@ -309,7 +295,7 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
// quick bar // quick bar
uiQuickBar = UIQuickslotBar() uiQuickBar = UIQuickslotBar()
uiQuickBar.isVisible = true uiQuickBar.isVisible = true
uiQuickBar.setPosition((Terrarum.WIDTH - uiQuickBar.width) / 2, 8) uiQuickBar.setPosition((Terrarum.WIDTH - uiQuickBar.width) / 2, AppLoader.getTvSafeGraphicsHeight())
// pie menu // pie menu
uiPieMenu = uiQuickslotPie() uiPieMenu = uiQuickslotPie()
@@ -332,7 +318,10 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
uiWatchTierOne = UITierOneWatch(actorNowPlaying) uiWatchTierOne = UITierOneWatch(actorNowPlaying)
uiWatchTierOne.setAsAlwaysVisible() uiWatchTierOne.setAsAlwaysVisible()
uiWatchTierOne.setPosition(Terrarum.WIDTH - uiWatchTierOne.width, uiWatchBasic.height - 2) uiWatchTierOne.setPosition(
((Terrarum.WIDTH - AppLoader.getTvSafeActionWidth()) - (uiQuickBar.posX + uiQuickBar.width) - uiWatchTierOne.width) / 2 + (uiQuickBar.posX + uiQuickBar.width),
AppLoader.getTvSafeGraphicsHeight() + 8
)
uiTooltip = UITooltip() uiTooltip = UITooltip()
@@ -373,12 +362,12 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
// these need to appear on top of any others // these need to appear on top of any others
uiContainer.add(notifier) uiContainer.add(notifier)
uiContainer.add(debugWindow)
LightmapRenderer.fireRecalculateEvent() LightmapRenderer.fireRecalculateEvent()
AppLoader.setDebugTime("Ingame.updateCounter", 0)
@@ -408,7 +397,7 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
itemOnGrip?.endSecondaryUse(delta) itemOnGrip?.endSecondaryUse(delta)
} }
protected val renderRate = Terrarum.renderRate
private var firstTimeRun = true private var firstTimeRun = true
@@ -421,7 +410,7 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
} }
} }
private var countdownToDeltaReset = 15 // number of frames private var updateAkku = 0.0
override fun render(delta: Float) { override fun render(delta: Float) {
// Q&D solution for LoadScreen and Ingame, where while LoadScreen is working, Ingame now no longer has GL Context // Q&D solution for LoadScreen and Ingame, where while LoadScreen is working, Ingame now no longer has GL Context
@@ -442,40 +431,28 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
gameFullyLoaded = true gameFullyLoaded = true
} }
if (countdownToDeltaReset >= 0) {3
if (countdownToDeltaReset == 0) {
AppLoader.resetDeltaSmoothingHistory()
}
countdownToDeltaReset -= 1
}
// ASYNCHRONOUS UPDATE AND RENDER // // ASYNCHRONOUS UPDATE AND RENDER //
/** UPDATE CODE GOES HERE */ /** UPDATE CODE GOES HERE */
val dt = Gdx.graphics.deltaTime
updateAkku += dt
var i = 0L
while (updateAkku >= delta) {
if (false && AppLoader.getConfigBoolean("multithread")) { // NO MULTITHREADING: camera don't like concurrent modification (jittery actor movements) AppLoader.measureDebugTime("Ingame.update") { updateGame(delta) }
if (firstTimeRun || updateThreadWrapper.state == Thread.State.TERMINATED) { updateAkku -= delta
updateThreadWrapper = Thread(ingameUpdateThread, "Terrarum UpdateThread") i += 1
updateThreadWrapper.start()
if (firstTimeRun) firstTimeRun = false
}
// else, NOP;
}
else {
AppLoader.debugTimers["Ingame.update"] = measureNanoTime { updateGame(delta) }
} }
AppLoader.setDebugTime("Ingame.updateCounter", i)
/** RENDER CODE GOES HERE */ /** RENDER CODE GOES HERE */
AppLoader.debugTimers["Ingame.render"] = measureNanoTime { renderGame() } AppLoader.measureDebugTime("Ingame.render") { renderGame() }
AppLoader.debugTimers["Ingame.render-Light"] = AppLoader.setDebugTime("Ingame.render-Light",
(AppLoader.debugTimers["Ingame.render"] as Long) - ((AppLoader.debugTimers["Renderer.LightTotal"] as? Long) ?: 0) (AppLoader.debugTimers["Ingame.render"] as Long) - ((AppLoader.debugTimers["Renderer.LightTotal"] as? Long) ?: 0)
)
} }
protected fun updateGame(delta: Float) { protected fun updateGame(delta: Float) {
@@ -484,7 +461,6 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
particlesActive = 0 particlesActive = 0
KeyToggler.update()
ingameController.update(delta) ingameController.update(delta)
@@ -505,8 +481,6 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
// camera-related updates // // camera-related updates //
//////////////////////////// ////////////////////////////
FeaturesDrawer.update(delta) FeaturesDrawer.update(delta)
WorldCamera.update(gameworld, actorNowPlaying)
/////////////////////////// ///////////////////////////
@@ -522,6 +496,14 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
particlesContainer.forEach { if (!it.flagDespawn) particlesActive++; it.update(delta) } particlesContainer.forEach { if (!it.flagDespawn) particlesActive++; it.update(delta) }
// TODO thread pool(?) // TODO thread pool(?)
CollisionSolver.process() CollisionSolver.process()
WorldCamera.update(gameworld, actorNowPlaying)
// completely consume block change queues because why not
terrainChangeQueue.clear()
wallChangeQueue.clear()
wireChangeQueue.clear()
} }
@@ -543,13 +525,15 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
private fun renderGame() { private fun renderGame() {
Gdx.graphics.setTitle(getCanonicalTitle()) Gdx.graphics.setTitle(getCanonicalTitle())
filterVisibleActors()
IngameRenderer.invoke( IngameRenderer.invoke(
world as GameWorldExtension, world as GameWorldExtension,
actorsRenderBehind, visibleActorsRenderBehind,
actorsRenderMiddle, visibleActorsRenderMiddle,
actorsRenderMidTop, visibleActorsRenderMidTop,
actorsRenderFront, visibleActorsRenderFront,
actorsRenderOverlay, visibleActorsRenderOverlay,
particlesContainer, particlesContainer,
actorNowPlaying, actorNowPlaying,
uiContainer uiContainer
@@ -557,6 +541,14 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
} }
private fun filterVisibleActors() {
visibleActorsRenderBehind = actorsRenderBehind.filter { it.inScreen() }
visibleActorsRenderMiddle = actorsRenderMiddle.filter { it.inScreen() }
visibleActorsRenderMidTop = actorsRenderMidTop.filter { it.inScreen() }
visibleActorsRenderFront = actorsRenderFront.filter { it.inScreen() }
visibleActorsRenderOverlay=actorsRenderOverlay.filter { it.inScreen() }
}
private fun repossessActor() { private fun repossessActor() {
// check if currently pocessed actor is removed from game // check if currently pocessed actor is removed from game
if (!theGameHasActor(actorNowPlaying)) { if (!theGameHasActor(actorNowPlaying)) {
@@ -672,6 +664,12 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
} }
} }
} }
if (it is CuedByTerrainChange) {
terrainChangeQueue.forEach { cue ->
it.updateForWorldChange(cue)
}
}
} }
} }
actorNowPlaying?.update(delta) actorNowPlaying?.update(delta)
@@ -886,7 +884,7 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
} }
override fun hide() { override fun hide() {
dispose() uiContainer.forEach { it.handler.dispose() }
} }
@@ -914,6 +912,7 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
notifier.setPosition( notifier.setPosition(
(Terrarum.WIDTH - notifier.width) / 2, Terrarum.HEIGHT - notifier.height) (Terrarum.WIDTH - notifier.width) / 2, Terrarum.HEIGHT - notifier.height)
uiQuickBar.setPosition((Terrarum.WIDTH - uiQuickBar.width) / 2, AppLoader.getTvSafeGraphicsHeight())
// inventory // inventory
/*uiInventoryPlayer = /*uiInventoryPlayer =
@@ -926,7 +925,11 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
// basic watch-style notification bar (temperature, new mail) // basic watch-style notification bar (temperature, new mail)
uiWatchBasic.setPosition(Terrarum.WIDTH - uiWatchBasic.width, 0) uiWatchBasic.setPosition(Terrarum.WIDTH - uiWatchBasic.width, 0)
uiWatchTierOne.setPosition(Terrarum.WIDTH - uiWatchTierOne.width, uiWatchBasic.height - 2) uiWatchTierOne.setPosition(
((Terrarum.WIDTH - AppLoader.getTvSafeGraphicsWidth()) - (uiQuickBar.posX + uiQuickBar.width) - uiWatchTierOne.width) / 2 + (uiQuickBar.posX + uiQuickBar.width),
AppLoader.getTvSafeGraphicsHeight() + 8
)
} }
@@ -934,26 +937,16 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
} }
override fun dispose() { override fun dispose() {
IngameRenderer.dispose()
actorsRenderBehind.forEach { it.dispose() } actorsRenderBehind.forEach { it.dispose() }
actorsRenderMiddle.forEach { it.dispose() } actorsRenderMiddle.forEach { it.dispose() }
actorsRenderMidTop.forEach { it.dispose() } actorsRenderMidTop.forEach { it.dispose() }
actorsRenderFront.forEach { it.dispose() } actorsRenderFront.forEach { it.dispose() }
actorsRenderOverlay.forEach { it.dispose() } actorsRenderOverlay.forEach { it.dispose() }
uiAliases.forEach { it.dispose() } uiContainer.forEach {
uiAliasesPausing.forEach { it.dispose() } it.handler.dispose()
it.dispose()
}
WatchDotAlph.dispose()
Watch7SegMain.dispose()
WatchDotAlph.dispose()
ItemSlotImageFactory.dispose()
MessageWindow.SEGMENT_BLACK.dispose()
MessageWindow.SEGMENT_WHITE.dispose()
} }
@@ -962,4 +955,5 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
printdbg(this, "-> $it") printdbg(this, "-> $it")
} }
} }
} }

View File

@@ -79,6 +79,9 @@ object IngameRenderer {
init() init()
batch.color = Color.WHITE
BlocksDrawer.world = world BlocksDrawer.world = world
LightmapRenderer.setWorld(world) LightmapRenderer.setWorld(world)
FeaturesDrawer.world = world FeaturesDrawer.world = world
@@ -208,6 +211,7 @@ object IngameRenderer {
// works but some UI elements have wrong transparency -> should be fixed with Terrarum.gdxCleanAndSetBlend -- Torvald 2019-01-12 // works but some UI elements have wrong transparency -> should be fixed with Terrarum.gdxCleanAndSetBlend -- Torvald 2019-01-12
blendNormal(batch) blendNormal(batch)
batch.color = Color.WHITE
} }

View File

@@ -225,20 +225,20 @@ open class ActorHumanoid(
isRightDown = Gdx.input.isKeyPressed(AppLoader.getConfigInt("keyright")) isRightDown = Gdx.input.isKeyPressed(AppLoader.getConfigInt("keyright"))
isJumpDown = Gdx.input.isKeyPressed(AppLoader.getConfigInt("keyjump")) isJumpDown = Gdx.input.isKeyPressed(AppLoader.getConfigInt("keyjump"))
if (Terrarum.controller != null) { if (AppLoader.gamepad != null) {
axisX = Terrarum.controller!!.getAxisValue(AppLoader.getConfigInt("joypadlstickx")) axisX = AppLoader.gamepad!!.getAxisValue(AppLoader.getConfigInt("gamepadlstickx"))
axisY = Terrarum.controller!!.getAxisValue(AppLoader.getConfigInt("joypadlsticky")) axisY = AppLoader.gamepad!!.getAxisValue(AppLoader.getConfigInt("gamepadlsticky"))
axisRX = Terrarum.controller!!.getAxisValue(AppLoader.getConfigInt("joypadrstickx")) axisRX = AppLoader.gamepad!!.getAxisValue(AppLoader.getConfigInt("gamepadrstickx"))
axisRY = Terrarum.controller!!.getAxisValue(AppLoader.getConfigInt("joypadrsticky")) axisRY = AppLoader.gamepad!!.getAxisValue(AppLoader.getConfigInt("gamepadrsticky"))
// deadzonning // deadzonning
if (Math.abs(axisX) < Terrarum.CONTROLLER_DEADZONE) axisX = 0f if (Math.abs(axisX) < AppLoader.gamepadDeadzone) axisX = 0f
if (Math.abs(axisY) < Terrarum.CONTROLLER_DEADZONE) axisY = 0f if (Math.abs(axisY) < AppLoader.gamepadDeadzone) axisY = 0f
if (Math.abs(axisRX) < Terrarum.CONTROLLER_DEADZONE) axisRX = 0f if (Math.abs(axisRX) < AppLoader.gamepadDeadzone) axisRX = 0f
if (Math.abs(axisRY) < Terrarum.CONTROLLER_DEADZONE) axisRY = 0f if (Math.abs(axisRY) < AppLoader.gamepadDeadzone) axisRY = 0f
isJumpDown = Gdx.input.isKeyPressed(AppLoader.getConfigInt("keyjump")) || isJumpDown = Gdx.input.isKeyPressed(AppLoader.getConfigInt("keyjump")) ||
Terrarum.controller!!.isButtonPressed(GAMEPAD_JUMP) AppLoader.gamepad!!.isButtonPressed(GAMEPAD_JUMP)
} }
} }
else { else {
@@ -250,7 +250,7 @@ open class ActorHumanoid(
} }
private inline val hasController: Boolean private inline val hasController: Boolean
get() = if (isGamer) Terrarum.controller != null get() = if (isGamer) AppLoader.gamepad != null
else true else true
private fun processInput(delta: Float) { private fun processInput(delta: Float) {
@@ -384,7 +384,7 @@ open class ActorHumanoid(
* *
* Be warned. * Be warned.
* *
* @param left (even if the game is joypad controlled, you must give valid value) * @param left (even if the game is gamepad controlled, you must give valid value)
* @param absAxisVal (set AXIS_KEYBOARD if keyboard controlled) * @param absAxisVal (set AXIS_KEYBOARD if keyboard controlled)
* @author minjaesong * @author minjaesong
*/ */
@@ -406,9 +406,9 @@ open class ActorHumanoid(
avAcceleration * applyVelo(walkCounterX) * (if (left) -1f else 1f) * absAxisVal avAcceleration * applyVelo(walkCounterX) * (if (left) -1f else 1f) * absAxisVal
if (absAxisVal != AXIS_KEYBOARD) if (absAxisVal != AXIS_KEYBOARD)
controllerMoveDelta?.x?.let { controllerMoveDelta!!.x = controllerMoveDelta!!.x.plus(readonly_totalX).bipolarClamp(avSpeedCap * absAxisVal) } controllerV?.x?.let { controllerV!!.x = controllerV!!.x.plus(readonly_totalX).bipolarClamp(avSpeedCap * absAxisVal) }
else else
controllerMoveDelta?.x?.let { controllerMoveDelta!!.x = controllerMoveDelta!!.x.plus(readonly_totalX).bipolarClamp(avSpeedCap) } controllerV?.x?.let { controllerV!!.x = controllerV!!.x.plus(readonly_totalX).bipolarClamp(avSpeedCap) }
if (walkCounterX < 1000000) { if (walkCounterX < 1000000) {
walkCounterX += 1 walkCounterX += 1
@@ -424,7 +424,7 @@ open class ActorHumanoid(
/** /**
* @param up (even if the game is joypad controlled, you must give valid value) * @param up (even if the game is gamepad controlled, you must give valid value)
* * * *
* @param absAxisVal (set AXIS_KEYBOARD if keyboard controlled) * @param absAxisVal (set AXIS_KEYBOARD if keyboard controlled)
*/ */
@@ -444,9 +444,9 @@ open class ActorHumanoid(
avAcceleration * applyVelo(walkCounterY) * (if (up) -1f else 1f) * absAxisVal avAcceleration * applyVelo(walkCounterY) * (if (up) -1f else 1f) * absAxisVal
if (absAxisVal != AXIS_KEYBOARD) if (absAxisVal != AXIS_KEYBOARD)
controllerMoveDelta?.y?.let { controllerMoveDelta!!.y = controllerMoveDelta!!.y.plus(readonly_totalY).bipolarClamp(avSpeedCap * absAxisVal) } controllerV?.y?.let { controllerV!!.y = controllerV!!.y.plus(readonly_totalY).bipolarClamp(avSpeedCap * absAxisVal) }
else else
controllerMoveDelta?.y?.let { controllerMoveDelta!!.y = controllerMoveDelta!!.y.plus(readonly_totalY).bipolarClamp(avSpeedCap) } controllerV?.y?.let { controllerV!!.y = controllerV!!.y.plus(readonly_totalY).bipolarClamp(avSpeedCap) }
if (walkCounterY < 1000000) { if (walkCounterY < 1000000) {
walkCounterY += 1 walkCounterY += 1
@@ -489,6 +489,7 @@ open class ActorHumanoid(
private var oldJUMPPOWERBUFF = -1.0 // init private var oldJUMPPOWERBUFF = -1.0 // init
private var oldScale = -1.0 private var oldScale = -1.0
private var oldDragCoefficient = -1.0 private var oldDragCoefficient = -1.0
// used by some AIs
var jumpAirTime: Double = -1.0 var jumpAirTime: Double = -1.0
get() { get() {
// compare all the affecting variables // compare all the affecting variables
@@ -519,7 +520,7 @@ open class ActorHumanoid(
val timedJumpCharge = jumpFunc(MAX_JUMP_LENGTH, jmpCtr) val timedJumpCharge = jumpFunc(MAX_JUMP_LENGTH, jmpCtr)
forceVec.y -= getJumpAcc(jumpPower, timedJumpCharge) forceVec.y -= getJumpAcc(jumpPower, timedJumpCharge)
forceVec.y += getDrag(1.0 / Terrarum.PHYS_REF_FPS, forceVec).y forceVec.y += getDrag(AppLoader.UPDATE_RATE.toFloat(), forceVec).y
simYPos += forceVec.y // ignoring all the fluid drag OTHER THAN THE AIR simYPos += forceVec.y // ignoring all the fluid drag OTHER THAN THE AIR
@@ -564,7 +565,7 @@ open class ActorHumanoid(
jumpAcc = getJumpAcc(jumpPower, timedJumpCharge) jumpAcc = getJumpAcc(jumpPower, timedJumpCharge)
controllerMoveDelta?.y?.let { controllerMoveDelta!!.y -= jumpAcc } // feed negative value to the vector controllerV?.y?.let { controllerV!!.y -= jumpAcc } // feed negative value to the vector
// do not think of resetting this to zero when counter hit the ceiling; that's HOW NOT // do not think of resetting this to zero when counter hit the ceiling; that's HOW NOT
// newtonian physics work, stupid myself :( // newtonian physics work, stupid myself :(
@@ -609,7 +610,7 @@ open class ActorHumanoid(
sprite?.update(delta) sprite?.update(delta)
spriteGlow?.update(delta) spriteGlow?.update(delta)
if (walledBottom && controllerMoveDelta?.x != 0.0) { if (walledBottom && controllerV?.x != 0.0) {
//switch row //switch row
sprite?.switchRow(SPRITE_ROW_WALK) sprite?.switchRow(SPRITE_ROW_WALK)
spriteGlow?.switchRow(SPRITE_ROW_WALK) spriteGlow?.switchRow(SPRITE_ROW_WALK)
@@ -617,8 +618,8 @@ open class ActorHumanoid(
// set anim frame delay // set anim frame delay
// 4f of the divider is a magic number, empirically decided // 4f of the divider is a magic number, empirically decided
if (this is HasAssembledSprite) { if (this is HasAssembledSprite) {
sprite?.delays?.set(SPRITE_ROW_WALK, scale.sqrt().toFloat() / (4f * (controllerMoveDelta?.x ?: 0.0001).abs().toFloat())) // FIXME empirical value sprite?.delays?.set(SPRITE_ROW_WALK, scale.sqrt().toFloat() / (4f * (controllerV?.x ?: 0.0001).abs().toFloat())) // FIXME empirical value
spriteGlow?.delays?.set(SPRITE_ROW_WALK, scale.sqrt().toFloat() / (4f * (controllerMoveDelta?.x ?: 0.0001).abs().toFloat())) // FIXME empirical value spriteGlow?.delays?.set(SPRITE_ROW_WALK, scale.sqrt().toFloat() / (4f * (controllerV?.x ?: 0.0001).abs().toFloat())) // FIXME empirical value
} }

View File

@@ -211,7 +211,7 @@ class ActorInventory(val actor: Pocketed, var maxCapacity: Int, var capacityMode
actor.avStrength / 1000.0 actor.avStrength / 1000.0
else else
1.0 // TODO variable: scale, strength 1.0 // TODO variable: scale, strength
val swingDmgToFrameDmg = AppLoader.getSmoothDelta().toFloat().toDouble() / actor.actorValue.getAsDouble(AVKey.ACTION_INTERVAL)!! val swingDmgToFrameDmg = AppLoader.UPDATE_RATE.toFloat().toDouble() / actor.actorValue.getAsDouble(AVKey.ACTION_INTERVAL)!!
// damage the item // damage the item
newItem.durability -= (baseDamagePerSwing * swingDmgToFrameDmg).toFloat() newItem.durability -= (baseDamagePerSwing * swingDmgToFrameDmg).toFloat()

View File

@@ -1,5 +1,6 @@
package net.torvald.terrarum.modulebasegame.gameactors package net.torvald.terrarum.modulebasegame.gameactors
import net.torvald.terrarum.IngameInstance
import net.torvald.terrarum.Point2d import net.torvald.terrarum.Point2d
import net.torvald.terrarum.blockproperties.Block import net.torvald.terrarum.blockproperties.Block
import net.torvald.terrarum.gameactors.ActorWBMovable import net.torvald.terrarum.gameactors.ActorWBMovable
@@ -7,9 +8,9 @@ import net.torvald.terrarum.gameactors.ActorWBMovable
/** /**
* Created by minjaesong on 2016-06-17. * Created by minjaesong on 2016-06-17.
*/ */
open class FixtureBase(val blockBox: BlockBox) : open class FixtureBase(val blockBox: BlockBox, val blockBoxProps: BlockBoxProps = BlockBoxProps(0)) :
// disabling physics (not allowing the fixture to move) WILL make things easier // disabling physics (not allowing the fixture to move) WILL make things easier
ActorWBMovable(RenderOrder.BEHIND, immobileBody = true, usePhysics = false) { ActorWBMovable(RenderOrder.BEHIND, immobileBody = true, usePhysics = false), CuedByTerrainChange {
/** /**
* Block-wise position of this fixture when it's placed on the world. Null if it's not on the world * Block-wise position of this fixture when it's placed on the world. Null if it's not on the world
@@ -32,6 +33,10 @@ open class FixtureBase(val blockBox: BlockBox) :
}
open fun updateSelf() {
} }
/** /**
@@ -42,6 +47,33 @@ open class FixtureBase(val blockBox: BlockBox) :
} }
} }
interface CuedByTerrainChange {
/**
* Fired by world's BlockChanged event (fired when blocks are placed/removed).
* The flooding check must run on every frame. use updateSelf() for that.
*
* E.g. if a fixture block that is inside of BlockBox is missing, destroy and drop self.
*/
fun updateForWorldChange(cue: IngameInstance.BlockChangeQueueItem) {
}
}
/**
* Standard 32-bit binary flags.
*
* (LSB)
* - 0: fluid resist - when FALSE, the fixture will break itself to item/nothing. For example, crops has this flag FALSE.
* - 1: don't drop item when broken - when TRUE, the fixture will simply disappear instead of dropping itself. For example, crop has this flag TRUE.
*
* (MSB)
*
* In the savegame's JSON, this flag set should be stored as signed integer.
*/
inline class BlockBoxProps(val flags: Int) {
}
data class BlockBox(var collisionType: Int, var width: Int, var height: Int) { data class BlockBox(var collisionType: Int, var width: Int, var height: Int) {
fun redefine(collisionType: Int, width: Int, height: Int) { fun redefine(collisionType: Int, width: Int, height: Int) {

View File

@@ -23,7 +23,7 @@ open class ParticleBase(renderOrder: Actor.RenderOrder, val despawnUponCollision
/** Will NOT actually delete from the CircularArray */ /** Will NOT actually delete from the CircularArray */
@Volatile var flagDespawn = false @Volatile var flagDespawn = false
override fun run() = update(AppLoader.getSmoothDelta().toFloat()) override fun run() = update(AppLoader.UPDATE_RATE.toFloat())
var isNoSubjectToGrav = false var isNoSubjectToGrav = false
var dragCoefficient = 3.0 var dragCoefficient = 3.0

View File

@@ -10,7 +10,6 @@ import net.torvald.terrarum.gameactors.AVKey
import net.torvald.terrarum.gameactors.ActorWBMovable import net.torvald.terrarum.gameactors.ActorWBMovable
import net.torvald.terrarum.gameactors.Controllable import net.torvald.terrarum.gameactors.Controllable
import net.torvald.terrarum.gameactors.Hitbox import net.torvald.terrarum.gameactors.Hitbox
import net.torvald.terrarum.gameworld.GameWorld
/** /**
* Created by minjaesong on 2018-01-17. * Created by minjaesong on 2018-01-17.
@@ -37,7 +36,7 @@ class PhysTestLuarLander : ActorWBMovable(RenderOrder.MIDTOP), Controllable {
super.update(delta) super.update(delta)
if (Gdx.input.isKeyPressed(Input.Keys.UP)) { if (Gdx.input.isKeyPressed(Input.Keys.UP)) {
controllerMoveDelta!!.y = avSpeedCap controllerV!!.y = avSpeedCap
} }
} }

View File

@@ -99,5 +99,6 @@ object PlayerBuilderSigrid {
walls.forEach { inventory.add(it + 4096, 9995) } walls.forEach { inventory.add(it + 4096, 9995) }
inventory.add(ItemCodex.ITEM_STATIC.first) inventory.add(ItemCodex.ITEM_STATIC.first)
inventory.add(9000) inventory.add(9000)
inventory.add(9001)
} }
} }

View File

@@ -28,7 +28,7 @@ interface Pocketed {
} }
inventory.itemEquipped[item.equipPosition] = null inventory.itemEquipped[item.equipPosition] = null
item.effectOnUnequip(AppLoader.getSmoothDelta().toFloat()) item.effectOnUnequip(AppLoader.UPDATE_RATE.toFloat())
} }
// no need for equipSlot(Int) // no need for equipSlot(Int)
@@ -50,7 +50,7 @@ interface Pocketed {
if (item.equipPosition >= 0) { if (item.equipPosition >= 0) {
inventory.itemEquipped[item.equipPosition] = item inventory.itemEquipped[item.equipPosition] = item
item.effectWhenEquipped(AppLoader.getSmoothDelta().toFloat()) item.effectWhenEquipped(AppLoader.UPDATE_RATE.toFloat())
} }
// else do nothing // else do nothing
} }
@@ -69,13 +69,13 @@ interface Pocketed {
fun consumePrimary(item: GameItem) { fun consumePrimary(item: GameItem) {
if (item.startPrimaryUse(AppLoader.getSmoothDelta().toFloat())) { if (item.startPrimaryUse(AppLoader.UPDATE_RATE.toFloat())) {
inventory.consumeItem(this as Actor, item) // consume on successful inventory.consumeItem(this as Actor, item) // consume on successful
} }
} }
fun consumeSecondary(item: GameItem) { fun consumeSecondary(item: GameItem) {
if (item.startSecondaryUse(AppLoader.getSmoothDelta().toFloat())) if (item.startSecondaryUse(AppLoader.UPDATE_RATE.toFloat()))
inventory.consumeItem(this as Actor, item) // consume on successful inventory.consumeItem(this as Actor, item) // consume on successful
} }
} }

View File

@@ -9,7 +9,6 @@ import net.torvald.terrarum.blockproperties.BlockCodex
import net.torvald.terrarum.gameactors.ActorWBMovable import net.torvald.terrarum.gameactors.ActorWBMovable
import net.torvald.terrarum.gameactors.Hitbox import net.torvald.terrarum.gameactors.Hitbox
import net.torvald.terrarum.gameactors.Luminous import net.torvald.terrarum.gameactors.Luminous
import net.torvald.terrarum.gameworld.GameWorld
import org.dyn4j.geometry.Vector2 import org.dyn4j.geometry.Vector2
import java.util.* import java.util.*
@@ -54,7 +53,7 @@ open class ProjectileSimple(
posPre = Point2d(fromPoint.x, fromPoint.y) posPre = Point2d(fromPoint.x, fromPoint.y)
// lightbox sized 8x8 centered to the bullet // lightbox sized 8x8 centered to the bullet
lightBoxList.add(Hitbox(-4.0, -4.0, 8.0, 8.0)) lightBoxList.add(Hitbox(-4.0, -4.0, 8.0, 8.0))
//this.externalForce.set(velocity) //this.externalV.set(velocity)
damage = bulletDatabase[type][OFFSET_DAMAGE] as Int damage = bulletDatabase[type][OFFSET_DAMAGE] as Int
displayColour = bulletDatabase[type][OFFSET_COL] as Color displayColour = bulletDatabase[type][OFFSET_COL] as Color
@@ -64,7 +63,7 @@ open class ProjectileSimple(
setHitboxDimension(2, 2, 0, 0) // should be following sprite's properties if there IS one setHitboxDimension(2, 2, 0, 0) // should be following sprite's properties if there IS one
externalForce.set((fromPoint to toPoint).setMagnitude(speed.toDouble())) externalV.set((fromPoint to toPoint).setMagnitude(speed.toDouble()))

View File

@@ -10,13 +10,13 @@ class ThreadActorUpdate(val startIndex: Int, val endIndex: Int) : Runnable {
override fun run() { override fun run() {
for (i in startIndex..endIndex) { for (i in startIndex..endIndex) {
val it = Terrarum.ingame!!.actorContainer[i] val it = Terrarum.ingame!!.actorContainer[i]
it.update(AppLoader.getSmoothDelta().toFloat()) it.update(AppLoader.UPDATE_RATE.toFloat())
if (it is Pocketed) { if (it is Pocketed) {
it.inventory.forEach { inventoryEntry -> it.inventory.forEach { inventoryEntry ->
inventoryEntry.item.effectWhileInPocket(AppLoader.getSmoothDelta().toFloat()) inventoryEntry.item.effectWhileInPocket(AppLoader.UPDATE_RATE.toFloat())
if (it.equipped(inventoryEntry.item)) { if (it.equipped(inventoryEntry.item)) {
inventoryEntry.item.effectWhenEquipped(AppLoader.getSmoothDelta().toFloat()) inventoryEntry.item.effectWhenEquipped(AppLoader.UPDATE_RATE.toFloat())
} }
} }
} }

View File

@@ -150,8 +150,8 @@ object CollisionSolver {
// if they actually makes collision (e.g. player vs ball), solve it // if they actually makes collision (e.g. player vs ball), solve it
if (a makesCollisionWith b) { if (a makesCollisionWith b) {
val a_moveDelta = a.externalForce + a.controllerMoveDelta val a_moveDelta = a.externalV + a.controllerV
val b_moveDelta = b.externalForce + b.controllerMoveDelta val b_moveDelta = b.externalV + b.controllerV
val ux_1 = a_moveDelta.x val ux_1 = a_moveDelta.x
val ux_2 = b_moveDelta.x val ux_2 = b_moveDelta.x

View File

@@ -1,5 +1,7 @@
package net.torvald.terrarum.modulebasegame.gameworld package net.torvald.terrarum.modulebasegame.gameworld
import net.torvald.terrarum.gameworld.fmod
typealias time_t = Long typealias time_t = Long
@@ -96,11 +98,11 @@ class WorldTime(initTime: Long = 0L) {
// these functions won't need inlining for performance // these functions won't need inlining for performance
val yearlyDays: Int // 0 - 119 val yearlyDays: Int // 0 - 119
get() = (TIME_T.toPositiveInt().div(DAY_LENGTH) % YEAR_DAYS) get() = (TIME_T.div(DAY_LENGTH) fmod YEAR_DAYS.toLong()).toInt()
val days: Int // 1 - 30 fixed val days: Int // 1 - 30 fixed
get() = (yearlyDays % 30) + 1 get() = (yearlyDays % MONTH_LENGTH) + 1
val months: Int // 1 - 4 val months: Int // 1 - 4
get() = (yearlyDays / 30) + 1 get() = (yearlyDays / MONTH_LENGTH) + 1
val years: Int val years: Int
get() = TIME_T.div(YEAR_DAYS * DAY_LENGTH).abs().toInt() + EPOCH_YEAR get() = TIME_T.div(YEAR_DAYS * DAY_LENGTH).abs().toInt() + EPOCH_YEAR
@@ -153,6 +155,9 @@ class WorldTime(initTime: Long = 0L) {
val EPOCH_YEAR = 125 val EPOCH_YEAR = 125
/**
* Parse a time in the format of "8h30" (hour and minute) or "39882" (second) and return a time of day, in seconds
*/
fun parseTime(s: String): Int = fun parseTime(s: String): Int =
if (s.length >= 4 && s.contains('h')) { if (s.length >= 4 && s.contains('h')) {
s.toLowerCase().substringBefore('h').toInt() * HOUR_SEC + s.toLowerCase().substringBefore('h').toInt() * HOUR_SEC +

View File

@@ -0,0 +1,38 @@
package net.torvald.terrarum.modulebasegame.imagefont
import com.badlogic.gdx.graphics.g2d.Batch
import com.badlogic.gdx.graphics.g2d.BitmapFont
import com.badlogic.gdx.graphics.g2d.GlyphLayout
import net.torvald.terrarum.ModMgr
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
/**
* Created by minjaesong on 2019-01-24.
*/
object WatchFont : BitmapFont() {
internal val W = 9
internal val H = 12
internal val fontSheet = TextureRegionPack(ModMgr.getGdxFile("basegame", "fonts/watch_new.tga"), W, H)
init {
setOwnsTexture(true)
}
override fun draw(batch: Batch, str: CharSequence, x: Float, y: Float): GlyphLayout? {
str.forEachIndexed { index, c ->
batch.draw(
fontSheet.get((c - '0') % 16, (c - '0') / 16),
x + W * index, y
)
}
return null
}
override fun getLineHeight() = H.toFloat()
override fun getCapHeight() = getLineHeight()
override fun getXHeight() = getLineHeight()
}

View File

@@ -23,7 +23,7 @@ class PickaxeGeneric(override val originalID: ItemID) : GameItem() {
override var stackable = true override var stackable = true
override var maxDurability = 147 override var maxDurability = 147
override var durability = maxDurability.toFloat() override var durability = maxDurability.toFloat()
override val equipPosition = 9 override val equipPosition = GameItem.EquipPosition.HAND_GRIP
override var inventoryCategory = Category.TOOL override var inventoryCategory = Category.TOOL
override val isUnique = false override val isUnique = false
override val isDynamic = true override val isDynamic = true
@@ -47,10 +47,10 @@ class PickaxeGeneric(override val originalID: ItemID) : GameItem() {
// linear search filter (check for intersection with tilewise mouse point and tilewise hitbox) // linear search filter (check for intersection with tilewise mouse point and tilewise hitbox)
// return false if hitting actors // return false if hitting actors
Terrarum.ingame!!.actorContainer.forEach({ Terrarum.ingame!!.actorContainer.forEach {
if (it is ActorWBMovable && it.hIntTilewiseHitbox.intersects(mousePoint)) if (it is ActorWBMovable && it.hIntTilewiseHitbox.intersects(mousePoint))
return false return false
}) }
// return false if here's no tile // return false if here's no tile
if (Block.AIR == (Terrarum.ingame!!.world).getTileFromTerrain(mouseTileX, mouseTileY)) if (Block.AIR == (Terrarum.ingame!!.world).getTileFromTerrain(mouseTileX, mouseTileY))

View File

@@ -17,8 +17,11 @@ import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
*/ */
object ItemSlotImageFactory { object ItemSlotImageFactory {
val colourBlack = Color(0x404040_FF) val CELLCOLOUR_BLACK_OPAQUE = Color(0x404040_FF)
val colourWhite = Color(0xC0C0C0_FF.toInt()) val CELLCOLOUR_WHITE_OPAQUE = Color(0xC0C0C0_FF.toInt())
val CELLCOLOUR_BLACK = Color(0x404040_88)
val CELLCOLOUR_WHITE = Color(0xC0C0C0_88.toInt())
val slotImage = TextureRegionPack(Gdx.files.internal("./assets/graphics/gui/quickbar/item_slots_atlas.tga"), 38, 38) // must have same w/h as slotLarge val slotImage = TextureRegionPack(Gdx.files.internal("./assets/graphics/gui/quickbar/item_slots_atlas.tga"), 38, 38) // must have same w/h as slotLarge

View File

@@ -1,19 +1,10 @@
package net.torvald.terrarum.modulebasegame.ui package net.torvald.terrarum.modulebasegame.ui
import com.badlogic.gdx.graphics.Camera
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.terrarum.Second
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.blendNormal
import net.torvald.terrarum.ui.UICanvas
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
/** /**
* Created by minjaesong on 2016-01-27. * Created by minjaesong on 2016-01-27.
*/ */
class MessageWindow(override var width: Int, isBlackVariant: Boolean) : UICanvas() { /*class MessageWindow(override var width: Int, isBlackVariant: Boolean) : UICanvas() {
private val segment = if (isBlackVariant) SEGMENT_BLACK else SEGMENT_WHITE private val segment = if (isBlackVariant) SEGMENT_BLACK else SEGMENT_WHITE
@@ -49,6 +40,9 @@ class MessageWindow(override var width: Int, isBlackVariant: Boolean) : UICanvas
messagesList.forEachIndexed { index, s -> messagesList.forEachIndexed { index, s ->
Terrarum.fontGame.draw(batch, s, segment.tileW + LRmargin, (segment.tileH - Terrarum.fontGame.lineHeight) / 2f) Terrarum.fontGame.draw(batch, s, segment.tileW + LRmargin, (segment.tileH - Terrarum.fontGame.lineHeight) / 2f)
} }
AppLoader.printdbg(this, "render")
} }
override fun doOpening(delta: Float) { override fun doOpening(delta: Float) {
@@ -76,4 +70,4 @@ class MessageWindow(override var width: Int, isBlackVariant: Boolean) : UICanvas
val SEGMENT_BLACK = TextureRegionPack("assets/graphics/gui/message_black.tga", 8, 56) val SEGMENT_BLACK = TextureRegionPack("assets/graphics/gui/message_black.tga", 8, 56)
val SEGMENT_WHITE = TextureRegionPack("assets/graphics/gui/message_white.tga", 8, 56) val SEGMENT_WHITE = TextureRegionPack("assets/graphics/gui/message_white.tga", 8, 56)
} }
} }*/

View File

@@ -1,32 +1,45 @@
package net.torvald.terrarum.modulebasegame.ui package net.torvald.terrarum.modulebasegame.ui
import com.badlogic.gdx.graphics.Camera import com.badlogic.gdx.graphics.Camera
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.terrarum.AppLoader import net.torvald.terrarum.AppLoader
import net.torvald.terrarum.Second import net.torvald.terrarum.Second
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.blendNormal
import net.torvald.terrarum.ui.UICanvas import net.torvald.terrarum.ui.UICanvas
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
/** /**
* Created by minjaesong on 2016-01-23. * Created by minjaesong on 2016-01-23.
*/ */
class Notification : UICanvas() { class Notification : UICanvas() {
private val SHOWUP_MAX = 15000 private val segment = SEGMENT_BLACK
private var fontCol: Color = Color.WHITE // assuming alpha of 1.0
override var openCloseTime: Second = OPEN_CLOSE_TIME
private val LRmargin = 0f // there's "base value" of 8 px for LR (width of segment tile)
private val SHOWUP_MAX = 6500
override var width: Int = 500 override var width: Int = 500
internal var msgUI = MessageWindow(width, true) override var height: Int = segment.tileH
override var height: Int = msgUI.height
private val visibleTime = Math.min( private val visibleTime = Math.min(
AppLoader.getConfigInt("notificationshowuptime"), AppLoader.getConfigInt("notificationshowuptime"),
SHOWUP_MAX SHOWUP_MAX
) ) / 1000f
private var displayTimer = 0f private var displayTimer = 0f
internal var message: Array<String> = Array(MessageWindow.MESSAGES_DISPLAY) { "" } internal var message: Array<String> = Array(MESSAGES_DISPLAY) { "" }
override var openCloseTime: Second = MessageWindow.OPEN_CLOSE_TIME
init {
}
override fun updateUI(delta: Float) { override fun updateUI(delta: Float) {
if (handler.isOpened) if (handler.isOpened)
@@ -38,8 +51,34 @@ class Notification : UICanvas() {
} }
} }
private val textAreaHeight = 48f
private val imageToTextAreaDelta = (segment.tileH - textAreaHeight) / 2
private val drawColor = Color(1f,1f,1f,1f)
override fun renderUI(batch: SpriteBatch, camera: Camera) { override fun renderUI(batch: SpriteBatch, camera: Camera) {
msgUI.render(batch, camera) blendNormal(batch)
drawColor.a = handler.opacity
fontCol.a = handler.opacity
val textWidth = width//maxOf(width, messagesList.map { Terrarum.fontGame.getWidth(it) }.sorted()[1])
batch.color = drawColor
batch.draw(segment.get(0, 0), -segment.tileW.toFloat(), 0f)
batch.draw(segment.get(1, 0), 0f, 0f, textWidth.toFloat(), segment.tileH.toFloat())
batch.draw(segment.get(2, 0), textWidth.toFloat(), 0f)
batch.color = fontCol
message.forEachIndexed { index, s ->
val y = imageToTextAreaDelta + index * (textAreaHeight / 2) + (textAreaHeight / 2 - Terrarum.fontGame.lineHeight) / 2
Terrarum.fontGame.draw(batch, s, LRmargin, y)
}
// dunno why, it doesn't work without this.
drawColor.a = 1f
fontCol.a = 1f
} }
override fun doOpening(delta: Float) { override fun doOpening(delta: Float) {
@@ -60,7 +99,6 @@ class Notification : UICanvas() {
fun sendNotification(message: Array<String>) { fun sendNotification(message: Array<String>) {
this.message = message this.message = message
msgUI.setMessage(this.message)
handler.openCloseCounter = 0f handler.openCloseCounter = 0f
handler.opacity = 0f handler.opacity = 0f
handler.setAsOpen() handler.setAsOpen()
@@ -68,4 +106,15 @@ class Notification : UICanvas() {
override fun dispose() { override fun dispose() {
} }
companion object {
// private int messagesShowingIndex = 0;
val MESSAGES_DISPLAY = 2
val OPEN_CLOSE_TIME = 0.16f
// will be disposed by Terrarum (application main instance)
val SEGMENT_BLACK = TextureRegionPack("assets/graphics/gui/message_black.tga", 8, 56)
val SEGMENT_WHITE = TextureRegionPack("assets/graphics/gui/message_white.tga", 8, 56)
}
} }

View File

@@ -0,0 +1,164 @@
package net.torvald.terrarum.modulebasegame.ui
import com.badlogic.gdx.graphics.Camera
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.Pixmap
import com.badlogic.gdx.graphics.Texture
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.blendNormal
import net.torvald.terrarum.blockproperties.Block
import net.torvald.terrarum.fillRect
import net.torvald.terrarum.itemproperties.ItemCodex
import net.torvald.terrarum.modulebasegame.ui.ItemSlotImageFactory.CELLCOLOUR_BLACK
import net.torvald.terrarum.ui.UICanvas
import net.torvald.terrarum.ui.UINSMenu
/**
* Created by minjaesong on 2019-02-03.
*/
class UIEditorPalette : UICanvas() {
override var width = 36
override var height = 72
override var openCloseTime = 0f
val LINE_HEIGHT = 24
val TEXT_OFFSETX = 3f
val TEXT_OFFSETY = (LINE_HEIGHT - Terrarum.fontGame.lineHeight) / 2f
fun mouseOnTitleBar() =
relativeMouseX in 0 until width && relativeMouseY in 0 until LINE_HEIGHT
var fore = Block.STONE_BRICKS
var back = Block.GLASS_CRUDE
private val titleText = "Pal."
private val swapIcon: Texture
init {
// make swap icon, because I can't be bothered to make yet another tga
val clut = intArrayOf(0, 0xaaaaaaff.toInt(), -1, -1)
val swapIconPixmap = Pixmap(13, 13, Pixmap.Format.RGBA8888)
arrayOf(
0b00_00_11_01_00_00_00_00_00_00_00_00_00,
0b00_11_11_01_00_00_00_00_00_00_00_00_00,
0b11_11_11_11_11_11_11_11_11_11_01_00_00,
0b01_11_11_01_01_01_01_01_01_11_01_00_00,
0b00_01_11_01_00_00_00_00_00_11_01_00_00,
0b00_00_01_01_00_00_00_00_00_11_01_00_00,
0b00_00_00_00_00_00_00_00_00_11_01_00_00,
0b00_00_00_00_00_00_00_00_00_11_01_00_00,
0b00_00_00_00_00_00_00_00_00_11_01_00_00,
0b00_00_00_00_00_00_00_11_11_11_11_11_01,
0b00_00_00_00_00_00_00_01_11_11_11_01_01,
0b00_00_00_00_00_00_00_00_01_11_01_01_00,
0b00_00_00_00_00_00_00_00_00_01_01_00_00
).reversed().forEachIndexed { index, bits ->
for (shiftmask in 12 downTo 0) {
val bit = bits.ushr(shiftmask * 2).and(3)
swapIconPixmap.drawPixel(12 - shiftmask, index, clut[bit])
}
}
swapIcon = Texture(swapIconPixmap)
swapIconPixmap.dispose()
}
override fun renderUI(batch: SpriteBatch, camera: Camera) {
// draw title bar
batch.color = UINSMenu.DEFAULT_TITLEBACKCOL
blendNormal(batch)
batch.fillRect(0f, 0f, width.toFloat(), LINE_HEIGHT.toFloat())
// draw "Pal."
batch.color = UINSMenu.DEFAULT_TITLETEXTCOL
Terrarum.fontGame.draw(batch, titleText, TEXT_OFFSETX, TEXT_OFFSETY)
// draw background
batch.color = CELLCOLOUR_BLACK
batch.fillRect(0f, LINE_HEIGHT.toFloat(), 36f, 48f)
// draw back and fore selection
batch.color = Color.WHITE
// TODO carve the overlap
batch.draw(ItemCodex.getItemImage(back), 14f, 41f)
batch.draw(ItemCodex.getItemImage(fore), 6f, 33f)
Terrarum.fontSmallNumbers.draw(batch, fore.toString(), 3f, 61f)
// draw swap icon
batch.color = Color.WHITE
batch.draw(swapIcon, 22f, 26f)
}
override fun updateUI(delta: Float) {
}
fun swapForeAndBack() {
// xor used, because why not?
fore = fore xor back
back = back xor fore
fore = fore xor back
}
override fun doOpening(delta: Float) {
}
override fun doClosing(delta: Float) {
}
override fun endOpening(delta: Float) {
}
override fun endClosing(delta: Float) {
}
override fun dispose() {
}
private var dragOriginX = 0 // relative mousepos
private var dragOriginY = 0 // relative mousepos
private var dragForReal = false
private var swapDown = false
override fun touchDragged(screenX: Int, screenY: Int, pointer: Int): Boolean {
if (mouseInScreen(screenX, screenY)) {
if (dragForReal) {
handler.setPosition(screenX - dragOriginX, screenY - dragOriginY)
//println("drag $screenX, $screenY")
}
}
return true
}
override fun touchDown(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
if (mouseOnTitleBar()) {
dragOriginX = relativeMouseX
dragOriginY = relativeMouseY
dragForReal = true
}
else {
dragForReal = false
}
// make swap button work
if (!swapDown && (relativeMouseX in 14..35 && relativeMouseY in 24..32 || relativeMouseX in 22..35 && relativeMouseY in 33..40)) {
swapDown = true
swapForeAndBack()
}
return true
}
override fun touchUp(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
swapDown = false
return true
}
}

View File

@@ -142,9 +142,9 @@ package net.torvald.terrarum.modulebasegame.ui
"${0xe011.toChar()}..${0xe010.toChar()} ${Lang["GAME_INVENTORY_REGISTER"]}$SP" + "${0xe011.toChar()}..${0xe010.toChar()} ${Lang["GAME_INVENTORY_REGISTER"]}$SP" +
"${0xe034.toChar()} ${Lang["GAME_INVENTORY_DROP"]}" "${0xe034.toChar()} ${Lang["GAME_INVENTORY_DROP"]}"
else else
"$joypadLabelNinY ${Lang["GAME_INVENTORY_USE"]}$SP" + "$gamepadLabelNinY ${Lang["GAME_INVENTORY_USE"]}$SP" +
"${0xe011.toChar()}${0xe010.toChar()} ${Lang["GAME_INVENTORY_REGISTER"]}$SP" + "${0xe011.toChar()}${0xe010.toChar()} ${Lang["GAME_INVENTORY_REGISTER"]}$SP" +
"$joypadLabelNinA ${Lang["GAME_INVENTORY_DROP"]}" "$gamepadLabelNinA ${Lang["GAME_INVENTORY_DROP"]}"
val listControlClose: String val listControlClose: String
get() = if (Terrarum.environment == RunningEnvironment.PC) get() = if (Terrarum.environment == RunningEnvironment.PC)
"${0xe037.toChar()} ${Lang["GAME_ACTION_CLOSE"]}" "${0xe037.toChar()} ${Lang["GAME_ACTION_CLOSE"]}"

View File

@@ -13,13 +13,16 @@ import net.torvald.terrarum.modulebasegame.Ingame
import net.torvald.terrarum.modulebasegame.gameactors.ActorInventory.Companion.CAPACITY_MODE_NO_ENCUMBER import net.torvald.terrarum.modulebasegame.gameactors.ActorInventory.Companion.CAPACITY_MODE_NO_ENCUMBER
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
import net.torvald.terrarum.ui.UICanvas import net.torvald.terrarum.ui.UICanvas
import net.torvald.terrarum.ui.UIItem
import net.torvald.terrarum.ui.UIItemTextButtonList
import net.torvald.terrarum.ui.UIUtils
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
/** /**
* Created by minjaesong on 2017-10-21. * Created by minjaesong on 2017-10-21.
*/ */
class UIInventoryFull( class UIInventoryFull(
var actor: Pocketed?, var actor: Pocketed,
toggleKeyLiteral: Int? = null, toggleButtonLiteral: Int? = null, toggleKeyLiteral: Int? = null, toggleButtonLiteral: Int? = null,
// UI positions itself? (you must g.flush() yourself after the g.translate(Int, Int)) // UI positions itself? (you must g.flush() yourself after the g.translate(Int, Int))
@@ -27,11 +30,15 @@ class UIInventoryFull(
doNotWarnConstant: Boolean = false doNotWarnConstant: Boolean = false
) : UICanvas(toggleKeyLiteral, toggleButtonLiteral, customPositioning, doNotWarnConstant) { ) : UICanvas(toggleKeyLiteral, toggleButtonLiteral, customPositioning, doNotWarnConstant) {
private val debugvals = false
override var width: Int = Terrarum.WIDTH override var width: Int = Terrarum.WIDTH
override var height: Int = Terrarum.HEIGHT override var height: Int = Terrarum.HEIGHT
val internalWidth: Int = 686 private val itemListToEquipViewGap = 24
val internalHeight: Int = 558 // grad_begin..grad_end..contents..grad_begin..grad_end
val internalWidth: Int = UIItemInventoryDynamicList.WIDTH + UIItemInventoryEquippedView.WIDTH + itemListToEquipViewGap
val internalHeight: Int = 166 + UIItemInventoryDynamicList.HEIGHT // grad_begin..grad_end..contents..grad_begin..grad_end
@@ -49,9 +56,19 @@ class UIInventoryFull(
"${0xe034.toChar()} ${Lang["GAME_INVENTORY_DROP"]}" "${0xe034.toChar()} ${Lang["GAME_INVENTORY_DROP"]}"
else else
"${0xe069.toChar()} ${Lang["GAME_ACTION_CLOSE"]}$SP" + "${0xe069.toChar()} ${Lang["GAME_ACTION_CLOSE"]}$SP" +
"${Terrarum.joypadLabelNinY} ${Lang["GAME_INVENTORY_USE"]}$SP" + "${Terrarum.gamepadLabelNinY} ${Lang["GAME_INVENTORY_USE"]}$SP" +
"${0xe011.toChar()}${0xe010.toChar()} ${Lang["GAME_INVENTORY_REGISTER"]}$SP" + "${0xe011.toChar()}${0xe010.toChar()} ${Lang["GAME_INVENTORY_REGISTER"]}$SP" +
"${Terrarum.joypadLabelNinA} ${Lang["GAME_INVENTORY_DROP"]}" "${Terrarum.gamepadLabelNinA} ${Lang["GAME_INVENTORY_DROP"]}"
val minimapControlHelp: String
get() = if (AppLoader.environment == RunningEnvironment.PC)
"${0xe031.toChar()} ${Lang["GAME_ACTION_CLOSE"]}"
else
"${0xe069.toChar()} ${Lang["GAME_ACTION_CLOSE"]}$SP${0xe06b.toChar()} ${Lang["GAME_INVENTORY"]}"
val gameMenuControlHelp: String
get() = if (AppLoader.environment == RunningEnvironment.PC)
"${0xe031.toChar()} ${Lang["GAME_ACTION_CLOSE"]}"
else
"${0xe069.toChar()} ${Lang["GAME_ACTION_CLOSE"]}$SP${0xe068.toChar()} ${Lang["GAME_INVENTORY"]}"
val controlHelpHeight = Terrarum.fontGame.lineHeight val controlHelpHeight = Terrarum.fontGame.lineHeight
private var encumbrancePerc = 0f private var encumbrancePerc = 0f
@@ -62,7 +79,7 @@ class UIInventoryFull(
val categoryBar = UIItemInventoryCatBar( val categoryBar = UIItemInventoryCatBar(
this, this,
(Terrarum.WIDTH - catBarWidth) / 2, (Terrarum.WIDTH - catBarWidth) / 2,
66 + (Terrarum.HEIGHT - internalHeight) / 2, 42 + (Terrarum.HEIGHT - internalHeight) / 2,
catBarWidth catBarWidth
) )
val catSelection: Int val catSelection: Int
@@ -73,48 +90,100 @@ class UIInventoryFull(
override var openCloseTime: Second = 0.0f override var openCloseTime: Second = 0.0f
private val itemList: UIItemInventoryDynamicList? = private val itemList: UIItemInventoryDynamicList =
if (actor != null) {
UIItemInventoryDynamicList( UIItemInventoryDynamicList(
this, this,
actor!!.inventory, actor.inventory,
0 + (Terrarum.WIDTH - internalWidth) / 2, 0 + (Terrarum.WIDTH - internalWidth) / 2,
109 + (Terrarum.HEIGHT - internalHeight) / 2 109 + (Terrarum.HEIGHT - internalHeight) / 2
) )
}
else null
private val equipped: UIItemInventoryEquippedView? = private val equipped: UIItemInventoryEquippedView =
if (actor != null) {
UIItemInventoryEquippedView( UIItemInventoryEquippedView(
this, this,
actor!!.inventory, actor.inventory,
actor as ActorWBMovable, actor as ActorWBMovable,
internalWidth - UIItemInventoryEquippedView.width + (Terrarum.WIDTH - internalWidth) / 2, internalWidth - UIItemInventoryEquippedView.WIDTH + (Terrarum.WIDTH - internalWidth) / 2,
109 + (Terrarum.HEIGHT - internalHeight) / 2 109 + (Terrarum.HEIGHT - internalHeight) / 2
) )
private val gameMenuListWidth = 400
private val gameMenuListHeight = 40 * 5
private val gameMenuCharInfoHeight = 64 + 40 // no top margin, 40 bottom margin
private val gameMenuListTotalHeight = gameMenuListHeight + gameMenuCharInfoHeight
private val gameMenuButtons = UIItemTextButtonList(
this, arrayOf("MENU_LABEL_MAINMENU", "MENU_LABEL_DESKTOP", "MENU_OPTIONS_CONTROLS", "MENU_OPTIONS_SOUND", "MENU_LABEL_GRAPHICS"),
Terrarum.WIDTH + (Terrarum.WIDTH - gameMenuListWidth) / 2,
(itemList.height - gameMenuListTotalHeight) / 2 + itemList.posY + gameMenuCharInfoHeight,
gameMenuListWidth, gameMenuListHeight,
readFromLang = true,
textAreaWidth = gameMenuListWidth,
activeBackCol = Color(0),
highlightBackCol = Color(0),
backgroundCol = Color(0),
inactiveCol = Color.WHITE,
defaultSelection = null
)
private val SCREEN_MINIMAP = 2f
private val SCREEN_INVENTORY = 1f
private val SCREEN_MENU = 0f
private var currentScreen = SCREEN_INVENTORY
private var transitionRequested = false
private var transitionOngoing = false
private var transitionReqSource = SCREEN_INVENTORY
private var transitionReqTarget = SCREEN_INVENTORY
private var transitionTimer = 0f
private val transitionLength = 0.212f
private val transitionalUpdateUIs = ArrayList<UIItem>()
private val transitionalUpdateUIoriginalPosX = ArrayList<Int>()
private fun addToTransitionalGroup(item: UIItem) {
transitionalUpdateUIs.add(item)
transitionalUpdateUIoriginalPosX.add(item.posX)
} }
else null
private fun updateTransitionalItems() {
for (k in 0..transitionalUpdateUIs.lastIndex) {
val intOff = inventoryScrOffX.roundInt()
transitionalUpdateUIs[k].posX = transitionalUpdateUIoriginalPosX[k] + intOff
}
}
init { init {
addItem(categoryBar) addItem(categoryBar)
itemList?.let { addItem(it) } itemList.let { addItem(it) }
equipped?.let { addItem(it) } equipped.let { addItem(it) }
categoryBar.selectionChangeListener = { old, new -> categoryBar.selectionChangeListener = { old, new ->
rebuildList() rebuildList()
itemList?.itemPage = 0 // set scroll to zero itemList.itemPage = 0 // set scroll to zero
itemList?.rebuild() // have to manually rebuild, too! itemList.rebuild() // have to manually rebuild, too!
} }
rebuildList() rebuildList()
addToTransitionalGroup(itemList)
addToTransitionalGroup(equipped)
addToTransitionalGroup(gameMenuButtons)
// make gameMenuButtons work
gameMenuButtons.selectionChangeListener = { old, new ->
if (new == 0) {
Terrarum.setScreen(TitleScreen(Terrarum.batch))
}
else if (new == 1) {
Gdx.app.exit()
}
}
} }
private var offsetX = ((Terrarum.WIDTH - internalWidth) / 2).toFloat() private var offsetX = ((Terrarum.WIDTH - internalWidth) / 2).toFloat()
@@ -129,8 +198,9 @@ class UIInventoryFull(
categoryBar.update(delta) categoryBar.update(delta)
itemList?.update(delta)
equipped?.update(delta) transitionalUpdateUIs.forEach { it.update(delta) }
} }
private val gradStartCol = Color(0x404040_60) private val gradStartCol = Color(0x404040_60)
@@ -140,9 +210,45 @@ class UIInventoryFull(
private val weightBarWidth = 60f private val weightBarWidth = 60f
private var xEnd = (Terrarum.WIDTH + internalWidth).div(2).toFloat()
private var yEnd = (Terrarum.HEIGHT + internalHeight).div(2).toFloat()
fun requestTransition(target: Int) {
if (!transitionOngoing) {
transitionRequested = true
transitionReqSource = currentScreen.round()
transitionReqTarget = target.toFloat()
}
}
override fun renderUI(batch: SpriteBatch, camera: Camera) { override fun renderUI(batch: SpriteBatch, camera: Camera) {
val xEnd = (Terrarum.WIDTH + internalWidth).div(2).toFloat()
val yEnd = (Terrarum.HEIGHT + internalHeight).div(2).toFloat() if (transitionRequested && !transitionOngoing) {
transitionRequested = false
transitionOngoing = true
transitionTimer = 0f
}
if (transitionOngoing) {
transitionTimer += Gdx.graphics.deltaTime
currentScreen = UIUtils.moveQuick(transitionReqSource, transitionReqTarget, transitionTimer, transitionLength)
if (transitionTimer > transitionLength) {
transitionOngoing = false
currentScreen = transitionReqTarget
}
}
// update at render time
updateTransitionalItems()
if (debugvals) {
batch.color = Color.WHITE
AppLoader.fontSmallNumbers.draw(batch, "screen:$currentScreen", 500f, 20f)
}
// background fill // background fill
@@ -167,32 +273,111 @@ class UIInventoryFull(
// UI items // UI items
categoryBar.render(batch, camera) categoryBar.render(batch, camera)
itemList?.render(batch, camera)
equipped?.render(batch, camera)
if (currentScreen > 1f + epsilon) {
renderScreenMinimap(batch, camera)
if (debugvals) {
batch.color = Color.CORAL
AppLoader.fontSmallNumbers.draw(batch, "Map", 300f, 10f)
}
}
if (currentScreen in epsilon..2f - epsilon) {
renderScreenInventory(batch, camera)
if (debugvals) {
batch.color = Color.CHARTREUSE
AppLoader.fontSmallNumbers.draw(batch, "Inv", 350f, 10f)
}
}
if (currentScreen < 1f - epsilon) {
renderScreenGamemenu(batch, camera)
if (debugvals) {
batch.color = Color.SKY
AppLoader.fontSmallNumbers.draw(batch, "Men", 400f, 10f)
}
}
if (debugvals) {
batch.color = Color.WHITE
AppLoader.fontSmallNumbers.draw(batch, "inventoryScrOffX:$inventoryScrOffX", 500f, 10f)
}
}
private val epsilon = 0.001f
private val minimapScrOffX: Float
get() = (currentScreen - 2f) * Terrarum.WIDTH
/**
* - 0 on inventory screen
* - +WIDTH on minimap screen
* - -WIDTH on gamemenu screen
*/
private val inventoryScrOffX: Float
get() = (currentScreen - 1f) * Terrarum.WIDTH
private val menuScrOffX: Float
get() = (currentScreen) * Terrarum.WIDTH
private fun renderScreenMinimap(batch: SpriteBatch, camera: Camera) {
// control hints
blendNormal(batch)
batch.color = Color.WHITE
Terrarum.fontGame.draw(batch, minimapControlHelp, offsetX + minimapScrOffX, yEnd - 20)
}
private fun renderScreenGamemenu(batch: SpriteBatch, camera: Camera) {
// control hints
blendNormal(batch)
batch.color = Color.WHITE
Terrarum.fontGame.draw(batch, gameMenuControlHelp, offsetX + menuScrOffX, yEnd - 20)
// text buttons
gameMenuButtons.render(batch, camera)
// character info window
// !! DUMMY !!
batch.color = itemList.backColour
batch.fillRect(
((Terrarum.WIDTH - 400) / 2) + menuScrOffX,
(itemList.height - gameMenuListTotalHeight) / 2 + itemList.posY.toFloat(),
gameMenuListWidth.toFloat(),
64f
)
}
private fun renderScreenInventory(batch: SpriteBatch, camera: Camera) {
itemList.render(batch, camera)
equipped.render(batch, camera)
// control hints // control hints
blendNormal(batch) blendNormal(batch)
batch.color = Color.WHITE batch.color = Color.WHITE
Terrarum.fontGame.draw(batch, listControlHelp, offsetX, offsetY + internalHeight) Terrarum.fontGame.draw(batch, listControlHelp, offsetX + inventoryScrOffX, yEnd - 20)
// encumbrance meter // encumbrance meter
if (actor != null) {
val encumbranceText = Lang["GAME_INVENTORY_ENCUMBRANCE"] val encumbranceText = Lang["GAME_INVENTORY_ENCUMBRANCE"]
Terrarum.fontGame.draw(batch, Terrarum.fontGame.draw(batch,
encumbranceText, encumbranceText,
xEnd - 9 - Terrarum.fontGame.getWidth(encumbranceText) - weightBarWidth, xEnd - 9 - Terrarum.fontGame.getWidth(encumbranceText) - weightBarWidth + inventoryScrOffX,
yEnd yEnd-20
) )
// encumbrance bar background // encumbrance bar background
blendMul(batch) blendMul(batch)
batch.color = Color(0xa0a0a0_ff.toInt()) batch.color = Color(0xa0a0a0_ff.toInt())
batch.fillRect( batch.fillRect(
xEnd - 3 - weightBarWidth, xEnd - 3 - weightBarWidth + inventoryScrOffX,
yEnd + 3f, yEnd-20 + 3f,
weightBarWidth, weightBarWidth,
controlHelpHeight - 6f controlHelpHeight - 6f
) )
@@ -200,33 +385,29 @@ class UIInventoryFull(
blendNormal(batch) blendNormal(batch)
batch.color = if (isEncumbered) Color(0xff0000_cc.toInt()) else Color(0x00ff00_cc.toInt()) batch.color = if (isEncumbered) Color(0xff0000_cc.toInt()) else Color(0x00ff00_cc.toInt())
batch.fillRect( batch.fillRect(
xEnd - 3 - weightBarWidth, xEnd - 3 - weightBarWidth + inventoryScrOffX,
yEnd + 3f, yEnd-20 + 3f,
if (actor?.inventory?.capacityMode == CAPACITY_MODE_NO_ENCUMBER) if (actor.inventory.capacityMode == CAPACITY_MODE_NO_ENCUMBER)
1f 1f
else // make sure 1px is always be seen else // make sure 1px is always be seen
minOf(weightBarWidth, maxOf(1f, weightBarWidth * encumbrancePerc)), minOf(weightBarWidth, maxOf(1f, weightBarWidth * encumbrancePerc)),
controlHelpHeight - 5f controlHelpHeight - 5f
) )
} }
}
fun rebuildList() { fun rebuildList() {
itemList?.rebuild() itemList.rebuild()
equipped?.rebuild() equipped.rebuild()
actor?.let { encumbrancePerc = actor.inventory.capacity.toFloat() / actor.inventory.maxCapacity
encumbrancePerc = actor!!.inventory.capacity.toFloat() / actor!!.inventory.maxCapacity isEncumbered = actor.inventory.isEncumbered
isEncumbered = actor!!.inventory.isEncumbered
}
} }
override fun dispose() { override fun dispose() {
categoryBar.dispose() categoryBar.dispose()
itemList?.dispose() itemList.dispose()
equipped?.dispose() equipped.dispose()
} }
@@ -243,7 +424,7 @@ class UIInventoryFull(
} }
override fun endClosing(delta: Float) { override fun endClosing(delta: Float) {
(Terrarum.ingame as? Ingame)?.setTooltipMessage(null) // required!! (Terrarum.ingame as? Ingame)?.setTooltipMessage(null) // required!
} }
@@ -253,6 +434,9 @@ class UIInventoryFull(
offsetX = ((Terrarum.WIDTH - internalWidth) / 2).toFloat() offsetX = ((Terrarum.WIDTH - internalWidth) / 2).toFloat()
offsetY = ((Terrarum.HEIGHT - internalHeight) / 2).toFloat() offsetY = ((Terrarum.HEIGHT - internalHeight) / 2).toFloat()
xEnd = (Terrarum.WIDTH + internalWidth).div(2).toFloat()
yEnd = (Terrarum.HEIGHT + internalHeight).div(2).toFloat()
} }

View File

@@ -10,6 +10,7 @@ import net.torvald.terrarum.itemproperties.ItemCodex
import net.torvald.terrarum.modulebasegame.Ingame import net.torvald.terrarum.modulebasegame.Ingame
import net.torvald.terrarum.modulebasegame.gameactors.ActorInventory import net.torvald.terrarum.modulebasegame.gameactors.ActorInventory
import net.torvald.terrarum.modulebasegame.gameactors.InventoryPair import net.torvald.terrarum.modulebasegame.gameactors.InventoryPair
import net.torvald.terrarum.modulebasegame.ui.ItemSlotImageFactory.CELLCOLOUR_BLACK
import net.torvald.terrarum.ui.UIItem import net.torvald.terrarum.ui.UIItem
import net.torvald.terrarum.ui.UIItemImageButton import net.torvald.terrarum.ui.UIItemImageButton
import java.util.* import java.util.*
@@ -32,8 +33,14 @@ class UIItemInventoryDynamicList(
override var posY: Int override var posY: Int
) : UIItem(parentUI) { ) : UIItem(parentUI) {
override val width = 496 // deal with the moving position
override val height = 384 override var oldPosX = posX
override var oldPosY = posY
override val width = WIDTH
override val height = HEIGHT
val backColour = CELLCOLOUR_BLACK
private val catArrangement = parentUI.catArrangement private val catArrangement = parentUI.catArrangement
@@ -74,35 +81,44 @@ class UIItemInventoryDynamicList(
val defaultTextColour = Color(0xeaeaea_ff.toInt()) val defaultTextColour = Color(0xeaeaea_ff.toInt())
private val listGap = 8 companion object {
private val itemList = Array<UIItemInventoryCellBase>(7 * 2) { const val listGap = 8
UIItemInventoryElem( const val horizontalCells = 11
const val verticalCells = 8
val largeListWidth = (horizontalCells * UIItemInventoryElemSimple.height + (horizontalCells - 2) * listGap) / 2
val WIDTH = horizontalCells * UIItemInventoryElemSimple.height + (horizontalCells - 1) * listGap
val HEIGHT = verticalCells * UIItemInventoryElemSimple.height + (verticalCells - 1) * listGap
}
private val itemGrid = Array<UIItemInventoryCellBase>(horizontalCells * verticalCells) {
UIItemInventoryElemSimple(
parentUI = inventoryUI, parentUI = inventoryUI,
posX = this.posX + (272 + listGap) * (it % 2), posX = this.posX + (UIItemInventoryElemSimple.height + listGap) * (it % horizontalCells),
posY = this.posY + (UIItemInventoryElem.height + listGap) * (it / 2), posY = this.posY + (UIItemInventoryElemSimple.height + listGap) * (it / horizontalCells),
width = 272,
item = null, item = null,
amount = UIItemInventoryElem.UNIQUE_ITEM_HAS_NO_AMOUNT, amount = UIItemInventoryElem.UNIQUE_ITEM_HAS_NO_AMOUNT,
itemImage = null, itemImage = null,
mouseoverBackCol = Color(0x282828_ff), mouseoverBackCol = Color(0x282828_ff),
mouseoverBackBlendMode = BlendMode.SCREEN, mouseoverBackBlendMode = BlendMode.SCREEN,
backCol = Color(0x404040_88), backCol = backColour,
backBlendMode = BlendMode.NORMAL, backBlendMode = BlendMode.NORMAL,
drawBackOnNull = true, drawBackOnNull = true,
inactiveTextCol = defaultTextColour inactiveTextCol = defaultTextColour
) )
} }
private val itemGrid = Array<UIItemInventoryCellBase>(7 * 10) { private val itemList = Array<UIItemInventoryCellBase>(verticalCells * 2) {
UIItemInventoryElemSimple( UIItemInventoryElem(
parentUI = inventoryUI, parentUI = inventoryUI,
posX = this.posX + (UIItemInventoryElemSimple.height + listGap) * (it % 10), posX = this.posX + (largeListWidth + listGap) * (it % 2),
posY = this.posY + (UIItemInventoryElemSimple.height + listGap) * (it / 10), posY = this.posY + (UIItemInventoryElem.height + listGap) * (it / 2),
width = largeListWidth,
item = null, item = null,
amount = UIItemInventoryElem.UNIQUE_ITEM_HAS_NO_AMOUNT, amount = UIItemInventoryElem.UNIQUE_ITEM_HAS_NO_AMOUNT,
itemImage = null, itemImage = null,
mouseoverBackCol = Color(0x282828_ff), mouseoverBackCol = Color(0x282828_ff),
mouseoverBackBlendMode = BlendMode.SCREEN, mouseoverBackBlendMode = BlendMode.SCREEN,
backCol = Color(0x404040_88), backCol = backColour,
backBlendMode = BlendMode.NORMAL, backBlendMode = BlendMode.NORMAL,
drawBackOnNull = true, drawBackOnNull = true,
inactiveTextCol = defaultTextColour inactiveTextCol = defaultTextColour
@@ -196,6 +212,15 @@ class UIItemInventoryDynamicList(
private val upDownButtonGapToDots = 7 // apparent gap may vary depend on the texture itself private val upDownButtonGapToDots = 7 // apparent gap may vary depend on the texture itself
override fun render(batch: SpriteBatch, camera: Camera) { override fun render(batch: SpriteBatch, camera: Camera) {
val posXDelta = posX - oldPosX
itemGrid.forEach { it.posX += posXDelta }
itemList.forEach { it.posX += posXDelta }
gridModeButtons.forEach { it.posX += posXDelta }
scrollUpButton.posX += posXDelta
scrollDownButton.posX += posXDelta
fun getScrollDotYHeight(i: Int) = scrollUpButton.posY + 10 + upDownButtonGapToDots + 10 * i fun getScrollDotYHeight(i: Int) = scrollUpButton.posY + 10 + upDownButtonGapToDots + 10 * i
scrollDownButton.posY = getScrollDotYHeight(itemPageCount) + upDownButtonGapToDots scrollDownButton.posY = getScrollDotYHeight(itemPageCount) + upDownButtonGapToDots
@@ -221,6 +246,8 @@ class UIItemInventoryDynamicList(
} }
super.render(batch, camera) super.render(batch, camera)
oldPosX = posX
} }

View File

@@ -8,6 +8,7 @@ import net.torvald.terrarum.gameactors.ActorWBMovable
import net.torvald.terrarum.itemproperties.GameItem import net.torvald.terrarum.itemproperties.GameItem
import net.torvald.terrarum.itemproperties.ItemCodex import net.torvald.terrarum.itemproperties.ItemCodex
import net.torvald.terrarum.modulebasegame.gameactors.ActorInventory import net.torvald.terrarum.modulebasegame.gameactors.ActorInventory
import net.torvald.terrarum.modulebasegame.ui.ItemSlotImageFactory.CELLCOLOUR_BLACK
import net.torvald.terrarum.ui.UIItem import net.torvald.terrarum.ui.UIItem
/** /**
@@ -21,12 +22,12 @@ class UIItemInventoryEquippedView(
override var posY: Int override var posY: Int
) : UIItem(parentUI) { ) : UIItem(parentUI) {
override val width = 104 override val width = WIDTH
override val height = 384 override val height = HEIGHT
companion object { companion object {
val width = 104 val WIDTH = 2 * UIItemInventoryElemSimple.height + UIItemInventoryDynamicList.listGap
val height = 384 val HEIGHT = UIItemInventoryDynamicList.HEIGHT
} }
private val listGap = 8 private val listGap = 8
@@ -37,9 +38,9 @@ class UIItemInventoryEquippedView(
lateinit var inventorySortList: Array<GameItem?> lateinit var inventorySortList: Array<GameItem?>
private var rebuildList = true private var rebuildList = true
val spriteViewBackCol: Color; get() = Color(0x404040_88.toInt())//Color(0xd4d4d4_ff.toInt()) val spriteViewBackCol: Color = CELLCOLOUR_BLACK
private val itemGrid = Array<UIItemInventoryCellBase>(2 * 5) { private val itemGrid = Array<UIItemInventoryCellBase>(2 * 6) {
UIItemInventoryElemSimple( UIItemInventoryElemSimple(
parentUI = parentUI, parentUI = parentUI,
posX = this.posX + (UIItemInventoryElemSimple.height + listGap) * ((it + 4) % 2), posX = this.posX + (UIItemInventoryElemSimple.height + listGap) * ((it + 4) % 2),
@@ -49,7 +50,7 @@ class UIItemInventoryEquippedView(
itemImage = null, itemImage = null,
mouseoverBackCol = Color(0x282828_ff), mouseoverBackCol = Color(0x282828_ff),
mouseoverBackBlendMode = BlendMode.SCREEN, mouseoverBackBlendMode = BlendMode.SCREEN,
backCol = Color(0x404040_88), backCol = CELLCOLOUR_BLACK,
backBlendMode = BlendMode.NORMAL, backBlendMode = BlendMode.NORMAL,
drawBackOnNull = true drawBackOnNull = true
) )
@@ -60,7 +61,18 @@ class UIItemInventoryEquippedView(
itemGrid.forEach { it.update(delta) } itemGrid.forEach { it.update(delta) }
} }
private val spriteDrawCol = Color(0xddddddff.toInt())
// deal with the moving position
override var oldPosX = posX
override var oldPosY = posY
override fun render(batch: SpriteBatch, camera: Camera) { override fun render(batch: SpriteBatch, camera: Camera) {
val posXDelta = posX - oldPosX
itemGrid.forEach { it.posX += posXDelta }
// sprite background // sprite background
blendNormal(batch) blendNormal(batch)
batch.color = spriteViewBackCol batch.color = spriteViewBackCol
@@ -74,51 +86,49 @@ class UIItemInventoryEquippedView(
sprite?.let { sprite?.let {
blendNormal(batch) blendNormal(batch)
it.render( batch.color = spriteDrawCol
batch, batch.draw(
it.textureRegion.get(0, 0),
posX + (width - it.cellWidth).div(2).toFloat(), posX + (width - it.cellWidth).div(2).toFloat(),
posY + (width - it.cellHeight).div(2).toFloat() posY + (width - it.cellHeight).div(2).toFloat()
) } )
itemGrid.forEach { it.render(batch, camera) }
} }
// TODO inscribe slot image on each cells HERE
itemGrid.forEach { it.render(batch, camera) }
oldPosX = posX
}
internal fun rebuild() { internal fun rebuild() {
inventorySortList = inventory.itemEquipped.clone()
rebuildList = false rebuildList = false
// sort by equip position // sort by equip position
// fill the grid from fastest index, make no gap in-between of slots // fill the grid from fastest index, make no gap in-between of slots
var listPushCnt = 0
for (k in 0 until itemGrid.size) { for (k in 0 until itemGrid.size) {
val it = inventorySortList[k] val item = inventory.itemEquipped[k]
if (it != null) { if (item == null) {
val itemRecord = inventory.getByDynamicID(it.dynamicID)!!
itemGrid[listPushCnt].item = it itemGrid[k].item = null
itemGrid[listPushCnt].amount = itemRecord.amount itemGrid[k].amount = 0
itemGrid[listPushCnt].itemImage = ItemCodex.getItemImage(it) itemGrid[k].itemImage = null
itemGrid[listPushCnt].quickslot = null // don't need to be displayed itemGrid[k].quickslot = null
itemGrid[listPushCnt].equippedSlot = null // don't need to be displayed itemGrid[k].equippedSlot = null
listPushCnt++
}
} }
else {
val itemRecord = inventory.getByDynamicID(item.dynamicID)!!
// empty out un-filled grids from previous garbage itemGrid[k].item = item
for (m in listPushCnt until itemGrid.size) { itemGrid[k].amount = itemRecord.amount
itemGrid[m].item = null itemGrid[k].itemImage = ItemCodex.getItemImage(item)
itemGrid[m].amount = 0 itemGrid[k].quickslot = null // don't need to be displayed
itemGrid[m].itemImage = null itemGrid[k].equippedSlot = null // don't need to be displayed
itemGrid[m].quickslot = null }
itemGrid[m].equippedSlot = null
} }
} }

View File

@@ -18,6 +18,10 @@ class UIItemModuleInfoCell(
override var posY: Int override var posY: Int
) : UIItem(parent) { ) : UIItem(parent) {
// deal with the moving position
override var oldPosX = posX
override var oldPosY = posY
override val height: Int = Terrarum.fontGame.lineHeight.toInt() * 2 override val height: Int = Terrarum.fontGame.lineHeight.toInt() * 2
private val numberAreaWidth = Terrarum.fontSmallNumbers.W * 3 + 4 private val numberAreaWidth = Terrarum.fontSmallNumbers.W * 3 + 4

View File

@@ -20,6 +20,10 @@ class UIItemSavegameInfoCell(
override var posY: Int override var posY: Int
) : UIItem(parent) { ) : UIItem(parent) {
// deal with the moving position
override var oldPosX = posX
override var oldPosY = posY
override val height: Int = Terrarum.fontGame.lineHeight.toInt() * 2 override val height: Int = Terrarum.fontGame.lineHeight.toInt() * 2
override fun render(batch: SpriteBatch, camera: Camera) { override fun render(batch: SpriteBatch, camera: Camera) {

View File

@@ -41,6 +41,8 @@ class UIQuickslotBar : UICanvas() {
override fun updateUI(delta: Float) { override fun updateUI(delta: Float) {
} }
private val drawColor = Color(1f,1f,1f,1f)
override fun renderUI(batch: SpriteBatch, camera: Camera) { override fun renderUI(batch: SpriteBatch, camera: Camera) {
for (i in 0..SLOT_COUNT - 1) { for (i in 0..SLOT_COUNT - 1) {
@@ -55,7 +57,8 @@ class UIQuickslotBar : UICanvas() {
val slotY = cellSize / 2 val slotY = cellSize / 2
// draw slots // draw slots
batch.color = Color(1f, 1f, 1f, handler.opacity * DISPLAY_OPACITY) drawColor.a = handler.opacity * DISPLAY_OPACITY
batch.color = drawColor
image.draw(batch, slotX, slotY) image.draw(batch, slotX, slotY)
} }

View File

@@ -8,9 +8,7 @@ import net.torvald.terrarum.*
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension
import net.torvald.terrarum.modulebasegame.gameworld.WorldTime import net.torvald.terrarum.modulebasegame.gameworld.WorldTime
import net.torvald.terrarum.modulebasegame.imagefont.Watch7SegMain import net.torvald.terrarum.modulebasegame.imagefont.WatchFont
import net.torvald.terrarum.modulebasegame.imagefont.Watch7SegSmall
import net.torvald.terrarum.modulebasegame.imagefont.WatchDotAlph
import net.torvald.terrarum.ui.UICanvas import net.torvald.terrarum.ui.UICanvas
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
@@ -18,28 +16,26 @@ import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
* Created by minjaesong on 2017-06-11. * Created by minjaesong on 2017-06-11.
*/ */
class UITierOneWatch(private val player: ActorHumanoid?) : UICanvas() { class UITierOneWatch(private val player: ActorHumanoid?) : UICanvas() {
override var width = 77 override var width = 160
override var height = 53 override var height = 23
override var openCloseTime: Second = 0f override var openCloseTime: Second = 0f
private var ELuptimer = 10f // init value higher than uptime: to make the light turned off by default private var ELuptimer = 10f // init value higher than uptime: to make the light turned off by default
private val ELuptime = 4f private val ELuptime = 4f
private var ELon = false private var ELon = false
private var atlas = TextureRegionPack(ModMgr.getPath("basegame", "gui/watchface2_atlas.tga"), width, height) private var atlas = TextureRegionPack(ModMgr.getPath("basegame", "gui/watchface_atlas.tga"), width, height)
private var littleFont = Watch7SegSmall private var watchFont = WatchFont
private var timeFont = Watch7SegMain
private var textFont = WatchDotAlph
private var moonDial = TextureRegionPack(ModMgr.getPath("basegame", "fonts/watch_17pxmoondial.tga"), 17, 17) private var moonDial = TextureRegionPack(ModMgr.getPath("basegame", "fonts/watch_17pxmoondial.tga"), 17, 17)
private var moonDialCount = moonDial.horizontalCount private var moonDialCount = moonDial.horizontalCount
private val drawCol = Color(1f,1f,1f,0.5f) private val drawCol = Color(1f,1f,1f,UIQuickslotBar.DISPLAY_OPACITY)
private val lcdLitColELoff = Color(0x141414_aa) private val lcdLitColELoff = Color(0xc0c0c0ff.toInt()) mul drawCol
private val lcdLitColELon = Color(0x141414_ff) private val lcdLitColELon = Color(0x404040ff) mul drawCol
private val lcdLitCol: Color private val lcdLitCol: Color = lcdLitColELoff
get() = if (ELon) lcdLitColELon else lcdLitColELoff //get() = if (ELon) lcdLitColELon else lcdLitColELoff
private val worldTime: WorldTime private val worldTime: WorldTime
get() = (Terrarum.ingame!!.world as GameWorldExtension).time get() = (Terrarum.ingame!!.world as GameWorldExtension).time
@@ -62,33 +58,30 @@ class UITierOneWatch(private val player: ActorHumanoid?) : UICanvas() {
override fun renderUI(batch: SpriteBatch, camera: Camera) { override fun renderUI(batch: SpriteBatch, camera: Camera) {
// light overlay or EL // light overlay or EL
/*blendNormal(batch)
if (ELon) { if (ELon) {
blendNormal(batch)
batch.draw(atlas.get(0, 2), 0f, 0f) batch.draw(atlas.get(0, 2), 0f, 0f)
} }
else { else {
// backplate // backplate
batch.draw(atlas.get(0, 0), 0f, 0f)
}*/
// disabling light button
batch.color = drawCol batch.color = drawCol
batch.draw(atlas.get(0, 0), 0f, 0f) batch.draw(atlas.get(0, 0), 0f, 0f)
}
// LCD back
blendNormal(batch)
batch.draw(atlas.get(0, 3), 0f, 0f)
// day name // day name
batch.color = lcdLitCol batch.color = lcdLitCol
textFont.draw(batch, worldTime.getDayNameShort().toUpperCase(), 9f, 5f) watchFont.draw(batch, worldTime.getDayNameShort().toUpperCase(), 73f, 7f)
// day // day
littleFont.draw(batch, worldTime.days.toString().padStart(2, ' '), 54f, 4f) watchFont.draw(batch, worldTime.days.toString().padStart(2, '@'), 107f, 7f)
// hour // hour
timeFont.draw(batch, worldTime.hours.toString().padStart(2, '/'), 25f, 31f) watchFont.draw(batch, worldTime.hours.toString().padStart(2, '@'), 27f, 7f)
// minute // minute
timeFont.draw(batch, worldTime.minutes.toString().padStart(2, '0'), 53f, 31f) watchFont.draw(batch, worldTime.minutes.toString().padStart(2, '0'), 49f, 7f)
// season marker // season marker
batch.draw(atlas.get(1, worldTime.months - 1), 0f, 0f) batch.draw(atlas.get(1, worldTime.months - 1), 0f, 0f)
@@ -97,7 +90,7 @@ class UITierOneWatch(private val player: ActorHumanoid?) : UICanvas() {
// moon dial // moon dial
val moonPhase = (worldTime.moonPhase * moonDialCount).roundInt() % moonDialCount val moonPhase = (worldTime.moonPhase * moonDialCount).roundInt() % moonDialCount
batch.color = lcdLitCol batch.color = lcdLitCol
batch.draw(moonDial.get(moonPhase, 0), 4f, 19f) batch.draw(moonDial.get(moonPhase, 0), 6f, 3f)
} }
override fun doOpening(delta: Float) { override fun doOpening(delta: Float) {

View File

@@ -1,9 +1,7 @@
package net.torvald.terrarum.modulebasegame.ui package net.torvald.terrarum.modulebasegame.ui
import net.torvald.terrarum.AppLoader import net.torvald.terrarum.AppLoader
import net.torvald.terrarum.QNDTreeNode
import net.torvald.terrarum.Yaml import net.torvald.terrarum.Yaml
import java.util.*
@@ -24,12 +22,14 @@ object UITitleRemoConYaml {
- MENU_OPTIONS - MENU_OPTIONS
- MENU_OPTIONS_GRAPHICS - MENU_OPTIONS_GRAPHICS
- MENU_OPTIONS_CONTROLS - MENU_OPTIONS_CONTROLS
- MENU_CONTROLS_KEYBOARD
- MENU_CONTROLS_GAMEPAD
- MENU_LABEL_RETURN
- MENU_OPTIONS_SOUND - MENU_OPTIONS_SOUND
- MENU_LABEL_LANGUAGE : net.torvald.terrarum.modulebasegame.ui.UITitleLanguage
- MENU_LABEL_RETURN - MENU_LABEL_RETURN
- MENU_MODULES : net.torvald.terrarum.modulebasegame.ui.UITitleModules - MENU_MODULES : net.torvald.terrarum.modulebasegame.ui.UITitleModules
- MENU_LABEL_RETURN - MENU_LABEL_RETURN
- MENU_LABEL_LANGUAGE : net.torvald.terrarum.modulebasegame.ui.UITitleLanguage
- MENU_LABEL_RETURN
- MENU_LABEL_CREDITS : net.torvald.terrarum.modulebasegame.ui.UITitleCredits - MENU_LABEL_CREDITS : net.torvald.terrarum.modulebasegame.ui.UITitleCredits
- MENU_LABEL_CREDITS : net.torvald.terrarum.modulebasegame.ui.UITitleCredits - MENU_LABEL_CREDITS : net.torvald.terrarum.modulebasegame.ui.UITitleCredits
- MENU_CREDIT_GPL_DNT : net.torvald.terrarum.modulebasegame.ui.UITitleGPL3 - MENU_CREDIT_GPL_DNT : net.torvald.terrarum.modulebasegame.ui.UITitleGPL3

View File

@@ -57,6 +57,8 @@ class uiQuickslotPie : UICanvas() {
} }
} }
private val drawColor = Color(1f,1f,1f,1f)
override fun renderUI(batch: SpriteBatch, camera: Camera) { override fun renderUI(batch: SpriteBatch, camera: Camera) {
// draw radial thingies // draw radial thingies
for (i in 0..slotCount - 1) { for (i in 0..slotCount - 1) {
@@ -75,7 +77,8 @@ class uiQuickslotPie : UICanvas() {
val slotX = slotCentrePoint.x.toInt() val slotX = slotCentrePoint.x.toInt()
val slotY = slotCentrePoint.y.toInt() val slotY = slotCentrePoint.y.toInt()
batch.color = Color(1f, 1f, 1f, handler.opacity * UIQuickslotBar.DISPLAY_OPACITY) drawColor.a = handler.opacity * UIQuickslotBar.DISPLAY_OPACITY
batch.color = drawColor
image.draw(batch, slotX, slotY) image.draw(batch, slotX, slotY)
} }

View File

@@ -2,25 +2,26 @@ package net.torvald.terrarum.modulebasegame.weather
import com.badlogic.gdx.Gdx import com.badlogic.gdx.Gdx
import com.badlogic.gdx.Input import com.badlogic.gdx.Input
import com.badlogic.gdx.graphics.* import com.badlogic.gdx.graphics.Camera
import com.badlogic.gdx.utils.GdxRuntimeException import com.badlogic.gdx.graphics.Color
import net.torvald.terrarum.utils.JsonFetcher import com.badlogic.gdx.graphics.GL20
import net.torvald.colourutil.* import com.badlogic.gdx.graphics.Texture
import net.torvald.colourutil.CIELuvUtil
import net.torvald.random.HQRNG import net.torvald.random.HQRNG
import net.torvald.terrarum.* import net.torvald.terrarum.GdxColorMap
import net.torvald.terrarum.console.CommandDict import net.torvald.terrarum.ModMgr
import net.torvald.terrarum.console.SetGlobalLightOverride import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.gameactors.ActorWithBody import net.torvald.terrarum.gameactors.ActorWithBody
import net.torvald.terrarum.modulebasegame.gameactors.ParticleMegaRain
import net.torvald.terrarum.gamecontroller.KeyToggler import net.torvald.terrarum.gamecontroller.KeyToggler
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.modulebasegame.Ingame import net.torvald.terrarum.modulebasegame.Ingame
import net.torvald.terrarum.modulebasegame.RNGConsumer import net.torvald.terrarum.modulebasegame.RNGConsumer
import net.torvald.terrarum.modulebasegame.gameactors.ParticleMegaRain
import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension
import net.torvald.terrarum.modulebasegame.gameworld.WorldTime import net.torvald.terrarum.modulebasegame.gameworld.WorldTime
import net.torvald.terrarum.modulebasegame.worldgenerator.WorldGenerator
import net.torvald.terrarum.utils.JsonFetcher
import net.torvald.terrarum.worlddrawer.FeaturesDrawer import net.torvald.terrarum.worlddrawer.FeaturesDrawer
import net.torvald.terrarum.worlddrawer.WorldCamera import net.torvald.terrarum.worlddrawer.WorldCamera
import net.torvald.terrarum.modulebasegame.worldgenerator.WorldGenerator
import java.io.File import java.io.File
import java.util.* import java.util.*
@@ -96,7 +97,7 @@ internal object WeatherMixer : RNGConsumer {
// test rain toggled by F2 // test rain toggled by F2
if (KeyToggler.isOn(Input.Keys.F2)) { if (KeyToggler.isOn(Input.Keys.F2) && Terrarum.ingame is Ingame) {
val playerPosX = player.hitbox.centeredX val playerPosX = player.hitbox.centeredX
val playerPosY = player.hitbox.centeredY val playerPosY = player.hitbox.centeredY
kotlin.repeat(7) { kotlin.repeat(7) {

View File

@@ -0,0 +1,62 @@
import kotlin.system.measureNanoTime
/**
* Created by minjaesong on 2019-01-27.
*/
class FixedMathTest {
fun invoke() {
val testSet = (1..100000).toList().shuffled()
val m1 = measureNanoTime {
testSet.forEach {
val x = (it * 1.41421356f)
}
}
val testSet2 = (1..100000).toList().shuffled()
val m2 = measureNanoTime {
testSet2.forEach {
val x2 = it.mulSqrt2()
}
}
val m3 = measureNanoTime {
testSet.forEach {
val x = (it * 1.41421356f)
}
}
val m4 = measureNanoTime {
testSet2.forEach {
val x2 = it.mulSqrt2()
}
}
println(m3)
println(m4)
println(m3.toDouble() / m4)
}
fun Int.mulSqrt2(): Int {
val xl = this
val yl = 92681
val xlo = xl and 0x0000FFFF
val xhi = xl shr 16
val ylo = yl and 0x0000FFFF
val yhi = yl shr 16
val lolo = xlo * ylo
val lohi = xlo * yhi
val hilo = xhi * ylo
val hihi = xhi * yhi
val loResult = lolo shr 16
val hiResult = hihi shl 16
val sum = loResult + lohi + hilo + hiResult
return sum
}
}
fun main(args: Array<String>) {
FixedMathTest().invoke()
}

View File

@@ -1,11 +1,12 @@
package net.torvald.terrarum.tests package net.torvald.terrarum.tests
import com.badlogic.gdx.* import com.badlogic.gdx.Gdx
import com.badlogic.gdx.InputAdapter
import com.badlogic.gdx.ScreenAdapter
import com.badlogic.gdx.backends.lwjgl.LwjglApplication import com.badlogic.gdx.backends.lwjgl.LwjglApplication
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration
import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.OrthographicCamera import com.badlogic.gdx.graphics.OrthographicCamera
import com.badlogic.gdx.graphics.Texture
import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.badlogic.gdx.graphics.g2d.SpriteBatch
import com.badlogic.gdx.graphics.glutils.ShaderProgram import com.badlogic.gdx.graphics.glutils.ShaderProgram
import net.torvald.terrarum.* import net.torvald.terrarum.*

View File

@@ -8,6 +8,7 @@ import com.jme3.math.FastMath
import net.torvald.terrarum.* import net.torvald.terrarum.*
import net.torvald.terrarum.Terrarum.mouseTileX import net.torvald.terrarum.Terrarum.mouseTileX
import net.torvald.terrarum.Terrarum.mouseTileY import net.torvald.terrarum.Terrarum.mouseTileY
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.modulebasegame.Ingame import net.torvald.terrarum.modulebasegame.Ingame
import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension
import net.torvald.terrarum.worlddrawer.FeaturesDrawer import net.torvald.terrarum.worlddrawer.FeaturesDrawer
@@ -19,8 +20,8 @@ import net.torvald.terrarum.worlddrawer.WorldCamera
*/ */
class BasicDebugInfoWindow : UICanvas() { class BasicDebugInfoWindow : UICanvas() {
override var width: Int = Terrarum.WIDTH override var width: Int = AppLoader.screenW
override var height: Int = Terrarum.HEIGHT override var height: Int = AppLoader.screenH
override var openCloseTime: Float = 0f override var openCloseTime: Float = 0f
@@ -30,14 +31,17 @@ class BasicDebugInfoWindow : UICanvas() {
private var xdelta = 0.0 private var xdelta = 0.0
private var ydelta = 0.0 private var ydelta = 0.0
private val ingame = Terrarum.ingame!! as Ingame private val ingame: IngameInstance?
get() = Terrarum.ingame
private val world: GameWorldExtension private val world: GameWorld?
get() = Terrarum.ingame!!.world as GameWorldExtension get() = Terrarum.ingame?.world
private val world2: GameWorldExtension?
get() = Terrarum.ingame?.world as GameWorldExtension?
override fun updateUI(delta: Float) { override fun updateUI(delta: Float) {
val player = ingame.actorNowPlaying val player = ingame?.actorNowPlaying
val hitbox = player?.hitbox val hitbox = player?.hitbox
if (hitbox != null) { if (hitbox != null) {
@@ -65,7 +69,7 @@ class BasicDebugInfoWindow : UICanvas() {
} }
override fun renderUI(batch: SpriteBatch, camera: Camera) { override fun renderUI(batch: SpriteBatch, camera: Camera) {
val player = ingame.actorNowPlaying val player = ingame?.actorNowPlaying
batch.color = Color(0xFFEE88FF.toInt()) batch.color = Color(0xFFEE88FF.toInt())
@@ -108,11 +112,11 @@ class BasicDebugInfoWindow : UICanvas() {
+ ccG + ccG
+ "${WorldCamera.y}") + "${WorldCamera.y}")
printLine(batch, 3, "veloX reported $ccG${player.externalForce.x}") printLine(batch, 3, "veloX reported $ccG${player.externalV.x}")
printLine(batch, 4, "veloY reported $ccG${player.externalForce.y}") printLine(batch, 4, "veloY reported $ccG${player.externalV.y}")
printLine(batch, 5, "p_WalkX $ccG${player.controllerMoveDelta?.x}") printLine(batch, 5, "p_WalkX $ccG${player.controllerV?.x}")
printLine(batch, 6, "p_WalkY $ccG${player.controllerMoveDelta?.y}") printLine(batch, 6, "p_WalkY $ccG${player.controllerV?.y}")
printLineColumn(batch, 2, 3, "veloX measured $ccG${xdelta}") printLineColumn(batch, 2, 3, "veloX measured $ccG${xdelta}")
printLineColumn(batch, 2, 4, "veloY measured $ccG${ydelta}") printLineColumn(batch, 2, 4, "veloY measured $ccG${ydelta}")
@@ -144,12 +148,15 @@ class BasicDebugInfoWindow : UICanvas() {
else "$rawR $rawG $rawB $rawA" else "$rawR $rawG $rawB $rawA"
printLine(batch, 8, "light@cursor $ccG$lightVal") printLine(batch, 8, "light@cursor $ccG$lightVal")
val tileNum = ingame.world.getTileFromTerrain(mouseTileX, mouseTileY) ?: -1 if (ingame != null) {
val fluid = ingame.world.getFluid(mouseTileX, mouseTileY) val tileNum = ingame!!.world.getTileFromTerrain(mouseTileX, mouseTileY) ?: -1
val fluid = ingame!!.world.getFluid(mouseTileX, mouseTileY)
printLine(batch, 9, "tile@cursor $ccG$tileNum ($mtX, $mtY)") printLine(batch, 9, "tile@cursor $ccG$tileNum ($mtX, $mtY)")
printLine(batch, 10, "fluid@cursor ${ccY}Type $ccM${fluid.type.value} ${ccY}Fill $ccG${fluid.amount}f") printLine(batch, 10, "fluid@cursor ${ccY}Type $ccM${fluid.type.value} ${ccY}Fill $ccG${fluid.amount}f")
}
// print time // print time
var dbgCnt = 12 var dbgCnt = 12
@@ -166,8 +173,10 @@ class BasicDebugInfoWindow : UICanvas() {
//printLineColumn(batch, 2, 1, "VSync $ccG" + Terrarum.appgc.isVSyncRequested) //printLineColumn(batch, 2, 1, "VSync $ccG" + Terrarum.appgc.isVSyncRequested)
//printLineColumn(batch, 2, 2, "Env colour temp $ccG" + FeaturesDrawer.colTemp) //printLineColumn(batch, 2, 2, "Env colour temp $ccG" + FeaturesDrawer.colTemp)
printLineColumn(batch, 2, 5, "Time $ccG${world.time.todaySeconds.toString().padStart(5, '0')}" + if (world != null) {
" (${world.time.getFormattedTime()})") printLineColumn(batch, 2, 5, "Time $ccG${world2!!.time.todaySeconds.toString().padStart(5, '0')}" +
" (${world2!!.time.getFormattedTime()})")
}
if (player != null) { if (player != null) {
printLineColumn(batch, 2, 6, "Mass $ccG${player.mass}") printLineColumn(batch, 2, 6, "Mass $ccG${player.mass}")
@@ -182,10 +191,10 @@ class BasicDebugInfoWindow : UICanvas() {
batch.color = Color.WHITE batch.color = Color.WHITE
if (Terrarum.controller != null) { if (AppLoader.gamepad != null) {
drawGamepadAxis(batch, drawGamepadAxis(batch,
Terrarum.controller!!.getAxisValue(3), AppLoader.gamepad!!.getAxisValue(3),
Terrarum.controller!!.getAxisValue(2), AppLoader.gamepad!!.getAxisValue(2),
Terrarum.WIDTH - 135, Terrarum.WIDTH - 135,
40 40
) )
@@ -216,15 +225,18 @@ class BasicDebugInfoWindow : UICanvas() {
* Bottom left * Bottom left
*/ */
Terrarum.fontSmallNumbers.draw(batch, "${ccY}Actors total $ccG${ingame.actorContainer.size + ingame.actorContainerInactive.size}", if (ingame != null) {
Terrarum.fontSmallNumbers.draw(batch, "${ccY}Actors total $ccG${ingame!!.actorContainer.size + ingame!!.actorContainerInactive.size}",
2f, Terrarum.HEIGHT - 10f) 2f, Terrarum.HEIGHT - 10f)
Terrarum.fontSmallNumbers.draw(batch, "${ccY}Active $ccG${ingame.actorContainer.size}", Terrarum.fontSmallNumbers.draw(batch, "${ccY}Active $ccG${ingame!!.actorContainer.size}",
(2 + 17*8).toFloat(), Terrarum.HEIGHT - 10f) (2 + 17 * 8).toFloat(), Terrarum.HEIGHT - 10f)
Terrarum.fontSmallNumbers.draw(batch, "${ccY}Dormant $ccG${ingame.actorContainerInactive.size}", Terrarum.fontSmallNumbers.draw(batch, "${ccY}Dormant $ccG${ingame!!.actorContainerInactive.size}",
(2 + 28*8).toFloat(), Terrarum.HEIGHT - 10f) (2 + 28 * 8).toFloat(), Terrarum.HEIGHT - 10f)
Terrarum.fontSmallNumbers.draw(batch, "${ccM}Particles $ccG${ingame.particlesActive}", if (ingame is Ingame) {
(2 + 41*8).toFloat(), Terrarum.HEIGHT - 10f) Terrarum.fontSmallNumbers.draw(batch, "${ccM}Particles $ccG${(ingame as Ingame).particlesActive}",
(2 + 41 * 8).toFloat(), Terrarum.HEIGHT - 10f)
}
}
/** /**
* Bottom right * Bottom right
@@ -235,8 +247,8 @@ class BasicDebugInfoWindow : UICanvas() {
(Terrarum.WIDTH - 2 - totalHardwareName.length * 8).toFloat(), Terrarum.HEIGHT - 10f) (Terrarum.WIDTH - 2 - totalHardwareName.length * 8).toFloat(), Terrarum.HEIGHT - 10f)
} }
private val processorName = Terrarum.processor.replace(Regex(""" Processor|( CPU)? @ [0-9.]+GHz"""), "") private val processorName = AppLoader.processor.replace(Regex(""" Processor|( CPU)? @ [0-9.]+GHz"""), "")
private val rendererName = Terrarum.renderer private val rendererName = AppLoader.renderer
private val totalHardwareName = "$processorName $rendererName" private val totalHardwareName = "$processorName $rendererName"
private fun printLine(batch: SpriteBatch, l: Int, s: String) { private fun printLine(batch: SpriteBatch, l: Int, s: String) {
@@ -304,8 +316,8 @@ class BasicDebugInfoWindow : UICanvas() {
val pointDX = axisX * halfW val pointDX = axisX * halfW
val pointDY = axisY * halfH val pointDY = axisY * halfH
val padName = if (Terrarum.controller!!.name.isEmpty()) "Gamepad" val padName = if (AppLoader.gamepad!!.name.isEmpty()) "Gamepad"
else Terrarum.controller!!.name else AppLoader.gamepad!!.name
blendNormal(batch) blendNormal(batch)

View File

@@ -3,6 +3,7 @@ package net.torvald.terrarum.ui
import com.badlogic.gdx.Gdx import com.badlogic.gdx.Gdx
import com.badlogic.gdx.graphics.Camera import com.badlogic.gdx.graphics.Camera
import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.badlogic.gdx.graphics.g2d.SpriteBatch
import com.badlogic.gdx.utils.Disposable
import net.torvald.terrarum.AppLoader import net.torvald.terrarum.AppLoader
import net.torvald.terrarum.Second import net.torvald.terrarum.Second
import net.torvald.terrarum.Terrarum import net.torvald.terrarum.Terrarum
@@ -21,7 +22,7 @@ abstract class UICanvas(
// UI positions itself? (you must g.flush() yourself after the g.translate(Int, Int)) // UI positions itself? (you must g.flush() yourself after the g.translate(Int, Int))
customPositioning: Boolean = false, // mainly used by vital meter customPositioning: Boolean = false, // mainly used by vital meter
doNotWarnConstant: Boolean = false doNotWarnConstant: Boolean = false
) { ): Disposable {
abstract var width: Int abstract var width: Int
abstract var height: Int abstract var height: Int
@@ -36,7 +37,7 @@ abstract class UICanvas(
/** /**
* Usage: (in StateInGame:) uiHandlerField.ui.handler = uiHandlerField * Usage: (in StateInGame:) uiHandlerField.ui.handler = uiHandlerField
*/ */
protected val handler = UIHandler(toggleKeyLiteral, toggleButtonLiteral, customPositioning, doNotWarnConstant) val handler = UIHandler(toggleKeyLiteral, toggleButtonLiteral, customPositioning, doNotWarnConstant)
init { init {
@@ -59,12 +60,14 @@ abstract class UICanvas(
get() = Terrarum.mouseScreenY - handler.posY get() = Terrarum.mouseScreenY - handler.posY
/** If mouse is hovering over it regardless of its visibility */ /** If mouse is hovering over it regardless of its visibility */
val mouseUp: Boolean open val mouseUp: Boolean
get() = relativeMouseX in 0..width - 1 && relativeMouseY in 0..height - 1 get() = _mouseUpThis || handler.mouseUp
/** If mouse is hovering over it and mouse is down */ /** If mouse is hovering over it and mouse is down */
val mousePushed: Boolean val mousePushed: Boolean
get() = mouseUp && Gdx.input.isButtonPressed(AppLoader.getConfigInt("mouseprimary")) get() = mouseUp && Gdx.input.isButtonPressed(AppLoader.getConfigInt("mouseprimary"))
private val _mouseUpThis: Boolean
get() = relativeMouseX in 0..width - 1 && relativeMouseY in 0..height - 1
/** Called by the screen */ /** Called by the screen */
fun update(delta: Float) { fun update(delta: Float) {
@@ -88,6 +91,9 @@ abstract class UICanvas(
* *
* Under normal circumstances, draws are automatically translated as per the handler's X/Y position. * Under normal circumstances, draws are automatically translated as per the handler's X/Y position.
* This means, don't write like: ```draw(posX + 4, posY + 32)```, do instead: ```draw(4, 32)``` unless you have a good reason to do so. * This means, don't write like: ```draw(posX + 4, posY + 32)```, do instead: ```draw(4, 32)``` unless you have a good reason to do so.
*
* The transparency of the handler is independent of the draw, you must specified the color yourself
* using handler.opacity or handler.opacityColour
*/ */
abstract fun renderUI(batch: SpriteBatch, camera: Camera) abstract fun renderUI(batch: SpriteBatch, camera: Camera)
@@ -111,7 +117,7 @@ abstract class UICanvas(
*/ */
abstract fun endClosing(delta: Float) abstract fun endClosing(delta: Float)
abstract fun dispose() abstract override fun dispose()
fun addItem(uiItem: UIItem) { fun addItem(uiItem: UIItem) {
uiItems.add(uiItem) uiItems.add(uiItem)
@@ -200,7 +206,7 @@ abstract class UICanvas(
// handler func aliases // // handler func aliases //
fun setPosition(x: Int, y: Int) { open fun setPosition(x: Int, y: Int) {
handler.setPosition(x, y) handler.setPosition(x, y)
} }
@@ -208,15 +214,15 @@ abstract class UICanvas(
handler.setAsAlwaysVisible() handler.setAsAlwaysVisible()
} }
fun setAsOpen() { open fun setAsOpen() {
handler.setAsOpen() handler.setAsOpen()
} }
fun setAsClose() { open fun setAsClose() {
handler.setAsClose() handler.setAsClose()
} }
fun toggleOpening() { open fun toggleOpening() {
handler.toggleOpening() handler.toggleOpening()
} }
@@ -254,7 +260,7 @@ abstract class UICanvas(
const val OPENCLOSE_GENERIC = 0.2f const val OPENCLOSE_GENERIC = 0.2f
fun doOpeningFade(ui: UICanvas, openCloseTime: Second) { fun doOpeningFade(ui: UICanvas, openCloseTime: Second) {
ui.handler.opacity = ui.handler.openCloseCounter / openCloseTime ui.handler.opacity = maxOf(0f, ui.handler.openCloseCounter - 0.02f) / openCloseTime // fade start 1/50 sec late, it's intended
} }
fun doClosingFade(ui: UICanvas, openCloseTime: Second) { fun doClosingFade(ui: UICanvas, openCloseTime: Second) {
ui.handler.opacity = (openCloseTime - ui.handler.openCloseCounter) / openCloseTime ui.handler.opacity = (openCloseTime - ui.handler.openCloseCounter) / openCloseTime

View File

@@ -3,8 +3,9 @@ package net.torvald.terrarum.ui
import com.badlogic.gdx.graphics.Camera import com.badlogic.gdx.graphics.Camera
import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.terrarum.modulebasegame.Ingame import com.badlogic.gdx.utils.Disposable
import net.torvald.terrarum.gamecontroller.KeyToggler import net.torvald.terrarum.gamecontroller.KeyToggler
import net.torvald.terrarum.modulebasegame.Ingame
/** /**
* UIHandler is a handler for UICanvas. It opens/closes the attached UI, moves the "window" (or "canvas") * UIHandler is a handler for UICanvas. It opens/closes the attached UI, moves the "window" (or "canvas")
@@ -20,7 +21,7 @@ class UIHandler(//var UI: UICanvas,
// UI positions itself? (you must g.flush() yourself after the g.translate(Int, Int)) // UI positions itself? (you must g.flush() yourself after the g.translate(Int, Int))
var customPositioning: Boolean = false, // mainly used by vital meter var customPositioning: Boolean = false, // mainly used by vital meter
var doNotWarnConstant: Boolean = false var doNotWarnConstant: Boolean = false
) { ): Disposable {
// X/Y Position relative to the game window. // X/Y Position relative to the game window.
var posX: Int = 0 var posX: Int = 0
@@ -54,8 +55,14 @@ class UIHandler(//var UI: UICanvas,
var closeFired = false var closeFired = false
var opacity = 1f var opacity = 1f
set(value) {
field = value
opacityColour.set(1f,1f,1f,opacity)
}
var scale = 1f var scale = 1f
val opacityColour = Color(1f,1f,1f,opacity)
var openCloseCounter = 0f var openCloseCounter = 0f
init { init {
@@ -69,6 +76,15 @@ class UIHandler(//var UI: UICanvas,
val subUIs = ArrayList<UICanvas>() val subUIs = ArrayList<UICanvas>()
val mouseUp: Boolean
get() {
for (k in 0 until subUIs.size) {
val ret2 = subUIs[k].mouseUp
if (ret2) return true
}
return false
}
fun addSubUI(ui: UICanvas) { fun addSubUI(ui: UICanvas) {
if (subUIs.contains(ui)) if (subUIs.contains(ui))
throw IllegalArgumentException( throw IllegalArgumentException(
@@ -174,13 +190,18 @@ class UIHandler(//var UI: UICanvas,
ui.renderUI(batch, camera) ui.renderUI(batch, camera)
//ingameGraphics.flush() //ingameGraphics.flush()
batch.color = Color.WHITE
setCameraPosition(batch, camera, 0f, 0f) setCameraPosition(batch, camera, 0f, 0f)
} }
subUIs.forEach { it.render(batch, camera) } subUIs.forEach {
it.render(batch, camera)
batch.color = Color.WHITE
}
} }
fun setPosition(x: Int, y: Int) { fun setPosition(x: Int, y: Int) {
@@ -341,4 +362,10 @@ class UIHandler(//var UI: UICanvas,
return false return false
} }
} }
/** Don't dispose common assets, this function is called when the ingame does hide() */
override fun dispose() {
toggleKey?.let { KeyToggler.forceSet(it, false) }
toggleButton?.let { /* ButtonToggler.forceSet(it, false) */ }
}
} }

Some files were not shown because too many files have changed in this diff Show More