KAZESUI'S PROFILE

Doing Super Programming
on Super Computers
for Super Performance
The Curse of Cpt. Lovele...
Nautical-themed cephalopod-pirate-based action-shmup.

Search

Filter

[RM2K3] DynRPG Compiling Error

author=McBick
So basically for manipulating Rm2k3 objects I should, and need to, use std map, but for integer arrays I should use vectors? I thought vectors could store other values such as with std::vector<Rpg::Image> myImage, but I guess not.

both std::map and std::vector can store any type of object (as defined by what you put in the <>). Accessing the entries of a std::vector is only done with integers, while with std::map you can access them with almost anything.

std::map<std::string, std::string> example;
example["foo"] = "bar";

This is possible with std::map but not with std::vector. With std::vector it's easy to do this however

std::vector<RPG::Image*> images;

...

for(int i = 0; i < images.size(); i++)
{
    RPG::screen->canvas->draw(x[i], y[i], images[i]);
}

This is not something which is guaranteed to work if you're using std::map, and if you use it this way, it might work, but it will look a bit weird (but the concept ought to still work).


author=McBick
When I get a compiling error with strings it always refers to them as chars or const chars despite only using static std string and std string variables, so I thought that maybe they were the same.

std::string most likely stored the actual string as a char* so that could be a possible reason for it. I have to admit, I haven't been actively coding in C++ for a rather long time now, so I don't remember what compile errors ought to look like when it comes to std::string any longer. As mentioned, they are similar, but not exactly the same. A simple char* is a bit more bare-bones than std::string.

author=McBick
For global variables I must use static or const outside the main() and all functions correct? That is what I have been doing anyways. I've also used static variables inside functions, so it only initiates the value once and can be changed within the function later if need be.

Nope, there is no need to declare global variables as static. The reason to do so would be to make sure that the global variable is only global to the file in which it is defined only, which is only of concern if you're actually compiling more than one file, or are building a code base which is meant for others to expand upon (with more files). If this is not the case, there is no need to declare any of these variables as static. At least that's what I read. I've never used static in this way myself. File also likely means .cpp file here, not .h file, as these are kind of added to the .cpp file at compile time.
Bottom line is still the same though, you probably won't need them for global variables.

It's also not necessary to declare anything as const, unless you want it to be unchangeable. There are very good reasons for using const, but I don't believe it is something you need to worry about at this point. The biggest thing you need to know is that there will be variables which are given as const which will throw a compile error if you try to alter their values, meaning if you want to manipulate those values, you need to make a copy of that variable first (one which is not const).

author=McBick
For arrays why does something like int N = RPG::monsters.size(), not work? I am trying to find a way to easily keep track of the size of certain rm2k3 arrays without using a loop every time I need their array size. As it is now I have created a function just to count array sizes as I am tired of constantly using loops every time I need the array size.

I can't give you the exact syntax, but it ought to be something along the lines of
RPG::dbMonsterGroups[group_id]->monsterList->count()

It is possible that you need to substitute the -> with a . at the last one, and it's possible there is something else I'm forgetting. As mentioned, haven't done much C++ in quite a while, and haven't done any DynRPG in even longer. Also note that this value should be the number of enemies in the group as given by the database, not the monsters still alive in the battle. I didn't see any obvious reference to the number of currently living monsters.

[RM2K3] DynRPG Compiling Error

author=McBick
@Kazesui
Could you explain the differences of std::map and vector? From what I understand they can both be used for the same thing? So when would I use one over the other?

For instance what is the difference or limitation between these two types of arrays, if any?
std::map<int, RPG::Image*> images
//and
std::vector<RPG::Image*> images


Also what is the difference between these arrays?
const char* myText[3] = {A, B, C};
//and
static std::string myText[3] = {A, B, C};


Both std::map and std::vector store data, so they can be used for the same thing in terms of accessing and using the data. Where there's a relevant difference in terms of how the access is done and how you add and remove data.

std::vector is in essence a simple array. You generally add elements with the "push" method, and access them with square brackets and the integer index. Note that these integers here will always be contiguous since the memory is listed from 0 to n, with n being the size of the array (n is excluded from the loop since the last element will be at position n - 1).

removing single elements from std::vector is considered slow, and should be avoided unless it is at the end of the array... but this will likely not matter too much within the context of usage for DynRPG. I would be very surprised if you managed to run into performance issue because of this.

