Sprite can not move in cocos2d-x - c++

I am new on cocos2d-x, i followed Cocos2d-x Game Development Essentials Ebook and trying to make demo app in iOS. with the help of its guidance,but when i trying to Move Astroids in GameScreen.cpp file as written in book, they actually doesn't move and i can't understand what am i missing?
here is code that i used:
bool GameScene::init()
{
//////////////////////////////
// 1. super init first
if ( !Layer::init() )
{
return false;
}
//Add EVENT LISTENER TO HANDLE TOUCH EVENT,
auto listener = EventListenerTouchOneByOne::create();
listener->setSwallowTouches(true);
listener->onTouchBegan = CC_CALLBACK_2(GameScene::ontouchBegin,this);
listener->onTouchMoved = CC_CALLBACK_2(GameScene::ontouchMoved, this);
listener->onTouchCancelled = CC_CALLBACK_2(GameScene::ontouchCanceled, this);
listener->onTouchEnded = CC_CALLBACK_2(GameScene::ontouchEnded, this);
this->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this);
istouching = false;
touchPosition = 0;
visibleSize = Director::getInstance()->getVisibleSize();
origin = Director::getInstance()->getVisibleOrigin();
auto backgroundSprite = Sprite::create("Game_Screen_Background.png");
backgroundSprite->setPosition(Point((visibleSize.width/2)+origin.x,(visibleSize.height/2)+origin.y));
this->addChild(backgroundSprite, -1);
auto pauseItem =
MenuItemImage::create("Pause_Button.png","Pause_Button(Click).png",CC_CALLBACK_1(GameScene::PushToGamePauseScene, this));
pauseItem->setPosition(Point(pauseItem->getContentSize().width-(pauseItem->getContentSize().width/4)+origin.x,visibleSize.height - pauseItem->getContentSize().height +(pauseItem->getContentSize().width / 4) + origin.y));
auto menu = Menu::create(pauseItem, NULL);
menu->setPosition(Point::ZERO);
this->addChild(menu);
for (int i = 0; i < 2; i ++){
backgroundSpriteArray[i] = Sprite::create("Game_Screen_Background.png");
backgroundSpriteArray[i]->setPosition(Point((visibleSize.width/2)+origin.x,(-1*visibleSize.height*i)+(visibleSize.height/2)+origin.y));
this->addChild(backgroundSpriteArray[i],-2);
}
playerSprite = Sprite::create("Space_Pod.png");
playerSprite->setPosition(Point(visibleSize.width/2,pauseItem->getPosition().y-(pauseItem->getContentSize().height/2)-(playerSprite->getContentSize().height/2)));
this->addChild(playerSprite, 1);
this->schedule(schedule_selector(GameScene::spawnAsteroid), 1.0);
this->scheduleUpdate();
return true;
}
Following is update method
void GameScene::update(float dt){
Size visibleSize = Director::getInstance()->getVisibleSize();
Point origin = Director::getInstance()->getVisibleOrigin();
for (int i = 0; i < 2; i ++){
if (backgroundSpriteArray[i]->getPosition().y >=visibleSize.height + (visibleSize.height / 2) -1){
backgroundSpriteArray[i]->setPosition(Point((visibleSize.width / 2) + origin.x, (-1 *visibleSize.height) + (visibleSize.height / 2)));
}
}
for (int i = 0; i < 2; i ++){
backgroundSpriteArray[i]->setPosition(Point(backgroundSpriteArray[i]->getPosition().x,backgroundSpriteArray[i]->getPosition().y + (0.75 *visibleSize.height * dt)));
}
for (int i = 0; i < asteroids.size(); i++){
asteroids[i]->setPosition(Point(asteroids[i]->getPosition().x,asteroids[i]->getPosition().y+(0.75 * visibleSize.height * dt)));
if (asteroids[i]->getPosition().y > visibleSize.height * 2){
this->removeChild(asteroids[i]);
asteroids.erase(asteroids.begin() + i);
}
}
//check for Touching
if(istouching == true){
//now check, which side of the screen is being touched
if(touchPosition < visibleSize.width /2){
//now, move the space pod to left
float positionX = playerSprite->getPosition().x;
playerSprite->setPositionX(positionX - (0.50* visibleSize.width * dt));
positionX = playerSprite->getPositionX();
//prevent space pod to getting off the screen (left side)
if(positionX <= 0+(playerSprite->getContentSize().width/2))
{
playerSprite->setPositionX(playerSprite->getContentSize().width / 2);
}
}
else{
//now, move the space pod to right
float positionX = playerSprite->getPositionX();
playerSprite->setPositionX(positionX + (0.50 * visibleSize.width *dt));
positionX = playerSprite->getPositionX();
// check to prevent the space pod from going off the screen (right side)
if(positionX >= visibleSize.width-(playerSprite->getContentSize().width/2))
{
playerSprite->setPositionX(visibleSize.width-(playerSprite->getContentSize().width/2));
}
}
}
}
For move astroid code:
void GameScene::spawnAsteroid(float dt){
Size visibleSize = Director::getInstance()->getVisibleSize();
Point origin = Director::getInstance()->getVisibleOrigin();
int asteroidIndex = (arc4random() % 3) + 1;
__String* asteroidString = __String::createWithFormat("Asteroid_%i.png",asteroidIndex);
auto *tempAsteroid = Sprite::create(asteroidString->getCString());
int xRandomPosition = (arc4random() % (int)(visibleSize.width - (tempAsteroid->getContentSize().width / 2))) + (tempAsteroid->getContentSize().width / 2);
tempAsteroid->setPosition(Point(xRandomPosition + origin.x, -tempAsteroid->getContentSize().height +origin.y));
asteroids.push_back(tempAsteroid);
this->update(touchPosition);
this->addChild(asteroids[asteroids.size() - 1], -1);
}
That method has been called at run time but don't know that my astroid object does not moved can anybody please help me for figure it out issue and how to fix it.
Edit
OK,i put this->scheduleUpdate() in init(),and starts moving astroids on the screen but when i move my sprite(not astroids) with touchBegin event the astroid got disappear from screen. please guide me on this.

