R0J0hound's Forum Posts

  • Main issue I'm seeing is you're not reading the pixel from the right spot. The snapshot size won't be the same size as the drawingCanvas unless the window isn't resized or if the drawing canvas' resolution mode is set to fixed, and the resolution is the same size as the canvas.

    Anyways, a fix would be to convert the coordinates. Instead of

    x = Mouse.x
    y = mouse.y

    use:

    x = Mouse.X*DrawingCanvas.SnapshotWidth/DrawingCanvas.Width
    y = Mouse.Y*DrawingCanvas.SnapshotHeight/DrawingCanvas.Height

    or if the drawing canvas isn't positioned at the top left of the layout:

    x = (Mouse.X-DrawingCanvas.BBoxLeft)*DrawingCanvas.SnapshotWidth/DrawingCanvas.Width
    y = (Mouse.Y-DrawingCanvas.BboxTop)*DrawingCanvas.SnapshotHeight/DrawingCanvas.Height

    dropbox.com/scl/fi/c9zekz1ru5pzw6u26mxon/read_pixels.c3p

    EDIT:

    Looks like these three expressions are approximately the same. So you could just divide the mouse position by the pixelScale. The fact that all three aren't all the same is another c3 issue but shouldn't matter too much.

    DrawingCanvas.SnapshotWidth/DrawingCanvas.Width

    DrawingCanvas.SnapshotHieght/DrawingCanvas.Height

    1/DrawingCanvas.PixelScale

    Edit2:

    If you manually set the fixed resolution mode size, then don't use pixelScale.

  • More ideas.

    This one starts with a list of all the numbers and removes random ones one by one. For example 20 possibilities.

    Var list=“”
    Var n=0
    
    Start of layout
    Repeat 20 times
    — add zeropad(loopindex,2) to list
    
    Start of layout
    For each sprite
    — set n to int(random(len(list))/2)*2
    — sprite: set frame to mid(list, n, 2)
    — set list to left(list, n) & right(len(list)-2-n)

    This one just randomizes till all four numbers are different.

    Var done = 1
    Start of layout
    While
    Compare: done>0
    — sprite: set animation frame to int(random(sprite.animationFrameCount))
    — set done to 0
    — add sprite(0).animationFrame = sprite(1).animationFrame to done
    — add sprite(0).animationFrame = sprite(2).animationFrame to done
    — add sprite(0).animationFrame = sprite(3).animationFrame to done
    — add sprite(1).animationFrame = sprite(2).animationFrame to done
    — add sprite(1).animationFrame = sprite(3).animationFrame to done
    — add sprite(2).animationFrame = sprite(3).animationFrame to done

    Same as above in a cleaner way.

    Var r0=0
    Var r1=0
    Var r2=0
    Var r3=0
    
    Start of layout
    while
    compare: (r0=r1 | r0=r2 | r0=r3 | r1=r2 | r1=r3 | r2=r3) = 1
    — sprite: set frame to int(random(sprite.animationFrameCount))
    — set r0 to sprite(0).animationFrame
    — set r1 to sprite(1).animationFrame
    — set r2 to sprite(2).animationFrame
    — set r3 to sprite(3).animationFrame

    This one uses a tuned pseudo random number generator to generate random numbers without duplicates. This one was tuned to handle 10 possible frames, but it would work for any count by changing the right numbers.

    Var r=0
    
    Start of layout
    — set r to int(random(1000))
    — for each sprite
    — — set r to (r*906+1866)%1000
    — — sprite: set frame to r%10

    I’m sure there are other ways. Each have pros and cons.

    Edit:

    One more for good measure using an array.

    Start of layout
    -- array: set size to (0,1,1)
    -- for each sprite
    -- -- sprite: set frame to int(random(self.animationFrameCount-loopindex))
    -- -- sprite: set frame to (loopindex>0 & Array.at(0)<=self.AnimationFrame)+self.AnimationFrame
    -- -- sprite: set frame to (loopindex>1 & Array.at(1)<=self.AnimationFrame)+self.AnimationFrame
    -- -- sprite: set frame to (loopindex>2 & Array.at(2)<=self.AnimationFrame)+self.AnimationFrame
    -- -- array: push sprite.animationFrame
    -- -- array: sort x axis
  • I mean if you’re after alternative ways to flip cards, here’s a way with two instance variables: target and spin.

    On card clicked
    — card: set target to 180-self.target
    
    Every tick
    — card: set spin to lerp(self.spin, self.target, exp(-16*dt))
    — card: set width to self.imageWidth*cos(self.spin)
    — card: set animation to self.width>0?”back”:”front”
  • In c2 you can do shuffle by having another y in the array with a random value and use sort. Here is the solution I posted above modified to do that.

     Start of layout
    — array: set size to (sprite.frame count,2,1)
    
    Start of layout
    Repeat array.width times
    — array: set at (loopindex,0) to random(1)
    — array: set at (loopindex,1) to loopindex
    
    Start of layout
    — array: sort x
    
    Start of layout
    For each sprite
    — sprite: set frame to array.at(loopindex,1)

    Now as an exercise you probably can reduce that to less events. One to populate a shuffled list of numbers, and one to set animation frames. You could use a text variable instead of the array if you wanted too.

  • If it works, it works and it seems to make sense to you so I say stick with it.

  • I’m becoming more and more convinced that construct isn’t as simple to use as it appears.

    There are many solutions to that, each with their own set of things to be familiar with.

    The first approach I’d use is how would you do that in real life? What would the steps be?

    Probably: roll 4 dice, then look for two or more dice that are the same, and reroll the duplicates and check again. So roll, and reroll if there are duplicates.

    However picking seems to be hard to most, so is picking two separate instances at the same time.

    So you could put all the possibilities values in an array, shuffle that, and use that to set frames.

    Start of layout

    — array: set size to (sprite.frame count,1,1)

    Start of layout

    Repeat array.width times

    — array: set at loopindex to loopindex

    Start of layout

    — array: shuffle

    Start of layout

    For each sprite

    — sprite: set frame to array.at(loopindex)

  • One of the issues you’re encountering is the object’s blend mode and the “drawing blend mode” are two different things. You’d want to set the drawing blend mode to destination-out before filling the ellipse, but you should leave the object’s blend mode as normal.

    So roughly this would create a canvas over the sprite, draw the sprite to the canvas, and erase a circle out of it. What you do with the sprite after is up to you, but I destroyed it here.

    On clicked sprite
    — create canvas at sprite position
    — set canvas size to sprite size
    — canvas: paste sprite
    — sprite: destroy
    — canvas: set drawing blend mode to destination-out
    — canvas: fill ellipse at mouse

    The other way could be to use circle sprites with the destination-out blend on layers with “force own texture”.

    You said each sprite is on its own layer, so just make sure each of those layers has “force own texture” enabled. Then erasing holes would be as simple as:

    On sprite clicked
    — create: circleSprite on layer: sprite.layer at mouse.x, mouse.y
    — circleSprite: set blend mode to destination-out
  • TestOverlapSolid just returns true or false. It doesn’t provide any info about what instance it was overlapping.

    To know the instance you’d need to use testOverlap(a,b) instead. But for that you’d need a list of instances with the solid behavior to loop over.

    One way to get that list is to access an object type that has the solid behavior, and get a list of all instances with solid like so:

    let inst = runtime.objects.Sprite. getFirstInstance();

    let list = inst.behaviors.Solid.behavior. getAllInstances();

    That’s basically how you access behaviors according to the manual. It’s not too generic if you have to tell it a type that has the solid behavior. Also it needs an instance to exist to be able to access the list too.

    A generic way could be to have a function that loops over the types in runtime.objects, gets the first instance and if it has the solid behavior save that somewhere. A bit brute force but ideally it would only need to run once, so if it found the solid behavior it would save it. Worst case is you’d have no instances with the solid behavior so it would keep searching and failing to find it.

    Anyways with that you’d be able to get a list of the instances with the solid behavior, loop over them and use testOverlap() to see if they overlap. And if they do you could then compare inst.instVars or something. Or you could even access the solid behavior tags but that may be automatic.

    You could also try and utilize constructs collision cells. To do that you’d use runtime.collisions.getCollisionCandidates() but for that it needs an object type. To get those you could loop over the list of instances with the solid behavior and make a second list without duplicates of the object types.

    Anyways I’d argue that js is fairly easy to learn. However, the hard part is finding ways to access things from the engine. Some things are easy to access, some things have to be accessed in round about ways, and for some there’s no access at all.

  • I’d say anything really. You don’t need a top of the line machine to do development. In fact if you develop something with an underpowered machine you’ll notice performance issues with your projects faster.

  • You can utilize the formula: speed*time=distance

    And solve it for time: Time=distance/speed

    You can the set distance to whatever the spacing you want is. Maybe every 8 pixels?

    Then you’d have “every 8/speed seconds”

    I can see a few issues with that approach though. At low speeds, say 0.1 pixels per second, it will be “every 80 seconds”, or worse still at a speed of zero it will be “every infinity seconds”. You can mitigate it by limiting how big the number can be: min(0.1, 8/speed)

    A second issue is the “every x seconds” is any value less than dt will be the same as dt. So at high speeds the tracks would be spaced out more again.

    Another idea is to keep track of the previous position of the tank and and use a loop to create tracks between the previous position and the next.

    Var prevx=0

    Var prevY=0

    Var ang=0

    Start of layout

    — set prevx to sprite.x

    — set prevy to sprite.y

    Every tick

    — set ang angle(prevx,prevy,sprite.x,sprite.y)

    Repeat distance(prevx,prevy,sprite.x,sprite.y)/8-1 times

    — create track at prevx,prevy

    — track: set angle to ang

    — add 8*cos(ang) to prevx

    — add 8*sin(ang) to prevy

  • Initially all the tiledbg instances share the same texture from the type. They could very well have made loading another texture replace the texture of the type instead of just the instance.

    With sprites the type has the animations attached to it so basically all the instances share the same list of animations. So when loading an image it is simplest to just replace the image in the animation which affects all instances. Only replacing an image in the animation for just one instance would be much harder to do. Probably would require duplication of the animations per instance but not the textures.

  • I think we may be talking about different things at this point. I was talking about something along the lines of:

    Mykey = str(sprite.uid)

    Dictionary: add key mykey with value dictionary.get(mykey)+1

    But I may have misunderstood what was being asked.

  • I don’t understand what you mean by str() doesn’t work with a dictionary. Sure it requires that the key be a string but you can convert a number into a string with the str() expression and it’s happy. And I’m not just saying that, I’ve done it a lot.

    I’ll defer the json questions to dop as he uses them pretty heavily. I’ve only used them sporadically and have to re figure out how to use them every time.

    If changing the layouts clears values then the object isn’t global. When something isn’t global it gets destroyed when leaving the layout and recreated when returning to it. You can make an object global in the objects settings. So maybe that’s what you’re encountering?

  • Interesting stuff. The precision of the numbers on the gpu varies depending on the hardware but the renderer does guarantee at least some minimum precisions.

    Webgl1 gives at least 24,16 and 10bit for highp,mediump and lowp float numbers.

    Webgl2 gives at least 32,16 and 10bit for highp,mediump and lowp float numbers.

    But my phone happens to give 32bit for all three.

    Presumably your phone implements the minimum spec or close to it. With less bits floating point numbers have bigger gaps between values when farther from zero. That’s why limiting the offset to be within the size of the image helps since it’s keeping values closer to zero.

    A significant example of that would be the so called “farlands” in Minecraft when exploring extremely far away.

    Anyways, I thought it was interesting. Also the fact that lowp,mediump and highp all are 32bit on my phone means if I was to make a shader I wouldn’t encounter issues that other users would see when I use mediump or lowp.

  • Try Construct 3

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

    Try Now Construct 3 users don't see these ads
  • Just make the number a string with str().

    I don’t understand the statement about json. It’s a plugin you can use.