"GOOD" RM2K3 EVENT CODING

How to code performant and practical in rm2k3

  • Kazesui
  • 07/14/2012 03:06 PM
  • 6316 views
This tutorial is going to be something akin to the past 2 "performance scripting" tutorials, where I share my knowledge on the engine combined with my own thoughts about how to better code in rm2k3.

This "tutorial" is aimed at people who have familiarized themself with the program, and who want to make custom stuff in it, as this could quickly lead to coding endeavours.


For stuff to make sense in terms of performance, I will define the term "Instruction Cycle", which here means the time it takes for the maker to execute a single line of event code in the maker. Generally, we want to keep the amount of instruction cycles as low as possible between "wait" instructions.
Less instruction cycles per wait, less chance of lag, simple as that.
A single instruction cycle clocks about 1.67µs, meaning there's room for about 10,000 instruction cycles within a frame (This however, does not mean it won't start lagging before you reach 10,000 instructions cycles as there are other factors at work here as well).

Keeping in mind how many instructions is executed within an frame (a 0.0 wait, or also 1/60 second in rm2k3) will allow you to determine how long event scripts you can have, and how many events you can set to parallel process.


Part 1: Branches



You're probably already quite familiar with them, since they are often required for different stuff to happen based on some imposed condition, like wether a hero has enough money, or a switch has been turned on.

Something important to know about these branches though, is that they are generally the most instruction cycle heavy command you can use.
Why is that you wonder?
Well, while the actual branch segment only takes a single instruction cycle, so does the empty line at the end of each block of event code (the one right above the "Else Handler" label and the "End" label).
Also, in the upper block, the "Else handler" label causes a jump to the "End" label, while for the lower block, "End" has the same effect as the empty lines, and simply wastes an instruction cycle.

This means that just setting up an empty conditional branch with else handler condition costs you 3 instruction cycles! This is a reason why it's bad to leave the "else condition" box checked if you're not using it within your branch.
It also looks ugly, so unless you're using the else statement, don't leave that box checked.

Tip on branch with else conditions:


By doing this, you actually achieve a conditional branch with else condition only taking 2 instruction cycles. The reason for this, is because you manage to get out of the block by yourself without having to execute the 2 unneccessary lines of either block (the jump at else handler becomes unneccssary when you jump manually), this saving 2 cycles by adding 1 instruction. A pretty good deal.
If you have a branch like this in a loop, which perhaps iterates a 100 times or so, you've saved yourself 100 instruction cycles!!

Notice however that this doesn't neccessarily apply to conditional branches without an else statement. If you do this for such a branch, it will be faster whenever the branch is triggered, and slower whenever it's not, because you'll waste an instruction cycle having to read the line with "label 1", meaning it's usually better to not do this for such branches.


Another thing about branches, is how to handle multiple branches well, as you sometimes have a list of conditions to take care of. Often I've seen people do something like this:


No, no, no. Just no. Don't do this. This looks horrendous, makes the event code harder to read, and is far more prone to accidentally making you create a bug.
The only reason you could have for nesting new conditions into else statements like this, is because you don't want the code to check the remaining branches if you one triggers. This is the right thought, but the wrong way of doing it. A better way would be to list them up after each others instead and use labels to jump out of the list of branches afterwards, like this:


This is so much easier to read, and it's more effective as well, since it doesn't leave tons of empty lines wasting instruction cycles. If you need to make a list of conditionals this is way is a lot better than the alternative mentioned up there.
Depending on what kind of conditions you are checking, it's possible to further optimize it for better performance at the cost of some readability, but this is very situational, so I won't be going through it here.


Part 2: Call Event

Next, we want to look into the "Call Event" command. It's basically a fantastic command which isn't used enough. It allows you to reuse blocks of code at ease, as well as make variables decide stuff like what direction an event should move, or what event should flash. Stuff you normally can't control with variables.

