Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
f1b47b2
Completely rework screens and fix a bug with tweens
stringdotjar Jan 12, 2026
84a4d33
Add animation functionality to FunkinSprite class
stringdotjar Jan 14, 2026
e280a4c
Rework the audio system to use something better
stringdotjar Jan 15, 2026
25a6012
Too tired to make a real title sob
stringdotjar Jan 16, 2026
5d257b9
Fix offset bugs, add multiple optimizations and add fullscreen
stringdotjar Jan 18, 2026
b9c4967
Fix many null errors with tweening
stringdotjar Jan 19, 2026
1f93696
Merge pull request #9 from stringdotjar/flixelgdx
stringdotjar Jan 19, 2026
9b76019
Reformat files to match new rules added
stringdotjar Jan 20, 2026
574a511
Moved everything into its own folder (especially FlixelGDX)
stringdotjar Jan 22, 2026
addc4f4
Add modding SDK task for future autocomplete with mod development
stringdotjar Jan 22, 2026
0f72421
Merge pull request #10 from stringdotjar/flixelgdx
stringdotjar Jan 22, 2026
95052c3
Rename global package and add Android build CI task
stringdotjar Jan 24, 2026
50b97c2
Merge pull request #11 from stringdotjar/flixelgdx
stringdotjar Jan 24, 2026
92b1cea
Merge branch 'develop' into polyverse
stringdotjar Jan 24, 2026
650ba47
Update build.gradle
stringdotjar Jan 24, 2026
4df1850
Update build.gradle
stringdotjar Jan 24, 2026
8d46c30
Dude please work 🙏
stringdotjar Jan 24, 2026
e967e51
I want to go to bed bro please 😭
stringdotjar Jan 24, 2026
f6a1572
Merge pull request #12 from stringdotjar/polyverse
stringdotjar Jan 24, 2026
24b5578
Completely move FlixelGDX and Polyverse into separate modules
stringdotjar Jan 27, 2026
4fd8ee4
Merge branch 'develop' into project-refactor
stringdotjar Jan 27, 2026
1e10427
Update FlixelObject.java
stringdotjar Jan 27, 2026
04ad748
Merge pull request #13 from stringdotjar/project-refactor
stringdotjar Jan 27, 2026
ceb0c30
Update notice formatting in README.md
stringdotjar Jan 27, 2026
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
12 changes: 8 additions & 4 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,21 @@ trim_trailing_whitespace = true
# 2-space indentation (Google Style Guide Section 4.2)
indent_style = space

# Limit line length to 100 characters (Section 4.4)
max_line_length = 100
# Even though Google Style Guide Section 2.3 recommends 100 characters,
# many modern IDEs default to 120 characters, so we follow that convention.
max_line_length = 120

# Standard Java formatting rules
# Standard Java formatting rules.
ij_java_use_single_class_imports = true
ij_java_insert_inner_class_imports = false
ij_java_class_count_to_use_import_on_demand = 999
ij_java_names_count_to_use_import_on_demand = 999
ij_java_packages_to_use_import_on_demand = unset
ij_java_blank_lines_before_class_end = 1
ij_java_blank_lines_before_class_end = 0
ij_java_blank_lines_after_class_header = 1
ij_java_doc_align_param_comments = false
ij_java_doc_do_not_wrap_if_one_line = true
ij_any_keep_simple_blocks_in_one_line = true

# Block formatting (Section 4.1.2)
ij_java_class_brace_style = end_of_line
Expand Down
2 changes: 1 addition & 1 deletion .github/FUNDING.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: stringfromjava
ko_fi: stringdotjar
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
Expand Down
39 changes: 31 additions & 8 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,48 @@ jobs:
os: [windows-latest, macos-latest, ubuntu-latest]

runs-on: ${{ matrix.os }}

steps:
- uses: actions/checkout@v4
# LibGDX typically uses Java 11 or newer

# LibGDX typically uses Java 11 or newer.
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
# Cache Gradle dependencies to speed up subsequent runs
# Cache Gradle dependencies to speed up subsequent runs.
cache: 'gradle'

