Creating a scrolling background (Scrolling from top to bottom) - c++

I'm having trouble creating a scrolling background. I'm literally trying to translate the C# I did two years ago, in to C++ and as a 'newb' (as it were), I'm having trouble.
Below are the variables and objects I am using.
//ScrollingBackground Inits from the Contructor/Main Method
_screenHeight = Graphics::GetViewportHeight();
_screenWidth = Graphics::GetViewportWidth();
//ScrollingBackground Content from the Load Content Method
_backgroundPosition = new Vector2(_screenWidth / 2, _screenHeight / 2);
_origin = new Vector2(_backgroundTexture->GetHeight() / 2, 0);
_textureSize = new Vector2(0, _backgroundTexture->GetHeight());
_backgroundTexture->Load("background.dds", false);
This is the Method that I'm trying to make where the scrolling occurs.
void Player::Scrolling(float deltaX)
{
//This is where the scrolling happens
_backgroundPosition->X += deltaX;
_backgroundPosition->X = _backgroundPosition->X % _textureSize->Y;
}
Still relatively new to this so please forgive me if I'm vague or sound like I don't have a clue what I'm talking about.
Many thanks,
Ryan.

You cannot use % operator on floats. The following fixes your problem, but will not give a true remainder. If precision is not an issue, you can use the following code and not see a huge issue with the scrolling background.
void Player::Scrolling(float deltaX)
{
//This is where the scrolling happens
_backgroundPosition->X += deltaX;
_backgroundPosition->X = static_cast<int>(_backgroundPosition->X) % static_cast<int>(_textureSize->Y);
}

Related

Programmatically aligning a created TButton right next to an adjacent TComponent in an FMX Frame

Referring to the picture, I would like to align a dynamically created TButton at runtime right next to a BindNavigator.
TButton *Add_But;
Add_But = new TButton(this);
Add_But->Visible = true;
Add_But->Text = "Add";
//Add_But->Position->X = 300;
//Add_But->Position->Y = 350;
Add_But->Parent=Form1->BindNavigator1;
Form1->Frame1->AddObject(Form1->StringGridBindSourceDB1);
Form1->Frame1->AddObject(Form1->BindNavigator1);
Form1->Frame1->AddObject(Add_But);
Add_But->Align=Fmx::Types::TAlignLayout::Right;
If I execute the above code, the Add_But button would align next to BindNavigator enclosed portion of the area between the last three buttons starting from the refresh button. Positioning Add_But using X,Y is not the ideal solution as I would like the Add_But to space out by certain margin padding just by using the Align property.
How to programmatically construct a TBounds margin object to resolve the issue?
Not Optimum solution using Two FlowLayout ,Believe TGridPanelLayout is much better choice , quite difficult to code correctly at runtime on cell position placement as the Main Frame is Just An Empty container refresh to hold Any child item based on selection
TFlowLayout *tlayout=new TFlowLayout(this);
tlayout->AddObject(Form1->StringGridBindSourceDB1);
TFlowLayout *tlayout1=new TFlowLayout(this);
// approximate the size of the TGrid
tlayout1->Width=600;
tlayout1->AddObject(Form1->BindNavigator1);
Add_But->Margins->Left = 10;
tlayout1->AddObject(Add_But);
tlayout->AddObject(tlayout1);
Form1->Frame1->AddObject(tlayout);
I have not written any apps in FMX but I saw no reason why you could not simply drop a TPanel on your FMX form then drop a TBindNavigator onto the TPanel unless there is a reason it can't be done this way, just trying to help.
This code works fine in Builder 10.3 on FMX Form
TButton *b = new TButton(TPanel1);
b->Parent = TPanel1;
b->Visible = true;
b->Position->X = TBindNavigator1->Width + 25;
b->Position->Y = TPanel1->Height / 2 - b->Height / 2;
b->Width = b->Width * 2;
b->Text = "Runtime Button";
How it looks when you run the code

Figuring out best solution for a Maze solver, with animated output