please put this line in your init method
this->scheduleUpdate();
Hope it helps

Sprite->runAction(Sequence::create(MoveTo::create(1.0f, Vec2(100,200)),NULL));

Related

Sprite collision with tile map

So, I'm trying to build my own game engine and my first project is creating a pacman clone. I've worked out how to create the tilemap and move pacman around on it. But I've having issues creating a collision detector with the tilemap. Particularly the issue is that the collision detects fine for any tiles north of the current location, however it thinks the tile below the current location is actually 1 tile larger than normal. And 0 collision exists for tiles east and west of the current location. I'm confused because the collision works for the north tile... but I'm using the same logic for the other directions and it's not working.
The logic I am using is that 'okay' tiles to move into are value 0. Any other tile is not able for movement.
Here is the code I'm using for the actual wall collision:
//checks for a sprite colliding with a wall tile
//direction refers to 1=North, 2=South, 3=West, 4=East
bool Wall_Collision(SPRITE sprite, int direction)
{
//grab center of sprite
Posx = sprite.x + Sprite_Radius;
Posy = sprite.y + Sprite_Radius;
//create rectangle for the sprite
RECT spriteRect;
spriteRect.left = (long)sprite.x;
spriteRect.top = (long)sprite.y;
spriteRect.right = (long)sprite.x + sprite.width * sprite.scaling;
spriteRect.bottom = (long)sprite.y + sprite.height * sprite.scaling;
//recover North tile info
int N_posx, N_posy;
int N_tilex, N_tiley;
int N_tilevalue;
N_posx = Posx / TILEWIDTH;
N_posy = (Posy - TILEHEIGHT) / TILEHEIGHT;
N_tilex = N_posx * TILEWIDTH;
N_tiley = N_posy * TILEHEIGHT;
N_tilevalue = MAPDATA[(N_posy * MAPWIDTH + N_posx)];
//create rectangle for tile North of sprite center
RECT northRect;
northRect.left = N_tilex;
northRect.top = N_tiley;
northRect.right = N_tilex + TILEWIDTH;
northRect.bottom = N_tiley + TILEHEIGHT;
//recover South tile info
int S_posx, S_posy;
int S_tilex, S_tiley;
int S_tilevalue;
S_posx = Posx / TILEWIDTH;
S_posy = (Posy + TILEHEIGHT) / TILEHEIGHT;
S_tilex = S_posx * TILEWIDTH;
S_tiley = S_posy * TILEHEIGHT;
S_tilevalue = MAPDATA[(S_posy * MAPWIDTH + S_posx)];
//create rectangle for tile South of sprite center
RECT southRect;
southRect.left = S_tilex;
southRect.top = S_tiley;
southRect.right = S_tilex + TILEWIDTH;
southRect.bottom = S_tiley + TILEHEIGHT;
//recover West tile info
int W_posx, W_posy;
int W_tilex, W_tiley;
int W_tilevalue;
W_posx = (Posx - TILEWIDTH) / TILEWIDTH;
W_posy = Posy / TILEHEIGHT;
W_tilex = W_posx * TILEWIDTH;
W_tiley = W_posy * TILEHEIGHT;
W_tilevalue = MAPDATA[(W_posy * MAPWIDTH + W_posx)];
//create rectangle for tile West of sprite center
RECT westRect;
westRect.left = W_tilex;
westRect.top = W_tiley;
westRect.right = W_tilex + TILEWIDTH;
westRect.bottom = W_tiley + TILEHEIGHT;
//recover East tile info
int E_posx, E_posy;
int E_tilex, E_tiley;
int E_tilevalue;
E_posx = (Posx + TILEWIDTH) / TILEWIDTH;
E_posy = Posy / TILEHEIGHT;
E_tilex = E_posx * TILEWIDTH;
E_tiley = E_posy * TILEHEIGHT;
E_tilevalue = MAPDATA[(E_posy * MAPWIDTH + E_posx)];
//create rectangle for tile East of sprite center
RECT eastRect;
eastRect.left = E_tilex;
eastRect.top = E_tiley;
eastRect.right = E_tilex + TILEWIDTH;
eastRect.bottom = E_tiley + TILEHEIGHT;
RECT dest; //ignored
//check North collision
if (direction == 1 && N_tilevalue != 0)
{
return IntersectRect(&dest, &spriteRect, &northRect);
}
else return false;
//check South collision
if (direction == 2 && S_tilevalue != 0)
{
return IntersectRect(&dest, &spriteRect, &southRect);
}
else return false;
//check West collision
if (direction == 3 && W_tilevalue != 0)
{
return IntersectRect(&dest, &spriteRect, &westRect);
}
else return false;
//check East collision
if (direction == 4 && E_tilevalue != 0)
{
return IntersectRect(&dest, &spriteRect, &eastRect);
}
else return false;
}
And then the context I'm using the function to move the player sprite:
void MovePacman()
{
if (Wall_Collision(pacman, 1))
{
pacman.y -= pacman.vely;
pacman.vely = 0.0f;
}
else
{
if (Key_Down(DIK_UP))
{
pacman.vely = -0.2f;
pacman.velx = 0.0f;
}
}
if (Wall_Collision(pacman, 2))
{
pacman.y -= pacman.vely;
pacman.vely = 0.0f;
}
else
{
if (Key_Down(DIK_DOWN))
{
pacman.vely = 0.2f;
pacman.velx = 0.0f;
}
}
if (Wall_Collision(pacman, 3))
{
pacman.x -= pacman.velx;
pacman.velx = 0.0f;
}
else
{
if (Key_Down(DIK_LEFT))
{
pacman.velx = -0.2f;
pacman.vely = 0.0f;
}
}
if (Wall_Collision(pacman, 4))
{
pacman.x -= pacman.velx;
pacman.velx = 0.0f;
}
else
{
if (Key_Down(DIK_RIGHT))
{
pacman.velx = 0.2f;
pacman.vely = 0.0f;
}
else;
}
if (pacman.vely < 0)
Sprite_Animate(pacman.frame, pacman.startframe, 18, 4, pacman.starttime, 250);
else if (pacman.vely > 0)
Sprite_Animate(pacman.frame, pacman.startframe, 16, 2, pacman.starttime, 250);
else if (pacman.velx < 0)
Sprite_Animate(pacman.frame, pacman.startframe, 17, 3, pacman.starttime, 250);
else if (pacman.velx > 0)
Sprite_Animate(pacman.frame, pacman.startframe, 15, 1, pacman.starttime, 250);
pacman.y += pacman.vely;
pacman.x += pacman.velx;
}
trust that I've defined everything that is not pasted and linked headers correctly. Any ideas where I'm going wrong?
You're only checking for collisions in one case:
//check North collision
if (direction == 1 && N_tilevalue != 0)
{
return IntersectRect(&dest, &spriteRect, &northRect);
}
else return false; // <--- this
//check South collision
if (direction == 2 && S_tilevalue != 0)
{
return IntersectRect(&dest, &spriteRect, &southRect);
}
else return false; // <--- and this, etc...
See the line highlighted above. If it doesn't test for a North collision (i.e. if direction isn't 1 or N_tilevalue is 0) then the function returns at that point in all other cases. It can never go on to do the other collision checks.

