«То, что не удаётся запрограммировать на ассемблере, приходится паять» – bash.im/quote/398169
© 1979–2023 Vladimir Igonin
SpaceWar Третья игра на GMS2 – «SpaceWar». Два корабля, пульсар, гравитация и баллистика. Вышло очень динамично!
Вы играете за синий корабль и должны поразить метким (ха!) выстрелом корабль противника. Проблема в пульсаре, расположенном в центре игрового поля. Он обладает мощной гравитацией, и чем вы ближе к нему, тем она сильнее. Гравитация влияет как на траекторию снарядов, так и траекторию кораблей. Управление осуществляется курсорными клавишами.
Вверх ↑
– Тяга.
Влево ←
и Вправо →
– Поворот корабля вокруг своей оси.
Пробел
– Выстрел.
Ваш браузер не поддерживает встраиваемое видео, но не переживайте, вы можете скачать его и смотреть в вашем любимом видеоплеере!
Ссылка на загрузку игры: SpaceWar.zip
На этой игрушке я учился в «GameMaker Studio 2» работе с частицами и шейдерами. Частицы используются при отрисовке взрывов и шлейфов от снарядов. А шейдер создаёт анимацию пульсара. Дальше немного примеров кода из этого проекта.
Код игры в GMS2
Код обработки ввода игрока, событие Step
в объекте obj_ship
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
image_index = 0 ;
if (keyboard_check (vk_left )) {
image_angle += 5 ;
image_index = 2 ;
}
if (keyboard_check (vk_right )) {
image_angle -= 5 ;
image_index = 3 ;
}
if (keyboard_check (vk_up )) {
motion_add (image_angle , 0.05 );
image_index = 1 ;
}
if (keyboard_check_pressed (vk_space )) {
if (cooldown < 1 ) {
xa = x + lengthdir_x (16 , image_angle );
ya = y + lengthdir_y (16 , image_angle );
var inst = instance_create_layer (xa , ya , "Bullets" , obj_bullet );
inst .direction = image_angle ;
inst .image_angle = image_angle ;
inst .speed += speed ;
cooldown = room_speed / 3 ;
}
}
cooldown = cooldown - 1 ;
with (self ) {
star_gravity ();
}
move_wrap (true , true , sprite_width / 4 );
Код шейдера пульсара:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Vertex shader
attribute vec3 in_Position; // (x,y,z)
attribute vec4 in_Colour; // (r,g,b,a)
attribute vec2 in_TextureCoord; // (u,v)
varying vec2 v_vTexcoord;
varying vec4 v_vColour;
void main ()
{
vec4 object_space_pos = vec4( in_Position.x, in_Position.y, in_Position.z, 1.0 );
gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * object_space_pos;
v_vColour = in_Colour;
v_vTexcoord = in_TextureCoord;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Fragment shader
varying vec2 v_vTexcoord;
varying vec4 v_vColour;
uniform float iTime;
void main ()
{
vec2 dir = v_vTexcoord - vec2(.75 );
float dist = distance(v_vTexcoord, vec2(.25 ));
vec2 offset = dir * (sin(dist * 80. - iTime* 15. ) + .5 ) / 30. ;
vec2 texCoord = v_vTexcoord + offset;
gl_FragColor = v_vColour * texture2D( gm_BaseTexture, texCoord );
}
Без шейдера пульсар выглядит так:
Пульсар без шейдера
А с шейдером так:
Ваш браузер не поддерживает встраиваемое видео, но не переживайте, вы можете скачать его и смотреть в вашем любимом видеоплеере!
Расчёт гравитации пульсара:
1
2
3
4
5
6
7
8
9
10
function star_gravity () {
star_distance = distance_to_point (room_width / 2 , room_height / 2 );
if (star_distance > 16 ) {
star_grav = (room_width / star_distance ^ 2 );
}
if (instance_exists (self )) {
star_direction = point_direction (room_width / 2 , room_height / 2 , x , y );
motion_add (star_direction , - 0.01 * star_grav );
}
}
Кстати, если не трогать управление при пролёте пульсара – корабль может выйти на круговую орбиту вокруг него.
Ваш браузер не поддерживает встраиваемое видео, но не переживайте, вы можете скачать его и смотреть в вашем любимом видеоплеере!