mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-06 08:38:30 +09:00
Compare commits
48 Commits
delta_t_aw
...
jni_light
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
af619cda79 | ||
|
|
78bbd9c051 | ||
|
|
3f108a6ea9 | ||
|
|
a831a4d798 | ||
|
|
e3ed712a42 | ||
|
|
daf5c02605 | ||
|
|
e8b39fc668 | ||
|
|
c20d7edb34 | ||
|
|
28f305e76f | ||
|
|
4c3fc2352c | ||
|
|
01094d49eb | ||
|
|
7d3bf0eece | ||
|
|
75f128a8f7 | ||
|
|
514f1e9012 | ||
|
|
60db83eddb | ||
|
|
90a7fcd4d0 | ||
|
|
d93c6de851 | ||
|
|
f603b58307 | ||
|
|
074fe2438d | ||
|
|
69e9fa4b0f | ||
|
|
9373feff34 | ||
|
|
10c188bea7 | ||
|
|
cd1ad9277a | ||
|
|
465ed0d7a4 | ||
|
|
bd1c1bff8a | ||
|
|
8ac5f1dc9e | ||
|
|
268907ee9d | ||
|
|
9937c34d25 | ||
|
|
bdbb30bc58 | ||
|
|
bdbf6cd458 | ||
|
|
e4f456ffa7 | ||
|
|
73a6c844c8 | ||
|
|
84ca954a26 | ||
|
|
66b18bf8c5 | ||
|
|
6d0bff2879 | ||
|
|
14b485dc32 | ||
|
|
a192abd657 | ||
|
|
0d534fd60c | ||
|
|
a4dabbbf37 | ||
|
|
450874540c | ||
|
|
53c45d6829 | ||
|
|
1c839f7135 | ||
|
|
f133406df3 | ||
|
|
ae14026191 | ||
|
|
b9a4e0f64b | ||
|
|
aef601e9b8 | ||
|
|
88db71f780 | ||
|
|
ded9cb1a10 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -14,7 +14,7 @@ Thumbs.db
|
||||
# Resources that should not be tracked
|
||||
*.jar
|
||||
assets/mods/basegame/demoworld
|
||||
assets/mods/basegame/demoworld.gz
|
||||
#assets/mods/basegame/demoworld.gz
|
||||
external_resource_packs.zip
|
||||
|
||||
# IntelliJ
|
||||
|
||||
BIN
assets/appicon128.png
Normal file
BIN
assets/appicon128.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 462 B |
BIN
assets/appicon16.png
Normal file
BIN
assets/appicon16.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 366 B |
BIN
assets/appicon256.png
Normal file
BIN
assets/appicon256.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 559 B |
BIN
assets/appicon32.png
Normal file
BIN
assets/appicon32.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 387 B |
BIN
assets/appicon64.png
Normal file
BIN
assets/appicon64.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 418 B |
@@ -71,7 +71,7 @@ The control is omnidirectional. In other words, \emph{not} cell-based.
|
||||
\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.}
|
||||
|
||||
\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”.
|
||||
|
||||
\section{World}
|
||||
|
||||
15
assets/graphics/! PSD to TGA imagemagick.bat
Normal file
15
assets/graphics/! PSD to TGA imagemagick.bat
Normal 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.
Binary file not shown.
@@ -2053,7 +2053,7 @@
|
||||
},
|
||||
{
|
||||
"n": "MENU_LABEL_MAINMENU",
|
||||
"s": "메뉴"
|
||||
"s": "메인 메뉴"
|
||||
},
|
||||
{
|
||||
"n": "MENU_LABEL_MORE",
|
||||
|
||||
@@ -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"
|
||||
"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"
|
||||
"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"
|
||||
"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"
|
||||
"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.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"
|
||||
"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"
|
||||
@@ -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"
|
||||
"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"
|
||||
"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"
|
||||
"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"
|
||||
"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"
|
||||
"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"
|
||||
|
||||
## Notes ##
|
||||
#
|
||||
# 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
|
||||
#
|
||||
# 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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -8,22 +8,22 @@
|
||||
"multithread": true,
|
||||
|
||||
|
||||
"joypadkeyn": 4,
|
||||
"joypadkeyw": 1,
|
||||
"joypadkeys": 2,
|
||||
"joypadkeye": 3,
|
||||
"gamepadkeyn": 4,
|
||||
"gamepadkeyw": 1,
|
||||
"gamepadkeys": 2,
|
||||
"gamepadkeye": 3,
|
||||
|
||||
"joypadlup": 4,
|
||||
"joypadrup": 5,
|
||||
"joypadldown": 6,
|
||||
"joypadrdown": 7,
|
||||
"gamepadlup": 4,
|
||||
"gamepadrup": 5,
|
||||
"gamepadldown": 6,
|
||||
"gamepadrdown": 7,
|
||||
|
||||
"joypadlstickx": 0,
|
||||
"joypadlsticky": 1,
|
||||
"joypadrstickx": 2,
|
||||
"joypadrsticky": 3,
|
||||
"gamepadlstickx": 0,
|
||||
"gamepadlsticky": 1,
|
||||
"gamepadrstickx": 2,
|
||||
"gamepadrsticky": 3,
|
||||
|
||||
"joypadlabelstyle": "msxb360",
|
||||
"gamepadlabelstyle": "msxb360",
|
||||
|
||||
|
||||
"keyup": 33,
|
||||
|
||||
BIN
assets/mods/basegame/demoworld.gz
LFS
Normal file
BIN
assets/mods/basegame/demoworld.gz
LFS
Normal file
Binary file not shown.
Binary file not shown.
BIN
assets/mods/basegame/fonts/watch_new.tga
LFS
Normal file
BIN
assets/mods/basegame/fonts/watch_new.tga
LFS
Normal file
Binary file not shown.
BIN
assets/mods/basegame/gui/old_watchface_atlas.tga
LFS
Normal file
BIN
assets/mods/basegame/gui/old_watchface_atlas.tga
LFS
Normal file
Binary file not shown.
BIN
assets/mods/basegame/gui/old_watchface_atlas_floatey.tga
LFS
Normal file
BIN
assets/mods/basegame/gui/old_watchface_atlas_floatey.tga
LFS
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -10,5 +10,5 @@ uniform sampler2D u_texture;
|
||||
|
||||
|
||||
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
108
assets/raytracelight.frag
Normal 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;
|
||||
|
||||
|
||||
}
|
||||
@@ -87,18 +87,18 @@ void main() {
|
||||
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
|
||||
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)
|
||||
mediump vec2 uvCoordOffsetBreakage = breakageXY * singleTileSizeInUV;
|
||||
vec2 uvCoordOffsetTile = tileXY * singleTileSizeInUV; // where the tile starts in the atlas, using uv coord (0..1)
|
||||
vec2 uvCoordOffsetBreakage = breakageXY * singleTileSizeInUV;
|
||||
|
||||
mediump vec2 finalUVCoordForTile = uvCoordForTile + uvCoordOffsetTile;// where we should be actually looking for in atlas, using UV coord (0..1)
|
||||
mediump vec2 finalUVCoordForBreakage = uvCoordForTile + uvCoordOffsetBreakage;
|
||||
vec2 finalUVCoordForTile = uvCoordForTile + uvCoordOffsetTile;// where we should be actually looking for in atlas, using UV coord (0..1)
|
||||
vec2 finalUVCoordForBreakage = uvCoordForTile + uvCoordOffsetBreakage;
|
||||
|
||||
|
||||
// blending a breakage tex with main tex
|
||||
@@ -110,7 +110,7 @@ void main() {
|
||||
|
||||
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;
|
||||
|
||||
|
||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
743
src/com/badlogic/gdx/backends/lwjgl/LwjglGraphics.java
Normal file
743
src/com/badlogic/gdx/backends/lwjgl/LwjglGraphics.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||
|
||||
class SpriteAnimation(val parentActor: ActorWBMovable) {
|
||||
|
||||
private lateinit var textureRegion: TextureRegionPack
|
||||
lateinit var textureRegion: TextureRegionPack; private set
|
||||
|
||||
var currentFrame = 0
|
||||
var currentRow = 0
|
||||
|
||||
@@ -7,11 +7,11 @@ import java.util.*
|
||||
import kotlin.collections.HashMap
|
||||
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"
|
||||
}
|
||||
|
||||
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"
|
||||
}
|
||||
|
||||
@@ -22,12 +22,12 @@ data class Skeleton(val name: String, val joints: List<Joint>) {
|
||||
* @param frames number of frames this animation has
|
||||
* @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}"
|
||||
}
|
||||
|
||||
/** 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"
|
||||
}
|
||||
|
||||
@@ -41,11 +41,11 @@ class ADProperties {
|
||||
lateinit var bodyparts: List<String>; private set
|
||||
lateinit var bodypartFiles: List<String>; private set
|
||||
/** 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) */
|
||||
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) */
|
||||
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 animMustContain = listOf("DELAY", "ROW", "SKELETON")
|
||||
@@ -56,7 +56,7 @@ class ADProperties {
|
||||
var frameHeight: Int = -1; private set
|
||||
var originX: Int = -1; private set
|
||||
var originY: Int = -1; private set
|
||||
val origin: ADPropertyObject.Vector2i
|
||||
internal val origin: ADPropertyObject.Vector2i
|
||||
get() = ADPropertyObject.Vector2i(originX, originY)
|
||||
|
||||
private val animFrameSuffixRegex = Regex("""_[0-9]+""")
|
||||
@@ -209,11 +209,11 @@ class ADProperties {
|
||||
fun toFilename(partName: String) =
|
||||
"${this.baseFilename}${partName.toLowerCase()}${this.extension}"
|
||||
|
||||
fun getAnimByFrameName(frameName: String) = animations[getAnimNameFromFrame(frameName)]!!
|
||||
fun getFrameNumberFromName(frameName: String) = frameName.substring(frameName.lastIndexOf('_') + 1 until frameName.length).toInt()
|
||||
internal fun getAnimByFrameName(frameName: String) = animations[getAnimNameFromFrame(frameName)]!!
|
||||
internal fun getFrameNumberFromName(frameName: String) = frameName.substring(frameName.lastIndexOf('_') + 1 until frameName.length).toInt()
|
||||
|
||||
fun getSkeleton(name: String) = skeletons[name]!!
|
||||
fun getTransform(name: String) = transforms[name]!!
|
||||
internal fun getSkeleton(name: String) = skeletons[name]!!
|
||||
internal fun getTransform(name: String) = transforms[name]!!
|
||||
|
||||
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 ivec2Regex = Regex("""-?[0-9]+,-?[0-9]+""")
|
||||
private val variableInputSepRegex = Regex(""" +""")
|
||||
@@ -292,7 +292,7 @@ class ADPropertyObject(propertyRaw: String) {
|
||||
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)"
|
||||
|
||||
operator fun plus(other: Vector2i) = Vector2i(this.x + other.x, this.y + other.y)
|
||||
|
||||
@@ -89,7 +89,7 @@ object AssembleSheetPixmap {
|
||||
|
||||
}
|
||||
|
||||
object AssembleFrameBase {
|
||||
internal object AssembleFrameBase {
|
||||
/**
|
||||
* Returns joints list with tranform applied.
|
||||
* @param skeleton list of joints
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
package net.torvald.terrarum;
|
||||
|
||||
import com.badlogic.gdx.ApplicationListener;
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.Screen;
|
||||
import com.badlogic.gdx.*;
|
||||
import com.badlogic.gdx.assets.AssetManager;
|
||||
import com.badlogic.gdx.audio.AudioDevice;
|
||||
import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
|
||||
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.JsonPrimitive;
|
||||
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.utils.JsonFetcher;
|
||||
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.TextureRegionPack;
|
||||
import org.lwjgl.input.Controller;
|
||||
import org.lwjgl.input.Controllers;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -106,9 +113,26 @@ public class AppLoader implements ApplicationListener {
|
||||
}
|
||||
|
||||
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 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)
|
||||
*/
|
||||
@@ -142,9 +166,16 @@ public class AppLoader implements ApplicationListener {
|
||||
private static boolean splashDisplayed = false;
|
||||
private static boolean postInitFired = false;
|
||||
private static boolean screenshotRequested = false;
|
||||
private static boolean resizeRequested = false;
|
||||
private static Point2i resizeReqSize;
|
||||
|
||||
public static LwjglApplicationConfiguration appConfig;
|
||||
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)
|
||||
@@ -154,23 +185,52 @@ public class AppLoader implements ApplicationListener {
|
||||
|
||||
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) {
|
||||
// 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;
|
||||
|
||||
LwjglApplicationConfiguration appConfig = new LwjglApplicationConfiguration();
|
||||
//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.width = 1110; // photographic ratio (1.5:1)
|
||||
appConfig.height = 740; // photographic ratio (1.5:1)
|
||||
appConfig.backgroundFPS = 9999;
|
||||
appConfig.foregroundFPS = 9999;
|
||||
//appConfig.width = 1110; // photographic ratio (1.5:1)
|
||||
//appConfig.height = 740; // photographic ratio (1.5:1)
|
||||
appConfig.width = getConfigInt("screenwidth");
|
||||
appConfig.height = getConfigInt("screenheight");
|
||||
appConfig.backgroundFPS = getConfigInt("displayfps");
|
||||
appConfig.foregroundFPS = getConfigInt("displayfps");
|
||||
appConfig.title = GAME_NAME;
|
||||
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")) {
|
||||
IS_DEVELOPMENT_BUILD = true;
|
||||
// safe area box
|
||||
//KeyToggler.INSTANCE.forceSet(Input.Keys.F11, true);
|
||||
}
|
||||
|
||||
new LwjglApplication(new AppLoader(appConfig), appConfig);
|
||||
@@ -179,6 +239,7 @@ public class AppLoader implements ApplicationListener {
|
||||
|
||||
private static ShaderProgram shaderBayerSkyboxFill;
|
||||
public static ShaderProgram shaderHicolour;
|
||||
public static ShaderProgram shaderPassthru;
|
||||
public static ShaderProgram shaderColLUT;
|
||||
|
||||
public static Mesh fullscreenQuad;
|
||||
@@ -207,23 +268,33 @@ public class AppLoader implements ApplicationListener {
|
||||
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 final float showupTime = 100f / 1000f;
|
||||
|
||||
private FrameBuffer renderFBO;
|
||||
|
||||
public static AssetManager assetManager;
|
||||
|
||||
@Override
|
||||
public void create() {
|
||||
assetManager = new AssetManager();
|
||||
|
||||
// set basis of draw
|
||||
logoBatch = new SpriteBatch();
|
||||
camera = new OrthographicCamera(((float) appConfig.width), ((float) appConfig.height));
|
||||
|
||||
initViewPort(appConfig.width, appConfig.height);
|
||||
|
||||
// logo here :p
|
||||
logo = new TextureRegion(new Texture(Gdx.files.internal("assets/graphics/logo_placeholder.tga")));
|
||||
logo.flip(false, true);
|
||||
|
||||
// set GL graphics constants
|
||||
shaderBayerSkyboxFill = loadShader("assets/4096.vert", "assets/4096_bayer_skyboxfill.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");
|
||||
|
||||
fullscreenQuad = new Mesh(
|
||||
@@ -233,99 +304,50 @@ public class AppLoader implements ApplicationListener {
|
||||
VertexAttribute.TexCoords(0)
|
||||
);
|
||||
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;
|
||||
|
||||
/**
|
||||
* Because fuck you GDX. (No, really; take a look at LwjglGraphics.java, getDeltaTime() and rawDeltaTime() are exactly the same)
|
||||
* @return Render delta that is smoothed out.
|
||||
*/
|
||||
public static double getSmoothDelta() {
|
||||
// kalman filter is calculated but not actually being used.
|
||||
// set up renderer info variables
|
||||
renderer = Gdx.graphics.getGLVersion().getRendererString();
|
||||
rendererVendor = Gdx.graphics.getGLVersion().getVendorString();
|
||||
|
||||
|
||||
// below is the kalman part
|
||||
return _kalman_return_value;
|
||||
}
|
||||
|
||||
public static void resetDeltaSmoothingHistory() {
|
||||
_kalman_xhat_k = 1.0 / 60.0;
|
||||
_kalman_p_k = 1.0;
|
||||
// make loading list
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @link http://bilgin.esme.org/BitsAndBytes/KalmanFilterforDummies
|
||||
*/
|
||||
private void updateKalmanRenderDelta() {
|
||||
|
||||
// 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;
|
||||
}
|
||||
// moved to LwjglGraphics
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render() {
|
||||
Gdx.gl.glDisable(GL20.GL_DITHER);
|
||||
|
||||
if (splashDisplayed && !postInitFired) {
|
||||
postInitFired = true;
|
||||
postInit();
|
||||
}
|
||||
|
||||
// update smooth delta AFTER postInit
|
||||
updateKalmanRenderDelta();
|
||||
|
||||
FrameBufferManager.begin(renderFBO);
|
||||
gdxClearAndSetBlend(.094f, .094f, .094f, 0f);
|
||||
setCameraPosition(0, 0);
|
||||
@@ -365,15 +387,24 @@ public class AppLoader implements ApplicationListener {
|
||||
}
|
||||
// draw the screen
|
||||
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!
|
||||
net.torvald.terrarum.FrameBufferManager.end();
|
||||
|
||||
PostProcessor.INSTANCE.draw(camera.combined, renderFBO);
|
||||
|
||||
|
||||
// process resize request
|
||||
if (resizeRequested) {
|
||||
resizeRequested = false;
|
||||
resize(resizeReqSize.getX(), resizeReqSize.getY());
|
||||
}
|
||||
|
||||
|
||||
// process screenshot request
|
||||
if (screenshotRequested) {
|
||||
screenshotRequested = false;
|
||||
@@ -394,6 +425,11 @@ public class AppLoader implements ApplicationListener {
|
||||
|
||||
@Override
|
||||
public void resize(int width, int height) {
|
||||
printdbg(this, "Resize called");
|
||||
for (StackTraceElement stackTraceElement : Thread.currentThread().getStackTrace()) {
|
||||
printdbg(this, stackTraceElement);
|
||||
}
|
||||
|
||||
//initViewPort(width, height);
|
||||
|
||||
screenW = width;
|
||||
@@ -422,9 +458,12 @@ public class AppLoader implements ApplicationListener {
|
||||
|
||||
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
|
||||
@@ -438,7 +477,19 @@ public class AppLoader implements ApplicationListener {
|
||||
}
|
||||
|
||||
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
|
||||
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) {
|
||||
this.screen.hide();
|
||||
this.screen.dispose();
|
||||
}
|
||||
this.screen = screen;
|
||||
if (this.screen != null) {
|
||||
@@ -468,17 +520,15 @@ public class AppLoader implements ApplicationListener {
|
||||
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() {
|
||||
// load configs
|
||||
getDefaultDirectory();
|
||||
createDirs();
|
||||
readConfigJson();
|
||||
|
||||
textureWhiteSquare = new Texture(Gdx.files.internal("assets/graphics/ortho_line_tex_2px.tga"));
|
||||
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,
|
||||
Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest, false, 256, false
|
||||
);
|
||||
fontSmallNumbers = TinyAlphNum.INSTANCE;
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
@@ -505,7 +560,7 @@ public class AppLoader implements ApplicationListener {
|
||||
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[]{
|
||||
0f, 0f, 0f, 1f, 1f, 1f, 1f, 0f, 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 RunningEnvironment environment;
|
||||
|
||||
private void getDefaultDirectory() {
|
||||
private static void getDefaultDirectory() {
|
||||
String OS = OSName.toUpperCase();
|
||||
if (OS.contains("WIN")) {
|
||||
operationSystem = "WINDOWS";
|
||||
@@ -550,11 +605,11 @@ public class AppLoader implements ApplicationListener {
|
||||
operationSystem = "SOLARIS";
|
||||
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";
|
||||
defaultDir = System.getProperty("user.home") + "/.Terrarum";
|
||||
environment = RunningEnvironment.MOBILE;
|
||||
}
|
||||
}*/
|
||||
else {
|
||||
operationSystem = "UNKNOWN";
|
||||
defaultDir = System.getProperty("user.home") + "/.Terrarum";
|
||||
@@ -568,7 +623,7 @@ public class AppLoader implements ApplicationListener {
|
||||
System.out.println(String.format("default directory: %s", defaultDir));
|
||||
}
|
||||
|
||||
private void createDirs() {
|
||||
private static void createDirs() {
|
||||
File[] dirs = {new File(defaultSaveDir)};
|
||||
|
||||
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.
|
||||
* @param key
|
||||
* *
|
||||
* @return Config from config set or default config if it does not exist.
|
||||
* *
|
||||
* @throws NullPointerException if the specified config simply 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.
|
||||
*/
|
||||
public static boolean getConfigBoolean(String key) {
|
||||
try {
|
||||
Object cfg = getConfigMaster(key);
|
||||
if (cfg instanceof JsonPrimitive)
|
||||
return ((JsonPrimitive) cfg).getAsBoolean();
|
||||
else
|
||||
return ((boolean) cfg);
|
||||
}
|
||||
catch (NullPointerException keyNotFound) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static int[] getConfigIntArray(String key) {
|
||||
Object cfg = getConfigMaster(key);
|
||||
@@ -714,7 +772,7 @@ public class AppLoader implements ApplicationListener {
|
||||
|
||||
if (config == null) {
|
||||
if (defaults == null) {
|
||||
throw new NullPointerException("key not found: '$key'");
|
||||
throw new NullPointerException("key not found: '" + key + "'");
|
||||
}
|
||||
else {
|
||||
return defaults;
|
||||
@@ -734,13 +792,13 @@ public class AppLoader implements ApplicationListener {
|
||||
// //
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
@@ -748,10 +806,36 @@ public class AppLoader implements ApplicationListener {
|
||||
public static ShaderProgram loadShader(String vert, String 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()));
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,35 +14,36 @@ object DefaultConfig {
|
||||
val jsonObject = JsonObject()
|
||||
|
||||
jsonObject.addProperty("displayfps", 0) // 0: no limit, non-zero: limit
|
||||
jsonObject.addProperty("usevsync", true)
|
||||
jsonObject.addProperty("forcedevbuild", false)
|
||||
jsonObject.addProperty("usevsync", false)
|
||||
jsonObject.addProperty("screenwidth", AppLoader.defaultW)
|
||||
jsonObject.addProperty("screenheight", AppLoader.defaultH)
|
||||
|
||||
|
||||
jsonObject.addProperty("imtooyoungtodie", false) // no perma-death
|
||||
jsonObject.addProperty("language", AppLoader.getSysLang())
|
||||
jsonObject.addProperty("notificationshowuptime", 6500)
|
||||
jsonObject.addProperty("notificationshowuptime", 4000)
|
||||
jsonObject.addProperty("multithread", true) // experimental!
|
||||
jsonObject.addProperty("multithreadedlight", false) // experimental!
|
||||
|
||||
|
||||
|
||||
// control-gamepad
|
||||
jsonObject.addProperty("joypadkeyn", 4)
|
||||
jsonObject.addProperty("joypadkeyw", 1)
|
||||
jsonObject.addProperty("joypadkeys", 2)
|
||||
jsonObject.addProperty("joypadkeye", 3) // logitech indices
|
||||
jsonObject.addProperty("gamepadkeyn", 4)
|
||||
jsonObject.addProperty("gamepadkeyw", 1)
|
||||
jsonObject.addProperty("gamepadkeys", 2)
|
||||
jsonObject.addProperty("gamepadkeye", 3) // logitech indices
|
||||
|
||||
jsonObject.addProperty("joypadlup", 4)
|
||||
jsonObject.addProperty("joypadrup", 5)
|
||||
jsonObject.addProperty("joypadldown", 6)
|
||||
jsonObject.addProperty("joypadrdown", 7) // logitech indices
|
||||
jsonObject.addProperty("gamepadlup", 4)
|
||||
jsonObject.addProperty("gamepadrup", 5)
|
||||
jsonObject.addProperty("gamepadldown", 6)
|
||||
jsonObject.addProperty("gamepadrdown", 7) // logitech indices
|
||||
|
||||
jsonObject.addProperty("joypadlstickx", 0)
|
||||
jsonObject.addProperty("joypadlsticky", 1)
|
||||
jsonObject.addProperty("joypadrstickx", 2)
|
||||
jsonObject.addProperty("joypadrsticky", 3) // 0-1-2-3 but sometimes 3-2-1-0 ?! what the actual fuck?
|
||||
jsonObject.addProperty("gamepadlstickx", 0)
|
||||
jsonObject.addProperty("gamepadlsticky", 1)
|
||||
jsonObject.addProperty("gamepadrstickx", 2)
|
||||
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"
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -464,7 +464,7 @@ class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
override fun run() {
|
||||
var updateTries = 0
|
||||
while (ingame.updateDeltaCounter >= ingame.updateRate) {
|
||||
ingame.updateGame(AppLoader.getSmoothDelta().toFloat())
|
||||
ingame.updateGame(AppLoader.UPDATE_RATE.toFloat())
|
||||
ingame.updateDeltaCounter -= ingame.updateRate
|
||||
updateTries++
|
||||
|
||||
@@ -529,7 +529,7 @@ class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
while (updateDeltaCounter >= updateRate) {
|
||||
|
||||
//updateGame(delta)
|
||||
AppLoader.debugTimers["Ingame.update"] = measureNanoTime { updateGame(delta) }
|
||||
AppLoader.measureDebugTime("Ingame.update") { updateGame(delta) }
|
||||
|
||||
updateDeltaCounter -= updateRate
|
||||
updateTries++
|
||||
@@ -544,7 +544,7 @@ class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
|
||||
/** RENDER CODE GOES HERE */
|
||||
//renderGame(batch)
|
||||
AppLoader.debugTimers["Ingame.render"] = measureNanoTime { renderGame(batch) }
|
||||
AppLoader.measureDebugTime("Ingame.render") { renderGame(batch) }
|
||||
}
|
||||
|
||||
protected fun updateGame(delta: Float) {
|
||||
@@ -1090,7 +1090,7 @@ class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
}
|
||||
|
||||
playableActorDelegate = newActor
|
||||
WorldSimulator(player, AppLoader.getSmoothDelta().toFloat())
|
||||
WorldSimulator(player, AppLoader.UPDATE_RATE.toFloat())
|
||||
}
|
||||
|
||||
private fun changePossession(refid: Int) {
|
||||
@@ -1107,7 +1107,7 @@ class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
// accept new delegate
|
||||
playableActorDelegate = PlayableActorDelegate(getActorByID(refid) as ActorHumanoid)
|
||||
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. */
|
||||
|
||||
@@ -17,9 +17,9 @@ class GdxColorMap {
|
||||
height = pixmap.height
|
||||
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)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
AppLoader.printdbg(this, "Loading colormap from ${imageFile.name()}; PixmapFormat: ${pixmap.format}; Dimension: $width x $height")
|
||||
|
||||
@@ -2,9 +2,11 @@ package net.torvald.terrarum
|
||||
|
||||
import com.badlogic.gdx.Screen
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||
import com.badlogic.gdx.utils.Queue
|
||||
import net.torvald.terrarum.gameactors.Actor
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
||||
import net.torvald.terrarum.realestate.LandUtil
|
||||
import net.torvald.terrarum.ui.ConsoleWindow
|
||||
import java.util.*
|
||||
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 actorContainerInactive = ArrayList<Actor>(ACTORCONTAINER_INITIAL_SIZE)
|
||||
|
||||
protected val terrainChangeQueue = Queue<BlockChangeQueueItem>()
|
||||
protected val wallChangeQueue = Queue<BlockChangeQueueItem>()
|
||||
protected val wireChangeQueue = Queue<BlockChangeQueueItem>()
|
||||
|
||||
override fun hide() {
|
||||
}
|
||||
|
||||
@@ -96,6 +102,33 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
|
||||
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) {
|
||||
|
||||
@@ -239,7 +239,7 @@ object LoadScreen : ScreenAdapter() {
|
||||
for (i in 0 until messages.elemCount) {
|
||||
Terrarum.fontGame.draw(it,
|
||||
messages[i] ?: "",
|
||||
40f,
|
||||
AppLoader.getTvSafeGraphicsWidth() + 16f,
|
||||
80f + (messages.size - i - 1) * Terrarum.fontGame.lineHeight
|
||||
)
|
||||
}
|
||||
@@ -264,7 +264,7 @@ object LoadScreen : ScreenAdapter() {
|
||||
for (i in 0 until messages.elemCount) {
|
||||
Terrarum.fontGame.draw(it,
|
||||
messages[i] ?: "",
|
||||
40f,
|
||||
AppLoader.getTvSafeGraphicsWidth() + 16f,
|
||||
80f + (messages.size - i - 1) * Terrarum.fontGame.lineHeight
|
||||
)
|
||||
}
|
||||
@@ -313,7 +313,6 @@ object LoadScreen : ScreenAdapter() {
|
||||
}
|
||||
|
||||
override fun hide() {
|
||||
dispose()
|
||||
}
|
||||
|
||||
override fun resize(width: Int, height: Int) {
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
package net.torvald.terrarum
|
||||
|
||||
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.OrthographicCamera
|
||||
import com.badlogic.gdx.graphics.Texture
|
||||
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.ShaderProgram
|
||||
import com.badlogic.gdx.graphics.glutils.ShapeRenderer
|
||||
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
|
||||
@@ -16,36 +20,71 @@ import kotlin.system.measureNanoTime
|
||||
object PostProcessor {
|
||||
|
||||
private lateinit var batch: SpriteBatch // not nulling to save some lines of code
|
||||
//private lateinit var camera: OrthographicCamera
|
||||
private var textureRegion: TextureRegion? = null
|
||||
|
||||
private lateinit var shapeRenderer: ShapeRenderer
|
||||
private lateinit var camera: OrthographicCamera
|
||||
|
||||
private lateinit var lutTex: Texture
|
||||
|
||||
private var init = false
|
||||
|
||||
fun reloadLUT(filename: String) {
|
||||
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) {
|
||||
|
||||
if (textureRegion == null) {
|
||||
textureRegion = TextureRegion(fbo.colorBufferTexture)
|
||||
// init
|
||||
if (!init) {
|
||||
init = true
|
||||
|
||||
debugUI.setPosition(0, 0)
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
|
||||
debugUI.update(Gdx.graphics.deltaTime)
|
||||
|
||||
|
||||
AppLoader.debugTimers["Renderer.PostProcessor"] = measureNanoTime {
|
||||
AppLoader.measureDebugTime("Renderer.PostProcessor") {
|
||||
|
||||
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? =
|
||||
if (AppLoader.getConfigBoolean("fxdither"))
|
||||
AppLoader.shaderHicolour
|
||||
else
|
||||
null
|
||||
AppLoader.shaderPassthru
|
||||
|
||||
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
|
||||
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
@@ -14,7 +14,6 @@ import com.badlogic.gdx.graphics.glutils.ShapeRenderer
|
||||
import com.badlogic.gdx.utils.GdxRuntimeException
|
||||
import com.jme3.math.FastMath
|
||||
import net.torvald.dataclass.CircularArray
|
||||
import net.torvald.getcpuname.GetCpuName
|
||||
import net.torvald.random.HQRNG
|
||||
import net.torvald.terrarum.AppLoader.*
|
||||
import net.torvald.terrarum.gameactors.Actor
|
||||
@@ -74,22 +73,12 @@ object Terrarum : Screen {
|
||||
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_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!!)
|
||||
// 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
|
||||
@@ -132,22 +121,22 @@ object Terrarum : Screen {
|
||||
|
||||
|
||||
val fontGame: GameFontBase = AppLoader.fontGame
|
||||
lateinit var fontSmallNumbers: TinyAlphNum
|
||||
val fontSmallNumbers: TinyAlphNum = AppLoader.fontSmallNumbers
|
||||
|
||||
var joypadLabelStart: Char = 0xE000.toChar() // lateinit
|
||||
var joypadLableSelect: Char = 0xE000.toChar() // lateinit
|
||||
var joypadLabelNinA: Char = 0xE000.toChar() // lateinit TODO
|
||||
var joypadLabelNinB: Char = 0xE000.toChar() // lateinit TODO
|
||||
var joypadLabelNinX: Char = 0xE000.toChar() // lateinit TODO
|
||||
var joypadLabelNinY: Char = 0xE000.toChar() // lateinit TODO
|
||||
var joypadLabelNinL: Char = 0xE000.toChar() // lateinit TODO
|
||||
var joypadLabelNinR: Char = 0xE000.toChar() // lateinit TODO
|
||||
var joypadLabelNinZL: Char = 0xE000.toChar() // lateinit TODO
|
||||
var joypadLabelNinZR: Char = 0xE000.toChar() // lateinit TODO
|
||||
val joypadLabelLEFT = 0xE068.toChar()
|
||||
val joypadLabelDOWN = 0xE069.toChar()
|
||||
val joypadLabelUP = 0xE06A.toChar()
|
||||
val joypadLabelRIGHT = 0xE06B.toChar()
|
||||
var gamepadLabelStart: Char = 0xE000.toChar() // lateinit
|
||||
var gamepadLableSelect: Char = 0xE000.toChar() // lateinit
|
||||
var gamepadLabelNinA: Char = 0xE000.toChar() // lateinit TODO
|
||||
var gamepadLabelNinB: Char = 0xE000.toChar() // lateinit TODO
|
||||
var gamepadLabelNinX: Char = 0xE000.toChar() // lateinit TODO
|
||||
var gamepadLabelNinY: Char = 0xE000.toChar() // lateinit TODO
|
||||
var gamepadLabelNinL: Char = 0xE000.toChar() // lateinit TODO
|
||||
var gamepadLabelNinR: Char = 0xE000.toChar() // lateinit TODO
|
||||
var gamepadLabelNinZL: Char = 0xE000.toChar() // lateinit TODO
|
||||
var gamepadLabelNinZR: Char = 0xE000.toChar() // lateinit TODO
|
||||
val gamepadLabelLEFT = 0xE068.toChar()
|
||||
val gamepadLabelDOWN = 0xE069.toChar()
|
||||
val gamepadLabelUP = 0xE06A.toChar()
|
||||
val gamepadLabelRIGHT = 0xE06B.toChar()
|
||||
|
||||
// 0x0 - 0xF: Game-related
|
||||
// 0x10 - 0x1F: Config
|
||||
@@ -170,10 +159,6 @@ object Terrarum : Screen {
|
||||
val STATE_ID_TOOL_NOISEGEN = 0x200
|
||||
val STATE_ID_TOOL_RUMBLE_DIAGNOSIS = 0x201
|
||||
|
||||
var controller: org.lwjgl.input.Controller? = null
|
||||
private set
|
||||
val CONTROLLER_DEADZONE = 0.1f
|
||||
|
||||
/** Available CPU threads */
|
||||
val THREADS = Runtime.getRuntime().availableProcessors() + 1
|
||||
|
||||
@@ -189,15 +174,6 @@ object Terrarum : Screen {
|
||||
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 shaderBayer: ShaderProgram
|
||||
lateinit var shaderSkyboxFill: ShaderProgram
|
||||
@@ -233,12 +209,12 @@ object Terrarum : Screen {
|
||||
println("vendor = $processorVendor")
|
||||
|
||||
|
||||
joypadLabelStart = when (getConfigString("joypadlabelstyle")) {
|
||||
gamepadLabelStart = when (getConfigString("gamepadlabelstyle")) {
|
||||
"nwii" -> 0xE04B.toChar() // + mark
|
||||
"logitech" -> 0xE05A.toChar() // number 10
|
||||
else -> 0xE042.toChar() // |> mark (sonyps, msxb360, generic)
|
||||
}
|
||||
joypadLableSelect = when (getConfigString("joypadlabelstyle")) {
|
||||
gamepadLableSelect = when (getConfigString("gamepadlabelstyle")) {
|
||||
"nwii" -> 0xE04D.toChar() // - mark
|
||||
"logitech" -> 0xE059.toChar() // number 9
|
||||
"sonyps" -> 0xE043.toChar() // solid rectangle
|
||||
@@ -248,7 +224,7 @@ object Terrarum : Screen {
|
||||
|
||||
|
||||
// setting environment as MOBILE precedes this code
|
||||
if (environment != RunningEnvironment.MOBILE) {
|
||||
//if (environment != RunningEnvironment.MOBILE) {
|
||||
environment = try {
|
||||
Controllers.getController(0) // test if controller exists
|
||||
if (getConfigString("pcgamepadenv") == "console")
|
||||
@@ -259,7 +235,8 @@ object Terrarum : Screen {
|
||||
catch (e: IndexOutOfBoundsException) {
|
||||
RunningEnvironment.PC
|
||||
}
|
||||
}
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -284,11 +261,6 @@ object Terrarum : Screen {
|
||||
val MINIMAL_GL_MAX_TEXTURE_SIZE = 4096
|
||||
|
||||
override fun show() {
|
||||
if (environment != RunningEnvironment.MOBILE) {
|
||||
Gdx.gl.glDisable(GL20.GL_DITHER)
|
||||
}
|
||||
|
||||
|
||||
assetManager = AssetManager()
|
||||
|
||||
|
||||
@@ -301,10 +273,6 @@ object Terrarum : Screen {
|
||||
println("GL_MAX_TEXTURE_SIZE = $GL_MAX_TEXTURE_SIZE")
|
||||
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) {
|
||||
// TODO notify properly
|
||||
@@ -321,10 +289,7 @@ object Terrarum : Screen {
|
||||
shapeRender = ShapeRenderer()
|
||||
|
||||
|
||||
fontSmallNumbers = TinyAlphNum
|
||||
|
||||
|
||||
ShaderProgram.pedantic = false
|
||||
shaderBlur = AppLoader.loadShader("assets/blur.vert", "assets/blur.frag")
|
||||
|
||||
|
||||
@@ -409,8 +374,8 @@ object Terrarum : Screen {
|
||||
}
|
||||
|
||||
override fun render(delta: Float) {
|
||||
AppLoader.debugTimers["GDX.rawDelta"] = Gdx.graphics.rawDeltaTime.times(1000_000_000f).toLong()
|
||||
AppLoader.debugTimers["GDX.smtDelta"] = AppLoader.getSmoothDelta().times(1000_000_000f).toLong()
|
||||
AppLoader.setDebugTime("GDX.rawDelta", Gdx.graphics.rawDeltaTime.times(1000_000_000f).toLong())
|
||||
AppLoader.setDebugTime("GDX.smtDelta", Gdx.graphics.deltaTime.times(1000_000_000f).toLong())
|
||||
AppLoader.getINSTANCE().screen.render(delta)
|
||||
}
|
||||
|
||||
@@ -422,35 +387,24 @@ object Terrarum : Screen {
|
||||
AppLoader.getINSTANCE().screen.resume()
|
||||
}
|
||||
|
||||
/** Don't call this! Call AppLoader.dispose() */
|
||||
override fun dispose() {
|
||||
AppLoader.getINSTANCE().screen.dispose()
|
||||
|
||||
fontGame.dispose()
|
||||
fontSmallNumbers.dispose()
|
||||
|
||||
|
||||
//dispose any other resources used in this level
|
||||
|
||||
|
||||
shaderBayer.dispose()
|
||||
shaderSkyboxFill.dispose()
|
||||
shaderBlur.dispose()
|
||||
shaderBlendGlow.dispose()
|
||||
|
||||
|
||||
shapeRender.dispose()
|
||||
batch.dispose()
|
||||
ingame?.dispose()
|
||||
}
|
||||
|
||||
override fun hide() {
|
||||
AppLoader.getINSTANCE().screen.hide()
|
||||
}
|
||||
|
||||
/** For the actual resize, call AppLoader.resize() */
|
||||
override fun resize(width: Int, height: Int) {
|
||||
/*try {
|
||||
AppLoader.getINSTANCE().screen.resize(width, height)
|
||||
}
|
||||
catch (e: NullPointerException) { }*/ // I sense circular recursion...
|
||||
ingame?.resize(width, 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 */
|
||||
inline val mouseX: Double
|
||||
val mouseX: Double
|
||||
get() = WorldCamera.x + Gdx.input.x / (ingame?.screenZoom ?: 1f).toDouble()
|
||||
/** Position of the cursor in the world */
|
||||
inline val mouseY: Double
|
||||
val mouseY: Double
|
||||
get() = WorldCamera.y + Gdx.input.y / (ingame?.screenZoom ?: 1f).toDouble()
|
||||
/** 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()
|
||||
/** Position of the cursor in the world */
|
||||
@JvmStatic inline val mouseTileY: Int
|
||||
@JvmStatic val mouseTileY: Int
|
||||
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
|
||||
get() = Gdx.input.x
|
||||
inline val mouseScreenY: Int
|
||||
get() = Gdx.input.y
|
||||
/** Bigger than 1.0 */
|
||||
/** Delta converted as it it was a FPS */
|
||||
inline val updateRate: Double
|
||||
get() = 1.0 / AppLoader.getSmoothDelta()
|
||||
/** Smaller than 1.0 */
|
||||
val renderRate = 1.0 / TARGET_INTERNAL_FPS
|
||||
val renderRateStr = TARGET_INTERNAL_FPS.toString()
|
||||
|
||||
get() = 1.0 / Gdx.graphics.deltaTime
|
||||
/**
|
||||
* 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.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) {
|
||||
@@ -657,7 +627,7 @@ object BlendMode {
|
||||
}
|
||||
|
||||
enum class RunningEnvironment {
|
||||
PC, CONSOLE, MOBILE
|
||||
PC, CONSOLE//, MOBILE
|
||||
}
|
||||
|
||||
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 Double.abs() = Math.abs(this)
|
||||
fun Double.sqr() = this * this
|
||||
fun Float.sqr() = this * this
|
||||
fun Double.sqrt() = Math.sqrt(this)
|
||||
fun Float.sqrt() = FastMath.sqrt(this)
|
||||
fun Int.abs() = this.absoluteValue
|
||||
|
||||
@@ -23,6 +23,7 @@ import net.torvald.terrarum.modulebasegame.Ingame
|
||||
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.HumanoidNPC
|
||||
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.UITitleRemoConYaml
|
||||
import net.torvald.terrarum.modulebasegame.weather.WeatherMixer
|
||||
@@ -129,7 +130,8 @@ class TitleScreen(val batch: SpriteBatch) : Screen {
|
||||
|
||||
|
||||
demoWorld = ReadLayerData(FileInputStream(ModMgr.getFile("basegame", "demoworld")))
|
||||
|
||||
// set time to summer
|
||||
demoWorld.time.addTime(WorldTime.DAY_LENGTH * 32)
|
||||
|
||||
// construct camera nodes
|
||||
val nodeCount = 100
|
||||
@@ -198,26 +200,28 @@ class TitleScreen(val batch: SpriteBatch) : Screen {
|
||||
|
||||
private val introUncoverTime: Second = 0.3f
|
||||
private var introUncoverDeltaCounter = 0f
|
||||
private var updateDeltaCounter = 0.0
|
||||
protected val renderRate = Terrarum.renderRate
|
||||
private var updateAkku = 0.0
|
||||
|
||||
override fun render(delta: Float) {
|
||||
// async update
|
||||
updateDeltaCounter += delta
|
||||
if (delta < 1f / 10f) { // discard async if measured FPS <= 10
|
||||
var updateTries = 0
|
||||
while (updateDeltaCounter >= renderRate && updateTries < 6) {
|
||||
updateScreen(delta)
|
||||
updateDeltaCounter -= renderRate
|
||||
updateTries++
|
||||
}
|
||||
}
|
||||
else {
|
||||
updateScreen(delta)
|
||||
// async update and render
|
||||
|
||||
val dt = Gdx.graphics.deltaTime
|
||||
updateAkku += dt
|
||||
|
||||
var i = 0L
|
||||
while (updateAkku >= delta) {
|
||||
AppLoader.measureDebugTime("Ingame.update") { updateScreen(delta) }
|
||||
updateAkku -= delta
|
||||
i += 1
|
||||
}
|
||||
AppLoader.setDebugTime("Ingame.updateCounter", i)
|
||||
|
||||
|
||||
// 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) {
|
||||
|
||||
@@ -6,7 +6,9 @@ import com.badlogic.gdx.graphics.Pixmap
|
||||
import com.badlogic.gdx.graphics.Texture
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||
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.
|
||||
@@ -18,6 +20,12 @@ class UIItemInventoryCatBar(
|
||||
override val width: Int
|
||||
) : 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 catArrangement = parentUI.catArrangement
|
||||
|
||||
@@ -91,15 +99,23 @@ class UIItemInventoryCatBar(
|
||||
private val underlineColour = Color(0xeaeaea_40.toInt())
|
||||
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 highlighterXEnd = highlighterXPos
|
||||
|
||||
private val highlighterYPos = catIcons.tileH + 4f
|
||||
private var highlighterMoving = false
|
||||
private val highlighterMoveDuration: Second = 0.1f
|
||||
private val highlighterMoveDuration: Second = 0.15f
|
||||
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
|
||||
init {
|
||||
// procedurally generate texture
|
||||
@@ -134,8 +150,8 @@ class UIItemInventoryCatBar(
|
||||
highlighterXPos = UIUtils.moveQuick(
|
||||
highlighterXStart,
|
||||
highlighterXEnd,
|
||||
highlighterMoveTimer.toDouble(),
|
||||
highlighterMoveDuration.toDouble()
|
||||
highlighterMoveTimer,
|
||||
highlighterMoveDuration
|
||||
)
|
||||
|
||||
if (highlighterMoveTimer > highlighterMoveDuration) {
|
||||
@@ -150,23 +166,61 @@ class UIItemInventoryCatBar(
|
||||
mainButtons.forEachIndexed { index, btn ->
|
||||
btn.update(delta)
|
||||
|
||||
if (btn.mousePushed && selectedPanel != 1) {
|
||||
transitionFired = true
|
||||
selectedPanel = 1
|
||||
}
|
||||
|
||||
if (btn.mousePushed && index != selectedIndex) {
|
||||
// normal stuffs
|
||||
val oldIndex = selectedIndex
|
||||
|
||||
highlighterXStart = mainButtons[selectedIndex].posX.toDouble() // using old selectedIndex
|
||||
highlighterXStart = mainButtons[selectedIndex].posX.toFloat() // using old selectedIndex
|
||||
selectedIndex = index
|
||||
highlighterMoving = true
|
||||
highlighterXEnd = mainButtons[selectedIndex].posX.toDouble() // using new selectedIndex
|
||||
highlighterXEnd = mainButtons[selectedIndex].posX.toFloat() // using new selectedIndex
|
||||
|
||||
selectionChangeListener?.invoke(oldIndex, index)
|
||||
}
|
||||
|
||||
if (selectedPanel == 1) {
|
||||
btn.highlighted = (index == selectedIndex) // forcibly highlight if this.highlighted != null
|
||||
|
||||
sideButtons[0].highlighted = false
|
||||
sideButtons[3].highlighted = false
|
||||
}
|
||||
}
|
||||
|
||||
sideButtons[0].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) {
|
||||
@@ -186,11 +240,15 @@ class UIItemInventoryCatBar(
|
||||
batch.drawStraightLine(posX.toFloat(), posY + height - 1f, posX + width.toFloat(), 1f, false)
|
||||
|
||||
// indicator
|
||||
if (selectedPanel == 1) {
|
||||
batch.color = underlineHighlightColour
|
||||
batch.draw(underlineIndTex, (highlighterXPos - buttonGapSize / 2).toFloat().round(), posY + highlighterYPos)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
override fun dispose() {
|
||||
|
||||
@@ -36,6 +36,10 @@ class UIItemInventoryElem(
|
||||
val drawBackOnNull: Boolean = true
|
||||
) : UIItemInventoryCellBase(parentUI, posX, posY, item, amount, itemImage, quickslot, equippedSlot) {
|
||||
|
||||
// deal with the moving position
|
||||
override var oldPosX = posX
|
||||
override var oldPosY = posY
|
||||
|
||||
companion object {
|
||||
val height = 48
|
||||
val UNIQUE_ITEM_HAS_NO_AMOUNT = -1
|
||||
@@ -194,7 +198,6 @@ class UIItemInventoryElem(
|
||||
|
||||
|
||||
override fun dispose() {
|
||||
itemImage?.texture?.dispose()
|
||||
}
|
||||
|
||||
override fun keyUp(keycode: Int): Boolean {
|
||||
|
||||
@@ -33,6 +33,10 @@ class UIItemInventoryElemSimple(
|
||||
val drawBackOnNull: Boolean = true
|
||||
) : UIItemInventoryCellBase(parentUI, posX, posY, item, amount, itemImage, quickslot, equippedSlot) {
|
||||
|
||||
// deal with the moving position
|
||||
override var oldPosX = posX
|
||||
override var oldPosY = posY
|
||||
|
||||
companion object {
|
||||
val height = UIItemInventoryElem.height
|
||||
}
|
||||
@@ -96,8 +100,8 @@ class UIItemInventoryElemSimple(
|
||||
batch.drawStraightLine(barOffset, posY + height - thickness, barOffset + barFullLen * (item!!.durability / item!!.maxDurability), thickness, false)
|
||||
}
|
||||
}
|
||||
else {
|
||||
// draw item count
|
||||
// draw item count when applicable
|
||||
else if (item!!.stackable) {
|
||||
val amountString = amount.toString()
|
||||
|
||||
// highlight item count (blocks/walls) if the item is equipped
|
||||
@@ -176,7 +180,6 @@ class UIItemInventoryElemSimple(
|
||||
|
||||
|
||||
override fun dispose() {
|
||||
itemImage?.texture?.dispose()
|
||||
}
|
||||
|
||||
override fun keyUp(keycode: Int): Boolean {
|
||||
|
||||
@@ -123,7 +123,10 @@ inline class Yaml(val text: String) {
|
||||
val nodeString = it.drop(2)
|
||||
val nodeNameAndInvocation = nodeString.split(SEPARATOR)
|
||||
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
|
||||
|
||||
@@ -193,5 +196,5 @@ inline class Yaml(val text: String) {
|
||||
*
|
||||
*/
|
||||
interface YamlInvokable {
|
||||
operator fun invoke()
|
||||
operator fun invoke(args: Array<Any>)
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
package net.torvald.terrarum.blockproperties
|
||||
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
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.PairedMapLayer
|
||||
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? {
|
||||
if (rawIndex == null || rawIndex == Block.NULL) {
|
||||
return null
|
||||
@@ -95,6 +111,7 @@ object BlockCodex {
|
||||
prop.shadeColG = floatVal(record, "shdg") / LightmapRenderer.MUL_FLOAT
|
||||
prop.shadeColB = floatVal(record, "shdb") / 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.density = intVal(record, "dsty")
|
||||
@@ -103,6 +120,7 @@ object BlockCodex {
|
||||
prop.lumColG = floatVal(record, "lumg") / LightmapRenderer.MUL_FLOAT
|
||||
prop.lumColB = floatVal(record, "lumb") / 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.viscosity = intVal(record, "vscs")
|
||||
|
||||
@@ -16,6 +16,7 @@ class BlockProp {
|
||||
var shadeColG = 0f
|
||||
var shadeColB = 0f
|
||||
var shadeColA = 0f
|
||||
lateinit var shadeColor: Color
|
||||
|
||||
/**
|
||||
* @param opacity Raw RGB value, without alpha
|
||||
@@ -39,12 +40,13 @@ class BlockProp {
|
||||
var lumColG = 0f
|
||||
var lumColB = 0f
|
||||
var lumColA = 0f
|
||||
lateinit var internalLumCol: Color
|
||||
|
||||
/**
|
||||
* @param luminosity
|
||||
*/
|
||||
inline val luminosity: Color
|
||||
get() = BlockPropUtil.getDynamicLumFunc(Color(lumColR, lumColG, lumColB, lumColA), dynamicLuminosityFunction)
|
||||
get() = BlockPropUtil.getDynamicLumFunc(internalLumCol, dynamicLuminosityFunction)
|
||||
|
||||
var drop: Int = 0
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.jme3.math.FastMath
|
||||
import net.torvald.random.HQRNG
|
||||
import net.torvald.terrarum.AppLoader
|
||||
import net.torvald.terrarum.Second
|
||||
import net.torvald.terrarum.Terrarum
|
||||
import net.torvald.terrarum.modulebasegame.gameworld.WorldTime
|
||||
@@ -64,9 +63,9 @@ object BlockPropUtil {
|
||||
internal fun dynamicLumFuncTickClock() {
|
||||
// FPS-time compensation
|
||||
if (Gdx.graphics.framesPerSecond > 0) {
|
||||
flickerFuncX += AppLoader.getSmoothDelta().toFloat() * 1000f
|
||||
breathFuncX += AppLoader.getSmoothDelta().toFloat() * 1000f
|
||||
pulsateFuncX += AppLoader.getSmoothDelta().toFloat() * 1000f
|
||||
flickerFuncX += Gdx.graphics.deltaTime * 1000f
|
||||
breathFuncX += Gdx.graphics.deltaTime * 1000f
|
||||
pulsateFuncX += Gdx.graphics.deltaTime * 1000f
|
||||
}
|
||||
|
||||
// flicker-related vars
|
||||
|
||||
@@ -44,6 +44,7 @@ object CommandDict {
|
||||
"kill" to KillActor,
|
||||
"money" to MoneyDisp,
|
||||
"screenshot" to TakeScreenshot,
|
||||
//"resize" to ResizeScreen,
|
||||
|
||||
// Test codes
|
||||
"bulletintest" to SetBulletin,
|
||||
|
||||
@@ -22,7 +22,8 @@ internal object CommandInterpreter {
|
||||
"help",
|
||||
"version",
|
||||
"tips",
|
||||
"screenshot"
|
||||
"screenshot",
|
||||
"resize"
|
||||
)
|
||||
|
||||
internal fun execute(command: String) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package net.torvald.terrarum.console
|
||||
|
||||
import net.torvald.terrarum.console.ConsoleCommand
|
||||
import com.badlogic.gdx.Gdx
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2016-01-15.
|
||||
@@ -8,7 +8,7 @@ import net.torvald.terrarum.console.ConsoleCommand
|
||||
internal object QuitApp : ConsoleCommand {
|
||||
|
||||
override fun execute(args: Array<String>) {
|
||||
System.exit(1)
|
||||
Gdx.app.exit()
|
||||
}
|
||||
|
||||
override fun printUsage() {
|
||||
|
||||
30
src/net/torvald/terrarum/console/ResizeScreen.kt
Normal file
30
src/net/torvald/terrarum/console/ResizeScreen.kt
Normal 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")
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,9 @@ object AVKey {
|
||||
const val JUMPPOWER = "jumppower"
|
||||
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
|
||||
* "Default" value of 1 000
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package net.torvald.terrarum.gameactors
|
||||
|
||||
import com.badlogic.gdx.Input
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||
import net.torvald.spriteanimation.SpriteAnimation
|
||||
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.BlockCodex
|
||||
import net.torvald.terrarum.blockproperties.BlockProp
|
||||
import net.torvald.terrarum.gamecontroller.KeyToggler
|
||||
import net.torvald.terrarum.gameworld.BlockAddress
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
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.:
|
||||
* 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:
|
||||
* veloY += 3.0
|
||||
* +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
|
||||
|
||||
/**
|
||||
* Unit: Pixels per 1/60 (or AppLoader.UPDATE_RATE) seconds.
|
||||
*
|
||||
* 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...
|
||||
//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
|
||||
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.
|
||||
@@ -348,23 +351,17 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
|
||||
* @param acc : Acceleration in Vector2
|
||||
*/
|
||||
fun applyForce(acc: Vector2) {
|
||||
externalForce += acc * speedMultByTile
|
||||
externalV += acc * speedMultByTile
|
||||
}
|
||||
|
||||
private val bounceDampenVelThreshold = 0.5
|
||||
|
||||
override fun update(fdelta: Float) {
|
||||
override fun update(delta: Float) {
|
||||
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 (sprite != null) sprite!!.update(fdelta)
|
||||
if (spriteGlow != null) spriteGlow!!.update(fdelta)
|
||||
if (sprite != null) sprite!!.update(delta)
|
||||
if (spriteGlow != null) spriteGlow!!.update(delta)
|
||||
|
||||
// make NoClip work for player
|
||||
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 <-- //
|
||||
@@ -396,8 +393,8 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
|
||||
}
|
||||
|
||||
// hard limit velocity
|
||||
externalForce.x = externalForce.x.bipolarClamp(VELO_HARD_LIMIT) // displaceHitbox SHOULD use moveDelta
|
||||
externalForce.y = externalForce.y.bipolarClamp(VELO_HARD_LIMIT)
|
||||
externalV.x = externalV.x.bipolarClamp(VELO_HARD_LIMIT) // displaceHitbox SHOULD use moveDelta
|
||||
externalV.y = externalV.y.bipolarClamp(VELO_HARD_LIMIT)
|
||||
|
||||
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
|
||||
*/
|
||||
if (!isNoCollideWorld) {
|
||||
displaceHitbox(delta)
|
||||
displaceHitbox(delta.toDouble())
|
||||
}
|
||||
else {
|
||||
val vecSum = externalForce + (controllerMoveDelta ?: Vector2(0.0, 0.0))
|
||||
hitbox.translate(vecSum * (Terrarum.PHYS_REF_FPS * delta))
|
||||
val vecSum = externalV + (controllerV ?: Vector2(0.0, 0.0))
|
||||
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)
|
||||
|
||||
// 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.
|
||||
setVerticalFriction(delta)
|
||||
//}
|
||||
@@ -470,33 +467,33 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
|
||||
if (!(isWalled(hitbox, COLLIDING_LEFT) && walkX < 0)
|
||||
|| !(isWalled(hitbox, COLLIDING_RIGHT) && walkX > 0)
|
||||
) {
|
||||
moveDelta.x = externalForce.x + walkX
|
||||
moveDelta.x = externalV.x + walkX
|
||||
}
|
||||
|
||||
// decide whether to ignore walkY
|
||||
if (!(isWalled(hitbox, COLLIDING_TOP) && walkY < 0)
|
||||
|| !(isWalled(hitbox, COLLIDING_BOTTOM) && walkY > 0)
|
||||
) {
|
||||
moveDelta.y = externalForce.y + walkY
|
||||
moveDelta.y = externalV.y + walkY
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!isWalled(hitbox, COLLIDING_LEFT)
|
||||
|| !isWalled(hitbox, COLLIDING_RIGHT)
|
||||
) {
|
||||
moveDelta.x = externalForce.x
|
||||
moveDelta.x = externalV.x
|
||||
}
|
||||
|
||||
// decide whether to ignore walkY
|
||||
if (!isWalled(hitbox, COLLIDING_TOP)
|
||||
|| !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
|
||||
* 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
|
||||
|
||||
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.
|
||||
// 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.
|
||||
*/
|
||||
private fun applyGravitation(delta: Double) {
|
||||
private fun applyGravitation(delta: Float) {
|
||||
|
||||
if (!isNoSubjectToGrav && !(gravitation.y > 0 && walledBottom || gravitation.y < 0 && walledTop)) {
|
||||
//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:
|
||||
// do nothing
|
||||
// [Friction]:
|
||||
// deform vector "externalForce"
|
||||
// deform vector "externalV"
|
||||
// if isControllable:
|
||||
// also alter walkX/Y
|
||||
// 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()
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -838,20 +835,20 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
|
||||
|
||||
// bounce X/Y
|
||||
if (bounceX) {
|
||||
externalForce.x *= elasticity
|
||||
controllerMoveDelta?.let { controllerMoveDelta!!.x *= elasticity }
|
||||
externalV.x *= elasticity
|
||||
controllerV?.let { controllerV!!.x *= elasticity }
|
||||
}
|
||||
if (bounceY) {
|
||||
externalForce.y *= elasticity
|
||||
controllerMoveDelta?.let { controllerMoveDelta!!.y *= elasticity }
|
||||
externalV.y *= elasticity
|
||||
controllerV?.let { controllerV!!.y *= elasticity }
|
||||
}
|
||||
if (zeroX) {
|
||||
externalForce.x = 0.0
|
||||
controllerMoveDelta?.let { controllerMoveDelta!!.x = 0.0 }
|
||||
externalV.x = 0.0
|
||||
controllerV?.let { controllerV!!.x = 0.0 }
|
||||
}
|
||||
if (zeroY) {
|
||||
externalForce.y = 0.0
|
||||
controllerMoveDelta?.let { controllerMoveDelta!!.y = 0.0 }
|
||||
externalV.y = 0.0
|
||||
controllerV?.let { controllerV!!.y = 0.0 }
|
||||
}
|
||||
|
||||
|
||||
@@ -1012,11 +1009,11 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
|
||||
(BlockCodex[tile].isSolid) ||
|
||||
// platforms, moving downward AND not "going down"
|
||||
(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) ||
|
||||
// platforms, moving downward
|
||||
(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
|
||||
|
||||
|
||||
@@ -1071,58 +1068,60 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
|
||||
|
||||
/** about stopping
|
||||
* for about get moving, see updateMovementControl */
|
||||
private fun setHorizontalFriction(delta: Double) {
|
||||
private fun setHorizontalFriction(delta: Float) {
|
||||
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 {
|
||||
// TODO status quo if !submerged else linearBlend(feetFriction, bodyFriction, submergedRatio)
|
||||
BASE_FRICTION * if (grounded) feetFriction else bodyFriction
|
||||
}
|
||||
|
||||
if (externalForce.x < 0) {
|
||||
externalForce.x += friction
|
||||
if (externalForce.x > 0) externalForce.x = 0.0 // compensate overshoot
|
||||
if (externalV.x < 0) {
|
||||
externalV.x += friction
|
||||
if (externalV.x > 0) externalV.x = 0.0 // compensate overshoot
|
||||
}
|
||||
else if (externalForce.x > 0) {
|
||||
externalForce.x -= friction
|
||||
if (externalForce.x < 0) externalForce.x = 0.0 // compensate overshoot
|
||||
else if (externalV.x > 0) {
|
||||
externalV.x -= friction
|
||||
if (externalV.x < 0) externalV.x = 0.0 // compensate overshoot
|
||||
}
|
||||
|
||||
if (this is Controllable) {
|
||||
if (controllerMoveDelta!!.x < 0) {
|
||||
controllerMoveDelta!!.x += friction
|
||||
if (controllerMoveDelta!!.x > 0) controllerMoveDelta!!.x = 0.0
|
||||
if (controllerV!!.x < 0) {
|
||||
controllerV!!.x += friction
|
||||
if (controllerV!!.x > 0) controllerV!!.x = 0.0
|
||||
}
|
||||
else if (controllerMoveDelta!!.x > 0) {
|
||||
controllerMoveDelta!!.x -= friction
|
||||
if (controllerMoveDelta!!.x < 0) controllerMoveDelta!!.x = 0.0
|
||||
else if (controllerV!!.x > 0) {
|
||||
controllerV!!.x -= friction
|
||||
if (controllerV!!.x < 0) controllerV!!.x = 0.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setVerticalFriction(delta: Double) {
|
||||
private fun setVerticalFriction(delta: Float) {
|
||||
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
|
||||
BASE_FRICTION * bodyFriction
|
||||
// TODO wall friction (wall skid) similar to setHorizintalFriction ?
|
||||
|
||||
if (externalForce.y < 0) {
|
||||
externalForce.y += friction
|
||||
if (externalForce.y > 0) externalForce.y = 0.0 // compensate overshoot
|
||||
|
||||
if (externalV.y < 0) {
|
||||
externalV.y += friction
|
||||
if (externalV.y > 0) externalV.y = 0.0 // compensate overshoot
|
||||
}
|
||||
else if (externalForce.y > 0) {
|
||||
externalForce.y -= friction
|
||||
if (externalForce.y < 0) externalForce.y = 0.0 // compensate overshoot
|
||||
else if (externalV.y > 0) {
|
||||
externalV.y -= friction
|
||||
if (externalV.y < 0) externalV.y = 0.0 // compensate overshoot
|
||||
}
|
||||
|
||||
if (this is Controllable) {
|
||||
if (controllerMoveDelta!!.y < 0) {
|
||||
controllerMoveDelta!!.y += friction
|
||||
if (controllerMoveDelta!!.y > 0) controllerMoveDelta!!.y = 0.0
|
||||
if (controllerV!!.y < 0) {
|
||||
controllerV!!.y += friction
|
||||
if (controllerV!!.y > 0) controllerV!!.y = 0.0
|
||||
}
|
||||
else if (controllerMoveDelta!!.y > 0) {
|
||||
controllerMoveDelta!!.y -= friction
|
||||
if (controllerMoveDelta!!.y < 0) controllerMoveDelta!!.y = 0.0
|
||||
else if (controllerV!!.y > 0) {
|
||||
controllerV!!.y -= friction
|
||||
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) {
|
||||
if (isVisible && sprite != null) {
|
||||
if (!KeyToggler.isOn(Input.Keys.F12)) {
|
||||
//if (!KeyToggler.isOn(Input.Keys.F12)) {
|
||||
BlendMode.resolve(drawMode, batch)
|
||||
drawSpriteInGoodPosition(sprite!!, batch)
|
||||
}
|
||||
/*}
|
||||
// ye olde tilewiseposition debugger, we don't use it anymore.
|
||||
else {
|
||||
batch.color = Color.NAVY
|
||||
val hb = intTilewiseHitbox
|
||||
@@ -1360,7 +1360,7 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
|
||||
|
||||
batch.color = Color.VIOLET
|
||||
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
|
||||
|
||||
if (value) {
|
||||
externalForce.zero()
|
||||
controllerMoveDelta?.zero()
|
||||
externalV.zero()
|
||||
controllerV?.zero()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ import org.luaj.vm2.*
|
||||
*/
|
||||
fun composeActorObject(actor: ActorWBMovable): 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["startX"] = actor.hitbox.centeredX.toLua()
|
||||
|
||||
@@ -68,6 +68,8 @@ class IngameController(val ingame: Ingame) : InputAdapter() {
|
||||
/////////////////////
|
||||
}
|
||||
|
||||
private var f12Down = false
|
||||
|
||||
override fun keyDown(keycode: Int): Boolean {
|
||||
|
||||
if (ingame.canPlayerControl) {
|
||||
@@ -90,14 +92,19 @@ class IngameController(val ingame: Ingame) : InputAdapter() {
|
||||
ingame.uiContainer.forEach { it.keyDown(keycode) } // for KeyboardControlled UIcanvases
|
||||
|
||||
// Debug UIs
|
||||
if (keycode == Input.Keys.F3) {
|
||||
ingame.debugWindow.toggleOpening()
|
||||
}
|
||||
if (keycode == Input.Keys.GRAVE) {
|
||||
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
|
||||
}
|
||||
|
||||
@@ -111,6 +118,10 @@ class IngameController(val ingame: Ingame) : InputAdapter() {
|
||||
ingame.uiContainer.forEach { it.keyUp(keycode) } // for KeyboardControlled UIcanvases
|
||||
|
||||
|
||||
// screenshot key
|
||||
if (keycode == Input.Keys.F12) f12Down = false
|
||||
|
||||
|
||||
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 (button == AppLoader.getConfigInt("mouseprimary")) {
|
||||
ingame.worldPrimaryClickEnd(AppLoader.getSmoothDelta().toFloat())
|
||||
ingame.worldPrimaryClickEnd(AppLoader.UPDATE_RATE.toFloat())
|
||||
}
|
||||
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 (button == AppLoader.getConfigInt("mouseprimary")) {
|
||||
ingame.worldPrimaryClickStart(AppLoader.getSmoothDelta().toFloat())
|
||||
ingame.worldPrimaryClickStart(AppLoader.UPDATE_RATE.toFloat())
|
||||
}
|
||||
if (button == AppLoader.getConfigInt("mousesecondary")) {
|
||||
ingame.worldSecondaryClickStart(AppLoader.getSmoothDelta().toFloat())
|
||||
ingame.worldSecondaryClickStart(AppLoader.UPDATE_RATE.toFloat())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package net.torvald.terrarum.gamecontroller
|
||||
/**
|
||||
* Created by minjaesong on 2016-01-15.
|
||||
*/
|
||||
@Deprecated("Use Gdx.Input.Keys")
|
||||
/*@Deprecated("Use Gdx.Input.Keys")
|
||||
object DeprecatedAsFuckKey {
|
||||
|
||||
val RETURN = 28
|
||||
@@ -90,4 +90,4 @@ object DeprecatedAsFuckKey {
|
||||
val PGDN = 209
|
||||
val HOME = 199
|
||||
val END = 207
|
||||
}
|
||||
}*/
|
||||
|
||||
@@ -1,29 +1,7 @@
|
||||
package net.torvald.terrarum.gameworld
|
||||
|
||||
import net.torvald.terrarum.blockproperties.Fluid
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2016-08-06.
|
||||
*/
|
||||
object FluidCodex {
|
||||
|
||||
operator fun get(type: FluidType): FluidProp {
|
||||
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
|
||||
}
|
||||
}
|
||||
// Use BlockCodex. --Torvald, 2019-01-27
|
||||
@@ -1,14 +1,9 @@
|
||||
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.
|
||||
*/
|
||||
class FluidProp {
|
||||
/*class FluidProp {
|
||||
|
||||
var density: Int = 0
|
||||
|
||||
@@ -45,4 +40,4 @@ class FluidProp {
|
||||
return p
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
@@ -2,6 +2,7 @@
|
||||
package net.torvald.terrarum.gameworld
|
||||
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import net.torvald.terrarum.Terrarum
|
||||
import net.torvald.terrarum.blockproperties.Block
|
||||
import net.torvald.terrarum.blockproperties.BlockCodex
|
||||
import net.torvald.terrarum.blockproperties.Fluid
|
||||
@@ -220,9 +221,13 @@ open class GameWorld {
|
||||
|
||||
fun setTileWall(x: Int, y: Int, tile: Byte, damage: Int) {
|
||||
val (x, y) = coerceXY(x, y)
|
||||
val oldWall = getTileFromWall(x, y)
|
||||
layerWall.setTile(x, y, tile)
|
||||
layerWallLowBits.setData(x, y, damage)
|
||||
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) {
|
||||
val (x, y) = coerceXY(x, y)
|
||||
val oldTerrain = getTileFromTerrain(x, y)
|
||||
layerTerrain.setTile(x, y, tile)
|
||||
layerTerrainLowBits.setData(x, y, damage)
|
||||
val blockAddr = LandUtil.getBlockAddr(this, x, y)
|
||||
@@ -240,11 +246,18 @@ open class GameWorld {
|
||||
fluidTypes.remove(blockAddr)
|
||||
}
|
||||
// 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) {
|
||||
val (x, y) = coerceXY(x, y)
|
||||
val oldWire = getTileFromWire(x, y)
|
||||
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? {
|
||||
@@ -412,7 +425,7 @@ open class GameWorld {
|
||||
data class FluidInfo(val type: FluidType, val amount: Float) {
|
||||
/** test if this fluid should be considered as one */
|
||||
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"
|
||||
}
|
||||
|
||||
@@ -443,6 +456,7 @@ open class GameWorld {
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
inline class FluidType(val value: Int) {
|
||||
|
||||
@@ -3,10 +3,10 @@ package net.torvald.terrarum.itemproperties
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import net.torvald.random.HQRNG
|
||||
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.langpack.Lang
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.ActorInventory
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
|
||||
|
||||
typealias ItemID = Int
|
||||
|
||||
@@ -207,28 +207,39 @@ abstract class GameItem : Comparable<GameItem>, Cloneable {
|
||||
object EquipPosition {
|
||||
@JvmStatic val NULL = -1
|
||||
|
||||
@JvmStatic val ARMOUR = 0
|
||||
// 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 HAND_GAUNTLET = 10
|
||||
@JvmStatic val HAND_BUFF2 = 11
|
||||
@JvmStatic val HAND_BUFF3 = 12
|
||||
@JvmStatic val HAND_BUFF4 = 13
|
||||
@JvmStatic val BODY_ARMOUR = 0
|
||||
@JvmStatic val BODY_FOOTWEAR = 1 // wings, jetpacks, etc.
|
||||
|
||||
@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 {
|
||||
|
||||
@@ -192,12 +192,38 @@ object ItemCodex {
|
||||
|
||||
override fun startSecondaryUse(delta: Float): Boolean {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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
|
||||
|
||||
@@ -233,23 +259,27 @@ object ItemCodex {
|
||||
fun getItemImage(item: GameItem?): TextureRegion? {
|
||||
if (item == null) return null
|
||||
|
||||
return getItemImage(item.originalID)
|
||||
}
|
||||
|
||||
fun getItemImage(itemOriginalID: Int): TextureRegion {
|
||||
// terrain
|
||||
if (item.originalID in ITEM_TILES) {
|
||||
if (itemOriginalID in ITEM_TILES) {
|
||||
return BlocksDrawer.tilesTerrain.get(
|
||||
(item.originalID % 16) * 16,
|
||||
item.originalID / 16
|
||||
(itemOriginalID % 16) * 16,
|
||||
itemOriginalID / 16
|
||||
)
|
||||
}
|
||||
// wall
|
||||
else if (item.originalID in ITEM_WALLS) {
|
||||
else if (itemOriginalID in ITEM_WALLS) {
|
||||
return BlocksDrawer.tileItemWall.get(
|
||||
(item.originalID.minus(ITEM_WALLS.first) % 16) * 16,
|
||||
(item.originalID.minus(ITEM_WALLS.first) / 16)
|
||||
(itemOriginalID.minus(ITEM_WALLS.first) % 16),
|
||||
(itemOriginalID.minus(ITEM_WALLS.first) / 16)
|
||||
)
|
||||
}
|
||||
// wire
|
||||
else if (item.originalID in ITEM_WIRES) {
|
||||
return BlocksDrawer.tilesWire.get((item.originalID % 16) * 16, item.originalID / 16)
|
||||
else if (itemOriginalID in ITEM_WIRES) {
|
||||
return BlocksDrawer.tilesWire.get((itemOriginalID % 16) * 16, itemOriginalID / 16)
|
||||
}
|
||||
// TODO get it real, using originalID...?
|
||||
else
|
||||
|
||||
@@ -118,7 +118,7 @@ object Lang {
|
||||
|
||||
// special treatment
|
||||
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"))
|
||||
"${AppLoader.fontGame.charsetOverrideBulgarian}${ret2.capitalize()}${AppLoader.fontGame.charsetOverrideDefault}"
|
||||
|
||||
@@ -4,23 +4,20 @@ import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.InputAdapter
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||
import net.torvald.terrarum.AppLoader
|
||||
import net.torvald.terrarum.IngameInstance
|
||||
import net.torvald.terrarum.Terrarum
|
||||
import net.torvald.terrarum.Yaml
|
||||
import net.torvald.terrarum.*
|
||||
import net.torvald.terrarum.blockproperties.Block
|
||||
import net.torvald.terrarum.gameactors.*
|
||||
import net.torvald.terrarum.gamecontroller.KeyToggler
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
||||
import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension
|
||||
import net.torvald.terrarum.modulebasegame.gameworld.WorldTime
|
||||
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.UINSMenu
|
||||
import net.torvald.terrarum.worlddrawer.LightmapRenderer
|
||||
import net.torvald.terrarum.worlddrawer.WorldCamera
|
||||
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||
import kotlin.system.measureNanoTime
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2018-07-06.
|
||||
@@ -29,24 +26,26 @@ class BuildingMaker(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
|
||||
private val menuYaml = Yaml("""
|
||||
- File
|
||||
- New
|
||||
- New flat ter.
|
||||
- New rand. ter.
|
||||
- Export…
|
||||
- Export sel…
|
||||
- Import…
|
||||
- Save world…
|
||||
- Load world…
|
||||
- Save terrain…
|
||||
- Load terrain…
|
||||
- Exit to Title : net.torvald.terrarum.modulebasegame.YamlCommandExit
|
||||
- Tool
|
||||
- Pencil
|
||||
- Pencil : net.torvald.terrarum.modulebasegame.YamlCommandToolPencil
|
||||
- Eyedropper
|
||||
- Select mrq.
|
||||
- Select mrq. : net.torvald.terrarum.modulebasegame.YamlCommandToolMarquee
|
||||
- Move
|
||||
- Undo
|
||||
- Redo
|
||||
- Time
|
||||
- Morning
|
||||
- Noon
|
||||
- Dusk
|
||||
- Night
|
||||
- Morning : net.torvald.terrarum.modulebasegame.YamlCommandSetTimeMorning
|
||||
- Noon : net.torvald.terrarum.modulebasegame.YamlCommandSetTimeNoon
|
||||
- Dusk : net.torvald.terrarum.modulebasegame.YamlCommandSetTimeDusk
|
||||
- Night : net.torvald.terrarum.modulebasegame.YamlCommandSetTimeNight
|
||||
- Set…
|
||||
- Weather
|
||||
- Sunny
|
||||
@@ -72,6 +71,8 @@ class BuildingMaker(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
}
|
||||
}
|
||||
|
||||
// set time to summer
|
||||
gameWorld.time.addTime(WorldTime.DAY_LENGTH * 32)
|
||||
|
||||
world = gameWorld
|
||||
}
|
||||
@@ -81,23 +82,29 @@ class BuildingMaker(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
|
||||
val uiToolbox = UINSMenu("Menu", 100, menuYaml)
|
||||
val notifier = Notification()
|
||||
val uiPalette = UIEditorPalette()
|
||||
|
||||
|
||||
val uiContainer = ArrayList<UICanvas>()
|
||||
|
||||
var currentPenMode = PENMODE_PENCIL
|
||||
|
||||
|
||||
val blockPointingCursor = object : ActorWithBody(Actor.RenderOrder.OVERLAY) {
|
||||
|
||||
override var referenceID: ActorID? = Terrarum.generateUniqueReferenceID(renderOrder)
|
||||
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)
|
||||
|
||||
|
||||
init {
|
||||
this.actorValue[AVKey.LUMR] = 1.0
|
||||
this.actorValue[AVKey.LUMG] = 1.0
|
||||
}
|
||||
|
||||
override fun drawBody(batch: SpriteBatch) {
|
||||
batch.color = Color.YELLOW
|
||||
batch.draw(body.get(0, 0), hitbox.startX.toFloat(), hitbox.startY.toFloat())
|
||||
batch.color = toolCursorColour[currentPenMode]
|
||||
batch.draw(body.get(currentPenMode, 0), hitbox.startX.toFloat(), hitbox.startY.toFloat())
|
||||
}
|
||||
|
||||
override fun drawGlow(batch: SpriteBatch) { }
|
||||
@@ -120,8 +127,15 @@ class BuildingMaker(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
}
|
||||
}
|
||||
|
||||
protected var updateDeltaCounter = 0.0
|
||||
protected val updateRate = 1.0 / Terrarum.TARGET_INTERNAL_FPS
|
||||
companion object {
|
||||
const val PENMODE_PENCIL = 0
|
||||
const val PENMODE_MARQUEE = 1
|
||||
|
||||
val toolCursorColour = arrayOf(
|
||||
Color.YELLOW,
|
||||
Color.MAGENTA
|
||||
)
|
||||
}
|
||||
|
||||
private val actorsRenderOverlay = ArrayList<ActorWithBody>()
|
||||
|
||||
@@ -132,12 +146,18 @@ class BuildingMaker(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
actorsRenderOverlay.add(blockPointingCursor)
|
||||
|
||||
uiContainer.add(uiToolbox)
|
||||
uiContainer.add(uiPalette)
|
||||
uiContainer.add(notifier)
|
||||
|
||||
|
||||
|
||||
uiToolbox.setPosition(0, 0)
|
||||
uiToolbox.isVisible = true
|
||||
uiToolbox.invocationArgument = arrayOf(this)
|
||||
|
||||
uiPalette.setPosition(Terrarum.WIDTH - uiPalette.width, 0)
|
||||
uiPalette.isVisible = true
|
||||
|
||||
notifier.setPosition(
|
||||
(Terrarum.WIDTH - notifier.width) / 2, Terrarum.HEIGHT - notifier.height)
|
||||
|
||||
@@ -154,43 +174,62 @@ class BuildingMaker(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
super.show()
|
||||
}
|
||||
|
||||
private var updateAkku = 0.0
|
||||
|
||||
override fun render(delta: Float) {
|
||||
Gdx.graphics.setTitle(Ingame.getCanonicalTitle())
|
||||
|
||||
|
||||
// ASYNCHRONOUS UPDATE AND RENDER //
|
||||
|
||||
val dt = Gdx.graphics.deltaTime
|
||||
updateAkku += dt
|
||||
|
||||
// async update
|
||||
updateDeltaCounter += delta
|
||||
if (delta < 1f / 10f) { // discard async if measured FPS <= 10
|
||||
var updateTries = 0
|
||||
while (updateDeltaCounter >= updateRate) {
|
||||
updateGame(delta)
|
||||
updateDeltaCounter -= updateRate
|
||||
updateTries++
|
||||
}
|
||||
}
|
||||
else {
|
||||
updateGame(delta)
|
||||
var i = 0L
|
||||
while (updateAkku >= delta) {
|
||||
AppLoader.measureDebugTime("Ingame.update") { updateGame(delta) }
|
||||
updateAkku -= delta
|
||||
i += 1
|
||||
}
|
||||
AppLoader.setDebugTime("Ingame.updateCounter", i)
|
||||
|
||||
// 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) {
|
||||
KeyToggler.update(false)
|
||||
var mouseOnUI = false
|
||||
|
||||
|
||||
WeatherMixer.update(delta, actorNowPlaying, gameWorld)
|
||||
blockPointingCursor.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)
|
||||
|
||||
|
||||
// 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() {
|
||||
IngameRenderer(world as GameWorldExtension, actorsRenderOverlay = actorsRenderOverlay, uisToDraw = uiContainer)
|
||||
IngameRenderer.invoke(world as GameWorldExtension, actorsRenderOverlay = actorsRenderOverlay, uisToDraw = uiContainer)
|
||||
}
|
||||
|
||||
override fun resize(width: Int, height: Int) {
|
||||
@@ -198,11 +237,24 @@ class BuildingMaker(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
uiToolbox.setPosition(0, 0)
|
||||
notifier.setPosition(
|
||||
(Terrarum.WIDTH - notifier.width) / 2, Terrarum.HEIGHT - notifier.height)
|
||||
|
||||
println("[BuildingMaker] Resize event")
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// let left mouse button to paint, because that's how graphic tablets work
|
||||
override fun touchDragged(screenX: Int, screenY: Int, pointer: Int): Boolean {
|
||||
screen.uiContainer.forEach { it.touchDragged(screenX, screenY, pointer) }
|
||||
return true
|
||||
@@ -260,10 +313,12 @@ class MovableWorldCamera : ActorHumanoid(0, usePhysics = false) {
|
||||
actorValue[AVKey.SPEED] = 8.0
|
||||
actorValue[AVKey.SPEEDBUFF] = 1.0
|
||||
actorValue[AVKey.ACCEL] = ActorHumanoid.WALK_ACCEL_BASE
|
||||
actorValue[AVKey.ACCELBUFF] = 1.0
|
||||
actorValue[AVKey.ACCELBUFF] = 4.0
|
||||
actorValue[AVKey.JUMPPOWER] = 0.0
|
||||
actorValue[AVKey.FRICTIONMULT] = 4.0
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,6 @@ import net.torvald.terrarum.console.Authenticator
|
||||
import net.torvald.terrarum.gameactors.Actor
|
||||
import net.torvald.terrarum.gameactors.ActorWithBody
|
||||
import net.torvald.terrarum.gamecontroller.IngameController
|
||||
import net.torvald.terrarum.gamecontroller.KeyToggler
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.itemproperties.GameItem
|
||||
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.gameworld.GameWorldExtension
|
||||
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.weather.WeatherMixer
|
||||
import net.torvald.terrarum.modulebasegame.worldgenerator.RoguelikeRandomiser
|
||||
import net.torvald.terrarum.modulebasegame.worldgenerator.WorldGenerator
|
||||
import net.torvald.terrarum.ui.BasicDebugInfoWindow
|
||||
import net.torvald.terrarum.ui.ConsoleWindow
|
||||
import net.torvald.terrarum.ui.UICanvas
|
||||
import net.torvald.terrarum.worlddrawer.FeaturesDrawer
|
||||
@@ -36,7 +32,6 @@ import net.torvald.terrarum.worlddrawer.LightmapRenderer
|
||||
import net.torvald.terrarum.worlddrawer.WorldCamera
|
||||
import java.util.*
|
||||
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 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
|
||||
//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 +
|
||||
" — F: ${Gdx.graphics.framesPerSecond}" +
|
||||
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"
|
||||
else
|
||||
""
|
||||
@@ -95,7 +95,6 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
|
||||
|
||||
|
||||
lateinit var debugWindow: UICanvas
|
||||
lateinit var notifier: UICanvas
|
||||
|
||||
lateinit var uiPieMenu: UICanvas
|
||||
@@ -276,31 +275,18 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
consoleHandler.setPosition(0, 0)
|
||||
|
||||
|
||||
// init debug window
|
||||
debugWindow = BasicDebugInfoWindow()
|
||||
debugWindow.setPosition(0, 0)
|
||||
|
||||
// init notifier
|
||||
notifier = Notification()
|
||||
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 -<
|
||||
// inventory
|
||||
/*uiInventoryPlayer = UIInventory(player,
|
||||
width = 900,
|
||||
height = Terrarum.HEIGHT - 160,
|
||||
categoryWidth = 210,
|
||||
toggleKeyLiteral = AppLoader.getConfigInt("keyinventory")
|
||||
)*/
|
||||
/*uiInventoryPlayer.setPosition(
|
||||
-uiInventoryPlayer.width,
|
||||
70
|
||||
)*/
|
||||
uiInventoryPlayer = UIInventoryFull(actorNowPlaying,
|
||||
uiInventoryPlayer = UIInventoryFull(actorNowPlaying!!,
|
||||
toggleKeyLiteral = AppLoader.getConfigInt("keyinventory")
|
||||
)
|
||||
uiInventoryPlayer.setPosition(0, 0)
|
||||
@@ -309,7 +295,7 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
// quick bar
|
||||
uiQuickBar = UIQuickslotBar()
|
||||
uiQuickBar.isVisible = true
|
||||
uiQuickBar.setPosition((Terrarum.WIDTH - uiQuickBar.width) / 2, 8)
|
||||
uiQuickBar.setPosition((Terrarum.WIDTH - uiQuickBar.width) / 2, AppLoader.getTvSafeGraphicsHeight())
|
||||
|
||||
// pie menu
|
||||
uiPieMenu = uiQuickslotPie()
|
||||
@@ -332,7 +318,10 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
|
||||
uiWatchTierOne = UITierOneWatch(actorNowPlaying)
|
||||
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()
|
||||
@@ -373,12 +362,12 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
|
||||
// these need to appear on top of any others
|
||||
uiContainer.add(notifier)
|
||||
uiContainer.add(debugWindow)
|
||||
|
||||
|
||||
LightmapRenderer.fireRecalculateEvent()
|
||||
|
||||
|
||||
AppLoader.setDebugTime("Ingame.updateCounter", 0)
|
||||
|
||||
|
||||
|
||||
@@ -408,7 +397,7 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
itemOnGrip?.endSecondaryUse(delta)
|
||||
}
|
||||
|
||||
protected val renderRate = Terrarum.renderRate
|
||||
|
||||
|
||||
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) {
|
||||
// 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
|
||||
}
|
||||
|
||||
|
||||
if (countdownToDeltaReset >= 0) {3
|
||||
if (countdownToDeltaReset == 0) {
|
||||
AppLoader.resetDeltaSmoothingHistory()
|
||||
}
|
||||
countdownToDeltaReset -= 1
|
||||
}
|
||||
|
||||
|
||||
// ASYNCHRONOUS UPDATE AND RENDER //
|
||||
|
||||
|
||||
/** UPDATE CODE GOES HERE */
|
||||
val dt = Gdx.graphics.deltaTime
|
||||
updateAkku += dt
|
||||
|
||||
|
||||
|
||||
if (false && AppLoader.getConfigBoolean("multithread")) { // NO MULTITHREADING: camera don't like concurrent modification (jittery actor movements)
|
||||
if (firstTimeRun || updateThreadWrapper.state == Thread.State.TERMINATED) {
|
||||
updateThreadWrapper = Thread(ingameUpdateThread, "Terrarum UpdateThread")
|
||||
updateThreadWrapper.start()
|
||||
|
||||
if (firstTimeRun) firstTimeRun = false
|
||||
}
|
||||
// else, NOP;
|
||||
}
|
||||
else {
|
||||
AppLoader.debugTimers["Ingame.update"] = measureNanoTime { updateGame(delta) }
|
||||
var i = 0L
|
||||
while (updateAkku >= delta) {
|
||||
AppLoader.measureDebugTime("Ingame.update") { updateGame(delta) }
|
||||
updateAkku -= delta
|
||||
i += 1
|
||||
}
|
||||
AppLoader.setDebugTime("Ingame.updateCounter", i)
|
||||
|
||||
|
||||
|
||||
/** RENDER CODE GOES HERE */
|
||||
AppLoader.debugTimers["Ingame.render"] = measureNanoTime { renderGame() }
|
||||
AppLoader.debugTimers["Ingame.render-Light"] =
|
||||
AppLoader.measureDebugTime("Ingame.render") { renderGame() }
|
||||
AppLoader.setDebugTime("Ingame.render-Light",
|
||||
(AppLoader.debugTimers["Ingame.render"] as Long) - ((AppLoader.debugTimers["Renderer.LightTotal"] as? Long) ?: 0)
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
protected fun updateGame(delta: Float) {
|
||||
@@ -484,7 +461,6 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
particlesActive = 0
|
||||
|
||||
|
||||
KeyToggler.update()
|
||||
ingameController.update(delta)
|
||||
|
||||
|
||||
@@ -505,8 +481,6 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
// camera-related updates //
|
||||
////////////////////////////
|
||||
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) }
|
||||
// TODO thread pool(?)
|
||||
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() {
|
||||
Gdx.graphics.setTitle(getCanonicalTitle())
|
||||
|
||||
filterVisibleActors()
|
||||
|
||||
IngameRenderer.invoke(
|
||||
world as GameWorldExtension,
|
||||
actorsRenderBehind,
|
||||
actorsRenderMiddle,
|
||||
actorsRenderMidTop,
|
||||
actorsRenderFront,
|
||||
actorsRenderOverlay,
|
||||
visibleActorsRenderBehind,
|
||||
visibleActorsRenderMiddle,
|
||||
visibleActorsRenderMidTop,
|
||||
visibleActorsRenderFront,
|
||||
visibleActorsRenderOverlay,
|
||||
particlesContainer,
|
||||
actorNowPlaying,
|
||||
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() {
|
||||
// check if currently pocessed actor is removed from game
|
||||
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)
|
||||
@@ -886,7 +884,7 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
}
|
||||
|
||||
override fun hide() {
|
||||
dispose()
|
||||
uiContainer.forEach { it.handler.dispose() }
|
||||
}
|
||||
|
||||
|
||||
@@ -914,6 +912,7 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
|
||||
notifier.setPosition(
|
||||
(Terrarum.WIDTH - notifier.width) / 2, Terrarum.HEIGHT - notifier.height)
|
||||
uiQuickBar.setPosition((Terrarum.WIDTH - uiQuickBar.width) / 2, AppLoader.getTvSafeGraphicsHeight())
|
||||
|
||||
// inventory
|
||||
/*uiInventoryPlayer =
|
||||
@@ -926,7 +925,11 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
|
||||
// basic watch-style notification bar (temperature, new mail)
|
||||
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() {
|
||||
IngameRenderer.dispose()
|
||||
|
||||
actorsRenderBehind.forEach { it.dispose() }
|
||||
actorsRenderMiddle.forEach { it.dispose() }
|
||||
actorsRenderMidTop.forEach { it.dispose() }
|
||||
actorsRenderFront.forEach { it.dispose() }
|
||||
actorsRenderOverlay.forEach { it.dispose() }
|
||||
|
||||
uiAliases.forEach { it.dispose() }
|
||||
uiAliasesPausing.forEach { it.dispose() }
|
||||
|
||||
|
||||
WatchDotAlph.dispose()
|
||||
Watch7SegMain.dispose()
|
||||
WatchDotAlph.dispose()
|
||||
|
||||
ItemSlotImageFactory.dispose()
|
||||
|
||||
MessageWindow.SEGMENT_BLACK.dispose()
|
||||
MessageWindow.SEGMENT_WHITE.dispose()
|
||||
uiContainer.forEach {
|
||||
it.handler.dispose()
|
||||
it.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -962,4 +955,5 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
printdbg(this, "-> $it")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -79,6 +79,9 @@ object IngameRenderer {
|
||||
|
||||
init()
|
||||
|
||||
batch.color = Color.WHITE
|
||||
|
||||
|
||||
BlocksDrawer.world = world
|
||||
LightmapRenderer.setWorld(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
|
||||
blendNormal(batch)
|
||||
batch.color = Color.WHITE
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -225,20 +225,20 @@ open class ActorHumanoid(
|
||||
isRightDown = Gdx.input.isKeyPressed(AppLoader.getConfigInt("keyright"))
|
||||
isJumpDown = Gdx.input.isKeyPressed(AppLoader.getConfigInt("keyjump"))
|
||||
|
||||
if (Terrarum.controller != null) {
|
||||
axisX = Terrarum.controller!!.getAxisValue(AppLoader.getConfigInt("joypadlstickx"))
|
||||
axisY = Terrarum.controller!!.getAxisValue(AppLoader.getConfigInt("joypadlsticky"))
|
||||
axisRX = Terrarum.controller!!.getAxisValue(AppLoader.getConfigInt("joypadrstickx"))
|
||||
axisRY = Terrarum.controller!!.getAxisValue(AppLoader.getConfigInt("joypadrsticky"))
|
||||
if (AppLoader.gamepad != null) {
|
||||
axisX = AppLoader.gamepad!!.getAxisValue(AppLoader.getConfigInt("gamepadlstickx"))
|
||||
axisY = AppLoader.gamepad!!.getAxisValue(AppLoader.getConfigInt("gamepadlsticky"))
|
||||
axisRX = AppLoader.gamepad!!.getAxisValue(AppLoader.getConfigInt("gamepadrstickx"))
|
||||
axisRY = AppLoader.gamepad!!.getAxisValue(AppLoader.getConfigInt("gamepadrsticky"))
|
||||
|
||||
// deadzonning
|
||||
if (Math.abs(axisX) < Terrarum.CONTROLLER_DEADZONE) axisX = 0f
|
||||
if (Math.abs(axisY) < Terrarum.CONTROLLER_DEADZONE) axisY = 0f
|
||||
if (Math.abs(axisRX) < Terrarum.CONTROLLER_DEADZONE) axisRX = 0f
|
||||
if (Math.abs(axisRY) < Terrarum.CONTROLLER_DEADZONE) axisRY = 0f
|
||||
if (Math.abs(axisX) < AppLoader.gamepadDeadzone) axisX = 0f
|
||||
if (Math.abs(axisY) < AppLoader.gamepadDeadzone) axisY = 0f
|
||||
if (Math.abs(axisRX) < AppLoader.gamepadDeadzone) axisRX = 0f
|
||||
if (Math.abs(axisRY) < AppLoader.gamepadDeadzone) axisRY = 0f
|
||||
|
||||
isJumpDown = Gdx.input.isKeyPressed(AppLoader.getConfigInt("keyjump")) ||
|
||||
Terrarum.controller!!.isButtonPressed(GAMEPAD_JUMP)
|
||||
AppLoader.gamepad!!.isButtonPressed(GAMEPAD_JUMP)
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -250,7 +250,7 @@ open class ActorHumanoid(
|
||||
}
|
||||
|
||||
private inline val hasController: Boolean
|
||||
get() = if (isGamer) Terrarum.controller != null
|
||||
get() = if (isGamer) AppLoader.gamepad != null
|
||||
else true
|
||||
|
||||
private fun processInput(delta: Float) {
|
||||
@@ -384,7 +384,7 @@ open class ActorHumanoid(
|
||||
*
|
||||
* 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)
|
||||
* @author minjaesong
|
||||
*/
|
||||
@@ -406,9 +406,9 @@ open class ActorHumanoid(
|
||||
avAcceleration * applyVelo(walkCounterX) * (if (left) -1f else 1f) * absAxisVal
|
||||
|
||||
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
|
||||
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) {
|
||||
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)
|
||||
*/
|
||||
@@ -444,9 +444,9 @@ open class ActorHumanoid(
|
||||
avAcceleration * applyVelo(walkCounterY) * (if (up) -1f else 1f) * absAxisVal
|
||||
|
||||
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
|
||||
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) {
|
||||
walkCounterY += 1
|
||||
@@ -489,6 +489,7 @@ open class ActorHumanoid(
|
||||
private var oldJUMPPOWERBUFF = -1.0 // init
|
||||
private var oldScale = -1.0
|
||||
private var oldDragCoefficient = -1.0
|
||||
// used by some AIs
|
||||
var jumpAirTime: Double = -1.0
|
||||
get() {
|
||||
// compare all the affecting variables
|
||||
@@ -519,7 +520,7 @@ open class ActorHumanoid(
|
||||
|
||||
val timedJumpCharge = jumpFunc(MAX_JUMP_LENGTH, jmpCtr)
|
||||
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
|
||||
|
||||
@@ -564,7 +565,7 @@ open class ActorHumanoid(
|
||||
|
||||
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
|
||||
// newtonian physics work, stupid myself :(
|
||||
|
||||
@@ -609,7 +610,7 @@ open class ActorHumanoid(
|
||||
sprite?.update(delta)
|
||||
spriteGlow?.update(delta)
|
||||
|
||||
if (walledBottom && controllerMoveDelta?.x != 0.0) {
|
||||
if (walledBottom && controllerV?.x != 0.0) {
|
||||
//switch row
|
||||
sprite?.switchRow(SPRITE_ROW_WALK)
|
||||
spriteGlow?.switchRow(SPRITE_ROW_WALK)
|
||||
@@ -617,8 +618,8 @@ open class ActorHumanoid(
|
||||
// set anim frame delay
|
||||
// 4f of the divider is a magic number, empirically decided
|
||||
if (this is HasAssembledSprite) {
|
||||
sprite?.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 * (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 * (controllerV?.x ?: 0.0001).abs().toFloat())) // FIXME empirical value
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -211,7 +211,7 @@ class ActorInventory(val actor: Pocketed, var maxCapacity: Int, var capacityMode
|
||||
actor.avStrength / 1000.0
|
||||
else
|
||||
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
|
||||
newItem.durability -= (baseDamagePerSwing * swingDmgToFrameDmg).toFloat()
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.torvald.terrarum.modulebasegame.gameactors
|
||||
|
||||
import net.torvald.terrarum.IngameInstance
|
||||
import net.torvald.terrarum.Point2d
|
||||
import net.torvald.terrarum.blockproperties.Block
|
||||
import net.torvald.terrarum.gameactors.ActorWBMovable
|
||||
@@ -7,9 +8,9 @@ import net.torvald.terrarum.gameactors.ActorWBMovable
|
||||
/**
|
||||
* 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
|
||||
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
|
||||
@@ -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) {
|
||||
|
||||
fun redefine(collisionType: Int, width: Int, height: Int) {
|
||||
|
||||
@@ -23,7 +23,7 @@ open class ParticleBase(renderOrder: Actor.RenderOrder, val despawnUponCollision
|
||||
/** Will NOT actually delete from the CircularArray */
|
||||
@Volatile var flagDespawn = false
|
||||
|
||||
override fun run() = update(AppLoader.getSmoothDelta().toFloat())
|
||||
override fun run() = update(AppLoader.UPDATE_RATE.toFloat())
|
||||
|
||||
var isNoSubjectToGrav = false
|
||||
var dragCoefficient = 3.0
|
||||
|
||||
@@ -10,7 +10,6 @@ import net.torvald.terrarum.gameactors.AVKey
|
||||
import net.torvald.terrarum.gameactors.ActorWBMovable
|
||||
import net.torvald.terrarum.gameactors.Controllable
|
||||
import net.torvald.terrarum.gameactors.Hitbox
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2018-01-17.
|
||||
@@ -37,7 +36,7 @@ class PhysTestLuarLander : ActorWBMovable(RenderOrder.MIDTOP), Controllable {
|
||||
super.update(delta)
|
||||
|
||||
if (Gdx.input.isKeyPressed(Input.Keys.UP)) {
|
||||
controllerMoveDelta!!.y = avSpeedCap
|
||||
controllerV!!.y = avSpeedCap
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -99,5 +99,6 @@ object PlayerBuilderSigrid {
|
||||
walls.forEach { inventory.add(it + 4096, 9995) }
|
||||
inventory.add(ItemCodex.ITEM_STATIC.first)
|
||||
inventory.add(9000)
|
||||
inventory.add(9001)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ interface Pocketed {
|
||||
}
|
||||
|
||||
inventory.itemEquipped[item.equipPosition] = null
|
||||
item.effectOnUnequip(AppLoader.getSmoothDelta().toFloat())
|
||||
item.effectOnUnequip(AppLoader.UPDATE_RATE.toFloat())
|
||||
}
|
||||
|
||||
// no need for equipSlot(Int)
|
||||
@@ -50,7 +50,7 @@ interface Pocketed {
|
||||
|
||||
if (item.equipPosition >= 0) {
|
||||
inventory.itemEquipped[item.equipPosition] = item
|
||||
item.effectWhenEquipped(AppLoader.getSmoothDelta().toFloat())
|
||||
item.effectWhenEquipped(AppLoader.UPDATE_RATE.toFloat())
|
||||
}
|
||||
// else do nothing
|
||||
}
|
||||
@@ -69,13 +69,13 @@ interface Pocketed {
|
||||
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,6 @@ import net.torvald.terrarum.blockproperties.BlockCodex
|
||||
import net.torvald.terrarum.gameactors.ActorWBMovable
|
||||
import net.torvald.terrarum.gameactors.Hitbox
|
||||
import net.torvald.terrarum.gameactors.Luminous
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import org.dyn4j.geometry.Vector2
|
||||
import java.util.*
|
||||
|
||||
@@ -54,7 +53,7 @@ open class ProjectileSimple(
|
||||
posPre = Point2d(fromPoint.x, fromPoint.y)
|
||||
// lightbox sized 8x8 centered to the bullet
|
||||
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
|
||||
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
|
||||
|
||||
|
||||
externalForce.set((fromPoint to toPoint).setMagnitude(speed.toDouble()))
|
||||
externalV.set((fromPoint to toPoint).setMagnitude(speed.toDouble()))
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -10,13 +10,13 @@ class ThreadActorUpdate(val startIndex: Int, val endIndex: Int) : Runnable {
|
||||
override fun run() {
|
||||
for (i in startIndex..endIndex) {
|
||||
val it = Terrarum.ingame!!.actorContainer[i]
|
||||
it.update(AppLoader.getSmoothDelta().toFloat())
|
||||
it.update(AppLoader.UPDATE_RATE.toFloat())
|
||||
|
||||
if (it is Pocketed) {
|
||||
it.inventory.forEach { inventoryEntry ->
|
||||
inventoryEntry.item.effectWhileInPocket(AppLoader.getSmoothDelta().toFloat())
|
||||
inventoryEntry.item.effectWhileInPocket(AppLoader.UPDATE_RATE.toFloat())
|
||||
if (it.equipped(inventoryEntry.item)) {
|
||||
inventoryEntry.item.effectWhenEquipped(AppLoader.getSmoothDelta().toFloat())
|
||||
inventoryEntry.item.effectWhenEquipped(AppLoader.UPDATE_RATE.toFloat())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,8 +150,8 @@ object CollisionSolver {
|
||||
|
||||
// if they actually makes collision (e.g. player vs ball), solve it
|
||||
if (a makesCollisionWith b) {
|
||||
val a_moveDelta = a.externalForce + a.controllerMoveDelta
|
||||
val b_moveDelta = b.externalForce + b.controllerMoveDelta
|
||||
val a_moveDelta = a.externalV + a.controllerV
|
||||
val b_moveDelta = b.externalV + b.controllerV
|
||||
|
||||
val ux_1 = a_moveDelta.x
|
||||
val ux_2 = b_moveDelta.x
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package net.torvald.terrarum.modulebasegame.gameworld
|
||||
|
||||
import net.torvald.terrarum.gameworld.fmod
|
||||
|
||||
|
||||
typealias time_t = Long
|
||||
|
||||
@@ -96,11 +98,11 @@ class WorldTime(initTime: Long = 0L) {
|
||||
|
||||
// these functions won't need inlining for performance
|
||||
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
|
||||
get() = (yearlyDays % 30) + 1
|
||||
get() = (yearlyDays % MONTH_LENGTH) + 1
|
||||
val months: Int // 1 - 4
|
||||
get() = (yearlyDays / 30) + 1
|
||||
get() = (yearlyDays / MONTH_LENGTH) + 1
|
||||
val years: Int
|
||||
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
|
||||
|
||||
/**
|
||||
* 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 =
|
||||
if (s.length >= 4 && s.contains('h')) {
|
||||
s.toLowerCase().substringBefore('h').toInt() * HOUR_SEC +
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
@@ -23,7 +23,7 @@ class PickaxeGeneric(override val originalID: ItemID) : GameItem() {
|
||||
override var stackable = true
|
||||
override var maxDurability = 147
|
||||
override var durability = maxDurability.toFloat()
|
||||
override val equipPosition = 9
|
||||
override val equipPosition = GameItem.EquipPosition.HAND_GRIP
|
||||
override var inventoryCategory = Category.TOOL
|
||||
override val isUnique = false
|
||||
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)
|
||||
// return false if hitting actors
|
||||
Terrarum.ingame!!.actorContainer.forEach({
|
||||
Terrarum.ingame!!.actorContainer.forEach {
|
||||
if (it is ActorWBMovable && it.hIntTilewiseHitbox.intersects(mousePoint))
|
||||
return false
|
||||
})
|
||||
}
|
||||
|
||||
// return false if here's no tile
|
||||
if (Block.AIR == (Terrarum.ingame!!.world).getTileFromTerrain(mouseTileX, mouseTileY))
|
||||
|
||||
@@ -17,8 +17,11 @@ import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||
*/
|
||||
object ItemSlotImageFactory {
|
||||
|
||||
val colourBlack = Color(0x404040_FF)
|
||||
val colourWhite = Color(0xC0C0C0_FF.toInt())
|
||||
val CELLCOLOUR_BLACK_OPAQUE = Color(0x404040_FF)
|
||||
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
|
||||
|
||||
|
||||
@@ -1,19 +1,10 @@
|
||||
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.
|
||||
*/
|
||||
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
|
||||
|
||||
@@ -49,6 +40,9 @@ class MessageWindow(override var width: Int, isBlackVariant: Boolean) : UICanvas
|
||||
messagesList.forEachIndexed { index, s ->
|
||||
Terrarum.fontGame.draw(batch, s, segment.tileW + LRmargin, (segment.tileH - Terrarum.fontGame.lineHeight) / 2f)
|
||||
}
|
||||
|
||||
AppLoader.printdbg(this, "render")
|
||||
|
||||
}
|
||||
|
||||
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_WHITE = TextureRegionPack("assets/graphics/gui/message_white.tga", 8, 56)
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
@@ -1,32 +1,45 @@
|
||||
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.AppLoader
|
||||
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-23.
|
||||
*/
|
||||
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
|
||||
|
||||
internal var msgUI = MessageWindow(width, true)
|
||||
|
||||
override var height: Int = msgUI.height
|
||||
override var height: Int = segment.tileH
|
||||
private val visibleTime = Math.min(
|
||||
AppLoader.getConfigInt("notificationshowuptime"),
|
||||
SHOWUP_MAX
|
||||
)
|
||||
) / 1000f
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
@@ -60,7 +99,6 @@ class Notification : UICanvas() {
|
||||
|
||||
fun sendNotification(message: Array<String>) {
|
||||
this.message = message
|
||||
msgUI.setMessage(this.message)
|
||||
handler.openCloseCounter = 0f
|
||||
handler.opacity = 0f
|
||||
handler.setAsOpen()
|
||||
@@ -68,4 +106,15 @@ class Notification : UICanvas() {
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
164
src/net/torvald/terrarum/modulebasegame/ui/UIEditorPalette.kt
Normal file
164
src/net/torvald/terrarum/modulebasegame/ui/UIEditorPalette.kt
Normal 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
|
||||
}
|
||||
}
|
||||
@@ -142,9 +142,9 @@ package net.torvald.terrarum.modulebasegame.ui
|
||||
"${0xe011.toChar()}..${0xe010.toChar()} ${Lang["GAME_INVENTORY_REGISTER"]}$SP" +
|
||||
"${0xe034.toChar()} ${Lang["GAME_INVENTORY_DROP"]}"
|
||||
else
|
||||
"$joypadLabelNinY ${Lang["GAME_INVENTORY_USE"]}$SP" +
|
||||
"$gamepadLabelNinY ${Lang["GAME_INVENTORY_USE"]}$SP" +
|
||||
"${0xe011.toChar()}${0xe010.toChar()} ${Lang["GAME_INVENTORY_REGISTER"]}$SP" +
|
||||
"$joypadLabelNinA ${Lang["GAME_INVENTORY_DROP"]}"
|
||||
"$gamepadLabelNinA ${Lang["GAME_INVENTORY_DROP"]}"
|
||||
val listControlClose: String
|
||||
get() = if (Terrarum.environment == RunningEnvironment.PC)
|
||||
"${0xe037.toChar()} ${Lang["GAME_ACTION_CLOSE"]}"
|
||||
|
||||
@@ -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.Pocketed
|
||||
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
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2017-10-21.
|
||||
*/
|
||||
class UIInventoryFull(
|
||||
var actor: Pocketed?,
|
||||
var actor: Pocketed,
|
||||
|
||||
toggleKeyLiteral: Int? = null, toggleButtonLiteral: Int? = null,
|
||||
// UI positions itself? (you must g.flush() yourself after the g.translate(Int, Int))
|
||||
@@ -27,11 +30,15 @@ class UIInventoryFull(
|
||||
doNotWarnConstant: Boolean = false
|
||||
) : UICanvas(toggleKeyLiteral, toggleButtonLiteral, customPositioning, doNotWarnConstant) {
|
||||
|
||||
private val debugvals = false
|
||||
|
||||
override var width: Int = Terrarum.WIDTH
|
||||
override var height: Int = Terrarum.HEIGHT
|
||||
|
||||
val internalWidth: Int = 686
|
||||
val internalHeight: Int = 558 // grad_begin..grad_end..contents..grad_begin..grad_end
|
||||
private val itemListToEquipViewGap = 24
|
||||
|
||||
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"]}"
|
||||
else
|
||||
"${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" +
|
||||
"${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
|
||||
|
||||
private var encumbrancePerc = 0f
|
||||
@@ -62,7 +79,7 @@ class UIInventoryFull(
|
||||
val categoryBar = UIItemInventoryCatBar(
|
||||
this,
|
||||
(Terrarum.WIDTH - catBarWidth) / 2,
|
||||
66 + (Terrarum.HEIGHT - internalHeight) / 2,
|
||||
42 + (Terrarum.HEIGHT - internalHeight) / 2,
|
||||
catBarWidth
|
||||
)
|
||||
val catSelection: Int
|
||||
@@ -73,48 +90,100 @@ class UIInventoryFull(
|
||||
override var openCloseTime: Second = 0.0f
|
||||
|
||||
|
||||
private val itemList: UIItemInventoryDynamicList? =
|
||||
if (actor != null) {
|
||||
private val itemList: UIItemInventoryDynamicList =
|
||||
UIItemInventoryDynamicList(
|
||||
this,
|
||||
actor!!.inventory,
|
||||
actor.inventory,
|
||||
0 + (Terrarum.WIDTH - internalWidth) / 2,
|
||||
109 + (Terrarum.HEIGHT - internalHeight) / 2
|
||||
)
|
||||
}
|
||||
else null
|
||||
|
||||
|
||||
private val equipped: UIItemInventoryEquippedView? =
|
||||
if (actor != null) {
|
||||
private val equipped: UIItemInventoryEquippedView =
|
||||
UIItemInventoryEquippedView(
|
||||
this,
|
||||
actor!!.inventory,
|
||||
actor.inventory,
|
||||
actor as ActorWBMovable,
|
||||
internalWidth - UIItemInventoryEquippedView.width + (Terrarum.WIDTH - internalWidth) / 2,
|
||||
internalWidth - UIItemInventoryEquippedView.WIDTH + (Terrarum.WIDTH - internalWidth) / 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 {
|
||||
addItem(categoryBar)
|
||||
itemList?.let { addItem(it) }
|
||||
equipped?.let { addItem(it) }
|
||||
itemList.let { addItem(it) }
|
||||
equipped.let { addItem(it) }
|
||||
|
||||
|
||||
categoryBar.selectionChangeListener = { old, new ->
|
||||
rebuildList()
|
||||
itemList?.itemPage = 0 // set scroll to zero
|
||||
itemList?.rebuild() // have to manually rebuild, too!
|
||||
itemList.itemPage = 0 // set scroll to zero
|
||||
itemList.rebuild() // have to manually rebuild, too!
|
||||
}
|
||||
|
||||
|
||||
|
||||
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()
|
||||
@@ -129,8 +198,9 @@ class UIInventoryFull(
|
||||
|
||||
|
||||
categoryBar.update(delta)
|
||||
itemList?.update(delta)
|
||||
equipped?.update(delta)
|
||||
|
||||
transitionalUpdateUIs.forEach { it.update(delta) }
|
||||
|
||||
}
|
||||
|
||||
private val gradStartCol = Color(0x404040_60)
|
||||
@@ -140,9 +210,45 @@ class UIInventoryFull(
|
||||
|
||||
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) {
|
||||
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
|
||||
@@ -167,32 +273,111 @@ class UIInventoryFull(
|
||||
|
||||
// UI items
|
||||
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
|
||||
blendNormal(batch)
|
||||
batch.color = Color.WHITE
|
||||
Terrarum.fontGame.draw(batch, listControlHelp, offsetX, offsetY + internalHeight)
|
||||
Terrarum.fontGame.draw(batch, listControlHelp, offsetX + inventoryScrOffX, yEnd - 20)
|
||||
|
||||
|
||||
// encumbrance meter
|
||||
if (actor != null) {
|
||||
val encumbranceText = Lang["GAME_INVENTORY_ENCUMBRANCE"]
|
||||
|
||||
Terrarum.fontGame.draw(batch,
|
||||
encumbranceText,
|
||||
xEnd - 9 - Terrarum.fontGame.getWidth(encumbranceText) - weightBarWidth,
|
||||
yEnd
|
||||
xEnd - 9 - Terrarum.fontGame.getWidth(encumbranceText) - weightBarWidth + inventoryScrOffX,
|
||||
yEnd-20
|
||||
)
|
||||
|
||||
// encumbrance bar background
|
||||
blendMul(batch)
|
||||
batch.color = Color(0xa0a0a0_ff.toInt())
|
||||
batch.fillRect(
|
||||
xEnd - 3 - weightBarWidth,
|
||||
yEnd + 3f,
|
||||
xEnd - 3 - weightBarWidth + inventoryScrOffX,
|
||||
yEnd-20 + 3f,
|
||||
weightBarWidth,
|
||||
controlHelpHeight - 6f
|
||||
)
|
||||
@@ -200,33 +385,29 @@ class UIInventoryFull(
|
||||
blendNormal(batch)
|
||||
batch.color = if (isEncumbered) Color(0xff0000_cc.toInt()) else Color(0x00ff00_cc.toInt())
|
||||
batch.fillRect(
|
||||
xEnd - 3 - weightBarWidth,
|
||||
yEnd + 3f,
|
||||
if (actor?.inventory?.capacityMode == CAPACITY_MODE_NO_ENCUMBER)
|
||||
xEnd - 3 - weightBarWidth + inventoryScrOffX,
|
||||
yEnd-20 + 3f,
|
||||
if (actor.inventory.capacityMode == CAPACITY_MODE_NO_ENCUMBER)
|
||||
1f
|
||||
else // make sure 1px is always be seen
|
||||
minOf(weightBarWidth, maxOf(1f, weightBarWidth * encumbrancePerc)),
|
||||
controlHelpHeight - 5f
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
fun rebuildList() {
|
||||
itemList?.rebuild()
|
||||
equipped?.rebuild()
|
||||
itemList.rebuild()
|
||||
equipped.rebuild()
|
||||
|
||||
actor?.let {
|
||||
encumbrancePerc = actor!!.inventory.capacity.toFloat() / actor!!.inventory.maxCapacity
|
||||
isEncumbered = actor!!.inventory.isEncumbered
|
||||
}
|
||||
encumbrancePerc = actor.inventory.capacity.toFloat() / actor.inventory.maxCapacity
|
||||
isEncumbered = actor.inventory.isEncumbered
|
||||
}
|
||||
|
||||
override fun dispose() {
|
||||
categoryBar.dispose()
|
||||
itemList?.dispose()
|
||||
equipped?.dispose()
|
||||
itemList.dispose()
|
||||
equipped.dispose()
|
||||
}
|
||||
|
||||
|
||||
@@ -243,7 +424,7 @@ class UIInventoryFull(
|
||||
}
|
||||
|
||||
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()
|
||||
offsetY = ((Terrarum.HEIGHT - internalHeight) / 2).toFloat()
|
||||
|
||||
xEnd = (Terrarum.WIDTH + internalWidth).div(2).toFloat()
|
||||
yEnd = (Terrarum.HEIGHT + internalHeight).div(2).toFloat()
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import net.torvald.terrarum.itemproperties.ItemCodex
|
||||
import net.torvald.terrarum.modulebasegame.Ingame
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.ActorInventory
|
||||
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.UIItemImageButton
|
||||
import java.util.*
|
||||
@@ -32,8 +33,14 @@ class UIItemInventoryDynamicList(
|
||||
override var posY: Int
|
||||
) : UIItem(parentUI) {
|
||||
|
||||
override val width = 496
|
||||
override val height = 384
|
||||
// deal with the moving position
|
||||
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
|
||||
|
||||
@@ -74,35 +81,44 @@ class UIItemInventoryDynamicList(
|
||||
|
||||
val defaultTextColour = Color(0xeaeaea_ff.toInt())
|
||||
|
||||
private val listGap = 8
|
||||
private val itemList = Array<UIItemInventoryCellBase>(7 * 2) {
|
||||
UIItemInventoryElem(
|
||||
companion object {
|
||||
const val listGap = 8
|
||||
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,
|
||||
posX = this.posX + (272 + listGap) * (it % 2),
|
||||
posY = this.posY + (UIItemInventoryElem.height + listGap) * (it / 2),
|
||||
width = 272,
|
||||
posX = this.posX + (UIItemInventoryElemSimple.height + listGap) * (it % horizontalCells),
|
||||
posY = this.posY + (UIItemInventoryElemSimple.height + listGap) * (it / horizontalCells),
|
||||
item = null,
|
||||
amount = UIItemInventoryElem.UNIQUE_ITEM_HAS_NO_AMOUNT,
|
||||
itemImage = null,
|
||||
mouseoverBackCol = Color(0x282828_ff),
|
||||
mouseoverBackBlendMode = BlendMode.SCREEN,
|
||||
backCol = Color(0x404040_88),
|
||||
backCol = backColour,
|
||||
backBlendMode = BlendMode.NORMAL,
|
||||
drawBackOnNull = true,
|
||||
inactiveTextCol = defaultTextColour
|
||||
)
|
||||
}
|
||||
private val itemGrid = Array<UIItemInventoryCellBase>(7 * 10) {
|
||||
UIItemInventoryElemSimple(
|
||||
private val itemList = Array<UIItemInventoryCellBase>(verticalCells * 2) {
|
||||
UIItemInventoryElem(
|
||||
parentUI = inventoryUI,
|
||||
posX = this.posX + (UIItemInventoryElemSimple.height + listGap) * (it % 10),
|
||||
posY = this.posY + (UIItemInventoryElemSimple.height + listGap) * (it / 10),
|
||||
posX = this.posX + (largeListWidth + listGap) * (it % 2),
|
||||
posY = this.posY + (UIItemInventoryElem.height + listGap) * (it / 2),
|
||||
width = largeListWidth,
|
||||
item = null,
|
||||
amount = UIItemInventoryElem.UNIQUE_ITEM_HAS_NO_AMOUNT,
|
||||
itemImage = null,
|
||||
mouseoverBackCol = Color(0x282828_ff),
|
||||
mouseoverBackBlendMode = BlendMode.SCREEN,
|
||||
backCol = Color(0x404040_88),
|
||||
backCol = backColour,
|
||||
backBlendMode = BlendMode.NORMAL,
|
||||
drawBackOnNull = true,
|
||||
inactiveTextCol = defaultTextColour
|
||||
@@ -196,6 +212,15 @@ class UIItemInventoryDynamicList(
|
||||
private val upDownButtonGapToDots = 7 // apparent gap may vary depend on the texture itself
|
||||
|
||||
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
|
||||
|
||||
scrollDownButton.posY = getScrollDotYHeight(itemPageCount) + upDownButtonGapToDots
|
||||
@@ -221,6 +246,8 @@ class UIItemInventoryDynamicList(
|
||||
}
|
||||
|
||||
super.render(batch, camera)
|
||||
|
||||
oldPosX = posX
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import net.torvald.terrarum.gameactors.ActorWBMovable
|
||||
import net.torvald.terrarum.itemproperties.GameItem
|
||||
import net.torvald.terrarum.itemproperties.ItemCodex
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.ActorInventory
|
||||
import net.torvald.terrarum.modulebasegame.ui.ItemSlotImageFactory.CELLCOLOUR_BLACK
|
||||
import net.torvald.terrarum.ui.UIItem
|
||||
|
||||
/**
|
||||
@@ -21,12 +22,12 @@ class UIItemInventoryEquippedView(
|
||||
override var posY: Int
|
||||
) : UIItem(parentUI) {
|
||||
|
||||
override val width = 104
|
||||
override val height = 384
|
||||
override val width = WIDTH
|
||||
override val height = HEIGHT
|
||||
|
||||
companion object {
|
||||
val width = 104
|
||||
val height = 384
|
||||
val WIDTH = 2 * UIItemInventoryElemSimple.height + UIItemInventoryDynamicList.listGap
|
||||
val HEIGHT = UIItemInventoryDynamicList.HEIGHT
|
||||
}
|
||||
|
||||
private val listGap = 8
|
||||
@@ -37,9 +38,9 @@ class UIItemInventoryEquippedView(
|
||||
lateinit var inventorySortList: Array<GameItem?>
|
||||
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(
|
||||
parentUI = parentUI,
|
||||
posX = this.posX + (UIItemInventoryElemSimple.height + listGap) * ((it + 4) % 2),
|
||||
@@ -49,7 +50,7 @@ class UIItemInventoryEquippedView(
|
||||
itemImage = null,
|
||||
mouseoverBackCol = Color(0x282828_ff),
|
||||
mouseoverBackBlendMode = BlendMode.SCREEN,
|
||||
backCol = Color(0x404040_88),
|
||||
backCol = CELLCOLOUR_BLACK,
|
||||
backBlendMode = BlendMode.NORMAL,
|
||||
drawBackOnNull = true
|
||||
)
|
||||
@@ -60,7 +61,18 @@ class UIItemInventoryEquippedView(
|
||||
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) {
|
||||
val posXDelta = posX - oldPosX
|
||||
itemGrid.forEach { it.posX += posXDelta }
|
||||
|
||||
|
||||
|
||||
// sprite background
|
||||
blendNormal(batch)
|
||||
batch.color = spriteViewBackCol
|
||||
@@ -74,51 +86,49 @@ class UIItemInventoryEquippedView(
|
||||
sprite?.let {
|
||||
blendNormal(batch)
|
||||
|
||||
it.render(
|
||||
batch,
|
||||
batch.color = spriteDrawCol
|
||||
batch.draw(
|
||||
it.textureRegion.get(0, 0),
|
||||
posX + (width - it.cellWidth).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() {
|
||||
inventorySortList = inventory.itemEquipped.clone()
|
||||
|
||||
|
||||
|
||||
rebuildList = false
|
||||
|
||||
// sort by equip position
|
||||
|
||||
// fill the grid from fastest index, make no gap in-between of slots
|
||||
var listPushCnt = 0
|
||||
for (k in 0 until itemGrid.size) {
|
||||
val it = inventorySortList[k]
|
||||
val item = inventory.itemEquipped[k]
|
||||
|
||||
if (it != null) {
|
||||
val itemRecord = inventory.getByDynamicID(it.dynamicID)!!
|
||||
if (item == null) {
|
||||
|
||||
itemGrid[listPushCnt].item = it
|
||||
itemGrid[listPushCnt].amount = itemRecord.amount
|
||||
itemGrid[listPushCnt].itemImage = ItemCodex.getItemImage(it)
|
||||
itemGrid[listPushCnt].quickslot = null // don't need to be displayed
|
||||
itemGrid[listPushCnt].equippedSlot = null // don't need to be displayed
|
||||
|
||||
listPushCnt++
|
||||
}
|
||||
itemGrid[k].item = null
|
||||
itemGrid[k].amount = 0
|
||||
itemGrid[k].itemImage = null
|
||||
itemGrid[k].quickslot = null
|
||||
itemGrid[k].equippedSlot = null
|
||||
}
|
||||
else {
|
||||
val itemRecord = inventory.getByDynamicID(item.dynamicID)!!
|
||||
|
||||
// empty out un-filled grids from previous garbage
|
||||
for (m in listPushCnt until itemGrid.size) {
|
||||
itemGrid[m].item = null
|
||||
itemGrid[m].amount = 0
|
||||
itemGrid[m].itemImage = null
|
||||
itemGrid[m].quickslot = null
|
||||
itemGrid[m].equippedSlot = null
|
||||
itemGrid[k].item = item
|
||||
itemGrid[k].amount = itemRecord.amount
|
||||
itemGrid[k].itemImage = ItemCodex.getItemImage(item)
|
||||
itemGrid[k].quickslot = null // don't need to be displayed
|
||||
itemGrid[k].equippedSlot = null // don't need to be displayed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,10 @@ class UIItemModuleInfoCell(
|
||||
override var posY: Int
|
||||
) : UIItem(parent) {
|
||||
|
||||
// deal with the moving position
|
||||
override var oldPosX = posX
|
||||
override var oldPosY = posY
|
||||
|
||||
override val height: Int = Terrarum.fontGame.lineHeight.toInt() * 2
|
||||
|
||||
private val numberAreaWidth = Terrarum.fontSmallNumbers.W * 3 + 4
|
||||
|
||||
@@ -20,6 +20,10 @@ class UIItemSavegameInfoCell(
|
||||
override var posY: Int
|
||||
) : 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 fun render(batch: SpriteBatch, camera: Camera) {
|
||||
|
||||
@@ -41,6 +41,8 @@ class UIQuickslotBar : UICanvas() {
|
||||
override fun updateUI(delta: Float) {
|
||||
}
|
||||
|
||||
private val drawColor = Color(1f,1f,1f,1f)
|
||||
|
||||
override fun renderUI(batch: SpriteBatch, camera: Camera) {
|
||||
|
||||
for (i in 0..SLOT_COUNT - 1) {
|
||||
@@ -55,7 +57,8 @@ class UIQuickslotBar : UICanvas() {
|
||||
val slotY = cellSize / 2
|
||||
|
||||
// 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)
|
||||
|
||||
}
|
||||
|
||||
@@ -8,9 +8,7 @@ import net.torvald.terrarum.*
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
||||
import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension
|
||||
import net.torvald.terrarum.modulebasegame.gameworld.WorldTime
|
||||
import net.torvald.terrarum.modulebasegame.imagefont.Watch7SegMain
|
||||
import net.torvald.terrarum.modulebasegame.imagefont.Watch7SegSmall
|
||||
import net.torvald.terrarum.modulebasegame.imagefont.WatchDotAlph
|
||||
import net.torvald.terrarum.modulebasegame.imagefont.WatchFont
|
||||
import net.torvald.terrarum.ui.UICanvas
|
||||
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||
|
||||
@@ -18,28 +16,26 @@ import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||
* Created by minjaesong on 2017-06-11.
|
||||
*/
|
||||
class UITierOneWatch(private val player: ActorHumanoid?) : UICanvas() {
|
||||
override var width = 77
|
||||
override var height = 53
|
||||
override var width = 160
|
||||
override var height = 23
|
||||
override var openCloseTime: Second = 0f
|
||||
|
||||
private var ELuptimer = 10f // init value higher than uptime: to make the light turned off by default
|
||||
private val ELuptime = 4f
|
||||
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 timeFont = Watch7SegMain
|
||||
private var textFont = WatchDotAlph
|
||||
private var watchFont = WatchFont
|
||||
private var moonDial = TextureRegionPack(ModMgr.getPath("basegame", "fonts/watch_17pxmoondial.tga"), 17, 17)
|
||||
private var moonDialCount = moonDial.horizontalCount
|
||||
|
||||
private val drawCol = Color(1f,1f,1f,0.5f)
|
||||
private val lcdLitColELoff = Color(0x141414_aa)
|
||||
private val lcdLitColELon = Color(0x141414_ff)
|
||||
private val drawCol = Color(1f,1f,1f,UIQuickslotBar.DISPLAY_OPACITY)
|
||||
private val lcdLitColELoff = Color(0xc0c0c0ff.toInt()) mul drawCol
|
||||
private val lcdLitColELon = Color(0x404040ff) mul drawCol
|
||||
|
||||
private val lcdLitCol: Color
|
||||
get() = if (ELon) lcdLitColELon else lcdLitColELoff
|
||||
private val lcdLitCol: Color = lcdLitColELoff
|
||||
//get() = if (ELon) lcdLitColELon else lcdLitColELoff
|
||||
|
||||
private val worldTime: WorldTime
|
||||
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) {
|
||||
// light overlay or EL
|
||||
/*blendNormal(batch)
|
||||
if (ELon) {
|
||||
blendNormal(batch)
|
||||
batch.draw(atlas.get(0, 2), 0f, 0f)
|
||||
}
|
||||
else {
|
||||
// backplate
|
||||
batch.draw(atlas.get(0, 0), 0f, 0f)
|
||||
}*/
|
||||
// disabling light button
|
||||
batch.color = drawCol
|
||||
batch.draw(atlas.get(0, 0), 0f, 0f)
|
||||
}
|
||||
|
||||
// LCD back
|
||||
blendNormal(batch)
|
||||
batch.draw(atlas.get(0, 3), 0f, 0f)
|
||||
|
||||
|
||||
|
||||
// day name
|
||||
batch.color = lcdLitCol
|
||||
textFont.draw(batch, worldTime.getDayNameShort().toUpperCase(), 9f, 5f)
|
||||
watchFont.draw(batch, worldTime.getDayNameShort().toUpperCase(), 73f, 7f)
|
||||
|
||||
// day
|
||||
littleFont.draw(batch, worldTime.days.toString().padStart(2, ' '), 54f, 4f)
|
||||
watchFont.draw(batch, worldTime.days.toString().padStart(2, '@'), 107f, 7f)
|
||||
|
||||
// hour
|
||||
timeFont.draw(batch, worldTime.hours.toString().padStart(2, '/'), 25f, 31f)
|
||||
watchFont.draw(batch, worldTime.hours.toString().padStart(2, '@'), 27f, 7f)
|
||||
// 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
|
||||
batch.draw(atlas.get(1, worldTime.months - 1), 0f, 0f)
|
||||
@@ -97,7 +90,7 @@ class UITierOneWatch(private val player: ActorHumanoid?) : UICanvas() {
|
||||
// moon dial
|
||||
val moonPhase = (worldTime.moonPhase * moonDialCount).roundInt() % moonDialCount
|
||||
batch.color = lcdLitCol
|
||||
batch.draw(moonDial.get(moonPhase, 0), 4f, 19f)
|
||||
batch.draw(moonDial.get(moonPhase, 0), 6f, 3f)
|
||||
}
|
||||
|
||||
override fun doOpening(delta: Float) {
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
package net.torvald.terrarum.modulebasegame.ui
|
||||
|
||||
import net.torvald.terrarum.AppLoader
|
||||
import net.torvald.terrarum.QNDTreeNode
|
||||
import net.torvald.terrarum.Yaml
|
||||
import java.util.*
|
||||
|
||||
|
||||
|
||||
@@ -24,12 +22,14 @@ object UITitleRemoConYaml {
|
||||
- MENU_OPTIONS
|
||||
- MENU_OPTIONS_GRAPHICS
|
||||
- MENU_OPTIONS_CONTROLS
|
||||
- MENU_CONTROLS_KEYBOARD
|
||||
- MENU_CONTROLS_GAMEPAD
|
||||
- MENU_LABEL_RETURN
|
||||
- MENU_OPTIONS_SOUND
|
||||
- MENU_LABEL_LANGUAGE : net.torvald.terrarum.modulebasegame.ui.UITitleLanguage
|
||||
- MENU_LABEL_RETURN
|
||||
- MENU_MODULES : net.torvald.terrarum.modulebasegame.ui.UITitleModules
|
||||
- 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_CREDIT_GPL_DNT : net.torvald.terrarum.modulebasegame.ui.UITitleGPL3
|
||||
|
||||
@@ -57,6 +57,8 @@ class uiQuickslotPie : UICanvas() {
|
||||
}
|
||||
}
|
||||
|
||||
private val drawColor = Color(1f,1f,1f,1f)
|
||||
|
||||
override fun renderUI(batch: SpriteBatch, camera: Camera) {
|
||||
// draw radial thingies
|
||||
for (i in 0..slotCount - 1) {
|
||||
@@ -75,7 +77,8 @@ class uiQuickslotPie : UICanvas() {
|
||||
val slotX = slotCentrePoint.x.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)
|
||||
|
||||
}
|
||||
|
||||
@@ -2,25 +2,26 @@ package net.torvald.terrarum.modulebasegame.weather
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.Input
|
||||
import com.badlogic.gdx.graphics.*
|
||||
import com.badlogic.gdx.utils.GdxRuntimeException
|
||||
import net.torvald.terrarum.utils.JsonFetcher
|
||||
import net.torvald.colourutil.*
|
||||
import com.badlogic.gdx.graphics.Camera
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.graphics.GL20
|
||||
import com.badlogic.gdx.graphics.Texture
|
||||
import net.torvald.colourutil.CIELuvUtil
|
||||
import net.torvald.random.HQRNG
|
||||
import net.torvald.terrarum.*
|
||||
import net.torvald.terrarum.console.CommandDict
|
||||
import net.torvald.terrarum.console.SetGlobalLightOverride
|
||||
import net.torvald.terrarum.GdxColorMap
|
||||
import net.torvald.terrarum.ModMgr
|
||||
import net.torvald.terrarum.Terrarum
|
||||
import net.torvald.terrarum.gameactors.ActorWithBody
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.ParticleMegaRain
|
||||
import net.torvald.terrarum.gamecontroller.KeyToggler
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.modulebasegame.Ingame
|
||||
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.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.WorldCamera
|
||||
import net.torvald.terrarum.modulebasegame.worldgenerator.WorldGenerator
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
@@ -96,7 +97,7 @@ internal object WeatherMixer : RNGConsumer {
|
||||
|
||||
|
||||
// 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 playerPosY = player.hitbox.centeredY
|
||||
kotlin.repeat(7) {
|
||||
|
||||
62
src/net/torvald/terrarum/tests/FixedMathTest.kt
Normal file
62
src/net/torvald/terrarum/tests/FixedMathTest.kt
Normal 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()
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
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.LwjglApplicationConfiguration
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.graphics.OrthographicCamera
|
||||
import com.badlogic.gdx.graphics.Texture
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||
import com.badlogic.gdx.graphics.glutils.ShaderProgram
|
||||
import net.torvald.terrarum.*
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.jme3.math.FastMath
|
||||
import net.torvald.terrarum.*
|
||||
import net.torvald.terrarum.Terrarum.mouseTileX
|
||||
import net.torvald.terrarum.Terrarum.mouseTileY
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.modulebasegame.Ingame
|
||||
import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension
|
||||
import net.torvald.terrarum.worlddrawer.FeaturesDrawer
|
||||
@@ -19,8 +20,8 @@ import net.torvald.terrarum.worlddrawer.WorldCamera
|
||||
*/
|
||||
class BasicDebugInfoWindow : UICanvas() {
|
||||
|
||||
override var width: Int = Terrarum.WIDTH
|
||||
override var height: Int = Terrarum.HEIGHT
|
||||
override var width: Int = AppLoader.screenW
|
||||
override var height: Int = AppLoader.screenH
|
||||
|
||||
override var openCloseTime: Float = 0f
|
||||
|
||||
@@ -30,14 +31,17 @@ class BasicDebugInfoWindow : UICanvas() {
|
||||
private var xdelta = 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
|
||||
get() = Terrarum.ingame!!.world as GameWorldExtension
|
||||
private val world: GameWorld?
|
||||
get() = Terrarum.ingame?.world
|
||||
private val world2: GameWorldExtension?
|
||||
get() = Terrarum.ingame?.world as GameWorldExtension?
|
||||
|
||||
|
||||
override fun updateUI(delta: Float) {
|
||||
val player = ingame.actorNowPlaying
|
||||
val player = ingame?.actorNowPlaying
|
||||
val hitbox = player?.hitbox
|
||||
|
||||
if (hitbox != null) {
|
||||
@@ -65,7 +69,7 @@ class BasicDebugInfoWindow : UICanvas() {
|
||||
}
|
||||
|
||||
override fun renderUI(batch: SpriteBatch, camera: Camera) {
|
||||
val player = ingame.actorNowPlaying
|
||||
val player = ingame?.actorNowPlaying
|
||||
|
||||
batch.color = Color(0xFFEE88FF.toInt())
|
||||
|
||||
@@ -108,11 +112,11 @@ class BasicDebugInfoWindow : UICanvas() {
|
||||
+ ccG
|
||||
+ "${WorldCamera.y}")
|
||||
|
||||
printLine(batch, 3, "veloX reported $ccG${player.externalForce.x}")
|
||||
printLine(batch, 4, "veloY reported $ccG${player.externalForce.y}")
|
||||
printLine(batch, 3, "veloX reported $ccG${player.externalV.x}")
|
||||
printLine(batch, 4, "veloY reported $ccG${player.externalV.y}")
|
||||
|
||||
printLine(batch, 5, "p_WalkX $ccG${player.controllerMoveDelta?.x}")
|
||||
printLine(batch, 6, "p_WalkY $ccG${player.controllerMoveDelta?.y}")
|
||||
printLine(batch, 5, "p_WalkX $ccG${player.controllerV?.x}")
|
||||
printLine(batch, 6, "p_WalkY $ccG${player.controllerV?.y}")
|
||||
|
||||
printLineColumn(batch, 2, 3, "veloX measured $ccG${xdelta}")
|
||||
printLineColumn(batch, 2, 4, "veloY measured $ccG${ydelta}")
|
||||
@@ -144,12 +148,15 @@ class BasicDebugInfoWindow : UICanvas() {
|
||||
else "$rawR $rawG $rawB $rawA"
|
||||
printLine(batch, 8, "light@cursor $ccG$lightVal")
|
||||
|
||||
val tileNum = ingame.world.getTileFromTerrain(mouseTileX, mouseTileY) ?: -1
|
||||
val fluid = ingame.world.getFluid(mouseTileX, mouseTileY)
|
||||
if (ingame != null) {
|
||||
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, 10, "fluid@cursor ${ccY}Type $ccM${fluid.type.value} ${ccY}Fill $ccG${fluid.amount}f")
|
||||
|
||||
}
|
||||
|
||||
|
||||
// print time
|
||||
var dbgCnt = 12
|
||||
@@ -166,8 +173,10 @@ class BasicDebugInfoWindow : UICanvas() {
|
||||
//printLineColumn(batch, 2, 1, "VSync $ccG" + Terrarum.appgc.isVSyncRequested)
|
||||
//printLineColumn(batch, 2, 2, "Env colour temp $ccG" + FeaturesDrawer.colTemp)
|
||||
|
||||
printLineColumn(batch, 2, 5, "Time $ccG${world.time.todaySeconds.toString().padStart(5, '0')}" +
|
||||
" (${world.time.getFormattedTime()})")
|
||||
if (world != null) {
|
||||
printLineColumn(batch, 2, 5, "Time $ccG${world2!!.time.todaySeconds.toString().padStart(5, '0')}" +
|
||||
" (${world2!!.time.getFormattedTime()})")
|
||||
}
|
||||
|
||||
if (player != null) {
|
||||
printLineColumn(batch, 2, 6, "Mass $ccG${player.mass}")
|
||||
@@ -182,10 +191,10 @@ class BasicDebugInfoWindow : UICanvas() {
|
||||
|
||||
batch.color = Color.WHITE
|
||||
|
||||
if (Terrarum.controller != null) {
|
||||
if (AppLoader.gamepad != null) {
|
||||
drawGamepadAxis(batch,
|
||||
Terrarum.controller!!.getAxisValue(3),
|
||||
Terrarum.controller!!.getAxisValue(2),
|
||||
AppLoader.gamepad!!.getAxisValue(3),
|
||||
AppLoader.gamepad!!.getAxisValue(2),
|
||||
Terrarum.WIDTH - 135,
|
||||
40
|
||||
)
|
||||
@@ -216,15 +225,18 @@ class BasicDebugInfoWindow : UICanvas() {
|
||||
* 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)
|
||||
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)
|
||||
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)
|
||||
Terrarum.fontSmallNumbers.draw(batch, "${ccM}Particles $ccG${ingame.particlesActive}",
|
||||
if (ingame is Ingame) {
|
||||
Terrarum.fontSmallNumbers.draw(batch, "${ccM}Particles $ccG${(ingame as Ingame).particlesActive}",
|
||||
(2 + 41 * 8).toFloat(), Terrarum.HEIGHT - 10f)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Bottom right
|
||||
@@ -235,8 +247,8 @@ class BasicDebugInfoWindow : UICanvas() {
|
||||
(Terrarum.WIDTH - 2 - totalHardwareName.length * 8).toFloat(), Terrarum.HEIGHT - 10f)
|
||||
}
|
||||
|
||||
private val processorName = Terrarum.processor.replace(Regex(""" Processor|( CPU)? @ [0-9.]+GHz"""), "")
|
||||
private val rendererName = Terrarum.renderer
|
||||
private val processorName = AppLoader.processor.replace(Regex(""" Processor|( CPU)? @ [0-9.]+GHz"""), "")
|
||||
private val rendererName = AppLoader.renderer
|
||||
private val totalHardwareName = "$processorName $rendererName"
|
||||
|
||||
private fun printLine(batch: SpriteBatch, l: Int, s: String) {
|
||||
@@ -304,8 +316,8 @@ class BasicDebugInfoWindow : UICanvas() {
|
||||
val pointDX = axisX * halfW
|
||||
val pointDY = axisY * halfH
|
||||
|
||||
val padName = if (Terrarum.controller!!.name.isEmpty()) "Gamepad"
|
||||
else Terrarum.controller!!.name
|
||||
val padName = if (AppLoader.gamepad!!.name.isEmpty()) "Gamepad"
|
||||
else AppLoader.gamepad!!.name
|
||||
|
||||
blendNormal(batch)
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package net.torvald.terrarum.ui
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.graphics.Camera
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||
import com.badlogic.gdx.utils.Disposable
|
||||
import net.torvald.terrarum.AppLoader
|
||||
import net.torvald.terrarum.Second
|
||||
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))
|
||||
customPositioning: Boolean = false, // mainly used by vital meter
|
||||
doNotWarnConstant: Boolean = false
|
||||
) {
|
||||
): Disposable {
|
||||
|
||||
abstract var width: Int
|
||||
abstract var height: Int
|
||||
@@ -36,7 +37,7 @@ abstract class UICanvas(
|
||||
/**
|
||||
* Usage: (in StateInGame:) uiHandlerField.ui.handler = uiHandlerField
|
||||
*/
|
||||
protected val handler = UIHandler(toggleKeyLiteral, toggleButtonLiteral, customPositioning, doNotWarnConstant)
|
||||
val handler = UIHandler(toggleKeyLiteral, toggleButtonLiteral, customPositioning, doNotWarnConstant)
|
||||
|
||||
init {
|
||||
|
||||
@@ -59,12 +60,14 @@ abstract class UICanvas(
|
||||
get() = Terrarum.mouseScreenY - handler.posY
|
||||
|
||||
/** If mouse is hovering over it regardless of its visibility */
|
||||
val mouseUp: Boolean
|
||||
get() = relativeMouseX in 0..width - 1 && relativeMouseY in 0..height - 1
|
||||
open val mouseUp: Boolean
|
||||
get() = _mouseUpThis || handler.mouseUp
|
||||
/** If mouse is hovering over it and mouse is down */
|
||||
val mousePushed: Boolean
|
||||
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 */
|
||||
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.
|
||||
* 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)
|
||||
|
||||
@@ -111,7 +117,7 @@ abstract class UICanvas(
|
||||
*/
|
||||
abstract fun endClosing(delta: Float)
|
||||
|
||||
abstract fun dispose()
|
||||
abstract override fun dispose()
|
||||
|
||||
fun addItem(uiItem: UIItem) {
|
||||
uiItems.add(uiItem)
|
||||
@@ -200,7 +206,7 @@ abstract class UICanvas(
|
||||
|
||||
// handler func aliases //
|
||||
|
||||
fun setPosition(x: Int, y: Int) {
|
||||
open fun setPosition(x: Int, y: Int) {
|
||||
handler.setPosition(x, y)
|
||||
}
|
||||
|
||||
@@ -208,15 +214,15 @@ abstract class UICanvas(
|
||||
handler.setAsAlwaysVisible()
|
||||
}
|
||||
|
||||
fun setAsOpen() {
|
||||
open fun setAsOpen() {
|
||||
handler.setAsOpen()
|
||||
}
|
||||
|
||||
fun setAsClose() {
|
||||
open fun setAsClose() {
|
||||
handler.setAsClose()
|
||||
}
|
||||
|
||||
fun toggleOpening() {
|
||||
open fun toggleOpening() {
|
||||
handler.toggleOpening()
|
||||
}
|
||||
|
||||
@@ -254,7 +260,7 @@ abstract class UICanvas(
|
||||
const val OPENCLOSE_GENERIC = 0.2f
|
||||
|
||||
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) {
|
||||
ui.handler.opacity = (openCloseTime - ui.handler.openCloseCounter) / openCloseTime
|
||||
|
||||
@@ -3,8 +3,9 @@ package net.torvald.terrarum.ui
|
||||
import com.badlogic.gdx.graphics.Camera
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
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.modulebasegame.Ingame
|
||||
|
||||
/**
|
||||
* 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))
|
||||
var customPositioning: Boolean = false, // mainly used by vital meter
|
||||
var doNotWarnConstant: Boolean = false
|
||||
) {
|
||||
): Disposable {
|
||||
|
||||
// X/Y Position relative to the game window.
|
||||
var posX: Int = 0
|
||||
@@ -54,8 +55,14 @@ class UIHandler(//var UI: UICanvas,
|
||||
var closeFired = false
|
||||
|
||||
var opacity = 1f
|
||||
set(value) {
|
||||
field = value
|
||||
opacityColour.set(1f,1f,1f,opacity)
|
||||
}
|
||||
var scale = 1f
|
||||
|
||||
val opacityColour = Color(1f,1f,1f,opacity)
|
||||
|
||||
var openCloseCounter = 0f
|
||||
|
||||
init {
|
||||
@@ -69,6 +76,15 @@ class UIHandler(//var UI: 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) {
|
||||
if (subUIs.contains(ui))
|
||||
throw IllegalArgumentException(
|
||||
@@ -174,13 +190,18 @@ class UIHandler(//var UI: UICanvas,
|
||||
|
||||
ui.renderUI(batch, camera)
|
||||
//ingameGraphics.flush()
|
||||
batch.color = Color.WHITE
|
||||
|
||||
|
||||
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) {
|
||||
@@ -341,4 +362,10 @@ class UIHandler(//var UI: UICanvas,
|
||||
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
Reference in New Issue
Block a user