Neopixel arduino fading from colour to colour using a Sparkcore

This question is a follow from another question I asked here that was answered.
I have the following function:
MotiColor startColor;
MotiColor endColor;
void setup()
{
// Begin strip.
strip.begin();
// Initialize all pixels to 'off'.
strip.show();
Serial1.begin(9600);
startColor = MotiColor(0, 0, 0);
endColor = MotiColor(0, 0, 0);
}
void loop () {
}
int tinkerSetColour(String command)
{
strip.show();
int commaIndex = command.indexOf(',');
int secondCommaIndex = command.indexOf(',', commaIndex+1);
int lastCommaIndex = command.lastIndexOf(',');
String red = command.substring(0, commaIndex);
String grn = command.substring(commaIndex+1, secondCommaIndex);
String blu = command.substring(lastCommaIndex+1);
startColor = MotiColor(red.toInt(), grn.toInt(), blu.toInt());
int16_t redDiff = endColor.getR() - startColor.getR();
int16_t greenDiff = endColor.getG() - startColor.getG();
int16_t blueDiff = endColor.getB() - startColor.getB();
int16_t _delay = 500;
int16_t duration = 3500;
int16_t steps = duration / _delay;
int16_t redValue, greenValue, blueValue;
for (int16_t i = steps; i >= 0; i--) {
redValue = (int16_t)startColor.getR() + (redDiff * i / steps);
greenValue = (int16_t)startColor.getG() + (greenDiff * i / steps);
blueValue = (int16_t)startColor.getB() + (blueDiff * i / steps);
sprintf(rgbString, "%i,%i,%i", redValue, greenValue, blueValue);
Spark.publish("rgb", rgbString);
for (uint16_t i = 0; i < strip.numPixels(); i++) {
strip.setPixelColor(i, strip.Color(redValue, greenValue, blueValue));
}
delay(_delay);
}
delay(_delay);
for (uint16_t i = 0; i < strip.numPixels(); i++) {
strip.setPixelColor(i, strip.Color(endColor.getR(), endColor.getG(), endColor.getB()));
}
delay(_delay);
endColor = MotiColor(startColor.getR(), startColor.getG(), startColor.getB());
return 1;
}
I am seeing the published results correctly:
This is from OFF (0,0,0) -> RED (255,0,0) -> GREEN (0,255,0).
It works fine when I publish the results back to a web console via the Spark.publish() event, however the actual Neopixel LED's don't fade from colour to colour as expected. They just change from colour to colour instead of fading nicely between themselves.
I'm just wondering where I'm going wrong or how I can improve my code so that I actually see the fading in real time.
You have to call strip.show() in your for loop, like so:
for (int16_t i = steps; i >= 0; i--) {
redValue = (int16_t)startColor.getR() + (redDiff * i / steps);
greenValue = (int16_t)startColor.getG() + (greenDiff * i / steps);
blueValue = (int16_t)startColor.getB() + (blueDiff * i / steps);
sprintf(rgbString, "%i,%i,%i", redValue, greenValue, blueValue);
Spark.publish("rgb", rgbString);
for (uint16_t i = 0; i < strip.numPixels(); i++) {
strip.setPixelColor(i, strip.Color(redValue, greenValue, blueValue));
}
// !!! Without this, you'll only see the result the next time you call
// tinkerSetColor() !!!
strip.show();
delay(_delay);
}
To understand what's happening, you can look at the NeoPixel library source. You'll see that strip.setPixelColor() only stores the RGB value in memory (think of it as a drawing buffer, so that you can update the whole strip at once, which makes sense if you look at how the controller chips work). Calling strip.show() causes the routine that will push the values out to each pixel in serial to run.

