Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

alnite

paralax scrolling

This topic is 5159 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

no I am not talking about scrolling background, but they are similar in some ways. Suppose I have a 2D array like this:
01010
11010
11001
10101
01010
01100
 
Now I want to push the 3rd column downward, and it would result like this:
01 10
11010
11001
10001
01110
01000
  1
 
But instead of 1 getting pushed out, I want it to wrap back to the beginning of the column
01110
11010
11001
10001
01110
01000
 
And the same thing when pushing rows. So the element that gets pushed out will become index #0. I have thought some brute-force approach, but I just need to know if there is a better approach to this problem. Oh and the array wouldn''t contain only 0s and 1s, they can be anything, numbers objects, etc.

Share this post


Link to post
Share on other sites
Advertisement
Assuming C++, you could just use the std::rotate() function. Getting the columns right might take a custom iterator or the use of one of the specialized C++ matrix libraries. (Doesn''t MTL offer a column iterator? I can''t remember right now.)

Share this post


Link to post
Share on other sites
quote:
Original post by SiCrane
Assuming C++, you could just use the std::rotate() function. Getting the columns right might take a custom iterator or the use of one of the specialized C++ matrix libraries. (Doesn''t MTL offer a column iterator? I can''t remember right now.)
I don''t understand the forward iterator part. Does it have to be the iterators of a list or a vector, or can I simply put integer numbers? If I just pass the iterators, how is it going to know which array I want to rotate?

@flangazor:
Not sure what you mean by "a vector of circular buffers each with an offset." :/

Share this post


Link to post
Share on other sites
Forward iterator part? I didn''t mention forward iterators in my post. Anyways, maybe code is easier to follow than words:

#include <iostream>
#include <algorithm>

const int rows = 6;
const int cols = 5;

int init_array[rows][cols] = {
{ 0, 1, 0, 1, 0},
{ 1, 1, 0, 1, 0},
{ 1, 1, 0, 0, 1},
{ 1, 0, 1, 0, 1},
{ 0, 1, 0, 1, 0},
{ 0, 1, 1, 0, 0}
};

class Wrapper {
public:
Wrapper() {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
data_[i][j] = init_array[i][j];
}
}
}

class VIterator : public std::iterator<std::random_access_iterator_tag, int> {
public:
VIterator(int * ptr) : ptr_(ptr) {}
VIterator operator+(int rhs) const {
return VIterator(ptr_ + (rhs * cols));
}
VIterator operator-(int rhs) const {
return VIterator(ptr_ - (rhs * cols));
}
int operator-(const VIterator & rhs) const {
return ((ptr_ - rhs.ptr_) / cols);
}
int & operator*() { return *ptr_; }

bool operator!=(const VIterator & rhs) const {
return ptr_ != rhs.ptr_;
}
bool operator==(const VIterator & rhs) const {
return ptr_ == rhs.ptr_;
}

private:
int * ptr_;
};

VIterator VBegin(int c) {
return &(data_[0][c]);
}
VIterator VEnd(int c) {
return &(data_[rows][c]);
}

int * HBegin(int r) {
return &(data_[r][0]);
}
int * HEnd(int r) {
return &(data_[r][cols]);
}

std::ostream & display(std::ostream & out) const {
int i, j;
for (i = 0; i < rows; i++) {
for (j = 0; j < cols - 1; j++) {
out << data_[i][j] << ",";
}
out << data_[i][j] << std::endl;
}
return out;
}
private:
int data_[rows][cols];
};

std::ostream & operator<<(std::ostream & lhs, const Wrapper & rhs) {
return rhs.display(lhs);
}

int main(int, char **) {
Wrapper w;
std::cout << w << std::endl;

// rotate column 2 by 1.

std::rotate(w.VBegin(2), w.VBegin(2) + 1, w.VEnd(2));
std::cout << w << std::endl;

// rotate column 2 by 1 the other way.

std::rotate(w.VBegin(2), w.VEnd(2) - 1, w.VEnd(2));
std::cout << w << std::endl;

// rotate row 4 by 1

std::rotate(w.HBegin(4), w.HBegin(4) + 1, w.HEnd(4));
std::cout << w << std::endl;

// rotate row 3 by 2 the other way

std::rotate(w.HBegin(3), w.HEnd(3) - 2, w.HEnd(3));
std::cout << w << std::endl;

return 0;
}

