Заметки за 2022 год

SpaceWar

Третья игра на GMS2 – «SpaceWar». Два корабля, пульсар, гравитация и баллистика. Вышло очень динамично!

Вы играете за синий корабль и должны поразить метким (ха!) выстрелом корабль противника. Проблема в пульсаре, расположенном в центре игрового поля. Он обладает мощной гравитацией, и чем вы ближе к нему, тем она сильнее. Гравитация влияет как на траекторию снарядов, так и траекторию кораблей. Управление осуществляется курсорными клавишами.

Вверх ↑ – Тяга.

Влево ← и Вправо → – Поворот корабля вокруг своей оси.

Пробел – Выстрел.

Ссылка на загрузку игры: SpaceWar.zip

На этой игрушке я учился в «GameMaker Studio 2» работе с частицами и шейдерами. Частицы используются при отрисовке взрывов и шлейфов от снарядов. А шейдер создаёт анимацию пульсара. Дальше немного примеров кода из этого проекта.

Код игры в GMS2
Код игры в GMS2

Код обработки ввода игрока, событие 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}

Кстати, если не трогать управление при пролёте пульсара – корабль может выйти на круговую орбиту вокруг него.