Let's start with the simple version first. Let's say that you have a list of branches like in the section above, and they all execute the same code. Instead of copying and pasting the block of code into every branch. It would be better to have a common event with the same code, which you then call on.
A reason for this, is because often enough, you will find bugs in your code or want to change it for other reasons. With a list of pasted blocks, you'd have to apply this change to every block manually. One mistake here and you create a new bug, which might be difficult to spot. It also takes a lot of time. This could all be avoided by having a common event, which would be the only block of code you'd have to change to effect all branches calling on it.

Something to know though, is that the Call Event command costs 2 instruction cycles, One for the call itself and one for the empty line at the end of the event it's calling. This means it could be more performant to not use Call Event.
However, to consider not using it for situations like these should be done when you have reasons to believe that performance will actually be a problem. Otherwise, it's better to keep your code better readable.

The cost of using the Call Event command is however well worth it whenever you want to put variable values to stuff like event movement. This is done by using the variable function of Call Event along with the plethora of "this" functionality in many of the event commands.
Let's say you have an NPC which you want to control with variables. Store the event ID of that NPC in one variable, and create a low page (that can't be accessed by the player by hitting the action key) and store the number of that page as well.
On this page, you simply make a list of conditional branches for a variable with 4 possible values, and make "this event" move to another direction in each branch.
And voila!
You have an event which you can control with variables and call event. By having a way of keeping track of the event ID's, you could even create an exact copy of the first NPC and have another call event command control it as well, meaning it's possible to mass produce events this way without fiddling with little bits of code on every NPC.

This has quite many uses, and I use this a lot! It can be very applicable for ABS games, where you have a number of enemies you need to copy, and who might require more sophisticated movement than simply "move towards hero". The alternative would have been to have tons of branches for each event, which needless to say, would have been far less effective.

Tip on effective map event calling:
When I have a lot of events which I need to control movement and stuff on with variables, I tend to make sure that all of these events have sequential event ID's.
This allows me to loop through them effectively. I also set off space for "page variables", which is basically different variables with a name like "NPC_MOVEMENT", which I set to a page number which will control the movement, and I keep this the page number the same for All events I want to be able to control this way, meaning that it's a good idea to keep the most generic capabilities at the lowest page numbers. Doing this makes it easier to recognize which variable to use when calling an event, as well as making it more readable afterwards when you're looking back at the code.

If you have a long list of branches checking for numbers which you somehow can turn into a unique page number, you could also use this to more effectively execute the code, as it'd only cost the 2 instruction cycles from the call event, while a list of branches would on average cost you instruction cycles for half the number of branches.

Part 3: Variables

If the stuff so far has been interesting, it's probably because you have or intend to create custom systems of some kind in rm2k3. And the life and blood of pretty much all the systems are variables and variable operations. Tons of them.
This is also a area where the usage of them will decide how performant your system is.

A couple a good thing to pay attention to when dealing with variables.
Try to keep blocks or related variables close to each other and systematic.
This makes it easier to deal with them, and find the correct variables when they grow many, and the systematic bit of it, makes it possible to use pointer operations to make the code shorter and more readable (for those who can keep track of the pointing).
Another reason for placing related variables close to each other is because you can use the range function to perform an operation on multiple variables at the cost of 1 instruction cycle!!

Another cool thing you can do with the range function, is basically to let it work as a double pointer by referencing a variable within a range of 2 (as the range is executed sequentially).

Knowing math, in particular algebra, can quickly come handy as well.
If you have a formula like:
dmg = multiplier*ATK + multiplier*SKILL
you can quickly see that
dmg = multiplier*(ATK + SKILL)
gives the same result with less variable operations. This was a trivial example, but often enough when devicing formulas, you'll end up complicating it while trying to adjust it. Just taking a quick look at it afterwards to see if you can simplify it can prove wonders in terms of number of variable operations you need to do.

Tip on variable storage:
An often uknown fact in rm2k3, is that you can use as many as 9,999,999 variables. This is done by using pointers to access any variable outside of the normal bounds and operating on them. This also allows you to hide variable values from the debug menu, or use the "outside scope" for array like structures, so that you don't have to fill up you're existing bounds with variable which are either a hassle to name or just empty, making it hard to know whether you already use them or not.
The only thing you need to pay attention to, is that using excessively many of these variables, will cause longer save and load times for the game.

