Hello all-
I'm working on a puzzle where the player is pushing a button to alter the position of a hatch that is blocking the flow of lava. The temperature and height of the lava within the pipe is determined by moving int counters. Each segment of the pipe has an odd number counter (the temp) and an even number counter (the height.) I've put all of this on an X/Y grid which I then transferred into a code, the first two segments of which are below. Right now I'm trying to have the code respond to a simple set of variables: "object 1" (the first hatch blocking flow from segment one to segment two) being visible should cause object 11, the segment, to show the graphic for 4/4 on the X/Y chart. That works. The problem is that I can't get the same response when object 2 is made visible.
Any help would be greatly appreciated.
function room_RepExec()
{
if (object[1].Visible == true) { myCounter1 = 4; myCounter2 = 4; return; }
if (object[2].Visible == true) { myCounter3 = 4; myCounter4 = 4; return; }
// Segment 1 integers
if (myCounter1 == 0 && myCounter2 == 0) {object[11].Graphic = 376; return;}
else if (myCounter1 == 1 && myCounter2 == 1) {object[11].Graphic = 404; return;}
else if (myCounter1 == 1 && myCounter2 == 2) {object[11].Graphic = 398; return;}
else if (myCounter1 == 1 && myCounter2 == 3) {object[11].Graphic = 392; return;}
else if (myCounter1 == 1 && myCounter2 == 4) {object[11].Graphic = 386; return;}
else if (myCounter1 == 2 && myCounter2 == 1) {object[11].Graphic = 407; return;}
else if (myCounter1 == 2 && myCounter2 == 2) {object[11].Graphic = 401; return;}
else if (myCounter1 == 2 && myCounter2 == 3) {object[11].Graphic = 395; return;}
else if (myCounter1 == 2 && myCounter2 == 4) {object[11].Graphic = 389; return;}
else if (myCounter1 == 3 && myCounter2 == 1) {object[11].Graphic = 405; return;}
else if (myCounter1 == 3 && myCounter2 == 2) {object[11].Graphic = 399; return;}
else if (myCounter1 == 3 && myCounter2 == 3) {object[11].Graphic = 393; return;}
else if (myCounter1 == 3 && myCounter2 == 4) {object[11].Graphic = 387; return;}
else if (myCounter1 == 4 && myCounter2 == 1) {object[11].Graphic = 402; return;}
else if (myCounter1 == 4 && myCounter2 == 2) {object[11].Graphic = 396; return;}
else if (myCounter1 == 4 && myCounter2 == 3) {object[11].Graphic = 390; return;}
else if (myCounter1 == 4 && myCounter2 == 4) {object[11].Graphic = 384; return;}
else if (myCounter1 == 5 && myCounter2 == 1) {object[11].Graphic = 406; return;}
else if (myCounter1 == 5 && myCounter2 == 2) {object[11].Graphic = 400; return;}
else if (myCounter1 == 5 && myCounter2 == 3) {object[11].Graphic = 394; return;}
else if (myCounter1 == 5 && myCounter2 == 4) {object[11].Graphic = 388; return;}
else if (myCounter1 == 6 && myCounter2 == 1) {object[11].Graphic = 403; return;}
else if (myCounter1 == 6 && myCounter2 == 2) {object[11].Graphic = 397; return;}
else if (myCounter1 == 6 && myCounter2 == 3) {object[11].Graphic = 391; return;}
else if (myCounter1 == 6 && myCounter2 == 4) {object[11].Graphic = 385; return;}
// Segment 2 integers
if (myCounter1 == 0 && myCounter2 == 0) {object[12].Graphic = 476; return;}
else if (myCounter1 == 1 && myCounter2 == 1) {object[12].Graphic = 504; return;}
else if (myCounter1 == 1 && myCounter2 == 2) {object[12].Graphic = 498; return;}
else if (myCounter1 == 1 && myCounter2 == 3) {object[12].Graphic = 492; return;}
else if (myCounter1 == 1 && myCounter2 == 4) {object[12].Graphic = 486; return;}
else if (myCounter1 == 2 && myCounter2 == 1) {object[12].Graphic = 507; return;}
else if (myCounter1 == 2 && myCounter2 == 2) {object[12].Graphic = 501; return;}
else if (myCounter1 == 2 && myCounter2 == 3) {object[12].Graphic = 495; return;}
else if (myCounter1 == 2 && myCounter2 == 4) {object[12].Graphic = 489; return;}
else if (myCounter1 == 3 && myCounter2 == 1) {object[12].Graphic = 505; return;}
else if (myCounter1 == 3 && myCounter2 == 2) {object[12].Graphic = 499; return;}
else if (myCounter1 == 3 && myCounter2 == 3) {object[12].Graphic = 493; return;}
else if (myCounter1 == 3 && myCounter2 == 4) {object[12].Graphic = 487; return;}
else if (myCounter1 == 4 && myCounter2 == 1) {object[12].Graphic = 502; return;}
else if (myCounter1 == 4 && myCounter2 == 2) {object[12].Graphic = 496; return;}
else if (myCounter1 == 4 && myCounter2 == 3) {object[12].Graphic = 490; return;}
else if (myCounter1 == 4 && myCounter2 == 4) {object[12].Graphic = 484; return;}
else if (myCounter1 == 5 && myCounter2 == 1) {object[12].Graphic = 506; return;}
else if (myCounter1 == 5 && myCounter2 == 2) {object[12].Graphic = 500; return;}
else if (myCounter1 == 5 && myCounter2 == 3) {object[12].Graphic = 494; return;}
else if (myCounter1 == 5 && myCounter2 == 4) {object[12].Graphic = 488; return;}
else if (myCounter1 == 6 && myCounter2 == 1) {object[12].Graphic = 503; return;}
else if (myCounter1 == 6 && myCounter2 == 2) {object[12].Graphic = 497; return;}
else if (myCounter1 == 6 && myCounter2 == 3) {object[12].Graphic = 491; return;}
else if (myCounter1 == 6 && myCounter2 == 4) {object[12].Graphic = 485; return;}
If it helps, here's the code for the whole room:
// room script file
// Segment 1
int myCounter1 ;
int myCounter2 ;
// Segment 2
int myCounter3 ;
int myCounter4 ;
// Segment 3
int myCounter5 ;
int myCounter6 ;
// Segment 4
int myCounter7 ;
int myCounter8 ;
// Segment 5
int myCounter9 ;
int myCounter10 ;
// Segment 6
int myCounter11 ;
int myCounter12 ;
// Segment 7
int myCounter13 ;
int myCounter14 ;
// Segment 8
int myCounter15 ;
int myCounter16 ;
// Segment 9
int myCounter17 ;
int myCounter18 ;
function oObject20_AnyClick()
{
if (object[20].Graphic == 410)
{object[20].Graphic = 411;
object[1].Visible = false;
object[2].Visible = true;
object[3].Visible = false;
return;}
if (object[20].Graphic == 411)
{object[20].Graphic = 412;
object[2].Visible = false;
object[3].Visible = true;
return;}
if (object[20].Graphic == 412)
{object[20].Graphic = 410;
object[1].Visible = true;
object[3].Visible = false;
return;}
}
function oObject21_AnyClick()
{
if (object[21].Graphic == 410)
{object[21].Graphic = 411;
object[4].Visible = false;
object[5].Visible = true;
object[6].Visible = false;
return;}
if (object[21].Graphic == 411)
{object[21].Graphic = 412;
object[4].Visible = false;
object[5].Visible = false;
object[6].Visible = true;
return;}
if (object[21].Graphic == 412)
{object[21].Graphic = 410;
object[4].Visible = true;
object[5].Visible = false;
object[6].Visible = false;
return;}
}
function oObject22_AnyClick()
{
if (object[22].Graphic == 410)
{object[22].Graphic = 411;
object[7].Visible = false;
object[8].Visible = true;
object[9].Visible = false;
return;}
if (object[22].Graphic == 411)
{object[22].Graphic = 412;
object[7].Visible = false;
object[8].Visible = false;
object[9].Visible = true;
return;}
if (object[22].Graphic == 412)
{object[22].Graphic = 410;
object[7].Visible = true;
object[8].Visible = false;
object[9].Visible = false;
return;}
}
function room_Load()
{
}
function room_RepExec()
{
if (object[1].Visible == true) { myCounter1 = 4; myCounter2 = 4; return; }
if (object[2].Visible == true) { myCounter3 = 4; myCounter4 = 4; return; }
// Segment 1 integers
if (myCounter1 == 0 && myCounter2 == 0) {object[11].Graphic = 376; return;}
else if (myCounter1 == 1 && myCounter2 == 1) {object[11].Graphic = 404; return;}
else if (myCounter1 == 1 && myCounter2 == 2) {object[11].Graphic = 398; return;}
else if (myCounter1 == 1 && myCounter2 == 3) {object[11].Graphic = 392; return;}
else if (myCounter1 == 1 && myCounter2 == 4) {object[11].Graphic = 386; return;}
else if (myCounter1 == 2 && myCounter2 == 1) {object[11].Graphic = 407; return;}
else if (myCounter1 == 2 && myCounter2 == 2) {object[11].Graphic = 401; return;}
else if (myCounter1 == 2 && myCounter2 == 3) {object[11].Graphic = 395; return;}
else if (myCounter1 == 2 && myCounter2 == 4) {object[11].Graphic = 389; return;}
else if (myCounter1 == 3 && myCounter2 == 1) {object[11].Graphic = 405; return;}
else if (myCounter1 == 3 && myCounter2 == 2) {object[11].Graphic = 399; return;}
else if (myCounter1 == 3 && myCounter2 == 3) {object[11].Graphic = 393; return;}
else if (myCounter1 == 3 && myCounter2 == 4) {object[11].Graphic = 387; return;}
else if (myCounter1 == 4 && myCounter2 == 1) {object[11].Graphic = 402; return;}
else if (myCounter1 == 4 && myCounter2 == 2) {object[11].Graphic = 396; return;}
else if (myCounter1 == 4 && myCounter2 == 3) {object[11].Graphic = 390; return;}
else if (myCounter1 == 4 && myCounter2 == 4) {object[11].Graphic = 384; return;}
else if (myCounter1 == 5 && myCounter2 == 1) {object[11].Graphic = 406; return;}
else if (myCounter1 == 5 && myCounter2 == 2) {object[11].Graphic = 400; return;}
else if (myCounter1 == 5 && myCounter2 == 3) {object[11].Graphic = 394; return;}
else if (myCounter1 == 5 && myCounter2 == 4) {object[11].Graphic = 388; return;}
else if (myCounter1 == 6 && myCounter2 == 1) {object[11].Graphic = 403; return;}
else if (myCounter1 == 6 && myCounter2 == 2) {object[11].Graphic = 397; return;}
else if (myCounter1 == 6 && myCounter2 == 3) {object[11].Graphic = 391; return;}
else if (myCounter1 == 6 && myCounter2 == 4) {object[11].Graphic = 385; return;}
// Segment 2 integers
if (myCounter1 == 0 && myCounter2 == 0) {object[12].Graphic = 476; return;}
else if (myCounter1 == 1 && myCounter2 == 1) {object[12].Graphic = 504; return;}
else if (myCounter1 == 1 && myCounter2 == 2) {object[12].Graphic = 498; return;}
else if (myCounter1 == 1 && myCounter2 == 3) {object[12].Graphic = 492; return;}
else if (myCounter1 == 1 && myCounter2 == 4) {object[12].Graphic = 486; return;}
else if (myCounter1 == 2 && myCounter2 == 1) {object[12].Graphic = 507; return;}
else if (myCounter1 == 2 && myCounter2 == 2) {object[12].Graphic = 501; return;}
else if (myCounter1 == 2 && myCounter2 == 3) {object[12].Graphic = 495; return;}
else if (myCounter1 == 2 && myCounter2 == 4) {object[12].Graphic = 489; return;}
else if (myCounter1 == 3 && myCounter2 == 1) {object[12].Graphic = 505; return;}
else if (myCounter1 == 3 && myCounter2 == 2) {object[12].Graphic = 499; return;}
else if (myCounter1 == 3 && myCounter2 == 3) {object[12].Graphic = 493; return;}
else if (myCounter1 == 3 && myCounter2 == 4) {object[12].Graphic = 487; return;}
else if (myCounter1 == 4 && myCounter2 == 1) {object[12].Graphic = 502; return;}
else if (myCounter1 == 4 && myCounter2 == 2) {object[12].Graphic = 496; return;}
else if (myCounter1 == 4 && myCounter2 == 3) {object[12].Graphic = 490; return;}
else if (myCounter1 == 4 && myCounter2 == 4) {object[12].Graphic = 484; return;}
else if (myCounter1 == 5 && myCounter2 == 1) {object[12].Graphic = 506; return;}
else if (myCounter1 == 5 && myCounter2 == 2) {object[12].Graphic = 500; return;}
else if (myCounter1 == 5 && myCounter2 == 3) {object[12].Graphic = 494; return;}
else if (myCounter1 == 5 && myCounter2 == 4) {object[12].Graphic = 488; return;}
else if (myCounter1 == 6 && myCounter2 == 1) {object[12].Graphic = 503; return;}
else if (myCounter1 == 6 && myCounter2 == 2) {object[12].Graphic = 497; return;}
else if (myCounter1 == 6 && myCounter2 == 3) {object[12].Graphic = 491; return;}
else if (myCounter1 == 6 && myCounter2 == 4) {object[12].Graphic = 485; return;}
}
I can see that on Line 128 of the full room code listing that object[2] relates to the variables myCounter3 and myCounter4. But I don't see where you handle either of those variables anywhere else in the code you posted (besides declaring them).
Edit: deleted, I was wrong.
Quote from: heltenjon on Thu 06/03/2025 08:54:31Edit: deleted, I was wrong.
In what way?
Edit: Never mind. You caught yourself as I was posting.
Yes, you're still checking myCounter1 and myCounter2, not myCounter3 and myCounter4.
---
Sorry, but please do yourself a favor and learn how to not write code like that.
Leaving aside how tedious this is to maintain, it's also really prone to typos.
First of all, please do not use variables like "myCounter1", "myCounter2", etc. It's a temperature and a height, so why not actually use "temp1" and "height1" for starters? Or t1 and h1?
Also, if you organize your sprite numbers, you can replace this *entire block* with a single line like
object[11].Graphic = 384 + t1 * 4 + h1;
You're already using an X/Y chart, now do the same for your sprite numbers. Instead of using 1 as the lowest number, make everything zero-based, at least internally.
The temperature has six different values, so 0-5. The height has four different values, 0-3.
Multiplying the temperature by 4 (the amount of height values) and adding the height will produce the numbers 0 to 23. Now simply add the first sprite number as offset and there your go.
If you add all the sprites to AGS in the correct order you won't even have to edit the sprite numbers.
TL;DR: Debugging code like this is a pointless exercise.
---
Also note that this code does not have to be inside repeatedly_execute/room_RepExec. The object's .Graphic only changes after one of the ints has changed, so that is the only point in time where you actually need to update it: right after an int change.
pell has found at least one issue, but I would point out a couple of other problems with this code.
First, please fix your indentation. Stuff like this is awful:
function oObject20_AnyClick()
{
if (object[20].Graphic == 410)
{object[20].Graphic = 411;
Second, you're using a lot of return statements all over the place. An old programming principle, due to Dijkstra, is that every function should have only one return statement. In practice it is often convenient to bend this rule, but it is still something to keep in mind. Having too many places a function can exit can make the program flow hard to follow. And most of these return statements are unnecessary because they're part of an if/else-if structure: only the block under the first condition that evaluates as true will run anyway.
And finally, you're using room_RepExec() to set the state. An old AGS rule of thumb, due to me, is that if you're using one of the repeatedly executing functions, you're probably doing something "wrong" (meaning: not in a good way). Here, the state only changes when the player clicks on something, so you should put all the common update code into a function and call that whenever an interaction can change the state.
In this case, those two rules combine in a particularly serious way: you're putting multiple return statements into a repeatedly executing function. So as soon as it hits a return statement, it will stop running the rest of the function, and this will keep happening every game cycle. (One reason this is bad is that the repeatedly executing functions very often contain logic for totally unrelated things that need to update, so you don't want to accidentally disable them by hitting a return.)
So in this case, if (object[1].Visible == true) or (object[2].Visible == true), none of the rest of the function will run, since you have a return at the end of each of those blocks. In fact, I don't see how this could work as you describe at all:
Quote from: Jordanowen42 on Thu 06/03/2025 05:50:32"object 1" (the first hatch blocking flow from segment one to segment two) being visible should cause object 11, the segment, to show the graphic for 4/4 on the X/Y chart. That works.
It should set the myCounter1 and myCounter2 values but not do anything else. Only when you set it (and object[2]) to not be visible should the graphics update.
Right, the "return" kills the second part, I didn't even catch that :-D
Quote from: Snarky on Thu 06/03/2025 09:52:58So in this case, if (object[1].Visible == true) or (object[2].Visible == true), none of the rest of the function will run, since you have a return at the end of each of those blocks. In fact, I don't see how this could work as you describe at all:
Quote from: Khris on Thu 06/03/2025 10:10:36Right, the "return" kills the second part, I didn't even catch that :-D
To be fair, at least as far as I understand the code, that looks like the intended behavior. The visibility of those two objects are set outside this function based on user clicks. If they are false, this function changes the sprites based on certain conditions, and if either are true, it returns without changing any of the sprites.
Oh, there was one more thing I forgot to mention: this problem would be pretty easy to debug yourself by setting a breakpoint and stepping through the code, except that it's a pain to do that in a repeatedly executing function because it keeps pausing the game constantly before you get to the point you want to test. This is another good reason to avoid using room_RepExec() unless absolutely necessary.
Quote from: pell on Thu 06/03/2025 10:46:43To be fair, at least as far as I understand the code, that looks like the intended behavior. The visibility of those two objects are set outside this function based on user clicks. If they are false, this function changes the sprites based on certain conditions, and if either are true, it returns without changing any of the sprites.
As Snarky already pointed out, the code will call "return;" in a ton of cases and thus exit the function before other variables are handled. This is almost guaranteed to not be intentional and very likely the reason why OP is posting in the first place; OP is just copy-pasting code without fully understanding what it does.
Quote from: Khris on Thu 06/03/2025 10:59:15Quote from: pell on Thu 06/03/2025 10:46:43To be fair, at least as far as I understand the code, that looks like the intended behavior. The visibility of those two objects are set outside this function based on user clicks. If they are false, this function changes the sprites based on certain conditions, and if either are true, it returns without changing any of the sprites.
As Snarky already pointed out, the code will call "return;" in a ton of cases and thus exit the function before other variables are handled. This is almost guaranteed to not be intentional and very likely the reason why OP is posting in the first place; OP is just copy-pasting code without fully understanding what it does.
The OP claimed the code worked fine for the first object, but not for the second. I'm thinking the bulk of the body of the function probably needs to be repeated but using myCounter3 and myCounter4.
Yes, but again: the code for the first object is very likely to also call "return;" which will exit the function and thus ensure that the code for the second object is never executed in the first place. Doesn't matter if the variable names are fixed if the code never runs.
Quote from: Khris on Thu 06/03/2025 11:08:17Yes, but again: the code for the first object is very likely to also call "return;" which will exit the function and thus ensure that the code for the second object is never executed in the first place. Doesn't matter if the variable names are fixed if the code never runs.
Are you seeing a short circuit that I'm missing? Most of the return statements are superfluous. After the first two statements that check for visibility, all the other returns could be deleted (and should be) with no change to control flow that I can see (edit: only because the function just returns anyway after all these if/else statements).
Edit: I think the behavior in your first sentence is what the OP intends from what I can see.
Edit again: The OP can clarify, but it looks to me like it's:
If object 1 visible, do nothing.
If object 2 visible, do nothing.
Otherwise, do all this stuff. (Except there is probably missing stuff causing the missing behavior.)
@pell My point is that in the "all this stuff" part, if any of the lines concerning segment #1 are a match, the code for segment #2
never runs. This is also most likely what caused OP to open this thread.
Because why would they deliberately sabotage their segment2 code, then ask here why it doesn't work?
None of this is intentional, because it's all a hot, flaming mess. Again, sorry. But this needs to be unlearned ASAP.
As an aside: using the object[] array in a room script is possible but less readable than using oButton1 or oSegment2 or whatever.
@Khris, the code will run if object[1] is turned off again, so
@pell is right that it could in theory be intended behavior. (I have written similar logic for things like mouse gestures that should only trigger once the button is released.) It's not how I read the description, but it might be glossing over that detail, and if Jordanowen says it does work...
I also took this bit:
Quote from: Jordanowen42 on Thu 06/03/2025 05:50:32Right now I'm trying to have the code respond to a simple set of variables
... to mean that this is only the first step of building the complete logic, so that the lines are temporary/incomplete in order to test that the idea works.
Of course you are right that it should all be scrapped and replaced by a simple expression. An alternative to doing sprite ID arithmetic (potentially requiring a reimport of all the sprites to get them in the right order) would be to load the sprites into a view, and map e.g. the temperature to the loop number and the height to the frame number. (So for temperature 2 and height 3 you would use loop 2 frame 3.) That way you would be able to see the sprite variations in a table-like layout in the editor, and use the animation preview to inspect them.
Quote from: Khris on Thu 06/03/2025 11:35:17@pell
My point is that in the "all this stuff" part, if any of the lines concerning segment #1 are a match, the code for segment #2 never runs. This is also most likely what caused OP to open this thread.
Because why would they deliberately sabotage their segment2 code, then ask here why it doesn't work?
None of this is intentional, because it's all a hot, flaming mess. Again, sorry. But this needs to be unlearned ASAP.
As an aside: using the object[] array in a room script is possible but less readable than using oButton1 or oSegment2 or whatever.
I think we're talking past each other. My point is that the code for object 2 is probably not running because it's probably missing. All the "stuff" looks to me like it applies to object1.
I do need to clarify that when I said the control flow is the same with or without most of those return statments, I meant that the function just returns after the if/else statements anyway. Of course, if any other statements are added afterwards, those returns within the bodies of the if statements would shortcircuit the control.
OP was copy-pasting the two dozen lines then replacing 11 with 12 but forgot to also rename the variables is my assessment.
So the second block is very much supposed to run in all cases and supposed to handle the second lava pipe segment (object[12]) but doesn't because the segment #1 / object[11] code always prematurely exits the function.
If I'm wrong it doesn't really matter anyway because this entire exchange is moot. This approach is fundamentally flawed and using it should not be encouraged even if certain minor aspects seem like a good idea. I hate to belabor this point but writing code like this needs not to happen, ever.
As an aside, I do not adhere to the "only one return statement" principle because it is bound to create a bunch of nesting but at the same time one obviously shouldn't use returns indiscriminately.
Using a view to connect the two variables and the according sprite is a great idea!
Quote from: Khris on Thu 06/03/2025 12:13:06OP was copy-pasting the two dozen lines then replacing 11 with 12 but forgot to also rename the variables is my assessment.
So the second block is very much supposed to run in all cases and supposed to handle the second lava pipe segment (object[12]) but doesn't because the segment #1 / object[11] code always prematurely exits the function.
This caused me to look back again. I missed that there was a second part in scrolling because it looks like the first part since the OP forgot (presumably) to change the variable names. That's the "missing part".
The solution is surely to change those variable names to myCounter3 and myCounter4 unless we've overlooked something else.
In regards to the problem of returning from the middle of "repeatedly execute":
If there's multiple unrelated stuff updated there, like for example: update puzzle, update character position, update blinking lights on background, and so forth, then I do recommend moving unrelated parts of code into separate functions and call these functions from rep-exec. Then each part will be updated separately, not conflicting with each other.
For a dumb example:
function UpdateTwoObjects()
{
// Idk if this code itself is correct, I'm just copy/pasting it for this example
if (object[1].Visible == true) { myCounter1 = 4; myCounter2 = 4; return; }
if (object[2].Visible == true) { myCounter3 = 4; myCounter4 = 4; return; }
}
function UpdateCounters()
{
// all the counter stuff
}
function room_RepExec()
{
UpdateTwoObjects();
UpdateCounters();
}
If updating counters should be skipped awhole under some condition (like objects visible or not), then you may solve that by adding a early return like this:
function UpdateCounters()
{
// don't update counters if something is off
if (some condition) { return; }
// all the counter stuff
}
PS. By the way, this "early return" code style is one that opposes the aforementioned Djikstra's proposal, apparently.
This pattern has its name in computer science, but I keep forgetting it.
Quote from: Khris on Thu 06/03/2025 11:35:17@pell
My point is that in the "all this stuff" part, if any of the lines concerning segment #1 are a match, the code for segment #2 never runs. This is also most likely what caused OP to open this thread.
Because why would they deliberately sabotage their segment2 code, then ask here why it doesn't work?
None of this is intentional, because it's all a hot, flaming mess. Again, sorry. But this needs to be unlearned ASAP.
As an aside: using the object[] array in a room script is possible but less readable than using oButton1 or oSegment2 or whatever.
I changed the segment 2 script so it's myCounter 3 and 4. Still nothing. Going to implement some more ideas.
Some really good stuff here guys- I really appreciate it. Will implement these ideas and get back to you.
Quote from: Jordanowen42 on Thu 06/03/2025 23:55:18Quote from: Khris on Thu 06/03/2025 11:35:17@pell
My point is that in the "all this stuff" part, if any of the lines concerning segment #1 are a match, the code for segment #2 never runs. This is also most likely what caused OP to open this thread.
Because why would they deliberately sabotage their segment2 code, then ask here why it doesn't work?
None of this is intentional, because it's all a hot, flaming mess. Again, sorry. But this needs to be unlearned ASAP.
As an aside: using the object[] array in a room script is possible but less readable than using oButton1 or oSegment2 or whatever.
I changed the segment 2 script so it's myCounter 3 and 4. Still nothing. Going to implement some more ideas.
Did you mean for segment 2 to run if segment 1 does not? Because the way you have it coded, the function will return if any of the if statements in segment 1 fail.
[/quote]
Did you mean for segment 2 to run if segment 1 does not? Because the way you have it coded, the function will return if any of the if statements in segment 1 fail.
[/quote]
No I mean for segment 1 to run then segment 2 and so on (there will be nine total.).
Hey guys-
Improvements implemented and first problem solved but it brings me to my second (and ongoing) problem which I will outline in this video:
So that's where it stands. I know I keep saying this but thanks so much for your help!
Here's the code as it currently stands:
// room script file
// Segment 1
int myCounter1 =0 ;
int myCounter2 =0 ;
// Segment 2
int myCounter3 =0 ;
int myCounter4 =0 ;
// Segment 3
int myCounter5 ;
int myCounter6 ;
// Segment 4
int myCounter7 ;
int myCounter8 ;
// Segment 5
int myCounter9 ;
int myCounter10 ;
// Segment 6
int myCounter11 ;
int myCounter12 ;
// Segment 7
int myCounter13 ;
int myCounter14 ;
// Segment 8
int myCounter15 ;
int myCounter16 ;
// Segment 9
int myCounter17 ;
int myCounter18 ;
function oObject20_AnyClick()
{
if (object[20].Graphic == 410)
{object[20].Graphic = 411;
object[1].Visible = false;
object[2].Visible = true;
object[3].Visible = false;
return;}
if (object[20].Graphic == 411)
{object[20].Graphic = 412;
object[2].Visible = false;
object[3].Visible = true;
return;}
if (object[20].Graphic == 412)
{object[20].Graphic = 410;
object[1].Visible = true;
object[3].Visible = false;
return;}
}
function oObject21_AnyClick()
{
if (object[21].Graphic == 410)
{object[21].Graphic = 411;
object[4].Visible = false;
object[5].Visible = true;
object[6].Visible = false;
return;}
if (object[21].Graphic == 411)
{object[21].Graphic = 412;
object[4].Visible = false;
object[5].Visible = false;
object[6].Visible = true;
return;}
if (object[21].Graphic == 412)
{object[21].Graphic = 410;
object[4].Visible = true;
object[5].Visible = false;
object[6].Visible = false;
return;}
}
function oObject22_AnyClick()
{
if (object[22].Graphic == 410)
{object[22].Graphic = 411;
object[7].Visible = false;
object[8].Visible = true;
object[9].Visible = false;
return;}
if (object[22].Graphic == 411)
{object[22].Graphic = 412;
object[7].Visible = false;
object[8].Visible = false;
object[9].Visible = true;
return;}
if (object[22].Graphic == 412)
{object[22].Graphic = 410;
object[7].Visible = true;
object[8].Visible = false;
object[9].Visible = false;
return;}
}
function room_Load()
{
object[1].Visible = true;
object[4].Visible = true;
object[7].Visible = true;
}
function UpdateTwoObjects()
{
if (object[1].Visible == true) { myCounter1 = 4; myCounter2 = 4; return;}
if (object[2].Visible == true) { myCounter3 += 3; myCounter4 += 2; myCounter1 -= 1; myCounter2 -= 1; return;}
}
function UpdateCounters()
{
// Segment 1 integers
if (myCounter1 == 0 && myCounter2 == 0) {object[11].Graphic = 376; }
else if (myCounter1 == 1 && myCounter2 == 1) {object[11].Graphic = 404; } //check
else if (myCounter1 == 1 && myCounter2 == 2) {object[11].Graphic = 398; } //check
else if (myCounter1 == 1 && myCounter2 == 3) {object[11].Graphic = 392; } //check
else if (myCounter1 == 1 && myCounter2 == 4) {object[11].Graphic = 386; } //check
else if (myCounter1 == 2 && myCounter2 == 1) {object[11].Graphic = 407; } //check
else if (myCounter1 == 2 && myCounter2 == 2) {object[11].Graphic = 401; } //check
else if (myCounter1 == 2 && myCounter2 == 3) {object[11].Graphic = 395; } //check
else if (myCounter1 == 2 && myCounter2 == 4) {object[11].Graphic = 389; } //check
else if (myCounter1 == 3 && myCounter2 == 1) {object[11].Graphic = 405; } //check
else if (myCounter1 == 3 && myCounter2 == 2) {object[11].Graphic = 399; } //check
else if (myCounter1 == 3 && myCounter2 == 3) {object[11].Graphic = 393; } //check
else if (myCounter1 == 3 && myCounter2 == 4) {object[11].Graphic = 387; } //check
else if (myCounter1 == 4 && myCounter2 == 1) {object[11].Graphic = 402; } //check
else if (myCounter1 == 4 && myCounter2 == 2) {object[11].Graphic = 396; } //check
else if (myCounter1 == 4 && myCounter2 == 3) {object[11].Graphic = 390; } //check
else if (myCounter1 == 4 && myCounter2 == 4) {object[11].Graphic = 384; } //check
else if (myCounter1 == 5 && myCounter2 == 1) {object[11].Graphic = 406; } //check
else if (myCounter1 == 5 && myCounter2 == 2) {object[11].Graphic = 400; } //check
else if (myCounter1 == 5 && myCounter2 == 3) {object[11].Graphic = 394; } //check
else if (myCounter1 == 5 && myCounter2 == 4) {object[11].Graphic = 388; } //check
else if (myCounter1 == 6 && myCounter2 == 1) {object[11].Graphic = 403; } //check
else if (myCounter1 == 6 && myCounter2 == 2) {object[11].Graphic = 397; } //check
else if (myCounter1 == 6 && myCounter2 == 3) {object[11].Graphic = 391; } //check
else if (myCounter1 == 6 && myCounter2 == 4) {object[11].Graphic = 385; } //check
// Segment 2 integers
if (myCounter3 == 0 && myCounter4 == 0) {object[12].Graphic = 376; }
else if (myCounter3 == 1 && myCounter4 == 1) {object[12].Graphic = 404; } //check
else if (myCounter3 == 1 && myCounter4 == 2) {object[12].Graphic = 398; } //check
else if (myCounter3 == 1 && myCounter4 == 3) {object[12].Graphic = 392; } //check
else if (myCounter3 == 1 && myCounter4 == 4) {object[12].Graphic = 386; } //check
else if (myCounter3 == 2 && myCounter4 == 1) {object[12].Graphic = 407; } //check
else if (myCounter3 == 2 && myCounter4 == 2) {object[12].Graphic = 401; } //check
else if (myCounter3 == 2 && myCounter4 == 3) {object[12].Graphic = 395; } //check
else if (myCounter3 == 2 && myCounter4 == 4) {object[12].Graphic = 389; } //check
else if (myCounter3 == 3 && myCounter4 == 1) {object[12].Graphic = 405; } //check
else if (myCounter3 == 3 && myCounter4 == 2) {object[12].Graphic = 399; } //check
else if (myCounter3 == 3 && myCounter4 == 3) {object[12].Graphic = 393; } //check
else if (myCounter3 == 3 && myCounter4 == 4) {object[12].Graphic = 387; } //check
else if (myCounter3 == 4 && myCounter4 == 1) {object[12].Graphic = 402; } //check
else if (myCounter3 == 4 && myCounter4 == 2) {object[12].Graphic = 396; } //check
else if (myCounter3 == 4 && myCounter4 == 3) {object[12].Graphic = 390; } //check
else if (myCounter3 == 4 && myCounter4 == 4) {object[12].Graphic = 384; } //check
else if (myCounter3 == 5 && myCounter4 == 1) {object[12].Graphic = 406; } //check
else if (myCounter3 == 5 && myCounter4 == 2) {object[12].Graphic = 400; } //check
else if (myCounter3 == 5 && myCounter4 == 3) {object[12].Graphic = 394; } //check
else if (myCounter3 == 5 && myCounter4 == 4) {object[12].Graphic = 388; } //check
else if (myCounter3 == 6 && myCounter4 == 1) {object[12].Graphic = 403; } //check
else if (myCounter3 == 6 && myCounter4 == 2) {object[12].Graphic = 397; } //check
else if (myCounter3 == 6 && myCounter4 == 3) {object[12].Graphic = 391; } //check
else if (myCounter3 == 6 && myCounter4 == 4) {object[12].Graphic = 385; } //check
}
function room_RepExec()
{
UpdateTwoObjects();
UpdateCounters();
}
I've watched the video, and I'm going through the code to try to match these variables names to what they're meant to represent.
In case you're still up, can you tell me if myCounter1 and myCounter3 are supposed to be the six states and myCounter2 and myCounter4 the four temperatures? I ask because myCounter1 and myCounter3 show seven states in the code, 0 through 6.
Quote from: pell on Fri 07/03/2025 07:37:05I've watched the video, and I'm going through the code to try to match these variables names to what they're meant to represent.
In case you're still up, can you tell me if myCounter1 and myCounter3 are supposed to be the six states and myCounter2 and myCounter4 the four temperatures? I ask because myCounter1 and myCounter3 show seven states in the code, 0 through 6.
So the counters represent the temp and height of lava in each segment of the pipe. Each set of two counters is assigned to one segment. Odd counters refer to the temperature on the spreadsheet I showed in the video and even numbers refer to the height. (So vertical and horizontal, respectively.
Objects 1-9 refer to the rectangular lights that indicate which hatch is closed. If a hatch light is on that means that hatch is closed.
Objects 11-19 refer to the square windows that indicate the temp and fluid levels of the lava in that segment of the pipe.
Objects 20-22 refer to the three switches (top to bottom) that are set to the left of each row of windows.
I think I know what's happening here. You're calling UpdateTwoObjects every game cycle, because you call it from room_RepExec. That means that while object[2] is visible, the calculations to change the values of the counters happen every game cycle. If I'm right about this being the problem, I recommend one of two options:
1. The easiest way is just to call UpdateTwoObjects only when it needs to happen. Am I right in thinking that would be whenever the player clicks on one of the buttons?
2. If you want to call it every game cycle, you could set some kind of TwoObjectsNeedUpdating type of variable, and then set that to true after pressing a button (or whenever the update needs to happen) and then false again after performing the update.
Edit: To be clear, option 2 would normally not be a good idea. But it does illustrate how to selectively control something that would otherwise get changed by a continuous process (like keyboard and mouse input).
I really loved the Myst games. I played the second, third and fourth games in the series, but not the first or last ones. I'm looking forward to seeing how this comes out.
Quote from: pell on Fri 07/03/2025 08:20:53I think I know what's happening here. You're calling UpdateTwoObjects every game cycle, because you call it from room_RepExec. That means that while object[2] is visible, the calculations to change the values of the counters happen every game cycle. If I'm right about this being the problem, I recommend one of two options:
1. The easiest way is just to call UpdateTwoObjects only when it needs to happen. Am I right in thinking that would be whenever the player clicks on one of the buttons?
2. If you want to call it every game cycle, you could set some kind of TwoObjectsNeedUpdating type of variable, and then set that to true after pressing a button (or whenever the update needs to happen) and then false again after performing the update.
Edit: To be clear, option 2 would normally not be a good idea. But it does illustrate how to selectively control something that would otherwise get changed by a continuous process (like keyboard and mouse input).
I really loved the Myst games. I played the second, third and fourth games in the series, but not the first or last ones. I'm looking forward to seeing how this comes out.
I think we're on the right track here but can you tell me what a "game cycle" is? I am very much learning as I go.
To answer your questions, the answer to #1 is yes. But how do I make it update the two objects only when I need it to happen? As regards point two, I think you're on the right track but I'm too much of a n00b to know how to implement that.
If you haven't played Myst 1 I recommend trying RealMyst which is on the Apple app store and, I believe, Steam as well. It's an upgraded version that plays in a full motion 3D environment so it's more like the latter period games you're familiar with. Avoid 5.
A game cycle, more commonly called a game loop, is just the continuous running process of the game. A game is a program that runs in a loop until you tell it to quit. While it's looping, it's checking for user input, updating the screen (animation) and performing the game logic.
The room_RepExec function is called repeatably, so anything you put in there is called repeatedly.
Just call UpdateTwoObjects where in the code you want that to happen. For example, you change visibility of the objects in oObject20_AnyClick() based on mouse clicks, so that might be a good place to call the update.
I want to point out that there's nothing magic about room_RepExec. You can designate a function to run repeatedly while you're in a particular room by clicking its "Repeatedly execute" field in the Events tab under the room's Properties. That function name is just the default name that the editor gives you, and it automatically generates an empty function with that name in your room script.
You can use any allowable function name or even create the function first in the room's script and then enter that name into the "Repeatedly execute" field. If you do change the name, you need to make sure the name in that field matches the name of the function you want to call. Just changing the name in the script won't automatically change the name in the Events tab. This is true of the functions called from the other events as well.
Hold on for one moment...
Quote from: Jordanowen42 on Fri 07/03/2025 06:48:25function UpdateCounters()
{
// Segment 1 integers
if (myCounter1 == 0 && myCounter2 == 0) {object[11].Graphic = 376; }
else if (myCounter1 == 1 && myCounter2 == 1) {object[11].Graphic = 404; } //check
else if (myCounter1 == 1 && myCounter2 == 2) {object[11].Graphic = 398; } //check
else if (myCounter1 == 1 && myCounter2 == 3) {object[11].Graphic = 392; } //check
else if (myCounter1 == 1 && myCounter2 == 4) {object[11].Graphic = 386; } //check
else if (myCounter1 == 2 && myCounter2 == 1) {object[11].Graphic = 407; } //check
else if (myCounter1 == 2 && myCounter2 == 2) {object[11].Graphic = 401; } //check
else if (myCounter1 == 2 && myCounter2 == 3) {object[11].Graphic = 395; } //check
else if (myCounter1 == 2 && myCounter2 == 4) {object[11].Graphic = 389; } //check
else if (myCounter1 == 3 && myCounter2 == 1) {object[11].Graphic = 405; } //check
else if (myCounter1 == 3 && myCounter2 == 2) {object[11].Graphic = 399; } //check
else if (myCounter1 == 3 && myCounter2 == 3) {object[11].Graphic = 393; } //check
else if (myCounter1 == 3 && myCounter2 == 4) {object[11].Graphic = 387; } //check
else if (myCounter1 == 4 && myCounter2 == 1) {object[11].Graphic = 402; } //check
else if (myCounter1 == 4 && myCounter2 == 2) {object[11].Graphic = 396; } //check
else if (myCounter1 == 4 && myCounter2 == 3) {object[11].Graphic = 390; } //check
else if (myCounter1 == 4 && myCounter2 == 4) {object[11].Graphic = 384; } //check
else if (myCounter1 == 5 && myCounter2 == 1) {object[11].Graphic = 406; } //check
else if (myCounter1 == 5 && myCounter2 == 2) {object[11].Graphic = 400; } //check
else if (myCounter1 == 5 && myCounter2 == 3) {object[11].Graphic = 394; } //check
else if (myCounter1 == 5 && myCounter2 == 4) {object[11].Graphic = 388; } //check
else if (myCounter1 == 6 && myCounter2 == 1) {object[11].Graphic = 403; } //check
else if (myCounter1 == 6 && myCounter2 == 2) {object[11].Graphic = 397; } //check
else if (myCounter1 == 6 && myCounter2 == 3) {object[11].Graphic = 391; } //check
else if (myCounter1 == 6 && myCounter2 == 4) {object[11].Graphic = 385; } //check
// Segment 2 integers
if (myCounter3 == 0 && myCounter4 == 0) {object[12].Graphic = 376; }
else if (myCounter3 == 1 && myCounter4 == 1) {object[12].Graphic = 404; } //check
else if (myCounter3 == 1 && myCounter4 == 2) {object[12].Graphic = 398; } //check
else if (myCounter3 == 1 && myCounter4 == 3) {object[12].Graphic = 392; } //check
else if (myCounter3 == 1 && myCounter4 == 4) {object[12].Graphic = 386; } //check
else if (myCounter3 == 2 && myCounter4 == 1) {object[12].Graphic = 407; } //check
else if (myCounter3 == 2 && myCounter4 == 2) {object[12].Graphic = 401; } //check
else if (myCounter3 == 2 && myCounter4 == 3) {object[12].Graphic = 395; } //check
else if (myCounter3 == 2 && myCounter4 == 4) {object[12].Graphic = 389; } //check
else if (myCounter3 == 3 && myCounter4 == 1) {object[12].Graphic = 405; } //check
else if (myCounter3 == 3 && myCounter4 == 2) {object[12].Graphic = 399; } //check
else if (myCounter3 == 3 && myCounter4 == 3) {object[12].Graphic = 393; } //check
else if (myCounter3 == 3 && myCounter4 == 4) {object[12].Graphic = 387; } //check
else if (myCounter3 == 4 && myCounter4 == 1) {object[12].Graphic = 402; } //check
else if (myCounter3 == 4 && myCounter4 == 2) {object[12].Graphic = 396; } //check
else if (myCounter3 == 4 && myCounter4 == 3) {object[12].Graphic = 390; } //check
else if (myCounter3 == 4 && myCounter4 == 4) {object[12].Graphic = 384; } //check
else if (myCounter3 == 5 && myCounter4 == 1) {object[12].Graphic = 406; } //check
else if (myCounter3 == 5 && myCounter4 == 2) {object[12].Graphic = 400; } //check
else if (myCounter3 == 5 && myCounter4 == 3) {object[12].Graphic = 394; } //check
else if (myCounter3 == 5 && myCounter4 == 4) {object[12].Graphic = 388; } //check
else if (myCounter3 == 6 && myCounter4 == 1) {object[12].Graphic = 403; } //check
else if (myCounter3 == 6 && myCounter4 == 2) {object[12].Graphic = 397; } //check
else if (myCounter3 == 6 && myCounter4 == 3) {object[12].Graphic = 391; } //check
else if (myCounter3 == 6 && myCounter4 == 4) {object[12].Graphic = 385; } //check
}
This looks like you've copy-pasted the same code twice, just changing the object index and variables. And you're planning to do the same thing for each of the nine segments?
STOP!If you ever find yourself copying large chunks of code in multiple places, you need to stop and think, because that's hardly ever right. What you should do here is to have a function that updates one of the displays, which takes the object that needs to be updated and the values that control how it will be updated as arguments:
// Corrected function name
function UpdateLavaState()
{
if (object[1].Visible == true) { myCounter1 = 4; myCounter2 = 4; return;}
if (object[2].Visible == true) { myCounter3 += 3; myCounter4 += 2; myCounter1 -= 1; myCounter2 -= 1; return;}
}
function UpdateLavaDisplay(Object* lavaDisplay, int lavaTemp, int lavaHeight)
{
if (lavaTemp == 0 && lavaHeight == 0) { lavaDisplay.Graphic = 376; }
else if (lavaTemp == 1 && lavaHeight == 1) { lavaDisplay.Graphic = 404; } //check
else if (lavaTemp == 1 && lavaHeight == 2) { lavaDisplay.Graphic = 398; } //check
else if (lavaTemp == 1 && lavaHeight == 3) { lavaDisplay.Graphic = 392; } //check
else if (lavaTemp == 1 && lavaHeight == 4) { lavaDisplay.Graphic = 386; } //check
else if (lavaTemp == 2 && lavaHeight == 1) { lavaDisplay.Graphic = 407; } //check
else if (lavaTemp == 2 && lavaHeight == 2) { lavaDisplay.Graphic = 401; } //check
else if (lavaTemp == 2 && lavaHeight == 3) { lavaDisplay.Graphic = 395; } //check
else if (lavaTemp == 2 && lavaHeight == 4) { lavaDisplay.Graphic = 389; } //check
else if (lavaTemp == 3 && lavaHeight == 1) { lavaDisplay.Graphic = 405; } //check
else if (lavaTemp == 3 && lavaHeight == 2) { lavaDisplay.Graphic = 399; } //check
else if (lavaTemp == 3 && lavaHeight == 3) { lavaDisplay.Graphic = 393; } //check
else if (lavaTemp == 3 && lavaHeight == 4) { lavaDisplay.Graphic = 387; } //check
else if (lavaTemp == 4 && lavaHeight == 1) { lavaDisplay.Graphic = 402; } //check
else if (lavaTemp == 4 && lavaHeight == 2) { lavaDisplay.Graphic = 396; } //check
else if (lavaTemp == 4 && lavaHeight == 3) { lavaDisplay.Graphic = 390; } //check
else if (lavaTemp == 4 && lavaHeight == 4) { lavaDisplay.Graphic = 384; } //check
else if (lavaTemp == 5 && lavaHeight == 1) { lavaDisplay.Graphic = 406; } //check
else if (lavaTemp == 5 && lavaHeight == 2) { lavaDisplay.Graphic = 400; } //check
else if (lavaTemp == 5 && lavaHeight == 3) { lavaDisplay.Graphic = 394; } //check
else if (lavaTemp == 5 && lavaHeight == 4) { lavaDisplay.Graphic = 388; } //check
else if (lavaTemp == 6 && lavaHeight == 1) { lavaDisplay.Graphic = 403; } //check
else if (lavaTemp == 6 && lavaHeight == 2) { lavaDisplay.Graphic = 397; } //check
else if (lavaTemp == 6 && lavaHeight == 3) { lavaDisplay.Graphic = 391; } //check
else if (lavaTemp == 6 && lavaHeight == 4) { lavaDisplay.Graphic = 385; } //check
}
And then you could just do:
function room_RepExec()
{
UpdateLavaState();
UpdateLavaDisplay(object[11], myCounter1, myCounter2); // Segment 1
UpdateLavaDisplay(object[12], myCounter3, myCounter4); // Segment 2
}
As you add more segments, you'll save more and more code.
(Khris already told you about other things you should be doing that would be better than this, but I guess as a novice coder you are confused by his advice, so let's take it one step at a time.)
Made a demo game:
https://drive.google.com/file/d/1Sypp0xs5XjlZUQleTxxjGfJbeQxGkBvB/view?usp=sharing
I implemented the three buttons; they switch hatches and randomly set the temperature and level.
This uses three sprites only, a few more are needed to polish the optics. The colored squares are rectangles drawn to the background, then the panel is drawn on top.
Here's the room script:
Spoiler
// room script file
// for each line, store active column, temp and level
int hatch[3];
int temp[3];
int level[3];
// 6 colors for 6 temperatures
int col[6];
void DrawSquare(DrawingSurface* ds, int line) {
ds.DrawingColor = col[temp[line]];
int x = hatch[line] * 220 + 370;
int y = line * 140 + 180;
ds.DrawRectangle(x, y + 40 - level[line] * 5, x + 60, y + 60);
}
void UpdateScreen() {
DrawingSurface* ds = Room.GetDrawingSurfaceForBackground();
ds.Clear(0);
// draw squares on background
for (int line = 0; line < 3; line++) {
DrawSquare(ds, line);
}
// draw panel on top
ds.DrawImage(286, 135, 3);
// draw green lights on panel
for (int line = 0; line < 3; line++) {
for (int column = 0; column < 3; column++) {
int slot = 2; // off
if (hatch[line] == column) slot = 1; // on
ds.DrawImage(column * 215 + 475, line * 142 + 175, slot);
}
}
ds.Release();
}
function room_Load()
{
// grey
col[0] = Game.GetColorFromRGB(128, 128, 128);
// light orange
col[1] = Game.GetColorFromRGB(255, 220, 80);
// orange
col[2] = Game.GetColorFromRGB(255, 160, 0);
// dark orange
col[3] = Game.GetColorFromRGB(210, 135, 0);
// light red
col[4] = Game.GetColorFromRGB(255, 100, 100);
// dark red
col[5] = Game.GetColorFromRGB(170, 0, 0);
UpdateScreen();
}
void HandleLine(int line) {
hatch[line] = (hatch[line] + 1) % 3; // switch column
// random values for now
temp[line] = Random(5);
level[line] = Random(5);
UpdateScreen();
}
function hButton_AnyClick(Hotspot *theHotspot, CursorMode mode)
{
// hotspots 1-3 => lines 0-2
HandleLine(theHotspot.ID - 1);
}
Quote from: Jordanowen42 on Fri 07/03/2025 06:48:25(Khris already told you about other things you should be doing that would be better than this, but I guess as a novice coder you are confused by his advice, so let's take it one step at a time.)
You are correct that I definitely find a lot of this confusing but I suppose the difficulty I'm having trouble seeing is how these things pertain to my overall problem. It seems like most of what you're telling me are essentially formatting issues that would make the script more succinct but I don't see how they will resolve the issues I described in the video.
Also, while I realize that you probably don't have the time it would help to see your updates inside of the larger whole of my existing script. A lot of what I'm seeing here is very alien to me.
Quote from: Khris on Fri 07/03/2025 10:10:12Made a demo game:
https://drive.google.com/file/d/1Sypp0xs5XjlZUQleTxxjGfJbeQxGkBvB/view?usp=sharing
I implemented the three buttons; they switch hatches and randomly set the temperature and level.
This uses three sprites only, a few more are needed to polish the optics. The colored squares are rectangles drawn to the background, then the panel is drawn on top.
Here's the room script:
Spoiler
// room script file
// for each line, store active column, temp and level
int hatch[3];
int temp[3];
int level[3];
// 6 colors for 6 temperatures
int col[6];
void DrawSquare(DrawingSurface* ds, int line) {
ds.DrawingColor = col[temp[line]];
int x = hatch[line] * 220 + 370;
int y = line * 140 + 180;
ds.DrawRectangle(x, y + 40 - level[line] * 5, x + 60, y + 60);
}
void UpdateScreen() {
DrawingSurface* ds = Room.GetDrawingSurfaceForBackground();
ds.Clear(0);
// draw squares on background
for (int line = 0; line < 3; line++) {
DrawSquare(ds, line);
}
// draw panel on top
ds.DrawImage(286, 135, 3);
// draw green lights on panel
for (int line = 0; line < 3; line++) {
for (int column = 0; column < 3; column++) {
int slot = 2; // off
if (hatch[line] == column) slot = 1; // on
ds.DrawImage(column * 215 + 475, line * 142 + 175, slot);
}
}
ds.Release();
}
function room_Load()
{
// grey
col[0] = Game.GetColorFromRGB(128, 128, 128);
// light orange
col[1] = Game.GetColorFromRGB(255, 220, 80);
// orange
col[2] = Game.GetColorFromRGB(255, 160, 0);
// dark orange
col[3] = Game.GetColorFromRGB(210, 135, 0);
// light red
col[4] = Game.GetColorFromRGB(255, 100, 100);
// dark red
col[5] = Game.GetColorFromRGB(170, 0, 0);
UpdateScreen();
}
void HandleLine(int line) {
hatch[line] = (hatch[line] + 1) % 3; // switch column
// random values for now
temp[line] = Random(5);
level[line] = Random(5);
UpdateScreen();
}
function hButton_AnyClick(Hotspot *theHotspot, CursorMode mode)
{
// hotspots 1-3 => lines 0-2
HandleLine(theHotspot.ID - 1);
}
I ran the game you provided and it worked but I'm not sure how to incorporate this into my code. I'm pretty much at the level of copy/pasting and what you see in my original code is the extent of my programming knowledge. I appreciate your help tho.
Quote from: Jordanowen42 on Sat 08/03/2025 06:21:51You are correct that I definitely find a lot of this confusing but I suppose the difficulty I'm having trouble seeing is how these things pertain to my overall problem. It seems like most of what you're telling me are essentially formatting issues that would make the script more succinct but I don't see how they will resolve the issues I described in the video.
I understand what you mean, but I would turn that around. You're over-focused on a particular bug that is blocking you from moving forward
right now (which is a very natural attitude when you just want it to work, dammit!), but the bigger problem is that you've built it wrong from the start.
This is essentially a pretty simple task, but you've over-complicated it in various ways, which leaves a lot of scope for mistakes. If the structure isn't fixed, you're going to be playing whack-a-mole with bugs every step of the way, and even if you ultimately get it to work it will be a mess that doesn't really make sense.
That's why it's better to step back and try to fix the foundation. There's a good chance the bug then won't appear at all, and if it does it will be much easier to fix.
And consider: this is not the only bit of coding you'll be doing for this game, right? In the big picture, it's more valuable to learn ways to avoid or solve such problems in the future, than to hack this until it somehow works and then immediately run into similar difficulties with the next task.
@Jordanowen42 Are you still having the problem we talked about?
Regarding the coding advice we've given you, I suggest taking whatever makes sense to you as a beginner and moving on to make your game. You can fall into a trap of rewriting things every time you get (or somebody gives you) a better idea and never get your project finished.
A lot of these things will make more sense to you as you gain experience.
A first step would be to replace myCounter1, myCounter2, etc. with properly named arrays.
Using arrays is very basic but also very useful.
Declare one at the top of the script:
int temp[3]; // three is the size, i.e. the number of variables you'll get
This creates three variables: temp[0], temp[1] and temp[2]. You can use these exactly like you would temp1, temp2 and temp3 with the added benefit that you can use a variable as the index:
int a = 1;
temp[a] = 4;
You can even use an expression:
temp[(4 + 2) / 3]
for instance is perfectly fine and will be the equivalent of temp[2].
(These examples are pretty nonsensical, they're just supposed to show what is possible)
The next useful thing is custom functions; you're already using them. It essentially means turning a bunch of lines into a single command, with the additional benefit of being able to customize each call using the function's parameters.
Writing code for Myst-style puzzles is way easier to do and debug if you learn a few basic programming concepts first.
Like Snarky said, it's not just about implementing this specific puzzle.
Let me pose another question- and I'm quite serious: how much would one of you chaps charge to program the whole puzzle for me?
Quote from: Jordanowen42 on Sun 09/03/2025 03:38:16Let me pose another question- and I'm quite serious: how much would one of you chaps charge to program the whole puzzle for me?
I'm always up for a freelance gig, and you can message me if you're serious. But like I said before, I think you're probably one line of code away from fixing the immediate issue of the counter automatically changing through all its stages.