Making a rectangle turn on an angle and change orientation

Hello, I am trying to make a rectangle move like a car. I want the red rectangle to move the same way the three green circles are moving.

openframeworks

In the first picture the three circles are aligned with the rectangle. In the second picture the three circles have changed orientation and turned. The rectangle has moved but It hasn’t changed orientation or turned like the circles did. I want the rectangle to move like the circles are moving. From my code the rectangle is suppose to turn in the direction of carHeading on the angle steerAngle (which the circles are doing). My idea is that I draw the rectangle with the angle carHeading or I use ofNode to make the rectangle a child of the circles, however I do not know how to either of these things. Any help would be much appreciated.

Code:

//ofApp.h

#pragma once

#include "ofMain.h"


class ofApp : public ofBaseApp {

public:
	void setup();
	void update();
	void draw();

	void keyPressed(int key);
	void keyReleased(int key);
	void mouseMoved(int x, int y);
	void mouseDragged(int x, int y, int button);
	void mousePressed(int x, int y, int button);
	void mouseReleased(int x, int y, int button);
	void mouseEntered(int x, int y);
	void mouseExited(int x, int y);
	void windowResized(int w, int h);
	void dragEvent(ofDragInfo dragInfo);
	void gotMessage(ofMessage msg);

	ofVec2f backWheel;
	ofVec2f frontWheel;
	ofVec2f carLocation;
	float wheelBase;
	float steerAngle;
	float carSpeed;
	float carHeading;
	float turn;

};

// ofApp.cpp

#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup()
{
	ofSetFrameRate(60);
	carLocation.set(100, 100);
	carHeading = 0;
	wheelBase = 90;
	carSpeed = 0;
	
}


//--------------------------------------------------------------
void ofApp::update()
{
	//position of front wheel
	frontWheel = carLocation + wheelBase / 2 * ofVec2f(cos(carHeading), sin(carHeading));
	
	//position of back wheel
	backWheel = carLocation - wheelBase / 2 * ofVec2f(cos(carHeading), sin(carHeading));

	//movement of front wheel
	frontWheel += carSpeed * 1/60 * ofVec2f(cos(carHeading + steerAngle), sin(carHeading + steerAngle));

	//movement of back wheel
	backWheel += carSpeed * 1/60 * ofVec2f(cos(carHeading), sin(carHeading));

	//new car location
	carLocation = (frontWheel + backWheel) / 2;

	//new car heading
	carHeading = atan2(frontWheel.y - backWheel.y, frontWheel.x - backWheel.x);
	
}

//--------------------------------------------------------------
void ofApp::draw()
{
	ofFill();
	ofSetColor(255, 0, 0);
	ofSetRectMode(OF_RECTMODE_CENTER);
	ofDrawRectangle(carLocation, 100, 60);
	
	ofFill();
	ofSetColor(0, 255, 0);
	ofDrawCircle(carLocation, 10);
	ofDrawCircle(frontWheel, 10);
	ofDrawCircle(backWheel, 10);
	
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key)
{
	if (key == 'd') //right
	{
		steerAngle = +15 * 180 / PI;
	}
	if (key == 'a')//left
	{
		steerAngle = -15 * 180 / PI;
	}
	if (key == 'w')//accelerate
	{
		carSpeed = (1+ carSpeed)* 5.0;
	}
	if (key == 's') //slow down
	{
		carSpeed = carSpeed / 5.0;
	}
	if (key == 'f') //go straghit
	{
		steerAngle = 0;
	}
}

//--------------------------------------------------------------
void ofApp::keyReleased(int key)
{

}

//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y ){

}

//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button)
{

}

//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button)
{
	
}

//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button)
{

}

//--------------------------------------------------------------
void ofApp::mouseEntered(int x, int y){

}

//--------------------------------------------------------------
void ofApp::mouseExited(int x, int y){

}

//--------------------------------------------------------------
void ofApp::windowResized(int w, int h){

}

//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg){

}

//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo){ 

}

//main.cpp

#include "ofMain.h"
#include "ofApp.h"

//========================================================================
int main( ){
	ofSetupOpenGL(1024,768,OF_WINDOW);			// <-------- setup the GL context

	// this kicks off the running of my app
	// can be OF_WINDOW or OF_FULLSCREEN
	// pass in width and height too:
	ofRunApp(new ofApp());

}

a simple way to do this is using

ofPushMatrix();

/// transformations

ofpopMatrix();

https://openframeworks.cc/documentation/graphics/ofGraphics/#show_ofPushMatrix

what this allows you to do is basically;
freeze where everything is
move the origin or centre of the screen (to the centre point of your car)
perform a simple transformation on an object (rotate your car to its heading)
unfreeze the screen and return everything to where it was before the transformation

Thanks for the answer. Your solution makes sense, I think for whatever reason through my program won’t read in carHeading as the rotation angle for the rectangle. I gave up on the rectangle and decided to just draw two lines that connected the backWheel, carLocation, and frontWheel then made the stroke width of the line 40 so that it resembled a rectangle. This worked and now the ‘car’ is moving like its suppose to.

that’s good news that you got something working :smiley:

the carheading calculation is giving odd results (my brain is tired so won’t find the right answer right now)

 carHeading = atan2(frontWheel.y - backWheel.y, frontWheel.x - backWheel.x);

ie - debugging with

    cout << "car heading" << carHeading << endl;

gives values of 0- 3.1 in the 0-180 degree rotation (can some one put the correct rotation calculation in here ?)

if you alter your draw routine like this

void ofApp::draw(){
    ofFill();
    ofSetColor(255, 0, 0);
    ofSetRectMode(OF_RECTMODE_CENTER);

    /// this is the bit i changed
    ofPushMatrix();
    ofTranslate(carLocation);
    ofRotateDeg(60 * carHeading); // using *60 as a cludge to get a reasonable looking angle from the atan calculation....
    ofDrawRectangle(0,0 , 100, 60);  
    ofPopMatrix();
    ///

    ofFill();
    ofSetColor(0, 255, 0);
    ofDrawCircle(carLocation, 10);
    ofDrawCircle(frontWheel, 10);
    ofDrawCircle(backWheel, 10);
}

then the rectangle will follow the wheels at the right position and right rotation

I tried this and it works! I printed out the values to the console that were being given for frontWheel position and backWheel position then caculated the carHeading and I was also getting some weird answers. If its interest you here is the link to where I got the equations for the car movement from, it has the equation for the carHeading in it

Thanks again for taking time to answer.

One more thing, I think I figured out why the math was wrong. The carHeading function calculates the angle in radians, while anything OF is in degrees. The conversion factor between one radian and one degree is 57.29, which is very close to 60. Every time I was drawing the rotation I was drawing it in degrees, so when we multiplied it by the conversion factor it worked because we converted it back to radians. When I drew the circle with ofRotateRad(carHeading) it worked fine. I think you might have already figured this out though since you knew to multiply it by 60.

aha ! well spotted - yes radians // degrees !

with that change this should work just fine now -

1 Like