Part 4: Loops

I've mentioned them a couple of times already. If you want to operate on many different variables, events or something at once, you'll normally want to make loops for the sake of minimizing the work you need to do writing it, and also for the case of more dynamic systems where they are more or less required.
The key to be successful here is to know how to use pointers, so if you don't know how to use them already, you should go and figure it out.
Personally, I like to make my loops like this:

(taken from the DynText Plugin Project, in case you wonder about the comments).

For loops, you generally put variables to some inital values above a label, and then you start changing them as you go through the loop. I like to a branch at the end which jumps back to the top if triggered, rather than one taking you out of the loop when triggered, cuz I think this looks cleaner.

This loop in particular gets different item names by iterating a variable, and positions them differently by adding to the y coordinate variable, giving me a fine list of itmes (which could be used to display items in a custom item menu).

Part 5: Trivia

Some more and less trivial trivia potentially worth knowing:
- You can select multiple commands in rm2k3 by click on one line, holding shift and pressing on another.
- A comment costs 1 instruction cycle
- There's a "hidden" 0.0 wait at the end of a parallel process event.
- Show Picture only cost 1 instruction cycle, but is still heavy since it requires to be read from memory, meaning the computer need more time for it.
- The reason Loops are slower then Labels used for looping is because of the empty line at the end of the loop.



Some more stuff I want to mention on the topic is that there's no need to overly fear using many parallel processes. In end effect it's often the number of instructions executed which will decide if it'll lag or not. This is not to say you should use them whenever, especially if they're not neccessary. If you don't know whether they are or not though, don't fear using them. Often enough, I read people citing parallel processes as the big evil. It can be evil, but it's not that (normally) not that big, as long as you're not trying to execute way to many instructions in the sum of all the parallel process events you have running at the same time.

Also, as said earlier, instruction cycles isn't the only thing causing lag. The maker allocated 1,67µs for each instruction cycle, but that doesn't mean that you'll computer will be able to complete the instruction within that time. Newer computers will probably have less trouble with these things, while older might suffer from certain commands.
Also, internal stuff like the amount of events on any given map also effects performance, as there are tons of internal branches associated with event pages which need to be run through for each frame, also potentially causing lag. It's ideal to have as few events on a map as possible.

