Player not moving in Raylib - c++

In Raylib I am trying to make a player character move however it is not moving
I have tried using different functions like KeyPressed(). Here is the code(This is compiled in c++20):
#include <raylib.h>;
int main(){
int camX = 0;
int camY = 0;
InitWindow(1080, 720, "Arachnacide");
while(!WindowShouldClose()){
if(IsKeyDown(KEY_W)){
camY -= 1;
}
if(IsKeyDown(KEY_S)){
camY += 1;
}
if(IsKeyDown(KEY_A)){
camX += 1;
}
if(IsKeyDown(KEY_D)){
camX -= 1;
}
BeginDrawing();
DrawCircle(540, 360, 25, RED);
DrawCircle(camX, camY, 25, BLUE);
EndDrawing();
}
}

Remember to clear the background each time you draw.
BeginDrawing();
ClearBackground(RAYWHITE); // Substitute with any color you prefer
...
EndDrawing();

Related

bject disappearing while rotating in openGL

I have this weird problem in which the object that I'm trying to rotate just suddenly disappears. The way I am looking to rotate the object is with a keypress, which turns a global variable rotateAnimation to true. When the variable rotateAnimation is false, the object is visible, but once it's true the object disappears.
Here is the code:
bool rotateAnimation = false;
bool moveAnimation = false;
int moveDirX = 1, moveDirY = 1;
void DrawSpiral(int x, int y)
{
float tx, ty;
float i;
float a = 0, b = 0;
glPointSize(3);
glBegin(GL_LINE_STRIP);
for (i = 0; i < 20; i = i + 0.025)
{
a = a + .05;
b = b + .05;
tx = x + b * cos(i);
ty = y + a * sin(i);
glVertex2f(tx, ty);
}
glEnd();
}
void DrawSquare(int x, int y, int size)
{
glBegin(GL_POLYGON);
glVertex2f(x, y);
glVertex2f(x - size, y);
glVertex2f(x - size, y - size);
glVertex2f(x, y - size);
glEnd();
}
void DrawPolygon(int x, int y)
{
glBegin(GL_POLYGON);
glVertex2f(x, y);
glVertex2f(x - 25, y - 25);
glVertex2f(x - 15, y - 53);
glVertex2f(x + 15, y - 53);
glVertex2f(x + 25, y - 25);
glEnd();
}
void init()
{
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
glMatrixMode(GL_PROJECTION); // Since I want to do rotation in 2D
glLoadIdentity();
glClearColor(1.0, 1.0, 1.0, 0);
glColor3f(0.0f, 0.0f, 0.0f);
gluOrtho2D(0, WINDOW_WIDTH, 0, WINDOW_HEIGHT);
}
void Keypress(int key, int x, int y)
{
switch (key)
{
case 'm':
moveAnimation = !moveAnimation;
break;
case 'o':
rotateAnimation = !rotateAnimation;
break;
}
}
void Display()
{
glClear(GL_COLOR_BUFFER_BIT);
staticScene(); // Some other drawings that should always be there on the screen
glPushMatrix();
if (rotateAnimation)
{
glRotatef(60, 1.0, 0.0, 0.0);
}
glColor3f(0.0f, 0.0f, 0.0f);
glPointSize(2);
if (shape == "square")
DrawSquare(X, Y, 40);
else if (shape == "polygon")
DrawPolygon(X, Y);
else if (shape == "spiral")
DrawSpiral(X, Y);
glPopMatrix();
glutSwapBuffers();
}
void timer(int value)
{
glutPostRedisplay();
glutTimerFunc(1000 / 60, timer, 0);
if (moveAnimation)
{
int dx = 2, dy = 2;
if (X - dx < 0) // Add from X
X += dx, moveDirX = 1;
else if (X + dx > drawingWindow[0].first) // Subtract to X
X -= dx, moveDirX = -1;
else
X += (dx * moveDirX);
if (Y - dy < drawingWindow[2].second) // Add from Y
Y += dy, moveDirY = 1;
else if (Y + dy > drawingWindow[0].second) // Subtract to Y
Y -= dy, moveDirY = -1;
else
Y += (dy * moveDirY);
}
}
When rotateAnimation is false:
When rotateAnimation is true:
EDIT: I tried to scale the object too, but the same thing happens, when the toggle is on the object disappears, and when off it appears. One thing I noted is that when I comment out the TimerFunc then nothing happens. Neither does the object scale or rotate depending on what is toggled on.
Edited: You didn't switch the matrix mode to GL_MODELVIEW.
void init()
{
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
glMatrixMode(GL_PROJECTION); // Since I want to do rotation in 2D
glLoadIdentity();
glClearColor(1.0, 1.0, 1.0, 0);
glColor3f(0.0f, 0.0f, 0.0f);
gluOrtho2D(0, WINDOW_WIDTH, 0, WINDOW_HEIGHT);
glMatrixMode(GL_MODELVIEW); //<--here
}

