Jump to content


Photo

Easy [2D] Shape Rotation


  • Please log in to reply
15 replies to this topic

#1 Glutex Master

Glutex Master

    The Game Guy

  • GMC Member
  • 204 posts
  • Version:GM8

Posted 22 December 2010 - 09:37 AM

Easy 2D Shape Rotation Scripts
Shapes currently supported: Rectangles, Lines, Circles, Ellipses
Shapes I plan on adding: Triangles

Make rotating 2D shapes EASY with these scripts!

Features:
  • Fast and easy using regular game maker's built in draw_ functions
  • Rotate to any angle (0-360)
  • Change the point of rotation
  • If the last argument: 'show marker' is set to true, a small red cross is drawn at the point of rotation, making it easy for you to check where you want your point of rotation to be used

Note that most scripts in places have 'width' and 'height' instead of x2 and y2.

The Scripts

//use as: draw_rectangle_rotated(x,y,width,height,outline,
    //angle,rotatepoint_x,rotatepoint_y,show_marker);
//argument0 = x
//argument1 = y
//argument2 = width
//argument3 = height
//argument4 = outlined rectangle? (true/false: use false for a filled rectangle)
//argument5 = angle of rotation
//argument6 = x co-ordinate of the point of rotation (relative)
//argument7 = y co-ordinate of the point of rotation (relative)
//argument8 = mark rotation point? (true/false: use false for no marker)
//NOTE: rotation point(argument2/2,arguemnt3/2) is the center
{
    //Set the rotation
    d3d_transform_set_rotation_z(argument5);
    
    //Set the translation
    d3d_transform_add_translation(argument0,argument1,0);
    
    //Draw the rectangle
    draw_rectangle(-argument6,-argument7,argument2-argument6,argument3-argument7,argument4);
    
    //Set identity
    d3d_transform_set_identity();
    
    //Draw the point of rotation when needed
    if (argument8)
    {
        var oldcol;
        oldcol=draw_get_color();
        draw_set_color(c_red);
        draw_line(argument0-8,argument1,argument0+8,argument1);
        draw_line(argument0,argument1-8,argument0,argument1+8);
        draw_set_color(oldcol);
    }
}


//use as: draw_line_rotated(x,y,width,angle
    //,rotatepoint_x,rotatepoint_y,show_marker);
//argument0 = x
//argument1 = y
//argument2 = width
//argument3 = angle of rotation
//argument4 = x co-ordinate of the point of rotation (relative)
//argument5 = y co-ordinate of the point of rotation (relative)
//argument6 = mark rotation point? (true/false: use false for no marker)
//NOTE: rotation point(argument2/2,0) is the center
{
    //Set the rotation
    d3d_transform_set_rotation_z(argument3);
    
    //Set the translation
    d3d_transform_add_translation(argument0,argument1,0);
    
    //Draw the line
    draw_line(-argument4,-argument5,argument2-argument4,-argument5);
    
    //Set identity
    d3d_transform_set_identity();
    
    //Draw the point of rotation when needed
    if (argument6)
    {
        var oldcol;
        oldcol=draw_get_color();
        draw_set_color(c_red);
        draw_line(argument0-8,argument1,argument0+8,argument1);
        draw_line(argument0,argument1-8,argument0,argument1+8);
        draw_set_color(oldcol);
    }
}


//use as: draw_circle_rotated(x,y,radius,outline,angle
    //,rotatepoint_x,rotatepoint_y,show_marker);
//argument0 = x
//argument1 = y
//argument2 = radius
//argument3 = outlined circle? (true/false: use false for a filled circle)
//argument4 = angle of rotation
//argument5 = x co-ordinate of the point of rotation (relative)
//argument6 = y co-ordinate of the point of rotation (relative)
//argument7 = mark rotation point? (true/false: use false for no marker)
//NOTE: rotation point(0,0) is the center
{
    //Set the rotation
    d3d_transform_set_rotation_z(argument4);
    
    //Set the translation
    d3d_transform_add_translation(argument0,argument1,0);
    
    //Draw the circle
    draw_circle(-argument5,-argument6,argument2,argument3);
    
    //Set identity
    d3d_transform_set_identity();
    
    //Draw the point of rotation when needed
    if (argument7)
    {
        var oldcol;
        oldcol=draw_get_color();
        draw_set_color(c_red);
        draw_line(argument0-8,argument1,argument0+8,argument1);
        draw_line(argument0,argument1-8,argument0,argument1+8);
        draw_set_color(oldcol);
    }
}


