R0J0hound's Forum Posts

  • Looks like your requirements were simpler than I thought after looking at your c3p.

    Updated and tested this as working in events. Adapting it to js will require you to convert the fov of 45 to radians.

    It takes the height of the viewport, 45 which is the fov, and the center of the screen which can be the scroll center or just half the viewport size if there is no scrolling.

    zplane = -100
    scale = 1-zplane*tan(45/2)/(Height/2)
    
    x = (mouse.x - center.x)*scale + center.x
    y = (mouse.y - center.y)*scale + center.x
    z = zplane
  • So it’s mostly just a matter of calculating the intersection of the mouse ray (camera to mouse) and the plane at z=-100.

    So the long way of calculating the mouse ray would be to consider the mouse position on a 2d layer and make a vector from the center of the screen and camera eye distance ( can be calculated from screen size and fov) to the mouse position. Then you’d need to rotate that by the camera’s orientation matrix and adding the camera position.

    The simpler way to get the mouse ray could be to leverage existing c3 features. If you get the mouse position on a 3d layer it will give you the xy of the mouse projected on the z=0 plane. So the ray would be from the camera to that.

    So, anyways the generic formulas for a line and plane are:

    P=p1+u*(p2-p1)

    N dot (P-p3)=0

    And the intersection can be found by combining the two formulas and solving for u:

    U= (N dot (p3-p1))/(N dot (p2-p1))

    And finally plugging that back into the line equation to get the actual point.

    However in your case it all can be simplified at lot.

    P1 = camera.pos

    P2 = vec(mouse.x, mouse.y, 0)

    P3 = vec(0,0,-100)

    N = vec(0,0,1)

    So barring any errors the final equations should be:

    PlaneZ =-100

    X = lerp(camera.x, mouse.x, -planeZ/camera.z+1)

    y = lerp(camera.y, mouse.y, -planeZ/camera.z+1)

    Z = planeZ

    Just make sure the mouse coordinates are from a 3d layer. You can specify the layer you get the mouse coordinates from with mouse.X(layer)

  • Looks cool as always.

    Is there a particular project that you're making to utilize this? Or is there any end goal feature set you want to have?

  • Try Construct 3

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

    Try Now Construct 3 users don't see these ads
  • One way could be to have a dummy 3d object that you rotate (since you said you have been able to do that).

    Then just set the 3dcamera’s orientation from that object’s orientation.

    The main issue is there are three ways to specify 3d orientation: Euler, quaternion, and 3x3matrix. Most objects let you use Euler and quaternion, but with the camera you can only set the orientation in a general way with the look at action which basically takes a 3x3matrix.

    You can convert between the different orientation representations with some math that you can find online. For example:

    euclideanspace.com/maths/geometry/rotations/conversions/quaternionToMatrix/index.htm

    So say you have an object’s orientation as a quaternion (qx,qy,qz,qw) which there are expressions for. Then you can convert it to a 3x3 matrix. In the matrix the second row would be the up vector, and the third row would be the forward or basically the look at vector if you add the camera position.

    So the parameters for the look at action should be:

    Camera x = self.x
    Camera y = self.y
    Camera z = self.z
    Look x = 2*qx*qz - 2*qy*qw +self.x
    Look y = 2*qy*qz + 2*qx*qw +self.y
    Look z = 1 - 2*qx^2 - 2*qy^2 +self.z
    Up x = 2*qx*qy + 2*qz*qw
    Up y = 1 - 2*qx^2 - 2*qz^2
    Up z = 2*qy*qz - 2*qx*qw

    The qx means 3dobject.QuaternionX In those expressions if that’s not clear. Same for qy, qz and qw.

    Anyways, barring any typos on my part or some oddity in c3 then that should work.

    You could also convert between Euler and matrix instead. But you’d have to try different rotation orders if c3 rotates xyz in different orders than the formulas.

    Maybe c3 will hide the complexity at a later date and just let you set the camera’s orientation from another object, or just give everything the same rotation tools. But short term things seem to look more and more cluttered to me.

  • You need to edit the function and specify the return value type there.

    Just using the return action isn’t enough.

  • I think most missing things are usually an oversight that a quick feature request could probably remedy.

    So apart from agreeing that such a feature sounds like it could be useful, I don’t have much to add.

  • Maybe you could set an instance variable in the timeline that’s normally a different value. Or if you specify the instance at runtime with the “set instance” action you could try to keep track of it then too.

    If you don’t mind a multiple build step approach you could make a tool to parses the timeline information out of the c3p file and sets a json file in the project you can access. Or maybe you could access the exported data file directly and parse out the timeline info from that.

    Scripting wise it may be easier to just request a method to be able to access it from the api.

  • Short of access to the actual project and someone taking time to look through it it won’t be possible to debug.

    That said areas you could focus your attention on is the “or” blocks and “trigger once” conditions. Or blocks tend to bite me often so I carefully ensure they are doing what I intend when I use them.

    Maybe putting a for each in the custom actions may help too. In general many find it simpler to use “for each” in any place that there may be multiple picked instances to make the logic more clear to them.

  • Let us know if you want to be confined to any other shape.

    A rotated rectangle can be done by first rotating position offset by the -angle, then clamping by the size, and rotating the angle back again.

    A circle shape can be done by measuring the angle and distance, clamping the distance, the calculating a new position from that.

    If you want to limit it to an object’s collision polygon, and the polygon is a convex polygon, you can take the position offset and clip it by each edge with a bit of math. Namely with (x-x0)*cos(a)+(y-y0)*sin(a) you can measure a distance along a certain direction. If you use that with an angle 90 degrees from an edge you can find if a point is on either side of an edge and clip it if on one side.

    Finally if you want to limit the motion to a concave shape you probably could do that by storing the players previous position and calculating the line intersections between the edges and the segment connecting the new and old position, and finally just stop at the first intersection. I don’t think that would provide any wall sliding but one idea for that involves decomposing the concave shape into convex ones, but it may be a bit more involved. Basically you’d check for overlaps with edges, the limit to the convex sub polygon that edge is part of.

    Also depending on the shape you could possibly utilize sdfs to implement the limit. That would let you have shapes with rounded corners.

    Taking the sdf idea further, you could make an approximate sdf on a 2d grid of any shape and raymarch through that. The main complexity there would be generating it.

    There are some low tech approaches too. You could store the old and new positions and use a loop with an overlap test to move but stop short of leaving the other object.

    Dop’s suggestion to place invisible solid objects around the shape is probably the easiest no code option. Another is to make the collision polygon a crescent shape that you wrap around the object image so there’s a thick wall around it.

    With collision based approaches beware of tunneling. Aka with high speeds and thin walls the collisions can be missed and objects will move right through.

    There are probably other approaches with varying pros and cons.

  • That’s a tricky one to give an exact answer since most don’t have such specific requirements.

    That said, it looks like there are expressions to get the current playback time and the time of nodes on the timeline. That combined with the duration of a landing animation you could have an event to check the time to decide when to change the animation.

    Having the requirement of only changing animations on a particular frame can be handled with events too. However combined with that other constraint you may need to adjust the speeds of things.

    For example, say you have a looping running animation you want to jump at a node on the timeline, but you only want it to change on a particular frame you’d want to either pause the timeline at that node and wait till it’s at the right frame or look at the time anticipating the node and speed up/ or slow down the animation speed so that the frame is where you want it to be at that node.

    There’s probably a system you could make to do that in a general way. Like you’d have the list of animations you know you need to move through and a list of the nodes on the timeline where you what the transitions to be. Then it would adjust either the speed on the path or the speed of the animations so that the transitions are at the exact time and frame you want.

  • I mean I know why it happens. It’s an artifact of how those behaviors resolve collisions.

    The collisions are resolved roughly by moving in steps till there is no overlap. Since it moves in steps it’s only approximate but is generally good enough. With zoomed in pixel art the error is magnified though.

    Anyways, I don’t think there’s any setting to eliminate it, but shrinking the collision poly could shift to look like it’s slightly overlapping instead of having a gap.

    You could also do your own collision handling. Aka don’t use the solid or jump through behaviors and do your own collision detection/resolution. You might get away with doing that with the 8direction behavior but with the platform behavior it would likely be better to just do the whole behavior from events.

    Focusing on how we could do a better collision resolution, we could do a progressive stepping solution that moves in big steps first then increasingly smaller steps to get a very close near perfect touch between the objects. Alternately, you could focus on calculating where the objects should be to be just touching. Either way we’d need to be able to calculate the collision normal to be able to update the velocity.

  • How many cases are you trying to handle? All of them?

    If it’s only some then you just need to know the number of wall to compare the pickedCount with and pick each wall in turn separated by pick all.

    You could make a helper function that returns 0 or 1 if a wall is at a location. But then you’d have to use 8 compares to check for each case.

    Or you could do that idea in my second reply that sets a neighbor variable to whether a wall is at each direction or not. For example “00000001” would be a wall to the NE.

    Not super readable but maybe you could modify it to be “NE” instead or maybe “7”.

  • My bad, it should be comparing the picked count with two in the second example since we are checking two tiles. I edited that post.

    You may just need to work though the logic yourself a bit more. The best solution is one you understand.

  • So it appears you can’t stay logged in on the same account with multiple devices anymore. I check the forum from my phone and laptop and if I login on one it logs me out on the other. I can see the reasoning to avoid multiple users using the same subscription, but I’m kind of the outlier since I don’t have a subscription, I’m just a forum user.

    No worries though. I’ll get used to it.

    More annoying is the incessant huge delay to verify I’m a human almost every visit to the forum from my phone. Often repeatedly if I use “back”. It seems to even be taking longer as of late. I suppose those kind of things are the new reality of the internet.

    It’s just a lot of friction to the point where I think maybe I should spend my time doing something else. Which isn’t a bad thing.

  • The pick all needs to be in the same event block. You’re using multiple.

    All the conditions in the last example I posted can be in one event block and it’ll work. Most of the conditions can have their own block but this at least has to be grouped in the same block.

    Wall: x=tile.x-100
    Wall: y=tile.y
    Pick all wall
    Wall: x=tile.x+100
    Wall: y=tile.y

    All it does if it’s able to pick the first wall it then tries to pick the second. The pick all makes so it can even pick another wall.