How to move an entity with a mouse click?

Ok i now manage to figure out the problem but now another issue appear, my robot seem to move on its own to another point which i have no idea where its from. Here my code
His code make this robot move to the location i click on the terrain.
bool DemoApp::nextLocation(void){
mDestination = mtoward;
mRobotDir = mDestination - mRobotNode[0]->getPosition();
mDistance = mRobotDir.normalise();
return true;
}
bool DemoApp::frameRenderingQueued(const Ogre::FrameEvent& evt)
{
if (mRobotDir == Ogre::Vector3::ZERO) {
if (nextLocation()) {
// Set walking animation
mAnimationState = mRobot[0]->getAnimationState("Walk");
mAnimationState->setLoop(true);
mAnimationState->setEnabled(true);
}//if
}else{
Ogre::Real move = mWalkSpeed * evt.timeSinceLastFrame;
mDistance -= move;
if (mDistance <= 0.0f){
mRobotNode[0]->setPosition(mDestination);
mRobotDir = Ogre::Vector3::ZERO;
// Set animation based on if the robot has another point to walk to.
if (!nextLocation()){
// Set Idle animation
mAnimationState = mRobot[0]->getAnimationState("Idle");
mAnimationState->setLoop(true);
mAnimationState->setEnabled(true);
}else{
// Rotation Code will go here later
Ogre::Vector3 src = mRobotNode[0]->getOrientation() * Ogre::Vector3::UNIT_X;
if ((1.0f + src.dotProduct(mRobotDir)) < 0.0001f) {
mRobotNode[0]->yaw(Ogre::Degree(180));
}else{
Ogre::Quaternion quat = src.getRotationTo(mRobotDir);
mRobotNode[0]->rotate(quat);
} // else
}//else
}else{
mRobotNode[0]->translate(mRobotDir * move);
} // else
} // if
mAnimationState->addTime(evt.timeSinceLastFrame);
}
Here is the raycast code for my mouse click
Ogre::Terrain* pTerrain = mTerrainGroup->getTerrain(0, 0);
Ogre::Viewport* vp = this->mWindow->getViewport(0);
Ogre::Ray mouseRay = mCamera->getCameraToViewportRay(static_cast<float>(mMouse->getMouseState().X.abs)/mMouse->getMouseState().width, static_cast<float>(mMouse->getMouseState().Y.abs)/mMouse->getMouseState().height);
std::pair <bool, Ogre::Vector3> result;
result = pTerrain->rayIntersects(mouseRay, true, 0);
if (result.first = true)
{
mtoward = result.second - mRobotNode[0]->_getDerivedPosition();
mRobotNode[0]->translate(mtoward, Ogre::Node::TS_LOCAL);
}