//use as: draw_ellipse_rotated(x,y,width,height,outline
    //,angle,rotatepoint_x,rotatepoint_y,show_marker);
//argument0 = x
//argument1 = y
//argument2 = width
//argument3 = height
//argument4 = outlined ellipse? (true/false: use false for a filled rectangle)
//argument5 = angle of rotation
//argument6 = x co-ordinate of the point of rotation (relative)
//argument7 = y co-ordinate of the point of rotation (relative)
//argument8 = mark rotation point? (true/false: use false for no marker)
//NOTE: rotation point(argument2/2,arguemnt3/2) is the center
{
    //Set the rotation
    d3d_transform_set_rotation_z(argument5);
    
    //Set the translation
    d3d_transform_add_translation(argument0,argument1,0);
    
    //Draw the ellipse
    draw_ellipse(-argument6,-argument7,argument2-argument6,argument3-argument7,argument4);
    
    //Set identity
    d3d_transform_set_identity();
    
    //Draw the point of rotation when needed
    if (argument8)
    {
        var oldcol;
        oldcol=draw_get_color();
        draw_set_color(c_red);
        draw_line(argument0-8,argument1,argument0+8,argument1);
        draw_line(argument0,argument1-8,argument0,argument1+8);
        draw_set_color(oldcol);
    }
}


Downloads
Download example (gm8): mirror1|mirror2|mirror3
Download example (gm7): mirror1|mirror2|mirror3
Download example (gm6): mirror1|mirror2|mirror3
Download example (gmres): mirror1|mirror2|mirror3
Download scripts (gml): mirror1|mirror2|mirror3
Download all as zip: mirror1|mirror2|mirror3


This topic probably could be a load better, But this the first piece of work I've published on the GMC, so you might expect that :)

Feedback would be great!, The Glutex Master
Credit not needed, but it would be nice :D

Edited by Glutex Master, 08 January 2011 - 09:34 PM.

  • 3

#2 MasterOfKings

MasterOfKings

    The True Master

  • GMC Member
  • 4888 posts
  • Version:GM8

Posted 23 December 2010 - 07:23 AM

Now, the ellipse and rectangle rotated, are good. But who needs a rotated line? It looks exactly as if you just draw the line at two different points. A little bit of trig, and you can draw a rotated line in one line.

-MoK
  • 0

#3 Glutex Master

Glutex Master

    The Game Guy

  • GMC Member
  • 204 posts
  • Version:GM8

Posted 23 December 2010 - 08:24 AM

Now, the ellipse and rectangle rotated, are good. But who needs a rotated line? It looks exactly as if you just draw the line at two different points. A little bit of trig, and you can draw a rotated line in one line.

-MoK


Thanks for your feedback!

The line and circle aren't as useful, but the more shapes the better :)
Plus, the rotated line is useful for new users who don't know how to use the point_direction/length_dir functions.
  • 1

#4 MasterOfKings

MasterOfKings

    The True Master

  • GMC Member
  • 4888 posts
  • Version:GM8

Posted 23 December 2010 - 09:27 AM

