Nonameded

Veteran
Veteran
Joined
Jan 10, 2019
Messages
67
Reaction score
9
First Language
not english
Primarily Uses
N/A

caethyril

^_^
Global Mod
Joined
Feb 21, 2018
Messages
2,824
Reaction score
2,162
First Language
EN
Primarily Uses
RMMZ
Yes, by default characters don't stop at non-integer coordinates. You can still move in a circle, but it won't look very smooth because character sprites move in straight lines between tiles. Here are some ideas, though~

Pictures​

You might be able to fake it, e.g. make a long transparent picture with a visible shape at one end. Then use the Rotate Picture command to make it spin around its origin. It should look like the shape is travelling in a circle. This has limitations:
  • The shape will also rotate;
  • Pictures are positioned relative to the screen, not the map.
Things get complicated if you want to do this with map characters...

Character position hack​

A relatively simple, but sort of hacky, way to do this visually is:
  • Give the character Frequency = 5 (Highest), i.e. 1 move command per frame.
  • Give the character a move route with 1 Script command something like this:
    JavaScript:
    this._t = (this._t || 0) + 1; this._x = this._realX = 9 + 5 * Math.cos(Math.PI * this._t / 300); this._y = this._realY = 7 + 5 * Math.sin(Math.PI * this._t / 300);
This repositions the character each frame.

However, non-integer coordinates basically break RMMV's default collision checks. If you need to check collisions, you can manually check the player's position each frame and start the event if necessary, e.g. add this to the end of the move route Script:
JavaScript:
if ($gamePlayer.pos(Math.round(this.x), Math.round(this.y))) this.start();
I.e. "if the player is on my tile, start my event".

Pixel movement plugin​

You may be able to find a pixel-movement plugin (maybe you are already using one) to solve the "non-integer coordinates" problem. It might even have built-in circular movement options! If not, you'd need to use trigonometry (see the example in the spoiler above) to decide where to move.
 

Nonameded

Veteran
Veteran
Joined
Jan 10, 2019
Messages
67
Reaction score
9
First Language
not english
Primarily Uses
N/A
  • JavaScript:
    this._t = (this._t || 0) + 1; this._x = this._realX = 9 + 5 * Math.cos(Math.PI * this._t / 300); this._y = this._realY = 7 + 5 * Math.sin(Math.PI * this._t / 300);
Sounds perfect.
It's working perfectly.
However, can you tell me how to modify this code to control coordinates, range of motion, direction, and speed?


Thank you in advance.
 

caethyril

^_^
Global Mod
Joined
Feb 21, 2018
Messages
2,824
Reaction score
2,162
First Language
EN
Primarily Uses
RMMZ
Great! Here's a more in-depth explanation~

JavaScript:
this._t = (this._t || 0) + 1;
This sets/increases the time variable (stored as a new property on the event). The motion starts at this._t = 0 and increases by 1 each frame. You can swap the 0 for a different positive number to change where on the circle that the event starts its motion.

JavaScript:
this._x = this._realX = 9 + 5 * Math.cos(Math.PI * this._t / 300);
this._y = this._realY = 7 + 5 * Math.sin(Math.PI * this._t / 300);
These lines set the position of the event. Together they define a circle with:
  • Centre: (x, y) = (9, 7) on the map.
  • Radius: 5 tiles.
  • Angular speed: π/300 radians per frame (i.e. 600 frames per full circle).
    This also controls the direction: make it negative to go the other way.

At time this._t = 0 (i.e. starting position):
  • x = 9 + 5 * 1 = 14
  • y = 7 + 5 * 0 = 7
Remember that RPG Maker MV uses a left-hand coordinate system:
  • +x goes right ->
  • +y goes down ↓
 

Nonameded

Veteran
Veteran
Joined
Jan 10, 2019
Messages
67
Reaction score
9
First Language
not english
Primarily Uses
N/A
Angular speed: π/300 radians per frame (i.e. 600 frames per full circle).
This also controls the direction: make it negative to go the other way.
What happens if x,y have different speeds?
I'm testing it, but I don't understand.
 