Prevent moving a sprite onto another sprite

I have some sprites (2d-boxes) of the same type stored in a formation vector. Now i want to move them around with the mouse, that works well. But the code should prevent the player to move one sprite onto another already existing sprite of the vector.
My solution is quite ugly and does not work. Whenever a sprite is moved around, i test with the spriteoverlap function if the sprite is moved onto another. The Problem:
Whenever the sprite is directly close to the it stops moving, which is what wanted.
But i can't move it anymore afterwards because the overlapfunction sets the bool always to false.
while (App.pollEvent(Event))
{
//Moving the playerbuttons on the formation screen
for (size_t k = 0; k < formation.size(); k++)
{
bool drag_onto_otherplayer = false;
if (isMouseOver(formation[k], App) == true)
{
//The next loop tests if the sprite being moved with the mouse overlaps with another sprite from the formation vector
for (size_t j = 0; j < formation.size(); j++)
{
if (spriteOverlap(formation[j], formation[k], App) == true && k!=j)
{
std::cout << drag_onto_otherplayer << std::endl;
drag_onto_otherplayer = true;
std::cout << drag_onto_otherplayer <<std::endl;
}
if (drag_onto_otherplayer == false)
//(If the sprite does not overlap getting the new sprite position from the mouseposition)
{
Mouseposition =sf::Vector2f(sf::Mouse::getPosition(App));
Mouseposition.x = Mouseposition.x - formation[k].getLocalBounds().width / 2;
Mouseposition.y = Mouseposition.y - formation[k].getLocalBounds().height / 2;
formation[k].setPosition(sf::Vector2f(Mouseposition));
Formation_playernames.clear();
Formation_playerinformation.clear();
Formation_Playernames(Font, Formation_playernames, formation, playerlist);
Formation_Playerinformation(Font, Formation_playerinformation, formation, playerlist);
}
So the problem are my loops and the bool test i guess, but i don't know how to solve it.
Any ideas ?
Here is my spriteoverlap function:
bool spriteOverlap(sf::Sprite &sprite1, sf::Sprite &sprite2, sf::RenderWindow &App)
{
float x_min1 = sprite1.getPosition().x;
float x_max1 = sprite1.getPosition().x + sprite1.getLocalBounds().width;
float y_min1 = sprite1.getPosition().y;
float y_max1 = sprite1.getPosition().y + sprite1.getLocalBounds().height;
float x_min2 = sprite2.getPosition().x;
float x_max2 = sprite2.getPosition().x + sprite2.getLocalBounds().width;
float y_min2 = sprite2.getPosition().y;
float y_max2 = sprite2.getPosition().y + sprite2.getLocalBounds().height;
if (x_min1 > x_max2 | x_max1 < x_min2 | y_min1 > y_max2 | y_max1 < y_max2)
return false;
else
return true;
};
And my isMouseover function:
bool isMouseOver(sf::Sprite &sprite, sf::RenderWindow &App)
{
float pos_x = sprite.getPosition().x;
float pos_y = sprite.getPosition().y;
if (sf::Mouse::getPosition(App).x > pos_x && sf::Mouse::getPosition(App).x < pos_x+sprite.getLocalBounds().width &&
sf::Mouse::getPosition(App).y >pos_y && sf::Mouse::getPosition(App).y < pos_y + sprite.getLocalBounds().height)
{
return true;
}
else
return false;
};
Check for collision is already included somewhat in sfml:
bool spriteOverlap(sf::Sprite& sprite1, sf::Sprite& sprite2) // possibly const, dunno
{
return sprite1.getGlobalBounds().intersects(sprite2.getGlobalBounds());
}
Generally try this: Only move, if the position of the next frame is valid. This prevents objects being stuck, because you already moved them into an invalid position, thus preventing any further movement
edit:
//untested
bool spritesWillOverlap(sf::Sprite& sprite1, sf::Sprite& sprite2, sf::Vector2f vel)
{
top1 = sprite1.getGobalBounds().top + vel.y;
left1 = sprite1.getGlobalBounds().left + vel.x;
right1 = left1 + sprite1.getGlobalBounds().width;
bottom1 = top1 + sprite1.getGlobalBounds().height;
top2 = sprite2.getGobalBounds().top + vel.y;
left2 = sprite2.getGlobalBounds().left + vel.x;
right2 = left2 + sprite1.getGlobalBounds().width;
bottom2 = top2 + sprite1.getGlobalBounds().height;
sf::FloatRect rect1(top1, left1, right1 - left1, bottom1 - top1);
sf::FloatRect rect2(top2, left2, right2 - left2, bottom2 - top2);
return rect1.intersects(rect2);
}
vel: velocity -> an object is moved by this 2D vector every frame
If the concept of "frames" is unfamiliar, read up on framerates/fixed framerate and/or timestep. here's an example article to get started: Fix Your Timestep!

3D picking lwjgl

I have written some code to preform 3D picking that for some reason dosn't work entirely correct! (Im using LWJGL just so you know.)
This is how the code looks like:
if(Mouse.getEventButton() == 1) {
if (!Mouse.getEventButtonState()) {
Camera.get().generateViewMatrix();
float screenSpaceX = ((Mouse.getX()/800f/2f)-1.0f)*Camera.get().getAspectRatio();
float screenSpaceY = 1.0f-(2*((600-Mouse.getY())/600f));
float displacementRate = (float)Math.tan(Camera.get().getFovy()/2);
screenSpaceX *= displacementRate;
screenSpaceY *= displacementRate;
Vector4f cameraSpaceNear = new Vector4f((float) (screenSpaceX * Camera.get().getNear()), (float) (screenSpaceY * Camera.get().getNear()), (float) (-Camera.get().getNear()), 1);
Vector4f cameraSpaceFar = new Vector4f((float) (screenSpaceX * Camera.get().getFar()), (float) (screenSpaceY * Camera.get().getFar()), (float) (-Camera.get().getFar()), 1);
Matrix4f tmpView = new Matrix4f();
Camera.get().getViewMatrix().transpose(tmpView);
Matrix4f invertedViewMatrix = (Matrix4f)tmpView.invert();
Vector4f worldSpaceNear = new Vector4f();
Matrix4f.transform(invertedViewMatrix, cameraSpaceNear, worldSpaceNear);
Vector4f worldSpaceFar = new Vector4f();
Matrix4f.transform(invertedViewMatrix, cameraSpaceFar, worldSpaceFar);
Vector3f rayPosition = new Vector3f(worldSpaceNear.x, worldSpaceNear.y, worldSpaceNear.z);
Vector3f rayDirection = new Vector3f(worldSpaceFar.x - worldSpaceNear.x, worldSpaceFar.y - worldSpaceNear.y, worldSpaceFar.z - worldSpaceNear.z);
rayDirection.normalise();
Ray clickRay = new Ray(rayPosition, rayDirection);
Vector tMin = new Vector(), tMax = new Vector(), tempPoint;
float largestEnteringValue, smallestExitingValue, temp, closestEnteringValue = Camera.get().getFar()+0.1f;
Drawable closestDrawableHit = null;
for(Drawable d : this.worldModel.getDrawableThings()) {
// Calcualte AABB for each object... needs to be moved later...
firstVertex = true;
for(Surface surface : d.getSurfaces()) {
for(Vertex v : surface.getVertices()) {
worldPosition.x = (v.x+d.getPosition().x)*d.getScale().x;
worldPosition.y = (v.y+d.getPosition().y)*d.getScale().y;
worldPosition.z = (v.z+d.getPosition().z)*d.getScale().z;
worldPosition = worldPosition.rotate(d.getRotation());
if (firstVertex) {
maxX = worldPosition.x; maxY = worldPosition.y; maxZ = worldPosition.z;
minX = worldPosition.x; minY = worldPosition.y; minZ = worldPosition.z;
firstVertex = false;
} else {
if (worldPosition.x > maxX) {
maxX = worldPosition.x;
}
if (worldPosition.x < minX) {
minX = worldPosition.x;
}
if (worldPosition.y > maxY) {
maxY = worldPosition.y;
}
if (worldPosition.y < minY) {
minY = worldPosition.y;
}
if (worldPosition.z > maxZ) {
maxZ = worldPosition.z;
}
if (worldPosition.z < minZ) {
minZ = worldPosition.z;
}
}
}
}
// ray/slabs intersection test...
// clickRay.getOrigin().x + clickRay.getDirection().x * f = minX
// clickRay.getOrigin().x - minX = -clickRay.getDirection().x * f
// clickRay.getOrigin().x/-clickRay.getDirection().x - minX/-clickRay.getDirection().x = f
// -clickRay.getOrigin().x/clickRay.getDirection().x + minX/clickRay.getDirection().x = f
largestEnteringValue = -clickRay.getOrigin().x/clickRay.getDirection().x + minX/clickRay.getDirection().x;
temp = -clickRay.getOrigin().y/clickRay.getDirection().y + minY/clickRay.getDirection().y;
if(largestEnteringValue < temp) {
largestEnteringValue = temp;
}
temp = -clickRay.getOrigin().z/clickRay.getDirection().z + minZ/clickRay.getDirection().z;
if(largestEnteringValue < temp) {
largestEnteringValue = temp;
}
smallestExitingValue = -clickRay.getOrigin().x/clickRay.getDirection().x + maxX/clickRay.getDirection().x;
temp = -clickRay.getOrigin().y/clickRay.getDirection().y + maxY/clickRay.getDirection().y;
if(smallestExitingValue > temp) {
smallestExitingValue = temp;
}
temp = -clickRay.getOrigin().z/clickRay.getDirection().z + maxZ/clickRay.getDirection().z;
if(smallestExitingValue < temp) {
smallestExitingValue = temp;
}
if(largestEnteringValue > smallestExitingValue) {
//System.out.println("Miss!");
} else {
if (largestEnteringValue < closestEnteringValue) {
closestEnteringValue = largestEnteringValue;
closestDrawableHit = d;
}
}
}
if(closestDrawableHit != null) {
System.out.println("Hit at: (" + clickRay.setDistance(closestEnteringValue).x + ", " + clickRay.getCurrentPosition().y + ", " + clickRay.getCurrentPosition().z);
this.worldModel.removeDrawableThing(closestDrawableHit);
}
}
}
I just don't understand what's wrong, the ray are shooting and i do hit stuff that gets removed but the result of the ray are verry strange it sometimes removes the thing im clicking at, sometimes it removes things thats not even close to what im clicking at, and sometimes it removes nothing at all.
Edit:
Okay so i have continued searching for errors and by debugging the ray (by painting smal dots where it travles) i can now se that there is something oviously wrong with the ray that im sending out... it has its origin near the world center and always shots to the same position no matter where i direct my camera...
My initial toughts is that there might be some error in the way i calculate my viewMatrix (since it's not possible to get the viewmatrix from the glulookat method in lwjgl; I have to build it my self and I guess thats where the problem is at)...
Edit2:
This is how i calculate it currently:
private double[][] viewMatrixDouble = {{0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,1}};
public Vector getCameraDirectionVector() {
Vector actualEye = this.getActualEyePosition();
return new Vector(lookAt.x-actualEye.x, lookAt.y-actualEye.y, lookAt.z-actualEye.z);
}
public Vector getActualEyePosition() {
return eye.rotate(this.getRotation());
}
public void generateViewMatrix() {
Vector cameraDirectionVector = getCameraDirectionVector().normalize();
Vector side = Vector.cross(cameraDirectionVector, this.upVector).normalize();
Vector up = Vector.cross(side, cameraDirectionVector);
viewMatrixDouble[0][0] = side.x; viewMatrixDouble[0][1] = up.x; viewMatrixDouble[0][2] = -cameraDirectionVector.x;
viewMatrixDouble[1][0] = side.y; viewMatrixDouble[1][1] = up.y; viewMatrixDouble[1][2] = -cameraDirectionVector.y;
viewMatrixDouble[2][0] = side.z; viewMatrixDouble[2][1] = up.z; viewMatrixDouble[2][2] = -cameraDirectionVector.z;
/*
Vector actualEyePosition = this.getActualEyePosition();
Vector zaxis = new Vector(this.lookAt.x - actualEyePosition.x, this.lookAt.y - actualEyePosition.y, this.lookAt.z - actualEyePosition.z).normalize();
Vector xaxis = Vector.cross(upVector, zaxis).normalize();
Vector yaxis = Vector.cross(zaxis, xaxis);
viewMatrixDouble[0][0] = xaxis.x; viewMatrixDouble[0][1] = yaxis.x; viewMatrixDouble[0][2] = zaxis.x;
viewMatrixDouble[1][0] = xaxis.y; viewMatrixDouble[1][1] = yaxis.y; viewMatrixDouble[1][2] = zaxis.y;
viewMatrixDouble[2][0] = xaxis.z; viewMatrixDouble[2][1] = yaxis.z; viewMatrixDouble[2][2] = zaxis.z;
viewMatrixDouble[3][0] = -Vector.dot(xaxis, actualEyePosition); viewMatrixDouble[3][1] =-Vector.dot(yaxis, actualEyePosition); viewMatrixDouble[3][2] = -Vector.dot(zaxis, actualEyePosition);
*/
viewMatrix = new Matrix4f();
viewMatrix.load(getViewMatrixAsFloatBuffer());
}
Would be verry greatfull if anyone could verify if this is wrong or right, and if it's wrong; supply me with the right way of doing it...
I have read alot of threads and documentations about this but i can't seam to wrapp my head around it...
I just don't understand what's wrong, the ray are shooting and i do hit stuff that gets removed but things are not disappearing where i press on the screen.
OpenGL is not a scene graph, it's a drawing library. So after removing something from your internal representation you must redraw the scene. And your code is missing some call to a function that triggers a redraw.
Okay so i finaly solved it with the help from the guys at gamedev and a friend, here is a link to the answer where i have posted the code!