I suppose. Although, it also gets them into bad habits (I don't mean for using your scripts, I mean doing a simple task with an over-coded script).

Regardless, they're all good scripts!

-MoK
  • 0

#5 brac37

brac37

    GMC Member

  • GMC Member
  • 765 posts
  • Version:GM7

Posted 01 January 2011 - 05:15 PM

I would suggest to use d3d_transform_stack_push and d3d_transform_stack_pop to reset the transformation instead of d3d_transform_set_identity.

D3D transformations are a nice way to transform 2D drawing as well. My most recent script submission uses D3D transformations as well, see here.
  • 0

#6 Gamer3D

Gamer3D

    Human* me = this;

  • GMC Member
  • 1590 posts
  • Version:GM8.1

Posted 04 January 2011 - 12:01 AM

Okay... This isn't that useful at the moment. This is because it uses D3D functions, which are for registered GM. Instead, I recommend creating an orthonormal matrix for transformations, which can be done in the free version.

Given an angle theta in radians, the vector to multiply y by is <sin(theta), cos(theta)>. I would put this into code as:
ytx = sin(theta);
yty = cos(theta);
Next, we need a y vector. By properties of (you pick) trigonometry or vectors, we get this:
xtx = yty;
xty = -ytx;

Now we can put this into practice. A point <x, y> can be rotated by theta around <0, 0> by this:
transformed_x = xtx * x + ytx * y;
transformed_y = xty * x + yty * y;

We simplify further by doing this:

s = sin(theta);
c = cos(theta);
transformed_x = c * x + s * y;
transformed_y = c * y - s * x;

Using this and polygon-drawing routines, we get (note that I assume the rotation point is the center of the shape and that showing the point of rotation is useless):
//use as: draw_rectangle_rotated(x,y,width,height,outline,angle);
//argument0 = x
//argument1 = y
//argument2 = width
//argument3 = height
//argument4 = outlined rectangle? (true/false: use false for a filled rectangle)
//argument5 = angle of rotation
var s, c, twx, twy, thx, thy, v1x, v1y, v2x, v2y, v3x, v3y, v4x, v4y;
s = sin(degtorad(argument5)) * 0.5;  //  Degrees are so annoying. Radians are MUCH better.
c = cos(degtorad(argument5)) * 0.5;
twx = c * argument2;
twy = -s * argument2;
thx = s * argument3;
thy = c * argument3;

v1x = argument0 - twx - thx;
v1y = argument0 - twy - thy;
v2x = argument0 - twx + thx;
v2y = argument0 - twy + thy;
v3x = argument0 + twx + thx;
v3y = argument0 + twy + thy;
v4x = argument0 + twx - thx;
v4y = argument0 + twy - thy;
if (argument4) {
draw_line(v1x, v1y, v2x, v2y);
draw_line(v2x, v2y, v3x, v3y);
draw_line(v3x, v3y, v4x, v4y);
draw_line(v4x, v4y, v1x, v1y);
} else {
draw_triangle(v1x, v1y, v4x, v4y, v3x, v3y, false);
draw_triangle(v1x, v1y, v3x, v3y, v2x, v2y, false);
}

//use as: draw_ellipse_rotated(x,y,width,height,outline,angle);

//argument0 = x
//argument1 = y
//argument2 = width
//argument3 = height
//argument4 = outlined rectangle? (true/false: use false for a filled rectangle)
//argument5 = angle of rotation

var s, c, twx, twy, thx, thy, v1x, v1y, v2x, v2y, v3x, v3y, v4x, v4y;
s = sin(degtorad(argument5)) * 0.5;  //  Degrees are so annoying. Radians are MUCH better.
c = cos(degtorad(argument5)) * 0.5;
twx = c * argument2;
twy = -s * argument2;
thx = s * argument3;
thy = c * argument3;

v1x = argument0 + twx;
v1y = argument1 + twy;
if (argument4) {
v3x = v1x;
v3y = v1y;
for (n = 2 * pi; n > 0; n -= pi * 0.1) {
s = sin(n);
c = cos(n);
v2x = argument0 + twx * c + thx * s;
v2y = argument1 + twy * c + thy * s;
draw_line(v1x, v1y, v2x, v2y);
v1x = v2x;
v1y = v2y;
}
draw_line(v1x, v1y, v3x, v3y);
} else {
v2x = v1x;
v2y = v1y;
for (n = 0; n < pi; n += pi * 0.1) {
s = sin(n);
c = cos(n);
v3x = argument0 + twx * c - thx * s;
v3y = argument1 + twy * c - thy * s;
v4x = argument0 + twx * c + thx * s;
v4y = argument1 + twy * c + thy * s;
draw_triangle(v1x, v1y, v2x, v2y, v3x, v3y, false);
draw_triangle(v3x, v3y, v2x, v2y, v4x, v4y, false);
v1x = v3x;
v1y = v3y;
v2x = v4x;
v2y = v4y;
}
draw_triangle(v1x, v1y, v2x, v2y, argument0 - twx, argument1 - twy, false);
}

There you go. Rotated rectangles and ellipses for unregistered GM. Feel free to use it.

EDIT: Updated so it still works with culling on.

Edited by Gamer3D, 05 January 2011 - 03:36 AM.

  • 0

#7 Glutex Master

Glutex Master

    The Game Guy

  • GMC Member
  • 204 posts
  • Version:GM8

Posted 04 January 2011 - 08:34 PM

@Gamer3D
Might add that tomorrow :)
  • 0

