I am trying to make a top down game where you throw a disc using Box2d. The world has no gravity so the disc can be thrown and just bounces around the stage with the inertia and linear damping that I have set it with. Now, if I try to introduce wind using ApplyForce on an enter frame it will constantly push the disc in that direction until it hits a wall. What I am looking to do - with no luck so far - is give the stage (ground) some fiction so as the ball loses momentum it will eventually rest/stick. The code for the ApplyForce is as follows:
var xA = (Math.sin(windDir*(Math.PI/180)) * windSpeed * -1);
var yA = (Math.cos(windDir*(Math.PI/180)) * windSpeed );
var wind:V2 = new V2(xA, yA);
ball1.b2body.ApplyForce(wind, new V2(ball1.x, ball1.y));
Any thoughts?
Thanks.
if it will have friction, it either wont move, or will move again until hits the wall, but slower.. its simple physics. you can slow down every object, but not with applyforce, because box2d is a simulator, and you want to do unrealistic thing.
Related
Let me tell you a scenario which am facing right now , I have a movieclip which will move along the bezier curve and a button which will start the play(movie clip will move along the curve) and bezier points , am using greensock which have an autorotate option where you will rotate the movie clip along the path.
so i need to know what rotation will the movieclip will be at the end of play , because when auto rotate is enabled my rotation at start time will be 0 but by the end time of the play what will it be ???? I need to know that value before the tween happens , please help!
There is, of course, math that you could do to figure it all out, but it's probably easier to just let the tween handle it and simply jump to the end, read the value, and rewind again. No need to create a separate tween that lasts 0.0001 seconds and wait for an onComplete or anything like that - just use the original tween:
var tween:TweenMax = TweenMax.to(...); //your bezier tween
tween.progress(1); //jump to the end
var endRotation:Number = mc.rotation; //read the final rotation
tween.progress(0); //rewind back to the beginning
There is sure some mathematical way to calculate this but then you would basically need to rewrite the whole bezier movement logic.
A quick and dirty way would be to set your movieclip alpha to 0 at first (or create a new empty sprite) and let the same bezier movement run within lets say 0.0001 second. In onComplete check the final movieclip rotation and start the actual tweening. I'ts kind of hacky but it will work :)
I'm attempting a to make a fighting game with multiple platforms. I've successfully made the controls, movement, (double)jumping, and gravity parts of the game.
The issue is, when a player jumps, upon reaching the ground, they seem to go a bit deeper than they should on the platform (they should land and stay on the surface of the platform). This is more visible when the player double jumps.
I know why this happens; it's because sometimes hitTestObject takes a while to react when objects come in too quickly.
So, the first thing I thought of is to make the player's foot's y axis equal to the y axis of the top of the platform he lands on.
Though, that solution resulted in a rather jerky landing.
My question is: Is there a way to make the player to land smoothly on the top surface of the platform?
Some things I've tried:
-Raising FPS, it just made the same effect happen, but more quickly.
-Decreasing the speed at which the player falls, but that makes the game less fun, so I've crossed it out.
And here's my relevant code:
stage.addEventListener(Event.ENTER_FRAME, loop);
var jumpConstant:Number = 30;
var gravityConstant:Number = 1.8;
function loop(e:Event):void //happens
{
if(player.leg1.foreleg1.foot1.hitTestObject(platforms.ground)||player.leg2.foreleg2.foot2.hitTestObject(platforms.ground)) //if either of the player's legs are colliding with the platform [ps: nested movieclips]
{
player.ySpeed = 0; //the player stops going downwards
player.y = platforms.y; //the player's y becomes the platform's y. don't worry, it puts the player in the right place, just not smoothly.
if (player.b_up) //if Up control button (W or Up Arrow) is being pressed
{
player.ySpeed = -player.jumpConstant; //make the player jump
}
else //if the player isn't colliding with the platform
{
player.ySpeed += player.gravityConstant; //the player is affected by gravity and is pulled downwards
}
Link to the game if you wanna try it out to see the jerky effect:
http://www.fastswf.com/-64Ux3I
The problem is that you are only checking for a collision at increments of ySpeed. Since y speed increases during a fall by 1.8 per step, you are quickly looking at collision checks spaced widely apart. If you want pixel precise collision checks, you need to check for collision at 1px increments. This means if y speed is 10, you need 10 collision checks during one loop update. Use a for loop within your loop function to accomplish this.
Why don't you set hitTestObject y coordinates a bit above the ground so the sinking into the ground will actually make it touch the ground now.
As i am working on side view bike stunt game in which am trying to add slow motion effect when a bike performs stunts.
Is there any solution for showing such kind of slow motion effect in Box2D. can anybody help me in this regard
Thanks and regards,
Chandrasekhar
As mentioned already, changing the length of the time step can give a slow motion effect. It also has the side-effect of altering the way gravity affects bodies, and can complicate other things like recording a replay or syncing state across multiplayer games for example.
Another option is to use a fixed time step length for every time step, and keep track of the previous position and angle for all bodies. Then you can interpolate between the last frame and the current frame to draw them at an in-between frames position. This means that you are always drawing things a tiny bit behind their current position in the physics engine, but it should not be noticeable with typical frame-rates of 30-60fps.
An easy way to do this effect with or without Box2D is to step up a time modifier.
so lets say you move the player in a run function like so:
player.x += vel_x;
player.y += vel_y;
you could setup a time modifier variable that is initialized to 1
var time_mod:Number = 1;
then update all your movements as followed
player.x += vel_x * time_mod;
player.y += vel_y * time_mod;
then when you want "the slow motion effect" change your time_mod variable. For half of real time change your time_mod to 0.5. If you want to super speed change it to 2 or 3, super slow? change to 0.3
you get the idea?
I am new to working in ActionScript and I'm experimenting with using the Timeline to trigger certain events in my game. In particular, I'm using the timeline to trigger the fire event for a gun so that when the fire animation gets to a certain frame, a bullet is spawned. In the gun class (Enter_Frame) I check that the mouse is being held down and the time between the last shot and the current time is longer than the cool down, if everything checks out I play the animation.
if (time - lastShot > cooldown)
{
canShoot = true;
lastShot = time;
}
if (mouseHold && canShoot)
{
play();
}
This creates a problem when the frame rate is brought below the point where the full animation cannot be played before the cool down is up again. In this instance the bullets fire slower with lower frame rates.
In addition, higher frame rates make the gun more responsive to mouse input because the fire frame comes sooner than in lower frame rates.
The goal is obviously to make the game completely frame rate independent. I would like to have the ability to slow down or speed up the frame rate of the animation depending on the cool down of the gun.
What is the best way to make this animation play in a specific time period without skipping over the actions that I have put into the timeline?
It sounds like you're on the right track, but approaching this the wrong way. Check out the Timer class, it's framerate independent, and will greatly aid you.
var my_timer = new Timer(1000,0); //in milliseconds
my_timer.addEventListener(TimerEvent.TIMER, catchTimer);
my_timer.start();
function catchTimer(e:TimerEvent)
{
trace("event fired");
}
You should look into time based animation instead of frame based if you want your animations to be precise and not depend on the framerate, this way your animations will always be the same and will compensate the slower frame rates of slower computers. Here is an article that explains it very well: http://www.flashgamesclassroom.com/classroom/actionscript/frame-based-vs-time-based-animation/
I have created a collision class to detect collisions using pixels. In my class I've also developed some functions for determining the collsion angle. Based on this I created some examples:
http://megaswf.com/serve/25437/
http://megaswf.com/serve/25436/
(Space to change gravity, right/left to give some speed to the ball.)
As you will probably notice, there are strange things that happen:
When the ball speed is very low
When the direction of the ball is
almost tangent to the obstacle.
collision http://img514.imageshack.us/img514/4059/colisao.png
The above image shows how I calculate the collision angle.
I call the red dots the keypoints. I search for a maximum number of keypoints (normally 4). If I find more then 2 keypoints, I choose the 2 farthest ones (as shown in one of the blue objects). Thats how I then find the normal angle to where in the surface the object collided. I don't know if this is an obsolete way of doing things.
based on that angle, I rotate the speed vector to do the bouncing.
The piece of code to do the maths is here:
static public function newSpeedVector(speedX: Number, speedY: Number, normalAngle: Number): Object{
var vector_angle: Number = Math.atan2(speedY, speedX) * (180/Math.PI);
var rotating_angle: Number = (2*(normalAngle - vector_angle) + 180) % 360;
var cos_ang: Number = Math.cos(rotating_angle/DEGREES_OF_1RAD);
var sin_ang: Number = Math.sin(rotating_angle/DEGREES_OF_1RAD);
var final_speedX: Number = speedX * cos_ang - speedY * sin_ang;
var final_speedY: Number = speedX * sin_ang + speedY * cos_ang;
return {x_speed: final_speedX, y_speed: final_speedY};
}
This is how the new speed vector is calculated...
My question is, has anyone faced this kind of problem or has some idea on how to avoid this from happening?
Without seeing your code, this is the best I can provide.
Collision physics should have some velocity threshold that is considered "stopped". That is, once the velocity gets small enough you should explicitly mark an object as stopped and exempt it from your collision code. This will help stabilize slow moving objects. Trial and error is required for a good threshold.
When a collision happens, it is important to at least attempt to correct any inter-penetration. This is most likely the reason why tangent collisions are behaving strangely. Attempt to move the colliding object away from what it hit in a reasonable manner.
Your method of determining the normal should work fine. Game physics is all about cheating (cheating in a way that still looks good). I take it rotation and friction isn't a part of what you're going for?
Try this. You have the contact normal. When you detect a collision, calculate the penetration depth and move your object along the normal so that is isn't penetrating anymore. You can use the two points you have already calculated to get one point of penetration, you'll need to calculate the other though. For circles it's easy (center point + radius in direction of normal). There are more complex ways of going about this but see if the simple method works well for you.
I have read and recommend this book: Game Physics Engine Development
I did something a little like that and got a similar problem.
What I did is that when the pixels from the bouncing object (a ball in your case) overlap with the pixels from the obstacle, you need to move the ball out of the obstacle so that they are not overlapping.
Say the ball is rolling on the obstacle, before your render the ball again you need to move it back by the amount of 'overlap'. If you know at what angle the ball hit the obstable just move it out along that angle.
You also need to add some damping otherwise the ball will never stop. Take a (very) small value, if the ball velocity is bellow that value, set the velocity to 0.
You can try one more thing, which I think is very effective.
You can make functions such as getNextX() and getNextY()(Which of course give their position coordinated after the next update) in your game objects and Check collision on objects based on their next position instead of their current position.
This way, the objects will never overlap, you'll know when they are about collide and apply your after collision physics gracefully!