MV bind sprite to map.

Started by chaucer, January 27, 2016, 08:21:06 pm

Previous topic - Next topic

chaucer

Hi everyone(been a while :P) I'm in the process of writing  a plugin, however I've run into a minor problem which seems to be setting me back. basically I've added shadow sprites below the character, however under certain circumstances I'd like the shadow sprite to be bound to a map Y location and not a screen Y location, now I've managed to accomplish this, however I seem to get a minor issue, the shadow seems to bounce around every time the player moves, I'm not exactly sure how to solve this issue though, I'll leave a video and the code used below.

Video of the problem :
https://www.youtube.com/watch?v=LA3_XVk0z2M

Code used:

Spoiler: ShowHide
 
        //------------------------------------------------------------------------------//
//create shadows
//------------------------------------------------------------------------------//
var spriteShadows = Spriteset_Map.prototype.createCharacters;
Spriteset_Map.prototype.createCharacters = function() {
spriteShadows.call(this);
this._characterShadow = [];
for (var i = 0; i < this._characterSprites.length; i++) {
if (this._characterSprites[i]._character._characterName !== '' &&
this._characterSprites[i]._character._characterName !== "Vehicle") {
this._characterShadow[i] = new Sprite();
this._characterShadow[i].bitmap = ImageManager.loadSystem('Shadow1');
this._characterShadow[i].anchor.x = 0.5;
this._characterShadow[i].anchor.y = 0.9;
this._characterShadow[i].z = 10;
this._tilemap.addChild(this._characterShadow[i]);
}
}
};

       //------------------------------------------------------------------------------//
//updates the shadows.
//------------------------------------------------------------------------------//
var updateShadow = Spriteset_Map.prototype.updateShadow;
Spriteset_Map.prototype.updateShadow = function() {
updateShadow.call(this);
var _party = function() {
var list = []
list.push($gamePlayer);
return list;
}
var characters = this._characterSprites;
for (var i = 0; i < characters.length; i++) {
if (!this._characterShadow[i]) {continue;}
var chara = characters[i]._character;
if (chara.characterName() == "") {
this._characterShadow[i].visible = false;
continue;
}
if (chara.constructor === Game_Vehicle) {
continue;
}
                        //used to update the shadows location(which is where the problem seems to be.)
chara.updateShadow();
this._characterShadow[i].x = chara.shadowX;
this._characterShadow[i].y = chara.shadowY;
this._characterShadow[i].z = chara.screenZ()-1;
this._characterShadow[i].opacity = characters[i].opacity;
this._characterShadow[i].visible = characters[i].visible;
}
};


        Game_CharacterBase.prototype.updateShadow = function() {
if (undefined !== this.shadowX && undefined !== this.shadowY && undefined === this._altitude) {
this.shadowX = this.screenX();
if (!this.jumping && !this.falling && !this.climbing) {
this.shadowY = this.screenY();
} else {
                                        //here's where the problem is.
var mapzero = this.screenY() - ((this._y) * $gameMap.tileHeight);
if (!this.jumpLoc) {
this.jumpLoc = this._y
}
                                         //calling this does keep the shadow from moving with the player, however it bounces when the player moves.
                                         //I'm aware of why, unfortunately just not sure how to fix it.
this.shadowY = mapzero + (this.jumpLoc * $gameMap.tileHeight);
}

}
};




KK20

January 27, 2016, 08:55:44 pm #1 Last Edit: January 27, 2016, 08:57:41 pm by KK20
Sounds like the player and shadow are updating on different frames. I've seen issues like this before in RMXP.

The basic idea is that the code looks like this:
# loop
#   change player x/y
#   Graphics.update (redraw the screen)
#   change shadow x/y
# end loop

I'm at least assuming this is what you're referring to by bouncing. It's really hard to tell in the video.

Other Projects
RPG Maker XP Ace  Upgrade RMXP to RMVXA performance!
XPA Tilemap  Tilemap rewrite with many features, including custom resolution!

Nintendo Switch Friend Code: 8310-1917-5318
Discord: KK20 Tyler#8901

Join the CP Discord Server!

chaucer

Apologies, I should have checked the video before uploading, didn't realize it's barely noticeable =/ and I'm fairly certain it isn't the case, as the X and the Y are updating at the same time, and only the Y is bouncing(the X moves perfectly along with the player). I think the problem is that the player's Y is changing in small increments, where as the shadow's Y is changing in larger numbers, I've found if I use the code below it stops the bouncing from occurring, however it bounces when the player is dashing with this same code. I wouldn't mind using this, except it continues moving in that direction(which can be fixed with a simple if statement same with the dashing), the only thing is that if the speed is changed to be something other than the default value(3), then i'd have to write out how it increments depending on each possible speed.

(this.shadowY += 1.5)


I'mfairly certain the solution would be to get how many pixels the player moves each frame, and tell the shadow to update by that as well, I tried using this code below(which I got from updateMovement in game_CharacterBase), and it works, kinda, except any way I try to apply the math it seems to not read the correct location.


// this is the original
this._realY = Math.max(this._realY - this.distancePerFrame(), this._y);
//here's what I tried.
this.shadowY = Math.min(mapzero + (this.jumpLoc * 48), this.jumpLoc * 48)

this code keeps it from bouncing, but the calculation just is off, >.<; I feel I'm just failing the math at this point, but I'm not entirely sure. Apologies hope this reply made sense, been a long day.

