21 KiB
LibGDX 1.9.6 → 1.14.1 Upgrade Plan
Overview
This plan upgrades Tick's Tales from libGDX 1.9.6 to 1.14.1, along with updating Clojure, core.async, and Java target version.
Risk Level: Medium - Breaking changes are well-defined and limited to specific methods.
Estimated Effort: 2-4 hours including testing
Background & Research Sources
Before executing this plan, the implementor should understand the scope of changes between libGDX 1.9.6 and 1.14.1.
Primary Research Sources
| Source | URL | Purpose |
|---|---|---|
| libGDX CHANGES file | https://github.com/libgdx/libgdx/raw/master/CHANGES | Official changelog - read versions 1.9.7 through 1.14.1 |
| libGDX Releases | https://github.com/libgdx/libgdx/releases | Release notes with upgrade guidance |
| libGDX Wiki | https://libgdx.com/wiki/ | General documentation |
| LWJGL 3 Changelog | https://www.lwjgl.org/changelog | LWJGL changes bundled with libGDX |
| Clojure Changelog | https://github.com/clojure/clojure/blob/master/Changes.md | Clojure version changes |
| core.async Changelog | https://github.com/clojure/core.async/blob/master/CHANGES.md | core.async version changes |
How to Research Issues
If you encounter unexpected errors during this upgrade:
-
Check the libGDX CHANGES file for your specific error message or class name
# Search for a specific class or method curl -s https://raw.githubusercontent.com/libgdx/libgdx/master/CHANGES | grep -i "YourClassName" -
Search libGDX issues: https://github.com/libgdx/libgdx/issues
- Search for error messages
- Search for class names that fail
-
Check LWJGL issues: https://github.com/LWJGL/lwjgl3/issues
- LWJGL3 is bundled with libGDX; native library issues may originate here
-
Check play-clj keyword translation:
- The macro
key->methodinplay-clj/src/play_clj/utils.clj:80-83converts keywords to Java method calls :set-fullscreen-modebecomes.setFullscreenMode()- If a method was renamed, search for the new name using the keyword pattern
- The macro
Why This Upgrade?
1. Bug Fixes
LibGDX 1.9.6 was released in 2017. The 1.14.1 release includes fixes for:
- Audio device switching issues (automatic in 1.12.1+)
- Borderless fullscreen bugs
- Various native crashes on LWJGL 3
- Memory leaks in frame buffer handling
2. LWJGL 3 Updates
The bundled LWJGL version updates from 3.1.0 to 3.3.3:
- Better hardware compatibility
- Fixed various native crashes
- Improved Wayland support (Linux)
3. Java Compatibility
LibGDX 1.13.0+ is built with Java 17:
- Targeting Java 11 ensures compatibility with modern JVMs
- Your current JDK 25 will work without issues
4. Clojure Updates
Clojure 1.8.0 → 1.11.3 brings:
- Better error messages
- Performance improvements
parse-double,parse-long,parse-booleanutilitiesupdate-keys,update-valsfunctions
Prerequisites
-
Create a branch for this upgrade work
cd /home/noti/dev/tickstales/desktop git checkout -b upgrade/libgdx-1.14.1 -
Verify current build works
lein checkNote any warnings or errors for comparison later.
Part 1: Update play-clj Library
The play-clj library (symlinked at /home/noti/dev/tickstales/play-clj → /home/noti/dev/play-clj) requires modifications before the game can be updated.
1.1 Create Branch in play-clj
- Navigate to play-clj and create a branch
cd /home/noti/dev/play-clj git checkout -b upgrade/libgdx-1.14.1
1.2 Update play-clj Dependencies
File: /home/noti/dev/play-clj/project.clj
Why this change:
- LibGDX must be updated to match the game's version
- Clojure 1.6.0 is ancient (2014); 1.11.3 is the current stable release
- Java 11 target is required for libGDX 1.13.0+ which is built with Java 17
Research if blocked:
-
Check Maven Central for available versions: https://central.sonatype.com/search?q=g:com.badlogicgames.gdx
-
Clojure versions: https://clojure.org/releases/downloads
-
Update libGDX dependencies (approximately lines 6-8):
;; BEFORE [com.badlogicgames.gdx/gdx "1.9.5"] [com.badlogicgames.gdx/gdx-box2d "1.9.5"] [com.badlogicgames.gdx/gdx-bullet "1.9.5"] ;; AFTER [com.badlogicgames.gdx/gdx "1.14.1"] [com.badlogicgames.gdx/gdx-box2d "1.14.1"] [com.badlogicgames.gdx/gdx-bullet "1.14.1"] -
Update Clojure version (approximately line 9):
;; BEFORE [org.clojure/clojure "1.6.0"] ;; AFTER [org.clojure/clojure "1.11.3"] -
Update Java target version in
:javac-options:;; BEFORE :javac-options ["-target" "1.8" "-source" "1.8" "-Xlint:-options"] ;; AFTER :javac-options ["-target" "11" "-source" "11" "-Xlint:-options"] -
Commit this change:
git add project.clj git commit -m "Update libGDX to 1.14.1 and Clojure to 1.11.3"
1.3 Fix InputProcessor.scrolled() Signature Change
File: /home/noti/dev/play-clj/src/play_clj/core_listeners.clj
Why this change:
In libGDX 1.9.12, the InputProcessor.scrolled() method signature changed to support:
- Horizontal scrolling (trackpads, some mice)
- Fractional scroll amounts (high-precision devices)
Before (1.9.6 - 1.9.11):
// InputProcessor interface
boolean scrolled(int amount);
After (1.9.12+):
// InputProcessor interface
boolean scrolled(float amountX, float amountY);
What happens if you don't fix this:
AbstractMethodErrorat runtime when any scroll event occurs- The game will crash when the mouse wheel is used
Research if blocked:
- libGDX CHANGES: Search for "scrolled" or "InputProcessor"
- libGDX PR #6154: https://github.com/libgdx/libgdx/pull/6154
- InputProcessor javadoc: https://libgdx.com/wiki/input/input-handling
Location in code:
The input-processor function creates a reify of the InputProcessor interface. Line 22-23 defines the scrolled method.
- Update the
scrolledmethod in theinput-processorfunction (lines 22-23):;; BEFORE (scrolled [this a] (execute-fn! on-scrolled {:amount a}) ;; AFTER (scrolled [this amountX amountY] (execute-fn! on-scrolled {:amount-x amountX :amount-y amountY})
Impact on game code:
-
Your game's
:on-scrolledhandler inscene.clj:1445is commented out, so this won't immediately affect gameplay -
If you use scrolling in the future, access scroll amounts via
:amount-xand:amount-yinstead of:amount -
Commit this change:
git add src/play_clj/core_listeners.clj git commit -m "Fix scrolled() signature for libGDX 1.9.12+ compatibility"
1.4 Add InputProcessor.touchCancelled() Method
File: /home/noti/dev/play-clj/src/play_clj/core_listeners.clj
Why this change:
In libGDX 1.12.0, a new method was added to the InputProcessor interface:
// Added in libGDX 1.12.0
boolean touchCancelled(int screenX, int screenY, int pointer, int button);
Purpose: This method is called when a touch event is cancelled by the system (e.g., when a dialog appears during a touch, or on mobile when a call comes in). Previously, these situations could leave the game in an inconsistent state.
What happens if you don't fix this:
AbstractMethodErrorat runtime when the game first processes any input- The reify will not implement all interface methods, causing immediate crash on startup
Research if blocked:
- libGDX CHANGES: Search for "touchCancelled"
- libGDX issue #6871: https://github.com/libgdx/libgdx/issues/6871
- libGDX 1.12.0 release notes: https://github.com/libgdx/libgdx/releases/tag/1.12.0
Location in code:
Add this method inside the reify InputProcessor block, after the touchUp method.
- Add the
touchCancelledmethod to theinput-processorfunction (after thetouchUpmethod, around line 33):(touchUp [this sx sy p b] (execute-fn! on-touch-up {:input-x sx :input-y sy :pointer p :button b}) false) ;; ADD THIS METHOD: (touchCancelled [this sx sy p b] false)
Optional enhancement: If you want to handle touch cancellation events:
;; You could add an :on-touch-cancelled handler similar to other input handlers:
(touchCancelled [this sx sy p b]
(execute-fn! on-touch-cancelled {:input-x sx :input-y sy :pointer p :button b})
false)
- Commit this change:
git add src/play_clj/core_listeners.clj git commit -m "Add touchCancelled() method for libGDX 1.12.0+ compatibility"
1.5 Update Documentation (Optional)
File: /home/noti/dev/play-clj/src/play_clj/core.clj
Why this change:
The docstring example for :on-scrolled shows the old :amount key. Updating it prevents confusion for future developers.
-
Update the
:on-scrolleddocstring (lines 206-210) to reflect new keys:;; BEFORE ; the mouse wheel was scrolled :on-scrolled (fn [screen entities] (println (:amount screen)) ; the amount scrolled entities) ;; AFTER ; the mouse wheel was scrolled :on-scrolled (fn [screen entities] (println (:amount-x screen)) ; the horizontal scroll amount (println (:amount-y screen)) ; the vertical scroll amount entities) -
Commit this change (if made):
git add src/play_clj/core.clj git commit -m "Update :on-scrolled documentation for new scroll API"
1.6 Install Updated play-clj
-
Install the updated play-clj library:
cd /home/noti/dev/play-clj lein install -
Verify installation succeeded (should see "Created jar" message)
If installation fails:
-
Check that all dependencies resolve:
lein deps -
Check for Clojure syntax errors:
lein check -
Verify Maven local repository:
ls ~/.m2/repository/play-clj/play-clj/ -
Commit any generated files:
git status # If pom.xml or other files were modified: git add -A git commit -m "Update generated files after lein install"
Part 2: Update Game Project
2.1 Return to Game Directory
- Navigate back to the game:
cd /home/noti/dev/tickstales/desktop
2.2 Update Game Dependencies
File: /home/noti/dev/tickstales/desktop/project.clj
Why this change:
- libGDX must match the version installed in play-clj
- Clojure 1.11.3 is compatible with 1.8.0 code; no source changes required
- core.async 1.6.681 includes bug fixes and performance improvements
- Java 11 target is required for libGDX 1.13.0+
Research if blocked:
-
Clojure compatibility: https://clojure.org/reference/compatibility
-
core.async releases: https://github.com/clojure/core.async/releases
-
Update libGDX dependencies (approximately lines 19-21):
;; BEFORE [com.badlogicgames.gdx/gdx "1.9.6"] [com.badlogicgames.gdx/gdx-backend-lwjgl3 "1.9.6"] [com.badlogicgames.gdx/gdx-platform "1.9.6" :classifier "natives-desktop"] ;; AFTER [com.badlogicgames.gdx/gdx "1.14.1"] [com.badlogicgames.gdx/gdx-backend-lwjgl3 "1.14.1"] [com.badlogicgames.gdx/gdx-platform "1.14.1" :classifier "natives-desktop"] -
Update Clojure version (approximately line 22):
;; BEFORE [org.clojure/clojure "1.8.0"] ;; AFTER [org.clojure/clojure "1.11.3"] -
Update core.async version (approximately line 27):
;; BEFORE [org.clojure/core.async "0.2.385"] ;; AFTER [org.clojure/core.async "1.6.681"] -
Update Java target version in
:javac-options(approximately line 30):;; BEFORE :javac-options ["-target" "1.7" "-source" "1.7" "-Xlint:-options"] ;; AFTER :javac-options ["-target" "11" "-source" "11" "-Xlint:-options"] -
Commit this change:
git add project.clj git commit -m "Update libGDX to 1.14.1, Clojure to 1.11.3, core.async to 1.6.681"
2.3 Fix ScreenUtils.getFrameBufferPixmap() Deprecation
File: /home/noti/dev/tickstales/desktop/src-common/advent/utils.clj
Why this change:
In libGDX 1.9.14, ScreenUtils.getFrameBufferPixmap() was deprecated and replaced with Pixmap.createFromFrameBuffer().
Old API (deprecated):
Pixmap pm = ScreenUtils.getFrameBufferPixmap(x, y, width, height);
New API:
Pixmap pm = Pixmap.createFromFrameBuffer(x, y, width, height);
What happens if you don't fix this:
- The code will still compile (deprecation warning, not error)
- May fail at runtime in future versions when the method is removed
- The new method is more efficient
Research if blocked:
- libGDX CHANGES: Search for "ScreenUtils" or "getFrameBufferPixmap"
- Pixmap javadoc: https://libgdx.com/wiki/graphics/2d/pixmaps
Location in code:
Line 258 in src-common/advent/utils.clj, inside the function that captures screenshots for save files.
-
Find line 258 and update the deprecated call:
;; BEFORE pm (ScreenUtils/getFrameBufferPixmap x y w h) ;; AFTER pm (Pixmap/createFromFrameBuffer x y w h) -
Commit this change:
git add src-common/advent/utils.clj git commit -m "Replace deprecated ScreenUtils/getFrameBufferPixmap with Pixmap/createFromFrameBuffer"
Part 3: Build and Test
3.1 Clean and Compile
-
Clean previous build artifacts:
lein clean -
Compile and check for errors:
lein checkExpected: Compilation should succeed. Some reflection warnings are acceptable.
If compilation fails:
-
"Could not locate play_clj__init.class" - play-clj wasn't installed
cd /home/noti/dev/play-clj && lein install && cd /home/noti/dev/tickstales/desktop -
"AbstractMethodError" - Interface method not implemented
- Check that
touchCancelledwas added tocore_listeners.clj - Check that
scrolledhas the correct signature
- Check that
-
"ClassNotFoundException" for libGDX classes
- Run
lein depsto download dependencies - Check Maven Central for correct artifact names
- Run
-
Java version errors
- Verify you're running JDK 11+:
java -version - Update
:javac-optionsif needed
- Verify you're running JDK 11+:
- If compilation fails, fix errors and commit fixes before proceeding.
3.2 Run Development Build
-
Start the game:
lein run -
Test Checklist:
- Game launches without errors
- Main menu displays correctly
- Mouse cursor changes work
- Click interactions work (left-click on objects)
- Dialogue system works
- Inventory system works
- Save/Load works
- Music plays
- Sound effects play
- Fullscreen/windowed toggle works
- Game exits cleanly
If runtime errors occur:
-
"UnsatisfiedLinkError" - Native library issue
- Check that
gdx-platformwith:classifier "natives-desktop"is in dependencies - LWJGL natives should auto-extract
- Check that
-
"NoClassDefFoundError" - Missing class at runtime
- Check for deprecated/removed classes in libGDX CHANGES
- Ensure all dependencies have matching versions
-
Audio issues
- LWJGL 3.3.x has improved audio device handling
- Check system audio configuration
- If any tests fail, fix issues and commit fixes before proceeding.
3.3 Build Release Uberjar
-
Build the standalone jar:
LEIN_SNAPSHOTS_IN_RELEASE=true lein with-profile steam do clean, compile, uberjar -
Verify jar was created:
ls -la target/advent-standalone.jar -
Test the uberjar:
java -jar target/advent-standalone.jar -
Test Checklist (uberjar):
- Game launches from uberjar
- Basic gameplay works
- Steam integration works (if applicable)
Part 4: Packaging (Optional)
If you need to create distributable packages:
4.1 Update packr Configuration (If Needed)
The packr configuration files reference JDK 8 JREs in the jvms/ directory. These should continue to work since the bytecode targets Java 11.
Why Java 8 JREs still work:
- We compile with
-target 11 -source 11 - Java bytecode is backwards compatible within major versions
- No Java 11+ specific APIs are used
Research if updating JREs:
-
Azul Zulu JREs: https://azul.com/downloads/?package=jre
-
packr documentation: https://github.com/libgdx/packr
-
If updating to Java 17+ runtime for distribution:
- Download Azul Zulu JDK 17+ JREs
- Place in
jvms/directory - Update
build-*.jsonfiles to reference new JRE paths
4.2 Test packr Build
-
Build Linux package:
java -jar packr.jar build-linux-64.json -
Test the built executable:
./target/linux/amd64/"Tick's Tales"
Summary of Changes
play-clj Changes (3 files)
| File | Change | Reason |
|---|---|---|
project.clj |
libGDX 1.9.5 → 1.14.1 | Match game version, get bug fixes |
project.clj |
Clojure 1.6.0 → 1.11.3 | Modern version, better error messages |
project.clj |
Java target 1.8 → 11 | Required for libGDX 1.13.0+ |
src/play_clj/core_listeners.clj |
Fix scrolled signature |
API changed in 1.9.12 |
src/play_clj/core_listeners.clj |
Add touchCancelled method |
New method in 1.12.0 |
src/play_clj/core.clj |
Update :on-scrolled docstring |
Reflect new API |
Game Changes (2 files)
| File | Change | Reason |
|---|---|---|
project.clj |
libGDX 1.9.6 → 1.14.1 | Match play-clj version |
project.clj |
Clojure 1.8.0 → 1.11.3 | Match play-clj version |
project.clj |
core.async 0.2.385 → 1.6.681 | Bug fixes, performance |
project.clj |
Java target 1.7 → 11 | Required for libGDX 1.13.0+ |
src-common/advent/utils.clj |
ScreenUtils/getFrameBufferPixmap → Pixmap/createFromFrameBuffer |
Deprecated in 1.9.14 |
What Does NOT Need Changes
Based on analysis, the following do NOT require modifications:
Keyword-Based Method Calls (All Compatible)
All keyword-based method calls in both play-clj and the game remain compatible. The play-clj macro system translates keywords to Java method calls at compile time:
:set-fullscreen-mode → .setFullscreenMode()
:get-key-frame-index → .getKeyFrameIndex()
None of the methods used by your game were renamed between 1.9.6 and 1.14.1.
Verified compatible keywords:
(graphics! :set-cursor ...)✓(music! ... :set-volume ...)✓(sound! ... :set-volume ...)✓(slider! ... :get-value)✓(label! ... :set-text ...)✓(texture! ... :get-region-width)✓(animation! ... :get-key-frame-index ...)✓(pixmap! ... :set-filter ...)✓(particle-effect! ... :reset/:start)✓
Features Not Used by Game
These libGDX features changed but your game doesn't use them:
- Box2D physics (API changes)
- Bullet 3D physics (API changes)
- TiledMap loading (new loaders)
- Pools/ReflectionPool (deprecated)
- 3D rendering (ModelBatch changes)
- JsonValue parsing (case sensitivity)
Scalingenum (became object)
Rollback Plan
If issues arise that cannot be resolved:
# Rollback play-clj
cd /home/noti/dev/play-clj
git checkout .
lein install
# Rollback game
cd /home/noti/dev/tickstales/desktop
git checkout .
lein clean
Completion
-
Final commit with all changes:
git add -A git commit -m "Complete libGDX 1.14.1 upgrade" -
Push branches (when ready):
# play-clj cd /home/noti/dev/play-clj git push origin upgrade/libgdx-1.14.1 # game cd /home/noti/dev/tickstales/desktop git push origin upgrade/libgdx-1.14.1
References
Official Documentation
- libGDX CHANGES - Complete changelog
- libGDX Wiki - General documentation
- LWJGL 3 Documentation - LWJGL3 guide
Release Notes
- libGDX 1.14.1 Release
- libGDX 1.14.0 Release - Major changes
- libGDX 1.13.0 Release - Java 17 build
- libGDX 1.12.0 Release -
touchCancelledadded - libGDX 1.9.12 Release -
scrolledsignature changed - libGDX 1.9.14 Release -
ScreenUtils.getFrameBufferPixmapdeprecated
Related Projects
- Clojure Changelog
- core.async Changelog
- packr - JRE bundling tool