caethyril

^_^
Global Mod
Joined
Feb 21, 2018
Messages
2,824
Reaction score
2,162
First Language
EN
Primarily Uses
RMMZ
Then the motion will not be circular (except perhaps in some very contrived situation). For circular motion, x² + y² must stay constant: having different speeds breaks this condition. The actual curve produced will depend on the ratio of x and y speeds.

A couple of examples:
  • Ellipse: make the x and y radius values different.
  • "8" curve: make the x speed double the y speed.
If you want more details, I suggest looking up parametric curves. :kaohi:
 
Last edited:

imcatman

Veteran
Veteran
Joined
Apr 12, 2019
Messages
38
Reaction score
13
First Language
German
Primarily Uses
RMMV
This is very nice.
I was able to make it look like a fairy moving around the player.
Also, I was able to move the event circle into an ellipse by changing it to a value like this._realX = 9 + 5 this._realY = 7 + 3 instead of a perfect circle.
However, how should I set it to draw an elliptical orbit diagonally as shown in the image below?
Plot-of-the-elliptical-orbit-in-the-r-1-r-2-plane-corresponding-to-Eq-82-with-e.png
 

caethyril

^_^
Global Mod
Joined
Feb 21, 2018
Messages
2,824
Reaction score
2,162
First Language
EN
Primarily Uses
RMMZ
@imcatman - that looks like a 45° (π/4 radians) rotation clockwise, i.e. +π/4 in RMMV's coordinate system. To get there, you can apply a rotation transform to the original equations:
  • Positive rotation matrix:
    cos(π/4) -sin(π/4)
    sin(π/4) cos(π/4)
  • This is a nice example angle, because the sine and cosine are equal:
    sin(π/4) = cos(π/4) = 1/√(2) (1 divided by the square root of 2)​
Applying the rotation to simple elliptical motion (matrix multiplication):
  • x = X + A cos(πωt) -> x = X + (A cos(πωt) - B sin(πωt)) / √(2)
  • y = Y + B sin(πωt) -> y = Y + (A cos(πωt) + B sin(πωt)) / √(2)
Or, in context:
JavaScript:
this._x = this._realX = 9 + (5 * Math.cos(Math.PI * this._t / 300) - 3 * Math.sin(Math.PI * this._t / 300)) / Math.sqrt(2);
this._y = this._realY = 7 + (5 * Math.cos(Math.PI * this._t / 300) + 3 * Math.sin(Math.PI * this._t / 300)) / Math.sqrt(2);
The origin coordinates are unaffected because the rotation happens around the origin.

Edit: minor corrections! I was getting confused about the left-hand coordinate system. :kaoslp:

Also, note that you can use $gamePlayer._realX and $gamePlayer._realY instead of fixed values like 9 and 7 if you want it to stay orbiting the player.
 
Last edited:

ShadowDragon

Realist
Veteran
Joined
Oct 8, 2018
Messages
4,490
Reaction score
1,720
First Language
Dutch
Primarily Uses
RMMV
this is so complicated, but really nice what you can do in the engine.

you really should create a minor demo of it of those 2 examples (if you dont mind) so I can store it.
not sure if I can use it or have a purpose for it.

but maybe something around it to avoid obstacles that you cannot hit the event with.
but you are a beastin in this kind @caethyril , you know your stuff around this.

I dont understand how "cos" and "sin" works in math (so dont explain).
but still it's amazing, I adore you :) (while I try to learn JS more, also for solution you provided to others.
I never knew that or how to event this kind of thing.
 

caethyril

