Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Messages - ThreeOhFour

#21
Thanks for the information! I did some tests with the different drivers and see that there's a difference there. Good to know, thank you.
#22
I've been taking a look at the alternate blending modes added to AGS 4.0 and some of them seem to handle alpha channels in a way different than I expect from these modes. Normal, additive and subtractive blending modes act exactly as I expect them to, but the rest seem to have trouble processing the alpha channel correctly, with alpha seeming to be processed without any gradation, and even blending where the image is completely transparent. Here's an example:

Normal blending mode

Mutliply blending mode

I'm using build 4.00.00.09, and I've put up a copy of the sprite used in this test here.
#23
I use Krita for the animation in Old Skies and also general compositing of VFX and things that need animated layers and masks. I use Clip Studio Paint for all digital painting - finally ditched Photoshop in favour of it a couple of years ago. Aseprite for pixel work. Moho for very specific 2D animation things and Blender for all sorts of odd jobs like VFX and the like.
#24
I enjoyed The Witness immensely when I first played it. I like solving puzzles, and it has an excellent puzzle sense, and some wonderfully devilish tricks it plays on you. The twist/reveal/whatever is worth experiencing firsthand, it's that good.

I revisited it a few weeks ago while thinking about design, and came away feeling quite empty in terms of what I wanted to take from it. The Witness is a world that exists to entertain you with logic. The things that it has to say are largely things that other people had to say that have been collated and acted nicely. The world that you explore is a world that you explore in order to find more facets of logic, and in finding those, you use them to solve more puzzles.

It's a Sisyphean cycle that ultimately has a wonderful moment where Sisyphus looks down at the boulder he's pushing up the hill and realises that it's the world, and on the world he sees himself pushing the world up a hill and it's a wonderful revelation and what it reveals is... more hills to push your boulder up.

I really like the logic tricks in The Witness. The process of slowly picking apart that knot of a world, concept by concept, trick by trick was one of the best puzzle solving experiences I've ever had, if not the best, and with a difficulty on par with Riven which left me feeling full when I had finally completed it. But in my head Riven exists as a world, a culture, a place where I spent time and learned about it. The Witness exists as a series of very good and beautiful logic puzzles.
#25
I am indeed using it on an overlay, and its transparency varies by 40% to give it a nice flickering effect. The colour has to stay how it is, though, it's an art direction thing! But yes in general I am a big fan of how the overlay system works with dynamic sprites, it's such a nice setup.
#26
Thank you, CW, that fixed it perfectly. I also went through some issues with the compiler finding problems in the Tween module with Edmundito and he praised the quality of the new compiler and the errors it catches!
#27
I just switched AGS 4.0 to use the extended script compiler, and now rellax gives me this error:

rellax.asc(679): 'Rellax::set_TargetCharacter' has the qualifiers '' here but 'static' elsewhere. See rellax.ash line 89

I realise that AGS 4.0 is still in development, but figured it would be worth mentioning here!
#28
Quote from: Crimson Wizard on Fri 06/12/2024 09:56:07Make sure you are using the new v4 script compiler. There's a Script compiler selection in General Settings -> Compiler.

That was the solution, thank you very much! And now I can just call Character.Energy, what a superbly useful feature this is!

Quote from: Snarky on Fri 06/12/2024 10:41:17Does this example have anything to do with the (very cool) lightning arc effect?

I did this one with a for loop, but was planning on writing another effect today which is a little more difficult for me to conceptualise because I'm not very good at planning things around modular arithmetic. Though I was very grateful earlier today when I was setting sprites in a loop based on a calculation and found that AGS supports the % remainder operator. But I figured I should investigate what other options there are before I start trying to build the effect!

I have heard of recursion in code but knew absolutely nothing about it, that's fascinating! This in particular sounds incredibly empowering:

"it would check the distance and decide whether to split it up into sections, calling itself to generate each section, until the sections are short enough to just draw a line"

Time for me to do some more study. I am learning so much lately.

Quote from: Crimson Wizard on Fri 06/12/2024 10:47:50Note that with the linked list you do not have to do recursion, you may do a classic loop over linked list; pseudo-code:

This is a new concept to me, and it seems very useful. Thank you!
#29
I tried setting an attribute today, following that example, but got this error:

"Attributes.ash(2): Error (line 2): expected variable or function after import, not 'attribute'"

I tried a few adjustments but as I am ignorant of the correct way to use these I didn't accomplish much other than getting different errors, so I figured I would post here!

Seeing as this is a conversation about best practices, I may as well ask about other ways of doing a single action to multiple elements. Let's say I want to draw l number of lines, using a function call that calculates their various positions based on an incrementing variable. Is there an alternative way of doing this to either writing it all out line by line or calling:

