• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
owl

Please lay me a hand.

15 posts in this topic

Hi. I've been trying to figure this out and I kind of can't.

I have an image that represents a character. By default, the character depicted in the image is standing and heading right. ( -> )

Then, inside the "game" the character has a velocity vector (x,y).

So, given this velocity vector I'm calculating an angle in the following way:

[code]float radians = atan2(x_vel, y_vel);[/code]


So far, so good. A first problem was that when the velocity represents an angle of (180 CCW) the image gets upside-down. So what I did was to check if the x velocity was smaller than zero, and if it was, then I'd flip the image horizontally.

But now I can't figure out how to apply the rotation. I need a way to adjust the rotation that comes from atan2 depending on whether the image is heading left or right.


[code]
coord (0,1)
?/2

?
?
<-heading left ? heading right ->
?
?
?
?
coord (-1,0) ? ???????????????????????????????? 0 or 2? coord (1,0)
?
?
?
?
?
?

3/4?
coord (0,-1)[/code]


Thanks in advance.
0

Share this post


Link to post
Share on other sites
[quote name='owl' timestamp='1307401553' post='4820289']
Hi. I've been trying to figure this out and I kind of can't.

I have an image that represents a character. By default, the character depicted in the image is standing and heading right. ( -> )

Then, inside the "game" the character has a velocity vector (x,y).

So, given this velocity vector I'm calculating an angle in the following way:

[code]float radians = atan2(x_vel, y_vel);[/code]


So far, so good. A first problem was that when the velocity represents an angle of (180 CCW) the image gets upside-down. So what I did was to check if the x velocity was smaller than zero, and if it was, then I'd flip the image horizontally.

But now I can't figure out how to apply the rotation. I need a way to adjust the rotation that comes from atan2 depending on whether the image is heading left or right.


[code]
coord (0,1)
?/2

?
?
<-heading left ? heading right ->
?
?
?
?
coord (-1,0) ? ???????????????????????????????? 0 or 2? coord (1,0)
?
?
?
?
?
?

3/4?
coord (0,-1)[/code]


Thanks in advance.
[/quote]

hmm wouldn't it work to rotate 0-(?-atan2(xvel,yvel) if xvel<0 ?(after flipping the image)