Writing game engine using SDL2 and C++, my sprite and collision box separate when moving at angle

Basically I'm trying to implement a game engine using C++ and SDL2, and for the most part things are going smooth.
Collision detection works (using Separation Axis Theorem), movement, etc. but when I'm drawing the vertices of my collision box, and my sprite moves at an angle, the sprite and collision box move away from each other.
I'm not sure what's going on, I have two different angles to represent the angle of the image itself and the movement angle, and I've tried adjusting them with constants, adjusting which one changes and how with the movement, etc, but they still don't move together (when moving at an angle).
It's not a drawing error as the when the collision box hits another sprite's collision box, it detects that collision.
I'll leave code I think is relevant below, but I think it's a lot so I'll also leave a link to the repo if someone would rather look at that. Repo link.
Relevant classes are probably Sprite and Ship, relevant functions: Sprite::VectorProjection, Sprite::UpdateVertices, Sprite::MoveSprite, Ship::PlayerInput
Code:
//Sprite.cpp
void Sprite::VectorProjection(double Speed)
{
Velocity.x = Speed * cos(MoveAngle) + Acceleration.x;
Velocity.y = Speed * sin(MoveAngle) + Acceleration.y;
this->Speed = sqrt((Velocity.x * Velocity.x) + (Velocity.y * Velocity.y));
MoveAngle = atan2(Velocity.y, Velocity.x);
}
void Sprite::UpdateVertices()
{
std::vector<Vec2D> NewVerts;
Vec2D vert;
for (int i = 0; i < vertices.size(); ++i)
{
vert.x = ((vertices[i].x - Center.x) * cos(ImageAngle - LastAngle)) - ((vertices[i].y - Center.y) * sin(ImageAngle - LastAngle)) + Center.x;
vert.y = ((vertices[i].x - Center.x)*sin(ImageAngle - LastAngle)) + ((vertices[i].y - Center.y)*cos(ImageAngle - LastAngle)) + Center.y;
NewVerts.push_back(vert);
}
LastAngle = ImageAngle;
vertices = NewVerts;
}
void Sprite::MoveSprite()
{
std::vector<Vec2D> NewVerts;
Vec2D vert;
texture.x += Velocity.x;
texture.y += Velocity.y;
Position.x += Velocity.x;
Position.y += Velocity.y;
Center.x += Velocity.x;
Center.y += Velocity.y;
for (int i = 0; i < vertices.size(); ++i)
{
vert.x = vertices[i].x + Velocity.x;
vert.y = vertices[i].y + Velocity.y;
NewVerts.push_back(vert);
}
vertices = NewVerts;
}
--------------------------------------------------
//Ship.cpp
void Ship::PlayerInput(SDL_Event Event, SDL_Renderer* renderer)
{
double IA;
double MA;
if(Event.type == SDL_MOUSEBUTTONDOWN)
{
if (Event.button.button == SDL_BUTTON_LEFT)
{
Fire();
}
}
if (Event.type == SDL_KEYDOWN)
{
if (Event.key.keysym.sym == SDLK_w)
{
//MoveAngle = -M_PI/2;
SetSpeed(2.00);
MoveSprite();
}
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
if (Event.key.keysym.sym == SDLK_a)
{
IA = ConvertToDegrees(ImageAngle);
MA = ConvertToDegrees(MoveAngle);
SetImageAngle(IA - 1);
SetMoveAngle(MA - 1);
UpdateVertices();
}
if (Event.key.keysym.sym == SDLK_d)
{
IA = ConvertToDegrees(ImageAngle);
MA = ConvertToDegrees(MoveAngle);
SetImageAngle(IA + 1);
SetMoveAngle(MA + 1);
UpdateVertices();
}
}
if (Event.type == SDL_KEYUP)
{
SetSpeed(0.00);
}
}
Any help would be appreciated. Image of what's happening: The blue dots are the vertices and the image of the sprite should be inside of it. When moving left/right, up/down, it stays inside, but at an angle this happens.
EDIT: was asked for code where I calculate vertices, and render them, here's that:
//Initial set of vertices:
void Sprite::SetVertices()
{
Vec2D vert1{(double)texture.x, (double)texture.y};
Vec2D vert2{(double)texture.x + (double)texture.w, (double)texture.y};
Vec2D vert3{(double)texture.x, (double)texture.y + (double)texture.h};
Vec2D vert4{(double)texture.x + (double)texture.w, (double)texture.y + (double)texture.h};
//Order of insertion of vertices matters
vertices.push_back(vert1);
vertices.push_back(vert3);
vertices.push_back(vert4);
vertices.push_back(vert2);
}
-------------------------------------------
//Vertices are drawn in the Tick function of the Scene class
void Scene::Tick()
{
bool bWindowVisible = true;
SDL_Event Event;
while (bPlay)
{
CurrentTime = std::chrono::system_clock::now();
DeltaTime = CurrentTime - LastTime;
if (DeltaTime.count() < RefreshSeconds)
{
continue; //only used here to clean up code and help alleviate several layers of nesting
}
LastTime = CurrentTime;
if (!bPaused)
{
SDL_PollEvent(&Event);
EventHandler(Event, OUT bPlay, OUT bPaused);
SDL_RenderClear(Renderer);
for (Sprite* s : Sprites)
{
s->Update(Renderer);
SDL_RenderCopyEx(Renderer, s->Image, NULL, &s->texture, s->ConvertToDegrees(s->ImageAngle), NULL, SDL_FLIP_NONE);
//Draws vertices for debugging
for (Vec2D vert : s->vertices)
{
SDL_SetRenderDrawColor(Renderer, 0, 0, 255, 255);
SDL_RenderDrawPoint(Renderer, vert.x, vert.y);
}
}
SDL_SetRenderDrawColor(Renderer, 0, 0, 0, 255);
SDL_RenderPresent(Renderer);
}
else
{
PausedEventHandler(OUT bPlay, OUT bPaused); // this function was also created to help alleviate
}
}
return;
}
Since an image in SDL is defined by it's point in the upperleft corner, it does not rotate with the image (so if you rotate the image, the point remains the same). However when moving at an angle, all the other points in the image will move relative to that angle, but not that point, which would cause a separation of the collision box and the sprite itself. The issue was in this code block
void Sprite::MoveSprite()
{
std::vector<Vec2D> NewVerts;
Vec2D vert;
texture.x += Velocity.x;
texture.y += Velocity.y;
Position.x += Velocity.x;
Position.y += Velocity.y;
Center.x += Velocity.x;
Center.y += Velocity.y;
for (int i = 0; i < vertices.size(); ++i)
{
vert.x = vertices[i].x + Velocity.x;
vert.y = vertices[i].y + Velocity.y;
NewVerts.push_back(vert);
}
vertices = NewVerts;
}
Where I assumed the texture coordinates should move with the velocity. To fix this, I created a variable called D and defined it as the distance between the texture coordinate and the center
D.x = Center.x - texture.x;
D.y = Center.y - texture.y;
This will work since the texture coordinate is always in the upperleft corner
then we change the movesprite method to say this:
void Sprite::MoveSprite()
{
std::vector<Vec2D> NewVerts;
Vec2D vert;
Position.x += Velocity.x;
Position.y += Velocity.y;
Center.x += Velocity.x;
Center.y += Velocity.y;
texture.x = Center.x - D.x;
texture.y = Center.y - D.y;
for (int i = 0; i < vertices.size(); ++i)
{
vert.x = vertices[i].x + Velocity.x;
vert.y = vertices[i].y + Velocity.y;
NewVerts.push_back(vert);
}
vertices = NewVerts;
}
and problem is resolved!

