How to make bullet shoot from the barrel in gamemaker 2[SOLVED] - game-development

when i shoot bullets with offset(when shooting the bullet would spawn as if the gun is straigh forward even if I have lets say aimed it upwards)
the gun origin point
the offset doesnt take gun rotation into the account.
The video of the problem: https://imgur.com/a/N3UxVHw.
Heres the gun/shooting code:
x = oPlayer.x + 30;
y = oPlayer.y;
image_angle=point_direction(x,y,mouse_x,mouse_y);
firerate -= 1;
if mouse_check_button_pressed(mb_left)
{
with(instance_create_layer(x + lengthdir_x(50,image_angle) ,y ,"Bullets",oBullet))
{
speed = 20;
direction = other.image_angle;
image_angle = direction;
}
}
Thanks in advance!
[SOLUTION]
edit: after 3 more hours of search I found the solution:
Spawn bullet at barrel of gun

Related

How to move camera around object to look at object from all sides?

How can a cesium camera be moved around an object in circular path?
Assuming you want something similar to helicopter circles... It can be done by 'lookAt' at every clock tick.
let heading = 0; //or any starting angle in radians
let rotation = -1; //counter-clockwise; +1 would be clockwise
let centre = new Cesium.Cartesian3.fromDegrees(longitude, latitude);
let elevation = 100; // 100 meters
let pitch = -0.7854; //looking down at 45 degrees
const SMOOTHNESS = 600; //it would make one full circle in roughly 600 frames
viewer.clock.onTick.addEventListener(() => {
heading += rotation * Math.PI / SMOOTHNESS;
viewer.camera.lookAt(centre, new Cesium.HeadingPitchRange(heading, pitch, elevation));
});

game maker GML twin stick shooter analogue controller

