Vallar's Forum Posts

  • What do you mean by arrange? Organize the global variables? How do you place them in the Event Sheet? Or are you referring to updating the global variables? If it is the first, that is up to you really, but you can look at dop2000's post.

    If you are referring to how to tell EventX to increase popularity and decrease success, that is a simple action in the event itself. System > Add To variable or Subtract From variable and choose what you want.

    If your events are loaded at run time not hard coded in an event sheet, then best is to give them an "id" and when you load one at run time, check the id and based on that, reduce/increase the variable you want.

    If you are referring to something related to UI, then that is a different matter and it is a matter of aesthetic and not something related to C3 unless you don't know how to create UI in C3.

  • Basically I have a turn based game (imagine a roguelike) and I want that projectiles in the game move in turns as well. So each turn the projectile moves a bit in a certain direction to allow the player the chance to dodge the projectile if it can (same with enemies).

    Any ideas how to achieve this with the bullet behaviour?

  • It's enemy.tilemovement.gridx. The tile movement has its own grid. If you set a sprite to grid position 0,0 you can work out where the grid is.

    Ah, OK, I see. Right, get the player's grid's location and provide it to the enemy. Gotcha. Thank you very much!

  • Set grid position (animate) and the X,Y are co-ords in the tile grid

    I didn't know that this action is used in this way. Thanks. Though how can I access the grid coordinates or turn X and Y of an object into grid coordinates?

    In the X I typed "Enemy.TileMovement." and I couldn't see anything that would allow me to do that calculation. Do I just place in the player's X and Y instead?

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • How do I make where when a object touches my player a death screen comes and lets you restart

    this is my first time using construct so sorry for any inconvenience

    So as mentioned you use the Object Overlap condition.

    If you want to show a screen you have two ways:

    1- You create the screen in a separate layout and then use the Go To Layout action.

    2- You can create the "UI" within the same layout, set it on a separate layer and then mark it as invisible. When the player dies, you use the condition "Set Layer Visible" to "Visible" and you can have a button in there to restart.

  • I am just saying that tile movement move to tile is enough for that kind of game. To pathfind to a tile is the same thing but you end up with the problems you mentioned like sluggish movement or maybe it can't find a path, in my opinion less reliable than the tile movement which is just move to a given tile.

    What is this Tile Movement move to tile is enough? I can't find that action at all. Is this a custom plugin or add-on?

  • Kinda depends on the exact gameplay. You say you don't want to build the move mechanic but pathfinding is demonstrating its own problems. When I look at that game you referenced you can click on a tile and move to it.

    That is out of combat. In combat, you move tile by tile like any roguelike.

    When you use pathfinding to move about you are not really using tile movement, it's one or the other. If you pathfind to a tile this is the same as using move to tile with tile movement.

    I am not sure I understand what you're saying. The first sentence makes it so I can't use both behaviours at the same time. The second one makes me think that Tile Movement has some sort of pathfinding embedded? I am not exactly following what you're saying on the second sentence.

    As for the turns, my characters have haste which puts them at the top of the list. If they can attack twice you can add them into the array twice, or like you said within the same turn give them 2 actions and track this with a variable.

    How are you implementing the notion of a turn? Is it just a bool you flip? Or is that by pressing "End Turn" button and for enemies you make sure that any decision is taken is followed by a "End Turn" button internally?

  • There is no reason to use pathfinding with tile movement for the basic movement. You would use only the tile movement behaviour and move to a tile based on grid ID. When you move you have the choice to animate so the unit walks to that tile.

    I am guessing in this case, I have to move the enemy manually to reach the player, right? Like check the direction (where the player is) then move based on that?

    I was hoping to avoid this to be honest and have pathfinding deal with it so I don't have to implement custom movement for every single enemy movement type I had; basically leaving complex movement to me custom making them and simple "move to reach enemy" would be pathfinding.

    Interesting you mention tile based movement in turn based setting, I am making a similar prototype right now. My approach was to add the units into an array for turns and pick the top one as the current turn. Then you move with the actions, chop it from the array and the next person moves up for their turn.

    I think this method may not work for me due to having attack speed and that affecting turns. But it could be mitigated with action count. Not sure. Basically I wanted to simulate attack speed = having more turns. But it could be that attack speed = more actions per turn and turn order/speed is the same regardless of your stats.

    Thing is, how do you "stop" the world and everything in it when it isn't their turn. If I use the pathfinding behaviour how do I tell pathfinding to move only one tile per turn? Or is this why you said I should forgo pathfinding?

  • Hi everyone,

    Imagine a classic Roguelike game such as Stoneshard for example; you move on a tile by tile basis and your enemies do the same.

    I am trying to simulate the same effect; having enemies in my game to pathfind their way to the player but moving based on tiles rather than fluid movement.

    The way I did it so far is to add both the Pathfinder and Tile Movement behavior to my enemy. But the results are really, really slow and off. Like sometimes the enemy would go far away from the player before starting to move towards them.

    Here is a GIF of what I mean by slow

    https://i.imgur.com/k7Fymhj.gif

    Originally I set my cell size to 16 (since I am planning to use 16x16 tilesets as seen from the sprites I am using. But that was a nightmare as the enemy would zigzag their way towards the bottom of the layout before starting to move upwards towards the player and it was much slower than what you're seeing here.

    Here is a screenshot of my current setup for both behaviours:

    https://i.imgur.com/tDNcZ1C.png

    Any ideas what I can do to achieve this?

    Side question; any idea how to setup this same behaviour but in a turn based system? Right now things are moving in real time. Any hints how I achieve turn based pathfinding and tile based movement for enemies?

  • > > The path you are using is not correct

    > >

    > > JSON2.get(".recipes" & loopindex) probably will work

    > > It depends on the content of your json file though.

    >

    > Interesting. Thank you for pointing that out. Does this mean that the parent "JSON part" (like the parent header) must have a "." before it? I thought it didn't need that, since it is at the very top.

    No, your path is correct, but returns an object like I mentionned earlier, and you can't use "Get" to retrieve its content. Top level absolute path never begins with ".", you only ever begin your path with "." when you are working with relative paths, like in a "for each" or by using the "Set path" action.

    Thanks for re-confirming that, Kyatric threw me off.

  • Oh sure. It takes the file and uses the tokenat expression to look at it a line at a time.

    One event sees if the line starts with #recipe, if it does it uses the rest of that line as the name of a new recipe.

    The other event handles either blank lines or lines that have a number followed by an ingredient name.

    Left() gets the left side of some text

    Mid() gets the middle

    Trim() removes any leading and trailing spaces in the text.

    Finally it keeps track of the uid of the last recipe created. That is just so we can pick it again when adding ingredients to it.

    Thank you for the explanation. If you don't mind a few questions just to make sure I understand this correctly.

    * When the event says "recipe > Set name to mid(line, 8, 100)", are you basically extracting the name of the recipe? You're using "mid" here since "left" is = to #recipe? Wouldn't "8" here count the space just before the recipe's name? Or does it ignore it? Also if you don't mind why 100? Is it arbitrary long so you can capture whatever name is here?

    * In the Else statement, there is System > Set count to int(line). The way I understand it is, line is equal to the current sentence (so in case of an ingredient for example "2 wormwood") how does int(someString) know what to grab as a number? I thought the "int" expression just approximates a float into an int?

    * In the same Else statement there is a line that says System > Set ingredient to trim(mid(line, len(str(count)), 100)). Does this basically says "Trim the current line from spaces leading and ending" Then you check the middle part, that starts right after "how many count is in characters" and for 100 characters long? This goes back to the first question. If len(str(count)) is equal to 1 (because count is going to be the one number at the left of the recipe) then again, wouldn't that return " wormwood" instead of "wormwood"? I know you used Trim to negate if this happens, but you didn't use it in the other one, this is confusing to me.

    Thanks.

  • >

    > https://i.imgur.com/MEVWcPs.png

    >

    > I am using the same sample JSON file as you. But when I run the layout, I get the DebugText changed to "00" only. So I am not sure what does this do and what am I getting even since the JSON has no 0s.

    The path you are using is not correct

    JSON2.get(".recipes" & loopindex) probably will work

    It depends on the content of your json file though.

    Interesting. Thank you for pointing that out. Does this mean that the parent "JSON part" (like the parent header) must have a "." before it? I thought it didn't need that, since it is at the very top.

    You might want to check back on the JSON example provided with Construct, it is pretty simple to understand how you are supposed to create your structure.

    https://editor.construct.net/#open=json

    Oh, I did. I looked at that for hours really, but it doesn't help in understanding how to divide a JSON and search based on sub-sub entries with a list. I wish there were more advanced examples that go in depth of how to use JSON and XML.

    And check back on the example provided by Laura, it should make more sense.

    The issue here doesn't seem to be with scripting or events, but with the actual structure of your JSON file.

    Post it, it will be easier to establish the correct events in regards to how you established your file.

    In my experience XML is not simpler.

    The JSON is fine, I posted it before here:

    https://www.construct.net/en/forum/construct-3/how-do-i-8/best-data-structure-crafting-154650#forumPost1020452

    I think you used it in the example .c3p you worked with Laura on. I've also used it to print out the information inside and it worked. Now the structure may not be C3's "optimum one" (if there is such a thing) but I use JSON validator when I write JSON since I personally can't write it properly without one :D.

    Thought I'd have a go at this.

    The events simplify nicely by having a dictionary for the inventory and an instance of a recipe dictionary for each recipe.

    https://www.dropbox.com/s/cw1xuiiymjqq6oq/crafting_test2.capx?dl=1

    JSON and XML are a pain to write imo. With the above example you can just create the recipes with events fairly cleanly, or just load and parse a plain text file to populate it.

    #recipe Blinding Flash Potion
    2 wormwood
    5 sulfer
    
    #recipe Potion of Sweet and Savory
    5 salt
    5 sugar

    I could get behind writing recipes like that all day long. No quotes or matching brackets.

    Thank you very much for trying this. I am using a similar approach at the moment (conceptually); I have a dictionary file for every recipe and one dictionary object that I load the file into the dictionary, check if it is this one or not. If it is not, I move to the next file. Which gets rather hectic fast events wise. This is interesting though. Could I ask you to ELI5 this part please?

    https://i.imgur.com/pt88uw6.png

  • Create placeholders at design time, create the slots at runtime is indeed how I would set it up, and depending on player/shop change the configuration and the way it looks

    Nice, thank you for confirming this :) makes things a lot easier this way!

  • Good question, I haven't given that a lot of thought really...

    My first hunch would be to create the slots dynamically as well, making a grid of slots, and filling in the id's programatically, and looping as you do now. Something like that.

    Shouldn't be too hard to do, if you just set up a number of rows and columns, decide on the height and width of the slots, an offset between the slots, left margin, top margin, and you're good to go really.

    Would something like say having some placeholder sprite denote locations and then creating the slots work? So have a sprite that is invisible in each slot's location and just then spawn the slots, add their IDs and then populate the dictionary?

    I'm a pretty big fan of placeholders, as you might have noticed on some of my video's on my youtube channel, and granted that has been prone to errors, but the need for generic systems is rarely the case. Certainly not in C3 as you don't (yet) have options to integrate predefined blocks of logic.

    In my current project (or maybe this is how I am used to thinking about implementation) there are quite a few cases where generic systems would work well. For example I have two inventories; one for a shop and one for the player. Both are populated in the same exact method we've been talking about (from a predefined dictionary). So setting up a generic system here that I don't have to manually create for both ends would save a lot of hassle overall. That doesn't mean it can't be done otherwise of course (after all that is what I am doing now).

  • > I see. I am trying to replicate chunks of what you did in my project to understand what you've done and wrap my head around it but I am failing quite a bit. So one thing I am doing is the below:

    The Get expression of the JSON object can only return string or numeric values. The expression you written actually returns an object and C3 can't deal with that so it defaults to 0. You can however use GetAsBeautifiedString or GetAsCompactString to get objects in JSON format.

    > Would you say in that case, XML would work better?

    It's pretty much the same I would say. Altough XPath is probably easier, it has the same caveats in terms of iterating. If you use "for each node" for a particular XPath, you can't use "stop loop" and that's a bummer.

    Personally, I'm partial to JSON, simply for that fact that I find it more concise.

    > Would you say it would be less of a headache if I try to write this one thing (searching for the correct component) in JS and attach it as a script instead?

    Indeed, if you feel confortable with scripting, you could replicate what I did in a much less convulated manner.

    The JSON plugins expose an API that makes it easier to do interactions between event sheets and scripts, if you go that way.

    https://www.construct.net/fr/make-games/manuals/construct-3/scripting/scripting-reference/plugin-interfaces/json

    Thank you very much for your answers, this is very helpful. I'll give your recommendations a try and stay with JSON for a bit longer. If things get hairy, I'll see if I can try XML in hopes I could replicate the same logic but with something easier to write :)