gluLookAt seems to be producting wrong view, OpenGL

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).

OpenGL - FPS style Camera move with object fixed on camera

I am trying to move a camera in a 3d space. So far I have had success in moving and rotating the camera using this code:
void specialKeyHandler(int key, int x, int y) {
float fraction = 0.05f;
switch (key) {
case GLUT_KEY_LEFT :
camAngle -= 0.01f;
lX = sin(camAngle);
lZ = -cos(camAngle);
break;
case GLUT_KEY_RIGHT :
camAngle += 0.01f;
lX = sin(camAngle);
lZ = -cos(camAngle);
break;
case GLUT_KEY_UP :
iX += lX * fraction;
iZ += lZ * fraction;
break;
case GLUT_KEY_DOWN :
iX -= lX * fraction;
iZ -= lZ * fraction;
break;
default:
break;
}
}
Of course I have these variables defined. lX, lY, lZ are for LookAt variables and iX, iY and iZ are for camera's eye.
The camera moves as required, but now I want to attach an object on the "camera's eye" which shall move with the camera. Just like a Weapon in a FPS game.
This is what I have for that:
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
drawEarth();
drawWalls();
glColor3f(255,0,0);
glPushMatrix();
glTranslatef(iX+0.05,iY, iZ-0.05);
glRotatef(camAngle, 0,1,0);
glutWireCone(0.005,0.1,20,20); // object to go with camera
glPopMatrix();
glutSwapBuffers();
}
This code currently does bind the object with the camera while moving up and down. But when I rotate the camera by pressing left and right keys, object stays there and camera moves on its own..
Any solution?
Here's the full opengl code, if anyone wants to run:
#include <GL/glut.h>
#include<iostream>
#include<math.h>
using namespace std;
void display(void);
void reshape(int, int);
void mouseHandler(int button, int state, int x, int y);
void keyBoardHandler(unsigned char c, int x, int y);
void specialKeyHandler(int key, int x, int y);
float angle = 0;
bool camDefault = true, perspectiveOrtho = true;
float iX =0 , iY = -0.8, iZ = 0, lX = 0, lY = -0.8, lZ = -1, uX = 0, uY = 1, uZ = 0;
float camAngle = 0;
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitWindowSize(512, 512);
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
glutCreateWindow("FPS Camera");
glutDisplayFunc(display);
glutIdleFunc(display);
//look from negative x axis towards origin. with y on top
glutReshapeFunc(reshape);
glEnable(GL_DEPTH_TEST);
glClearColor(0,0,0,1);
glutMouseFunc(mouseHandler);
glutKeyboardFunc(keyBoardHandler);
glutSpecialFunc(specialKeyHandler);
glutMainLoop();
return 0;
}
void drawEarth() {
glColor3f(0,255,0);
glBegin(GL_QUADS);
glVertex3f(-1,-1,-1);
glVertex3f(-1,-1,1);
glVertex3f(1,-1,1);
glVertex3f(1,-1,-1);
glEnd();
}
void drawWalls() {
glColor3f(0,0,255);
glBegin(GL_QUADS);
glVertex3f(-1,-1,-1);
glVertex3f(-1,-1,1);
glVertex3f(-1,1,1);
glVertex3f(-1,1,-1);
glEnd();
glColor3f(0,234,255);
glBegin(GL_QUADS);
glVertex3f(-1,-1,1);
glVertex3f(-1,1,1);
glVertex3f(1,1,1);
glVertex3f(1,-1,1);
glEnd();
}
float unitVector(float dir, float x, float y, float z) {
float sumSqr = pow(x,2) + pow(y,2) + pow(z,2);
return dir / (sqrt(sumSqr));
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
drawEarth();
drawWalls();
glColor3f(255,0,0);
glPushMatrix();
glTranslatef(iX+0.05,iY, iZ-0.05);
glRotatef(camAngle, 0,1,0);
glutWireCone(0.005,0.1,20,20);
glPopMatrix();
glutSwapBuffers();
}
void reshape(int width, int height)
{
glViewport(0,0,width,height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(90,1, 0.001, 1000);
gluLookAt(iX,iY,iZ,iX+lX,lY,iZ+lZ,uX,uY,uZ);
glMatrixMode(GL_MODELVIEW);
}
void updateLookAt() {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective (90, 1 ,0.001, 1000);
gluLookAt(iX,iY,iZ,iX+lX,lY,iZ+lZ,uX,uY,uZ);
glMatrixMode(GL_MODELVIEW);
}
void keyBoardHandler(unsigned char c, int x, int y) {
switch(c) {
case 'f': // go left
iX-=0.01;
lX -= 0.01;
cout<<endl<<"S pressed";
break;
case 's': // go right
iX += 0.01;
lX += 0.01;
break;
case 'e': // go up
iZ += 0.01;
lZ += 0.01;
break;
case 'd': // go down
iZ -= 0.01;
lZ -= 0.01;
break;
default:
break;
}
updateLookAt();
}
void mouseHandler(int button, int state, int x, int y) {
if(button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) {
if(camDefault) {
glLoadIdentity();
gluLookAt(-1,0,0,0.0,0.0,0.0,0.0,1,0);
camDefault = false;
}
else {
glLoadIdentity();
gluLookAt(0,0,0,0.0,0.0,0.0,0.0,1,0);
camDefault = true;
}
}
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if(perspectiveOrtho) {
gluPerspective (90, 1 ,0.00001, 1000);
perspectiveOrtho = false;
}
else {
glOrtho(-1,1,-1,1, -1,100);
perspectiveOrtho = true;
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
if(camDefault)
gluLookAt(0,0,1,0.0,0.0,0.0,0.0,1,0);
else
gluLookAt(-1,0,0,0.0,0.0,0.0,0.0,1,0);
}
}
void specialKeyHandler(int key, int x, int y) {
float fraction = 0.05f;
switch (key) {
case GLUT_KEY_LEFT :
camAngle -= 0.01f;
lX = sin(camAngle);
lZ = -cos(camAngle);
break;
case GLUT_KEY_RIGHT :
camAngle += 0.01f;
lX = sin(camAngle);
lZ = -cos(camAngle);
break;
case GLUT_KEY_UP :
iX += lX * fraction;
iZ += lZ * fraction;
break;
case GLUT_KEY_DOWN :
iX -= lX * fraction;
iZ -= lZ * fraction;
break;
default:
break;
}
updateLookAt();
}
You have two problems.
The first problem is on your coordinates system.
When you apply :
glTranslatef(iX+0.05,iY, iZ-0.05);
You place the object at the camera position, and add an offset to see him. But this is in the world coordinates system. So when you rotate the camera, the object doesn't move cause it doesn't follow the camera's coordinates system.
You need to translate to the camera center, rotate the camera, then add the offset.
The second problem is on the rotation. Your "camAngle" variable is in radian, cause you use it with cos() and sin(). But in OpenGL, glRotate take the angle as a degree value. You need to convert this angle in angle : angle *= 180/PI. (180/PI ~= 57.2957795)
Here the corrected display function :
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(255,0,0);
glPushMatrix();
glTranslatef(iX,iY,iZ); // Translation to the camera center
glRotatef(-camAngle * 57.2957795, 0,1,0); // Rotate to correspond to the camera
glTranslatef(0.05,0,-0.05); // Offset to draw the object
glutWireCone(0.005,0.1,20,20);
glPopMatrix();
drawEarth();
drawWalls();
glutSwapBuffers();
}