(Also , it should be 3/2? at 0,-1
1

Share this post


Link to post
Share on other sites
[quote name='SimonForsman' timestamp='1307402192' post='4820291']
hmm wouldn't it work to rotate 0-(?-atan2(xvel,yvel) if xvel<0 ?(after flipping the image)

(Also , it should be 3/2? at 0,-1

[/quote]

Almost! With your tip the image gets well rotated when heading left, but when heading right [b](edit: or left)[/b] and going towards (x=1,y=1) or( x=-1,y=-1) (that is diagonally) the angle is flipped vertically (heading down when going up and the opposite).

here is the code I'm using to rotate the bitmap with your suggestion included:


[source lang="cpp"]
void rotate()
{
float radians = atan2(x_vel, y_vel); //0; //1.5708; //

if (x_vel<0)
{
radians = 0-(3.1416-atan2(x_vel,y_vel));
}

float cosine=(float)cos(radians);
float sine=(float)sin(radians);

int bmp_width = image.get_width();
int bmp_height = image.get_height();

float point1_x=(-bmp_height*sine);
float point1_y=(bmp_height*cosine);
float point2_x=(bmp_width*cosine-bmp_height*sine);
float point2_y=(bmp_height*cosine+bmp_width*sine);
float point3_x=(bmp_width*cosine);
float point3_y=(bmp_width*sine);

float minx=min(0,min(point1_x,min(point2_x,point3_x)));
float miny=min(0,min(point1_y,min(point2_y,point3_y)));
float maxx=max(point1_x,max(point2_x,point3_x));
float maxy=max(point1_y,max(point2_y,point3_y));

int dest_width=(int)ceil(fabs(maxx)-minx);
int dest_height=(int)ceil(fabs(maxy)-miny);

if (image_rotated.buffer.size()!= (uint32_t)dest_width*dest_height)
{
image_rotated.new_transparent(dest_width, dest_height);
}

for(int x=0;x<dest_width;x++)
{
for(int y=0;y<dest_height;y++)
{
int src_bitmap_x=(int)((x+minx)*cosine+(y+miny)*sine);
int src_bitmap_y=(int)((y+miny)*cosine-(x+minx)*sine);
if( src_bitmap_x>=0 && src_bitmap_x<image.get_width() && src_bitmap_y>=0 && src_bitmap_y<image.get_height() )
{
image_rotated.buffer[y * image_rotated.get_width() + x] = image.buffer[src_bitmap_x * image.get_width() + src_bitmap_y];
}
}
}
}[/source]
0

Share this post


Link to post
Share on other sites
[quote name='owl' timestamp='1307403258' post='4820299']
[quote name='SimonForsman' timestamp='1307402192' post='4820291']
hmm wouldn't it work to rotate 0-(?-atan2(xvel,yvel) if xvel<0 ?(after flipping the image)

(Also , it should be 3/2? at 0,-1

[/quote]

Almost! With your tip the image gets well rotated when heading left, but when heading right [b](edit: or left)[/b] and going towards (x=1,y=1) or( x=-1,y=-1) (that is diagonally) the angle is flipped vertically (heading down when going up and the opposite).

here is the code I'm using to rotate the bitmap with your suggestion included:


[source lang="cpp"]
void rotate()
{
float radians = atan2(x_vel, y_vel); //0; //1.5708; //

if (x_vel<0)
{
radians = 0-(3.1416-atan2(x_vel,y_vel));
}

float cosine=(float)cos(radians);
float sine=(float)sin(radians);

int bmp_width = image.get_width();
int bmp_height = image.get_height();

float point1_x=(-bmp_height*sine);
float point1_y=(bmp_height*cosine);
float point2_x=(bmp_width*cosine-bmp_height*sine);
float point2_y=(bmp_height*cosine+bmp_width*sine);
float point3_x=(bmp_width*cosine);
float point3_y=(bmp_width*sine);

float minx=min(0,min(point1_x,min(point2_x,point3_x)));
float miny=min(0,min(point1_y,min(point2_y,point3_y)));
float maxx=max(point1_x,max(point2_x,point3_x));
float maxy=max(point1_y,max(point2_y,point3_y));

int dest_width=(int)ceil(fabs(maxx)-minx);
int dest_height=(int)ceil(fabs(maxy)-miny);

if (image_rotated.buffer.size()!= (uint32_t)dest_width*dest_height)
{
image_rotated.new_transparent(dest_width, dest_height);
}

for(int x=0;x<dest_width;x++)
{
for(int y=0;y<dest_height;y++)
{
int src_bitmap_x=(int)((x+minx)*cosine+(y+miny)*sine);
int src_bitmap_y=(int)((y+miny)*cosine-(x+minx)*sine);
if( src_bitmap_x>=0 && src_bitmap_x<image.get_width() && src_bitmap_y>=0 && src_bitmap_y<image.get_height() )
{
image_rotated.buffer[y * image_rotated.get_width() + x] = image.buffer[src_bitmap_x * image.get_width() + src_bitmap_y];
}
}
}
}[/source]
[/quote]

Hmm, if you get things wrong when heading right aswell then the problem shouldn't be with the code i added (as it only applies when facing left) but rather with the rest of the rotation code.

I'm having a hard time wrapping my head around that at the moment though. (lots of math, might need a pen and paper for this)
1

Share this post


Link to post
Share on other sites
[quote name='SimonForsman' timestamp='1307405593' post='4820308']
Hmm, if you get things wrong when heading right aswell then the problem shouldn't be with the code i added (as it only applies when facing left) but rather with the rest of the rotation code.

I'm having a hard time wrapping my head around that at the moment though. (lots of math, might need a pen and paper for this)
[/quote]


Without flipping the image horizontally nor negating the angle in relation the the velocity:

- Originally the image is heading right:

- When the angle is 0 it gets rotated so it looks straight down
- When the angle is ?/2 (1.5708) it ends up looking straight to the right (like if it was horizontally flipped)
- When the angle is (3/2)*3.1416 it looks straight up
- When the angle is 3.1416 it looks straight up too! wtf?

Shouldn't I rotate it only a max of 180º when if flip it first? I mean, to avoid having it rotated 360º.

0

Share this post


Link to post
Share on other sites
[quote][code]float radians = atan2(x_vel, y_vel);[/code][/quote]
Assuming you're using standard conventions (which it sounds like you are), the above should probably be:

[code]float radians = atan2(y_vel, x_vel);[/code]
1

Share this post


Link to post
Share on other sites
[quote name='jyk' timestamp='1307410259' post='4820329']
[quote][code]float radians = atan2(x_vel, y_vel);[/code][/quote]
Assuming you're using standard conventions (which it sounds like you are), the above should probably be:

[code]float radians = atan2(y_vel, x_vel);[/code]
[/quote]

You're right about that. Yet, ironically, doing it the right way brings worst results! Now the image never faces the direction it's going! What's going on? O_o
1

Share this post


Link to post
Share on other sites
[quote name='owl' timestamp='1307413592' post='4820346']
You're right about that. Yet, ironically, doing it the right way brings worst results! Now the image never faces the direction it's going! What's going on? O_o
[/quote]
Do you still have any of the 'corrective' code in place? That is, are you modifying the angle returned by atan2() in any way?

Also, although this is probably too obvious, are you missing any degrees<->radians conversions anywhere?
1

Share this post


Link to post
Share on other sites
[quote name='jyk' timestamp='1307414032' post='4820350']
[quote name='owl' timestamp='1307413592' post='4820346']
You're right about that. Yet, ironically, doing it the right way brings worst results! Now the image never faces the direction it's going! What's going on? O_o
[/quote]
Do you still have any of the 'corrective' code in place? That is, are you modifying the angle returned by atan2() in any way?

Also, although this is probably too obvious, are you missing any degrees<->radians conversions anywhere?
[/quote]

Yes, correcting the order of the parameters in the atan2 function, the code that rotates the image is [b]*exactly*[/b] this one:

[source lang="cpp"]void rotate()
{
float radians = atan2(y_vel, x_vel); //0; //1.5708; //

if (x_vel<0)
{
radians = 0-(3.1416-atan2(y_vel,x_vel));
}

float cosine=(float)cos(radians);
float sine=(float)sin(radians);

int bmp_width = image.get_width();
int bmp_height = image.get_height();

float point1_x=(-bmp_height*sine);
float point1_y=(bmp_height*cosine);
float point2_x=(bmp_width*cosine-bmp_height*sine);
float point2_y=(bmp_height*cosine+bmp_width*sine);
float point3_x=(bmp_width*cosine);
float point3_y=(bmp_width*sine);

float minx=min(0,min(point1_x,min(point2_x,point3_x)));
float miny=min(0,min(point1_y,min(point2_y,point3_y)));
float maxx=max(point1_x,max(point2_x,point3_x));
float maxy=max(point1_y,max(point2_y,point3_y));

int dest_width=(int)ceil(fabs(maxx)-minx);
int dest_height=(int)ceil(fabs(maxy)-miny);

if (image_rotated.buffer.size()!= (uint32_t)dest_width*dest_height)
{
image_rotated.new_transparent(dest_width, dest_height);
}

for(int x=0;x<dest_width;x++)
{
for(int y=0;y<dest_height;y++)
{
int src_bitmap_x=(int)((x+minx)*cosine+(y+miny)*sine);
int src_bitmap_y=(int)((y+miny)*cosine-(x+minx)*sine);
if( src_bitmap_x>=0 && src_bitmap_x<image.get_width() && src_bitmap_y>=0 && src_bitmap_y<image.get_height() )
{
image_rotated.buffer[y * image_rotated.get_width() + x] = image.buffer[src_bitmap_x * image.get_width() + src_bitmap_y];
}
}
}
}[/source]

Given that code, now the image never faces towards the direction it's going... I still think I should cap the rotation to 180º if I flip the image before rotating it. Yet I'm not sure how to limit it... As far as I can tell everything seems to work in radians here... *blocked*

EDIT: If I change the order of the parameters in the atan2 function to be as they should (y, x) and I swap the sin and cos then it works exactly as having the atan2 function with the parameters as (x,y).


[code]
float cosine=(float)sin(radians);
float sine=(float)cos(radians);[/code]
1

Share this post


Link to post
Share on other sites
[quote name='owl' timestamp='1307414502' post='4820353']
[quote name='jyk' timestamp='1307414032' post='4820350']
[quote name='owl' timestamp='1307413592' post='4820346']
You're right about that. Yet, ironically, doing it the right way brings worst results! Now the image never faces the direction it's going! What's going on? O_o
[/quote]
Do you still have any of the 'corrective' code in place? That is, are you modifying the angle returned by atan2() in any way?

Also, although this is probably too obvious, are you missing any degrees<->radians conversions anywhere?
[/quote]

Yes, correcting the order of the parameters in the atan2 function, the code that rotates the image is [b]*exactly*[/b] this one:

[source lang="cpp"]void rotate()
{
float radians = atan2(y_vel, x_vel); //0; //1.5708; //

if (x_vel<0)
{
radians = 0-(3.1416-atan2(y_vel,x_vel));
}

float cosine=(float)cos(radians);
float sine=(float)sin(radians);

int bmp_width = image.get_width();
int bmp_height = image.get_height();

float point1_x=(-bmp_height*sine);
float point1_y=(bmp_height*cosine);
float point2_x=(bmp_width*cosine-bmp_height*sine);
float point2_y=(bmp_height*cosine+bmp_width*sine);
float point3_x=(bmp_width*cosine);
float point3_y=(bmp_width*sine);

float minx=min(0,min(point1_x,min(point2_x,point3_x)));
float miny=min(0,min(point1_y,min(point2_y,point3_y)));
float maxx=max(point1_x,max(point2_x,point3_x));
float maxy=max(point1_y,max(point2_y,point3_y));

int dest_width=(int)ceil(fabs(maxx)-minx);
int dest_height=(int)ceil(fabs(maxy)-miny);

if (image_rotated.buffer.size()!= (uint32_t)dest_width*dest_height)
{
image_rotated.new_transparent(dest_width, dest_height);
}

for(int x=0;x<dest_width;x++)
{
for(int y=0;y<dest_height;y++)
{
int src_bitmap_x=(int)((x+minx)*cosine+(y+miny)*sine);
int src_bitmap_y=(int)((y+miny)*cosine-(x+minx)*sine);
if( src_bitmap_x>=0 && src_bitmap_x<image.get_width() && src_bitmap_y>=0 && src_bitmap_y<image.get_height() )
{
image_rotated.buffer[y * image_rotated.get_width() + x] = image.buffer[src_bitmap_x * image.get_width() + src_bitmap_y];
}
}
}
}[/source]

Given that code, now the image never faces towards the direction it's going... I still think I should cap the rotation to 180º if I flip the image before rotating it. Yet I'm not sure how to limit it... As far as I can tell everything seems to work in radians here... *blocked*

EDIT: If I change the order of the parameters in the atan2 function to be as they should (y, x) and I swap the sin and cos then it works exactly as having the atan2 function with the parameters as (x,y).


[code]
float cosine=(float)sin(radians);
float sine=(float)cos(radians);[/code]

[/quote]

You shouldn't need to cap the rotation, xvel<0 should always result in a rotation between pi/2 and 3pi/2 (90-270 degrees) while xvel > 0 results in one that is either between 0 and pi/2(0-90 degrees) or between 3pi/2 and 2pi (270-360 degrees)

The fact that your image gets rotated at all when the angle is 0 means that you've messed up your rotation formula. (when radians is 0 there should be no rotation)

//some mindless typing to help me keep my mind on track, possible conclusion further down.

sin(0) = 0
cos(0) = 1

Thus your 3 points when you're not supposed to rotate anything becomes:

float point1_x=0;float point1_y=bmp_height;

float point2_x=bmp_width;float point2_y=bmp_height;
float point3_x=bmp_width;float point3_y=0;

then:

float minx=min(0,min(point1_x,min(point2_x,point3_x)));float miny=min(0,min(point1_y,min(point2_y,point3_y)));float maxx=max(point1_x,max(point2_x,point3_x));float maxy=max(point1_y,max(point2_y,point3_y));

minx = 0
miny = 0
maxx = bmp_width
maxy = bmp_height

//Image size doesn't change atleast.

Then for each pixel in the rotated image you do
[code]
int src_bitmap_x=(int)((x+0));
int src_bitmap_y=(int)((y+0));
if( src_bitmap_x>=0 && src_bitmap_x<image.get_width() && src_bitmap_y>=0 && src_bitmap_y<image.get_height() ) {
image_rotated.buffer[y * image_rotated.get_width() + x] = image.buffer[src_bitmap_x * image.get_width() + src_bitmap_y];
}
[/code]
shouldn't:
image_rotated.buffer[y * image_rotated.get_width() + x] = image.buffer[[b]src_bitmap_x * image.get_width() + src_bitmap_y[/b]];

be

image_rotated.buffer[y * image_rotated.get_width() + x] = image.buffer[[b]src_bitmap_y * image.get_width() + src_bitmap_x[/b]];
2

Share this post


Link to post
Share on other sites
[quote name='SimonForsman' timestamp='1307452577' post='4820496']
Then for each pixel in the rotated image you do
[code]
int src_bitmap_x=(int)((x+0));
int src_bitmap_y=(int)((y+0));
if( src_bitmap_x>=0 && src_bitmap_x<image.get_width() && src_bitmap_y>=0 && src_bitmap_y<image.get_height() ) {
image_rotated.buffer[y * image_rotated.get_width() + x] = image.buffer[src_bitmap_x * image.get_width() + src_bitmap_y];
}
[/code]
shouldn't:
image_rotated.buffer[y * image_rotated.get_width() + x] = image.buffer[[b]src_bitmap_x * image.get_width() + src_bitmap_y[/b]];

be

image_rotated.buffer[y * image_rotated.get_width() + x] = image.buffer[[b]src_bitmap_y * image.get_width() + src_bitmap_x[/b]];
[/quote]

OUTSTANDING CATCH MAN! :) It works now.

There are some special cases where the image will still face the opposite direction it is moving, but that smells like something being wrong with the algorithm that decides to flip the image horizontally.

You're awesome guys! :)
1

Share this post


Link to post
Share on other sites
i think that you problem is in this

[code]
if (x_vel<0)
{
radians = 0-(3.1416-atan2(y_vel,x_vel));
}
[/code]

you can't flip image by rotateing. you need to do this

[code]
if (x_vel<0)
{
for(int x=0; x<width; x++) for(int y=0; y<height; y++)
image_fliped.buffer[(y+1) * width - x] = image.buffer[y * width + x];
}
[/code]
0

Share this post


Link to post
Share on other sites
or you can remove the if statement and change this

[code]

image_rotated.buffer[y * image_rotated.get_width() + x] = image.buffer[src_bitmap_y * image.get_width() + src_bitmap_x];

[/code]

to this


[code]

int rot_index = (x_vel<0) ? (y+1) * image_rotated.get_width() - x : y * image_rotated.get_width() + x;

image_rotated.buffer[rot_index] = image.buffer[src_bitmap_y * image.get_width() + src_bitmap_x];

[/code]
1

Share this post


Link to post
Share on other sites
[quote name='Borg_Ri' timestamp='1307456671' post='4820520']
i think that you problem is in this

[code]
if (x_vel<0)
{
radians = 0-(3.1416-atan2(y_vel,x_vel));
}
[/code]

you can't flip image by rotateing. you need to do this

[code]
if (x_vel<0)
{
for(int x=0; x<width; x++) for(int y=0; y<height; y++)
image_fliped.buffer[(y+1) * width - x] = image.buffer[y * width + x];
}
[/code]
[/quote]

[code]
if (x_vel<0)
{
radians = 0-(3.1416-atan2(y_vel,x_vel));
}
[/code]

doesn't flip the image, it adjusts the rotation so that the flipped image faces in the correct direction (as flipping the image effectivly changes the direction its facing by pi radians the performed rotation has to be adjusted by the same amount to compensate to avoid having the flipped image face the wrong way)

it should probably be changed to:

float radians = atan2(y_vel, x_vel);
if (x_vel<0) {
radians -= 3.1416;
} //This should be equivalent but avoids one atan2 call and thus should be faster (unless the compiler is capable of optimizing out calls to pure functions when the variables passed doesn't change)

I'm assuming owl has a flip function aswell that he calls when xvel<0 since he said he was flipping the image in his original post (yet the code he posted doesn't flip it).

The remaining "special cases" could probably be solved if we knew in what ranges they occured (If it happens when moving close to straight up or straight down for example)
1

Share this post


Link to post
Share on other sites
[quote name='SimonForsman' timestamp='1307461920' post='4820560']
The remaining "special cases" could probably be solved if we knew in what ranges they occured (If it happens when moving close to straight up or straight down for example)
[/quote]

It was a problem related to sometimes not flipping the image. This code is for the fish tank entry and I'm writing it as it comes, that is: messy :)
1

Share this post


Link to post
Share on other sites
i am sorry, in my code i gave you i was fliping image the wrong way, that is probably why it didn't work. try this.




comment out the

[code]

if (x_vel<0)
{
radians = 0-(3.1416-atan2(y_vel,x_vel));
}


[/code]




and replace

[code]

image_rotated.buffer[y * image_rotated.get_width() + x] = image.buffer[src_bitmap_y * image.get_width() + src_bitmap_x];

[/code]




with

[code]

int rot_index = (x_vel<0) ? (dest_height-y-1) * image_rotated.get_width() + x : y * image_rotated.get_width() + x;

image_rotated.buffer[rot_index] = image.buffer[src_bitmap_y * image.get_width() + src_bitmap_x];


[/code]
1

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0