KK20

I did something a little different. Since I can't run your code in a clean project, I'm making a lot of assumptions here.

First thing is, in Game_CharacterBase#updateShadow, in the else-block, I did this:

if (this.mapzero === undefined) {
    this.mapzero = (this._y * $gameMap.tileHeight() + 42);
}
this.shadowY = this.mapzero - $gameMap._displayY * $gameMap.tileHeight();

Doing this pinned the shadow at its current location. mapzero is set to wherever the character is currently at in regards to the entire map (Y coordinate multiplied by the tile height). You then subtract that amount by how much the screen has scrolled down, which you use $gameMap._displayY multiplied by tile height.

In the if-block, I just set mapzero = undefined, so when we get back to the else-block, we can recalculate mapzero.
Spoiler: ShowHide



Other Projects
RPG Maker XP Ace  Upgrade RMXP to RMVXA performance!
XPA Tilemap  Tilemap rewrite with many features, including custom resolution!

Nintendo Switch Friend Code: 8310-1917-5318
Discord: KK20 Tyler#8901

Join the CP Discord Server!

chaucer

perfect! this works perfectly, removed the bouncing effect from the map, many thanks bro.

KK20

Of course, if your character is jumping and moving up or down, the shadow needs to follow along accordingly. But it shouldn't be too hard now.

Other Projects
RPG Maker XP Ace  Upgrade RMXP to RMVXA performance!
XPA Tilemap  Tilemap rewrite with many features, including custom resolution!

Nintendo Switch Friend Code: 8310-1917-5318
Discord: KK20 Tyler#8901

Join the CP Discord Server!

chaucer

January 28, 2016, 06:46:09 pm #6 Last Edit: January 28, 2016, 06:51:04 pm by chaucer
:facepalm: Unfortunately even with the help I can't seem to figure out how to make the shadow follow the player if moving up/down, math was never my strongpoint. :/ well I can actually make it follow but I can't seem to make it follow smoothly, it just sort of snaps, I'd been trying since morning and haven't been able to make it work, this was the best I'd gotten it. (placed this inside the else block.)


//checks if this is player, and it's jumping, and pressing up,
if (this === player && this.jumping && this.getInputDirection() === 8) {
                                        //change the landing location if pressing up
                                        // landLoc is just the players _y location created only when player begins a jump.
if (this.landLoc - this.moveSizeY  > this._y) {
this.landLoc -= this.moveSizeY
}
}
if (!this.mapzero || this.mapzero !== (this.landLoc * $gameMap.tileHeight() + 42)) {
this.mapzero = (this.landLoc * $gameMap.tileHeight() + 42);
}
this.shadowY = this.mapzero - $gameMap._displayY * $gameMap.tileHeight();
}


Thought this would work, but I'm still apparently missing something. any help would be greatly appreciated, :D lol this should be the last difficult part of this plugin, so I should be fine after this, I'll keep trying this myself and let you know if I find a solution.

KK20

When the character jumps, its map Y coordinate should not be changing. If that's the case, you can always bound the shadow to be at the character's map coordinates. The real problem is making the character sprite appear to "move up" while not actually moving up. I assume you have some kind of variable that stores how many pixels off the ground the character currently is.

What ultimately affects the drawing location of the sprite? screenY? If so, then you'll need to subtract the result of whatever screenY gives by that variable explained above.

IIRC, being at the top of the screen (this._y = 0) gave my character a screenY of 42. If I were to jump 20 pixels in the air, screenY should equal some value in the range of 22 to 42 inclusive. As such, the shadow sprite cannot rely on the character's screenY anymore, but rather some usage of the character._y * tile_height.

Other Projects
RPG Maker XP Ace  Upgrade RMXP to RMVXA performance!
XPA Tilemap  Tilemap rewrite with many features, including custom resolution!

Nintendo Switch Friend Code: 8310-1917-5318
Discord: KK20 Tyler#8901

Join the CP Discord Server!

chaucer

January 29, 2016, 01:42:10 pm #8 Last Edit: January 29, 2016, 06:57:55 pm by chaucer
Ok, I think I get what you're saying so I tried to apply it, it seems to remove a lot of the "bounce" however it's still quite noticeable, basically here's what I've done I feel I'm on the right track, but just missing something, again. I'll write comments describing what each one is since I've only shown a small snippet, and again much thanks for the help. I'll make sure to notify you if I find the solution before I get a response. xP


//checks if player is pressing up
if (this === player && !this.isMovingY()&& this.jumping && this.getInputDirection() === 8) {
                                                //jumpMove: temporaty variable to apply to the shadows Y.
                                                //this.orgLandLoc: original designated shadow Y location which is only applied once, when the player starts his jump.
                                                //this.landLoc: this is the landing location(does not effect the sprite, only where the player lands on the map.)
jumpMove =  ((this.orgLandLoc * $gameMap.tileHeight()) + 42 - (this._y * $gameMap.tileHeight() + 42)) / 2;
this.landLoc = this.orgLandLoc - ((this.orgLandLoc - this._y) / 2);
}
                               //applying the temporary variable to the shadow location.
                               this.shadowY = this.mapzero - $gameMap._displayY * $gameMap.tileHeight() - jumpMove;



:facepalm: completely missed what you said about $gameMap._displayY that makes it smoother, now I just need to find the right math to apply. lol

Edit: Figured it out :D it may not be the most elegant solution, but it will work.