From 12e70002d63c03caa6de280c4329ec6e7abf5943 Mon Sep 17 00:00:00 2001 From: fd Date: Sun, 12 Apr 2015 10:25:03 -0400 Subject: [PATCH 1/2] More curve types Catmull curves Line Curves(half assed) Curve refactor #73 near 0 length sliders --- src/itdelatrisu/opsu/objects/Slider.java | 5 +- .../opsu/objects/curves/Bezier2.java | 47 +----- .../opsu/objects/curves/CatmullCurve.java | 53 +++++++ .../objects/curves/CentripetalCatmullRom.java | 101 +++++++++++++ .../objects/curves/CircumscribedCircle.java | 16 +- .../opsu/objects/curves/Curve.java | 22 ++- .../opsu/objects/curves/CurveType.java | 79 ++++++++++ .../curves/EqualDistanceMultiCurve.java | 141 ++++++++++++++++++ .../opsu/objects/curves/LinearBezier.java | 136 ++--------------- .../opsu/objects/curves/Vec2f.java | 16 ++ src/itdelatrisu/opsu/states/Game.java | 10 ++ 11 files changed, 444 insertions(+), 182 deletions(-) create mode 100644 src/itdelatrisu/opsu/objects/curves/CatmullCurve.java create mode 100644 src/itdelatrisu/opsu/objects/curves/CentripetalCatmullRom.java create mode 100644 src/itdelatrisu/opsu/objects/curves/CurveType.java create mode 100644 src/itdelatrisu/opsu/objects/curves/EqualDistanceMultiCurve.java diff --git a/src/itdelatrisu/opsu/objects/Slider.java b/src/itdelatrisu/opsu/objects/Slider.java index 9c53bbe3..19740c77 100644 --- a/src/itdelatrisu/opsu/objects/Slider.java +++ b/src/itdelatrisu/opsu/objects/Slider.java @@ -25,6 +25,7 @@ import itdelatrisu.opsu.GameMod; import itdelatrisu.opsu.OsuFile; import itdelatrisu.opsu.OsuHitObject; import itdelatrisu.opsu.Utils; +import itdelatrisu.opsu.objects.curves.CatmullCurve; import itdelatrisu.opsu.objects.curves.CircumscribedCircle; import itdelatrisu.opsu.objects.curves.Curve; import itdelatrisu.opsu.objects.curves.LinearBezier; @@ -459,8 +460,10 @@ public class Slider implements HitObject { if (hitObject.getSliderType() == OsuHitObject.SLIDER_PASSTHROUGH && hitObject.getSliderX().length == 2) this.curve = new CircumscribedCircle(hitObject, color); + else if ( hitObject.getSliderType() == OsuHitObject.SLIDER_CATMULL) + this.curve = new CatmullCurve(hitObject, color); else - this.curve = new LinearBezier(hitObject, color); + this.curve = new LinearBezier(hitObject, color, hitObject.getSliderType() == OsuHitObject.SLIDER_LINEAR); } @Override diff --git a/src/itdelatrisu/opsu/objects/curves/Bezier2.java b/src/itdelatrisu/opsu/objects/curves/Bezier2.java index 35552b4a..979ae8a1 100644 --- a/src/itdelatrisu/opsu/objects/curves/Bezier2.java +++ b/src/itdelatrisu/opsu/objects/curves/Bezier2.java @@ -23,22 +23,10 @@ package itdelatrisu.opsu.objects.curves; * * @author fluddokt (https://github.com/fluddokt) */ -public class Bezier2 { +public class Bezier2 extends CurveType{ /** The control points of the Bezier curve. */ private Vec2f[] points; - /** Points along the curve of the Bezier curve. */ - private Vec2f[] curve; - - /** Distances between a point of the curve and the last point. */ - private float[] curveDis; - - /** The number of points along the curve. */ - private int ncurve; - - /** The total distances of this Bezier. */ - private float totalDistance; - /** * Constructor. * @param points the control points @@ -52,19 +40,7 @@ public class Bezier2 { for (int i = 0; i < points.length - 1; i++) approxlength += points[i].cpy().sub(points[i + 1]).len(); - // subdivide the curve - this.ncurve = (int) (approxlength / 4); - this.curve = new Vec2f[ncurve]; - for (int i = 0; i < ncurve; i++) - curve[i] = pointAt(i / (float) ncurve); - - // find the distance of each point from the previous point - this.curveDis = new float[ncurve]; - this.totalDistance = 0; - for (int i = 0; i < ncurve; i++) { - curveDis[i] = (i == 0) ? 0 : curve[i].cpy().sub(curve[i - 1]).len(); - totalDistance += curveDis[i]; - } + init(approxlength); // System.out.println("New Bezier2 "+points.length+" "+approxlength+" "+totalDistance()); } @@ -84,25 +60,6 @@ public class Bezier2 { return c; } - /** - * Returns the points along the curve of the Bezier curve. - */ - public Vec2f[] getCurve() { return curve; } - - /** - * Returns the distances between a point of the curve and the last point. - */ - public float[] getCurveDistances() { return curveDis; } - - /** - * Returns the number of points along the curve. - */ - public int points() { return ncurve; } - - /** - * Returns the total distances of this Bezier curve. - */ - public float totalDistance() { return totalDistance; } /** * Calculates the binomial coefficient. diff --git a/src/itdelatrisu/opsu/objects/curves/CatmullCurve.java b/src/itdelatrisu/opsu/objects/curves/CatmullCurve.java new file mode 100644 index 00000000..c0b51687 --- /dev/null +++ b/src/itdelatrisu/opsu/objects/curves/CatmullCurve.java @@ -0,0 +1,53 @@ +/* + * opsu! - an open-source osu! client + * Copyright (C) 2014, 2015 Jeffrey Han + * + * opsu! is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * opsu! is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with opsu!. If not, see . + */ + +package itdelatrisu.opsu.objects.curves; + +import java.util.LinkedList; + +import itdelatrisu.opsu.OsuHitObject; + +import org.newdawn.slick.Color; + +public class CatmullCurve extends EqualDistanceMultiCurve{ + + public CatmullCurve(OsuHitObject hitObject, Color color) { + super(hitObject, color); + LinkedList catmulls = new LinkedList(); + int ncontrolPoints = hitObject.getSliderX().length + 1; + LinkedList points = new LinkedList(); // temporary list of points to separate different curves + + //aaa .... needs at least two points + //aabb + //aabc abcc + //aabc abcd bcdd + points.addLast(new Vec2f(getX(0),getY(0))); + for(int i=0;i=4){ + catmulls.add(new CentripetalCatmullRom(points.toArray(new Vec2f[0]))); + points.removeFirst(); + } + } + points.addLast(new Vec2f(getX(ncontrolPoints-1),getY(ncontrolPoints-1))); + if(points.size()>=4){ + catmulls.add(new CentripetalCatmullRom(points.toArray(new Vec2f[0]))); + } + init(catmulls); + } +} diff --git a/src/itdelatrisu/opsu/objects/curves/CentripetalCatmullRom.java b/src/itdelatrisu/opsu/objects/curves/CentripetalCatmullRom.java new file mode 100644 index 00000000..743cfcdf --- /dev/null +++ b/src/itdelatrisu/opsu/objects/curves/CentripetalCatmullRom.java @@ -0,0 +1,101 @@ +/* + * opsu! - an open-source osu! client + * Copyright (C) 2014, 2015 Jeffrey Han + * + * opsu! is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * opsu! is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with opsu!. If not, see . + */ + +package itdelatrisu.opsu.objects.curves; + +/** + * Representation of a Centripetal Catmull–Rom spline. + * http://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline + * + * Currently not technically Centripetal Catmull–Rom + * + * @author fluddokt (https://github.com/fluddokt) + */ +public class CentripetalCatmullRom extends CurveType{ + + float [] time; + Vec2f[] points; + protected CentripetalCatmullRom(Vec2f[] points) { + if (points.length != 4) + throw new Error("need exactly 4 points"); + + this.points = points; + System.out.println("C"); + for(int i=0;i<4;i++){ + System.out.println(points[i]); + } + time = new float[4]; + time[0] = 0; + float approxLength = 0; + for(int i=1;i<4;i++){ + float len = 0; + if(i>0) + len = points[i].cpy().sub(points[i-1]).len(); + if(len<=0) + len+=0.0001f; + approxLength += len; + //time[i] = (float) Math.sqrt(len) + time[i-1];// ^(0.5) + time[i] = i; + System.out.println("knot:"+i+" "+time[i]); + } + init(approxLength/2); + } + public Vec2f pointAt(float t, int start, int end){ + int ind1 = start; + int ind2 = end; + if(end-start==3){ + ind1 = 1; + ind2 = 2; + } + //System.out.println("ST:"+start+" "+end+" "+ind1+" "+ind2); + float div = (time[ind2] - time[ind1]); + float v1 = (time[ind2] - t)/div; + float v2 = (t - time[ind1])/div; + System.out.println("div"+div+" "+v1+" "+v2); + if(end-start==1) + return points[start].cpy().scale(v1).add(points[end].cpy().scale(v2)); + else + return pointAt(t,start,end-1).scale(v1).add(pointAt(t,start+1,end).scale(v2)); + } + + public Vec2f pointAt(float t){ + t = t * (time[2]-time[1]) + time[1]; + + Vec2f A1 = points[0].cpy().scale((time[1]-t)/(time[1]-time[0])).add(points[1].cpy().scale((t-time[0])/(time[1]-time[0]))); + Vec2f A2 = points[1].cpy().scale((time[2]-t)/(time[2]-time[1])).add(points[2].cpy().scale((t-time[1])/(time[2]-time[1]))); + Vec2f A3 = points[2].cpy().scale((time[3]-t)/(time[3]-time[2])).add(points[3].cpy().scale((t-time[2])/(time[3]-time[2]))); + + Vec2f B1 = A1.cpy().scale((time[2]-t)/(time[2]-time[0])).add(A2.cpy().scale((t-time[0])/(time[2]-time[0]))); + Vec2f B2 = A2.cpy().scale((time[3]-t)/(time[3]-time[1])).add(A3.cpy().scale((t-time[1])/(time[3]-time[1]))); + + Vec2f C = B1.cpy().scale((time[2]-t)/(time[2]-time[1])).add(B2.cpy().scale((t-time[1])/(time[2]-time[1]))); + + return C; + } + public String toString(){ + String t = "CATMULLROM"; + for(Vec2f p: points){ + t+=p; + } + + t+=pointAt(0); + t+=pointAt(1); + + return t; + } +} diff --git a/src/itdelatrisu/opsu/objects/curves/CircumscribedCircle.java b/src/itdelatrisu/opsu/objects/curves/CircumscribedCircle.java index f534db95..5b09cccb 100644 --- a/src/itdelatrisu/opsu/objects/curves/CircumscribedCircle.java +++ b/src/itdelatrisu/opsu/objects/curves/CircumscribedCircle.java @@ -56,9 +56,6 @@ public class CircumscribedCircle extends Curve { /** The number of steps in the curve to draw. */ private float step; - /** Points along the curve. */ - private Vec2f[] curve; - /** * Constructor. * @param hitObject the associated OsuHitObject @@ -67,8 +64,7 @@ public class CircumscribedCircle extends Curve { public CircumscribedCircle(OsuHitObject hitObject, Color color) { super(hitObject, color); - this.step = hitObject.getPixelLength() / 5f; - + // construct the three points this.start = new Vec2f(getX(0), getY(0)); this.mid = new Vec2f(getX(1), getY(1)); @@ -125,6 +121,7 @@ public class CircumscribedCircle extends Curve { this.drawStartAngle = (float) ((startAng + (startAng > endAng ? -HALF_PI : HALF_PI)) * 180 / Math.PI); // calculate points + this.step = hitObject.getPixelLength() / CURVE_POINTS_SEPERATION; curve = new Vec2f[(int) step + 1]; for (int i = 0; i < curve.length; i++) { float[] xy = pointAt(i / step); @@ -178,15 +175,6 @@ public class CircumscribedCircle extends Curve { }; } - @Override - public void draw(Color color) { - Image hitCircle = GameImage.HITCIRCLE.getImage(); - Image hitCircleOverlay = GameImage.HITCIRCLE_OVERLAY.getImage(); - for (int i = 0; i < step; i++) - hitCircleOverlay.drawCentered(curve[i].x, curve[i].y, Utils.COLOR_WHITE_FADE); - for (int i = 0; i < step; i++) - hitCircle.drawCentered(curve[i].x, curve[i].y, color); - } @Override public float getEndAngle() { return drawEndAngle; } diff --git a/src/itdelatrisu/opsu/objects/curves/Curve.java b/src/itdelatrisu/opsu/objects/curves/Curve.java index ab3d23aa..59374a14 100644 --- a/src/itdelatrisu/opsu/objects/curves/Curve.java +++ b/src/itdelatrisu/opsu/objects/curves/Curve.java @@ -18,9 +18,12 @@ package itdelatrisu.opsu.objects.curves; +import itdelatrisu.opsu.GameImage; import itdelatrisu.opsu.OsuHitObject; +import itdelatrisu.opsu.Utils; import org.newdawn.slick.Color; +import org.newdawn.slick.Image; /** * Representation of a curve. @@ -28,6 +31,8 @@ import org.newdawn.slick.Color; * @author fluddokt (https://github.com/fluddokt) */ public abstract class Curve { + + protected static float CURVE_POINTS_SEPERATION = 50; /** The associated OsuHitObject. */ protected OsuHitObject hitObject; @@ -37,6 +42,9 @@ public abstract class Curve { /** The scaled slider x, y coordinate lists. */ protected float[] sliderX, sliderY; + /** Points along the curve. To be set be inherited classes*/ + protected Vec2f[] curve; + /** * Constructor. * @param hitObject the associated OsuHitObject @@ -48,6 +56,7 @@ public abstract class Curve { this.y = hitObject.getScaledY(); this.sliderX = hitObject.getScaledSliderX(); this.sliderY = hitObject.getScaledSliderY(); + CURVE_POINTS_SEPERATION = 5; } /** @@ -61,7 +70,18 @@ public abstract class Curve { * Draws the full curve to the graphics context. * @param color the color filter */ - public abstract void draw(Color color); + public void draw(Color color) { + if ( curve == null){ + System.out.println("draw curve"+this); + return; + } + Image hitCircle = GameImage.HITCIRCLE.getImage(); + Image hitCircleOverlay = GameImage.HITCIRCLE_OVERLAY.getImage(); + for (int i = 0; i < curve.length; i++) + hitCircleOverlay.drawCentered(curve[i].x, curve[i].y, Utils.COLOR_WHITE_FADE); + for (int i = 0; i < curve.length; i++) + hitCircle.drawCentered(curve[i].x, curve[i].y, color); + } /** * Returns the angle of the first control point. diff --git a/src/itdelatrisu/opsu/objects/curves/CurveType.java b/src/itdelatrisu/opsu/objects/curves/CurveType.java new file mode 100644 index 00000000..e41037b6 --- /dev/null +++ b/src/itdelatrisu/opsu/objects/curves/CurveType.java @@ -0,0 +1,79 @@ +/* + * opsu! - an open-source osu! client + * Copyright (C) 2014, 2015 Jeffrey Han + * + * opsu! is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * opsu! is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with opsu!. If not, see . + */ + +package itdelatrisu.opsu.objects.curves; + +/** + * Representation of a curve with the distance between each point calculated. + * + * @author fluddokt (https://github.com/fluddokt) + */ +public abstract class CurveType { + + /** Points along the curve of the Bezier curve. */ + private Vec2f[] curve; + + /** Distances between a point of the curve and the last point. */ + private float[] curveDis; + + /** The number of points along the curve. */ + private int ncurve; + + /** The total distances of this Bezier. */ + private float totalDistance; + + public abstract Vec2f pointAt(float t); + + public void init(float approxlength){ + // subdivide the curve + this.ncurve = (int) (approxlength / 4) + 1; + this.curve = new Vec2f[ncurve]; + System.out.println(approxlength+" "+ncurve); + for (int i = 0; i < ncurve; i++) + curve[i] = pointAt(i / (float) (ncurve - 1)); + + // find the distance of each point from the previous point + this.curveDis = new float[ncurve]; + this.totalDistance = 0; + for (int i = 0; i < ncurve; i++) { + curveDis[i] = (i == 0) ? 0 : curve[i].cpy().sub(curve[i - 1]).len(); + totalDistance += curveDis[i]; + System.out.println("curvedis:"+curveDis[i]); + } + } + /** + * Returns the points along the curve of the Bezier curve. + */ + public Vec2f[] getCurve() { return curve; } + + /** + * Returns the distances between a point of the curve and the last point. + */ + public float[] getCurveDistances() { return curveDis; } + + /** + * Returns the number of points along the curve. + */ + public int getCurvesCount() { return ncurve; } + + /** + * Returns the total distances of this Bezier curve. + */ + public float totalDistance() { return totalDistance; } + +} diff --git a/src/itdelatrisu/opsu/objects/curves/EqualDistanceMultiCurve.java b/src/itdelatrisu/opsu/objects/curves/EqualDistanceMultiCurve.java new file mode 100644 index 00000000..f3dc8bc4 --- /dev/null +++ b/src/itdelatrisu/opsu/objects/curves/EqualDistanceMultiCurve.java @@ -0,0 +1,141 @@ +/* + * opsu! - an open-source osu! client + * Copyright (C) 2014, 2015 Jeffrey Han + * + * opsu! is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * opsu! is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with opsu!. If not, see . + */ + +package itdelatrisu.opsu.objects.curves; + +import itdelatrisu.opsu.OsuHitObject; + +import java.util.Iterator; +import java.util.LinkedList; + +import org.newdawn.slick.Color; + +/** + * Representation of a Bezier curve with equidistant points. + * http://pomax.github.io/bezierinfo/#tracing + * + * @author fluddokt (https://github.com/fluddokt) + */ +public abstract class EqualDistanceMultiCurve extends Curve { + /** The angles of the first and last control points for drawing. */ + private float startAngle, endAngle; + + /** The number of points along the curve. */ + private int ncurve; + + /** + * Constructor. + * @param hitObject the associated OsuHitObject + * @param color the color of this curve + */ + public EqualDistanceMultiCurve(OsuHitObject hitObject, Color color) { + super(hitObject, color); + + } + + public void init(LinkedList beziers){ + for(CurveType ct : beziers){ + System.out.println("CT:"+ct); + } + // now try to creates points the are equidistant to each other + this.ncurve = (int) (hitObject.getPixelLength() / CURVE_POINTS_SEPERATION); + this.curve = new Vec2f[ncurve + 1]; + + float distanceAt = 0; + Iterator iter = beziers.iterator(); + int curPoint = 0; + CurveType curBezier = iter.next(); + Vec2f lastCurve = curBezier.getCurve()[0]; + float lastDistanceAt = 0; + + // length of Bezier should equal pixel length (in 640x480) + float pixelLength = hitObject.getPixelLength() * OsuHitObject.getXMultiplier(); + + // for each distance, try to get in between the two points that are between it + for (int i = 0; i < ncurve + 1; i++) { + int prefDistance = (int) (i * pixelLength / ncurve); + while (distanceAt < prefDistance) { + lastDistanceAt = distanceAt; + lastCurve = curBezier.getCurve()[curPoint]; + distanceAt += curBezier.getCurveDistances()[curPoint++]; + + if (curPoint >= curBezier.getCurvesCount()) { + if (iter.hasNext()) { + curBezier = iter.next(); + curPoint = 0; + } else { + curPoint = curBezier.getCurvesCount() - 1; + if (lastDistanceAt == distanceAt) { + // out of points even though the preferred distance hasn't been reached + break; + } + } + } + } + System.out.println("prefDis:"+prefDistance+" "+distanceAt+" "+lastDistanceAt); + Vec2f thisCurve = curBezier.getCurve()[curPoint]; + + // interpolate the point between the two closest distances + if (distanceAt - lastDistanceAt > 1) { + float t = (prefDistance - lastDistanceAt) / (distanceAt - lastDistanceAt); + curve[i] = new Vec2f(lerp(lastCurve.x, thisCurve.x, t), lerp(lastCurve.y, thisCurve.y, t)); + } else + curve[i] = thisCurve; + } + +// if (hitObject.getRepeatCount() > 1) { + Vec2f c1 = curve[0]; + int cnt = 1; + Vec2f c2 = curve[cnt++]; + while (cnt <= ncurve && c2.cpy().sub(c1).len() < 1) + c2 = curve[cnt++]; + this.startAngle = (float) (Math.atan2(c2.y - c1.y, c2.x - c1.x) * 180 / Math.PI); + + c1 = curve[ncurve]; + cnt = ncurve - 1; + c2 = curve[cnt--]; + while (cnt >= 0 && c2.cpy().sub(c1).len() < 1) + c2 = curve[cnt--]; + this.endAngle = (float) (Math.atan2(c2.y - c1.y, c2.x - c1.x) * 180 / Math.PI); +// } + } + + @Override + public float[] pointAt(float t) { + float indexF = t * ncurve; + int index = (int) indexF; + if (index >= ncurve) { + Vec2f poi = curve[ncurve]; + return new float[] { poi.x, poi.y }; + } else { + Vec2f poi = curve[index]; + Vec2f poi2 = curve[index + 1]; + float t2 = indexF - index; + return new float[] { + lerp(poi.x, poi2.x, t2), + lerp(poi.y, poi2.y, t2) + }; + } + } + + @Override + public float getEndAngle() { return endAngle; } + + @Override + public float getStartAngle() { return startAngle; } +} diff --git a/src/itdelatrisu/opsu/objects/curves/LinearBezier.java b/src/itdelatrisu/opsu/objects/curves/LinearBezier.java index ca7dede2..cb919699 100644 --- a/src/itdelatrisu/opsu/objects/curves/LinearBezier.java +++ b/src/itdelatrisu/opsu/objects/curves/LinearBezier.java @@ -18,15 +18,10 @@ package itdelatrisu.opsu.objects.curves; -import itdelatrisu.opsu.GameImage; import itdelatrisu.opsu.OsuHitObject; -import itdelatrisu.opsu.Utils; - -import java.util.Iterator; import java.util.LinkedList; import org.newdawn.slick.Color; -import org.newdawn.slick.Image; /** * Representation of a Bezier curve with equidistant points. @@ -34,34 +29,32 @@ import org.newdawn.slick.Image; * * @author fluddokt (https://github.com/fluddokt) */ -public class LinearBezier extends Curve { - /** The angles of the first and last control points for drawing. */ - private float startAngle, endAngle; - - /** List of Bezier curves in the set of points. */ - private LinkedList beziers = new LinkedList(); - - /** Points along the curve at equal distance. */ - private Vec2f[] curve; - - /** The number of points along the curve. */ - private int ncurve; +public class LinearBezier extends EqualDistanceMultiCurve { /** * Constructor. * @param hitObject the associated OsuHitObject * @param color the color of this curve */ - public LinearBezier(OsuHitObject hitObject, Color color) { + public LinearBezier(OsuHitObject hitObject, Color color, boolean line) { super(hitObject, color); + LinkedList beziers = new LinkedList(); + // a b c - c d - d e f g + // ab bc cd de ef fg // splits points into different Beziers if has the same points (red points) int controlPoints = hitObject.getSliderX().length + 1; LinkedList points = new LinkedList(); // temporary list of points to separate different Bezier curves Vec2f lastPoi = null; for (int i = 0; i < controlPoints; i++) { Vec2f tpoi = new Vec2f(getX(i), getY(i)); - if (lastPoi != null && tpoi.equals(lastPoi)) { + if (line) { + if(lastPoi != null) { + points.add(tpoi); + beziers.add(new Bezier2(points.toArray(new Vec2f[0]))); + points.clear(); + } + } else if (lastPoi != null && tpoi.equals(lastPoi)) { if (points.size() >= 2) beziers.add(new Bezier2(points.toArray(new Vec2f[0]))); points.clear(); @@ -69,113 +62,14 @@ public class LinearBezier extends Curve { points.add(tpoi); lastPoi = tpoi; } - if (points.size() < 2) { + if (line || points.size() < 2) { // trying to continue Bezier with less than 2 points // probably ending on a red point, just ignore it } else { beziers.add(new Bezier2(points.toArray(new Vec2f[0]))); points.clear(); } - - // find the length of all beziers -// int totalDistance = 0; -// for (Bezier2 bez : beziers) { -// totalDistance += bez.totalDistance(); -// } - - // now try to creates points the are equidistant to each other - this.ncurve = (int) (hitObject.getPixelLength() / 5f); - this.curve = new Vec2f[ncurve + 1]; - - float distanceAt = 0; - Iterator iter = beziers.iterator(); - int curPoint = 0; - Bezier2 curBezier = iter.next(); - Vec2f lastCurve = curBezier.getCurve()[0]; - float lastDistanceAt = 0; - - // length of Bezier should equal pixel length (in 640x480) - float pixelLength = hitObject.getPixelLength() * OsuHitObject.getXMultiplier(); - - // for each distance, try to get in between the two points that are between it - for (int i = 0; i < ncurve + 1; i++) { - int prefDistance = (int) (i * pixelLength / ncurve); - while (distanceAt < prefDistance) { - lastDistanceAt = distanceAt; - lastCurve = curBezier.getCurve()[curPoint]; - distanceAt += curBezier.getCurveDistances()[curPoint++]; - - if (curPoint >= curBezier.points()) { - if (iter.hasNext()) { - curBezier = iter.next(); - curPoint = 0; - } else { - curPoint = curBezier.points() - 1; - if (lastDistanceAt == distanceAt) { - // out of points even though the preferred distance hasn't been reached - break; - } - } - } - } - Vec2f thisCurve = curBezier.getCurve()[curPoint]; - - // interpolate the point between the two closest distances - if (distanceAt - lastDistanceAt > 1) { - float t = (prefDistance - lastDistanceAt) / (distanceAt - lastDistanceAt); - curve[i] = new Vec2f(lerp(lastCurve.x, thisCurve.x, t), lerp(lastCurve.y, thisCurve.y, t)); - } else - curve[i] = thisCurve; - } - -// if (hitObject.getRepeatCount() > 1) { - Vec2f c1 = curve[0]; - int cnt = 1; - Vec2f c2 = curve[cnt++]; - while (cnt <= ncurve && c2.cpy().sub(c1).len() < 1) - c2 = curve[cnt++]; - this.startAngle = (float) (Math.atan2(c2.y - c1.y, c2.x - c1.x) * 180 / Math.PI); - - c1 = curve[ncurve]; - cnt = ncurve - 1; - c2 = curve[cnt--]; - while (cnt >= 0 && c2.cpy().sub(c1).len() < 1) - c2 = curve[cnt--]; - this.endAngle = (float) (Math.atan2(c2.y - c1.y, c2.x - c1.x) * 180 / Math.PI); -// } + + init(beziers); } - - @Override - public float[] pointAt(float t) { - float indexF = t * ncurve; - int index = (int) indexF; - if (index >= ncurve) { - Vec2f poi = curve[ncurve]; - return new float[] { poi.x, poi.y }; - } else { - Vec2f poi = curve[index]; - Vec2f poi2 = curve[index + 1]; - float t2 = indexF - index; - return new float[] { - lerp(poi.x, poi2.x, t2), - lerp(poi.y, poi2.y, t2) - }; - } - } - - @Override - public void draw(Color color) { - Image hitCircle = GameImage.HITCIRCLE.getImage(); - Image hitCircleOverlay = GameImage.HITCIRCLE_OVERLAY.getImage(); - for (int i = curve.length - 2; i >= 0; i--) - hitCircleOverlay.drawCentered(curve[i].x, curve[i].y, Utils.COLOR_WHITE_FADE); - for (int i = curve.length - 2; i >= 0; i--) - hitCircle.drawCentered(curve[i].x, curve[i].y, color); - } - - @Override - public float getEndAngle() { return endAngle; } - - @Override - public float getStartAngle() { return startAngle; } } diff --git a/src/itdelatrisu/opsu/objects/curves/Vec2f.java b/src/itdelatrisu/opsu/objects/curves/Vec2f.java index b49bac2d..7f1cd527 100644 --- a/src/itdelatrisu/opsu/objects/curves/Vec2f.java +++ b/src/itdelatrisu/opsu/objects/curves/Vec2f.java @@ -49,6 +49,18 @@ public class Vec2f { return new Vec2f((x + o.x) / 2, (y + o.y) / 2); } + public Vec2f scale(float s) { + x *= s; + y *= s; + return this; + } + + public Vec2f add(Vec2f o) { + x += o.x; + y += o.y; + return this; + } + /** * Subtracts a vector from this vector. * @param o the other vector @@ -97,4 +109,8 @@ public class Vec2f { * @return true if the two vectors are numerically equal */ public boolean equals(Vec2f o) { return (x == o.x && y == o.y); } + + public String toString(){ + return "Vec2f:"+x+" "+y; + } } diff --git a/src/itdelatrisu/opsu/states/Game.java b/src/itdelatrisu/opsu/states/Game.java index 6032b5b8..728f72f7 100644 --- a/src/itdelatrisu/opsu/states/Game.java +++ b/src/itdelatrisu/opsu/states/Game.java @@ -1043,6 +1043,16 @@ public class Game extends BasicGameState { // reset game data resetGameData(); + // load the first timingPoint + timingPointIndex = 0; + beatLengthBase = beatLength = 1; + if (!osu.timingPoints.isEmpty()) { + OsuTimingPoint timingPoint = osu.timingPoints.get(0); + if (!timingPoint.isInherited()) { + setBeatLength(timingPoint, true); + timingPointIndex++; + } + } // initialize object maps for (int i = 0; i < osu.objects.length; i++) { OsuHitObject hitObject = osu.objects[i]; From e792c3cae6a6ef63c92698f015e2c623c71e403f Mon Sep 17 00:00:00 2001 From: fd Date: Sun, 12 Apr 2015 13:19:33 -0400 Subject: [PATCH 2/2] Clean --- .../opsu/objects/curves/Bezier2.java | 7 +- .../opsu/objects/curves/CatmullCurve.java | 33 ++++--- .../objects/curves/CentripetalCatmullRom.java | 89 ++++++++----------- .../objects/curves/CircumscribedCircle.java | 9 +- .../opsu/objects/curves/Curve.java | 8 +- .../opsu/objects/curves/CurveType.java | 17 +++- .../curves/EqualDistanceMultiCurve.java | 34 +++---- .../opsu/objects/curves/LinearBezier.java | 7 +- .../opsu/objects/curves/Vec2f.java | 10 +++ src/itdelatrisu/opsu/states/Game.java | 2 +- 10 files changed, 112 insertions(+), 104 deletions(-) diff --git a/src/itdelatrisu/opsu/objects/curves/Bezier2.java b/src/itdelatrisu/opsu/objects/curves/Bezier2.java index 979ae8a1..fa02b542 100644 --- a/src/itdelatrisu/opsu/objects/curves/Bezier2.java +++ b/src/itdelatrisu/opsu/objects/curves/Bezier2.java @@ -41,14 +41,9 @@ public class Bezier2 extends CurveType{ approxlength += points[i].cpy().sub(points[i + 1]).len(); init(approxlength); -// System.out.println("New Bezier2 "+points.length+" "+approxlength+" "+totalDistance()); } - /** - * Returns the point on the Bezier curve at a value t. - * @param t the t value [0, 1] - * @return the point [x, y] - */ + @Override public Vec2f pointAt(float t) { Vec2f c = new Vec2f(); int n = points.length - 1; diff --git a/src/itdelatrisu/opsu/objects/curves/CatmullCurve.java b/src/itdelatrisu/opsu/objects/curves/CatmullCurve.java index c0b51687..262906f5 100644 --- a/src/itdelatrisu/opsu/objects/curves/CatmullCurve.java +++ b/src/itdelatrisu/opsu/objects/curves/CatmullCurve.java @@ -24,28 +24,39 @@ import itdelatrisu.opsu.OsuHitObject; import org.newdawn.slick.Color; +/** + * Representation of Catmull Curve with equidistant points. + * + * @author fluddokt (https://github.com/fluddokt) + */ public class CatmullCurve extends EqualDistanceMultiCurve{ + /** + * Constructor. + * @param hitObject the associated OsuHitObject + * @param color the color of this curve + */ public CatmullCurve(OsuHitObject hitObject, Color color) { super(hitObject, color); LinkedList catmulls = new LinkedList(); int ncontrolPoints = hitObject.getSliderX().length + 1; - LinkedList points = new LinkedList(); // temporary list of points to separate different curves + // temporary list of points to separate different curves + LinkedList points = new LinkedList(); - //aaa .... needs at least two points - //aabb - //aabc abcc - //aabc abcd bcdd - points.addLast(new Vec2f(getX(0),getY(0))); - for(int i=0;i=4){ + // repeat the first and last points as controls points + // aabb + // aabc abcc + // aabc abcd bcdd + points.addLast(new Vec2f(getX(0), getY(0))); + for (int i = 0; i < ncontrolPoints; i++) { + points.addLast(new Vec2f(getX(i), getY(i))); + if (points.size() >= 4) { catmulls.add(new CentripetalCatmullRom(points.toArray(new Vec2f[0]))); points.removeFirst(); } } - points.addLast(new Vec2f(getX(ncontrolPoints-1),getY(ncontrolPoints-1))); - if(points.size()>=4){ + points.addLast(new Vec2f(getX(ncontrolPoints - 1),getY(ncontrolPoints - 1))); + if (points.size() >= 4) { catmulls.add(new CentripetalCatmullRom(points.toArray(new Vec2f[0]))); } init(catmulls); diff --git a/src/itdelatrisu/opsu/objects/curves/CentripetalCatmullRom.java b/src/itdelatrisu/opsu/objects/curves/CentripetalCatmullRom.java index 743cfcdf..283dab2b 100644 --- a/src/itdelatrisu/opsu/objects/curves/CentripetalCatmullRom.java +++ b/src/itdelatrisu/opsu/objects/curves/CentripetalCatmullRom.java @@ -28,74 +28,59 @@ package itdelatrisu.opsu.objects.curves; */ public class CentripetalCatmullRom extends CurveType{ + /** The time values of the Catmull curve. */ float [] time; + + /** The control points of the Catmull curve. */ Vec2f[] points; + + /** + * Constructor. + * @param hitObject the associated OsuHitObject + * @param color the color of this curve + */ protected CentripetalCatmullRom(Vec2f[] points) { if (points.length != 4) throw new Error("need exactly 4 points"); - + this.points = points; - System.out.println("C"); - for(int i=0;i<4;i++){ - System.out.println(points[i]); - } time = new float[4]; time[0] = 0; float approxLength = 0; - for(int i=1;i<4;i++){ + for (int i = 1; i < 4; i++) { float len = 0; - if(i>0) - len = points[i].cpy().sub(points[i-1]).len(); - if(len<=0) - len+=0.0001f; + if (i > 0) + len = points[i].cpy().sub(points[i - 1]).len(); + if (len <= 0) + len += 0.0001f; approxLength += len; - //time[i] = (float) Math.sqrt(len) + time[i-1];// ^(0.5) + // time[i] = (float) Math.sqrt(len) + time[i-1];// ^(0.5) time[i] = i; - System.out.println("knot:"+i+" "+time[i]); } - init(approxLength/2); + init(approxLength / 2); } - public Vec2f pointAt(float t, int start, int end){ - int ind1 = start; - int ind2 = end; - if(end-start==3){ - ind1 = 1; - ind2 = 2; - } - //System.out.println("ST:"+start+" "+end+" "+ind1+" "+ind2); - float div = (time[ind2] - time[ind1]); - float v1 = (time[ind2] - t)/div; - float v2 = (t - time[ind1])/div; - System.out.println("div"+div+" "+v1+" "+v2); - if(end-start==1) - return points[start].cpy().scale(v1).add(points[end].cpy().scale(v2)); - else - return pointAt(t,start,end-1).scale(v1).add(pointAt(t,start+1,end).scale(v2)); - } - - public Vec2f pointAt(float t){ - t = t * (time[2]-time[1]) + time[1]; - Vec2f A1 = points[0].cpy().scale((time[1]-t)/(time[1]-time[0])).add(points[1].cpy().scale((t-time[0])/(time[1]-time[0]))); - Vec2f A2 = points[1].cpy().scale((time[2]-t)/(time[2]-time[1])).add(points[2].cpy().scale((t-time[1])/(time[2]-time[1]))); - Vec2f A3 = points[2].cpy().scale((time[3]-t)/(time[3]-time[2])).add(points[3].cpy().scale((t-time[2])/(time[3]-time[2]))); - - Vec2f B1 = A1.cpy().scale((time[2]-t)/(time[2]-time[0])).add(A2.cpy().scale((t-time[0])/(time[2]-time[0]))); - Vec2f B2 = A2.cpy().scale((time[3]-t)/(time[3]-time[1])).add(A3.cpy().scale((t-time[1])/(time[3]-time[1]))); - - Vec2f C = B1.cpy().scale((time[2]-t)/(time[2]-time[1])).add(B2.cpy().scale((t-time[1])/(time[2]-time[1]))); + + @Override + public Vec2f pointAt(float t){ + t = t * (time[2] - time[1]) + time[1]; + + Vec2f A1 = points[0].cpy().scale((time[1] - t) / (time[1] - time[0])) + .add(points[1].cpy().scale((t - time[0]) / (time[1] - time[0]))); + Vec2f A2 = points[1].cpy().scale((time[2] - t) / (time[2] - time[1])) + .add(points[2].cpy().scale((t - time[1]) / (time[2] - time[1]))); + Vec2f A3 = points[2].cpy().scale((time[3] - t) / (time[3] - time[2])) + .add(points[3].cpy().scale((t - time[2]) / (time[3] - time[2]))); + + Vec2f B1 = A1.cpy().scale((time[2] - t) / (time[2] - time[0])) + .add(A2.cpy().scale((t - time[0]) / (time[2] - time[0]))); + Vec2f B2 = A2.cpy().scale((time[3] - t) / (time[3] - time[1])) + .add(A3.cpy().scale((t - time[1]) / (time[3] - time[1]))); + + Vec2f C = B1.cpy().scale((time[2] - t) / (time[2] - time[1])) + .add(B2.cpy().scale((t - time[1]) / (time[2] - time[1]))); return C; } - public String toString(){ - String t = "CATMULLROM"; - for(Vec2f p: points){ - t+=p; - } - - t+=pointAt(0); - t+=pointAt(1); - - return t; - } + } diff --git a/src/itdelatrisu/opsu/objects/curves/CircumscribedCircle.java b/src/itdelatrisu/opsu/objects/curves/CircumscribedCircle.java index 5b09cccb..0e334634 100644 --- a/src/itdelatrisu/opsu/objects/curves/CircumscribedCircle.java +++ b/src/itdelatrisu/opsu/objects/curves/CircumscribedCircle.java @@ -19,12 +19,9 @@ package itdelatrisu.opsu.objects.curves; import itdelatrisu.opsu.ErrorHandler; -import itdelatrisu.opsu.GameImage; import itdelatrisu.opsu.OsuHitObject; -import itdelatrisu.opsu.Utils; import org.newdawn.slick.Color; -import org.newdawn.slick.Image; /** * Representation of a curve along a Circumscribed Circle of three points. @@ -53,9 +50,6 @@ public class CircumscribedCircle extends Curve { /** The start and end angles for drawing. */ private float drawStartAngle, drawEndAngle; - /** The number of steps in the curve to draw. */ - private float step; - /** * Constructor. * @param hitObject the associated OsuHitObject @@ -64,7 +58,6 @@ public class CircumscribedCircle extends Curve { public CircumscribedCircle(OsuHitObject hitObject, Color color) { super(hitObject, color); - // construct the three points this.start = new Vec2f(getX(0), getY(0)); this.mid = new Vec2f(getX(1), getY(1)); @@ -121,7 +114,7 @@ public class CircumscribedCircle extends Curve { this.drawStartAngle = (float) ((startAng + (startAng > endAng ? -HALF_PI : HALF_PI)) * 180 / Math.PI); // calculate points - this.step = hitObject.getPixelLength() / CURVE_POINTS_SEPERATION; + float step = hitObject.getPixelLength() / CURVE_POINTS_SEPERATION; curve = new Vec2f[(int) step + 1]; for (int i = 0; i < curve.length; i++) { float[] xy = pointAt(i / step); diff --git a/src/itdelatrisu/opsu/objects/curves/Curve.java b/src/itdelatrisu/opsu/objects/curves/Curve.java index 59374a14..354c0135 100644 --- a/src/itdelatrisu/opsu/objects/curves/Curve.java +++ b/src/itdelatrisu/opsu/objects/curves/Curve.java @@ -32,7 +32,9 @@ import org.newdawn.slick.Image; */ public abstract class Curve { - protected static float CURVE_POINTS_SEPERATION = 50; + /** Points generated along the curve should be spaced this much apart*/ + protected static float CURVE_POINTS_SEPERATION = 5; + /** The associated OsuHitObject. */ protected OsuHitObject hitObject; @@ -56,7 +58,6 @@ public abstract class Curve { this.y = hitObject.getScaledY(); this.sliderX = hitObject.getScaledSliderX(); this.sliderY = hitObject.getScaledSliderY(); - CURVE_POINTS_SEPERATION = 5; } /** @@ -71,8 +72,7 @@ public abstract class Curve { * @param color the color filter */ public void draw(Color color) { - if ( curve == null){ - System.out.println("draw curve"+this); + if (curve == null){ return; } Image hitCircle = GameImage.HITCIRCLE.getImage(); diff --git a/src/itdelatrisu/opsu/objects/curves/CurveType.java b/src/itdelatrisu/opsu/objects/curves/CurveType.java index e41037b6..b1986ac1 100644 --- a/src/itdelatrisu/opsu/objects/curves/CurveType.java +++ b/src/itdelatrisu/opsu/objects/curves/CurveType.java @@ -37,13 +37,23 @@ public abstract class CurveType { /** The total distances of this Bezier. */ private float totalDistance; + /** + * Returns the point on the curve at a value t. + * @param t the t value [0, 1] + * @return the point [x, y] + */ public abstract Vec2f pointAt(float t); - public void init(float approxlength){ + /** + * Initialize the curve points and distance + * Must be called by inherited classes + * + * @param approxlength an approximate length of the curve + */ + public void init(float approxlength) { // subdivide the curve this.ncurve = (int) (approxlength / 4) + 1; this.curve = new Vec2f[ncurve]; - System.out.println(approxlength+" "+ncurve); for (int i = 0; i < ncurve; i++) curve[i] = pointAt(i / (float) (ncurve - 1)); @@ -53,13 +63,12 @@ public abstract class CurveType { for (int i = 0; i < ncurve; i++) { curveDis[i] = (i == 0) ? 0 : curve[i].cpy().sub(curve[i - 1]).len(); totalDistance += curveDis[i]; - System.out.println("curvedis:"+curveDis[i]); } } /** * Returns the points along the curve of the Bezier curve. */ - public Vec2f[] getCurve() { return curve; } + public Vec2f[] getCurvePoint() { return curve; } /** * Returns the distances between a point of the curve and the last point. diff --git a/src/itdelatrisu/opsu/objects/curves/EqualDistanceMultiCurve.java b/src/itdelatrisu/opsu/objects/curves/EqualDistanceMultiCurve.java index f3dc8bc4..f1959ffb 100644 --- a/src/itdelatrisu/opsu/objects/curves/EqualDistanceMultiCurve.java +++ b/src/itdelatrisu/opsu/objects/curves/EqualDistanceMultiCurve.java @@ -26,7 +26,7 @@ import java.util.LinkedList; import org.newdawn.slick.Color; /** - * Representation of a Bezier curve with equidistant points. + * Representation of multiple curve with equidistant points. * http://pomax.github.io/bezierinfo/#tracing * * @author fluddokt (https://github.com/fluddokt) @@ -48,22 +48,25 @@ public abstract class EqualDistanceMultiCurve extends Curve { } - public void init(LinkedList beziers){ - for(CurveType ct : beziers){ - System.out.println("CT:"+ct); - } + /** + * Initialize the curve points with equal distance + * Must be called by inherited classes + * + * @param curvesList a list of curves to join + */ + public void init(LinkedList curvesList){ // now try to creates points the are equidistant to each other this.ncurve = (int) (hitObject.getPixelLength() / CURVE_POINTS_SEPERATION); this.curve = new Vec2f[ncurve + 1]; float distanceAt = 0; - Iterator iter = beziers.iterator(); + Iterator iter = curvesList.iterator(); int curPoint = 0; - CurveType curBezier = iter.next(); - Vec2f lastCurve = curBezier.getCurve()[0]; + CurveType curCurve = iter.next(); + Vec2f lastCurve = curCurve.getCurvePoint()[0]; float lastDistanceAt = 0; - // length of Bezier should equal pixel length (in 640x480) + // length of Curve should equal pixel length (in 640x480) float pixelLength = hitObject.getPixelLength() * OsuHitObject.getXMultiplier(); // for each distance, try to get in between the two points that are between it @@ -71,15 +74,15 @@ public abstract class EqualDistanceMultiCurve extends Curve { int prefDistance = (int) (i * pixelLength / ncurve); while (distanceAt < prefDistance) { lastDistanceAt = distanceAt; - lastCurve = curBezier.getCurve()[curPoint]; - distanceAt += curBezier.getCurveDistances()[curPoint++]; + lastCurve = curCurve.getCurvePoint()[curPoint]; + distanceAt += curCurve.getCurveDistances()[curPoint++]; - if (curPoint >= curBezier.getCurvesCount()) { + if (curPoint >= curCurve.getCurvesCount()) { if (iter.hasNext()) { - curBezier = iter.next(); + curCurve = iter.next(); curPoint = 0; } else { - curPoint = curBezier.getCurvesCount() - 1; + curPoint = curCurve.getCurvesCount() - 1; if (lastDistanceAt == distanceAt) { // out of points even though the preferred distance hasn't been reached break; @@ -87,8 +90,7 @@ public abstract class EqualDistanceMultiCurve extends Curve { } } } - System.out.println("prefDis:"+prefDistance+" "+distanceAt+" "+lastDistanceAt); - Vec2f thisCurve = curBezier.getCurve()[curPoint]; + Vec2f thisCurve = curCurve.getCurvePoint()[curPoint]; // interpolate the point between the two closest distances if (distanceAt - lastDistanceAt > 1) { diff --git a/src/itdelatrisu/opsu/objects/curves/LinearBezier.java b/src/itdelatrisu/opsu/objects/curves/LinearBezier.java index cb919699..5d2e7a5c 100644 --- a/src/itdelatrisu/opsu/objects/curves/LinearBezier.java +++ b/src/itdelatrisu/opsu/objects/curves/LinearBezier.java @@ -24,7 +24,7 @@ import java.util.LinkedList; import org.newdawn.slick.Color; /** - * Representation of a Bezier curve with equidistant points. + * Representation of Bezier curve with equidistant points. * http://pomax.github.io/bezierinfo/#tracing * * @author fluddokt (https://github.com/fluddokt) @@ -40,9 +40,12 @@ public class LinearBezier extends EqualDistanceMultiCurve { super(hitObject, color); LinkedList beziers = new LinkedList(); + + // Beziers: splits points into different Beziers if has the same points (red points) // a b c - c d - d e f g + // Lines: generate a new curve for each sequential pair // ab bc cd de ef fg - // splits points into different Beziers if has the same points (red points) + int controlPoints = hitObject.getSliderX().length + 1; LinkedList points = new LinkedList(); // temporary list of points to separate different Bezier curves Vec2f lastPoi = null; diff --git a/src/itdelatrisu/opsu/objects/curves/Vec2f.java b/src/itdelatrisu/opsu/objects/curves/Vec2f.java index 7f1cd527..b857ad33 100644 --- a/src/itdelatrisu/opsu/objects/curves/Vec2f.java +++ b/src/itdelatrisu/opsu/objects/curves/Vec2f.java @@ -49,12 +49,22 @@ public class Vec2f { return new Vec2f((x + o.x) / 2, (y + o.y) / 2); } + /** + * Scales the vector. + * @param s scaler to scale by + * @return itself (for chaining) + */ public Vec2f scale(float s) { x *= s; y *= s; return this; } + /** + * Adds a vector to this vector. + * @param o the other vector + * @return itself (for chaining) + */ public Vec2f add(Vec2f o) { x += o.x; y += o.y; diff --git a/src/itdelatrisu/opsu/states/Game.java b/src/itdelatrisu/opsu/states/Game.java index 728f72f7..cede90d4 100644 --- a/src/itdelatrisu/opsu/states/Game.java +++ b/src/itdelatrisu/opsu/states/Game.java @@ -1043,7 +1043,7 @@ public class Game extends BasicGameState { // reset game data resetGameData(); - // load the first timingPoint + // load the first timingPoint for stacking timingPointIndex = 0; beatLengthBase = beatLength = 1; if (!osu.timingPoints.isEmpty()) {