^_^
Global Mod
Joined
Feb 21, 2018
Messages
2,824
Reaction score
2,162
First Language
EN
Primarily Uses
RMMZ
I just wrote up a more accessible version of the move route script including rotation, in case it helps:
JavaScript:
var t0 = 0, ox = 9, oy = 7, rx = 2, ry = 5, Tx = 300, Ty = 300, ro = 120; this._t = (this._t || t0) + 1; this._x = this._realX = ox + rx * Math.cos(Math.PI * ro / 180) * Math.cos(2 * Math.PI * this._t / Tx) - ry * Math.sin(Math.PI * ro / 180) * Math.sin(2 * Math.PI * this._t / Ty); this._y = this._realY = oy + rx * Math.sin(Math.PI * ro / 180) * Math.cos(2 * Math.PI * this._t / Tx) + ry * Math.cos(Math.PI * ro / 180) * Math.sin(2 * Math.PI * this._t / Ty);
This defines some values at the start so it is easier to edit:
JavaScript:
var t0 = 0, ox = 9, oy = 7, rx = 2, ry = 5, Tx = 300, Ty = 300, ro = 120;
Description:
  • t0 = starting time. Affects where on the curve that the motion will begin.
  • ox, oy = origin (tiles). The centre/focal point of the curve.
  • rx, ry = radius (tiles). For a circle, rx = ry.
  • Tx, Ty = period (frames). I.e. how long it takes to get back to the start point. Make these values negative to move anticlockwise instead.
  • ro = rotation (degrees). Rotates the entire path clockwise around its origin.
Since this is a script call, you can use formulae for the values if you like, e.g. for something that orbits the player:
  • ...ox = $gamePlayer._realX, oy = $gamePlayer._realY...
As mentioned before, this workaround breaks RMMV's default collision system for that event. If necessary, you can manually check the player's location and start the event, e.g. by adding something like this to the end of the big line of script:
JavaScript:
if ($gamePlayer.pos(Math.round(this._realX), Math.round(this._realY))) this.start();
Given how involved the script call is, I wouldn't recommend using it a lot on the same map. :kaoswt2:

Here's a demo project with a few examples for anyone who's interested:
Remember to extract the files from the archive before trying to open the project in RPG Maker MV. :kaophew:
 

ShadowDragon

Realist
Veteran
Joined
Oct 8, 2018
Messages
4,490
Reaction score
1,720
First Language
Dutch
Primarily Uses
RMMV
I checked the demo out quickly, but the 4 looks stunning, just amazing,
not exacly sure about the tile around the player, but I dive later deeper into it
to see how every works together,amazng job and a huge thank you for the mini demo.

this helps me out alot in case I see fit for my game somewhere and increase time,
which I need to lower to faster speed.

thank you again for the demo, it helps alot to understand for many people, rather than keep
asking it.

it can have other purposes like above player and a moving light circling in a bigger circle.
but a great start.

your the best @caethyril =)
 

imcatman

Veteran
Veteran
Joined
Apr 12, 2019
Messages
38
Reaction score
13
First Language
German
Primarily Uses
RMMV
JavaScript:
this._x = this._realX = 9 + (5 * Math.cos(Math.PI * this._t / 300) - 3 * Math.sin(Math.PI * this._t / 300)) / Math.sqrt(2);
this._y = this._realY = 7 + (5 * Math.cos(Math.PI * this._t / 300) + 3 * Math.sin(Math.PI * this._t / 300)) / Math.sqrt(2);

@caethyril

Thanks for explaining.
This is great!
Diagonal oval launch worked fine in your script call.
I never thought that RPGMV could do this without a plugin.
I haven't caught up with it yet, but I'll play around with the contents of this demo to understand how circular motion works.
 

Latest Threads

Latest Posts

Latest Profile Posts

Working on a Premium version of my minimap plugin that will have advanced functionalities such as drawing a Terrain map based completely on the users tilesets, whatever they may be, and drawing minimap radar icons automatically based on texture of the event the note is applied to.
Psttt come look, this is the secret technique to tenderizing steaks, it makes it extra beefy. :rwink:

pixeldailyaxemeatsheild.gif
#screenshotsaturday update, featuring vaporwave angels lol
Lil' sketch I drew of Nico di Angelo :)
The spooky boi himself ♥
Nico sketch by Artemis Yates.jpg

Forum statistics

Threads
115,852
Messages
1,093,440
Members
151,057
Latest member
Mikuhighness
Top