0 Favourites

Need help working with bullets [Resolved]

  • Okay, folks, I'm about to write another dissertation, here, so sorry about the text-wall again beforehand.

    I got some excellent help here with the last problem I encountered trying to learn the engine, so I'm back again with yet another problem that I could use some help with. More accurately: I have a whole set of problems this time. Heh.

    I'm dealing, now, with bullets. The game I'm working on is, quote, unquote "realistic," so I'm desperately trying to avoid having any visible projectile when my guns are firing. But, there doesn't seem to be an option for instant-hit projectiles in Construct 2, so I've simply made an object with Bullet behavior with a very small sprite (3x3) that travels very fast (speed: 5000). Unfortunately, this combination of small sprite and fast speed seems to be leading to a "skipping" problem, where the bullets are not registering collision.

    Also, I would like to occasionally (about 1/8 chance; 100% on critical hit, but that's another discussion) display a tracer effect on the screen when a shot is fired, just so that there is some visible indication as to where the shots are going. Since my bullet is very fast, the tracer effect basically amounts to a line drawn across the screen in the direction of the bullet.

    I've achieved some success with the tracer by making a spherical gradient sprite, blending it Additive, and attempting to stretch it from the muzzle of the gun to the bullet as it travels across the screen by setting its width and height. The effect looks nice, but it begins several hundred pixels out from the muzzle of the gun, rather than at the coordinates of the image point. I'm assuming this is because the bullet to which it is pinned is traveling extremely fast. I'm hoping someone can give me some insight about how to fix that.

    Finally: I would like to group the bullet object and the tracer object together such that when a bullet is spawned, a tracer is also spawned along with it automatically; furthermore, when that bullet is destroyed, be it on contact with a solid object, or target, or out of the layout, or what-have-you, I'd like the tracer to be simultaneously destroyed along with it. Using the Container feature seems to be the way to do this—again, I'm new, I don't know these things for sure—but unfortunately, every time I try to combine the two objects into a container, I'm greeted with this:

    I've been working on it off and on all day, and have come up with nothing satisfactory. I honestly can't provide much in the way of examples of my work because I've completely discombobulated it with about a zillion lines of crud, and it would be very difficult to make sense of. At this point, I probably need to scrap what I have and start over.

    Can anyone offer advice, or point me in the general direction of examples that I can use to achieve the effects I'm after?

  • On the bullet issue, the reason why it skips is because is too fast, and too small. The fix, add a "tail" or something to bullet, make it invisible if u wish, so it can make the body of the bullet long enough to "touch" the object you are intending to hit. Maybe use it as ur tracing line, or something like that

  • When working with invisible/instant bullets, I highly suggest avoiding actually using the bullet behavior on a sprite for any sort of hit calculation. Basically with speed 5000, for example, your sprite jumps 5000 pixels every frame - it doesn't actually travel through those pixels. So if your collision object is somewhere in the middle there, the two sprites never touch each other, so there is no collision. It's fine for just visuals though, for example your tracer lines.

    For your hitbox mechanics, you'll need some work in some custom code, since as you mentioned there are no built in behaviors for instant hit projectiles in C2 (also remember all behaviors are just shortcuts, they can all be recreated with the event system).

    You can try using a line of sight style calculation. The condition to check for is if the target is within angle of your shot, which you can base on either the current angle of the player sprite or the angle from the player sprite to your mouse, depending on what your controls are like. When you fire, if your target is within this angle, then hit! From there, you can add sub-events to have % chance to crit, or % chance to hit even when the shot is on target. Then create the visual based on what actually happened. Also, you can use the Line of Sight behavior to make sure there isn't an obstacle between player and target.

    Some angle expressions you might find useful when working on this -

    angle(targetSprite.x, targetSprite.y, playerSprite.x, playerSprite.y) - The angle between player and target.

    angle(mouse.x, mouse,y, playerSprite.x, playerSprite.y) - The angle between player and mouse.

    playerSprite.angle - The angle the player is currently facing.

    random(100) - A random number between but not including 0 and 100

    cel(random(100)) - A random WHOLE number between and including 1 and 100

    I'm working on something similar so let me know if you want a .capx example. I find there's a lot of satisfaction in figuring it out for yourself though!

  • It might just be because I have a horrible headache, but the solution to this is still illuding me. Basically what I want is:

    On mouse click, draw a line.

    If that line hits something, anything, return the position of the collision, and the object that was hit.

    Set the end-position of the shot to the position of the hit

    Handle the collision (damage, sparks, debris flying, whatever)

    Else, if the line hits nothing

    Set the end position to the border of the window (keeps errant bullets from hitting things off screen)

    Draw a tracer between the muzzle of the gun and the end position (whichever end position that may be)

    I just can't find the methods I'd need to pull that off, nor a suitable replacement for that behavior. Maybe I'm looking in the wrong places, or maybe there's a different way of looking at it. The editor that I used to use had a function for determining whether or not there was a collision along some line segment (x1,y1,x2,y2), so I'd just call that in a recursive binary search until I determined the exact pixellate location of the impact and go from there. I lack enough familiarity with Construct 2 to duplicate the effect.

    I appreciate the input, I'll take it back up tomorrow. I can't stare at my screen anymore right now. Heh.

  • Construct 3

    Buy Construct 3

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

    Buy Now Construct 3 users don't see these ads
  • Okay, I was able to achieve the summation of the effects I desired by elongating the actual image for the bullet (a spin-off of an above suggestion) and leaving everything else (the high speed, etc) the same. As it turns out, the elongated sprite works both for helping with the collision detection and (combined with the high velocity) providing a nice "tracer" effect. I guess I was overthinking the problem, something which I'm notorious for.

    I do, however, have one more problem I'd like to resolve: the first bullet being fired doesn't seem to be originating from the correct position. All of my player sprites have an image point called "Muzzle." It is image point 1. The "Muzzle" point, as the name implies, is supposed to be the origin of muzzle flashes and bullets. I have verified that it's position is correct on all animations, in all sub-images.

    However, the first bullet fired, and only the first bullet fired, in a sequence is positioned a good distance away from the player sprite, i.e.: nowhere near the "Muzzle" point. If an automatic weapon is fired, and there are therefore subsequent shots, all of those shots are fired from the "Muzzle" point. Only shots from "single-shot" weapons, and the first shot from automatic weapons is affected.

    I assume there is an error somewhere in my sequence of events that I have been unable to detect. Below is an image of the relevant events.

    If anyone can provide some insight into why only the first bullet seems to be off in position, I'd greatly appreciate it.

  • The first thing that comes to mind is your image point being off for that animation/frame but you said you checked that already. Did you check the origin point for the bullet itself? Is that animated?

  • The first thing that comes to mind is your image point being off for that animation/frame but you said you checked that already. Did you check the origin point for the bullet itself? Is that animated?

    The "bullet" itself is nothing more than a single image. I've tried moving its origin point around to see if that had any effect, but it does not. The first shot is still placed considerably farther away from all subsequent shots.

  • Is it in line with where it should be? Maybe it is travelling a frame before it gets rendered. Another thing I thought of was maybe it is starting out invisible (50%chance?) And gets revealed on the next tick.

  • Just to clarify a few things:

    The distance an object moves per frame is speed*dt, so with a speed of 5000 the object will move 5000/60 or about 83 pixels per frame, which is why it can pass other objects without colliding.

    For doing an instant hit, the common approach is called "ray casting", but you can also find examples on the forum about lasers that do it too. By using a sprite and changing the width you can do the same thing as the line segment idea.

    That error is a bug I'd say, and a good candidate for an error report.

    Your last issue is probably something simple, but we'd need to see a capx to find it. The posted events don't seem to cause it.

  • EDIT: Unfortunately, the forum's auto-moderation is preventing me from posting the link to the tutorial I describe below. However, it's a pretty popular one, and comes up pretty quick in a search engine.

    Is it in line with where it should be? Maybe it is travelling a frame before it gets rendered. Another thing I thought of was maybe it is starting out invisible (50%chance?) And gets revealed on the next tick.

    Yes, it's spawned at the proper angle. The delay between spawn and render is my best guess as to why it's not showing up at the proper point. For testing purposes, the sprite is set to visible by default, bypassing the random "tracer chance," so I know it's probably not that.

    Just to clarify a few things:

    The distance an object moves per frame is speed*dt, so with a speed of 5000 the object will move 5000/60 or about 83 pixels per frame, which is why it can pass other objects without colliding.

    For doing an instant hit, the common approach is called "ray casting", but you can also find examples on the forum about lasers that do it too. By using a sprite and changing the width you can do the same thing as the line segment idea.

    That error is a bug I'd say, and a good candidate for an error report.

    Your last issue is probably something simple, but we'd need to see a capx to find it. The posted events don't seem to cause it.

    When I was first exploring the site, before I actually downloaded the software, I found what looked to be a good raycasting tutorial ( ... raycasting), but, unfortunately, due to my bumbling unfamiliarity with Construct 2, I was unable to determine how to return the values I need from that function for post-impact processing:

    • The ID of the entity that was hit by the ray, for damage/stat/knockback calculations
    • The relative position of the impact for my ridiculous, stomach-turning, nightmare inducing gore splatter engine

    If anyone can help me figure out getting that information from that style of raycasting function, then that would be perfect. The function I used in my other editors followed very similar logic, and I'd love to use it here, if possible.

  • Here's the basics of how to do it. It can be further refined to be more precise and you can use a family instead of wall to hit more object types.

    Add a Sprite to your project and call it Ray. In the image editor put it's origin on the left-center and add another image point to the right center. Once on the layout, make it's height 1.

    Every tick

    --- ray: set position to player

    --- ray: set angle towards (mouse.x, mouse.y)

    Repeat 100 times

    --- ray: set width to 100*(loopindex+1)

    [sub event] ray: overlaps wall

    --- stop loop

    --- ray: spawn explosion at imagepoint 1

    --- wall: destroy

  • Nifty! So looking at this the ray keeps growing until it hits something, but the explosions would always spawn at 100 pixel intervals, at the end of the ray. You can increase the resolution by decreasing the width increase but at the cost of more repeats in your loop which *might* lag.

    How about spawning the explosion/hit from the target that got hit instead? After you confirm a hit, spawn the explosion from the sprite that got hit - at an angle back towards the player a certain distance based on the size of the target.

    You'll be able to get the distance from the player to the target as well, which can be useful for graphical elements like so the tracer doesn't go through the target (unless you want it to).

    Another problem I anticipate: what if there are two targets in close proximity, that both get overlapped when the ray grows? Maybe use another sub event to pick the closest out of the targets that were picked by the ray?

  • oosyrag

    I meant it to be 10 pixel intervals:

    ray: set width to 10*(loopindex+1)

    So the furthest a ray would be able to go is 100*10 or 1000 pixels which is fine for stuff on screen with a res of 640x480. Best case it would check for collisions once, and worst case it would check for collisions 100 times. It's the difference of hitting something close or nothing at all.

    If you're curious here's a more advanced example that also can be tweaked:

    The laser in it has a range of 1000 pixels and only checks for collisions 10 times if nothing is hit. It's progressive so it finds the hit point with a 1/1000 pixel accuracy. The worst case is around 50 collision checks if it hits an object near the 1000 pixel range, but typically it's much lower.

  • I see, a progressive increase in accuracy is much more efficient, and no need to worry about overlapping multiple objects.. Also yay for custom particles, I was just running into some limitations of the particle object in my own project, like not being able to have random angles. This will do nicely

  • With the help of the information I've gleaned from this thread, and the raycasting tutorial I discovered, I put together the following function:

    This function performs very well, since it is only called once per "pull of the trigger," so to speak. There's no need to constantly call it since I only need to check once whether or not each bullet hits.

    However, there is still one small problem I'm experiencing when dealing with multiple targets. If multiple targets are lined up, both horizontally and vertically, then when shots are fired into the group, shots coming from the left and from the top (firing toward 0° and 270° respectively) hit only the first target in range, as it's supposed to, leaving the ones "behind" them in line untouched. However, if firing into the group from the bottom or from the right (90° and 180° respectively), then the shots hit all targets in the line instead of just the first one.

    I find it odd that it works perfectly from two sides, and not from the other. The sprite itself (the visual component) is properly sized for all shots, those that work right and those that don't. i.e., even when shots are hitting multiple targets, the width of the "ray" sprite displays correctly (stops upon hitting the first target in line). This leads me to believe I'm selecting instances from the data structure incorrectly.

    Any thoughts?

Jump to:
Active Users
There are 1 visitors browsing this topic (0 users and 1 guests)