Share this post


Link to post
Share on other sites
Isn''t that a little overkill for something this simple? How about:

const int ROWS = 6;
const int COLS = 5;

int myArray[ROWS][COLS] = {
{ 0, 1, 0, 1, 0},
{ 1, 1, 0, 1, 0},
{ 1, 1, 0, 0, 1},
{ 1, 0, 1, 0, 1},
{ 0, 1, 0, 1, 0},
{ 0, 1, 1, 0, 0}
};

void RotateRow(int **array, int row, int count) // This works for -COLS <= count <= COLS

{
int i;

int tempRow[COLS];

for(i = 0; i < COLS; i++)
tempRow[i] = array[row][i];

for(i = 0; i < COLS; i++)
array[row][i] = tempRow[(COLS + i - count) % COLS];
}

void RotateColumn(int **array, int col, int count) // This works for -ROWS <= count <= ROWS

{
int i;

int tempCol[ROWS];

for(i = 0; i < ROWS; i++)
tempCol[i] = array[i][col];

for(i = 0; i < ROWS; i++)
array[i][col] = tempCol[(ROWS + i - count) % ROWS];
}

Share this post


Link to post
Share on other sites
quote:
Original post by SiCrane
Forward iterator part? I didn''t mention forward iterators in my post.
Oh, I looked up std::rotate in gcc.gnu.org, and the function declaration looks like this:

template < typename _ForwardIter >
std::rotate( _ForwardIter first, _ForwardIter middle, _ForwardIter last );

first: a forward iterator
middle: a forward iterator
last: a forward iterator

So I was thinking what they mean by forward iterator. If I pass only numbers, I know just by the declaration it would work because it''s just a template, but which array does it work on confuses me.
quote:

// rotate column 2 by 1.
std::rotate(w.VBegin(2), w.VBegin(2) + 1, w.VEnd(2));
std::cout << w << std::endl;
Correct me if I am wrong, that would push the column upward, right? AFAIK, std::rotate will swap first-middle with middle-last. first is the beginning of array, middle is the element next to it, and last is the rest of the array. So you put the first element to the last elemet, and shifted the array up.
quote:

// rotate column 2 by 1 the other way.
std::rotate(w.VBegin(2), w.VEnd(2) - 1, w.VEnd(2));
std::cout << w << std::endl;
And this will push the array downward.


- Google - MSDN Library - GameDev.net Articles & Resources - Wikipedia The Free Encyclopedia -
- Alnite Design -

Share this post


Link to post
Share on other sites
quote:
Original post by alnite
So I was thinking what they mean by forward iterator. If I pass only numbers, I know just by the declaration it would work because it''s just a template, but which array does it work on confuses me.


As you can see, you don''t pass numbers, you pass pointers to the numbers or objects that can be used like pointers to the numbers.

quote:

quote:

// rotate column 2 by 1.
std::rotate(w.VBegin(2), w.VBegin(2) + 1, w.VEnd(2));
std::cout << w << std::endl;
Correct me if I am wrong, that would push the column upward, right? AFAIK, std::rotate will swap first-middle with middle-last. first is the beginning of array, middle is the element next to it, and last is the rest of the array. So you put the first element to the last elemet, and shifted the array up.


Right, that shifts them up.
quote:

quote:

// rotate column 2 by 1 the other way.
std::rotate(w.VBegin(2), w.VEnd(2) - 1, w.VEnd(2));
std::cout << w << std::endl;
And this will push the array downward.


Right, that should shift them down one.

Share this post


Link to post
Share on other sites
Just keep in mind I only implemented as much of VIterator as necessary to get it to compile. If you want to use other functions from the <algorithm> header like std::for_each() with VIterators, you might need to add in more functionality (like overloading operator ++ and --, etc.).

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!