I am creating a bowling game in openGL C++.
What I have done so far that I have drawn a bowl and three points(obstacles).
The bowl is moved upon key-pressed.
I want to make illusion that when the bowl hits those obstacles, they should be dropped. To do this, I have code like when the X and Y co-ordinates of the ball and of those obstacles are same, then the obstacle's X and Y co-ordinates are incremented to make illusion that they are dropped.
Suggest some logic.
This is my code: -
#include <GL/glut.h>
#include <cmath>
#include <stdio.h>
float posX = 0.01, posY = -0.1, posZ = 0,
bx1 = 0.01, by1 = 0.1,
bx2 = 0.06, by2 = 0.1,
bx3 = 0.10, by3 = 0.1;
GLfloat rotation = 90.0;
double x, y, angle;
#define PI 3.1415926535898
GLint circle_points = 50;
void bottle() {
glColor3f(0.0, 0.0, 1.0);
glPointSize(9.0);
glBegin(GL_POINTS);
glVertex3f(bx1, by1, 0.0);
glEnd();
glBegin(GL_POINTS);
glVertex3f(bx2, by2, 0.0);
glEnd();
glBegin(GL_POINTS);
glVertex3f(bx3, by3, 0.0);
glEnd();
glFlush();
}
void circ() {
glColor3f(0.0, 0.0, 1.0);
glBegin(GL_TRIANGLE_FAN);
for (int i = 0; i <= 300; i++) {
angle = 2 * PI * i / 300;
x = cos(angle) / 20;
y = sin(angle) / 20;
glVertex2d(x, y);
}
glEnd();
}
void display() {
glClearColor(1.0, 1.0, 1.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-1.0, 1.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
bottle();
glPopMatrix();
glPushMatrix();
glTranslatef(posX, posY, posZ);
circ();
glPopMatrix();
glutSwapBuffers();
}
float move_unit = 0.02f;
void keyboardown(int key, int x, int y) {
switch (key) {
case GLUT_KEY_RIGHT:
posX += move_unit;
break;
case GLUT_KEY_LEFT:
posX -= move_unit;
break;
case GLUT_KEY_UP:
posY += move_unit;
break;
case GLUT_KEY_DOWN:
posY -= move_unit;
break;
default:
break;
}
if ( posX == bx1 || posX == bx2 ) {
bx1 -= 0.02,by1 += 0.06;
bx2 = 0.02,
by2 += 0.08;
bx3 = 0.04,
by3 += 0.04;
}
glutPostRedisplay();
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(600, 500);
glutInitWindowPosition(0, 0);
glutCreateWindow("Practice 1");
glutDisplayFunc(display);
glutSpecialFunc(keyboardown);
glutMainLoop();
}
Instead of calling circ() function inside display you could call
glutIdleFunc(nameOfYourChoice);
in your main function after keyboard function. So that function is calling again and again.
In the above function (nameOfYourChoice) you can manipulate any variables you want for x's and y's. So in that function you can check if there was a collision between objects and if appear collisions you can "drop" things, in this example boxes, via x's and y's in that function.
At the end of that function you have to call
glutPostRedisplay();
Now if you want to get those boxes up again you can use timers(also with your time-step) and then after a certain amount of time you can put those boxes up again via x's and y's obviously.For that you also will need bool variables to know if there was a collision.
So collision happens:
bool flagBox1 = true;
time passed:
bool flagBox1 = false;
//code to put back the dropped object
code in (nameOfYourChoice) function:
if(flagBox1){
//proceed to your actions...
}
All those changes you will pass them in your display function as you did for the circ with
glTranslatef(box1posX, box1posY, box1posZ);
glTranslatef(box2posX, box2posY, box2posZ);
glTranslatef(box3posX, box3posY, box3posZ);
Then render them.
A good practice is to change all your "changeable" variables with a step like a time-step.
In that way the hole movement will be depending on that time-step.
First, moving objects in discrete intervals (something like 'posX += move_unit;') just isn't the way animation is done these days. Instead you should measure the time that passed since the last update/frame and move the object according to that. So if you want to move your ball 50 units per second you would write 'posX += 50.0 * passedTime;'. This guarantees that the movement does not get any faster or slower if fps changes.
Second, what you are asking about is rotating a vector. The most general way of doing this is creating a rotation-matrix and multiplying it with the vector, just google rotation-matrix. In your simple case it should be sufficient to calculate the pole's coordinates using sin() and cos(). You also could use the Matrix-Stack of OpenGL, have look into glRotate(), glPushMatrix() etc.
Third, your question is very general, and the code snippet cant be called snippet anymore. Keep your questions precise and the snippets short.
Related
I have program in which the object (a triangle) follows the mouse as it moves around and rotates to the direction its moving. What do I have to do to make it so the object stays still, until I click it, drag it to a position and once I release the mouse, it starts to move to that position?
#include <GL/glut.h>
#include <math.h>
# define ANIMATION_STEP (1000/300)
# define PI 3.1415926535897932
struct Globals {
centre_x, centre_y, rotate;
float length;
float mouse_x, mouse_y, speed;
int animating;
} globals;
void init(void){
// Starting position of the triangle
globals.centre_x = 100;
globals.centre_y = 100;
globals.rotate = 0.0;
globals.mouse_x = 300.0;
globals.mouse_y = 300.0;
// Animation speed in pixels per second
globals.speed = 300.0;
// size of the triangle
globals.length = 27;
globals.animating = 1;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, 1000.0, 0.0, 700.0);
}
void triangle(void){
glBegin(GL_POLYGON);
glVertex2f(0.5, 0.0);
glVertex2f(-0.5, -0.5);
glVertex2f(-0.5, 0.5);
glEnd();
}
void display(void){
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(globals.mouse_x, globals.mouse_y, 0.0);
glRotatef(globals.rotate, 0.0, 0.0, 1.0);
glScalef(globals.length, globals.length, 1.0);
triangle();
glFlush();
glutSwapBuffers();
}
float limit(float x, float min, float max){
if (x < min) {
x = min;
}
if (x > max) {
x = max;
}
return x;
}
void timer(int v){
// Computing elapsed time for smooth animation.
int time = glutGet(GLUT_ELAPSED_TIME);
float angle;
glutTimerFunc(ANIMATION_STEP, timer, time);
if (globals.animating) {
int delta_t = time - v;
float delta_x, delta_y, length, step_size;
// Compute vector from current location to mouse
delta_x = globals.mouse_x - globals.centre_x;
delta_y = globals.mouse_y - globals.centre_y;
// Compute length of the vector
length = sqrt (delta_x*delta_x + delta_y*delta_y);
// If the triangle is close to the mouse, then no motion is required.
step_size = globals.speed * delta_t / 1000.0;
if (length > step_size * 0.55) {
delta_x = delta_x / length;
delta_y = delta_y / length;
globals.centre_x += delta_x * step_size;
globals.centre_y += delta_y * step_size;
angle = atan2(delta_y, delta_x);
globals.rotate = angle * 180.0 / PI;
// Keep the triangle inside the world window.
globals.centre_x = limit(globals.centre_x, 0.0 + globals.length/2, 1000.0 - globals.length/2);
globals.centre_y = limit(globals.centre_y, 0.0 + globals.length/2, 700.0 - globals.length/2);
}
glutPostRedisplay();
}
}
void mousemotion(int x, int yc){
globals.mouse_x = x;
globals.mouse_y = 700 - yc;
glutPostRedisplay();
}
main(int argc, char** argv){
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(1000, 700);
glutInitWindowPosition(10, 10);
glutDisplayFunc(display);
glutTimerFunc(ANIMATION_STEP, timer, 0);
glutPassiveMotionFunc(mousemotion);
init();
glutMainLoop();
return 0;
}
I have investigated processMouse() where if state == GLUT_DOWN then it records the current position and mouse press cordinates, but the best ive been able to get is that it immediately teleports to the mouse click. Can someone please explain what I would need to do to click on it, drag, release, then move to position?
in opengl, how to change mouse...
You don't. Mouse does not exist in OpenGL. Maybe you should change the question to "How to process mouse events in windows/GLUT/SDL/whatever-framework?" for which there are dozens of duplicates.
I am working on an nbody simulator and I want to display it with OpenGL. I want to always be looking at the centre of mass reference frame. I have the following code. I calculate the COM and I set the center coordinate in the gluLookAt function to be the center of mass. I then subtract the "zoom" from the z coordinate to get the eye position. By logic this should ensure that I am always looking at whatever value the center of mass is. The only issue is that I marked where the center of mass should be on the screen with a red dot and it is moving. Shouldn't it never move if I am always looking at it from the same relative position? Here is my code. Focus on the display function since I assume that is where the error will be. I had similar code working in another project and I can't really find any differences.
#include "Universe.cuh"
#include <iostream>
#include <cstdlib>
#include <ctime>
#include "timer.hpp"
#include <GL/glut.h>
Universe u;
float* vbuf;
double angle = 0.0, zoom = 1000;
void display()
{
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
float3 c = u.getCenterOfMass();
gluLookAt(c.x, c.y, c.z - zoom, c.x, c.y, c.z, 0, 1, 0);
glScalef(0.1, 0.1, 0.1);
glRotated(angle, 1, 0, 0);
glColor4f(1, 1, 1, 0.25);
glBegin(GL_POINTS);
{
glColor3f(1.0, 0.0, 0.0);
glVertex3d(c.x, c.y, c.z);
}
glEnd();
glutSwapBuffers();
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, (double)w / (double)h, 1.0, zoom * 1e9);
glMatrixMode(GL_MODELVIEW);
}
void copy_to_vbuf()
{
for(int i = 0; i < u.size(); i++)
{
vbuf[3 * i + 0] = u.getObjects()[i].p.x;
vbuf[3 * i + 1] = u.getObjects()[i].p.y;
vbuf[3 * i + 2] = u.getObjects()[i].p.z;
}
}
void keyboard(unsigned char c, int x, int y)
{
if(c == 'w')
angle += 1;
else if(c == 's')
angle -= 1;
else if(c == '=')
zoom /= 1.2;
else if(c == '-')
zoom *= 1.2;
glutPostRedisplay();
}
void idle()
{
u.timeStep();
copy_to_vbuf();
glutPostRedisplay();
}
int main(int argc, char** argv)
{
cudaSetDevice(0);
srand(time(0));
u.getConfiguration().max_velocity = 10;
u.getConfiguration().softening_factor = 0.01;
u.getConfiguration().threshold_angle = 35;
u.getConfiguration().time_step = 0.1;
const int N = 5;
vbuf = new float[3 * N];
for(int i = 0; i < N; i++)
{
Object o;
o.m = rand() % 100 + 1;
o.p.x = 500.0 * rand() / RAND_MAX - 250.0;
o.p.y = 500.0 * rand() / RAND_MAX - 250.0;
o.p.z = 500.0 * rand() / RAND_MAX - 250.0;
u.addObject(o);
}
copy_to_vbuf();
glutInit(&argc, argv);
glutInitDisplayMode(GL_DOUBLE);
glutInitWindowSize(1000, 1000);
glutCreateWindow("N-Body");
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutIdleFunc(idle);
glutKeyboardFunc(keyboard);
glEnable(GL_POINT_SMOOTH);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glPointSize(1.0);
glutMainLoop();
return 0;
}
Two points regarding:
glScalef(0.1, 0.1, 0.1);
glRotated(angle, 1, 0, 0);
Since your axis is not centered on the 'COM', when you apply rotation the COM point will not stay in place and logically would move around the screen.
AFIK the normal order is scale,rotate,translate for transformations. This will apply the rotation and then scale.
EDIT:
To expand on that: Currently you take an arbitrary point rotate it, scale it and then focus on the point where it used to be. If you want to rotate your model (e.g. point marking the 'COM') around itself, it needs to be centered at (0,0,0).
I am working on an assignment to draw wire frame GLUT standard objects. This seems simple but we are told we cannot use gluAtLook(), glOrtho(), glFrustrum but we must use glTranslate(), glScale() and glRotate. How to you project the object without using these functions in glMatrixMode(GL_PROJECTION)?
This is what I have so far:
#include "stdafx.h"
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <math.h> // for sqrt()
#include <glut.h>
void init(void)
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_FLAT);
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 1.0, 1.0);
glLoadIdentity(); /* clear the matrix */
/* viewing transformation */
glTranslatef(0.0, 0.0, -5.0);
glScalef(1.0, 2.0, 1.0); /* modeling transformation */
glutWireCube(1.0);
glFlush();
}
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0);
//glTranslatef(0.0, 0.0, -5.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow(argv[0]);
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
Can someone please help with this?
we are told we cannot use gluAtLook(), glOrtho(), glFrustrum but we must use glTranslate(), glScale() and glRotate
gluLookAt sets up the world to view space transformation, glOrtho does view to orthographic projection space transformation and glFrustum does view to perspective projection space transformation. When you say your tutor hasn't allowed to use it, it clearly means that the intention is to understand how these functions work in the first place.
There're many resources on the internet which teach you that. Here's one by a renowned UC Berkeley professor Dr. Ravi Ramamoorthi. SongHo has good articles which will help you do the same thing.
I can demonstrate a simple case in 2D. Say we've a world defined with objects (for simplicity we take a point P); we want the camera to be at (3, 3) with its X and Y axes pointing in directions opposite to world's X and Y axes. For simplicity we'll assume both frames have the same scaling factor i.e. 1 unit in both X and Y directions measure the same distance (magnitude) for both systems. So the two frames differ only by orientation and origin location (W0 and V0 are the symbols denoting them).
We need to derive Mworld->view i.e. the matrix which maps points in world space to view space. This is what the now-deprecated gluLookAt function calculates and multiplies with GL_MODELVIEW matrix stack. This matrix will be used to get a view of the world from the camera's viewpoint.
We know that Mworld->view = Tview->world. The matrix which maps points of frame A to frame B will also be the matrix which transforms B's frame into A's frame. The derivation goes like this
The point P in world has (1, 2) = Pw as coordinates, we're effectively finding a matrix, which when multiplied with Pw will give Pv i.e. the same point's coordinates in view frame. The point is written as a 3D point since homogeneous extension of a 2D point would be a 3D point; the homogeneous coordinate would be 1 since it's a point; had it been a vector, it'd be 0.
Step one is rotation; rotating view's frame by -180° (right-handed system where +ve rotation is counter-clockwise); now the axes are along the same direction for both frames. We've to tackle the origin difference, this is done by translation, which is step 2. Multiplying both will give the required matrix. Note that each step transforms the view's frame more closer into world's frame by post-multiplying. Also each transformation is based on that current local frame we're in and not based on the starting global (world) frame.
The same idea can be extended to 3D too, with some more effort. In the above derivation all I needed were just rotation matrix, translation matrix and matrix multiplication; no gluLookat.The links I gave you should help in calculating the same for 3D. The projection matrix derivation is a bit more involved. However, you can still achieve the result without using glOrtho; the links I gave above has the formula for the final matrix; you can compose a matrix using that and multiply that to the GL_PROJECTION matrix stack.
Note: The above derivation assumes column vectors and thus transformation matrices (like rotation) and multiplication order are done based on that. If you assume row vector convention then transpose all the matrices and reverse the order of multplication since
(AB)^T = B^T A^T
What you need to do is compute your own projection matrix and model-view matrix. After that you can load them using glLoadMatrix right after you call glLoadIdentity.
#include "stdafx.h"
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <math.h> // for sqrt()
#include <glut.h>
static GLfloat Xvalue = 0.0f;
static GLfloat Yvalue = 0.0f;
static GLfloat xRot = 0.0f;
static GLfloat yRot = 0.0f;
static GLfloat zRot = 0.0f;
static GLfloat xScale = 1.0f;
static GLfloat yScale = 1.0f;
static GLfloat zScale = 1.0f;
void init(void)
{
glClearColor(1.0, 1.0, 1.0, 1.0);
glShadeModel(GL_FLAT);
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0, 0.0, 0.0);
glLoadIdentity(); //clear the matrix
glTranslatef(Xvalue, Yvalue, -3.0); // viewing transformation
glScalef(xScale, yScale, zScale); // modeling transformation
glRotatef(xRot, 1.0f, 0.0f, 0.0f);
glRotatef(yRot, 0.0f, 1.0f, 0.0f);
glRotatef(zRot, 0.0f, 0.0f, 1.0f);
glutWireCube(1.0);
glFlush();
}
void reshape(int w, int h)
{
GLfloat identity[16] = { 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 };
if (h == 0) // don't want a divide by zero
{
h = 1;
}
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(identity);
GLfloat fovy = 52.0f; // in degrees
GLfloat c = 1.0 / (GLfloat)tan(fovy / 4.0), a = (GLfloat)w / (GLfloat)h, n = 1.0f, f = 1000.0f;
GLfloat projection[16] = { c / a, 0.0, 0.0, 0.0,
0.0, c, 0.0, 0.0,
0.0, 0.0, -(f + n) / (f - n), -1.0,
0.0, 0.0, -2.0*f*n / (f - n), 0.0 };
glMultMatrixf(projection);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void keyInput(unsigned char key, int x, int y)
{ // Keyboard input processing routine.
switch (key)
{
case 'b': // move left
Xvalue -= 0.1;
glutPostRedisplay();
break;
case 'B': // move right
Xvalue += 0.1;
glutPostRedisplay();
break;
case 'c': // move down
Yvalue -= 0.1;
glutPostRedisplay();
break;
case 'C': // move up
Yvalue += 0.1;
glutPostRedisplay();
break;
case 'e': // scale down
zScale -= 0.1;
xScale -= 0.1;
yScale -= 0.1;
glutPostRedisplay();
break;
case 'E': // scale up
zScale += 0.1;
xScale += 0.1;
yScale += 0.1;
glutPostRedisplay();
break;
case 'f': // rotate x axis CW
xRot -= 5.0f;
glutPostRedisplay();
break;
case 'F': // rotate x axis CCW
xRot += 5.0f;
glutPostRedisplay();
break;
case 'g': // rotate y axis CW
yRot -= 5.0f;
glutPostRedisplay();
break;
case 'G': // rotate y axis CCW
yRot += 5.0f;
glutPostRedisplay();
break;
case 'h': // rotate z axis CW
zRot -= 5.0f;
glutPostRedisplay();
break;
case 'H': // rotate z axis CCW
zRot += 5.0f;
glutPostRedisplay();
break;
}
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow(argv[0]);
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyInput);
glutMainLoop();
return 0;
}
I am currently trying to create a 2D side scroller and i currently have my "world" drawing (a large white box for the time being), but i cannot figure out any relationship between the edge of the world map and the edge of the viewport to ensure that the viewport is always fully covered by the map.
My basic world drawing code is:
void drawTiles(void)
{
for (int i = 0; i < 50; i++)
{
for (int j = 0; j < 500; j++)
{
glPushMatrix();
glTranslatef(j, -i, 0);
glBegin (GL_QUADS);
glTexCoord2d(0.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glTexCoord2d(1.0, 0.0);
glVertex3f(1.0, 0.0, 0.0);
glTexCoord2d(1.0, 1.0);
glVertex3f(1.0, 1.0, 0.0);
glTexCoord2d(0.0, 1.0);
glVertex3f(0.0, 1.0, 0.0);
glEnd();
glPopMatrix();
}
}
}
void display(void)
{
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
glPushMatrix();
glTranslatef(camX, camY, -20); //translate back a bit to view the map correctly (our camera)
drawTiles(); //draw our tiles
glPopMatrix();
glutSwapBuffers();
}
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, (GLfloat)w / (GLfloat)h, 1.0, 100.0);
glMatrixMode(GL_MODELVIEW);
}
void keyboard(unsigned char key, int x, int y)
{
switch(key)
{
case 'w':
camY -= 0.25;
break;
case 's':
camY += 0.25;
break;
case 'a':
camX += 0.25;
break;
case 'd':
camX -= 0.25;
break;
}
}
How would i go about ensuring that when I use WASD and on viewport resize, that i do not translate beyond the bounds of the map (currently 500x50 tiles)?
If you have a planar scene (2D only), it should be sufficient to use an orthographic projection transformation. The projection transformation determines the camera's parameters. In the current state (with the perspective projection) you have a usual pin hole camera with a vertical opening angle of 60°.
An orthographic projection is defined by its edges. Let's say you want your camera to "see" two units to the left, 3 units to the right, 1 unit up and 4 units down. This would be possible, although it might not be reasonable in your case.
The current perspective camera "sees" about 11.5 units up and down. The according width can be calculated from the window dimensions (we do not want to stretch the image). So instead of gluPerspective, use the following:
float halfHeight = 11.5f;
float halfWidth = halfHeight * (GLfloat)w / (GLfloat)h; //based on window aspect ratio
glOrtho(-halfWidth, halfWidth, halfHeight, -halfHeight, -1, 1);
If you want to change the visible area, you just need to adjust the halfHeight. The -1 and 1 are the znear and zfar plane. Everything that is between these planes is visible. Everything else will be cut off. But since you have only 2D content, this should not be relevant.
In your call to glTranslatef(camX, camY, -20);, set the z-coordinate to 0. This is not needed any more, because we have an orthographic view.
Now if you want to check if the map is still visible, do the following. I'll just show the exmple of checking the left/right boundary. The vertical case is similar:
//The camera can see from camX-halfWidth to camX+halfWidth
//You might want to make halfWidth and halfHeight class variables
float leftMapBoundary = 0;
float rightMapBoundary = 500;
//the camera must be
// * at least halfWidth right of the left boundary and
// * at least halfWidth left of the right one:
if(camX < leftMapBoundary + halfWidth)
camX = leftMapBoundary + halfWidth;
if(camX > rightMapBoundary - halfWidth)
camX = rightMapBoundary - halfWidth;
Add the code after the switch in your keyboard function or whenever you move the camera.
I have to make a bowling game in openGL. This is the code I have so far. What it does that it draws a ball and is moved accordingly when an arrow key is pressed.
So far, I have that ball moving, that is fine. What I want to do that other point I have created, that should not be moved. Because, when that ball reaches to that point, it should be drop or something I will make that obstacle is dropped.
The code is written in Eclipse IDE.
#include <stdio.h>
#include <GL/glut.h>
#include <math.h>
#include <stdio.h> /* printf, scanf, puts, NULL */
float posX = 0, posY = -0.1, posZ = 0;
GLfloat rotation = 90.0;
double x, y, angle;
#define PI 3.1415926535898
GLint circle_points = 50;
void reshape(int width, int heigth) {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//clip the windows so its shortest side is 2.0
if (width < heigth) {
glOrtho(-2.0, 2.0, -2.0 * (GLfloat) heigth / (GLfloat) width,
2.0 * (GLfloat) heigth / (GLfloat) width, 2.0, 2.0);
} else {
glOrtho(-2.0, 2.0, -2.0 * (GLfloat) width / (GLfloat) heigth,
2.0 * (GLfloat) width / (GLfloat) heigth, 2.0, 2.0);
}
// set viewport to use the entire new window
glViewport(0, 0, width, heigth);
}
void circ() {
glColor3f(0.0, 0.0, 1.0);
glPointSize(11.0);
glBegin(GL_POINTS);
glVertex3f(0.1, 0.1, 0.0);
glEnd();
glBegin(GL_TRIANGLE_FAN);
for (int i = 0; i <= 300; i++) {
angle = 2 * PI * i / 300;
x = cos(angle) / 20;
y = sin(angle) / 20;
glVertex2d(x, y);
}
glEnd();
}
void display() {
//Clear Window
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
glTranslatef(posX, posY, posZ);
circ();
glPopMatrix();
glFlush();
}
void init() {
// set clear color to black
glClearColor(1.0, 1.0, 1.0, 0.0);
// set fill color to white
glColor3f(1.0, 1.0, 1.0);
//This is the default view and these statements could be removed
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-1.0, 1.0, -1.0, 1.0);
}
float move_unit = 0.02f;
void keyboardown(int key, int x, int y) {
switch (key) {
case GLUT_KEY_RIGHT:
posX += move_unit;
break;
case GLUT_KEY_LEFT:
posX -= move_unit;
break;
case GLUT_KEY_UP:
posY += move_unit;
break;
case GLUT_KEY_DOWN:
posY -= move_unit;
break;
default:
break;
}
glutPostRedisplay();
}
int main(int argc, char** argv) {
//initialize mode and open a windows in upper left corner of screen
//Windows tittle is name of program
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(600, 500);
glutInitWindowPosition(0, 0);
glutCreateWindow("Practice 1");
glutDisplayFunc(display);
init();
glutSpecialFunc(keyboardown);
glutMainLoop();
}
Modern graphics APIs simulating finite state machine. That means that before Draw calls you must fully configure (or leave default) graphics pipeline "machine":
SetStates(); // Configure pipeline state: set geometry, textures, matrices, etc.
Begin();
Draw(); // Render frame according to current pipeline configuration (state)
End(); // Swap screen buffers
In case of many objects, you can just wrap all stuff with for loop:
for( each_object )
{
SetStates(); // current object's vertex/index buffer, texture, matrices, etc.
Begin();
Draw();
End();
}
Not very efficient. Next step of improvement might include: frustum culling, instancing, vertex buffers merging, texture atlases, draw calls sorting, etc.
BTW, consider using Vertex Buffer Objects (VBOs), instead of Begin/glVertex2d/End which is deprecated
Try this:
#include <GL/glut.h>
#include <cmath>
float posX = 0, posY = -0.1, posZ = 0;
GLfloat rotation = 90.0;
double x, y, angle;
#define PI 3.1415926535898
GLint circle_points = 50;
void point()
{
glColor3f(0.0, 0.0, 1.0);
glPointSize(11.0);
glBegin(GL_POINTS);
glVertex3f(0.1, 0.1, 0.0);
glEnd();
}
void circ()
{
glColor3f(0.0, 0.0, 1.0);
glBegin(GL_TRIANGLE_FAN);
for (int i = 0; i <= 300; i++)
{
angle = 2 * PI * i / 300;
x = cos(angle) / 20;
y = sin(angle) / 20;
glVertex2d(x, y);
}
glEnd();
}
void display()
{
glClearColor(1.0, 1.0, 1.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-1.0, 1.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
point();
glPopMatrix();
glPushMatrix();
glTranslatef(posX, posY, posZ);
circ();
glPopMatrix();
glutSwapBuffers();
}
float move_unit = 0.02f;
void keyboardown(int key, int x, int y)
{
switch (key)
{
case GLUT_KEY_RIGHT:
posX += move_unit;
break;
case GLUT_KEY_LEFT:
posX -= move_unit;
break;
case GLUT_KEY_UP:
posY += move_unit;
break;
case GLUT_KEY_DOWN:
posY -= move_unit;
break;
default:
break;
}
glutPostRedisplay();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(600, 500);
glutInitWindowPosition(0, 0);
glutCreateWindow("Practice 1");
glutDisplayFunc(display);
glutSpecialFunc(keyboardown);
glutMainLoop();
}