# Grant execute permission for gradlew (necessary for macOS and Linux)
# Grant execute permission for gradlew (necessary for macOS and Linux).
- name: Grant execute permission for gradlew
run: chmod +x gradlew
# Use an 'if' condition to only run this on non-Windows OS
# Use an 'if' condition to only run this on non-Windows OS.
if: startsWith(runner.os, 'macOS') || startsWith(runner.os, 'Linux')
# This task compiles all modules (core, desktop, etc.)

# This task compiles all modules (core, desktop, etc.).
- name: Build with Gradle
run: ./gradlew build

build-android:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

# LibGDX typically uses Java 11 or newer.
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
# Cache Gradle dependencies to speed up subsequent runs.
cache: 'gradle'

# Grant execute permission for gradlew.
- name: Grant execute permission for gradlew
run: chmod +x gradlew

# Build Android module.
- name: Build Android with Gradle
run: ./gradlew android:build
7 changes: 4 additions & 3 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 Expand Up @@ -155,8 +156,8 @@ Thumbs.db
*~
*.*#
*#*#
/.kotlin/
/assets/assets.txt
/assets/sdk/

## Special cases:

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
> [!NOTE]
> 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/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
tools:ignore="UnusedAttribute"
android:theme="@style/GdxTheme">
<activity
android:name="me.stringfromjava.funkin.android.AndroidLauncher"
android:name="me.stringdotjar.funkin.android.AndroidLauncher"
android:label="@string/app_name"
android:screenOrientation="landscape"
android:configChanges="keyboard|keyboardHidden|navigation|orientation|screenSize|screenLayout"
Expand Down
19 changes: 11 additions & 8 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ apply plugin: 'com.android.application'


android {
namespace "me.stringfromjava.funkin"
compileSdk 35
namespace "me.stringdotjar.funkin"
compileSdk 36
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
Expand All @@ -30,8 +30,8 @@ android {
}
}
defaultConfig {
applicationId 'me.stringfromjava.funkin'
minSdkVersion 26
applicationId 'me.stringdotjar.funkin'
minSdkVersion 34
targetSdkVersion 35
versionCode 1
versionName "1.0"
Expand All @@ -47,7 +47,7 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
minifyEnabled true
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
Expand All @@ -63,8 +63,12 @@ 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"
api "games.rednblack.miniaudio:gdx-miniaudio-platform:$miniaudioVersion:natives-x86"
api "games.rednblack.miniaudio:gdx-miniaudio-platform:$miniaudioVersion:natives-x86_64"
natives "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-arm64-v8a"
natives "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-armeabi-v7a"
natives "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-x86"
Expand All @@ -73,7 +77,6 @@ dependencies {
natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-armeabi-v7a"
natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-x86"
natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-x86_64"

}

// Called every time gradle gets executed, takes the native dependencies of
Expand Down Expand Up @@ -126,7 +129,7 @@ tasks.register('run', Exec) {
}

def adb = path + "/platform-tools/adb"
commandLine "$adb", 'shell', 'am', 'start', '-n', 'me.stringfromjava.funkin/me.stringfromjava.funkin.android.AndroidLauncher'
commandLine "$adb", 'shell', 'am', 'start', '-n', 'me.stringdotjar.funkin/me.stringdotjar.funkin.android.AndroidLauncher'
}

eclipse.project.name = appName + "-android"
17 changes: 17 additions & 0 deletions android/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,17 @@
-dontwarn android.support.**
-dontwarn com.badlogic.gdx.backends.android.AndroidFragmentApplication

# Ignore missing AWT classes (desktop-only, not needed on Android)
-dontwarn java.awt.**
-dontwarn javax.swing.**

# Ignore Java 9+ classes that don't exist on Android
-dontwarn java.lang.Runtime$Version
-dontwarn java.lang.reflect.InaccessibleObjectException

# Ignore all Groovy warnings (Gradle's internal dependency)
-dontwarn org.codehaus.groovy.**

# Needed by the gdx-controllers official extension.
-keep class com.badlogic.gdx.controllers.android.AndroidControllers

