View difference between Paste ID: bJNmWAaU and fYN34fXv
SHOW: | | - or go back to the newest paste.
1
///***** Cloned from badwrong: https://pastebin.com/fYN34fXv ******
2
// ********* Create ***************//
3
bbox = new tile_bbox(mask_index); // Instance of the struct below
4
5
// ********* How to call it when moving (step event or something) *************** //
6
bbox.move_collide(id, x, y, _vx, _vy);  // _vx and _vy are whatever your movement speeds are
7
8
9
// ********* The struct ******************************//
10
function tile_bbox(_mask) constructor
11
{
12
	/* Performs tile collision independent from object's bbox.
13
	 * Since we can use a separate mask here from the objects, that allows
14
	 * the object to use a different shaped mask for hit detection and not
15
	 * need a whole other "hurtbox" object.
16
	 * 
17
	 * Plus this is actually faster and requires less round/floor/ceil nonsense
18
	 * to fix some internal junk.
19
	 *
20
	 * Note the "& 1" checks for odd numbered tiles as "solid", pretty usefull 
21
	 * if you want waist high walls that cause movement collision but can be 
22
	 * shot over with a gun or something.
23
	 */
24
25
	#macro TILE_SOLID 1
26
	#macro TILE_ONE_WAY 2
27
	#macro TILE_SIZE 16
28
	#macro TILE_SIZE_M1 15
29
	
30
	#macro COLLIDE_VER_UP 1
31
	#macro COLLIDE_VER_DOWN -1
32
	#macro COLLIDE_VER_NONE 0
33
	#macro COLLIDE_HOR_RIGHT 1
34
	#macro COLLIDE_HOR_LEFT -1
35
	#macro COLLIDE_HOR_NONE 0
36
	
37
	var _w = sprite_get_width(_mask), 
38
		_h = sprite_get_height(_mask),
39
		_y_count = ceil(_h / TILE_SIZE),
40
		_x_count = ceil(_w / TILE_SIZE);
41
		
42
	mask_sprite = _mask;
43
	
44
	cmap   = global.layer_collision;  
45
	// or layer_tilemap_get_id(layer_get_id("collision_map")); 
46
	// Remember the id could change between rooms
47
	
48
	left   = -sprite_get_xoffset(_mask);
49
	right  = _w - sprite_get_xoffset(_mask);
50
	top    = -sprite_get_yoffset(_mask);
51
	bottom = _h - sprite_get_yoffset(_mask);
52
	
53
	hor_count     = _y_count + 1;
54
	hor_increment = (_h - 1) / _y_count;
55
	ver_count     = _x_count + 1;
56
	ver_increment = (_w - 1) / _x_count;
57
	
58
	on_horizontal = 0; // Useful for wall jumps
59
	on_vertical = 0; // Can be used to set on_ground
60
	on_one_way_platform = false;
61
				
62
	function move_collide(_this, _x, _y, _vx, _vy)
63
	{
64
		_x += _vx;
65
		if (_vx > 0) _x = collide_right(_x, _y);
66
		else if (_vx < 0) _x = collide_left(_x, _y);
67
		else on_horizontal = COLLIDE_HOR_NONE;
68
69
		_y += _vy;
70
		if (_vy > 0) _y = collide_bottom(_x, _y, _vy);
71
		else if (_vy < 0) _y = collide_top(_x, _y);
72
		else 
73
		{
74
			on_vertical = COLLIDE_VER_NONE;
75
			on_one_way_platform = false;
76
		}
77
		
78
		_this.x = _x;
79
		_this.y = _y;
80
	}			
81
				
82
	function collide_right(_x, _y)
83
	{
84
		var _right = _x + right;
85
		_y = round(_y + top);
86
		for (var _i = 0; _i < hor_count; _i++)
87
		{
88
			if ((tilemap_get_at_pixel(cmap, _right, _y) & tile_index_mask) & 1)
89
			{
90
				on_horizontal = COLLIDE_HOR_RIGHT;
91
				return (_right &~ TILE_SIZE_M1) - right;
92
			}
93
			_y += hor_increment;
94
		}
95
		on_horizontal = COLLIDE_HOR_NONE;
96
		return _x;
97
	}
98
	
99
	function collide_left(_x, _y)
100
	{
101
		var _left = _x + left;
102
		_y = round(_y + top);
103
		for (var _i = 0; _i < hor_count; _i++)
104
		{
105
			if ((tilemap_get_at_pixel(cmap, _left, _y) & tile_index_mask) & 1) 
106
			{
107
				on_horizontal = COLLIDE_HOR_LEFT;
108
				return (_left &~ TILE_SIZE_M1) + TILE_SIZE - left;
109
			}
110
			_y += hor_increment;
111
		}
112
		on_horizontal = COLLIDE_HOR_NONE;
113
		return _x;
114
	}
115
	
116
	function collide_top(_x, _y)
117
	{
118
		on_one_way_platform = false;
119
		var _top = _y + top;
120
		_x = round(_x + left);
121
		for (var _i = 0; _i < ver_count; _i++)
122
		{
123
			if ((tilemap_get_at_pixel(cmap, _x, _top) & tile_index_mask) & 1)
124
			{
125
				on_vertical = COLLIDE_VER_UP;
126
				return (_top &~ TILE_SIZE_M1) + TILE_SIZE - top;
127
			}
128
			_x += ver_increment;
129
		}
130
		on_vertical = COLLIDE_VER_NONE;
131
		return _y;
132
	}
133
	
134
	function collide_bottom(_x, _y, _vy)
135
	{
136
		// A bit different to account for one-way platforms
137
		
138
		var _bottom = _y + bottom,
139
			_tile_top = _bottom &~ TILE_SIZE_M1,
140
			_above_one_way = (_bottom - _vy) <= _tile_top;
141
			
142
		_x = round(_x + left);
143
		for (var _i = 0; _i < ver_count; _i++)
144
		{
145
			var _tile_index = tilemap_get_at_pixel(cmap, _x, _bottom) & tile_index_mask,
146
				_on_one_way_platform = (_above_one_way && _tile_index == TILE_ONE_WAY);
147
			
148
			if (_tile_index & 1 || _on_one_way_platform)
149
			{
150
				on_vertical = COLLIDE_VER_DOWN;
151
				on_one_way_platform = _on_one_way_platform;
152
				return _tile_top - bottom;
153
			}
154
			_x += ver_increment;
155
		}
156
		on_vertical = COLLIDE_VER_NONE;
157
		return _y;
158
	}
159
	
160
	function draw_mask(_x, _y)
161
	{
162
		draw_sprite(mask_sprite, 0, _x, _y);
163
	}
164
	
165
}