Simple Standing Picture Plugin

DynamiteRed

Warper
Member
Joined
Nov 22, 2017
Messages
1
Reaction score
1
First Language
English
Primarily Uses
RMMV
DRG_StandingPicture version 1.0
DynamiteRed

Introduction
This is a specialized plugin for displaying a "Standing Picture" image of your player character on the side of the map screen.
It is licensed under the GNU General Public License version 3.
https://opensource.org/licenses/GPL-3.0

Features
  • Simple and easy to use.
  • Supports any game window size.
  • Supports any standing picture image size.
  • Fade in/out animation, and moves from one side to the other so that the player character is not blocked from view.
  • Automatically hides when a map event is running.
  • Can be enabled/disabled/set at will with plugin commands.
  • Independent from the built in ShowPicture RPG Maker command. Uses sprites drawn onto the map layer.

Screenshots



How to Use
  • Place DRG_StandingPicture.js into your plugin folder.
  • Enable the plugin within the RPG Maker MV Editor Plugin Manager
  • Place your standing picture images in the pictures folder. Make sure the file names do not contain spaces and start with the file name prefix specified in the plugin properties. For example (using the default file prefix) "Standing_MainChar.png"
  • In an event, use the "StandingPicEnable" plugin command to enable the standing picture system.
  • In an event, use the "StandingPicSet" plugin command to set the image. Specify the file name without the prefix or file extension. For example, "StandingPicSet MainChar".

Demo
Demo project download.

Script
Filename: DRG_StandingPicture.js
Code:
/*:
 * NOTE: Standing Picture images must be in the img\pictures folder
 *
 * The code contained in this file is licensed under the GNU General Public License version 3.
 * https://opensource.org/licenses/GPL-3.0
 *
 * @plugindesc Displays a character "Standing Picture" image on one side of the map screen.
 * @author DynamiteRed
 *
 * @help Standing Picture plugin by DynamiteRed.
        Version 1.0
        ---------------------------------------

        Standing Picture images must be in your img\pictures folder.
        Make sure your file names start with the "File Name Prefix" plugin
        option, and do not have any spaces or whitespace characters.
        The image can be of any size. They are scaled automatically to fit
        into the game window. This plugin does not use the standard RPG
        maker ShowPicture command, but rather draws the sprite directly onto
        the map screen, so it should be compatible with most plugins. If an
        image file cannot be found, an error is printed to the development
        console and the game will not crash. By default on a new game the
        Standing Picture is disabled.

        Plugin commands:

        StandingPicEnable
        - Enables (Shows) the Standing Picture

        StandingPicDisable
        - Disables (Hides) the Standing Picture

        StandingPicToggle
        - Toggles the visibility of the Standing Picture

        StandingPicSet [Filename minus prefix]
        - Sets the Standing Picture to the given filename. Make sure the image
        file names do not have any spaces or other whitespace characters.

        ---------------------------------------
 *
 * @param File Name Prefix
 * @desc Prefix string that is appended to the start of the file name before loading the image. Surround with quotes ("").
 * Default: "Standing_"
 * @default "Standing_"
 *
 * @param Fade Frames
 * @desc Number of frames it takes for the image to fade in/out.
 * Default: 15
 * @default 15
 *
 * @param Side Swap Distance
 * @desc Distance (in tiles) from the right side of the map where the image will swap sides if the character reaches it.
 * Default: 10
 * @default 10
 *
 * @param Hide On Event
 * @desc If true, the Standing Picture is hidden while an event is running.
 * Default: true
 * @default true
 *
 */

var DRG = DRG || {};

DRG.StandingPic = DRG.StandingPic || {};
DRG.StandingPic.Parameters = PluginManager.parameters('DRG_StandingPicture');
DRG.StandingPic.FilePrefix = JSON.parse(DRG.StandingPic.Parameters["File Name Prefix"]);
DRG.StandingPic.FadeFrames = JSON.parse(DRG.StandingPic.Parameters["Fade Frames"]);
DRG.StandingPic.SideSwapDistance = JSON.parse(DRG.StandingPic.Parameters["Side Swap Distance"]);
DRG.StandingPic.HideOnEvent = JSON.parse(DRG.StandingPic.Parameters["Hide On Event"]);

DRG.StandingPic.CurrentFile = null;
DRG.StandingPic.FadeTime = 0.25;
DRG.StandingPic.Left  = { targetOpacity: 0, sprite: null };
DRG.StandingPic.Right = { targetOpacity: 0, sprite: null };
DRG.StandingPic.SideShown = 1;