Screen goes black when drawing to it SFML C++

I have a basic game set up in C++, openGL and SFML.
But then when i try to add text or draw a square to the screen(for the GUI) the screen goes mainly black, i can see something happens in the top left, but i don't know what
And i receive this error in the console:
An internal OpenGL call failed in RenderTarget.cpp<362> : GL_INVLAD_OPERATION,
the specified operation is not allowed in the current state
Here is the full code:
#include "Engine.h"
static sf::RenderWindow App(sf::VideoMode(1600, 900, 32), "SFML OpenGL");
Engine::Engine()
{
glewInit();
c_player = Player(Vector3D(0, 14, 0), 0);
c_enemy = Enemy(Vector3D(0, 14, -10), 0);
c_gui = Gui(App);
c_mouseSensitivityX = 5;
c_mouseSensitivityY = 5;
}
Engine::~Engine(void)
{
}
void Engine::init(void)
{
text.setString("Hello SFML");
text.setCharacterSize(50);
text.setPosition(10.0f, 10.0f);
c_wall.LoadModel("Wall.dae");
c_crates.LoadModel("crates.dae");
c_cargoWall.LoadModel("cargoWall.dae");
c_leftCorner.LoadModel("leftCorner.dae");
c_rightCorner.LoadModel("rightCorner.dae");
c_shipPipeWall.LoadModel("shipPipeWall.dae");
c_shipWindow.LoadModel("shipWindow.dae");
float posx = -200;
float posfar = 200;
float posnear = -200;
/*for(int i = -200; i < 200 ; i += 20)
{
c_wallProperties.push_back(wallProps(Vector3D(i, 15, posfar), 0));
c_wallProperties.push_back(wallProps(Vector3D(i, 15, posnear),0));
c_wallProperties.push_back(wallProps(Vector3D(posfar, 15, i), 90));
c_wallProperties.push_back(wallProps(Vector3D(posnear, 15, i),90));
}*/
int xflip = 1;
for (int i=0; i<2; ++i)
{
c_wallProperties.push_back(wallProps(Vector3D(70 * xflip,15,20), 0));
c_crateProperties.push_back(wallProps(Vector3D(55 * xflip,15,10), 0));
// //c_wallProperties.push_back(wallProps(Vector3D(40 * xflip,15,20), 0));
// ////c_wallProperties.push_back(wallProps(Vector3D(25 * xflip,15,20), 0));
// //c_wallProperties.push_back(wallProps(Vector3D(85 * xflip,15,20), 0));
// //c_wallProperties.push_back(wallProps(Vector3D(100 * xflip,15,20), 0));
// //c_wallProperties.push_back(wallProps(Vector3D(140 * xflip,15,20), 0));
// //c_wallProperties.push_back(wallProps(Vector3D(70 * xflip,15,-10), 0));
// //c_wallProperties.push_back(wallProps(Vector3D(55 * xflip,15,-10), 0));
// //c_wallProperties.push_back(wallProps(Vector3D(40 * xflip,15,-10), 0));
// ////c_wallProperties.push_back(wallProps(Vector3D(25 * xflip,15,-10), 0));
// //c_wallProperties.push_back(wallProps(Vector3D(85 * xflip,15,-10), 0));
// //c_wallProperties.push_back(wallProps(Vector3D(100 * xflip,15,-10), 0));
// c_wallProperties.push_back(wallProps(Vector3D(140 * xflip,15,-10), 0));
xflip = xflip * -1;
}
//c_myModels.push_back(new buildings("rightCorner.dae",Vector3D(120,15,1)));
////c_myModels.push_back(new Objects("phoenix_ugv.md2", Vector3D(-50,0,20)));
glClearDepth(1.f);
glClearColor(0.f, 0.f, 0.f, 0.f);
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
GLfloat lightpos[] = {.5, 1., 1., 0.};
glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
c_FPSClock.restart();
ParticleSystem newParticle;
newParticle.setMaxParticles(500);
newParticle.setParticleColour(sf::Color(143, 44, 1, 255), sf::Color(255, 127, 39, 255));
newParticle.setParticleLifespan(60, 180);
newParticle.setParticleSpawnrate(0.2, 0.3);
newParticle.setParticleVelocity(Vector3D(-10, 30, -10), Vector3D(10, 50, 10));
newParticle.setParticleAcceleration(Vector3D(0, -9.81, 0), Vector3D(0, -9.81, 0));
newParticle.setSpawnerPosition(Vector3D(0, 10, 0));
c_particleSystems.push_back(newParticle);
}
void Engine::getInput(void)
{
while (App.pollEvent(c_event))
{
// Close window : exit
if (c_event.type == sf::Event::Closed)
App.close();
// Resize event : adjust viewport
if (c_event.type == sf::Event::Resized)
glViewport(0, 0, c_event.size.width, c_event.size.height);
// Camera Controls
if (c_event.type == sf::Event::KeyPressed)
{
switch (c_event.key.code)
{
case sf::Keyboard::Escape:
App.close();
break;
case sf::Keyboard::W:
c_player.move(Vector3D(0, 0, -1));
break;
case sf::Keyboard::S:
c_player.move(Vector3D(0, 0, 1));
break;
case sf::Keyboard::A:
c_player.move(Vector3D(-1, 0, 0));
break;
case sf::Keyboard::D:
c_player.move(Vector3D(1, 0, 0));
break;
case sf::Keyboard::X:
c_camera.togglePerspective();
break;
}
}
}
}
void Engine::run()
{
while (App.isOpen())
{
while (c_FPSClock.getElapsedTime().asSeconds() < 1.f/60)
{
}
// Set the active window before using OpenGL commands
// It's useless here because active window is always the same,
// but don't forget it if you use multiple windows or controls
App.setActive();
//App.draw(rectangle);
// Clear color and depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
getInput();
update();
render();
}
}
void Engine::update(void)
{
mouseMove();
c_worldEngine.update();
c_player.update();
c_enemy.update();
c_camera.update(c_player);
for (vector<ParticleSystem>::iterator iter = c_particleSystems.begin(); iter != c_particleSystems.end(); ++iter)
{
iter->update();
}
}
void Engine::render(void)
{
c_camera.render();
c_gui.render();
c_worldEngine.render(c_camera.getPos());
App.draw(text);
for (vector<pair<Vector3D, float>>::iterator iter = c_wallProperties.begin(); iter != c_wallProperties.end(); ++iter)
{
glEnable(GL_TEXTURE_3D);
glPushMatrix();
glTranslatef(iter->first.x, iter->first.y, iter->first.z);
glRotatef(iter->second, 0, 1, 0);
c_wall.Render();
glPopMatrix();
glDisable(GL_TEXTURE_3D);
}
glPushMatrix();
glEnable(GL_COLOR_MATERIAL);
if (c_camera.isFirstPerson() == false)
{
c_player.render();
}
c_enemy.render();
glDisable(GL_COLOR_MATERIAL);
glPopMatrix();
c_glModel.render(Vector3D(0,5,0));
for (vector<ParticleSystem>::iterator iter = c_particleSystems.begin(); iter != c_particleSystems.end(); ++iter)
{
iter->render();
}
App.display();
c_FPSClock.restart();
}
void Engine::mouseMove(void)
{
sf::Vector2u winSize = App.getSize();
sf::Vector2u winMid = sf::Vector2u(winSize.x/2, winSize.y/2);
sf::Vector2i mousePos = sf::Mouse::getPosition(App);
if ((mousePos.x == winMid.x) && (mousePos.y == winMid.y))
{
return;
}
sf::Mouse::setPosition(Vector2i(winMid.x, winMid.y), App);
sf::Vector2i mouseDiff = sf::Vector2i(winMid.x - mousePos.x, winMid.y - mousePos.y);
sf::Vector2f diffRatio = sf::Vector2f(mouseDiff.x / c_mouseSensitivityX, mouseDiff.y / c_mouseSensitivityY);
if (c_camera.isFirstPerson())
{
diffRatio.y /= 10;
}
c_player.rotate(diffRatio.x);
c_camera.rotateY(diffRatio.y);
}
In my init function i simply set the text properties like so:
text.setString("Hello SFML");
text.setCharacterSize(50);
text.setPosition(10.0f, 10.0f);
text is declared in my header file as sf::Text text.
I cant see any reason for the text not to be printed to the screen!
EDIT
Ok so i looked into the whole pushing and popping openGL states and implemented it as shown on a thread and i now get this image!:
So im getting there, as you can see the problem with this is the player is no longer shown and the input is all messed up :/
Here is the updated loop:
void Engine::run()
{
while (App.isOpen())
{
while (c_FPSClock.getElapsedTime().asSeconds() < 1.f/60)
{
}
App.pushGLStates();
App.draw(text);
App.popGLStates();
// Set the active window before using OpenGL commands
// It's useless here because active window is always the same,
// but don't forget it if you use multiple windows or controls
App.setActive();
//App.draw(rectangle);
// Clear color and depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
getInput();
update();
render();
}
}
In regards to loading a font i have implemented it but for some reason the font cant be found with this code:
if(!font.loadFromFile("../arial.tff"))
{
cout<<"no font"<<endl;
}
although the file is in the file it is directed at?
1: if the sf::Font you set for that sf::Text (which i assume you must have) goes out of scope it wont display it, because its font reference is gone.
2: if you have another thread running (possibly displaying your scenery) and you set your App.setActive() the other thread is deactivated automagically
3: openGL states sometimes conflict with SFML if you're switching between them.. Save them, draw with SFML, restore them, then you can resume openGL drawing.
hope this helps a little.
oh and hey, look at this wonderful page:
http://www.sfml-dev.org/tutorials/2.0/window-opengl.php