GMLscripts.com

Discuss and collaborate on GML scripts
Invert

You are not logged in.

#1 2021-09-09 15:36:37

maras
Member
Registered: 2021-04-25
Posts: 22
Website

Draw a bent sprite

Don't remember seeing any GM script that can do that soo... here it is

Expand/// draw_sprite_bent(vf, spr, img, x, y, around_x, around_y, bend_angle, segments, xscale, yscale, rot, color, alpha)
//
// returns nothing
//
//	vf	vertex format, get it with get_vf()
//	spr	sprite index, real
//	img	image index, real
//	x	draw it here, real
//	y	draw it here, real
//	around_x	bend the sprite around this x position, real
//	around_y	bend the sprite around this y position, real
//	bend_angle	apply angle, real
//	segments	the more segments, the better quality (but lower performance), real
//	xscale	scale on the x axis, real
//	yscale	scale on the y axis, real
//	rot	rotation of the final drawn texture (does not affect actual bending and around_x/y position), real
//	color	colour
//	alpha	alpha, real
//
// *note*
// create the "vf" variable in the Create event or create it once somewhere and make it global
// there is no need to keep recreating it every step
//
// the default number of segments is around 20 but more will be required for larger bend angles
// 
// if the sprite is a png with alpha around DON'T FORGET TO TICK THE "Separate texture page" BUTTON
// otherwise it will mess the sprite up
// 
/// GMLscripts.com/license

function draw_sprite_bent(vf, spr, img, x, y, around_x, around_y, bend_angle, segments, xscale, yscale, rot, color, alpha) {
	
	var spr_w = sprite_get_width(spr);
	var spr_h = sprite_get_height(spr);
	var xoff = sprite_get_xoffset(spr) * xscale;
	var yoff = sprite_get_yoffset(spr) * yscale;
	
	var prec = max(2, round(segments));
	var step = spr_h / prec;
	var angle_step = bend_angle / prec;
	
	// split the sprite into triangles with UVs
	
	var uv = [];
	var c_len = 0;
	
	uv[c_len++] = [1, 0];
	
	var on_right = false;
	for(var h = 0; h < spr_h + step * 0.5; h += step) {
		
		uv[c_len++] = [real(on_right), h/spr_h];
		on_right = !on_right;
	}
	uv[c_len++] = [real(on_right), 1];
	
	// rotate the triangles around pivot and save their coordinates
	
	var counter = 0;
	var angl = 0;
	var coords = [];
	c_len = 0;
	
	for(var i = array_length(uv)-1; i > -1; i--) {
		
		var u = uv[i][0];
		var v = uv[i][1];
		
		var pivot_x = (around_x - (x - xoff)) / xscale;
		var pivot_y = (around_y - (y - yoff)) / yscale;
		
		var pdr = point_direction(pivot_x, pivot_y, u * spr_w, v * spr_h);
		var pds = point_distance(pivot_x, pivot_y, u * spr_w, v * spr_h);
		var xx = pivot_x + lengthdir_x(pds, pdr + angl);
		var yy = pivot_y + lengthdir_y(pds, pdr + angl);
		
		coords[c_len++] = [xx * xscale, yy * yscale, (counter == 1), u, v];
		
		if counter == 2 {
			counter = 0;
			
			if i == 0 break;
			
			i += 2;
			angl += angle_step;
		}
		else counter++;
	}
	
	// draw it
	
	var b = vertex_create_buffer();
	vertex_begin(b, vf);
	
	for(var i = 0; i < array_length(coords); i++) {
		
		if i == clamp(i, 2, array_length(coords)-3) {
			
			var c_prev = coords[i-2];
			var c_next = coords[i+2];
			if c_prev[2] coords[i] = [ c_prev[0], c_prev[1], false, coords[i][3], coords[i][4] ];
			if c_next[2] coords[i] = [ c_next[0], c_next[1], false, coords[i][3], coords[i][4] ];
		}
		
		var xx = coords[i][0] - xoff;
		var yy = coords[i][1] - yoff;
		
		if rot != 0 {
			var pdr = point_direction(0, 0, xx, yy);
			var pds = point_distance(0, 0, xx, yy);
			xx = lengthdir_x(pds, pdr + rot);
			yy = lengthdir_y(pds, pdr + rot);
		}
		
		vertex_position(b, x + xx, y + yy);
		vertex_colour(b, color, alpha);
		vertex_texcoord(b, coords[i][3], coords[i][4]);
	}
	
	vertex_end(b);
	vertex_submit(b, pr_trianglelist, sprite_get_texture(spr, img));
}
Expandfunction get_vf() {
	vertex_format_begin();
	vertex_format_add_position();
	vertex_format_add_colour();
	vertex_format_add_textcoord();
	return vertex_format_end();	
}

The green dot is around_x and around_y attached to the mouse cursor
Adjusting the bend_angle with mouse wheel
40 segments
ezgif-2-b48a104d230e.gif

Last edited by maras (2021-09-10 08:21:00)

Offline

Board footer

Powered by FluxBB