Pulstar's Recent Forum Activity

  • It is not a limitation. I believe you are using it incorrectly.

    The reason the counter does not change on kill all is that the event only triggers if a sprite with "countme" set to true exists. Pickedcount for an Object will never return 0 if you do it in any kind of event that picks instances of that object meeting a condition, because events with conditions trigger only after at least one instance meeting the conditions is found (assuming there is no condition set by you to tell it "if picked count>X", then you would need x+1). Also the event changing the counter is before the event destroying the enemies. What happens is:

    Tick 1

    1) counter is changed to reflect current number (5)

    2) button was pressed, destroyed all (after counter last updated)

    Tick 2

    1) no enemies exist and thus the condition for updating the counter is not met. This is why you see the initial number as the set text action does not execute at all.

    The proper way to do this would be as in the attached capx, use a subevent in a event block with no conditions, check if any marked with "countme" enemies exist in one subevent, else in the other subevent set counter to 0 (as they don't exist).

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

  • Instead of "on collision" use the "is overlapping another object" condition, right click on the condition and select invert. Invert works like a "NOT" statement IIRC.

    Basically that will trigger only if the instance is not colliding with whatever sprite you want it to not collide with.

  • I do not have much time as I have a business trip tomorrow morning, but I glanced at your capx and I can tell you I had the same problem. And mine was a bit bigger because I have a 64 by 64 tile building floor with ~40 randomly generated rooms with different shapes.

    What I did was the following, please note I forgotten some details and I feel an immense sense of dread whenever I need to look into my map generation logic (at 350 event blocks it is a bit big and unpleasant to look at, also it takes 40-50 seconds to generate a level on my LG spirit LTE/4G droid phone (Desktop PC with NW.js takes 3-4 seconds for the same). I know the solution is not fool proof but the margin of not accessible rooms I get is acceptable (maybe 1 in a 100 if not less). Still it should give you some ideas.

    One thing I did is that in my array that stores all map data in z-indexes (from 0 to 17 I think, stuff like fog of war, walls, bitwise for walls etc.). One of the things stores was room ID.

    1) Generate rooms/walls first. I used prefabs for this but it doesn't matter so long as you have an array which tells you which tile belongs to which room. I have a separate array used for rooms which uses the y-axis to store data such as, what is the parent room, is the room connected to the starting room (elevator in my case). So every time I placed a new room, it would also get pushed as an X element to the array.

    2) For each room I checked the whole map array for all tiles belonging to that room that were walls (but not corner walls). Every time a tile like that was found, it was added to yet another array. This array stored the x coordinate at y=1 and the y coordinate of the tile at y=2. So what was at y=0 you ask? A random number from 0 to 100. Why? Because after I finished checking the whole map for that particular room and had all its wall, I would sort the array. Since it sorts by values at (x,0) I would have wall arrays in a random order.

    3) I would go through the now randomly sorted wall tiles for the room and start checking the following. Does it neighbour a different room? If yes, is that room already a child or parent of this room (a parent here is a room that is "closer" to the start, a child is a room "closer" to the end, but not by actual distance but by the number of rooms needed to cross)? If yes, we skip to the next tile in the array, if not we can create a door at that tile. The room to which we just connected is now set as the parent of the current room. If the parent happens to be connected to the start, we also mark the current room as connected in the room array.

    4) We did 2 and 3 for each room. So next we check the room array if all rooms are connected to the start. When we find a room that is not connected, we do 2 and 3 for it again. The logic should again create a door to a room that was previously not directly connected with the current one. We do that for every room that is not connected until all rooms are connected or there are no more connections that can be created for the unconnected rooms(I do this via a while loop).

    Actually I stretched the truth a bit, I looked at my project and I never bothered marking rooms as being out of possibilities to connect. I just hard-capped the while loop that goes through each room>generates a door>creates the connection tree/map, to run two times an apparently it was enough to not get unconnected rooms >_>. I do not know why, but there's probably some mathematical theory or theorem that explains this. I kind of like it because the room connections are quite random, sometimes there are dead end rooms, there are rooms with 2 doors, some have 3 and in more rare cases 4.

  • Is the tilemap a side-scrolling map or a top-down one? I assume the former from your image. (edit: I saw your second post after posting this one, obviously sidescrolling)

    Here's a capx example:

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

    Basically for bridges or straight slopes you only need to use the a or m (slope) parameter of a linear function. You go from the lower x to the upper x and add a to Y with every loop iteration.

    For filling terrain of a random height you need to nest a loop that will fill terrain from the bottom to it top (or vice versa) within the loop going from the lower x to the upper x. Every time you go to the new x you pick a random Y that will be your top.

    With some tinkering you can also clamp the random Y's so that the height difference between x and x+1 is of a given maximum. Basically something like Y=Y+floor(random(0,3)*choose(-1,1). That will generate the height at the next X position at most 2 tiles lower or higher than the previous x position. The terrain would be more even yet still jagged at places.

  • Wait, are you using actual pixel sized sprites or a tilemap with pixel sized tiles? Did you test how fast the collisions work with it? It sounds like it would run rather slow.

    At any rate I have bad news, there is an upper limit on how much total array size the engine can handle. I once reached it when experimenting with inifinite world generation.

    The workaround in nwjs I found was to offload avery part of the array that is not used by the visible area into as a json string to custom text files files using nwjs file saving to disk function. I would load them back into a smaller visible area array when needed. That however required setting up a filenaming system so the game knew what to load at what coordinates.

  • CJacobsSA

    Try the below demo I just made. Everything should be commented (besides the very obvious on flash stop make warning text invisible event).

    Basically this is an inventory system working kind of like in minecraft where you have a max stack size per slot. Although unlike in minecraft here the stack size is the same for all objects, set by the global variable MaxStackSize. In minecraft tools, buckets etc. have a stack size of 1 vs 64 for most if not all blocks IIRC.

    I ended up using a while loop as it is the most flexible and efficient IMO for doing such searches through an array. Note that the demo is fairly rudimentary, and it will not for instance, prioritize putting a block into a not yet full slot with the same type over putting it in an empty slot (if one has a lower index). As there is no way in the demo to remove an item from a slot, this case will never happen.

    https://www.dropbox.com/s/3k9v2fdlqhn3b ... .capx?dl=1

  • Ah ok, I did not notice the edit, sorry. You are using array.indexof(0) to find the empty right? Also a valid way to do it, never thought of it. Anyway I have some suggestions as to the solution. I will give you two solutions actually, the first one is applicable in your case since you store type at index y=0. The second is more general if you need to check things at other y indexes.

    Specific for type stored at y=0:

    Remember that snazzy indexof you are using? Use array.indexof(block.type). It will return an index of 0 or greater if the block of that type is already in the array. It will return -1 if the block type has not yet been added to the inventory at all. And if the block type is in the array, you can use the same expression to tell the function at which index to add the new block amount.

    General:

    What I do is the following. Create a local variable "IsInInventory" or something similar in the event. Default value 0. Create another for the type of item you add if needed.

    Event conditions

    Loop for every X element of the inventory.

    Inventory value at (Self.CurX,0) = type

    Event Actions

    set value "IsInInventory" to 1

    Next you just make an event with condition IsInInventory=1 and do whatever you need to do.

    BTW I like your project, pretty cool.

  • Personally I would not use the array size as the inventory size, Instead I would add a variable to the array object and call it "ItemLimit" or similar, next I would set the default inventory array width to 0.

    Every time an item is added or removed I would push or pop an array X element. That way you would know for sure that every X element is an item, so if array.width would equal "ItemLimit" you would know it is full. And if it is full, you would prevent any item add events from firing.

  • But those classic RPG's used layout yes?

    I assume you meant to ask if they had a separate layout/screen/scene for the inventory or if the inventory window.

    Now that is a good question, but overall in the case of here and now with construct 2 I think how they handled it is not really relevant. We are not bound by the same limitations of the hardware and tools but have different limitations due to the nature of construct 2. I think that at least for the PS1 games it was not a separate scene, because they would have to load it from the CD each time then load back the actual game world scene from the CD. But that's just a guess.

    If you can make it work you can use a separate layout, however you need to consider that:

    1) you will need to make sure the objects you interact with (such as the player or party members) get transferred between the layouts.

    2) the state of the game layout after you switch back is exactly the same. IIRC if you switch to a layout the initial objects and their placing is restored in addition to any objects that had persistent behaviour.

    If you do it on the same layout but as a different layer that is invisible when the inventory is closed:

    1) you will need to "pause" all enemy movement etc.

    2) you will need to make sure player input events for movement or other actions does not trigger when doing something in the inventory. For example I needed to make sure that if I click on an item in my inventory window, the player character will not start moving to the tile hidden behind the inventory window.

    All of the issues in both approaches can be overcome, but you will need to think or look for the solutions and decide what you want to use. There is no universal "best" way to do this, there is one that is best for you and finding out what it is might take trying and experimenting and even failing. But do not get discouraged, Rome was not built in a single day and knowing what doesn't work and why is important to know what works

  • Depends on the target device and what you do with the objects and how often. I found out the hard way why using sprites as tiles for a game with Z-levels is bad, especially when you have a couple thousand of them. But I digress. And you want infinite inventories anyway.

    But generally I would recommend against having such a thing as an item object for each item when not necessary and that is the approach I took when doing inventory systems in some of my attempts at such.

    What I do instead is the following. Store items only in an array, they exist only as a columns in arrays. An array with many rows mind you as it contains general information such as item type, sub-type, weight, size, sprite, name and description. It also has a bunch of rows dedicated to "special" data. In those rows I store coma separated value strings that are different for each item type. For example weapons have different strings, armor has differently formatted strings etc.

    So how do I fire a gun a with that or equip body armor? There are two approaches I am considering now but I will most likely use the second one (I used the first in the past):

    1) Have a weapon object created and assigned to the player, just one. It is in reality a container, a shapeshifter that takes the properties of whatever weapon is currently equipped by the assigned parent player or NPC object. Whenever the weapon is changed, a function will reset all its variables and load new values. The new values will be taken from the "special" data strings. The logic of the function will retrieve the special string and next, using the tokenat expression, load the weapon properties into the weapon object. Next I use the weapon object in the events as I please.

    2) Do not have a separate object altogether, store all equipped weapon data as variables of the NPC object. Otherwise it will work the same as approach 1.

    Now you asked how Final Fantasy etc. manage infinite items. They don't use object obviously for each item. When you look at an inventory you are looking at a graphical representation of an array. What they do, what I do and indeed what even such advanced business software such as SAP do (at least for multiple single value selection fields) is that they have a set number of list position objects or slot objects. Each slot is assigned an ordered position from 0 to X.

    Next what they do is store the index of the first object in the table/inventory they are showing, let's call it "i" for short. When you scroll the list a function is called updating the index of the currently displayed first object. Next the list is refreshed and the code uses a loop to put the data of item "i" into the first slot object, "i"+1 into the second slot object etc. i=4 would mean that object with index 4 (so the 5th row) of the inventory array would be shown first (top of the list/first slot).

    So you only need slot objects to show the item, as many as fit in the inventory window you designed. They will never change position, they will only change their appearance.

    Bah, if you are using only a text based inventory without any item icons or anything like earlier FF games did, you could do it with a single text object. You would just need to know how many rows you can fit in the text and how much text in a row (I recommend using monospace fonts for that, which is also what systems displaying lots of lists and tables such as SAP do).

    It would look like:

    set text as array.at(i,0) [0 would be the y index of the item name in this example]

    loop for 1 to number of rows

    append text [newline&array.at(i+loopindex(),0)]

    However making things such as highlighting the selected item, selecting it with clicking etc. would require additional objects.

    tl;dr version store the data that is needed as an object now as an object, keep everything that you need later in arrays.

  • > Please clarify what exactly you want to do. Do you want to copy 3 new items or add an item with 3 properties?

    >

    * Item on ground has;

    HpID:175

    MpID:125

    VitalityID:100

    * - When the item goes from ground to inventory, we want the HP/MP/Vitality ID values to follow

    The first thing you need to do is define how you store the HP/MP/Vitality data of the item, so from where is the data supposed to be copied. Let's assume the simplest case, that you have it as variables of an object (sprite) that represents the item. On Item pickup the object will be destroyed but only after you store the item in the inventory.

    This is how it can be done (there are arguably better, but more complicated and requiring more explaining ways). For example:

    When the player clicks or does some other action triggering item pickup, you call an "Item Pickup" function, and pass all the properties of the object as parameters of the function. So name, HpID etc. would all be instance variables of the item object (sprite).

    So you would have a call function "item pickup" action with parameter 0 = item.name, parameter 1 = item.HpID, parameter 2 = item.MpID and parameter 3 = item.VitalityID.

    Next you need to have the "item pickup" function store the data passed as parameters in the inventory array. I have no idea how many item statistics you exactly need, but you need at least 4. So your array, if it is a 2D array like in the inventory tutorial example, it needs a height of 4.

    Now, the important thing you need to do, is to write down which row stores what information for an item. Let's assume for the purpose of this example the following, as it is consistent with what we used in the parameters:

    y = 0 is the name of the item

    y = 1 is HpID

    y = 2 is MpID

    y = 3 is VitalityID

    Assuming you know into which element x (slot) you want to put the item into, which I shall simply call "i" (short for index) here, all you need to do is use the set array value at action as follows in the "on function "Item Pickup" event:

    Set value at X=i Y=0 to function.param(0)

    Set value at X=i Y=1 to function.param(1)

    Set value at X=i Y=2 to function.param(2)

    Set value at X=i Y=3 to function.param(3)

    That's it, the data will be stored in the array. You just need to know at what element x to store it, pass the right values in the function and make sure the array has the correct height so that it can store y from 0 to 3.

  • Try Construct 3

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

    Try Now Construct 3 users don't see these ads
  • Please clarify what exactly you want to do. Do you want to copy 3 new items or add an item with 3 properties?

Pulstar's avatar

Pulstar

Member since 10 Jan, 2016

None one is following Pulstar yet!

Trophy Case

  • 8-Year Club
  • Email Verified

Progress

9/44
How to earn trophies