Slime Sprite  •  App Comparison  •  10/01/2026
TNT — Processing Cross Training  •  Sergio’s Slime

animated slime Slime Sprite:
Three Languages, One Algorithm

The same animated sprite — identical movement, identical breathing trick, identical boundary clamping — in JavaScript (p5.js), Java Processing, and Python Processing. Five concepts that cross language boundaries.

Key Cross-Training Ideas

Five Concepts — Three Languages

These five ideas appear in all three sketches. The concept is the same in every language; only the mechanism the language provides to express it differs. Find each one in the code panels below.

⌨️
Keyboard Input — Three Strategies

All three versions poll key state every frame inside draw(). The mechanism each language provides differs significantly.

JS: keyIsDown(68) — built-in polling, zero setup Java: heldKeys.contains(KEY_D) — HashSet updated by events Python: KEY_D in held_keys — set() updated by events

Java and Python fire keyPressed() / keyReleased() events and maintain a snapshot set. The in operator in Python replaces contains() in Java. Python uses discard() instead of remove() so a missed release event never crashes.

keyIsDown() HashSet<Integer> set()
🎯
Vectors — Library vs Plain Floats

JS and Java use PVector objects with .x and .y fields and an add() method. Python uses plain floats — the library support is absent, but the math is identical.

JS/Java: pos.add(vel) → pos.x += vel.x; pos.y += vel.y Python: pos_x += vel_x; pos_y += vel_y (explicit)

The braking mechanism is the same in all three: zero the velocity at the end of every frame so the slime stops the instant a key is released. The concept travels. The container is language-specific.

createVector() new PVector() plain floats
🖼️
Sprite-Sheet Crop — A Subtle API Difference

The 9-parameter image() is NOT identical across languages. The destination parameters are the same; the source region parameters differ.

p5.js: sx, sy, sw, sh ← offset + WIDTH/HEIGHT Java/Python: u1, v1, u2, v2 ← top-left + BOTTOM-RIGHT

The fix is one extra line in Java and Python: srcX2 = srcX + idle.height computes the bottom-right x. Frame 0 (srcX=0) silently produces the same result either way, so this bug only appears when the second frame is displayed — exactly the kind of off-by-one that is very hard to spot.

sw = width u2 = right corner u2 = right corner
🏷️
Constants — Enforced vs Conventional

Every magic number in the sketch is replaced with a named constant. The three languages express “this value should not change” with different mechanisms:

JS: const PLAYER_SIZE = 50 Java: final float PLAYER_SIZE = 50; Python: PLAYER_SIZE = 50.0 # ALL_CAPS convention

Java enforces immutability at compile time — the compiler rejects any assignment to a final field. JavaScript’s const prevents reassignment in the same scope. Python uses UPPER_CASE as a signal to human readers; nothing prevents reassignment in the runtime.

const final ALL_CAPS
📦
The Player Class — Same Concept, Three Syntaxes

All three versions define a Player class with position, velocity, a frame counter, and two methods: drawPlayer() and update(). The lifecycle is identical: constructed once in setup(), updated every frame in draw().

JS: class Player { constructor() { this.pos = ... } } Java: class Player { PVector pos, vel; Player(...){} } Python: class Player: def __init__(self): self.pos_x = ...

Java and Python are single-file sketches (the class lives at the bottom). The JavaScript version separates the class into a companion Player.js file — a design choice, not a requirement.

Player.js (separate) bottom of .pde bottom of .py
💨
The Breathing Trick — Identical in All Three

The two-frame animation is the central teaching concept of this project. The algorithm is completely identical across all three languages.

ANIM_SPEED = 0.05 → 40 steps to cycle ≈ 0.67 s floor(frame) / (int)frame / int(frame) srcX = idle.height * frameIndex (all three)

The frame counter advances every call to update() regardless of whether a key is pressed, so the slime is always alive at rest. The floor/truncate operation converts the smooth counter to a 0-or-1 frame index that selects which half of the sprite sheet to crop. This is the algorithm. It does not depend on the language.

floor() (int) cast int()

All Three Sketches, Side by Side

Yellow paper = JavaScript (sketch.js)  •  Blue paper = Java (.pde, single file incl. Player class)  •  Green paper = Python (.py, single file incl. Player class). Each panel scrolls independently. Scroll to the bottom to see the Player class syntax in each language.

JavaScript sketch.js + Player.js (combined)
    Java sergiosUpdatedSlimeJavaSketch.pde
      Python sergiosUpdatedSlimePythonSketch.py

        What’s the Same — and What’s Different

        • JS / Java / Python: velocity math, braking, boundary checking, and the breathing trick counter are word-for-word identical in logic across all three languages.
        • constrain(): same function name and semantics in all three — constrain(vel.x, -SPEED, SPEED)
        • pushMatrix() / popMatrix() + scale(-1,1): the left-facing mirror flip technique is identical in Java and Python; JS uses push() / pop() (which also saves style — a minor behavioral difference documented in the chat log).
        • colorMode(HSB, 360, 100, 100, 100): identical in all three. imageMode(CENTER): identical in all three.
        • Java only: import java.util.HashSet required for the held-keys set. new PVector() for position/velocity.
        • Python only: global idle, back, bg, player required in setup() when reassigning module-level variables. Plain floats pos_x/pos_y/vel_x/vel_y replace PVector.
        • The 9-param image() surprise: p5.js uses offset + size for source crop; Java and Python use top-left + bottom-right corner. See Session 9 in the chat log for the full explanation.