#8 torigara

torigara

    GMC Member

  • GMC Member
  • 6483 posts

Posted 05 January 2011 - 02:20 AM

There you go. Rotated rectangles and ellipses for unregistered GM. Feel free to use it.

Unfortunately, drawing primitives also requires pro.

Advanced drawing functions
This functionality is only available in the Pro Edition of Game Maker.

You could draw non-filled shapes with draw_line, though.
  • 0

#9 Gamer3D

Gamer3D

    Human* me = this;

  • GMC Member
  • 1590 posts
  • Version:GM8.1

Posted 05 January 2011 - 03:37 AM


There you go. Rotated rectangles and ellipses for unregistered GM. Feel free to use it.

Unfortunately, drawing primitives also requires pro.

Advanced drawing functions
This functionality is only available in the Pro Edition of Game Maker.

You could draw non-filled shapes with draw_line, though.


Replaced primitives with draw_triangle. It's now fully unregistered.

I made the original mistake because I'd seen triangles in other people's "3D in Lite" examples. I didn't bother checking what they did (and didn't re-read the manual), so I assumed that primitives were Lite functions.

Edited by Gamer3D, 05 January 2011 - 06:15 AM.

  • 0

#10 Armisticdoom

Armisticdoom

    GMC Member

  • New Member
  • 73 posts

Posted 08 January 2011 - 09:30 PM

this is AMAZING! this is just what I need for my new game, called Troght!
  • 0

#11 flayd99

flayd99

    GMC Member

  • New Member
  • 1 posts

Posted 09 January 2011 - 12:59 AM

Thanks Glutex Master & Gamer3D! its just what i need, i implemented on my game engine and looks so nice ^_^
  • 0

#12 Glutex Master

Glutex Master

    The Game Guy

  • GMC Member
  • 204 posts
  • Version:GM8

Posted 09 January 2011 - 08:05 AM

this is AMAZING! this is just what I need for my new game, called Troght!

Thanks Glutex Master & Gamer3D! its just what i need, i implemented on my game engine and looks so nice ^_^


Glad you like it :)
Just pointing out that this topic wouldn't be here at all without ragarnak, so a big thanks to him as well :)

Edited by Glutex Master, 09 January 2011 - 08:06 AM.

  • 0

#13 Glutex Master

Glutex Master

    The Game Guy

  • GMC Member
  • 204 posts
  • Version:GM8

Posted 21 January 2011 - 07:31 PM

*small bump*
  • 0

#14 poizen

poizen

    Soft Aqua

  • GMC Member
  • 168 posts
  • Version:GM:Studio

Posted 22 January 2011 - 02:56 PM

I needed rotated rectangles for my tree generator. So thanks for this. =)

Posted Image
  • 0

#15 Glutex Master

Glutex Master

    The Game Guy

  • GMC Member
  • 204 posts
  • Version:GM8

Posted 01 October 2011 - 07:32 PM

BUMP
  • 0

#16 HelpMyFellowPeople

HelpMyFellowPeople

    GMC Member

  • GMC Member
  • 239 posts

Posted 07 October 2011 - 09:40 AM

Haha, cool. I made the exact same thing :D. Never knew it was already done!

Edited by HelpMyFellowPeople, 07 October 2011 - 09:40 AM.

  • 0




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users