If following this stuff won't get you where you want, you might just be working in the wrong engine (probably slightly more than just "might"). To remedy this, you'll probably have to change engine, or start using patches, or learn to use the DynRPG SDK which can give you a large performance boost (i.e. learn C++... chances are you'll have an easier time learning a new game making engine).

Still, this should provide some pointers on how to improve code you already have going to potentially prevent lag problems and stuff.
Pretty sure there was more concepts I wanted to bring up, but can't remember anymore, and article is long enough already.

Hope whoever read this far found any of this interesting

Posts

Pages: 1
Wow, there's some neat stuff in this article. Good work!
LockeZ
I'd really like to get rid of LockeZ. His play style is way too unpredictable. He's always like this too. If he ran a country, he'd just kill and imprison people at random until crime stopped.
5183
You spend the first half of this article telling us why we should use GOTO every chance we get? Really? That's not good coding practice! That's like, the thing everyone learns not to do on day 1 of intro to computer programming. It saves a couple cycles, but makes unreadable spaghetti code. There might be one person in the entire world making a game that's coded badly enough that it could potentially cause lag, and one other person in the world with a computer that's old enough that it would actually lag in that game, but screw those two guys. It's not worth making the game such a pain in the ass to edit later for their sake.

Utilizing Call Event to separate out subroutines is definitely good advice, though.
author=Lockez
nreadable spaghetti code.

Comment your code properly and you'll be fine?
author=LockeZ
You spend the first half of this article telling us why we should use GOTO every chance we get?


Technically speaking, all loops and branches are based on "GOTO", just abstracted away in the programming language such that it's to the compiler to add in it afterwards. These are structures you don't have as readily available in rm2k3, and then you have to make do with what you have.

I also fail to see where I advocated spaghetti coding here. Are you really saying that you prefer the first example in the multiple branch part I showed? Really?
The labels are pretty much making the code MORE readable.
Using GOTO != Spaghetti Code
Labels aren't inherently evil, it's the people using it poorly.
You rarily will need them in an actual programming language, as they are considerably more flexible and less prone to performance issues.
rm2k3 however is considerably more limited in terms of performance and control structures, and when you start building some bigger custom system, you can very quickly notice performance issues.

I'm not sure what world you come from, but lag in rm2k3 games which does anything outside of the "usual" isn't exactly that rare. The games themselves might be more of the rare kind (depending on the fanciness of a potential CMS attempted), but it's also rather that kind which this tutorial is aimed towards.

I might not have emphasized enough on the importance of keeping your code readable in this tutorial, and don't remember if I said it up there, but sacrificing readability for sake of performance should first happen when performance becomes an issue. But as said, I'm merely showing some applications of labels with none of the examples really produce the spaghetti code you talk of.
dragonheartman
Developer, Starless Umbra / Heroes of Umbra
2690
author=LockeZ
You spend the first half of this article telling us why we should use GOTO every chance we get? Really? That's not good coding practice! That's like, the thing everyone learns not to do on day 1 of intro to computer programming. It saves a couple cycles, but makes unreadable spaghetti code. There might be one person in the entire world making a game that's coded badly enough that it could potentially cause lag, and one other person in the world with a computer that's old enough that it would actually lag in that game, but screw those two guys. It's not worth making the game such a pain in the ass to edit later for their sake.

Utilizing Call Event to separate out subroutines is definitely good advice, though.
Notice "good" in the title is in quotation marks. You have to jump some hoops to work with 2k3 at times, and it's not always a 1-to-1 mapping between good programming and good rm2k "scripting" or whatever you want to call it.

I do avoid GOTO for general-purpose programming. RM2k/3 I tend to avoid them when possible, but they have their place.
I agree with you on the else thing, because from personal experience, I've known
If
Else
If
Else
chains to get very, very bad. The same can be done done with a number of simple If conditions.

Think of it this way:
1. A blank else is almost identical to not checking the else
2. A blank else can in come conditions allow for ANYTHING other than the condition, meaning strange errors have the potential to pop up.
3. When two nested If statements you can quickly create a mess where before something like
If Var is < 8
If Var is > 1
would have simply activated between those numbers.

THEREFORE

The ONLY time you should be using else is when you have a few conditions based on something not happening, or if you want to clearly separate two instances (if you don't have enough berries the monster eats you, versus a simple situation of something only happening when you have enough berries.

The rule of thumb is, only use else boxes if you have a series of conditions dependent on things not happening.

Common Events should be used far more often than Goto. You can edit things remotely, rather than going back and finding every instance of a local event. The non-character/door/chest local event should ideal just be a parallel process/auto calling the common event, then either End Event Process or Erase Event. Goto is for two major uses:

Back skipping.
Label
"Choose Whatever..."
"Are you Sure"
Y (Go Ahead)
N (Goto Label)

And skipping over code that would activate otherwise.
"Skip the Intro?"
Y (Goto Label)
Label
(The event/character setup, and the teleport event)

Event still, this is to be used sparingly. I have only about 10 instances of using goto, and it was frequently in tutorial-type things where I wanted to go to a certain point on the page (and almost always triggered by choices, to keep infinite triggering glitches).



This is not particularly good code (good code, should as much as possible, save variables). I'll try to dig up an example of good code.
This is good code.



No loops, no else, no fluff whatsoever. It lets you access any variable or switch and changes it. If something shouldn't be done (protected or invalid numbers), it just exits out.

*Sigh* If only my earlier code could be this clean.
author=bulmabriefs144

This is not particularly good code (good code, should as much as possible, save variables). I'll try to dig up an example of good code.


...What point are you trying to make here, because you're not really making a lot of sense.
Are you trying to claim that loops are bad and that you should rather rely on copy pasting, or are you trying to argue that there's any particular good reason for being insanely sparse with memory, considering each variable only cost couple of bytes anyway?
It's too bad there is a lot of personal taste here and most of the "rules" described is bound to the situation.

For example:

The stacking of conditional variables is handy if you want to copy and paste that block in one instance to alter it to other conditions. When you make them saparate you have to spent more time on copying them with the chance of forgetting one or two. It's sometimes also clearer if you have diffrent sets of them to use that stacking shape as some sort of pointer. If people don't use Cherry's RM2k9 (with colour codes for diffrent eventcommands) it's sometimes hard to see the boundry between one set and the other, even when comments are used.

Next to that your way of getting out of loops does look like a nice set up, but can also be confusing sometimes. Most of the times when I break a loop (with labels) I want to reset some variables or adjust them. By using the conditional branch, get out of loop I get blocks of coding which are easier to recognize.

label 1
do stuff
do stuff
when stuff
go to label 1
do stuff
do stuff

Vs:

label 1
=do stuff
=do stuff
=when is not stuff
=do stuff
=do stuff
=go to label 2
go to label 1
label 2

Which makes it one block. Again, I don't see this is ideal, but it's not wrong in any way, even if you did use "good" in your title. You could better make this a tutorial about comparing certain ways.

I do however totally agree with you about the range possibility. Also with switches. I opened a game this week which had like 20 to 30 switch operations that turned them off. Why not use a single switch operation with a range in it.

Next to that with variables people should put comparable variables parralel. For example, in one of my projects I show hero statistics with pictures. Instead of making three (number of heroes) statistic menu's I just use 1 which changes coordinates and data.

Example:

Set variable calculator 1 to 1
Set variable calculator 2 to 121
label 1
Set variable in index caculator 1 to variable in index calculator 2
conditional branch if calculator 1 is not 20
go to label 1 (yeah I just made you happy by using your descriped looping =p).

Btw, Bulmabriefs I don't agree to you on the variable save. Less code is always better than saving variables. Next to that, as you can see in the example above you can do the stuff seen in that picture without using "too many" variables. I have tons of those and they only took me two extra variables in total "calculator 1" and "calculator 2". My big friends in calculating and tracking stuff that don't need to be remembered that long =).

All by all conclussion: The way to architect your eventing is bound to the situation and personal taste of the eventer. My whole message is full of personal taste and I won't tell anybody to change their way of eventing just because I say so.

I do however advocate using ranges and using more variables to save eventcommands (I mean this in a way so you can recycle bigger chunks of eventcommands like menu's and number showing).
You are of course very right, there's a lot of personal flavour going here, this having been written more in my flavour of course. That said, my looping style isn't just based on preference, it's actually slightly more efficient than yours as well (in rm2k3 that is, which is an important distinction here).
In rm2k3 it costs one instruction cycle less. The bigger the content of the loop, the more negligible that one instruction cycle becomes, but for tiny loops with lots of iterations, it can become rather noticeable. Of course, this will rarily be a problem unless you're working on some heavy system (a moderately complex real time system, like an advanced ABS for example).

Among the goals of my little article/tutorial here was to combine some coding style with efficiency, not so much about merits of different styles. If I was focusing more on how to code to keep it readable, clean and organized, I probably would have drawn some comparisons to show how it can be done differently yet still good, which would make quite some sense, considering I used to use your looping approach before as well, before switching to my current style.
author=Kazesui
...What point are you trying to make here, because you're not really making a lot of sense.
Are you trying to claim that loops are bad and that you should rather rely on copy pasting, or are you trying to argue that there's any particular good reason for being insanely sparse with memory, considering each variable only cost couple of bytes anyway?

Exactly what I said. Good code saves variables, because sooner or later you'll run into something that requires alot of them, and having loops in the first place, yes, is very much to be avoided.

Why does it matter? Because somewhere, someone will have a 5-10 year old computer, because they either were poor or uncertain whether they could still program 2k3 on Windows 8. So, yes, it does matter to a certain extent.

  • Don't use Loops, if you can help it. They have a nasty habit of stalling character motion, and certain things get lagged out by using them. A parallel process with no erase, will do the same without the tendency to clog actions.
  • Don't use labels, they're even worse. C++ manuals warn against spaghetti code, and I'm not even a great C programmer. Tutorials are really the only decent place for labels, that and things for skipping processes, and even then, it's better to skip with an if-else branch than to murk up the code with labels. I have a few of them in common events, and one day I'm going to need to rewrite massive lines.
  • Do use common events, as much as possible. They allow you to outsource events, speeding processes up (I tried the same code written into a local variable parallel process, and written in a parallel process with just a common event. There was a noticeable lag difference, in favor of the common events. Also, it makes the code far easier to edit. This is the problem that often plagues battle events, having to copy paste the same damn code 300+ times.
  • Some common events should be switch activated, some should work as a by-screen parallel/auto event. Understand what goes where, and don't decide it's a great thing to have all common events by switch. This means until you turn them off, a whole bunch of events are constantly active.

Looping is bad, because it slows movement down. I even had just a loop using for music to end after play (it doesn't seem to work outside a loop), and I couldn't press buttons or move until the song was actually over.

Then this Common Event on another parallel local event

<> Branch if (msgptr) is 5 Greater/Equal
<> End Event Processing
<> Else
(Instead of doing +/- the x y, set the variables to a specific amount, since it prevents stuff from going weird places or off the screen, possibly nest an If msgptr = for each number with no else inside here if you want a different text for each)
<> Var msgptr, +1
<> End Event Processing

Okay, this will run through in a fraction of the time (and you can slow it down with wait if need be), it counts up to five, and then it blanks. The cycle is still technically going, but it's not doing anything but quitting out. No lag, no waiting for all of this to finish, you can walk off if you want rather than waiting around for all the text to show (meaning monsters on the screen can do the same).
Though I must agree with you guys when we are concidering more "uncomplicated" stuff, I certainly disagree on some points.

First of Rm2k3 is not to be compared to scripting language, it's way more inferiour to it and goes by diffrent rules. Labels are your friends and variables are even more your friends (why save them, you have a standard of 5000 of them and can even go upto 999999).

I use a bunch of labels in my common events to do loops instead of parallel processes. This is because I absolutly hate containing dataflow with switches. They tend to bug and sometimes I just want something to happen before the code runs any further. I solely use them to use auto events like the menu and a battle system initiation. Apart from that only call events for me, they are way better at containing the flow of events. I don't want any background parallels running.

So if one of you guys could tell me how to make this example flow any better or any less "laggy" (which it absolutly doesn't) please tell me:

In my item menu I need to check if variable item amount # is bigger than 0 to set the order of that item to a item order # variabel. I do this by doing the following:

set var index item amount 200
set var index item order 240
set var order = 1
label 1
set var index item amount +1
set var index item order +1
set var calculator to variable stored in index var item amount
if var calculator = greater than 0
<>set var in index item order = var item order
<>var order +1
end
if var index item amount = not 281
<>jump to label 1
end

This was inbetween an item menu to check the order of the items that you have. I could do this in a parallel proces which is initiated by a switch. But that would mean that the event that needs this information would be keep on running through (which would be weird because that only loops when a button is pressed, but let us not take that in concideration) until this loop was done by switching of the switch that initiated it.

I could offcourse by the logic of you guys do it like this, times 40:

var order = 1
if var item amount 1 = bigger than 0
<>set var item order 1 = var order
<>var order + 1
if var item amount 2 = bigger than 0
<>set var item order 2 = var order
<>var order + 1
end
(and so on till we reach 40 times)

Example two, displaying the graphics in the menu. As it is now:

(set var x and y to starting position of the item list and two variabels to check picture ID and picture to be shown)

set var index item order to 200
set var order to 1
label
set var index item order + 1
set var calculator to var stored in index item order
if var calculator = var order
<>set picture name to var index item order
<>show picture (item_0000)
<>set picture id +1
<>set order +1
end
if order =not 8 (to show only 7 items on screen)
<>go to label
end

I won't go in the more technical aspects on how to trace cursor positions and starting points. But without the loops I couldn't even hope to make a dynamic item menu in a fast way. But the list goes on:

Setting a set of dummy variabels to variables that keep hero statistics.

Would we go for the 20 set variables which clutter big blocks all over the place, or just go for:

set calculator to 0
set calculator 2 to 20
label 1
set calculator +1
set calculator 2 +1
set variable stored in index calculator to variable stored in calculator 2
if calculator is nog 21
<>go to label 1
end

And for deleting about 100 pictures? Is it that much better to do 100 erase picture commands to avoid labels or are we just going to do:

set var image id to 1
label
erase picture 0000
set var image id + 1
if var image id =not 101
jump to label
end

Please tell me why I would use cluttering parallel processes (with or without switch) if I could easily control dataflow which 2 labels and/or a call event so I know for certain which commands are being used without any background stuff going on. And why wouldn't I use variables to make my life a lot easier. Or would you suggest I would ditch my common event which can generate all my selectable dynamic "item" menu's and copy the base code like 10 times for equip, weapon, armour, quest log etc to save about 20 variables that track the size, position etc for those menus.

Which also means that if I would want to add some animation to it or find a bug in it I need to fix 10 menu events instead of just 1.

Sorry if got a bit personal on this, but I just don't see the major pros in saving variables that should make your life easier and controlling parallel processes that give you lots of background "noise" (wheater or not with switches) over labels and call events that create massive control over the commandflow without any background noise.
@bulma
Sorry, but you're post shows massive lack of understanding of how stuff works.
To suggest that loops should be avoided is stupid, inefficient, tedious and even more bug prone.

Your argument about loops being bad for old computers is downright bullshit. If you don't terminate a loop after you're done with it, or loop without ever stopping it, then yes, of course it's bad. But that's not a fault of the loop, that's a fault of the coder being an idiot.

Good code saves space, but the space saved by conserving rm2k3 variables is utterly trivial. Even if you set the variable array to 9999 you're not even using a single Mega Byte... which pretty much means it's going to have no impact on performance whatsoever, and any other increase in size as a result of this is also totally trivial, so exactly WHY is it so important to be saving variables, when adding a few can make life a lot easier, make stuff more readable, or even add more flexibility to your code, which is argueable far far more important for the code.

As it stands, pointers in combination with loops allow for much more flexibility, which could only be compensated by massive use of branches, which is way way more inefficient. THIS hurts the usage of old computers.

Also, yes, typically, programming languages tell you to avoid using labels, which is a good advice for novices. However, this isn't necessarily worth much if you don't really understand WHY they can end up being bad. Just having read that they are more prone to cause spaghetti code just doesn't cut it.
The problem with labels is that they can make code more unreadable, or even be totally confusing if you abuse them.

However, rm2k3 does not have proper control structures, and if done right, like shown in my examples, or even in the example of Trujin, which isn't bad either, it's not that much spaghetti. It retains readability, sometimes being even more so than whatever alternative you might be facing by trying to just avoid labels, because you don't understand the concept.

Another thing, Common events does not speed up code, it actually slows it down!
in terms of performance, you don't want a million common event calls. You do this for the sake of reuseability, easier maintenance, less bug prone and for keeping it more readable. Also, it can cut down the size of the set of event instruction, which is actually linked to the performance in terms of memory usage... however if you experience a considerable boost because of this, its most likely because you're doing something horribly wrong in the first place.
You should of course use them, but not for performance, and not just for the sake of using them either. If the code isn't reused at any time other than once in that particular event, it's most of the time better to just keep that code there, rather than to move it out to a common event.

And finally, your last example... Having it run as a parallel process just won't cut it for more demanding real time systems.
if you need to do 60 iterations in a loop, it would take A FULL SECOND for the loop to finish. That's just not acceptable. If you're doing lot of hit collision checks by this kind of loop, you'd get all kind of faulty data, because what happens on the screen will never be checked in time in the actual event. Not to speak of how immensely unecessary it is to have an event which does absolutely nothing except cost cpu time be running. If anything, you'd want to only let that common event be active when a switch is set ON.

All in all, you're primarily listing up bad advice, rather than good ones.
Pages: 1