Code: ags
for (int l = 0; l != 17; l++)
{
  DrawLine(l);
}

I was thinking about this today, and genuinely do not know another way of handling this. Is there something obvious I am missing?
#30
A module also comes ready to take input parameters and provide a result, the intended result being documented by the creator. A piece of code taken from some source and plopped into your script does not. A well made module is likely a very good source to point a beginner at because if they do want to understand how it works they can study it in the way you describe.

If I believed I had to understand *every* line of code that makes things run I wouldn't be using AGS. Or Windows. :=
#31
This looks very nice to use. I will give this a try tomorrow and see how I get on, cheers!
#32
I had this exact conversation with someone who was urging me to use AI for coding help recently. A piece of code that works might seem nice, but if I do not understand the mechanics of it then it is useless to me the moment I want to adjust it or need to fix something with it. It's worth struggling to learn something as long as I understand how the logic works at the conclusion, I think.
#33
Quote from: eri0o on Thu 05/12/2024 09:56:33Seeing this code I would refactor for something completely different, I don't have time right now, but in my head I have like an intermediary managed struct per entity with all things necessary and it's this intermediary managed struct that I would pass around to account for the lack of generics, it would be a bit verbose but I would try to repeat myself a lot only where logic is simple

When I started trying to figure out how I would approach all of this I was debating whether to use custom properties or structs. In the end it seemed to me that custom properties were a much nicer approach - in order to set a hotspot up I can click directly on it in the room editor and assign the necessary values while looking at it, which is very easy and convenient.

While this might look at little clumsy, I will hopefully never have to edit this function again for the duration of developing the game, while I will be adding hotspots for months to come. Having to populate a struct with information each time is quite doable, but feels like it would be less enjoyable. I'm very happy to take the advice, I know my weaknesses in terms of writing code, but from a development point of view this approach seemed to be the one with the least friction for me while implementing gameplay.

And apologies for sparking a debate, definitely not my intent! I appreciate everybody's input. I have very little experience doing this kind of work. :smiley:
#34
In the interests of the discussion, here's the function as it stands now:

Code: ags
function Flux(this Hotspot*)
{
  //======================= initialisation=======================================================================================||
  int player_energy = player.GetProperty(ENERGY);
  int hotspot_energy = this.GetProperty(ENERGY);
  int player_max = player.GetProperty(MAX_ENERGY);
  int hotspot_max = this.GetProperty(MAX_ENERGY);
  int x_coord = this.GetProperty(X_COORDINATE);
  int y_coord = this.GetProperty(Y_COORDINATE);
  ButtonReset(); //turn off the gui controls we have currently active and all related effects
  ButtonLabel.Text = " "; //get rid of the button label text
  this.HotspotWalk(); //walk to the hotspot, face the correct direction, apply any appropriate offsets and fire the default animation if one has been set
  if (this.GetProperty(PROTECTED) == true) this.TakeProtection(); // first check if the hotspot has been protected from interference and remove if so
  //=============================================================================================================================||
  
  
  //======================== end the function if there is no energy==============================================================||
  if (hotspot_energy == 0 && player_energy == 0)
  {
    zNoEnergy(); 
  }
  //=============================================================================================================================||
  
  
  //======================== energy transfer for hotspot has energy==============================================================||
  else if (hotspot_energy != 0) //if the hotspot DOES have energy
  {
    if (player_energy == player_max && hotspot_energy == hotspot_max)
    {
      zPowerFull(); //first make sure the player can take it
    }
    else if (player_energy == player_max && hotspot_energy != hotspot_max)//if player's at energy limit, put energy into the hotspot even if the hotspot has some energy
    {
      DrawPowerParticles(x_coord, y_coord, Give);
      this.GivePower();
      while (hotspot_energy != hotspot_max && player_energy != 0) //keep giving it until the player's energy is empty OR the hotspot can take no more power
      {
        this.ChangeProperty(ENERGY, 1);
        hotspot_energy++;
        player.ChangeProperty(ENERGY, -1);
        player_energy--;
      }
    }
    else
    {
      this.TakePower();//I think the reason I'm not handling DrawPowerParticles() within TakePower() & GivePower() is that the order has to be different to look right? I forget. Seems right.
      DrawPowerParticles(x_coord, y_coord, Take);
      while (hotspot_energy != 0 && player_energy != player_max) //then keep taking it until the player's energy is full OR the hotspot has no power left
      {
        this.ChangeProperty(ENERGY, -1);
        hotspot_energy--;
        player.ChangeProperty(ENERGY, 1);
        player_energy++;
      }
    }
  }
  //=============================================================================================================================||
  
  
  //======================== energy transfer for player has energy===============================================================||
  else if (player_energy != 0) // the hotspot doesn't have some energy but the player does
  {
    if (hotspot_energy == hotspot_max) zAlreadyPowered(); // First check that the hotspot can take power
    else
    {
      DrawPowerParticles(x_coord, y_coord, Give);
      this.GivePower();
      while (hotspot_energy != this.GetProperty(MAX_ENERGY) && player_energy != 0) //then keep giving it until the player's energy is empty OR the hotspot can take no more power
      {
        this.ChangeProperty(ENERGY, 1);
        hotspot_energy++;
        player.ChangeProperty(ENERGY, -1);
        player_energy--;
      }
    }
  }
  //=============================================================================================================================||
  
  
  //====================================================== reset ================================================================||
  this.FinishHotspot();//Plays the interaction animation backwards, removes any offsets applied, resets the player's loop
  //=============================================================================================================================||
}