Abstract
My ultimate goal is to use Fltk to take user inputs of pixels, display a generated maze (either my own, or fetch it from the website mentioned in the details), and then show the animated solution.
This is what i've managed so far:
https://giant.gfycat.com/VioletWelloffHatchetfish.webm
Details
I'm in my first c++/algorithm class of a bachelors in CE.
As we've been learning about graphs, dijkstra etc. the last weeks i decided after watching Computerphile's video about Maze solving, to try to put the theory into "practice".
At first i wanted to output a maze from this site, http://hereandabove.com/maze/mazeorig.form.html, with the plotted solution. I chose that walls and paths should be 1x1 pixel, to make it easier to make into a 2D-vector, and then a graph.
This went well, and my program outputs a solved .png file, using dijkstra to find the shortest path.
I then wanted to put the entire solution in an animated gif.
This also works well. For each pixel it colors green/yellow, it passes an RGBA-vector to a gif-library, and in the end i end up with an animated step by step solution.
I also for each RGBA-vector passed to the gif-library, scale it up first, using this function:
//Both the buffer and resized buffer are member variables, and for each //plotted pixel in the path it updates 'buffer', and in this function makes a //larger version of it to 'resized_buffer'
// HEIGHT and WIDTH are the original size
// nHeight and nWidth are the new size.
bool Maze_IMG::resample(int nWidth, int nHeight)
{
if (buffer.size() == 0) return false;
resized_buffer.clear();
for (int i = 0; i < nWidth * nHeight * 4; i++) resized_buffer.push_back(-1);
double scaleWidth = (double)nWidth / (double)WIDTH;
double scaleHeight = (double)nHeight / (double)HEIGHT;
for (int cy = 0; cy < nHeight; cy++)
{
for (int cx = 0; cx < nWidth; cx++)
{
int pixel = (cy * (nWidth * 4)) + (cx * 4);
int nearestMatch = (((int)(cy / scaleHeight) * (WIDTH * 4)) + ((int)(cx / scaleWidth) * 4));
resized_buffer[pixel] = buffer[nearestMatch];
resized_buffer[pixel + 1] = buffer[nearestMatch + 1];
resized_buffer[pixel + 2] = buffer[nearestMatch + 2];
resized_buffer[pixel + 3] = buffer[nearestMatch + 3];
}
}
return true;
}
Problems
The problem is that it takes a looong time to do this while scaling them up, even with "small" mazes at 50x50 pixels, when trying to scale them to say 300x300. I've spent a lot of time to make code as efficient and fast as possible, but after i added the scaling, stuff that used to take 10 minutes, now takes hours.
In fltk i use the Fl_Anim_Gif-library to display animated gifs, but it wont load the maze gifs that has been scaled up (still troubleshooting this).
My real questions
Is it possible to improve the scaling function, so that it does not take forever? Or is this a totally wrong approach?
Is it a stupid idea to try to display it as a gif in fltk, would it be easier to just draw it directly in fltk, or should i rather try to display the images one after another i fltk?
I'm just familiarizing myself with fltk. Would it be easier now to use something like Qt instead. Would that be more beneficial in the long run as far as learning a GUI-library goes?
I'm mainly doing this for learning, and to start building some sort of portfolio for when i graduate. Is it beneficial at all to make a gui for this, or is this a waste of time?
Any thoughts or input would be greatly appreciated.
Whatever graphics package you use, the performance will be similar. It depends on how you handle the internals. For instance,
If you write it to a buffer and BLT it to the screen, it would be faster than writing to the screen directly.
If you only BLT on the paint event, it would be faster than forcing and update every time the screen data changes.
If you preallocate the buffers then the system does not have to keep on reallocating whenever the buffer space runs out.
Assuming that the space is preallocated, it can be written to without clearing first. Every cell it going to be written to so no need to clear, allocate and and reallocate.

Qt - Scrolling the visible area of the chart