std::map is a binary tree which store two values, the "key" and the "value", and is sorted on the former. Important difference here is that you do not need to use integers as key values, and they do not need to be contiguous. e.g. you could have an RPG::Image* associated with the keys 1, 3, 42, and that would be perfectly fine. You could also use "battler1", "battler2", "hero1" as keys, and it would give you an easier time manipulating specific pictures as you don't have to remember the integer index assigned to them. If you don't need to manipulate individual images much, this is not really needed.

There are some performance considerations here, where std::vector will likely outperform std::map if you don't manipulate the images and you just want to show all them in a specific order (with the order being easier to enforce in an std::vector), but ultimately, you can use what you're comfortable with as non of these performance issues are likely going to impact you in a meaningful way at this stage. The code will be simpler for std::vector if it provides all the functionality you need, and that would be my incentive to use it.

As an example, for the text plugin however, I also used std::map, because I think it's easier for the user to give specific names to their images and allow them to manipulate each individually. This is of course different if the plugin is for private use, or supposed to contain a full system using images rather than giving users control of the individual images.

as for the differences of your strings.
Using char* for strings is the C way of doing things, while std::string is the C++ way of doing things.
char* is just a pointer to an array of 8bit values used to represent characters (or letters and symbols if you'd like), which under normal circumstances should be terminated with "\0" to signify the end of the string.

std::string is a class which holds a similar array, but also provides some more functionality out of the box by holding methods which can operate on the string directly.

For a lot of intents and purposes, they are quite similar in terms of behavior as strings, and the biggest difference is in terms of how you manipulate them, which generally require C libraries for char* strings, and C++ libraries for std::string.

const and static are more generic and don't deal with text variables specifically but operate on mutability and scope. const implies that you're not allowed to change the following variable, though special care must be taken when using pointers as where you place the const relates to whether it's the address stored in the pointer you're not allowed to change, or the contents at the end of that address. There's a lot of nuance here, so further reading is probably best to properly understand it.

static is used in a couple of ways in C++.
You can use static in a class member to make sure that all objects created of that class will share the value of this member variable, or a method might be belonging to the class itself rather than objects instantiated with it (like RPG::Image::create() which does not belong to a single RPG::Image object, unlike with RPG::Window::create() which does belong to the object, at least as defined in the documentation).

It can also be used within a function to add persistence to that variable without being declared initially in global scope.

int foo()
{
    static int counter = 0;
    counter = counter + 1;
    return counter
}

the "counter" variable in this case would always return 1 if not for the static keyword. The static keyword makes this variable instantiated the first time the function is called, and reused whenever this function is called again, meaning the second time you would call this function, it would return "2". This does not mean that you can use this variable as you'd like outside of this function however. In other words, statics make the variable not be "destroyed" upon leaving a function, but is not quite the same as making the variable global.

[RM2K3] DynRPG Compiling Error

author=McBick
I tried this too, but it gives the same error. I think the issue is the destructor in the class, but I am not familiar with how destructors work, so I could be wrong. I may just be better off creating my own window function as nothing I have tried works, not to mention I would have more customization options if I make my own.

I experimented with the RPG::battleData::navLevel and I have discovered some things. If I set it to 0 first, I will then be allowed to change it to whatever value I want, but this ends up doing nothing if I set it to RPG::BNAV_IN_COMMAND_WINDOW, so useless. Also this is the exact error I receive, "Access violation in module "RPG_RT.exe" in with address 004BFF9E and offset 00000034 of type Read occured". If I understand correctly the address is to RPG::battleData and the offset is RPG::battleData->navLevel, but I'm not sure why it is a Read type violation.

Is there a way to force input? I could do that instead, but I don't see a way to force input in DynRPG.


As mentioned, it could be because it the only way RPG Maker expects to be able to transition from one state to another involves processing key inputs. It's quite possible that they allocate a pointer of some sort internally in case the player acts upon a nav position, which is not always valid. Again, I believe it's safe to assume this particular member variable does not expect to be messed with. And no, the address of BattleData should be 0x4CDD38 not 0x4BFF9E (note, prefixing numbers with 0x implies that the number following it is given in hexadecimals), at least based on the headerfile. Either way, it boils down to it trying to access something it shouldn't, for reasons which will be hard to determine without the source code.

There are ways to simulate key presses with C++ code, but it's very hacky and I would not really recommend this as a solution. Apart from that I'm also not sure how to force the change.

[RM2K3] DynRPG Compiling Error

First of all, thank you for using the code tags. It makes it so much easier to read the code.

author=McBick
So if I am to understand correctly using the map operator is in fact allocating the proper memory for me? I just want to make sure. I have changed my code to this for images.


std::map is not an operator, but rather a "data structure", which is an umbrella term for objects focused on storing data. In particular, map is a binary tree, to quickly find the value associated with a given key. In your case, the integers are the key and the pointers are the value.
std::map dynamically allocate the necessary memory as needed, so your RAM is pretty much what defines the limit. In other words, nothing you need worry about. As long as you keep it global it should be fine as is.

If you don't need direct access to the various pointers, there are also other alternatives you could use, like std::list or std::vector.
std::vector resembles a normal array which you can call with the square bracket operator, but dynamically increases it's size as needed (assuming you use the right methods).
If you're looking at learning a little bit of C++, having a quick look at all three of these could be a good start as they are very common, and generally useful. If you simply want to draw all pictures you've made, it could be easier to just put them all in a std::vector and then iterate over all the elements in the array.

For all of these, you do not need to worry about the memory of the data structures themselves... but if they contain pointers to dynamically allocated memory, (like the RPG::Images), you still need to care for those yourself.

author=McBick
How can that be? I thought variables are an address in memory, so if I use the same variable it is using the same memory? Otherwise how would you manipulate memory? How can I ensure I am using the same memory then?


This was specifically related to the code you put before you added the if test for your image. With this if statement, this should work a lot better
That said, I want to highlight something about that if statement of yours as well, i.e. the
if(!myImage[img])

What it does, is not not to check if there is an image in std::map myImage, but rather if there is a key with the same value as "img" in myImage. The reason this is relevant is because it doesn't say anything about whether the RPG::Image* has been allocated or not. This should not be a problem right now, but something to keep in mind when you start removing images because you're transitioning from battle to non battle and back. The best thing to do is probably to make sure to completely empty myImage inbetween these, while remembering to destroying each instance of RPG::Image first.

author=McBick
If I create new RPG::class objects will I have to destroy them with the onExit function or will they terminate themselves?


I'm assuming you're referring to RPG::Image and RPG:Window, because as mentioned, in general you should not make new RPG::class objects outside a few exceptions. As for terminating themselves, effectively, they should. Once a program terminates, it will generally free up the heap and stack memory it was using, but that's more of an implicit cleanup rather than a real one, but you should be fine even if you don't use onExit to clean stuff.
You might want to consider doing some cleanup still for whenever there are scene changes still though.

author=McBick
By any chance do you know how the Window class/functions operate?

This was added with the updated DynRPG version, which I never got around to use. Also, I never really dealt much with stuff related to the battle scene, as I personally wasn't very interested in it.
What I can say though is that to try and assign values to most of the RPG classes will usually lead to bad things in my experience. Exactly why, is hard to say as I would like to see the source code of RPG Maker for that, but for the navLevel thing, it could be because it expects the state to be RPG::BNAV_IN_PARTY_WINDOW, and from the perspective of RPG Maker, the only way to transition from this window to another, is to do a certain action (involving selecting a certain option), and the rest of the code operates on the assumption that this holds true. When the state is suddenly changed without going through the normal process of changing the state, the variables of this new state might not have been initialized properly and thus leads to what is referred to as a segfault in c++ lingo, i.e. trying to access something you should not have access to because you either messed up the indexing or you didn't assign / allocate / create it yet.

I guess there are some parameters which you can change the value of (like the ATB gauge from the sound of it), but this should be not be the expectation when it comes to the various members of the various classes.

author=McBick
std::map<int, RPG::Window> myWindow;
void createWindow()
    {
        myWindow[0].create(64, 64, 120, 96, false);
    }

This function results in a memory read error, "A violation in C08BC35D occured at C08BC35D with Read".


You made a mistake in there. When you write
myWindow[0].create(64, 64, 120, 96, false);
it assumes you've already instantiated an object of the Window class with 0 as a key

std::map<int, RPG::Window> myWindow;
void createWindow()
{
    myWindow[0] = RPG::Window()
    myWindow[0].create(64, 64, 120, 96, false)
}


I can't guarantee that the code above will work, as I don't have a good way of testing it, and as mentioned, I've never worked with the RPG::Window class, but this would probably be how you should be doing it. It assumes you're allowed to instantiate it like this rather than like a pointer, which generally wasn't allowed with any classes I used in DynRPG (Not saying it isn't correct, just pointing out a potential cause in case it doesn't work).

[RM2K3] DynRPG Compiling Error

The "new" operator is an essential part of the language and is not really something frowned upon. If you've read the DynRPG manual, you might have gotten this idea since it explicitly tells you not to use new with any of it's classes, which is very correct but for different reasons. Don't try to use "new" on any of the DynRPG classes, you'll probably break things.

That said, I imagine you can get away without using this operator, since it's often implicitly called for you. RPG::Image::create() somewhere along the lines of function calls does put this memory on the heap, while returning a pointer to this memory. std::map also allocated part of it's memory dynamically, most likely with the new operator. It's just that it does it all for you so you do not have to think about it. The compiler is not the one which do these. This is in fact a weakness of stuff put on the stack, as it needs to know exactly how much memory needs to be allocated for these objects beforehand and does not allow for dynamic scaling (i.e . it expects all sizes to be known at the time the code is compiled).

In the way your current code is setup, you wouldn't lose the address in the pointer when you go out of scope thanks to the global std:map, but you would lose it the second you call RPG::Image::create() again, since it now allocated new space and gives you a new pointer to the address of the newly allocated memory.

It's also important to know that just because an image is not visible on the screen when you call draw does not necessarily mean it has been destroyed. For every single frame displayed by the game everything is redrawn. Normally, what happens is that everything is drawn onto the canvas by a predetermined order. Anything drawn later will be drawn on top of what was already drawn (i.e. graphics from events set as "above hero" will be drawn after anything related to the tileset, and any picture will be drawn on top of everything else (except a picture with a higher ID). First when everything has been drawn on to the canvas, the canvas will be displayed to the player.
I'm not sure exactly when the event script commands are triggered (which is what would trigger onComment), but it's quite possible that this happens before the rest of the stuff is drawn to the canvas, meaning that when you draw an image to canvas in the onComment callback, you are indeed drawing it to the canvas, but everything is drawn on top of that afterwards, and you end up not seeing it. Nothing has been destroyed, you're just not seeing the results for other reasons.

So, even if you put the comment in a parallel process (which you would need to since otherwise you'd only be drawing the image for the single frame you executed the comment), there's still no guarantee that you will see it.

onFrame does a better job here, since I believe this is called after RPG Maker is done drawing everything it wants to draw, which is done for every frame. onFrame or onDrawScreen are proabably your best bets here. You could also use onBattlerDrawn, but you'd probably want to include an if statement there to make sure you're only executing the code after the last Battler has been drawn.

The answers to this is kind of contained in the wall of text up there, but just to directly address the various questions
author=McBick
I thought in c++ objects created are destroyed after the function is terminated, unless you return an object?

Only stuff which is put on the stack. RPG::Image::create allocated memory on the heap and returns a pointer to it which is not destroyed after the function is terminated.

author=McBick
From what I am to understand I am generating an infinite amount of Image objects?

Still looks like it. Try calling
myImages[0]->init(width, height)
instead after having called RPG::Image::create one time instead, as this will clear the image without creating a new one. Only works after you have created an Image though.

author=McBick
How can that be though, if I am creating the same object?

You might use the same variable name, but the code don't consider that to be the same object. You might have saved the address of that memory block in some other variable somewhere else in the code and want to reuse that variable name for a new pointer, which is what's happening it the code you outlined.

author=McBick
And how is it that my image is constantly being destroyed over and over?

Is it actually being destroyed or just not drawn? Not necessarily the same thing. You need to draw an image every frame, because if you don't the next frame is drawn on top of the old image and you won't see it anymore. This is why the text plugin also uses the onDrawPicture callback, since this something which is drawn for every frame (if the picture exists), but still allows for some graphics chosen by the developer to be put on top of the text (which is why I did not go for onFrame or onScreen myself).

What I would recommend, is to create all the images necessary in onComment callback at the start of a battle, and then to draw the images created in onFrame (without the use of RPG::Image::create in this callback). You use Destroy when the image is not used anymore or when the battle is over at which point you'll have to stop drawing as well (onFrame will keep drawing whatever it's told to draw whether you're in a battle or not, so you'll need a way to discern when you're in battle).

also, tiny tip. Use the code tags when posting code. This allows you to use square brackets, and the formatting is a bit easier to read.

[RM2K3] DynRPG Compiling Error

author=McBick
So I figured out what was wrong, kinda. When I create an image in a function that only runs once, for example the onComment() function. My RPG::Image object is destroyed after the function finishes executing the code which results in nothing happening. I had to use the onFrame() function to ensure it would persists in every scene. Unfortunately, now I have run into another issue and that is my images are being immediately destroyed after being made and I am not sure why. I at least see my image for a frame before it is destroyed though, unlike before where nothing would happen. The only solution I found is to have it draw to the canvas every frame which makes me think the game automatically destroys all images every frame and redraws them, excluding the new images.


A quick lesson in C++ (slightly simplified)
There are two types of memory which are relevant during runtime of a program called "stack" and "heap". When you define a variable inside a function, like an integer, this is put on the "stack" memory, and is only valid within it's scope, usually defined by the curly brackets. You can define an integer within an if bracket, in which case that integer will not be usable once the code execution is outside the if block (as denoted by the curly brackets).
The nice thing about the stack is that it cleans itself and does not cause problems.

The heap memory is for variables which are generally supposed to persist outside of the scope of functions. You normally allocate the memory for these variables with the "new" operator in C++, or calling a function which uses this (or C equivalent like malloc()). Usually, the variable you use to associate with this memory block allocated, is by a pointer. And it is important to keep track of the address stored in this pointer, since stuff which is put on the heap does not go away unless you specifically remove it (usually with the "delete" operator in C++).

Now, to take it back to your issue, what you're doing might a whole lot worse than you're imagining.
Whenever you call
RPG::Image* myImagePtr = RPG::Image::create(320, 240);

You're allocating an image of 320x240 pixels on the heap, and you store the address to that data in the pointer "myImagePtr". Problem is, that this pointer is put on the stack, and when you leave the function, it goes out of scope and it loses the address of that data, which now can never be deleted (until the termination of the program). This is known as a memory leak, and if you're calling this functionality at every frame without freeing that image, you probably have a massive leak going on. (You might want to open the task manager and look at the memory consumption of your game application during runtime. If it keeps increasing, that's a pretty bad sign).
In other words the game does not destroy the images at every frame, you're just losing track of them (also, the game is re-drawing everything every frame, so trying to call canvas draw with the onComment callback will not do much as it will "maybe" draw it for the single frame where the comment is triggered and will be lost immediately afterwards)

What you need to do, is to make a global variable of some sort. You could create one instance of that 320x240 image, and just draw text on that directly, but it makes it tricky to remove text afterwards, so you'll probably have to "clean" the image every time you want to remove something. You need make the drawing of the image happens in a callback which is drawn at every frame you want it to be visible, and here the order can be important.

[RM2K3] Dyntext error

I do have my doubts that this could be the issue, but if you save the game while a text is being displayed, iirc this will be stored alongside the savefile and automatically displayed when you load the file again (even if there is no event script to generate that piece of text anymore).

That's the only thing from the top of my head which I could imagine being the reason, apart from the text being generated by some other event script long forgotten.

[Poll] Better late than never! The DynRPG plugin contest

I did not remember having entered this at all, Possibly because I made quite a few plugins with no contest in mind (maybe I had already forgotten about it by my second public plugin).
It's a little bit sad that I didn't at the very least (re)submit the updated version of the particles effect plugin as it saw a substantial upgrade some time later than this particular iteration.

[DynRPG]Text Plugin

It's been a while, so I don't remember all the ins and outs of the plugin, but from what I recall:
The position of the picture has no bearing on the text images, and as such, using move picture will have no effect on the text. The text just happen to share some properties with the picture, being the drawing order and the transparency.
So, the only way to deal with movement of the text is the painful way by utilizing coordinates to reposition the text manually, probably using change_position (which seems to be in listed in the documentation having 3 parameters, id tag, x position and y position, at least in the readme I just downloaded from the most recent download button)

[DynRPG]Text Plugin

Yes, there is a some sort of memory leak happening each time append line is used, which I never got around to fixing. As pointed out above, this leak is cleaned up by calling a write_text or doing pretty much anything else which leads to the underlying image being discarded and redrawn, so it won't cause any known harm outside of this. I'd recommend not using append line more than 2 or 3 times before calling a write text, or alternatively just use multiple texts instead.
It kind of defeats the purpose of the function, but I'm not too sure it will be fixed at this point.