I am using OpenGL to create the 3D space.
I have a spaceship which can fire lasers.
Up until now I have had it so that the lasers will simply to deeper into the Z-axis once fired.
But I am attempting to make a proper aiming system with crosshairs so that you can aim and shoot in any direction, but I have not been successfull in trying to update the laser's path.
I have a directional vector based off the lasers end tip and start tip, which is gotten from the aiming.
How should I update the laser's X,Y,Z values (or vectors) properly so that it looks natural?
I think I see.
Let's say you start with the aiming direction as a 3D vector, call it "aimDir". Then in your update loop add all 3 (x, y and z) to the projectile "position". (OK, at the speed of light you wouldn't actually see any movement, but I think I see what you're going for here).
void OnUpdate( float deltaT )
{
// "move" the laser in the aiming direction, scaled by the amount of time elapsed
// since our last update (you probably want another scale factor here to control
// how "fast" the laser appears to move)
Vector3 deltaLaser = deltaT * aimDir; // calc 3d offset for this frame
laserEndpoint += deltaLaser; // add it to the end of the laser
}
then in the render routine draw the laser from the firing point to the new endpoint:
void OnRender()
{
glBegin(GL_LINES);
glVertex3f( gunPos.x, gunPos.Y, gunPos.z );
glVertex3f( laserEndPoint.x, laserEndPoint.y, laserEndPoint.z );
glEnd();
}
I'm taking some liberties because I don't know if you're using glut, sdl or what. But I'm sure you have at least an update function and a render function.
Warning, just drawing a line from the gun to the end of the laser might be disappointing visually, but it will be a critical reference for adding better effects (particle systems, bloom filter, etc.). A quick improvement might be to make the front of the laser (line) a bright color and the back black. And/or make multiple lines like a machine gun. Feel free to experiment ;-)
Also, if the source of the laser is directly in front of the viewer you will just see a dot! So you may want to cheat a bit and fire from just below or to the right of the viewer and then have in fire slightly up or in. Especially if you have one one each side (wing?) that appear to converge as in conventional machine guns.
Hope that's helpful.
Related
I am editing the rollingball example map from Unreal (in Unreal Engine). I changed it so my ball you grow and melt (it's a snowball), gaining and losing size and mass.
My problem is the control of it. The example map moves the ball by adding torque. My problem is that my mass changes a lot, so I need a torque the changes depending on the size of my ball (not 1:1 as a bigger snowball should still moves slower).
My problem is that my ball seems to accumulate torque and spins a lot (I added a lot of friction to the ball, it did not helped, it just moved the problem a bit). As an example, if I press left for a while, it's gonna go left. Then if I press right, it goes right. But when I stop pressing right, it spins and goes left again.
This is my current code:
void ASnowballBall::MoveRight(float Val)
{
const FVector Torque = FVector(-1.f * getNewTorque(Val), 0.f, 0.f);
Ball->AddTorque(SpringArm->GetComponentRotation().RotateVector(Torque));
}
void ASnowballBall::MoveForward(float Val)
{
const FVector Torque = FVector(0.f, getNewTorque(Val), 0.f);
Ball->AddTorque(SpringArm->GetComponentRotation().RotateVector(Torque));
}
float ASnowballBall::getNewTorque(float Val)
{
return (Val * RollTorque * (log2(Ball->GetMass()))) / 10000;
}
Note: The log was a test to increase the torque slowly with the mass. It's not working well at all. Right now I am using return Val * RollTorque instead, but it's almost as bad.
The control is horrible and I would like to get an idea on how to fix it. If removing the torque would be better, I will change it. I simply want a responsive control that is fun, and where the player still have a sense of the size of the ball (slower when big compared to small).
PS: My original mass is about 500 kg and can go up to 20 000 kg (it's a puzzle game). I did not set the original mass, it's set by Unreal relative to it's size. I could change the mass scale though.
You could try using AddForce instead of AddTorque.
So the speed of the ball is modified every tick like this:
void APlayerBallBearing::Tick(float deltaSeconds)
{
Super::Tick(deltaSeconds);
BallMesh->AddForce(FVector(InputLongitude, InputLatitude, 0.0f) * ControllerForce * BallMesh->GetMass());
}
InputLongitude and InputLatitude are the values that are put in by the user in the current frame for movement in cardinal directions, they correspond to your MoveForward and MoveRight values I reckon.
The controller force is something you need to tweak in order to find the right value for your ball movement. With a value of at least 600.0f I started getting "decent" behaviour.
I cannot help you with the mass though you would need to try that out yourself, the default mass of the ball mesh I used was ~110.
I want to move a 2d circle in opengl automatically with constant speed on load and then control it with keyboard to move smoothly.
Right now i have the code to move the circle with keyboard, but it is moving only one unit for every keypress.
I want a smooth movement when keypress and automatic movement when on load.
Use glTranslatef to move your object, or alternatively you can just adjust its position x,y,z by a set amount in each update cycle when the keyboard keys are pressed.
E.g
const float MOVE_AMOUNT = 5.0;
public void Update()
{
if (Keyboard.IsKeyDown("a"))
circle.position.x -= MOVE_AMOUNT;
else if (Keyboard.IsKeyDown("d"))
circle.position.y += MOVE_AMOUNT;
}
NOTE: this is not valid C++ syntax, but it gives the overall logic of what you need to be doing, you should be able to figure it out from this. If you want a glTranslate example please let me know.
I'm creating a 3d solar system in OpenGL for a university project and I've come to the point where I have to generate moons. Now generating a moon that orbits a planet is simple enough but I'm trying to create a loop that will generate the amount of moons I tell it too, and at random positions around the planet so the orbit for all of them is different.
for(int count = 0; count < 5; count ++)
{
glPushMatrix();
glEnable(GL_LIGHTING);
glTranslated (rand() % 8+8, 0.0, 0.0); //FIRST
glRotated((GLdouble) spin, 1.0, 70, 0.0);
glutSolidSphere(0.8, 20, 10);
glPopMatrix();
}
This is what I've come up with, however It appears to be creating the moons over and over. It creates the amount I specify but constantly re-creates them. Anyone got any ideas?
You should store the position of you moon when they are created and update this position when they rotate around their planet.
Your code, as it's currently written, will create a random Translate every time it is executed.
So to make it simple, add a process that creates moons, one that updates the moons to rotate around their planet (you probably already have a piece of code that handles rotation around the star?) and then render the updated solar system.
Do an srand(0) before the for-loop so you get the same sequence of random numbers each time.
You should probably create a structure or class like:
struct Moon
{
float x, y, z;
float rotAngle;
};
(Make it as complex as you need it to be)
Create the needed amount of objects (use array/list/...), initialize their values before the render loop.
And in the render loop, loop through all of those objects, update (if you need?) and display using their values.
however It appears to be creating drawing the moons over and over.
FTFY. OpenGL is not a scene graph. You do not generate a scene with it, that's somehow stored internally and presented to the user on demand. OpenGL is a drawing API. If you call drawing code in the animation loop, but always draw with some new random, parameters, things will jump around.
The solution: You need a scene graph. In you case a simple list where you store the initial parameters does suffice. If you want to spice it up, you could also determine the correct orbital velocity for a given distance from the planet of a given mass.
I have got a ball which bounces of walls. This bounce is simple, i just do this, ( code snippet )
if ( x - moveSpeed < 0 ) // Ball hit left wall
xVel *= -1;
However i also got a rectangle which the player moves. The bounce on this practically works as the bounce on walls.
But i figured out that when a ball got similar movement as the picture, its impossible for me to make it go straight up again. I therefore need some kind of calculation regarding the rectangles movement to influence the outcoming angle of the ball. The rectangle always got a constant movement speed when moving. This picture shows a rectangle moving to the left and the ball hitting it during its movement, which results in a 90 degree angle.
( Which shouldn't always be 90 ).
Sorry about my crappy pictures i hope they make sense. My math is rusty thats why i really could need a push in the right direction.
Here is a tutorial on some physics (which is what you need to know) and you need to learn about vectors. The tutorial doesn't go over exactly what you are looking for (the reflection of the bounce and angles) but this is a GREAT start for beginning, because you'll need to know all this to finish your project.Game Physics 101
If you want to do it the easy way, here is code in c++ that describes exactly how to do what your looking for.
Edit
You should actually check out the second link first, its a tutorial on exactly what you need to know. But if you are looking to do more than just make the ball bounce around, say include other moving objects or something like that, check out the first link.
No need for any fancy math here. My understanding of these types of games is that the angle the ball comes off of the paddle is determined by where on the paddle it bounces. If it bounces in the middle, then the current angle is preserved. As it bounces closer to the edge of the paddle, the angle is adjusted in the direction of that side of the paddle. Think of the paddle as a rounded surface.
Going the route of simulating actual physics (as opposed to #Treebranche's answer, which is how I think those sort of games really work) can get very complicated. You can consider friction, spin, duration of contact, etc. Here are a couple links that discuss this.
https://physics.stackexchange.com/questions/11686/finding-angular-velocity-and-regular-velocity-when-bouncing-off-a-surface-with-f
https://physics.stackexchange.com/questions/1142/is-there-a-2d-generalization-of-the-coefficient-of-restitution/
This code demonstrates how to bounce the ball back or in another direction by reversing the ball's X or Y heading with ball.headingX=-ball.headingX and ball.headingY=-ball.headingY .
Putting theory to practice :
/* update ball's x heading */
ball.x+=ball.headingX;
/* update ball's y heading */
ball.y+=ball.headingY;
/* if ball at most right of screen then reverse ball's x heading */
if( (ball.x>PONG_SCREEN_RIGHT) )
{
ball.headingX=-ball.headingX;
}
/* check if ball's location at top or bottom of screen,if true reverse ball's y heading */
if( (ball.y<PONG_SCREEN_TOP) || (ball.y>PONG_SCREEN_BOTTOM-2) )
{
ball.headingY=-ball.headingY;
}
/* check if ball lands on pad, if true bounce back */
if ( (ball.y>= PlayersPad.LEFT) && (ball.y<= PlayersPad.RIGHT) && (ball.x==PlayersPad.x))
{
ball.headingX=-ball.headingX;
playersScore+=10;
}
/* let computer track ball's movement */
if (ball.x>PONG_SCREEN_RIGHT-18) computersPad.y=ball.y;
/* check if ball misses pad, if true display you missed */
if (ball.x<PONG_SCREEN_LEFT)
{
displayYouMissed();
ball.x=ball_Default_X;
ball.y=ball_Default_Y;
}
It seems that this is quite a common question, but I can't find a person with my same circumstances. The closest seems to be: OpenGL: scale then translate? and how?.
The problem I'd really like some help with is to do with moving around while zoomed into (and out of) a 2d scene using OpenGl. The code for zooming out is pretty simple:
void RefMapGLScene::zoomOut(){
currentScale = currentScale-zoomFactor;
double xAdjust = (((get_width())*zoomFactor/2));
double yAdjust = ((get_height()*zoomFactor/2));
zoomTranslateX -= xAdjust;
zoomTranslateY -= yAdjust;
}
The code for zooming in is basically the same (add the zoomFactor to currentScale, and increment zoomTranslateX and Y).
The code for rending everything is also simple:
glPushMatrix();
glTranslated(-zoomTranslateX, -zoomTranslateY, 0);
glScaled(currentScale, currentScale, 1);
glTranslated(totalMovedX, totalMovedY, 0);
graph->draw();
glPopMatrix();
Essentially, zoomTranslate stores an adjustment needed to make the screen move a little towards the middle when zooming. I don't do anything nice like move to where the mouse is pointing, I just move to the middle (ie, to the right and up/down depending on your co-ordinate system). TotalMovedX and Y store the mouse movement as follows:
if (parent->rightButtonDown){
totalMovedX += (-(mousex-curx))/currentScale;
totalMovedY += (-(mousey-cury))/currentScale;
}
Dragging while not zoomed in or out works great. Zooming works great. Dragging while zoomed in/out does not work great :) Essentially, when zoomed in, the canvas moves a lot slower than the mouse. The opposite for when zoomed out.
I've tried everything I can think of, and have read a lot of this site about people with similar issues. I also tried reimplementing my code using glOrtho to handle the zooms, but ended up facing other problems, so came back to this way. Could anybody please suggest how I handle these dragging events?
The order of operations matter. Operations on matrices are applied in the reverse order in which you multiplied the matrices. In your case you apply the canvas movement before the scaling, so your mouse drag is also zoomed.
Change your code to this:
glPushMatrix();
glTranslated(-zoomTranslateX, -zoomTranslateY, 0);
glTranslated(totalMovedX, totalMovedY, 0);
glScaled(currentScale, currentScale, 1);
graph->draw();
glPopMatrix();
Also after changing that order you don't have to scale your mouse moves, so you can omit that division by currentScale
if (parent->rightButtonDown){
totalMovedX += (-(mousex-curx));
totalMovedY += (-(mousey-cury));
}