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