(function() {

    // Method aliases
    DRG.StandingPic.GS_Init = Game_System.prototype.initialize;
    DRG.StandingPic.Scene_Map_UpdateMain = Scene_Map.prototype.updateMain;
    DRG.StandingPic.Sprite_Map_CreateLowerLayer = Spriteset_Map.prototype.createLowerLayer
    DRG.StandingPic.executeMove = Game_Player.prototype.executeMove;
    DRG.StandingPic.Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;

    // Game System Init Override
    Game_System.prototype.initialize = function()
    {
        DRG.StandingPic.GS_Init.call(this);

        this._DRG_StandingPic_CurrentImg = "";
        this._DRG_StandingPic_Hide = true;
    };

    // Called every frame as long as the map screen is active
    // Updates the fade opacity of the standing pic
    Scene_Map.prototype.updateMain = function() {
        DRG.StandingPic.Scene_Map_UpdateMain.call(this);

        // Update standing picture fade
        DRG.StandingPic.UpdateFade();
    };

    // Called when the player takes a step
    // Updates which side the standing picture is displayed
    Game_Player.prototype.executeMove = function(direction) {
        DRG.StandingPic.executeMove.call(this, direction);

        DRG.StandingPic.UpdateSide();
    };

    // Called each time the map screen object is recreated, which is extremely often for some reason.
    // That doesn't seem very efficient, RPG Maker devs!
    Spriteset_Map.prototype.createLowerLayer= function() {
        DRG.StandingPic.Sprite_Map_CreateLowerLayer.call(this);


        if (typeof $gameSystem._DRG_StandingPic_CurrentImg == 'undefined' || $gameSystem._DRG_StandingPic_CurrentImg == null)
        {
            $gameSystem._DRG_StandingPic_CurrentImg = "";
        }

        if (typeof $gameSystem._DRG_StandingPic_Hide == 'undefined' || $gameSystem._DRG_StandingPic_Hide == null)
        {
            $gameSystem._DRG_StandingPic_Hide = true;
        }

        this.createStandingPictureSprites();
        DRG.StandingPic.UpdateImage();
        DRG.StandingPic.UpdatePosition();
        DRG.StandingPic.UpdateSide();

        DRG.StandingPic.Left.opacity = 0;
        DRG.StandingPic.Right.opacity = 0;

        // Add standing pic sprites to map layer
        this.addChild(DRG.StandingPic.Left.sprite);
        this.addChild(DRG.StandingPic.Right.sprite);

        console.log("Standing Picture Map Layer Created.");
    };

    // Creates the map layer sprite objects if they have not already
    // been created.
    Spriteset_Map.prototype.createStandingPictureSprites = function()
    {
        if (typeof DRG.StandingPic.Left.sprite == 'undefined' || DRG.StandingPic.Left.sprite == null)
        {
            DRG.StandingPic.Left.sprite = new Sprite();
        }

        if (typeof DRG.StandingPic.Right.sprite == 'undefined' || DRG.StandingPic.Right.sprite == null)
        {
            DRG.StandingPic.Right.sprite = new Sprite();
        }
    };

    Game_Interpreter.prototype.pluginCommand = function(command, args) {
        DRG.StandingPic.Game_Interpreter_pluginCommand.call(this, command, args);
    
        command = command.toLowerCase();

        if (command === 'standingpicenable')
        {
            console.log("Plugin Cmd: " + command);
            $gameSystem._DRG_StandingPic_Hide = false;
        }
        else if (command === 'standingpicdisable')
        {
            console.log("Plugin Cmd: " + command);
            $gameSystem._DRG_StandingPic_Hide = true;
        }
        else if (command === 'standingpictoggle')
        {
            console.log("Plugin Cmd: " + command);
            $gameSystem._DRG_StandingPic_Hide = !$gameSystem._DRG_StandingPic_Hide;
        }
        else if (command === 'standingpicset')
        {
            console.log("Plugin Cmd: " + command);
            if (args.length > 0) {
                $gameSystem._DRG_StandingPic_CurrentImg = args[0];
                DRG.StandingPic.UpdateImage();
            }
        }
    };

    // Returns the full file name of the current Standing Picture
    // including the file name prefix if the file exists. Otherwise
    // returns null.
    DRG.StandingPic.getFileName = function()
    {
        var picID = "";
        var fileName;

        if ($gameSystem._DRG_StandingPic_CurrentImg === "") {
            console.log("Warning: No standing picture image is set.");
            return null;
        }

        fileName = this.FilePrefix + $gameSystem._DRG_StandingPic_CurrentImg;

        if (this.PictureExists(fileName)) {
            return fileName;
        }
        else
        {
            console.log("Warning: Unable to load standing picture image (File not found): " + fileName);
            return null;
        }
    };

    // Updates the position of the left and right standing picture
    // sprite objects on the map screen
    DRG.StandingPic.UpdatePosition = function()
    {
        var leftSprite = this.Left.sprite;
        var rightSprite = this.Right.sprite;

        leftSprite.x = 0;
        leftSprite.y = 0;
        leftSprite.anchor.x = 0;
        leftSprite.anchor.y = 0;

        rightSprite.x = Graphics.width;
        rightSprite.y = 0;
        rightSprite.anchor.x = 1.0;
        rightSprite.anchor.y = 0;
    };

    // Scales the standing picture image so that it is the same height as the
    // game window
    DRG.StandingPic.UpdateScale = function()
    {
        var leftSprite = this.Left.sprite;
        var rightSprite = this.Right.sprite;
        var bitmap = leftSprite.bitmap;

        // Scale image if it is not the same height as the
        // game window
        if (bitmap.height != Graphics.height)
        {
            var scale = Graphics.height / bitmap.height;
            var width = Math.round(bitmap.width * scale);
            var height = Graphics.height;

            // Create a new bitmap that is the preferred size, and blit the standing picture image
            // onto it
            var resizedBitmap = new Bitmap(width, height);
            resizedBitmap.bltImage(bitmap, 0, 0, bitmap.width, bitmap.height, 0, 0, width, height);

            // Update sprite object bitmap references
            leftSprite.bitmap = resizedBitmap;
            rightSprite.bitmap = resizedBitmap;

            this.UpdatePosition();

            console.log("Standing Picture Resized.");
        }
    };

    // Checks the player position and enables the approprate
    // standing picture side
    DRG.StandingPic.UpdateSide = function()
    {
        var _playerX = $gamePlayer.x;
        var _mapWidth = $gameMap.width();
        var distFromRight = _mapWidth - _playerX;

        if (distFromRight < this.SideSwapDistance)
        {
            this.Left.targetOpacity = 255;
            this.Right.targetOpacity = 0;

        }
        else
        {
            this.Left.targetOpacity = 0;
            this.Right.targetOpacity = 255;
        }
    };

    // Updates the opacity of both standing pictures (left and right)
    DRG.StandingPic.UpdateFade = function()
    {
        var leftSpriteObj = this.Left;
        var rightSpriteObj = this.Right;
        var fadeStep = this.GetFadeStep(); // Get opacity offset

        // Fade out standing picture if hidden/event is running
        if ($gameSystem._DRG_StandingPic_Hide || ($gameMap.isEventRunning() && DRG.StandingPic.HideOnEvent))
        {
            leftSpriteObj.sprite.opacity -= fadeStep;
            rightSpriteObj.sprite.opacity -= fadeStep;

            return;
        }

        // Update sprite fade
        if (leftSpriteObj.sprite.opacity < leftSpriteObj.targetOpacity) {
            leftSpriteObj.sprite.opacity += fadeStep;
        }
        else if (leftSpriteObj.sprite.opacity > leftSpriteObj.targetOpacity) {
            leftSpriteObj.sprite.opacity -= fadeStep;
        }

        if (rightSpriteObj.sprite.opacity < rightSpriteObj.targetOpacity) {
            rightSpriteObj.sprite.opacity += fadeStep;
        }
        else if (rightSpriteObj.sprite.opacity > rightSpriteObj.targetOpacity) {
            rightSpriteObj.sprite.opacity -= fadeStep;
        }
    };

    // Returns the opacity difference for one frame of fading
    DRG.StandingPic.GetFadeStep = function()
    {
        return 255 / DRG.StandingPic.FadeFrames;
    };

    // Loads the standing picture image file and updates
    // the map sprite objects
    DRG.StandingPic.UpdateImage = function()
    {
        var standingPicFile = this.getFileName();
        if (this.CurrentFile == standingPicFile) { return; }

        if (standingPicFile != null) {
            var bitmap = ImageManager.loadPicture(standingPicFile)

            this.Left.sprite.bitmap = bitmap;
            this.Right.sprite.bitmap = bitmap;

            bitmap.addLoadListener(this._onBitmapLoad.bind(this));

            this.CurrentFile = standingPicFile;
            console.log("Standing Picture Updated: " + standingPicFile);
        }
        else {
            this.Left.sprite.bitmap = null;
            this.Right.sprite.bitmap = null;
        }
    };

    // Callback for when the image finishes loading.
    // This ensures the standing picture image is resized to the game window height
    DRG.StandingPic._onBitmapLoad = function()
    {
        this.UpdateScale();
    };

    // Checks if the given picture file name is in the img/pictures folder
    DRG.StandingPic.PictureExists = function(picture)
    {
        var fileName = picture + ".png";
        var path = require('path');
        var base = path.dirname(process.mainModule.filename);
        path = path.join(base, 'img/pictures/') + fileName;

        var fs = require('fs');
        if (fs.existsSync(path))
        {
            return true;
        }
        else
        {
            return false;
        }
    };

})()

//=============================================================================
// End of File
//=============================================================================
Credit and Thanks
- Created by DynamiteRed
 

Attachments

Last edited:
  • Like
Reactions: SMF

Super-User

Villager
Member
Joined
Apr 11, 2019
Messages
21
Reaction score
5
First Language
Chinese
Primarily Uses
RMVX
(deleted)
 
Last edited:

Users Who Are Viewing This Thread (Users: 0, Guests: 1)

Latest Threads

Latest Posts

Latest Profile Posts

Stream will be live shortly! Going to do another art stream tonight so that I can finish my Fauna Focus piece~ Feel free to drop by!
Humans are fallible creatures, we all know that. It's when we're forced to look at ourselves that we start to disagree. :p
Expectation: Working on boss battle.
Reality: "Look at how awful are these code and database organization. Let me clean this mess", *yet, casually adding more modules that I have no idea if I would use it later*
Trying to learn to read Japanese so I read my manga. I like to buy them without all the edits made during translation.
The only thing getting me through today so far is coffee. And lots of it.

Forum statistics

Threads
97,852
Messages
947,384
Members
129,079
Latest member
DerLaPux
Top