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 | } |