For reference, the maximum amount that this transfer will ever process at this point is a value of 3. This may change at some point, but it's never going to require many cycles of the loop in any event.

Apologies to cat if this is considered to be getting off-topic but I don't have any specific questions to ask about it, I'm mostly interested in talking about it!
#35
Quote from: Jordanowen42 on Wed 04/12/2024 07:19:12I thought I was supposed to specify "BlueSphereisTakeable == true" but ChatGPT disagrees.

Just to clarify this, because it doesn't look like ChatGPT thought to give you any explanations here (another good reason to ask AGS folks instead of ChatGPT). The "==" operator is used to check things, not set them. The reason Snarky's version works is because he used the "=" operator. That's the one that sets things.

I am not much of a programmer and so sometimes I accidentally use the wrong one of these myself. It's a very good idea to search your AGS manual for a list of the operators and what they do, because knowing this will be very helpful for figuring out problems like this!
#36
I figured it would be a little annoying if I endlessly bumped the thread myself with nobody else replying. But maybe I can make a habit of that. Currently I'm posting weekly, and I've been updating the first post here when I do. I've put up this week's post just this hour.

The while loop is probably a strange way of doing things! Edmundo already told me this was not the best approach, and given me an alternate way of approaching things. I haven't tried his way yet, but I like it when I can follow a train of logic step by step in my head, and this is the way that allowed me to do that here. I know I am not a very competent programmer.  :=

Very good to have those texts posted here, too. Considering how many years it's been since I tried building a game in AGS I have been referring to the manual regularly for even the most basic things, let alone these nice new things, but I'll make sure I bookmark these. It took me quite a while to figure out how to remove walkable areas with AGS 4, but most of my other issues have been that I'm still just figuring things out.
#37
I love this idea.
#38
Quote from: Crimson Wizard on Wed 04/12/2024 01:46:33Normally anything you do in "room load" is happening prior to the first room's draw. There should not be any visible "jumps".

I probably need to re-check whether I have the calculation in repeatedly_execute_always or late_repeatedly_execute_always (although I think I tried this!). The Wait(1); in room load did hide the problem, but was definitely intended as a quick hide until I fixed it properly.

QuoteWhat I meant as debug was actually the setting in general settings

Yep! I was replying to the bit about only when running from the editor! Or maybe I misunderstood what you meant by that, it's quite possible!  :=
#39
Yes, this was a quick workaround in a room where object positions are calculated according to some variables, I'm going to replace the Wait() with a call to that function now. I just wanted to stop the strange jump to new positions after the fade in quickly while I was having people test it.  :smiley:
#40
Thanks for the input, all!

QuoteNo, it's not really necessary: when AGS closes it frees up all the memory anyway.

Yes, I read in the manual that the sprite cache loads and deletes sprites automatically, which is why I was confused about this warning.

QuoteIf I remember correctly this warning is only emitted when running in debug mode (I don't remember if only when run from editor too or not).

I asked some testers to give me the details of their warnings.log file and it was present there, so it seems to be generated from compiled versions as well as when run from the editor.

QuoteThere's no AGS event that runs right before AGS closes as far as I remember.

I did search in the manual for something like "eEventQuitGame" but it seems that such a thing doesn't exist.

QuoteThe engine reports a internal number, which is assigned automatically,

Interesting to know! I noticed my warning referenced a number greater than my sprite count by one, so I assume that I can find which number a sprite has been assigned by assigning the sprite to something and then calling something like String.Format("%d", thing.Graphic); should I ever want to know this value myself.

At the moment I've just inserted a line to delete this sprite right before I call QuitGame, just to clear up the warning. But I also notice that the warnings.log file is warning about things like a Wait(1); call in a room_Load() function and that it closed a dialog when all options had been turned off, so I'm probably going to end up with some warnings in there, even if I try to clean up.

Thanks for the information, all!
SMF spam blocked by CleanTalk