Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
.gradle/
gradle-app.setting
/build/
/funkin/build/
/flixelgdx/build/
/polyverse/build/
/android/build/
/core/build/
/lwjgl2/build/
/lwjgl3/build/
/html/build/
/teavm/build/
Expand Down
6 changes: 3 additions & 3 deletions COMPILING.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# How to Compile FNF:JE

> [!TIP]
> If you want some helpful info about the Gradle tasks (or the framework FNF:JE uses), consider taking a look at [LIBGDX.md](LIBGDX.md)!
> If you want some helpful info about the Gradle tasks (or the framework FNF:JE uses), consider taking a look at [LIBGDX.md](PROJECT.md)!

There are two main ways you can download and compile the game's code: with GitHub Desktop or the terminal.

Expand All @@ -12,13 +12,13 @@ In this guide, we'll use the GitHub Desktop method, since it the most user-frien
- A [Java Development Kit (JDK)](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html) to compile the game's code.
- An integrated development environment.
- We recommend either one of the options listed below:
- [Intellij IDEA](https://www.jetbrains.com/idea/download/)
- [IntelliJ IDEA](https://www.jetbrains.com/idea/download/)
- [Eclipse](https://www.eclipse.org/downloads/)
- [VS Code](https://code.visualstudio.com/)
- Some basic knowledge of programming (especially Gradle) and how to navigate an IDE.

> [!TIP]
> Although every IDE listed is great for Java, we STRONGLY recommend Intellij IDEA, due to how beginner friendly and integrated it is with FNF:JE!
> Although every IDE listed is great for Java, we STRONGLY recommend IntelliJ IDEA, due to how beginner-friendly and integrated it is with FNF:JE!

# Step-by-Step Guide

Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ hard to understand in general, then they won't be any
use. Even too many comments are unnecessary, since your code should be
self documented and easily readable.

<u>***Formatting MUST match the [Google Java Style Guide](https://google.github.io/styleguide/javaguide.html).***</u>
<u>***Formatting MUST match the configurations set in the [editor config file](.editorconfig), with the formatting based on the [Google Java Style Guide](https://google.github.io/styleguide/javaguide.html).***</u>

### Example of GOOD Comments (With Good Formatting)

Expand Down
7 changes: 5 additions & 2 deletions LIBGDX.md → PROJECT.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@

FNF:JE is designed to run on multiple different platforms. Below are the different modules that hold the code for each one.

- `core`: Main module with the game's logic shared by all platforms. <u>This is where you want to write your source code!</u>
- `lwjgl3`: Primary desktop platform using [LWJGL3](https://www.lwjgl.org/). <u>This is what launches the desktop versions of the game!</u>
- `funkin`: The core part of the game's code. This is where all the game logic is implemented.
- `flixelgdx`: Custom framework that bridges [HaxeFlixel](https://haxeflixel.com/) and is based on libGDX. This is where the HaxeFlixel-like API is implemented.
- `polyverse`: Custom library for adding modding capabilities to the game.
- `lwjgl3`: Primary desktop platform using [LWJGL3](https://www.lwjgl.org/). This is what launches the desktop versions of the game!
- `android`: Android mobile platform. <u>This requires the Android SDK, which can be downloaded and configured simply by running the universal [setup file](setup/android_setup.sh)!</u>

> [!IMPORTANT]
Expand All @@ -32,6 +34,7 @@ The Gradle wrapper was included, so you can run Gradle tasks using `gradlew.bat`
- `clean`: removes `build` folders, which store compiled classes and built archives.
- `eclipse`: generates Eclipse project data.
- `idea`: generates IntelliJ project data.
- `funkin:exportModSDK`: Exports the game's API and its dependencies as `.jar` files to the assets folder.
- `lwjgl3:jar`: builds the game's runnable jar, which can be found at `lwjgl3/build/libs`.
- `lwjgl3:run`: starts the desktop version of the game.
- `test`: runs unit tests (if any).
Expand Down
19 changes: 18 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,21 @@

Welcome to the official GitHub repository for the Java edition of Friday Night Funkin'!

### Please note that this unofficial version of the game is NOT completed! This has a long way to go, but with YOUR help, we can make this project come alive! <3
> [!NOTICE]
> This is a fan-made project and is not affiliated with the original developers. You can play the original game [here](https://ninja-muffin24.itch.io/funkin).

## <u>Please note that this unofficial version of the game is NOT completed! This has a long way to go, but with YOUR help, we can make this project come alive! <3</u>

# About the Project
Friday Night Funkin': Java Edition is an open-source project that aims to recreate the popular rhythm game [Friday Night Funkin'](https://github.com/FunkinCrew/Funkin) using Java.
It is built using its own custom framework based on libGDX, called FlixelGDX: a Java port of the HaxeFlixel framework used in the original game.

The project is designed to have practically endless modding capabilities, empowering developers to use features for mods
which otherwise would be impossible to accomplish in the original game and HaxeFlixel.

# Project Navigation

- [Contributing](CONTRIBUTING.md)
- [Project Structure and Gradle Tasks](PROJECT.md)
- [Compiling the Game](COMPILING.md)
- [License](LICENSE.md)
2 changes: 1 addition & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ configurations { natives }
dependencies {
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.5'
implementation "com.badlogicgames.gdx:gdx-backend-android:$gdxVersion"
implementation project(':core')
implementation project(':funkin')

api "games.rednblack.miniaudio:gdx-miniaudio-platform:$miniaudioVersion:natives-armeabi-v7a"
api "games.rednblack.miniaudio:gdx-miniaudio-platform:$miniaudioVersion:natives-arm64-v8a"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import com.badlogic.gdx.backends.android.AndroidApplication;
import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;
import me.stringdotjar.funkin.FunkinGame;
import me.stringdotjar.funkin.init.InitScreen;
import me.stringdotjar.funkin.InitScreen;
import me.stringdotjar.funkin.util.FunkinConstants;

/** Launches the Android application. */
Expand Down

This file was deleted.

This file was deleted.

17 changes: 17 additions & 0 deletions flixelgdx/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
eclipse.project.name = appName + '-flixelgdx'

dependencies {
api "com.badlogicgames.gdx:gdx-freetype:$gdxVersion"
api "com.badlogicgames.gdx:gdx:$gdxVersion"
api "com.github.tommyettinger:anim8-gdx:$anim8Version"
api "com.github.tommyettinger:libgdx-utils:$utilsVersion"
api "io.github.libktx:ktx-freetype:$ktxVersion"
api "games.rednblack.miniaudio:miniaudio:$miniaudioVersion"

implementation "org.jetbrains:annotations:26.0.2-1"

if (enableGraalNative == 'true') {
implementation "io.github.berstanio:gdx-svmhelper-annotations:$graalHelperVersion"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,12 @@ public final class Flixel {
private static MAGroup soundsGroup;

/** The sound for playing music throughout the game. */
public static MASound music;
private static MASound music;

/** The current master volume that is set. */
private static float masterVolume = 1;

/**
* The static instance used to access the core elements of the game. This includes the main loop,
* setting the current screen, and more.
*/
/** The static instance used to access the core elements of the game. */
private static FlixelGame game;

/** Has the global manager been initialized yet? */
Expand Down Expand Up @@ -323,7 +320,7 @@ public static void playMusic(String path, float volume, boolean looping, boolean
* @param volume The new master volume to set.
*/
public static void setMasterVolume(float volume) {
engine.setMasterVolume(volume);
engine.setMasterVolume(!(volume > 1.0) ? volume : 1.0f);
masterVolume = volume;
}

Expand Down Expand Up @@ -458,7 +455,7 @@ private static void outputLog(String tag, Object message, FlixelLogLevel level)
false,
underline);
String formattedTag = colorText("[" + level + "] [" + tag + "] [" + file + "] [" + method + "] ", color, true, false, underline);
String formattedMessage = colorText(message.toString(), color, false, true, underline);
String formattedMessage = colorText((message != null) ? message.toString() : null, color, false, true, underline);

System.out.println(timeAndDate + formattedTag + formattedMessage);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,9 @@
import com.badlogic.gdx.utils.viewport.FitViewport;
import me.stringdotjar.flixelgdx.graphics.screen.FlixelScreen;
import me.stringdotjar.flixelgdx.graphics.sprite.FlixelObject;
import me.stringdotjar.flixelgdx.graphics.sprite.FlixelSprite;
import me.stringdotjar.flixelgdx.tween.FlixelTween;
import me.stringdotjar.flixelgdx.util.FlixelConstants;
import me.stringdotjar.flixelgdx.util.FlixelRuntimeUtil;
import me.stringdotjar.funkin.util.FunkinConstants;
import me.stringdotjar.polyverse.Polyverse;
import me.stringdotjar.polyverse.script.type.Script;

import static me.stringdotjar.flixelgdx.signal.FlixelSignalData.RenderSignalData;

Expand All @@ -37,11 +33,14 @@ public abstract class FlixelGame implements ApplicationListener {
protected String title;

/** The size of the game's starting window position and its viewport. */
protected Vector2 size;
protected Vector2 windowSize;

/** The entry point screen the game starts in (which becomes null after the game is done setting up!). */
protected FlixelScreen initialScreen;

/** Is the game's window currently focused? */
protected boolean isFocused = true;

/** Is the game's window currently minimized? */
protected boolean isMinimized = false;

Expand Down Expand Up @@ -71,7 +70,7 @@ public abstract class FlixelGame implements ApplicationListener {
*/
public FlixelGame(String title, int width, int height, FlixelScreen initialScreen) {
this.title = title;
this.size = new Vector2(width, height);
this.windowSize = new Vector2(width, height);
this.initialScreen = initialScreen;
}

Expand All @@ -80,11 +79,11 @@ public void create() {
configureCrashHandler(); // This should ALWAYS be called first no matter what!

batch = new SpriteBatch();
viewport = new FitViewport(size.x, size.y);
viewport = new FitViewport(windowSize.x, windowSize.y);
viewport.apply();

camera = new OrthographicCamera();
camera.setToOrtho(false, size.x, size.y);
camera.setToOrtho(false, windowSize.x, windowSize.y);

stage = new Stage(viewport, batch);

Expand Down Expand Up @@ -127,10 +126,11 @@ public void render() {
screen.render(delta);
var members = screen.members.begin();
for (FlixelObject object : members) {
if (object instanceof FlixelSprite sprite) {
sprite.update(delta);
sprite.draw(batch);
if (object == null) {
continue;
}
object.update(delta);
object.draw(batch);
}
screen.members.end();
}
Expand All @@ -152,7 +152,7 @@ public void resume() {}

/** Called when the user regains focus on the game's window. */
public void onWindowFocused() {
Flixel.setMasterVolume(1);
isFocused = true;
Flixel.Signals.windowFocused.dispatch();
Flixel.info("Game window has regained focus.");
}
Expand All @@ -162,7 +162,7 @@ public void onWindowUnfocused() {
if (isMinimized) {
return;
}
Flixel.setMasterVolume(0.008f);
isFocused = false;
Flixel.Signals.windowUnfocused.dispatch();
Flixel.info("Game window has lost focus.");
}
Expand All @@ -178,7 +178,7 @@ public void onWindowMinimized(boolean iconified) {
if (!isMinimized) {
return;
}
Flixel.setMasterVolume(0);
isFocused = false;
Flixel.Signals.windowMinimized.dispatch();
Flixel.info("Game window has been minimized.");
}
Expand All @@ -187,7 +187,7 @@ public void onWindowMinimized(boolean iconified) {
public void toggleFullscreen() {
boolean isFullscreen = Gdx.graphics.isFullscreen();
if (isFullscreen) {
Gdx.graphics.setWindowedMode(FunkinConstants.WINDOW_WIDTH, FunkinConstants.WINDOW_HEIGHT);
Gdx.graphics.setWindowedMode((int) windowSize.x, (int) windowSize.y);
Flixel.info("Exiting fullscreen mode.");
} else {
Gdx.graphics.setFullscreenMode(Gdx.graphics.getDisplayMode());
Expand Down Expand Up @@ -216,7 +216,6 @@ public void dispose() {
Flixel.getAudioEngine().dispose();

Flixel.info("Disposing and shutting down scripts...");
Polyverse.forAllScripts(Script::onDispose);

Flixel.Signals.postGameClose.dispatch();
}
Expand All @@ -225,8 +224,12 @@ public String getTitle() {
return title;
}

public int[] getWindowSize() {
return new int[]{(int) size.x, (int) size.y};
public Vector2 getWindowSize() {
return windowSize;
}

public boolean isFocused() {
return isFocused;
}

public Stage getStage() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package me.stringdotjar.flixelgdx.graphics.sprite;

import com.badlogic.gdx.graphics.g2d.Batch;
import me.stringdotjar.flixelgdx.graphics.screen.FlixelScreen;

/** An interface which allows any class that implements it to be added to a {@link FlixelScreen}. */
public interface FlixelObject {
void update(float delta);
void draw(Batch batch);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Rectangle;
Expand Down Expand Up @@ -62,11 +63,11 @@ public FlixelSprite() {
*
* @param delta The amount of time that has passed since the last frame update.
*/
@Override
public void update(float delta) {
if (animations.containsKey(currentAnim)) {
stateTime += delta;
currentFrame =
(TextureAtlas.AtlasRegion) animations.get(currentAnim).getKeyFrame(stateTime, looping);
currentFrame = (TextureAtlas.AtlasRegion) animations.get(currentAnim).getKeyFrame(stateTime, looping);
setRegion(currentFrame);
}
}
Expand Down Expand Up @@ -286,17 +287,14 @@ public void draw(Batch batch) {

// Adjust drawing position by the Sparrow offsets
float drawX = getX() + currentFrame.offsetX;
float drawY =
getY()
+ (currentFrame.originalHeight - currentFrame.getRegionHeight() - currentFrame.offsetY);
float drawY = getY() + (currentFrame.originalHeight - currentFrame.getRegionHeight() - currentFrame.offsetY);

batch.draw(
currentFrame,
drawX,
drawY,
originX - currentFrame.offsetX,
originY
- (currentFrame.originalHeight - currentFrame.getRegionHeight() - currentFrame.offsetY),
originY - (currentFrame.originalHeight - currentFrame.getRegionHeight() - currentFrame.offsetY),
currentFrame.getRegionWidth(),
currentFrame.getRegionHeight(),
getScaleX(),
Expand Down Expand Up @@ -335,6 +333,14 @@ public void reset() {
frames = null;
}

public void changeX(float x) {
setX(getX() + x);
}

public void changeY(float y) {
setY(getY() + y);
}

public Map<String, Animation<TextureRegion>> getAnimations() {
return animations;
}
Expand Down
Loading