I'm beginner at Qt, and currently learning from Mastering Qt5 book and I got stuck. There is a piece of code
// Global variables
const int CHART_X_RANGE_COUNT = 50;
const int CHART_X_RANGE_MAX = CHART_X_RANGE_COUNT - 1;
void MemoryWidget::updateSeries()
{
double memoryUsed = SysInfo::instance().memoryUsed(); // retrieve the latest memory percentage used
mSeries->append(mPointPositionX++, memoryUsed);
if (mSeries->count() > CHART_X_RANGE_COUNT)
{
QChart *chart = chartView().chart();
chart->scroll(chart->plotArea().width() / CHART_X_RANGE_MAX, 0);
mSeries->remove(0);
}
}
I only don't understand the following piece of code
chart->scroll(chart->plotArea().width() / CHART_X_RANGE_MAX, 0);
If I want to scroll to the latest point on the X axis and nothing on Y, then why i have to do this:
chart->plotArea().width() / CHART_X_RANGE_MAX
and can't do just this:
chart->scroll(1, 0);
According to docs scroll Scrolls the visible area of the chart by the distance specified by dx and dy.
and why chart->scroll(chart->plotArea().width() / CHART_X_RANGE_MAX, 0);
because mSeries->append(mPointPositionX++, memoryUsed); is called periodically and after a while a full window of xaxis will be filled and after each full window fills plot will scroll, if you use chart->scroll(1, 0); each time updateSeries() called you scroll window to next and always showing last point,
In general this plot wants to scroll per CHART_X_RANGE_MAX.

Smooth (Inertial) Scrolling with SDL2?

