R0J0hound's Recent Forum Activity

  • It’s working for me.

    I added a sprite font, added the yen to the character set, then drew it in on the image. Then the set character width action worked fine.

    Example:

    dropbox.com/scl/fi/owlta99xjl1kd5f761sbr/spritefont_spacing_test.c3p

  • Try Construct 3

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

    Try Now Construct 3 users don't see these ads
  • I ended up taking a dive looking a lerping like this in a framerate independent way.

    In a frame dependent way we'd use:

    set a to lerp(a, b, f)

    Where f is a value from 0 to 1. The speed it moves will vary according to the framerate.

    The quick improvement is to just multiply it by dt. 60 is multiplied by it too to make it have the exact same motion as the non-dt version.

    set a to lerp(a, b, 60*f*dt)

    With that it's largely framerate independent and approximately follows the same motion path no matter the fps, but the path can vary a bit and overshoot.

    For full framerate independent version I've found two versions online.

    One is from Ashley:

    set a to lerp(a, b, 1-f^dt)

    and one from Freya Holmer:

    set a to b+(a-b)*exp(-decay*dt)
    or
    set a to lerp(a, b, 1-exp(-decay*dt))

    Where decay is a value from 1 to 25.

    But the rate of change is different between the two. Surprisingly if we tweak either of them to use a f value of 0 to 1 and shift it to match the f and f*60*dt version we get the same equation:

    set a to lerp(a, b, 1-(1-f)^(60*dt))

    Which will give the exact motion no matter the framerate.

  • 1) One way could be to create an invisible sprite at every grid location that isn't occupied and pick the closest one. Likely you could do that with collision detection and a double loop to loop over all the squares. It would give you an opportunity to understand some extra nuances to picking since you'd need wait or something to let all the newly created objects be pickable before picking the closest. Or just keep an invisible sprite at all the grid positions and not have to worry about it.

    Or if you prefer traditional programming logic you'd just loop over the center positions of all the empty squares, and calculate the distance. While doing it you'd keep track of the position with the closest distance, and update that if another is closer.

    2)

    It's mostly a matter of adding a condition i imagine. This is the power of events. If you want to do something conditionally you can add another condition.

  • You can look in the manual, namely the system expression section. But in general you can use any sort of math or combination of expressions as parameters. Construct supports expressions with text and numbers but you can convert between the two.

    There's even a tutorial about the uses of dt.

    construct.net/en/tutorials/delta-time-framerate-2

  • For the grid you can set the position to int(x/64)*64+32, int(y/64)*64+32 to center it in the grid. Notice the +32 which is half the grid size. I used int instead of round because it works better for this case, but you can try both to see what i mean.

    For the rest of your question I'd recommend utilizing families and\or representing things as instances of fewer types. Both would require less events.

    Consider a simple example with similarities with your setup. Each object has it's own object type: Bullet1, bullet2, enemy1 and enemy2. And both enemies have health variables. Events would look like:

    keyboard: on z key pressed
    -- create bullet1
    
    keyboard: on x key pressed
    -- create bullet2
    
    bullet1: collides with enemy1
    -- enemy1: subtract 1 from health
    -- bullet1: destroy
    
    bullet1: collides with enemy2
    -- enemy2: subtract 1 from health
    -- bullet1: destroy
    
    bullet2: collides with enemy1
    -- enemy1: subtract 2 from health
    -- bullet2: destroy
    
    bullet2: collides with enemy2
    -- enemy2: subtract 2 from health
    -- bullet2: destroy

    A quick fix would be to instead use families. Remove the health instance variables from enemy1 and enemy2, and then add enemy1 and enemy2 to a family. Call the family enemyFamily and give it a health instance variable. Similarly add bullet1 and bullet2 to a family and call it bulletFamily. Then add a variable called damage to that family. Your events then could reduce down to:

    keyboard: on z key pressed
    -- create bullet1
    -- bullet1: set damage to 1
    
    keyboard: on x key pressed
    -- create bullet2
    -- bullet2: set damage to 2
    
    bulletFamily: collides with enemyFamily
    -- enemyFamily: subtract bulletFamily.damage from health
    -- bulletFamily: destroy

    You can do something similar by just having different enemies be different animations on the same object type. But it just depends what you want to do.

  • Manually in what way? In construct we deal with positions in layout coordinates, and construct converts those to canvas coordinates using scrollx/scrolly, layout scale, layout rotation, canvas size, and layer scale, parallax, etc… to draw.

    Well, maybe you are asking how viewportMidX(“ui”) is calculated… that could also be calculated with:

    ViewportLeft(“ui”)+viewportWidth(“ui”)/2

    Or

    (ViewportRight(“ui”)-ViewportLeft(“ui”))/2

    Or presumably if the ui layer has a parallax of 0,0 then you could just use:

    viewportWidth(“ui”)/2

    If the ui had a parallax of 100,100, and the layout had unbounded scrolling checked, then you could also just use:

    Scrollx

    With bounded scrolling the scrollx gets clamped but you can also clamp it manually if you’re so inclined:

    Clamp(scrollx, viewportWidth/2, layoutWidth-viewportWidth/2)

    But it would behave oddly if the view was smaller than the layout.

    If you set the canvas width the the window.innerWidth and had no layer or layout scaling then you could use:

    PlatformInfo.InnerWidth/2

    Of course all of those could be used with int() to round away the 0.5s from odd sizes. Also to manually handle the transformations that layers let you have then the formulas would get more involved and you may as well just use the expressions construct offers.

    Anyways, based on your previous posts you could get an unscaled pixel perfect viewport covering the window by setting the fullscreen scaling in your project properties to “none”, the set the canvas size in events to the innerWidth/height of the window. As long as the canvas is the only thing on the window there shouldn’t be any page scrolling. Then you’d just center with viewportMidX like you did above. There really isn’t a whole lot of benefit to calculating it more manually unless you encounter something that the engine doesn’t recalculate until drawing.

  • Construct supports JavaScript, typescript and events. No other languages are supported beyond that.

    You’d need to add support yourself or get someone else to do that. In theory you could compile the python interpreter into wasm to use via JavaScript, then add some kind of layer to call things from construct’s js api with python. But even doing all that would result in limits with what you can do. Aka you wouldn’t be able to run arbitrary python since within the web browser there are limits on things you can do or access. Generally working with supported languages are the easier way to go.

    On the bright side any programming concepts you learn often transfer to other programming languages. Or you can go down the python rabbit trail.

  • You probably will run into a snag in that c3 and threejs each have their own rendering contexts and you can’t share the same texture between contexts. What you’d end up needing to do is copy the texture to memory from one context and load that into the other context. Memory wise you’ll be loading the texture twice and speed wise transferring images to and from vram is rather slow. So you likely will want to do that selectively.

    Generally most of the time when integrating a different renderer with construct they each would have their own unique context so the above is pretty unavoidable. In theory you could have two different renderers operate with the same context to be able to share resources. But in practice it’s not really feasible since the renderers with conflict with each other a lot so you’d need to juggle rendering state.

  • I need to stop posting text versions of events I guess. Here's what I posted implemented in events. Does that work?

    dropbox.com/scl/fi/7skmhfwidcf0ygdqucsp3/oval_to_oval.capx

  • When I write so called pseudocode it usually can be written in the exact same way with events. However, it's probably not clear to most which is ok, but I am not around a computer often enough to whip up an example instead. Anyways, here is an example showing the idea since what I wrote is pretty exact. Only typos were 20 instead of 33 with the volume calculation and "duration" instead of "playbackTime".

    It has only one sound file, in which there are two sounds a gunshot and a monkey. I just wrote down the start and end time of both files.

    Then in the events to play a sound we get a unique tag, play the sound, and seek to the start time. I then add the tag and end time to an array so we can keep track of each sound to stop later.

    To avoid audio clipping from stacking sounds getting too loud I calculate a volume from the number of sounds playing. 1 sound: 100%, 2 sounds: 50%, 3: 33% and so on... The rest of the formula is convert percentage to decibels. It does avoid the clipping, but with a high number of sounds it does make things a bit quiet.

    An alternate idea to handle the clipping could to be to add an analyzer effect to the tags, sum up the peak levels of all the playing sounds, and ease the volume down if it gets too high. Might be a bit heavy though.

    dropbox.com/scl/fi/7574tn2yq9k3wimj8ywek/sub_sounds.capx

    It shows the number of playing sounds at any time.

    Anyways, its just an idea and an array works fine for this purpose.

  • In the loop you need to update shoottag. It should be array.at(i). As is it’s just stopping the shoottag of the last sound you started.

    Edit:

    That only partially matches the pseudocode i sent. I’ll have to screenshot the events later i suppose if it’s not clear.

  • Why not have a unique tag per sound you play? Like have a global variable ID and when you play a sound set the tag to “shoot”&ID then add one to the ID variable. To keep track of all those tags you could add them to an array, and remove them as they finish.

    I’m unfamiliar with playing multiple different sounds from the same file but I assume it involves having a start and stop time to each sound in the file.

    So roughly the idea would be this. Array.width would be the number of sounds playing.

    global number id=0
    Global text tag=“”
    Start of layout
    — set array size to (0,2,1)
    
    Keyboard: On space pressed
    — set tag to “shoot”&id
    — add 1 to id
    — array: push tag to front
    — audio: play sound with tag tag
    — audio: seek tag to startTime
    — array: set at (0,1) to endtime
    
    Global number vol=0
    Global number I=0
    
    Every tick:
    — set vol to 33*log10(1/array.width)
    — set i to 0
    
    While
    I<array.width
    — set tag to array.at(i)
    — audio: set volume of tag:tag to vol
    — compare: audio.duration(tag)>=array.at(i,1)
    — — audio: stop tag
    — — array: remove index i
    — else
    — — add 1 to i