accessing element 0 in string array makes it crash - c++

I am declaring the following array
string names[4] = { "grass" , "smallGrassBlock" , "dirt" , "sand" };
and then
extern string names [];`
However it crashes when I do this:
string ss=names[0];
All relevent code:
Main:
#include<stdlib.h>
#include<windows.h>
#include<GL/glut.h>
#include<GL/freeglut.h>
#include<iostream>
#include <vector>
#include "include/Block.h"
#include <string>
extern string names [];
void initTextures();
GLint GetTexture(string file);
void IdleFunction();
void removeBlock(int x,int y);
int xOffset,yOffset = 0;
using namespace std;
string to_string(int number);
void placeBlock(int x,int y);
void drawBitmapText(char *string, float x, float y, float z);
void reshape(int w, int h);
void render(void);
void keyboard(unsigned char c,int x,int y);
void mouse(int button,int state, int x, int y);
void arrows(int key, int x, int y );
std::vector <Block> blockList;
GLuint textures[1];
int screenXSize=800;
int screenYSize=800;
int selectedBlockType = 1;
int main(int argc, char ** argv){
blockList.push_back(Block(0,-111,-111));
string s = blockList.at(0).getName();
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100,100);
glutInitWindowSize(screenXSize,screenYSize);
glutCreateWindow("TITLE");
glutDisplayFunc(render);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutIdleFunc(IdleFunction);
glutSpecialFunc(arrows);
glutMouseFunc(mouse);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
initTextures();
glutMainLoop();
}
void initTextures(){
for(int i =0; i<=2; i++){
string file = "C:/Users/Samuel/Documents/Documents/projects/test/MapCreator/"+names[i]+".png";
textures[i]=GetTexture(file);
}
}
GLint GetTexture(std::string Filename)
{
GLuint tex_ID;
tex_ID = SOIL_load_OGL_texture(
Filename.c_str(),
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
SOIL_FLAG_POWER_OF_TWO
| SOIL_FLAG_MIPMAPS
| SOIL_FLAG_MULTIPLY_ALPHA
| SOIL_FLAG_COMPRESS_TO_DXT
| SOIL_FLAG_DDS_LOAD_DIRECT
| SOIL_FLAG_INVERT_Y
);
if( tex_ID > 0 )
{
glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D, tex_ID );
return tex_ID;
}
else{
cout<<"Texture failed to load";
return 0;
}}
void arrows(int key, int x, int y ){
if(key==101){
selectedBlockType++;
if(selectedBlockType > blockList.at(0).getTotal()){
selectedBlockType=1;
}
}
if(key==103){
selectedBlockType--;
if(selectedBlockType < 0){
selectedBlockType=blockList.at(0).getTotal();
}
}
}
void IdleFunction()
{
glutPostRedisplay();
}
void mouse(int button,int state, int x, int y){
y+=15;
x-=15;
if(button==GLUT_RIGHT_BUTTON){
removeBlock(x,y);
}
if(button==GLUT_LEFT_BUTTON){
placeBlock(x,y);
}
}
void keyboard(unsigned char c,int x,int y){
//wasd
if(c==119){
yOffset+=30;
}
if(c==97){
xOffset-=30;
}
if(c==115){
yOffset-=30;
}
if(c==100){
xOffset+=30;
}
if (c==27){
exit(0);
}
}
void removeBlock(int x, int y){
y-= yOffset;
x+=xOffset;
y-=400;
y*=-1;
y+=400;
int xmod = x%30;
x-=xmod;
if(xmod>=15){
x+=30;
}
int ymod = y%30;
y-=ymod;
if(ymod>=15){
y+=30;
}
for(int i = 0; i<blockList.size();i++){
if(blockList.at(i).getX()==x){
if(blockList.at(i).getY()==y){
blockList.erase(blockList.begin()+i);
}
}
}
}
void placeBlock(int x, int y){
y-= yOffset;
x+=xOffset;
y-=400;
y*=-1;
y+=400;
//gets it on the grid lines
int xmod = x%30;
x-=xmod;
if(xmod>=15){
x+=30;
}
int ymod = y%30;
y-=ymod;
if(ymod>=15){
y+=30;
}
bool there=false;
for(int i = 0; i<blockList.size();i++){
if(blockList.at(i).getXMin()<=x&&blockList.at(i).getXMax()>=x&&blockList.at(i).getYMin()<=y&&blockList.at(i).getYMax()>=y){
there=true;
cout<<"cannot place there!"<<endl;
}
}
if(!there){
blockList.push_back(Block(selectedBlockType, x, y));
}
}
void reshape(int w, int h)
{
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluOrtho2D (0, (GLdouble) 800, 0, (GLdouble) 800);
glutReshapeWindow(screenXSize,screenYSize);
}
void drawBitmapText(char *string, float x, float y, float z)
{
char *c;
glRasterPos3f(x, y, z);
for (c=string; *c != '\0'; c++)
{
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, *c);
}
}
void render(void){
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
for(int i = 0; i<blockList.size();i++){
blockList.at(i).render(xOffset,yOffset,textures[blockList.at(i).getType()]);
}
glColor3f(0,0,0);
//This creates the grid
//Should be broken every 30
for(float f = 0;f<800; f+=30){
glBegin(GL_LINE_STRIP);
glVertex2f(f,0);
glVertex2f(f,800);
glEnd();
glBegin(GL_LINE_STRIP);
glVertex2f(0,f);
glVertex2f(800,f);
glEnd();
}
glColor3f(0.35,0.35,0.35);
string s = to_string(selectedBlockType);
string ss=names[0];
cout<<"YAY"<<endl;
cout<<ss;
cout<<endl<<"Selected"<<selectedBlockType;
s=s+" "+names[selectedBlockType];
cout<<"YAY"<<endl;
char *c = (char*)s.c_str();
drawBitmapText(c,5,760,0);
glutSwapBuffers();
glFlush();
}
string to_string(int number){
string number_string = "";
char ones_char;
int ones = 0;
while(true){
ones = number % 10;
switch(ones){
case 0: ones_char = '0'; break;
case 1: ones_char = '1'; break;
case 2: ones_char = '2'; break;
case 3: ones_char = '3'; break;
case 4: ones_char = '4'; break;
case 5: ones_char = '5'; break;
case 6: ones_char = '6'; break;
case 7: ones_char = '7'; break;
case 8: ones_char = '8'; break;
case 9: ones_char = '9'; break;
}
number -= ones;
number_string = ones_char + number_string;
if(number == 0){
break;
}
number = number/10;
}
return number_string;
}
Block header:
#ifndef BLOCK_H
#define BLOCK_H
#include <string>
#include <iostream>
#include<GL/freeglut.h>
#include <soil.h>
using namespace std;
class Block
{
public:
int getXMax();
int getXMin();
int getYMin();
int getYMax();
Block(int,int,int);
int getX();
int getY();
static int getTotal();
int getType();
void render(int,int,GLuint);
string getName();
string getNType(int i);
virtual ~Block();
protected:
private:
int x,xsize,ysize,y,Type,size;
};
#endif // BLOCK_H
Block:
#include "../include/Block.h"
#include <string>
#include <iostream>
#include<GL/freeglut.h>
#include <soil.h>
using namespace std;
string names[4] = { "grass" , "smallGrassBlock" , "dirt" , "sand" };
Block::Block(int type, int X,int Y)
{
size=3;
Type=type;
x=X;
y=Y;
switch(Type){
case 0:
xsize=546;
ysize=217;
break;
case 1:
xsize = 200;
ysize=95;
break;
default:
xsize=30;
ysize=30;
break;
}
}
int Block:: getTotal(){
return 3;
}
int Block::getX(){
return x;
}
int Block::getY(){
return y;
}
int Block::getXMin(){
return x-(xsize/2);
}
int Block::getYMin(){
return y-(ysize/2);
}
int Block::getXMax(){
return x+(xsize/2);
}
int Block::getYMax(){
return y+(ysize/2);
}
int Block::getType(){
return Type;
}
string Block::getName(){
return names[Type];;
}
string Block::getNType(int i){
return names[i];
}
void Block:: render(int xOffset,int yOffset,GLuint texture){
if(texture==0){
}
x-=xOffset;
y-=yOffset;
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable( GL_BLEND );
glClearColor(0.0,0.0,0.0,0.0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture);
glBegin(GL_POLYGON);
glTexCoord2f(1,1); glVertex2f(x+(xsize/2), y+(ysize/2));
glTexCoord2f(1,0); glVertex2f(x+(xsize/2), y-(ysize/2));
glTexCoord2f(0,0); glVertex2f(x-(xsize/2), y-(ysize/2));
glTexCoord2f(0,1); glVertex2f(x-(xsize/2), y+(ysize/2));
glEnd();
glDisable(GL_TEXTURE_2D);
glDisable( GL_BLEND );
glClearColor(1.0,1.0,1.0,0.0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glPopAttrib();
x+=xOffset;
y+=yOffset;
}
Block::~Block()
{
//dtor
}
Further information:
The program does not crash when getting any valid element other than 0, nor does it provide an error message.

It is not clear how you implemented your program. The following is the test case that I wrote. It ran fine without any problem using Microsoft C++ compiler (cl.exe).
Test.cpp
#include <iostream>
#include <string>
using namespace std;
extern string names[];
int main()
{
cout << names[0] << endl;
return 0;
}
Test2.cpp
#include <string>
using namespace std;
string names[4] = { "grass" , "smallGrassBlock" , "dirt" , "sand" };
Compile command:
cl.exe test.cpp test2.cpp

If your code is like this, then this works fine
main.cpp
extern string names[];
int main() {
string ss = names[3];
cout << ss << endl;
cin.get();
}
string.cpp
#include <string>
using namespace std;
string names[4] = { "grass" , "smallGrassBlock" , "dirt" , "sand" };
Note: Keep both the files in the same project.
OR compile both the .cpp files together
gcc main.cpp other.cpp

Related

C++ Compiler throwing error with GLUT

The code was working fine but after I added the void projection(float), it's giving me unqaulified-id error inside the projection function. I'm using CodeBlocks IDE, MinGW. Please help me.
This is the error I'm getting:
||=== Build: Debug in L3 (compiler: GNU GCC Compiler) ===|
C:\Users\sos\Documents\Code Blocks c++\L3\src\CallbackFunctions.cpp||In function 'void projection(float)':|
C:\Users\sos\Documents\Code Blocks c++\L3\src\CallbackFunctions.cpp|56|error: expected unqualified-id before '=' token|
C:\Users\sos\Documents\Code Blocks c++\L3\src\CallbackFunctions.cpp|57|error: expected primary-expression before ',' token|
C:\Users\sos\Documents\Code Blocks c++\L3\src\CallbackFunctions.cpp| 57|error: expected primary-expression before ')' token|
C:\Users\sos\Documents\Code Blocks c++\L3\src\CallbackFunctions.cpp||In function 'void specialKeyboard(int, int, int)':|
||=== Build failed: 3 error(s), 15 warning(s) (0 minute(s), 0 second(s)) ===|
Moreover, if I comment everything inside projection, I get this error:
obj\Debug\src\Display.o||In function `glutInit_ATEXIT_HACK':|
C:\Program Files\CodeBlocks\MinGW\include\GL\freeglut_std.h|623|multiple definition of `keyboardKey'|
C:\Program Files\CodeBlocks\MinGW\include\GL\freeglut_std.h|623|multiple definition of `mouseX'|
C:\Program Files\CodeBlocks\MinGW\include\GL\freeglut_std.h|623|multiple definition of `mouseY'|
C:\Program Files\CodeBlocks\MinGW\include\GL\freeglut_std.h|623|multiple definition of `toggleProjection'|
CallbackFunctions.h
#ifndef CALLBACKFUNCTIONS_H
#define CALLBACKFUNCTIONS_H
#include "GL/freeglut.h"
unsigned char keyboardKey;
char *specialKeyboardKey ="";
char *modifier="";
char *mouseButtonPressed="";
char *mouseState="";
int mouseX, mouseY;
int toggleProjection=0;
char *view="";
/* Hardware Interrupts callback functions */
void display(); //called every single frame
void reshape(int width, int height); //called whenever the dimensions of the window are changed
void idle(); //when there is no interaction with the window
void keyboard(unsigned char key, int x, int y); //whenever a keyboard key is pressed/interrupt occurs
void specialKeyboard(int button, int x, int y); //captures special keys like: SHIFT ALT CTRL F1.....
void mouse(int button, int state, int x, int y); //captures the mouse clicks and their state
void mouseMotion(int x, int y); //captures the motion of the mouse pointer in the window
void projection(float asp);
#endif // CALLBACKFUNCTIONS_H
CallbackFunctions.cpp
#include "../include/CallbackFunctions.h"
#include "../include/Text.h"
extern int dim;
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
//Drawing stuff
glFlush();
glutSwapBuffers();
}
void idle()
{
display();
}
/* This callback function is called whenever the window is resized or reshaped */
void reshape(int width, int height)
{
//Width To Height Ratio
float w2h = (height>0)? (float)width/height : 1;
glViewport(0, 0, width, height);
projection(w2h);
}
void projection(float asp)
{
//Setting up the Viewing Matrix
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if(toggleProjection==0)
{
glOrtho(-dim*asp, +dim*asp, -dim, +dim, -dim, +dim);
}
else
{
float fov = 55.0, near = asp/5, far = asp*5;
gluPerspective(fov, asp, near, far);
//To do
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
/* This callback function is called when there is no activity in the window */
void keyboard(unsigned char key, int x, int y)
{
switch(key)
{
case 27:
exit(0);
break;
}
keyboardKey = key;
glutPostRedisplay();
}
/* This callback function is called whenever a keyboard interrupt is encountered */
void specialKeyboard(int key, int state, int a)
{
int currentModifier = glutGetModifiers();
switch(currentModifier)
{
case GLUT_ACTIVE_SHIFT:
modifier = "SHIFT";
break;
case GLUT_ACTIVE_CTRL:
modifier = "CTRL";
break;
case GLUT_ACTIVE_ALT:
modifier = "ALT";
break;
}
switch(key)
{
case GLUT_KEY_F1:
if(toggleProjection=0)
{
toggleProjection = 1;
view = "perspective";
break;
}
else
{
toggleProjection = 0;
view = "orthographic";
break;
}
}
glutPostRedisplay();
}
void mouse(int button, int state, int x, int y)
{
if(button == GLUT_LEFT_BUTTON)
mouseButtonPressed = "Left";
else if(button == GLUT_RIGHT_BUTTON)
mouseButtonPressed = "Right";
if(state == GLUT_DOWN)
mouseState = "down";
else if(state == GLUT_UP)
mouseState = "up";
}
void mouseMotion(int x, int y)
{
mouseX = x;
mouseY = y;
}
/*void info()
{
displayTextAt(-130, -40, 0, "mouseButton: %s", mouseButtonPressed);
displayTextAt(-130, -50, 0, "mouseButtonState: %s", mouseState);
displayTextAt(-130, -60, 0, "mouseX: %d", mouseX);
displayTextAt(-130, -70, 0, "mouseY: %d", mouseY);
displayTextAt(-130, -80, 0, "keyboard key: %c", keyboardKey);
displayTextAt(-130, -90, 0, "modifier: %s", modifier);
displayTextAt(70, -90, 0, view);
}*/
This is really a global variable declaration in a header problem. I've included the pastebin code (with fixes) for posterity.
/*This is the CallbackFunctions.h ------------------ */
#ifndef CALLBACKFUNCTIONS_H
#define CALLBACKFUNCTIONS_H
#include <GL/freeglut.h>
extern unsigned char keyboardKey;
/* Hardware Interrupts callback functions */
void display(); //called every single frame
void keyboard(unsigned char key, int x, int y); //whenever a keyboard key is pressed/interrupt occurs
#endif // CALLBACKFUNCTIONS_H
/*This is the CallbackFunctions.cpp ------------------ */
#include "CallbackFunctions.h"
unsigned char keyboardKey = 0;
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void keyboard(unsigned char key, int x, int y)
{
keyboardKey = key;
}
/* --------------- This is the Main.cpp ---------------- */
#include <GL/freeglut.h>
#include "CallbackFunctions.h"
#define WIDTH 700
#define HEIGHT 400
void setupGlutWindow(int *argc, char **argv, int width, int height);
void setupCallbackFunctions();
int main(int argc, char** argv)
{
setupGlutWindow(&argc, argv, WIDTH, HEIGHT);
setupCallbackFunctions();
glutMainLoop();
}
void setupGlutWindow(int *argc, char **argv, int width, int height)
{
glutInit(argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(700, 500);
glutCreateWindow("Project L3");
glViewport(0, 0, width, height);
}
void setupCallbackFunctions()
{
glutDisplayFunc(display);
glutIdleFunc(display);
glutKeyboardFunc(keyboard);
}

Creating a array of class objects (C++) [duplicate]

This question already has answers here:
How do I use arrays in C++?
(5 answers)
Closed 7 years ago.
I have been trying to make a simulator which involves ants randomly running around (for now...) I want to make a array of "Ant" to contain all my ant information and later functions. How would I do that?? (example with my code if possible)(I know java fairly well so if you could relate it to java that would be nice
//inclusions
#include <GLUT/glut.h>
#include <OpenGL/glu.h>
#include <OpenGL/gl.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
//declarations
//class declarations
void keyboard (unsigned char key, int x, int y);
void keyboardUp (unsigned char key, int x, int y);
void mouseLocation(int,int);
int onMouse;
int rightClick;
int a = 0;
int mx;
int my;
float red=1.0, blue=0, green=0;
class Ant {
int x;
int y;
int type;
Ant() { } // private default constructor
public:
Ant(int nx, int ny, int ntype)
{
x = nx;
y = ny;
type = ntype;
}
void SetX(int swagger)
{
x = swagger;
}
void SetY(int ny)
{
y = ny;
}
void SetType(int ntype)
{
type = ntype;
}
int GetX() { return x; }
int GetY() { return y; }
};
//mouse listener methods
void mouseLocation(int x,int y) {
mx = x;
my = y;
}
void mouseClicks(int button, int state, int x, int y) {
mx = x;
my = y;
if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
onMouse = 1;
}
if(button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
onMouse = 0;
}
if(button == GLUT_RIGHT_BUTTON && state == GLUT_UP) {
rightClick = 0;
}
if(button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) {
rightClick = 1;
}
}
//keylistner methods
void keyboard (unsigned char key, int x, int y)
{
if (key == 'a')
{
a = 1;
}
}
void keyboardUp (unsigned char key, int x, int y)
{
if(key == 'a')
{
a = 0;
}
}
//ant methods
int randommove(int position,int speed)
{
speed++;
int random = rand() %speed - speed/2 ;
position = position + random;
return position;
}
//drawing methods
Ant ant1(100,100,1);
Ant ant2(50,500,1);
//Here is the where I want to try the ant array something like
//Ant ants[x] and then I would fill in the values with the SetX, SetY... methods
void ant()
{
int a2 = randommove(ant1.GetX(),2);
ant1.SetX(a2);
glLineWidth(1);
glBegin(GL_LINES);
glColor4f(1, 0, 0, 1);
glVertex2i(ant1.GetX(),ant1.GetY());
glVertex2i(ant1.GetX()+5,ant1.GetY()+5);
glEnd();
}
void line1()
{
if(a == 1)
{
glLineWidth(2.5);
glBegin(GL_LINES);
glVertex2i(80,20);
glVertex2i(100,400);
glEnd();
}
}
void line2()
{
if(onMouse == 1)
{
glLineWidth(2.5);
glBegin(GL_LINES);
glVertex2i(200,20);
glVertex2i(100,400);
glEnd();
}
}
void rect1()
{
if(mx >= 50 && my >= 50)
{
int x = 100;
int y = 100;
int w = 100;
int h = 100;
unsigned int rgba = 0xff0000ff; // red, no alpha
glBegin(GL_QUADS);
glColor4f(((rgba>>24)&0xff)/255.0f,
((rgba>>16)&0xff)/255.0f,
((rgba>>8)&0xff)/255.0f,
(rgba&0xff)/255.0f);
glVertex3f(x,y,0);
glVertex3f(x+w,y,0);
glVertex3f(x+w,y+h,0);
glVertex3f(x,y+h,0);
glEnd();
glColor4f(1, 1, 1, 1);
}
}
void rect2()
{
if(rightClick == 1)
{
int w = 100;
int h = 100;
unsigned int rgba = 0xff0000ff; // red, no alpha
glBegin(GL_QUADS);
glColor4f(((rgba>>24)&0xff)/255.0f,
((rgba>>16)&0xff)/255.0f,
((rgba>>8)&0xff)/255.0f,
(rgba&0xff)/255.0f);
glVertex3f(mx,my,0);
glVertex3f(mx+w,my,0);
glVertex3f(mx+w,my+h,0);
glVertex3f(mx,my+h,0);
glEnd();
glColor4f(1, 1, 1, 1);
}
}
//render drawing methods
void renderScence(void){
glClear (GL_COLOR_BUFFER_BIT);
glColor3f(red, green, blue);
ant();
line1();
line2();
rect1();
rect2();
glFlush();
}
//graphics init method
void init(void)
{
glutInitDisplayMode(GLUT_SINGLE |GLUT_RGB);
glutInitWindowSize (500,500);
glutInitWindowPosition (100, 100);
glutCreateWindow ("Testing");
glClearColor (0, 0, 0, 1.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, 500, 0, 500);
}
//main/graphics calls
int main(int argc,char** argv)
{
glutInit(&argc, argv);
init();
glutDisplayFunc(renderScence);
glutIdleFunc(renderScence);
glutMouseFunc(mouseClicks);
glutPassiveMotionFunc(mouseLocation);
glutKeyboardUpFunc (keyboardUp);
glutKeyboardFunc (keyboard);
glutMainLoop();
return 0;
}
You could create the array of Ant objects inside main, and it's the same way you'd create any other array except it's of type Ant:
Ant ants[25]; // 25 Ant objects
/* to set them all the same, as an example */
for(i=0; i<25; i++)
{
ants[i].SetX(1); // x = 1
ants[i].SetY(2); // y = 2
ants[i].SetType(3); // type = 3
}

C++ declaring classes/objects for a noobie

I have recently decided to try to learn c++. My major road block so far is object/class declaration I am reasonably experienced in java but the way c++ works confuses me. Can someone please show me a example of using a object (like the one below if possible) inside one file or multiple files? here is my current code (object is not implemented).
//inclusions
#include <GLUT/glut.h>
#include <OpenGL/glu.h>
#include <OpenGL/gl.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
//declarations
void keyboard (unsigned char key, int x, int y);
void keyboardUp (unsigned char key, int x, int y);
void mouseLocation(int,int);
int onMouse;
int rightClick;
int a = 0;
int mx;
int my;
float red=1.0, blue=0, green=0;
class Ant
{
private:
int x;
int y;
int speed;
Ant() { } // private default constructor
public:
Ant(int nx, int ny, int nspeed)
{
SetX(nx);
SetY(ny);
SetSpeed(nspeed);
}
void SetX(int nx)
{
x = nx;
}
void SetY(int ny)
{
y = ny;
}
void SetSpeed(int nspeed)
{
speed = nspeed;
}
int GetX() { return x; }
int GetY() { return y; }
int GetSpeed() { return speed; }
};
//mouse listener methods
void mouseLocation(int x,int y) {
mx = x;
my = y;
}
void mouseClicks(int button, int state, int x, int y) {
mx = x;
my = y;
if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
onMouse = 1;
}
if(button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
onMouse = 0;
}
if(button == GLUT_RIGHT_BUTTON && state == GLUT_UP) {
rightClick = 0;
}
if(button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) {
rightClick = 1;
}
}
//keylistner methods
void keyboard (unsigned char key, int x, int y)
{
if (key == 'a')
{
a = 1;
}
}
void keyboardUp (unsigned char key, int x, int y)
{
if(key == 'a')
{
a = 0;
}
}
//drawing methods
void line1()
{
if(a == 1)
{
glLineWidth(2.5);
glBegin(GL_LINES);
glVertex2i(20,20);
glVertex2i(100,400);
glEnd();
}
}
void line2()
{
if(onMouse == 1)
{
glLineWidth(2.5);
glBegin(GL_LINES);
glVertex2i(200,20);
glVertex2i(100,400);
glEnd();
}
}
void rect1()
{
if(mx >= 50 && my >= 50)
{
int x = 100;
int y = 100;
int w = 100;
int h = 100;
unsigned int rgba = 0xff0000ff; // red, no alpha
glBegin(GL_QUADS);
glColor4f(((rgba>>24)&0xff)/255.0f,
((rgba>>16)&0xff)/255.0f,
((rgba>>8)&0xff)/255.0f,
(rgba&0xff)/255.0f);
glVertex3f(x,y,0);
glVertex3f(x+w,y,0);
glVertex3f(x+w,y+h,0);
glVertex3f(x,y+h,0);
glEnd();
glColor4f(1, 1, 1, 1);
}
}
void rect2()
{
if(rightClick == 1)
{
int x = 100;
int y = 100;
int w = 100;
int h = 100;
unsigned int rgba = 0xff0000ff; // red, no alpha
glBegin(GL_QUADS);
glColor4f(((rgba>>24)&0xff)/255.0f,
((rgba>>16)&0xff)/255.0f,
((rgba>>8)&0xff)/255.0f,
(rgba&0xff)/255.0f);
glVertex3f(mx,my,0);
glVertex3f(mx+w,my,0);
glVertex3f(mx+w,my+h,0);
glVertex3f(mx,my+h,0);
glEnd();
glColor4f(1, 1, 1, 1);
}
}
//render drawing methods
void renderScence(void){
glClear (GL_COLOR_BUFFER_BIT);
glColor3f(red, green, blue);
line1();
line2();
rect1();
rect2();
glFlush();
}
//graphics init method
void init(void)
{
glutInitDisplayMode(GLUT_SINGLE |GLUT_RGB);
glutInitWindowSize (500,500);
glutInitWindowPosition (100, 100);
glutCreateWindow ("Testing");
glClearColor (0, 0, 0, 1.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, 500, 0, 500);
}
//main/graphics calls
int main(int argc,char** argv)
{
glutInit(&argc, argv);
init();
glutDisplayFunc(renderScence);
glutIdleFunc(renderScence);
glutMouseFunc(mouseClicks);
glutPassiveMotionFunc(mouseLocation);
glutKeyboardUpFunc (keyboardUp);
glutKeyboardFunc (keyboard);
glutMainLoop();
return 0;
}
Your class definition is correct (although a bit Javaish). You can create and use an object of type Ant like this:
Ant a(3, 7, 82);
a.SetSpeed(42);
int speed = a.GetSpeed();

How to draw text letter by letter in glut?

I can't get my GLUT program to work properly.I want to draw text (a char array) letter by letter with some miliseconds interval. My program:
#include <string.h>
#include <windows.h>
#include <glut.h>
#include<iostream>
int hei = glutGet(GLUT_SCREEN_HEIGHT)/2;
int wid = glutGet(GLUT_SCREEN_WIDTH)/2;
void *font = GLUT_BITMAP_TIMES_ROMAN_24;
void *fonts[] =
{
GLUT_BITMAP_9_BY_15,
GLUT_BITMAP_TIMES_ROMAN_10,
GLUT_BITMAP_TIMES_ROMAN_24
};
void selectFont(int newfont)
{
font = fonts[newfont];
glutPostRedisplay();
}
void selectColor(float r, float g, float b)
{
glColor3f(r, g, b);
glutPostRedisplay();
}
char *msg;
void tick(void)
{
glutPostRedisplay();
}
void timer(int value) {
}
int element=0;
void output(int x, int y, char *string, bool center=true) {
int len;
len = strlen(string);
if(center){
glRasterPos2f((wid-len), y);
}
else {
glRasterPos2f(x, y);
}
for(int i=0;i<len;i++) {
glutBitmapCharacter(font, string[i]);
glPopMatrix();
glutSwapBuffers();
Sleep(500);
}
}
void outputmsg(int x, int y, bool center=true) {
int len;
len = strlen(msg);
if(center){
glRasterPos2f((wid-len), y);
}
else {
glRasterPos2f(x, y);
}
for(int i=0;i<len;i++) {
glutBitmapCharacter(font, msg[i]);
}
}
void updatemsg() {
msg="test msg letter by letter";
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
msg="|";
updatemsg();
if(msg!="|")
output(wid, hei, msg, true);
else
output(wid,hei,msg,true);
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, w, h, 0);
glMatrixMode(GL_MODELVIEW);
}
void keyboard(unsigned char key, int x, int y) {
switch(key){
case 27:
exit(1);
break;
}
}
int main(int argc, char **argv)
{
int i, msg_submenu, color_submenu;
glutInit(&argc, argv);
for (i = 1; i < argc; i++) {
if (!strcmp(argv[i], "-mono")) {
font = GLUT_BITMAP_9_BY_15;
}
}
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(wid*2, hei*2);
glutCreateWindow("CHAT");
glutFullScreen();
glClearColor(0.0, 0.0, 0.0, 1.0);
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutIdleFunc(tick);
selectFont(0);
glutMainLoop();
return 0; /* ANSI C requires main to return int. */
}
It does really weird stuff like erasing the previus one char then printing then printing the next one and the erased one. I tried everything what i could find about this topic on the forums. How can i fix it?
What you should do is also hold the length of the string you want to display and increment it every few milliseconds:
int len;
char *msg;
void incrementLength(int value){
if(msg[len]==0)return; //end of string stop the callback
len++;
glutTimerFunc(100, incrementLength, 0);
glutPostRedisplay();
}
void updatemsg() {
msg="test msg letter by letter";
len=0;
glutTimerFunc(100, incrementLength, 0);
}
And then in outputmsg (if you actually call it) you only loop until len:
void outputmsg(int x, int y, bool center=true) {
if(center){
glRasterPos2f((wid-len), y);
}
else {
glRasterPos2f(x, y);
}
for(int i=0;i<len;i++) {
glutBitmapCharacter(font, msg[i]);
}
}
This code has a couple of issues:
for(int i=0;i<len;i++) {
glutBitmapCharacter(font, string[i]);
glPopMatrix();
glutSwapBuffers();
Sleep(500);
}
You are popping a matrix that you never pushed anywhere, and you are doing it len-many times.
You are swapping buffers without clearing the screen in-between... that's going to lead to undefined results (generally a garbled mess of characters from previous frames).
You really need to re-think how you've implemented this.
I would suggest you implement some elapsed time check in your display (...) function that determines which character to print, rather than doing this in a loop that calls Sleep (...).

opengl tiny rendering glitch, need help & tips

here is my code:
#include <stdlib.h>
#include <iostream>
#include <gl/glew.h>
#include <gl/freeglut.h>
#include <gl/GL.h>
#include <gl/GLU.h>
#include <SDL.h>
using namespace std;
typedef unsigned short us;
typedef unsigned char uc;
bool *keystates = new bool[256];
bool *skeystates= new bool[256];
uc dir_m[8][2]={
{ 0, 1 },
{ 0,-1 },
{ -1,0 },
{ 1,0 },
{ 1,1},
{ 1,-1 },
{ -1,-1 },
{ -1,1 }
};
us totalbots=15;
float zoomlvl=-70.f;
float camx=0.f,camy=0.f;
struct bot_data{
float x,y,z;
float r,g,b;
float size; // "radius" of the square
us coold;
us age;
us trans:5;
us dir:3,fac:2;
bot_data(void);
void move(void);
void deliver(us bot);
};
struct bool_data{
bool ch:1,ch2:1;
};
bot_data::bot_data(void){
size=0.25f;
fac=rand()%4;
switch(fac){
case 0:x=10.f,y=10.f,z=0.f;
r=1.0f,g=0.f,b=0.f;
break;
case 1:x=-10.f,y=-10.f,z=0.f;
r=0.0f,g=0.f,b=1.f;
break;
case 2:x=-10.f,y=10.f,z=0.f;
r=1.0f,g=1.f,b=0.f;
break;
case 3:x=10.f,y=-10.f,z=0.f;
r=0.0f,g=1.f,b=0.f;
break;
}
coold=0;
trans=0;
age=0;
dir=rand()%8;
}
bot_data *cubers=new bot_data[65536];
bool_data *bools=new bool_data;
void bot_data::move(void){
float move=size/10.f;
switch(dir){
case 0:y+=move;
break;
case 1:y-=move;
break;
case 2:x-=move;
break;
case 3:x+=move;
break;
case 4:x+=move;
y+=move;
break;
case 5:x+=move;
y-=move;
break;
case 6:y-=move;
x-=move;
break;
case 7:y+=move;
x-=move;
break;
}
}
void bot_data::deliver(us bot){
age=-10;
totalbots+=3;
float tmp=size-(size/4.f);
size=0.25f;
x-=size;
y+=size;
for(uc i=1;i<=3;i++){
cubers[totalbots-i].fac=fac;
switch(fac){
case 0:cubers[totalbots-i].r=1.0f,cubers[totalbots-i].g=0.f,cubers[totalbots-i].b=0.f;
break;
case 1:cubers[totalbots-i].r=0.0f,cubers[totalbots-i].g=0.f,cubers[totalbots-i].b=1.f;
break;
case 2:cubers[totalbots-i].r=1.0f,cubers[totalbots-i].g=1.f,cubers[totalbots-i].b=0.f;
break;
case 3:cubers[totalbots-i].r=0.0f,cubers[totalbots-i].g=1.f,cubers[totalbots-i].b=0.f;
break;
}
cubers[totalbots-i].coold=coold;
cubers[totalbots-i].size=size;
switch(i){
case 1:cubers[totalbots-i].x=x;
cubers[totalbots-i].y=y-size*2;
break;
case 2:cubers[totalbots-i].x=x+size*2;
cubers[totalbots-i].y=y;
break;
case 3:cubers[totalbots-i].x=x+size*2;
cubers[totalbots-i].y=y-size*2;
break;
}
}
}
void initkeys(void){
for(uc i=0;i<255;i++){
keystates[i]=false;
skeystates[i]=false;
}
}
void p_keys(unsigned char key, int x, int y){
keystates[key]=true;
}
void keyup(unsigned char key, int x, int y){
keystates[key]=false;
}
void sp_keys(int key, int x, int y){
skeystates[key]=true;
}
void skeyup(int key, int x, int y){
skeystates[key]=false;
}
void key_func(void){
if (keystates['z']){
if(skeystates[GLUT_KEY_UP])zoomlvl+=1.f;
else if (skeystates[GLUT_KEY_DOWN])zoomlvl-=1.f;
if(zoomlvl<-100.0f)zoomlvl=-100.f;
else if(zoomlvl>-5.f)zoomlvl=-5.f;
}
else{
if(skeystates[GLUT_KEY_UP])camy-=1.f;
else if(skeystates[GLUT_KEY_DOWN])camy+=1.f;
}
if(skeystates[GLUT_KEY_LEFT])camx+=1.f;
else if(skeystates[GLUT_KEY_RIGHT])camx-=1.f;
}
void render_p(us bot){
glColor3f(cubers[bot].r,cubers[bot].g,cubers[bot].b);
glBegin(GL_QUADS);
glVertex2f(cubers[bot].size,cubers[bot].size);
glVertex2f(cubers[bot].size,-cubers[bot].size);
glVertex2f(-cubers[bot].size,-cubers[bot].size);
glVertex2f(-cubers[bot].size,cubers[bot].size);
glEnd();
}
void process_cubers(void){
for(us i=0;i<totalbots;i++){
//glPushMatrix();
glLoadIdentity();
glTranslatef(cubers[i].x,cubers[i].y,cubers[i].z);
if(cubers[i].coold==0){
cubers[i].move();
cubers[i].trans++;
if(cubers[i].trans==20){
cubers[i].trans=0;
cubers[i].coold=50;
if(cubers[i].age<100){
cubers[i].size+=0.025f;
}
else if(cubers[i].age==150){
cubers[i].deliver(i);
}
cubers[i].dir=rand()%8;
cubers[i].age+=10;
}
}
else cubers[i].coold--;
render_p(i);
//glPopMatrix();
}
}
void display(void){
key_func();
glClearColor(0.6f,0.6f,0.6f,1.f);
glClear (GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glTranslatef(camx,camy,zoomlvl);
process_cubers();
glutSwapBuffers();
SDL_Delay(1000/30);
glutPostRedisplay();
}
void resize(int width,int height){
glViewport(0,0,(GLsizei)width,(GLsizei)height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60,(GLfloat)width/(GLfloat)height,1.f,100.f);
glMatrixMode(GL_MODELVIEW);
}
int main (int argc, char **argv) {
initkeys();
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE);
glutInitWindowSize (640, 480);
glutInitWindowPosition (0, 0);
glutCreateWindow ("opengl 1");
glutDisplayFunc(display);
glutIdleFunc(display);
glutReshapeFunc(resize);
glutKeyboardFunc(p_keys);
glutKeyboardUpFunc(keyup);
glutSpecialFunc(sp_keys);
glutSpecialUpFunc(skeyup);
glutMainLoop();
return 0;
}
it renders a certain amount of said squares that move each certain intervals. their move distance is their size. each time they move they grow in size until they reach the size limit (1.f in radius in this case) after a certain amount of moves (15 in this case) the square will split into 4 smaller squares and FILLING OUT THE EXACT SPACE its precursor occupied, that means it is supposed to look completely seamless..the problem is instead, i get this split second tear & glitch-looking rendering after the square splits, but other than that i found no other problems.
what i suspect is perhaps i missed some gl function i was supposed to call around the time i am rendering the new 3 squares (the splitting occurs by adding 3 new squares, and shrinking the current one to a quarter of its size, then adjusting all the squres.)
Try this:
#include <GL/glew.h>
#include <GL/glut.h>
typedef unsigned short us;
typedef unsigned char uc;
bool *keystates = new bool[256];
bool *skeystates= new bool[256];
uc dir_m[8][2]=
{
{ 0, 1 },
{ 0,-1 },
{ -1,0 },
{ 1,0 },
{ 1,1},
{ 1,-1 },
{ -1,-1 },
{ -1,1 }
};
us totalbots=15;
float zoomlvl=-70.f;
float camx=0.f,camy=0.f;
struct bot_data
{
float x,y,z;
float r,g,b;
float size; // "radius" of the square
us coold;
us age;
us trans:5;
us dir:3,fac:2;
bot_data(void);
void move(void);
void deliver(us bot);
};
struct bool_data
{
bool ch:1,ch2:1;
};
bot_data::bot_data(void)
{
size=0.25f;
fac=rand()%4;
switch(fac){
case 0:x=10.f,y=10.f,z=0.f;
r=1.0f,g=0.f,b=0.f;
break;
case 1:x=-10.f,y=-10.f,z=0.f;
r=0.0f,g=0.f,b=1.f;
break;
case 2:x=-10.f,y=10.f,z=0.f;
r=1.0f,g=1.f,b=0.f;
break;
case 3:x=10.f,y=-10.f,z=0.f;
r=0.0f,g=1.f,b=0.f;
break;
}
coold=0;
trans=0;
age=0;
dir=rand()%8;
}
bot_data *cubers=new bot_data[65536];
bool_data *bools=new bool_data;
void bot_data::move(void)
{
float move=size/10.f;
switch(dir){
case 0:y+=move;
break;
case 1:y-=move;
break;
case 2:x-=move;
break;
case 3:x+=move;
break;
case 4:x+=move;
y+=move;
break;
case 5:x+=move;
y-=move;
break;
case 6:y-=move;
x-=move;
break;
case 7:y+=move;
x-=move;
break;
}
}
void bot_data::deliver(us bot)
{
age=-10;
totalbots+=3;
float tmp=size-(size/4.f);
size=0.25f;
x-=size;
y+=size;
for(uc i=1;i<=3;i++){
cubers[totalbots-i].fac=fac;
switch(fac){
case 0:cubers[totalbots-i].r=1.0f,cubers[totalbots-i].g=0.f,cubers[totalbots-i].b=0.f;
break;
case 1:cubers[totalbots-i].r=0.0f,cubers[totalbots-i].g=0.f,cubers[totalbots-i].b=1.f;
break;
case 2:cubers[totalbots-i].r=1.0f,cubers[totalbots-i].g=1.f,cubers[totalbots-i].b=0.f;
break;
case 3:cubers[totalbots-i].r=0.0f,cubers[totalbots-i].g=1.f,cubers[totalbots-i].b=0.f;
break;
}
cubers[totalbots-i].coold=coold;
cubers[totalbots-i].size=size;
switch(i){
case 1:cubers[totalbots-i].x=x;
cubers[totalbots-i].y=y-size*2;
break;
case 2:cubers[totalbots-i].x=x+size*2;
cubers[totalbots-i].y=y;
break;
case 3:cubers[totalbots-i].x=x+size*2;
cubers[totalbots-i].y=y-size*2;
break;
}
}
}
void initkeys(void)
{
for(uc i=0;i<255;i++){
keystates[i]=false;
skeystates[i]=false;
}
}
void p_keys(unsigned char key, int x, int y)
{
keystates[key]=true;
}
void keyup(unsigned char key, int x, int y)
{
keystates[key]=false;
}
void sp_keys(int key, int x, int y)
{
skeystates[key]=true;
}
void skeyup(int key, int x, int y)
{
skeystates[key]=false;
}
void key_func(void)
{
if (keystates['z'])
{
if(skeystates[GLUT_KEY_UP])zoomlvl+=1.f;
if(skeystates[GLUT_KEY_DOWN])zoomlvl-=1.f;
if(zoomlvl<-100.0f)zoomlvl=-100.f;
if(zoomlvl>-5.f)zoomlvl=-5.f;
}
else
{
if(skeystates[GLUT_KEY_UP])camy-=1.f;
if(skeystates[GLUT_KEY_DOWN])camy+=1.f;
if(skeystates[GLUT_KEY_LEFT])camx+=1.f;
if(skeystates[GLUT_KEY_RIGHT])camx-=1.f;
}
}
void render_p(us bot)
{
glColor3f(cubers[bot].r,cubers[bot].g,cubers[bot].b);
glBegin(GL_QUADS);
glVertex2f(cubers[bot].size,cubers[bot].size);
glVertex2f(cubers[bot].size,-cubers[bot].size);
glVertex2f(-cubers[bot].size,-cubers[bot].size);
glVertex2f(-cubers[bot].size,cubers[bot].size);
glEnd();
}
void process_cubers(void)
{
for(us i=0;i<totalbots;i++){
if(cubers[i].coold==0){
cubers[i].move();
cubers[i].trans++;
if(cubers[i].trans==20){
cubers[i].trans=0;
cubers[i].coold=50;
if(cubers[i].age<100){
cubers[i].size+=0.025f;
}
else if(cubers[i].age==150){
cubers[i].deliver(i);
}
cubers[i].dir=rand()%8;
cubers[i].age+=10;
}
}
else cubers[i].coold--;
}
for(us i=0;i<totalbots;i++)
{
glPushMatrix();
glTranslatef(cubers[i].x,cubers[i].y,cubers[i].z);
render_p(i);
glPopMatrix();
}
}
void display(void)
{
key_func();
glClearColor(0.6f,0.6f,0.6f,1.f);
glClear (GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
double w = glutGet( GLUT_WINDOW_WIDTH );
double h = glutGet( GLUT_WINDOW_HEIGHT );
gluPerspective(60, w / h,1.f,100.f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(camx,camy,zoomlvl);
process_cubers();
glutSwapBuffers();
}
void timer(int extra)
{
glutPostRedisplay();
glutTimerFunc(33, timer, 0);
}
int main (int argc, char **argv)
{
initkeys();
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_RGBA | GLUT_DOUBLE);
glutInitWindowSize (640, 480);
glutInitWindowPosition (0, 0);
glutCreateWindow ("opengl 1");
glutDisplayFunc(display);
glutKeyboardFunc(p_keys);
glutKeyboardUpFunc(keyup);
glutSpecialFunc(sp_keys);
glutSpecialUpFunc(skeyup);
glutTimerFunc(0, timer, 0);
glutMainLoop();
return 0;
}
You were drawing in your simulation loop. This splits that into two loops, sim then draw.
The way graphics rendering works (OpenGL or otherwise) is that it only guarantees a "nice" seam between two triangles that are "exactly" aligned along some edge if you render them as part of the same triangle strip, the same (vertex buffer, index buffer) model pair, or some other construct that groups triangles into a single render unit.
When you render a "quad," you are really rendering a 2-triangle triangle strip, so the seam between the two triangles looks nice.
When you render two seperate quads that are aligned along some edge, the edge can look bad. Anti-aliasing can help to fix the problem a little bit, but ultimately you need to use a single render unit if you want to get rid of the tearing along seams.
The figure shows four quads (eight triangles) being rendered in a grid. The diagonals are within quads so there isn't any tearing, but the since the quads are all rendered separately there is tearing along their seams.