Expand All @@ -39,6 +50,10 @@
float reportRayFixture(long, float, float, float, float, float);
}

# Don't obfuscate code at all, since it's open source and we want people to mess with the game's
# internals and reverse engineer the code as much as possible.
-dontobfuscate

# Ignore missing Java Beans classes (Android doesn't have java.beans, Groovy handles this internally)
-dontwarn java.beans.**

Expand All @@ -61,6 +76,8 @@
# You will probably need this line in most cases:
-keep public class com.badlogic.gdx.graphics.Color { *; }

-keep class me.stringdotjar.** { *; }

# These two lines are used with mapping files; see https://developer.android.com/build/shrink-code#retracing
-keepattributes LineNumberTable,SourceFile
-renamesourcefileattribute SourceFile
Original file line number Diff line number Diff line change
@@ -1,18 +1,26 @@
package me.stringfromjava.funkin.android;
package me.stringdotjar.funkin.android;

import android.os.Bundle;
import com.badlogic.gdx.backends.android.AndroidApplication;
import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;
import me.stringfromjava.funkin.FunkinGame;
import me.stringdotjar.funkin.FunkinGame;
import me.stringdotjar.funkin.InitScreen;
import me.stringdotjar.funkin.util.FunkinConstants;

/** Launches the Android application. */
public class AndroidLauncher extends AndroidApplication {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FunkinGame game = new FunkinGame(
FunkinConstants.WINDOW_TITLE,
FunkinConstants.WINDOW_WIDTH,
FunkinConstants.WINDOW_HEIGHT,
new InitScreen()
);
AndroidApplicationConfiguration configuration = new AndroidApplicationConfiguration();
configuration.useImmersiveMode = true; // Recommended, but not required.
initialize(new FunkinGame(), configuration);
initialize(game, configuration);
}
}
25 changes: 12 additions & 13 deletions assets/another_test.groovy
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.Input
import com.badlogic.gdx.graphics.Texture
import com.badlogic.gdx.graphics.g2d.Sprite
import me.stringfromjava.funkin.Funkin
import me.stringfromjava.funkin.backend.system.Paths
import me.stringfromjava.funkin.polyverse.script.type.Script
import me.stringfromjava.funkin.util.Constants
import me.stringdotjar.flixelgdx.Flixel
import me.stringdotjar.flixelgdx.backend.FlixelPaths
import me.stringdotjar.flixelgdx.graphics.sprite.FlixelSprite
import me.stringdotjar.funkin.util.FunkinConstants
import me.stringdotjar.polyverse.script.type.Script

class AnotherTestClass extends Script {

Expand All @@ -17,30 +16,30 @@ class AnotherTestClass extends Script {
void onCreate() {
super.onCreate()

Funkin.info("AnotherTestClass", "Script has been created!")
Flixel.info("AnotherTestClass", "Script has been created!")

Funkin.playMusic("songs/bopeebo/Inst.ogg")
Flixel.playMusic("songs/bopeebo/Inst.ogg")
}

@Override
void onRender(float delta) {
super.onRender(delta)

if (Gdx.input.isKeyJustPressed(Input.Keys.SPACE)) {
var sprite = new Sprite(new Texture(Paths.image("pauseAlt/bfLol")))
var randomPosX = new Random().nextInt(Constants.Display.WINDOW_WIDTH)
var randomPosY = new Random().nextInt(Constants.Display.WINDOW_HEIGHT)
var sprite = new FlixelSprite().loadGraphic(FlixelPaths.sharedImageAsset("pauseAlt/bfLol"))
var randomPosX = new Random().nextInt(FunkinConstants.WINDOW_WIDTH)
var randomPosY = new Random().nextInt(FunkinConstants.WINDOW_HEIGHT)

sprite.setPosition(randomPosX, randomPosY)

Funkin.screen.add(sprite)
Flixel.screen.add(sprite)
}
}

@Override
void onDispose() {
super.onDispose()

Funkin.info("AnotherTestClass", "Script has been disposed!")
Flixel.info("AnotherTestClass", "Script has been disposed!")
}
}
Loading