Заметки за 2022 год
SpaceWar
Третья игра на GMS2 – «SpaceWar». Два корабля, пульсар, гравитация и баллистика. Вышло очень динамично!
Вы играете за синий корабль и должны поразить метким (ха!) выстрелом корабль противника. Проблема в пульсаре, расположенном в центре игрового поля. Он обладает мощной гравитацией, и чем вы ближе к нему, тем она сильнее. Гравитация влияет как на траекторию снарядов, так и траекторию кораблей. Управление осуществляется курсорными клавишами.
Вверх ↑ – Тяга.
Влево ← и Вправо → – Поворот корабля вокруг своей оси.
Пробел – Выстрел.
Ссылка на загрузку игры: SpaceWar.zip
На этой игрушке я учился в «GameMaker Studio 2» работе с частицами и шейдерами. Частицы используются при отрисовке взрывов и шлейфов от снарядов. А шейдер создаёт анимацию пульсара. Дальше немного примеров кода из этого проекта.

Код обработки ввода игрока, событие Step в объекте obj_ship:
1image_index = 0;
2
3if (keyboard_check(vk_left)) {
4 image_angle += 5;
5 image_index = 2;
6}
7
8if (keyboard_check(vk_right)) {
9 image_angle -= 5;
10 image_index = 3;
11}
12
13if (keyboard_check(vk_up)) {
14 motion_add(image_angle, 0.05);
15 image_index = 1;
16}
17
18
19 if (keyboard_check_pressed(vk_space)) {
20 if (cooldown < 1) {
21 xa = x + lengthdir_x(16, image_angle);
22 ya = y + lengthdir_y(16, image_angle);
23 var inst = instance_create_layer(xa, ya, "Bullets", obj_bullet);
24 inst.direction = image_angle;
25 inst.image_angle = image_angle;
26 inst.speed += speed;
27 cooldown = room_speed / 3;
28 }
29 }
30 cooldown = cooldown - 1;
31
32with (self) {
33 star_gravity();
34}
35
36move_wrap(true, true, sprite_width / 4);Код шейдера пульсара:
1// Vertex shader
2
3attribute vec3 in_Position; // (x,y,z)
4attribute vec4 in_Colour; // (r,g,b,a)
5attribute vec2 in_TextureCoord; // (u,v)
6
7varying vec2 v_vTexcoord;
8varying vec4 v_vColour;
9
10void main()
11{
12 vec4 object_space_pos = vec4( in_Position.x, in_Position.y, in_Position.z, 1.0);
13 gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * object_space_pos;
14
15 v_vColour = in_Colour;
16 v_vTexcoord = in_TextureCoord;
17} 1// Fragment shader
2
3varying vec2 v_vTexcoord;
4varying vec4 v_vColour;
5
6uniform float iTime;
7
8void main()
9{
10 vec2 dir = v_vTexcoord - vec2(.75);
11 float dist = distance(v_vTexcoord, vec2(.25));
12 vec2 offset = dir * (sin(dist * 80. - iTime*15.) + .5) / 30.;
13 vec2 texCoord = v_vTexcoord + offset;
14 gl_FragColor = v_vColour * texture2D( gm_BaseTexture, texCoord );
15}Без шейдера пульсар выглядит так:

А с шейдером так:
Расчёт гравитации пульсара:
1function star_gravity() {
2 star_distance = distance_to_point(room_width/2, room_height/2);
3 if (star_distance > 16) {
4 star_grav = (room_width / star_distance^2);
5 }
6 if (instance_exists(self)) {
7 star_direction = point_direction(room_width/2, room_height/2, x, y);
8 motion_add(star_direction, -0.01*star_grav);
9 }
10}Кстати, если не трогать управление при пролёте пульсара – корабль может выйти на круговую орбиту вокруг него.