I am trying to make a twin stick shooter but I cannot get right analogue stick to shoot in the correct direction. Here is the code I have the weapon sits on top of the player and rotates. It all works fine just need to know how to get the correct angle of the right stick and fire a bullet in that direction.
//set depth
depth = -y + obj_player.y_off_set - 1;
//analog left stick face direction
var h_point = gamepad_axis_value(0, gp_axisrh);
var v_point = gamepad_axis_value(0, gp_axisrv);
if ((h_point != 0) || (v_point != 0))
{
var pdir = point_direction(0, 0, h_point, v_point);
var dif = angle_difference(pdir, image_angle);
image_angle += median(-20, dif, 20);
}
//flips gun when turning
if(gamepad_axis_value(0, gp_axisrh) < -0.5)
{
image_yscale = -1;
}else if (gamepad_axis_value(0, gp_axisrh) > 0.5)
{
image_yscale = 1;
}
//fireing
fire = gamepad_button_check_pressed(0, gp_shoulderr) && alarm[0] <= 0;
if(fire)
{
var face = point_direction(0, 0, gp_axisrh, gp_axisrv);
var p = instance_create(x, y, obj_projectile);
var xforce = lengthdir_x(20, face*90);
var yforce = lengthdir_x(20, face*90);
p.creator = id;
with (p){
physics_apply_impulse(x, y, xforce, yforce);
}
as this question is a couple months old, I imagine you found the solution to your problem, but hopefully this answer can help anyone else stuck on the issue.
Based on the code snippet you provided, it looks like if you remove the *90 from the lengthdir_ functions, your code should work.
Here is the code I wrote in my game to get 360 degree shooting working with the right analog stick (this code lives in the step event of the Player object):
if (shooting) {
bullet = instance_create(x, y, Bullet);
with (bullet) {
haxis = gamepad_axis_value(0, gp_axisrh);
vaxis = gamepad_axis_value(0, gp_axisrv);
dir = point_direction(0, 0, haxis, vaxis);
physics_apply_impulse(x, y, lengthdir_x(50, gp_axisrh), lengthdir_y(50, dir));
}
}
This particular thread on the GameMaker community forums was quite helpful as I researched how to solve this issue in my game.

Collision response for rectangles

I've been working on a physics engine for about a week now, being stuck for several days trying to work out how to resolve collisions.
My problem is that if there's a box stuck in the middle of 2 other boxes, or between a box and a wall, my application will get stuck in a while loop. It wont resolve the collisions.
This is my code (note: if collision is right side, it means that object A is colliding against object B with its right side. Distance is negative because the objects are inside eachother, and it's in x or y axis depending on side of collision. If you need more code, for example the collision class, which is simply a container of the 2 objects, i can provide that.):
edit: Code edited with new way of dealing with collisions:
//Move colliding objects so they don't collide anymore.
while (getCollidingAmount(objectVector)){
for (int i = 0; i < objectVector.size(); i++){
PhysicsObject* A = objectVector[i];
if (objectVector[i]->getPhysicsType() != PhysicsType::staticT && A->_collision.size() > 0){
Collision collision = A->_collision[A->getDeepestPenetrationCollisionIndex(A->_collision)];
PhysicsObject* B = collision.getObject();
switch (collision.getSide()){
case SideOfCollision::left:
case SideOfCollision::top:
//Opposite velocity
if (A->_saveVelocity.x < 0 && B->_saveVelocity.x > 0){
long double percentageOfVelocity = std::min(abs(B->_saveVelocity.x), abs(A->_saveVelocity.x)) /
std::max(abs(B->_saveVelocity.x), abs(A->_saveVelocity.x));
A->_position.x -= percentageOfVelocity*collision.getVectorPenetration().x;
A->_position.y -= percentageOfVelocity*collision.getVectorPenetration().y;
}
else{
A->_position.x -= collision.getVectorPenetration().x;
A->_position.y -= collision.getVectorPenetration().y;
}
break;
case SideOfCollision::right:
case SideOfCollision::bottom:
//Opposite velocity
if (A->_saveVelocity.x > 0 && B->_saveVelocity.x < 0){
long double percentageOfVelocity = 1 - std::min(abs(B->_saveVelocity.x), abs(A->_saveVelocity.x)) /
std::max(abs(B->_saveVelocity.x), abs(A->_saveVelocity.x));
A->_position.x -= percentageOfVelocity*collision.getVectorPenetration().x;
A->_position.y -= percentageOfVelocity*collision.getVectorPenetration().y;
}
else{
A->_position.x -= collision.getVectorPenetration().x;
A->_position.y -= collision.getVectorPenetration().y;
}
break;
}
updateCollisions(objectVector);
}
}
}
Update
Something wrong with my trigonometry in bottom and top collisions:
sf::Vector2<long double> Collision::getVectorPenetration() const{
long double x;
long double y;
long double velX = _object->getVelocity().x;
long double velY = _object->getVelocity().y;
long double angle = atan2(velY, velX);
if (_side == SideOfCollision::left || _side == SideOfCollision::right){
x = getDistance();
y = x * tan(angle);
return sf::Vector2<long double>(x, y);
}
else if (_side == SideOfCollision::top || _side == SideOfCollision::bottom){
y = getDistance();
x = y / tan(angle);
return sf::Vector2<long double>(x, y);
}
}
Update 2
Thanks to Aiman, i solved my issue. Updated my collisionResponse code aswell to match my new way of dealing with collisions. I'm having another issue now where gravity makes it so i can't move in X direction when touching another object. If anyone familiar with this issue wants to give any tips to solve it, i appreciate it :).
Update 3
So it seems gravity is not actually the problem since i can swap gravity to the x axis, and then be able to slide boxes along the walls. There seems to still be something wrong with the trigonometry.
I can think of many ways to approach the problem.
1-**The more complicated one is to **introduce friction. Here is how I'd implement it, though this is untested and there is a chance I missed something in my train of thought.
Every shape gets a friction constant, and according to those your objects slide when they collide.
First, you need to get the angle that is perpendicular to your surface. To do this, you just get the arctan of the the surface's normal slope. The normal is simply -1/m, where m is the slope of your surface (which you is the ratio/quotient of how much the surface extends in y to/by how much it extends in x). Let's call this angle sNormal for "surface normal". We may also need sAngle-"surface angle" for later (you find that by arctan(m)). There remains some ambiguity in the angle that has to do with whether you're talking about the 'front' or the 'back' of the surface. You'll have to deal with that manually.
Next, you need the angle of the trajectory your object flies in, which you already know how to find (atan2(y,x)). We'll call this angle oAngle for "object's surface angle". Next, you calculate deltaAngle = sNormal - oAngle. This angle represents how much momentum was not blocked completely by the surface. A deltaAngle of 0 means all momentum is gone, and a value of PI/2 or 90 means the 2 surfaces are in parallel touching each other not blocking any momentum at all. Anything in between, we interpolate:
newSpeed = objectSpeed * deltaAngle/(PI/2);
newVelocity.x = cos(sAngle) * objectSpeed;
newVelocity.y = sin(sAngle) * objectSpeed;
Now this assumes 0 friction. If we let a friction of 1 be the maximum friction which doesn't allow the object to "slide", we modify the newSpeed before we apply the newVelocity values, like so: newSpeed *= (1-friction);.
And there we have it! Just give your platform a friction value of less than 1 and your box will be able to slide. If you're dealing with upright boxes, then the surface angle is PI for top wall, 0 for the bottom, PI/2 for the right and -PI/2 for the left wall.
2-The simpler option is to subtract gravity from the object's y-velocity in the solver's calculation.

How do I randomize the starting direction of a ball in Spritekit?

I've started trying a few things with SpriteKit for Game Development. I was creating a brick breaking game. So I've run into a issue on how to randomize the starting direction of the ball.
My ball has the following properties
ball.physicsBody.friction = 0;
ball.physicsBody.linearDamping = 0;
ball.physicsBody.restitution = 1 ; //energy lost on impact or bounciness
To start at different direction during the gameplay, I've randomized the selection of the 4 vectors because I'm using the applyImpulse method to direct the ball in a particular direction and I need to make sure the ball does not go slow if the vector values are low.
int initialDirection = arc4random()%10;
CGVector myVector;
if(initialDirection < 2)
{
myVector = CGVectorMake(4, 7);
}
else if(initialDirection >3 && initialDirection <= 6)
{
myVector = CGVectorMake(-7, -5);
}
else if(initialDirection >6 && initialDirection <= 8)
{
myVector = CGVectorMake(-5, -8);
}
else
{
myVector = CGVectorMake(8, 5);
}
//apply the vector
[ball.physicsBody applyImpulse:myVector];
Is this the right way to do it? I tried using applyForce method but then, ball slowed down after the force was applied.
Is there any way I can randomize the direction and still maintain a speed for my ball ?
The basic steps
Randomly select an angle in [0, 2*PI)
Select the magnitude of the impulse
Form vector by converting magnitude/angle to vector components
Here's an example of how to do that
ObjC:
CGFloat angle = arc4random_uniform(1000)/1000.0 * M_PI_2;
CGFloat magnitude = 4;
CGVector vector = CGVectorMake(magnitude*cos(angle), magnitude*sin(angle));
[ball.physicsBody applyImpulse:vector];
Swift
let angle:CGFloat = CGFloat(arc4random_uniform(1000)/1000) * (CGFloat.pi/2)
let magnitude:CGFloat = 4
let vector = CGVector(x:magnitude * cos(angle), y:magnitude * sin(angle))
ball.physicsBody?.applyImpulse(vector)

Looping moving background objective-C

I am testing a background-loop animation where there will be to images both 1024x768 pixels in dimension, move leftwards, go offscreen, then jump back to the other side, and repeat.
I was able to do this by creating a constant speed for both background image to move (successful), and then I tried the following code to make it jump, but there was a problem:
if((background.center.x) < -511){
background.center = CGPointMake(1536, background.center.y);
}
if((background2.center.x) < -511){
background2.center = CGPointMake(1536, background2.center.y);
}
Somehow this is not working the way I expected. It leaves a few pixels of gap every time, and I am confused why. Does anyone know what's causing this to happen and how to fix it? Thanks!
It seems like you have forgotten to take into account the distance moved. The greater than expression might have been triggered because you moved to far. I guess your movement is larger than 1 pixel/frame.
I am not sure what kind of values that are feeding your movement but I think to take into account the movement you should do something like...
if ((background.center.x) < -511){
CGFloat dist = background.center.x + 512;
background.center = CGPointMake(1536+dist, background.center.y);
}
if ((background2.center.x) < -511){
CGFloat dist = background2.center.x + 512;
background2.center = CGPointMake(1536+dist, background2.center.y);
}
Rather than have the two images move (sort of) independently, I would keep track of a single backgroundPosition variable and then constantly update the position of both images relative to that one position. This should keep everything nice and tidy:
CGFloat const backgroundWidth = 1024;
CGFloat const backgroundSpeed = 2;
- (void)animateBackground {
backgroundPosition -= backgroundSpeed;
if (backgroundPosition < 0) {
backgroundPosition += backgroundWidth;
}
background1.center.x = backgroundPosition - backgroundWidth/2;
background2.center.x = backgroundPosition + backgroundWidth/2;
}