diff --git a/flixelgdx/src/main/java/me/stringdotjar/flixelgdx/FlixelGame.java b/flixelgdx/src/main/java/me/stringdotjar/flixelgdx/FlixelGame.java index 5630cd8..0d30fc5 100644 --- a/flixelgdx/src/main/java/me/stringdotjar/flixelgdx/FlixelGame.java +++ b/flixelgdx/src/main/java/me/stringdotjar/flixelgdx/FlixelGame.java @@ -58,6 +58,9 @@ public abstract class FlixelGame implements ApplicationListener { /** Where all the global viewports are stored. */ protected SnapshotArray viewports; + /** Is the game currently closing? */ + private boolean isClosing = false; + /** * Creates a new game instance with the specified title, window width/height, and initial screen. This configures * the game's core parts, such as the viewport, stage, etc. @@ -257,6 +260,12 @@ public void toggleFullscreen() { @Override public void dispose() { + if (isClosing) { + Flixel.warn("Game is already closing. Skipping dispose..."); + return; + } + isClosing = true; + Flixel.warn("SHUTTING DOWN GAME AND DISPOSING ALL RESOURCES."); Flixel.Signals.preGameClose.dispatch(); diff --git a/flixelgdx/src/main/java/me/stringdotjar/flixelgdx/graphics/FlixelState.java b/flixelgdx/src/main/java/me/stringdotjar/flixelgdx/graphics/FlixelState.java index d184750..dde2799 100644 --- a/flixelgdx/src/main/java/me/stringdotjar/flixelgdx/graphics/FlixelState.java +++ b/flixelgdx/src/main/java/me/stringdotjar/flixelgdx/graphics/FlixelState.java @@ -49,7 +49,7 @@ public void update(float delta) { } /** - * Draws its members onto the screen. + * Draws {@code this} state's members onto the screen. * * @param batch The batch that's used to draw {@code this} state's members. */ @@ -71,8 +71,26 @@ public void resume() {} @Override public void hide() {} + /** + * Disposes {@code this} state and all of its members. Called automatically when {@link + * me.stringdotjar.flixelgdx.Flixel#switchState(FlixelState)} is used, so that sprites and other + * {@link FlixelObject}s release its resources. + */ @Override - public void dispose() {} + public void dispose() { + if (members == null) { + return; + } + Object[] items = members.begin(); + for (int i = 0, n = members.size; i < n; i++) { + FlixelObject obj = (FlixelObject) items[i]; + if (obj != null) { + obj.destroy(); + } + } + members.end(); + members.clear(); + } /** * Adds a new sprite to {@code this} screen. If it is {@code null}, it will not be added and diff --git a/flixelgdx/src/main/java/me/stringdotjar/flixelgdx/graphics/sprite/FlixelSprite.java b/flixelgdx/src/main/java/me/stringdotjar/flixelgdx/graphics/sprite/FlixelSprite.java index 30b5946..5f5a58a 100644 --- a/flixelgdx/src/main/java/me/stringdotjar/flixelgdx/graphics/sprite/FlixelSprite.java +++ b/flixelgdx/src/main/java/me/stringdotjar/flixelgdx/graphics/sprite/FlixelSprite.java @@ -7,6 +7,7 @@ import com.badlogic.gdx.graphics.g2d.Sprite; import com.badlogic.gdx.graphics.g2d.TextureAtlas; import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.graphics.g2d.TextureAtlas.AtlasRegion; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Pool; @@ -147,7 +148,7 @@ public FlixelSprite loadSparrowFrames(FileHandle texture, FileHandle xmlFile) { public FlixelSprite loadSparrowFrames(Texture texture, XmlReader.Element xmlFile) { // We store regions in a list so we can filter them by prefix later. // TextureAtlas.AtlasRegion is used because it supports offsets. - atlasRegions = new Array<>(); + atlasRegions = new Array<>(AtlasRegion.class); for (XmlReader.Element subTexture : xmlFile.getChildrenByName("SubTexture")) { String name = subTexture.getAttribute("name"); @@ -325,23 +326,37 @@ public void reset() { stateTime = 0; currentAnim = null; looping = true; - texture.dispose(); - texture = null; - currentFrame.getTexture().dispose(); - currentFrame = null; - for (int i = atlasRegions.size; i >= 0; i--) { - var region = atlasRegions.items[i]; - region.getTexture().dispose(); + if (texture != null) { + texture.dispose(); + texture = null; } - atlasRegions.setSize(0); - atlasRegions = null; - for (int i = frames.length - 1; i >= 0; i--) { - var frame = frames[i]; - for (TextureRegion region : frame) { - region.getTexture().dispose(); + if (currentFrame != null) { + currentFrame.getTexture().dispose(); + currentFrame = null; + } + if (atlasRegions != null) { + for (int i = atlasRegions.size - 1; i >= 0; i--) { + var region = atlasRegions.items[i]; + if (region != null) { + region.getTexture().dispose(); + } + } + atlasRegions.setSize(0); + atlasRegions = null; + } + if (frames != null) { + for (int i = frames.length - 1; i >= 0; i--) { + var frame = frames[i]; + if (frame != null) { + for (TextureRegion region : frame) { + if (region != null) { + region.getTexture().dispose(); + } + } + } } + frames = null; } - frames = null; } public void changeX(float x) { @@ -352,6 +367,10 @@ public void changeY(float y) { setY(getY() + y); } + public void changeRotation(float rotation) { + setRotation(getRotation() + rotation); + } + public Map> getAnimations() { return animations; } diff --git a/flixelgdx/src/main/java/me/stringdotjar/flixelgdx/group/FlixelGroup.java b/flixelgdx/src/main/java/me/stringdotjar/flixelgdx/group/FlixelGroup.java index 40eadec..1aac9ab 100644 --- a/flixelgdx/src/main/java/me/stringdotjar/flixelgdx/group/FlixelGroup.java +++ b/flixelgdx/src/main/java/me/stringdotjar/flixelgdx/group/FlixelGroup.java @@ -1,21 +1,24 @@ package me.stringdotjar.flixelgdx.group; +import com.badlogic.gdx.graphics.g2d.Batch; import com.badlogic.gdx.utils.SnapshotArray; +import me.stringdotjar.flixelgdx.graphics.FlixelObject; + import java.util.function.Consumer; /** * Base class for creating groups with a list of members inside of it. */ -public abstract class FlixelGroup implements FlixelGroupable { +public abstract class FlixelGroup implements FlixelGroupable, FlixelObject { /** * The list of members that {@code this} group contains. */ - protected SnapshotArray members; + protected SnapshotArray members; public FlixelGroup() { - members = new SnapshotArray<>(); + members = new SnapshotArray<>(FlixelObject.class); } @Override @@ -23,30 +26,64 @@ public void add(T member) { members.add(member); } + @Override + public void update(float elapsed) { + FlixelObject[] items = members.begin(); + for (int i = 0, n = members.size; i < n; i++) { + FlixelObject member = items[i]; + if (member == null) { + continue; + } + member.update(elapsed); + } + members.end(); + } + + @Override + public void draw(Batch batch) { + FlixelObject[] items = members.begin(); + for (int i = 0, n = members.size; i < n; i++) { + FlixelObject member = items[i]; + if (member == null) { + continue; + } + member.draw(batch); + } + members.end(); + } + @Override public void remove(T member) { members.removeValue(member, true); } @Override - public void clear() { + public void destroy() { + members.forEach(FlixelObject::destroy); members.clear(); } @Override - public void forEachMember(Consumer callback) { - for (T member : members.begin()) { + public void clear() { + members.clear(); + } + + public void forEachMember(Consumer callback) { + FlixelObject[] items = members.begin(); + for (int i = 0, n = members.size; i < n; i++) { + FlixelObject member = items[i]; if (member == null) { continue; } callback.accept(member); } + members.end(); } public void forEachMemberType(Class type, Consumer callback) { - T[] items = members.begin(); + FlixelObject[] items = members.begin(); for (int i = 0, n = members.size; i < n; i++) { - T member = items[i]; + FlixelObject member = items[i]; if (type.isInstance(member)) { callback.accept(type.cast(member)); } @@ -54,7 +91,7 @@ public void forEachMemberType(Class type, Consumer callback) { members.end(); } - public SnapshotArray getMembers() { + public SnapshotArray getMembers() { return members; } } diff --git a/flixelgdx/src/main/java/me/stringdotjar/flixelgdx/group/FlixelGroupable.java b/flixelgdx/src/main/java/me/stringdotjar/flixelgdx/group/FlixelGroupable.java index c464452..b6340a0 100644 --- a/flixelgdx/src/main/java/me/stringdotjar/flixelgdx/group/FlixelGroupable.java +++ b/flixelgdx/src/main/java/me/stringdotjar/flixelgdx/group/FlixelGroupable.java @@ -1,13 +1,10 @@ package me.stringdotjar.flixelgdx.group; -import java.util.function.Consumer; - /** * Interface for creating new groups with members inside of them. */ -public interface FlixelGroupable { - void add(T member); - void remove(T member); +public interface FlixelGroupable { + void add(FlixelObject member); + void remove(FlixelObject member); void clear(); - void forEachMember(Consumer callback); } diff --git a/flixelgdx/src/main/java/me/stringdotjar/flixelgdx/group/FlixelSpriteGroup.java b/flixelgdx/src/main/java/me/stringdotjar/flixelgdx/group/FlixelSpriteGroup.java new file mode 100644 index 0000000..324eb5a --- /dev/null +++ b/flixelgdx/src/main/java/me/stringdotjar/flixelgdx/group/FlixelSpriteGroup.java @@ -0,0 +1,555 @@ +package me.stringdotjar.flixelgdx.group; + +import com.badlogic.gdx.math.MathUtils; +import me.stringdotjar.flixelgdx.graphics.FlixelObject; +import me.stringdotjar.flixelgdx.graphics.sprite.FlixelSprite; + +import java.util.Comparator; +import java.util.Random; +import java.util.function.Consumer; + +/** + * A group of sprites that can be used to group and manage multiple sprites at once. + *

+ * Setting the group's position ({@link #setX}, {@link #setY}, {@link #setPosition}) moves all + * member sprites by the same delta, mirroring how HaxeFlixel propagates position changes + * (except in {@link RotationMode#WHEEL} mode where positions are set absolutely each frame). + * Sprites added to the group are automatically offset by the group's current position. + *

+ * Rotation behaviour is controlled by {@link #rotationMode}: + *

    + *
  • {@link RotationMode#INDIVIDUAL} (default) – {@link #setRotation}/{@link #changeRotation} + * apply the delta to each sprite's own rotation; no positional changes.
  • + *
  • {@link RotationMode#WHEEL} – sprites are arranged radially around the center + * like a wheel, repositioned absolutely each frame in {@link #update(float)}.
  • + *
  • {@link RotationMode#ORBIT} – sprites orbit around the group origin as a rigid body + * (like a rotating camera/TV screen); both position and individual rotation are adjusted + * by the delta.
  • + *
+ */ +public class FlixelSpriteGroup extends FlixelGroup { + + /** + * Maximum number of members allowed. When {@code 0}, the group can grow without limit (default). + * When {@code > 0}, {@link #add(FlixelSprite)} will not add if at capacity. + */ + private int maxSize = 0; + + /** + * The X position of the group. When changed, all member sprites are moved by the delta + * (unless {@link #rotationMode} is {@link RotationMode#WHEEL}, in which case positions are + * set absolutely each frame). + */ + private float x; + + /** + * The Y position of the group. When changed, all member sprites are moved by the delta + * (unless {@link #rotationMode} is {@link RotationMode#WHEEL}, in which case positions are + * set absolutely each frame). + */ + private float y; + + /** + * The current rotation mode. See {@link RotationMode} for details. + */ + private RotationMode rotationMode = RotationMode.INDIVIDUAL; + + /** + * Distance of each sprite from the center when {@link #rotationMode} is + * {@link RotationMode#WHEEL}. + */ + private float rotationRadius = 100f; + + /** + * The group's rotation in degrees. How this value is used depends on {@link #rotationMode}: + *
    + *
  • {@link RotationMode#INDIVIDUAL} – delta is applied to each sprite's own rotation.
  • + *
  • {@link RotationMode#WHEEL} – base angle for the radial layout; sprite {@code i} + * gets angle {@code rotation + (360 / size) * i}.
  • + *
  • {@link RotationMode#ORBIT} – delta rotates all sprites around the group origin.
  • + *
+ */ + private float rotation; + + private static final Random RANDOM = new Random(); + + /** + * Creates a new FlixelSpriteGroup with default parameters. + */ + public FlixelSpriteGroup() { + this(0, 100f, 0f); + } + + /** + * Creates a new FlixelSpriteGroup with the given max size. + * + * @param maxSize Maximum members allowed; 0 for unlimited. + */ + public FlixelSpriteGroup(int maxSize) { + this(maxSize, 100f, 0f); + } + + /** + * Creates a new FlixelSpriteGroup with the given parameters. + * + * @param maxSize Maximum members allowed; 0 for unlimited. + * @param rotationRadius Distance of each sprite from the center when in {@link RotationMode#WHEEL}. + * @param rotation Initial rotation in degrees. + */ + public FlixelSpriteGroup(int maxSize, float rotationRadius, float rotation) { + super(); + this.maxSize = Math.max(0, maxSize); + this.rotationRadius = rotationRadius; + this.rotation = rotation; + } + + public float getX() { + return x; + } + + /** + * Sets the group's X position. Every member sprite is moved by the delta ({@code newX - oldX}), + * unless the rotation mode is {@link RotationMode#WHEEL} (positions are set absolutely each frame). + */ + public void setX(float x) { + float dx = x - this.x; + this.x = x; + + if (rotationMode != RotationMode.WHEEL) { + transformMembersX(dx); + } + } + + /** + * Adds the given amount to the group's X position. Equivalent to {@code setX(getX() + x)}. + */ + public void changeX(float x) { + setX(this.x + x); + } + + public float getY() { + return y; + } + + /** + * Sets the group's Y position. Every member sprite is moved by the delta ({@code newY - oldY}), + * unless the rotation mode is {@link RotationMode#WHEEL} (positions are set absolutely each frame). + */ + public void setY(float y) { + float dy = y - this.y; + this.y = y; + + if (rotationMode != RotationMode.WHEEL) { + transformMembersY(dy); + } + } + + /** + * Adds the given amount to the group's Y position. Equivalent to {@code setY(getY() + y)}. + */ + public void changeY(float y) { + setY(this.y + y); + } + + /** + * Sets both X and Y in a single call, applying the deltas to all members in one pass + * to avoid iterating twice. + */ + public void setPosition(float x, float y) { + float dx = x - this.x; + float dy = y - this.y; + this.x = x; + this.y = y; + + if (rotationMode != RotationMode.WHEEL) { + transformMembersPosition(dx, dy); + } + } + + + /** + * Returns the current rotation mode. + */ + public RotationMode getRotationMode() { + return rotationMode; + } + + /** + * Sets the rotation mode. See {@link RotationMode} for the available options. + */ + public void setRotationMode(RotationMode rotationMode) { + this.rotationMode = rotationMode; + } + + public float getRotationRadius() { + return rotationRadius; + } + + public void setRotationRadius(float rotationRadius) { + this.rotationRadius = rotationRadius; + } + + /** + * Returns the group's rotation in degrees. + */ + public float getRotation() { + return rotation; + } + + /** + * Sets the group's rotation in degrees. The behaviour depends on {@link #rotationMode}: + *
    + *
  • {@link RotationMode#INDIVIDUAL} – the delta is applied to each sprite's + * own rotation (no positional change).
  • + *
  • {@link RotationMode#WHEEL} – the value is stored and applied during the + * next {@link #update(float)} call.
  • + *
  • {@link RotationMode#ORBIT} – each sprite's position is rotated around the + * group origin by the delta, and its individual rotation is also adjusted.
  • + *
+ */ + public void setRotation(float rotation) { + float delta = rotation - this.rotation; + this.rotation = rotation; + + switch (rotationMode) { + case INDIVIDUAL: + transformMembersIndividualRotation(delta); + break; + case ORBIT: + orbitMembersAroundCenter(delta); + break; + case WHEEL: + break; + } + } + + /** + * Adds the given amount to the group's rotation. Equivalent to + * {@code setRotation(getRotation() + degrees)}. + */ + public void changeRotation(float degrees) { + setRotation(this.rotation + degrees); + } + + /** + * Number of members. Prefer this over {@code members.size} for consistency. + */ + public int getLength() { + return members.size; + } + + public int getMaxSize() { + return maxSize; + } + + public void setMaxSize(int maxSize) { + this.maxSize = Math.max(0, maxSize); + } + + + /** + * Adds a sprite to the group. The sprite's position is automatically offset by + * the group's current ({@link #x}, {@link #y}), matching HaxeFlixel's {@code preAdd} behaviour. + */ + @Override + public void add(FlixelSprite sprite) { + if (sprite == null) { + return; + } + + if (maxSize > 0 && members.size >= maxSize) { + return; + } + + preAdd(sprite); + super.add(sprite); + } + + /** + * Adds a sprite and returns it for chaining. + */ + public FlixelSprite addAndReturn(FlixelSprite sprite) { + add(sprite); + return sprite; + } + + /** + * Inserts a new sprite at the given index. The sprite is offset by the group's position. + */ + public void insert(int index, FlixelSprite sprite) { + if (sprite == null) { + return; + } + + if (maxSize > 0 && members.size >= maxSize) { + return; + } + + preAdd(sprite); + index = MathUtils.clamp(index, 0, members.size); + members.insert(index, sprite); + } + + /** + * Removes a sprite from the group. The group's position offset is subtracted from the + * sprite, restoring it to "local" coordinates, matching HaxeFlixel's {@code remove} behaviour. + */ + @Override + public void remove(FlixelSprite sprite) { + if (sprite == null) { + return; + } + + super.remove(sprite); + sprite.setX(sprite.getX() - x); + sprite.setY(sprite.getY() - y); + } + + /** + * Replaces an existing sprite with a new one. The new sprite is offset by the group's position. + * + * @return the new sprite + */ + public FlixelSprite replace(FlixelSprite oldSprite, FlixelSprite newSprite) { + if (oldSprite == null || newSprite == null) { + return newSprite; + } + + int idx = members.indexOf(oldSprite, true); + if (idx < 0) { + add(newSprite); + return newSprite; + } + + preAdd(newSprite); + members.set(idx, newSprite); + return newSprite; + } + + /** + * Sorts members using the given comparator. + */ + public void sort(Comparator comparator) { + if (comparator == null) { + return; + } + + members.sort((a, b) -> comparator.compare((FlixelSprite) a, (FlixelSprite) b)); + } + + /** + * Returns a random member, or null if the group is empty. + */ + public FlixelSprite getRandom() { + return getRandom(0, members.size); + } + + /** + * Returns a random member from the range [startIndex, startIndex + length), or null if none. + */ + public FlixelSprite getRandom(int startIndex, int length) { + if (members.size == 0) { + return null; + } + + startIndex = MathUtils.clamp(startIndex, 0, members.size - 1); + if (length <= 0) { + length = members.size; + } + + int end = Math.min(startIndex + length, members.size); + int span = end - startIndex; + if (span <= 0) { + return null; + } + + return (FlixelSprite) members.get(startIndex + RANDOM.nextInt(span)); + } + + /** + * Applies a function to each member. + */ + public void forEach(Consumer function) { + if (function == null) { + return; + } + + for (int i = 0, n = members.size; i < n; i++) { + FlixelSprite s = (FlixelSprite) members.get(i); + if (s != null) { + function.accept(s); + } + } + } + + /** + * Returns the member at the given index, or null. + */ + public FlixelSprite get(int index) { + if (index < 0 || index >= members.size) { + return null; + } + + return (FlixelSprite) members.get(index); + } + + @Override + public void update(float elapsed) { + super.update(elapsed); + + if (rotationMode == RotationMode.WHEEL) { + applyWheelRotation(); + } + } + + + @Override + public void clear() { + for (int i = 0, n = members.size; i < n; i++) { + FlixelObject member = members.get(i); + if (member != null) { + member.destroy(); + } + } + + members.clear(); + } + + /** + * Offsets a sprite by the group's current position before it is inserted into the group, + * matching HaxeFlixel's {@code preAdd} behaviour. + */ + private void preAdd(FlixelSprite sprite) { + sprite.setX(sprite.getX() + x); + sprite.setY(sprite.getY() + y); + } + + /** + * Moves every member's X by the given delta. + */ + private void transformMembersX(float dx) { + for (int i = 0, n = members.size; i < n; i++) { + FlixelSprite s = (FlixelSprite) members.get(i); + if (s != null) { + s.setX(s.getX() + dx); + } + } + } + + /** + * Moves every member's Y by the given delta. + */ + private void transformMembersY(float dy) { + for (int i = 0, n = members.size; i < n; i++) { + FlixelSprite s = (FlixelSprite) members.get(i); + if (s != null) { + s.setY(s.getY() + dy); + } + } + } + + /** + * Moves every member's position by the given deltas in a single pass. + */ + private void transformMembersPosition(float dx, float dy) { + for (int i = 0, n = members.size; i < n; i++) { + FlixelSprite s = (FlixelSprite) members.get(i); + if (s != null) { + s.setPosition(s.getX() + dx, s.getY() + dy); + } + } + } + + /** + * {@link RotationMode#INDIVIDUAL}: applies the rotation delta to each sprite's own rotation + * without changing any positions. + */ + private void transformMembersIndividualRotation(float delta) { + for (int i = 0, n = members.size; i < n; i++) { + FlixelSprite s = (FlixelSprite) members.get(i); + if (s != null) { + s.setRotation(s.getRotation() + delta); + } + } + } + + /** + * {@link RotationMode#ORBIT}: rotates every member's position around the group origin + * ({@link #x}, {@link #y}) by {@code angleDelta} degrees and adjusts each sprite's own + * rotation by the same amount, like a rotating camera/TV screen. + */ + private void orbitMembersAroundCenter(float angleDelta) { + float cos = MathUtils.cosDeg(angleDelta); + float sin = MathUtils.sinDeg(angleDelta); + + for (int i = 0, n = members.size; i < n; i++) { + FlixelSprite s = (FlixelSprite) members.get(i); + if (s == null) { + continue; + } + + float localX = s.getX() - x; + float localY = s.getY() - y; + float rotatedX = localX * cos - localY * sin; + float rotatedY = localX * sin + localY * cos; + s.setPosition(x + rotatedX, y + rotatedY); + s.setRotation(s.getRotation() + angleDelta); + } + } + + /** + * {@link RotationMode#WHEEL}: positions and rotates each sprite consecutively around the + * group center in a radial/wheel pattern. Called each frame from {@link #update(float)}. + */ + private void applyWheelRotation() { + int n = members.size; + if (n == 0) { + return; + } + + float angleStep = 360f / n; + for (int i = 0; i < n; i++) { + FlixelSprite s = (FlixelSprite) members.get(i); + if (s == null) { + continue; + } + + float angleDeg = rotation + angleStep * i; + float px = x + rotationRadius * MathUtils.cosDeg(angleDeg); + float py = y + rotationRadius * MathUtils.sinDeg(angleDeg); + s.setPosition(px, py); + s.setRotation(angleDeg); + } + } + + /** + * Controls how a {@link FlixelSpriteGroup}'s {@link #rotation} affects its members. + */ + public enum RotationMode { + + /** + * Rotation is applied to each sprite's individual rotation by the delta. + * No positional changes occur from rotation. + */ + INDIVIDUAL, + + /** + * Sprites are arranged in a radial/wheel pattern around the group center + * ({@link #x}, {@link #y}). Each sprite is positioned at {@link #rotationRadius} from the + * center, spaced evenly around 360 degrees. Positions and rotations are set absolutely + * each frame in {@link #update(float)}. + *

+ * Note that you cannot change the rotation of any specific sprite of the group when in this mode, as it + * is locked to the group's rotation. + */ + WHEEL, + + /** + * All sprites orbit around the group origin ({@link #x}, {@link #y}) as a rigid body, + * like a rotating camera or TV screen. When rotation changes, each sprite's position is + * rotated around the center by the delta and its individual rotation is also adjusted + * by the same amount. + */ + ORBIT + } +} diff --git a/flixelgdx/src/main/java/me/stringdotjar/flixelgdx/input/FlixelKey.java b/flixelgdx/src/main/java/me/stringdotjar/flixelgdx/input/FlixelKey.java index 963a94b..3b522fc 100644 --- a/flixelgdx/src/main/java/me/stringdotjar/flixelgdx/input/FlixelKey.java +++ b/flixelgdx/src/main/java/me/stringdotjar/flixelgdx/input/FlixelKey.java @@ -5,4 +5,7 @@ /** * A simple extension of {@link Input.Keys} to simplify accessing key constants. */ -public class FlixelKey extends Input.Keys {} +public class FlixelKey extends Input.Keys { + + private FlixelKey() {} +} diff --git a/funkin/src/main/java/me/stringdotjar/funkin/menus/TitleState.java b/funkin/src/main/java/me/stringdotjar/funkin/menus/TitleState.java index 03e0778..e02411f 100644 --- a/funkin/src/main/java/me/stringdotjar/funkin/menus/TitleState.java +++ b/funkin/src/main/java/me/stringdotjar/funkin/menus/TitleState.java @@ -5,6 +5,7 @@ import me.stringdotjar.flixelgdx.backend.FlixelPaths; import me.stringdotjar.flixelgdx.graphics.FlixelState; import me.stringdotjar.flixelgdx.graphics.sprite.FlixelSprite; +import me.stringdotjar.flixelgdx.group.FlixelSpriteGroup; import me.stringdotjar.flixelgdx.input.FlixelKey; import me.stringdotjar.flixelgdx.tween.FlixelEase; import me.stringdotjar.flixelgdx.tween.FlixelTween; @@ -15,6 +16,12 @@ public class TitleState extends FlixelState { private FlixelSprite logo; + private FlixelSpriteGroup spriteGroup; + private FlixelSprite s1; + private FlixelSprite s2; + private FlixelSprite s3; + private FlixelSprite s4; + private FlixelTween tween; private MASound tickleFight; @@ -31,6 +38,26 @@ public void create() { tickleFight = Flixel.playSound("shared/sounds/tickleFight.ogg"); // Flixel.playMusic("preload/music/freakyMenu/freakyMenu.ogg", 0.5f); + spriteGroup = new FlixelSpriteGroup(0, 200f, 0f); + s1 = new FlixelSprite().loadGraphic(FlixelPaths.sharedImageAsset("transitionSwag/stickers-set-1/bfSticker1")); + s2 = new FlixelSprite().loadGraphic(FlixelPaths.sharedImageAsset("transitionSwag/stickers-set-1/bfSticker2")); + s3 = new FlixelSprite().loadGraphic(FlixelPaths.sharedImageAsset("transitionSwag/stickers-set-1/bfSticker3")); + s4 = new FlixelSprite().loadGraphic(FlixelPaths.sharedImageAsset("transitionSwag/stickers-set-1/gfSticker1")); + s1.setX(200); + s2.setX(-200); + s3.setX(200); + s4.setX(-200); + s1.setY(200); + s2.setY(200); + s3.setY(-200); + s4.setY(-200); + spriteGroup.add(s1); + spriteGroup.add(s2); + spriteGroup.add(s3); + spriteGroup.add(s4); + spriteGroup.setRotationMode(FlixelSpriteGroup.RotationMode.INDIVIDUAL); + add(spriteGroup); + FlixelTweenSettings settings = new FlixelTweenSettings() .addGoal("x", 600) .addGoal("y", 40) @@ -50,17 +77,65 @@ public void update(float elapsed) { super.update(elapsed); float speed = 500 * elapsed; + // if (Flixel.keyPressed(FlixelKey.W)) { + // logo.changeY(speed); + // } + // if (Flixel.keyPressed(FlixelKey.S)) { + // logo.changeY(-speed); + // } + // if (Flixel.keyPressed(FlixelKey.A)) { + // logo.changeX(-speed); + // } + // if (Flixel.keyPressed(FlixelKey.D)) { + // logo.changeX(speed); + // } if (Flixel.keyPressed(FlixelKey.W)) { - logo.changeY(speed); + spriteGroup.changeY(speed); } if (Flixel.keyPressed(FlixelKey.S)) { - logo.changeY(-speed); + spriteGroup.changeY(-speed); } if (Flixel.keyPressed(FlixelKey.A)) { - logo.changeX(-speed); + spriteGroup.changeX(-speed); } if (Flixel.keyPressed(FlixelKey.D)) { - logo.changeX(speed); + spriteGroup.changeX(speed); + } + + if (Flixel.keyPressed(FlixelKey.I)) { + s1.changeY(speed); + } + if (Flixel.keyPressed(FlixelKey.K)) { + s1.changeY(-speed); + } + if (Flixel.keyPressed(FlixelKey.J)) { + s1.changeX(-speed); + } + if (Flixel.keyPressed(FlixelKey.L)) { + s1.changeX(speed); + } + if (Flixel.keyPressed(FlixelKey.U)) { + s1.changeRotation(speed); + } + if (Flixel.keyPressed(FlixelKey.O)) { + s1.changeRotation(-speed); + } + + if (Flixel.keyJustPressed(FlixelKey.NUM_1)) { + spriteGroup.setRotationMode(FlixelSpriteGroup.RotationMode.INDIVIDUAL); + } + if (Flixel.keyJustPressed(FlixelKey.NUM_2)) { + spriteGroup.setRotationMode(FlixelSpriteGroup.RotationMode.WHEEL); + } + if (Flixel.keyJustPressed(FlixelKey.NUM_3)) { + spriteGroup.setRotationMode(FlixelSpriteGroup.RotationMode.ORBIT); + } + + if (Flixel.keyPressed(FlixelKey.LEFT)) { + spriteGroup.changeRotation(speed); + } + if (Flixel.keyPressed(FlixelKey.RIGHT)) { + spriteGroup.changeRotation(-speed); } if (Flixel.keyJustPressed(FlixelKey.SPACE)) {