I am building SDL2 applications for macOS using C++. I need some "basic" scrolling for an app (like a web browser). I achieve that using the SDL_MouseWheel event, which gives me a fully functional "windows-like" scrolling. I am using a Macbook Pro and I want to bring the trackpad's functionality in.
Simply, I am asking for a better scrolling algorithm (Macbook's trackpad scrolling, inertial scrolling)
I know about the SDL_MultiGesture event, but I don't really know how to put things together to achieve the result I want.
I ran into the same issue, and it turns out that SDL opts out of momentum scroll events by turning off the AppleMomentumScrollSupported default in the user defaults system.
You can turn this back on in your application with the following bit of Objective-C++, and your SDL_MouseWheel events will become smoothed.
NSDictionary *appDefaults = [[NSDictionary alloc] initWithObjectsAndKeys:
[NSNumber numberWithBool:YES], #"AppleMomentumScrollSupported",
nil];
[[NSUserDefaults standardUserDefaults] registerDefaults:appDefaults];
[appDefaults release];
Okay, here's the answer to the problem.
First of all, you will have to do it manually.
I also assume that you know SDL2 and C++.
*Note: I'm doing scrolling only for Y-Axis (you can do it for both if you want).
Firstly we will need some variables:
int scrolling; // flag (scrolling or not)
int scroll_sensitivity = 40; // how fast we want to scroll
double scroll_Y = 0; // current scrolling amount (on Y-Axis)
double scroll_acceleration; // scrolling speed
double scroll_friction = 0.001; // how fast we decelerate
double scroll_prev_pos; // previous event's position
After that you will need to handle the SDL_MultiGesture event:
case SDL_MULTIGESTURE:{
if(event.mgesture.numFingers == 2){
if(scrolling == 0){
scrolling = 1;
scroll_prev_pos = event.mgesture.y;
} else{
double dy = event.mgesture.y - scroll_prev_pos;
scroll_acceleration = dy * 40;
scroll_prev_pos = event.mgesture.y;
scrolling = 1;
}
}
break;
}
Also, we need to stop scrolling on SDL_FingerDown event:
case SDL_FINGERDOWN:{
scrolling = 0;
break;
}
Next, we want to update scroll_Y (put it in your "update" function):
if(scrolling){
if(scroll_acceleration > 0) scroll_acceleration -= scroll_friction;
if(scroll_acceleration < 0) scroll_acceleration += scroll_friction;
if(abs(scroll_acceleration) < 0.0005) scroll_acceleration = 0;
scroll_Y += scroll_sensitivity * scroll_acceleration;
// Here you have to set your scrolling bounds i.e. if(scroll_Y < 0) scroll_Y = 0;
}
Finally, we want to render according to our scroll values:
SDL_Rect rect = {some_x, some_y + scroll_Y, some_w, some_h};
SDL_RenderCopy(renderer, some_texture, NULL, &rect);
This is it!
I have a fully working app with the above code, so I'm 100% sure that this works as supposed. If you have any problems (because it's not actual code, it's more like an algorithm) contact me. As I mentioned before, I assume that you already know good enough SDL and C++, so I believe that you are able to understand the implementation.
Also, I know that this solution can become better, so if you have anything to add / change, just say it!
Have a nice day!
For some reason, #Aleski's answer doesn't work anymore. The new way to hack this feature back on is:
[[NSUserDefaults standardUserDefaults] setBool: YES
forKey: #"AppleMomentumScrollSupported"];

Stuck trying to implement touch and hold (bullet firing)? - cocos2d-x

I've been having a lot of trouble implementing a smooth and reliable touch-and-hold solution for firing bullet (sprites) - even after looking at other people's solutions.
The solution has to switch between touch-began, touch moved and touch ended seamlessly: always firing bullets at the touch location until the finger is released. At the moment I have many problems with reliability and stability with every case but touchmoved, which works fine.
The exact issue is around half the time a finger is held down (touchBegan + scheduler) the bullets appear but disappear a second later but other times they move towards the touch perfectly - something is deleting them and i don't have much experience with schedulers or actions to know what.
Heres my code, I've used 2 different firing methods: one scheduled to run every 0.05 seconds after touchBegan, and one triggered every time touchMoved is detected. The touchMoved one works fine, but getting it to work with the unreliable touchBegan one is trouble. The really annoying part is even if I remove the touch part and just schedule sprites to appear and run scheduled actions non-stop from init, the same reliability problem happens (disappearing/deletion). Maybe I dont understand getting schedulers and actions to play nice, or maybe theres a better touch and hold method? Thanks in advance for any help.
bool HelloWorld::init()
{
... miscellaneous sprite creation
this->schedule(schedule_selector(HelloWorld::fireBullets), 0.05);
}
void HelloWorld::ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent)
{
CCTouch* touch = (CCTouch*)( pTouches->anyObject() ); // get single-touch as opposed to multitouch
touchLocation = CCDirector::sharedDirector()->convertToGL(touch->getLocationInView());
if (touchLocation.x > 400)
{
float dX = touchLocation.x - gun->getPosition().x;
float dY = touchLocation.y - gun->getPosition().y;
touchAngle = atan2(dY, dX);
gun->setRotation(-CC_RADIANS_TO_DEGREES(touchAngle));
cursor->setPosition(touchLocation);
screenHeld = true;
}
}
void HelloWorld::ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent)
{
CCTouch* touch = (CCTouch*)( pTouches->anyObject() ); // for single-touch as opposed to multitouch
touchLocation = CCDirector::sharedDirector()->convertToGL(touch->getLocationInView());
if (touchLocation.x > 400)
{
float dX = touchLocation.x - gun->getPosition().x;
float dY = touchLocation.y - gun->getPosition().y;
float angle = atan2(dY, dX);
gun->setRotation(-CC_RADIANS_TO_DEGREES(angle));
cursor->setPosition(touchLocation);
screenHeld = false; //not technically true but touchMoved bullet firing works differently (not scheduled, every movement instead)
if (getTimeTick() - lastBulletFire > 50) //getTickTime is simple get system time method, works fine
{
fireBullet(angle);
}
}
}
//this is for touchBegan and has issues, scheduled to run every 50ms touch-held
void HelloWorld::fireBullets(CCTime dt)
{
if (screenHeld)
{
CCSprite* bullet = CCSprite::create("bullet.png");
bullet->setPosition(ccp(gun->getPosition().x, gun->getPosition().y));
bullet->setRotation(-CC_RADIANS_TO_DEGREES(touchAngle));
//send bullet towards touchlocation
bullet->runAction(CCSequence::create(CCMoveBy::create(1.5f, ccp(800 * cos(touchAngle), 800 * sin(touchAngle))), NULL));
this->addChild(bullet, 5);
}
}
//this is for touchMoved and works fine, everytime finger is moved bullet fired
void HelloWorld::fireBullet(float angle)
{
CCSprite* bullet = CCSprite::create("bullet.png");
bullet->setPosition(ccp(gun->getPosition().x, gun->getPosition().y)); //add a random spread to the y value (or maybe the y-value of the destination)
this->addChild(bullet, 5);
bullet->setRotation(-CC_RADIANS_TO_DEGREES(angle));
bullet->runAction(CCSequence::create(CCMoveBy::create(1.5f, ccp(800 * cos(angle), 800 * sin(angle))), NULL));
lastBulletFire = getTimeTick();
}
Found the solution, it wasn't anything to do with actions/schedulers but the fact that I wasn't calling retain() on the bullets. Normally I'd manage C++ memory manually but this hybrid style threw my off