Форум программистов, компьютерный форум, киберфорум
C# Windows Forms
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.87/15: Рейтинг темы: голосов - 15, средняя оценка - 4.87
 Аватар для Рядовой
1524 / 914 / 329
Регистрация: 17.05.2015
Сообщений: 3,438

Игра блоки

12.08.2015, 16:20. Показов 3313. Ответов 16
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Пишу игру блоки, разрабатывал на пикчербоксе, но решил перенести отрисовку на форму. Но тут начались проблемы (ранее напрямую на форме не рисовал никогда).
По сути рисовать нужно только блоки.
C#
1
2
3
4
5
6
7
 private void Form1_Paint(object sender, PaintEventArgs e)
        {
            Graphics G = CreateGraphics();
            foreach (Block A in Block)
                A.Paint(G);
            TempPaint(G); // это временный метод для работы с двумерным массивом
        }
Но после отрисовки - изображение пропадает через мгновение.
Перерисовка в таймере - дает моргающую картинку. Двойной буфер - включен.
C#
1
2
3
4
5
6
7
private void timer1_Tick(object sender, EventArgs e)
        {
            IndexBlock();
            FallBlocks();
            IndexBlock();
            Invalidate(); // перерисовка
        }
Вопросы:
1. Рисовать на форме, как я понял, получится только методом OnPaint и событием Form1_Paint?
2. Почему пропадает изображение? Мне ведь не нужно каждый ход таймера перерисовывать, только когда блоки удаляются.
Спасибо, полный код программы внизу.
Кликните здесь для просмотра всего текста
C#
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
 
namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            DoubleBuffered = true;
            for (int i = 0; i < 405; i += 27)
                for (int j = 0; j < 405; j += 27)
                    Block.Add(new Block(j, i, color()));
        }
        static Random D = new Random();
        public int Left = 0;
        List<Block> Block = new List<Block>();
        int[,] index = new int[15, 15];
        #region Methods
        private void IndexBlock()
        {
            for (int i = 0; i < 15; i++)
                for (int j = 0; j < 15; j++)
                    index[i, j] = 0;
            foreach (Block A in Block)
            {
                if (A.Col == Color.Aqua)
                {
                    index[A.posX / 27, A.posY / 27] = 1;
                    continue;
                }
                if (A.Col == Color.MediumBlue)
                {
                    index[A.posX / 27, A.posY / 27] = 2;
                    continue;
                }
                if (A.Col == Color.Gold)
                {
                    index[A.posX / 27, A.posY / 27] = 3;
                    continue;
                }
                if (A.Col == Color.Red)
                {
                    index[A.posX / 27, A.posY / 27] = 4;
                    continue;
                }
                if (A.Col == Color.Magenta)
                {
                    index[A.posX / 27, A.posY / 27] = 5;
                    continue;
                }
            }
        }
        private void TempPaint(Graphics g)
        {
            Font font1 = new Font("TimesNewRoman", 9);
 
            for (int i = 0; i < 15; i++)
                for (int j = 0; j < 15; j++)
                {
                    RectangleF xy = new RectangleF(j * 27, i * 27, 27, 27);
                    g.DrawString(index[j, i].ToString(), font1, Brushes.Black, xy);
                }
        }
        private void FallBlocks()
        {
            for (int i = 0; i < 405; i += 27)
                for (int j = 0; j < 405; j += 27)
                    if (index[j / 27, i / 27] == 0)
                        foreach (Block A in Block)
                            if (A.posY < i && A.posX == j)
                                A.posY += 27;
        }
        private bool FallLeftTrue()
        {
            for (int i = 0; i < 15; i++)
            {
                for (int j = 0; j < 15; j++)
                {
                    if (j == 14 && index[i, j] == 0)
                    {
                        Left = i * 27;
                        return true;
                    }
                    if (index[i, j] != 0)
                        break;
                }
            }
            return false;
 
        }
        private Color color()
        {
            int a = D.Next(1, 6);
            switch (a)
            {
                case (1):
                    return Color.Aqua;
                case (2):
                    return Color.MediumBlue;
                case (3):
                    return Color.Gold;
                case (4):
                    return Color.Red;
                default:
                    return Color.Magenta;
            }
        }
        private void DeleteBlock(int X, int Y)
        {
            for (int a = 0; a < Block.Count; a++)
                for (int i = Block[a].posY; i < (Block[a].posY + 27); i++)
                    for (int j = Block[a].posX; j < (Block[a].posX + 27); j++)
                    {
                        if (Y == i && X == j && TrueDelete(Block[a].posX, Block[a].posY))
                        {
                            IndexTrue(Block[a].posX, Block[a].posY);
                            Block.RemoveAll(d => d.Index == true);
                            return;
                        }
                    }
        }
        private void FallLeft()
        {
            foreach (Block A in Block)
            {
                if (A.posX > Left)
                {
                    index[A.posX / 27, A.posY / 27] = 0;
                    A.posX -= 27;
                }
            }
        }
        private bool TrueDelete(int a, int b)
        {
            int col = index[a / 27, (b / 27)];
            int rig = 0, lef = 0, up = 0, dow = 0;
            try { rig = index[(a + 27) / 27, b / 27]; }
            catch { ;}
            try { lef = index[(a - 27) / 27, b / 27]; }
            catch { ;}
            try { up = index[a / 27, (b - 27) / 27]; }
            catch { ;}
            try { dow = index[a / 27, (b + 27) / 27]; }
            catch { ;}
            if (col == rig || col == lef || col == up || col == dow)
                return true;
            return false;
 
        }
        private void IndexTrue(int a, int b)
        {
            int Q = Block.FindIndex(d => d.posX == a && d.posY == b);
            Block[Q].Index = true;
            int col = index[a / 27, (b / 27)];
            int rig, lef, up, dow;
            try
            {
                rig = index[(a + 27) / 27, b / 27];
                if (rig == col)
                {
 
                    int Qrig = Block.FindIndex(d => d.posX == (a + 27) && d.posY == b);
                    if (Block[Qrig].Index == false)
                        IndexTrue(Block[Qrig].posX, Block[Qrig].posY);
                }
            }
            catch { ;}
            try
            {
                lef = index[(a - 27) / 27, b / 27];
                if (lef == col)
                {
 
                    int Qlef = Block.FindIndex(d => d.posX == (a - 27) && d.posY == b);
                    if (Block[Qlef].Index == false)
                        IndexTrue(Block[Qlef].posX, Block[Qlef].posY);
                }
            }
            catch { ;}
            try
            {
                up = index[a / 27, (b + 27) / 27];
                if (up == col)
                {
 
                    int Qup = Block.FindIndex(d => d.posX == a && d.posY == (b + 27));
                    if (Block[Qup].Index == false)
                        IndexTrue(Block[Qup].posX, Block[Qup].posY);
                }
            }
            catch { ;}
            try
            {
                dow = index[a / 27, (b - 27) / 27];
                if (dow == col)
                {
 
                    int Qdow = Block.FindIndex(d => d.posX == a && d.posY == (b - 27));
                    if (Block[Qdow].Index == false)
                        IndexTrue(Block[Qdow].posX, Block[Qdow].posY);
                }
            }
            catch { ;}
 
 
 
        }
        #endregion
        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            Graphics G = CreateGraphics();
            foreach (Block A in Block)
                A.Paint(G);
            TempPaint(G);
        }
        private void timer1_Tick(object sender, EventArgs e)
        {
            IndexBlock();
            FallBlocks();
            IndexBlock();
            Invalidate();
        }
        private void Form1_MouseClick(object sender, MouseEventArgs Click)
        {
            DeleteBlock(Click.X, Click.Y);
            FallBlocks();
            IndexBlock();
            if (FallLeftTrue())
                FallLeft();
            Invalidate();
            
        }
    }
    public class Block
    {
        public Block(int X, int Y, Color C)
        {
            posX = X;
            posY = Y;
            Col = C;
        }
        public int posX;
        public int posY;
        public Color Col;
        public bool Index = false;
        public void Paint(Graphics g)
        {
            SolidBrush one = new SolidBrush(Color.Black);
            SolidBrush two = new SolidBrush(Col);
            g.FillRectangle(one, posX, posY, 27, 27);
            g.FillRectangle(two, posX, posY, 25, 25);
        }
 
    }
}
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
12.08.2015, 16:20
Ответы с готовыми решениями:

Игра Блоки
Нашел в интернете игру блоки. Более менее разобрался в коде, но не знаю как сделать так, чтобы при отсутствии рядом стоящих одноцветных...

Игра : блоки (уничтожение по цвету)
Всем привет, очень нужна помощь с курсовой, в общем тема такая, нужно написать игру на с++ builder`е, игра что то на подобии тетриса, но...

Игра блоки(подобие тетриса)
Всем привет, есть задание на курсовой проект &quot;игра блоки&quot; очень нужна ваша помощь в написании этой игры , поскольку у самого мозгов на это...

16
 Аватар для Sanya_sa
912 / 816 / 333
Регистрация: 03.02.2015
Сообщений: 5,276
Записей в блоге: 9
12.08.2015, 20:38
Лучший ответ Сообщение было отмечено Рядовой как решение

Решение

Наслаждайтесь игрой
Вложения
Тип файла: rar Blocs.rar (59.6 Кб, 141 просмотров)
0
 Аватар для Рядовой
1524 / 914 / 329
Регистрация: 17.05.2015
Сообщений: 3,438
13.08.2015, 01:08  [ТС]
Sanya_sa, спасибо, а можно пару комментариев?
Заменил в своем проекте событие Form1_Paint на OnPaint, убрал таймер, но изображение все равно пропадает, у вас нет, что я упускаю?
0
 Аватар для Sanya_sa
912 / 816 / 333
Регистрация: 03.02.2015
Сообщений: 5,276
Записей в блоге: 9
13.08.2015, 07:48
Да вроде все понятно. Просто переопределяем OnPaint и делаем в нем свои отрисовки. Вот тут довольно понятно описано http://wm-help.net/lib/b/book/656723049/188 например.
0
 Аватар для Рядовой
1524 / 914 / 329
Регистрация: 17.05.2015
Сообщений: 3,438
13.08.2015, 08:53  [ТС]
Разобрался, вся проблема была в этой строке
C#
1
Graphics G = e.Graphics;
Я вместо нее создавал новую поверхность рисования..
0
 Аватар для Рядовой
1524 / 914 / 329
Регистрация: 17.05.2015
Сообщений: 3,438
18.08.2015, 21:38  [ТС]
Господа, как лучше отслеживать блок по которому кликаю?
Делал тотальным перебором:
C#
1
2
3
4
for (int a = 0; a < Block.Count; a++)
                for (int i = Block[a].posY; i < (Block[a].posY + 27); i++)
                    for (int j = Block[a].posX; j < (Block[a].posX + 27); j++)
                        if (Y == i && X == j)// Y и X - это координаты клика на форме
Но чувствую это существенно тормозит, пробовал такое:
C#
1
2
3
4
private void Form1_MouseClick(object sender, MouseEventArgs Click)
        {
              Block A = (Block)sender;...
        }
Но не компилит. Тип объекта Form1 нельзя привести к типу Block.
Есть варианты ускорить первоначальную процедуру?
0
 Аватар для tarasalk
1992 / 1216 / 440
Регистрация: 13.06.2013
Сообщений: 4,115
18.08.2015, 22:12
Рядовой, если вы прям на форме рисуете то скорее всего только перебор. Но не обязательно перебирать все фигуры. С ходу пока не могу придумать оптимальный алгоритм, но явно если кликнули в верхнюю половину формы, то нет смысла проверять блоки лежащие в нижней половине формы.
Впрочем если у вас там не 100500 блоков, то одноразовый поиск по клику едва ли будет существенно тормозить. Лучше замерьте реальное затрачиваемое время.

Добавлено через 11 минут
Кстати тотальный перебор у вас очень странный. Зачем каждый пиксель перебирать, когда можно проверять находится ли точка клика внутри блока.
Вот такой код у меня работает.
C#
1
2
3
4
5
6
7
8
9
10
11
12
for (int a = 0; a < Block.Count; a++)
{
    if(X > Block[a].posX &&
        X < Block[a].posX + 27 &&
        Y > Block[a].posY &&
        Y < Block[a].posY + 27)
    {
        IndexTrue(Block[a].posX, Block[a].posY);
        Block.RemoveAll(d => d.Index == true);
        return;
    }
}
Я тут правда не учел клик по границе блока, но это уж сами)
1
 Аватар для Рядовой
1524 / 914 / 329
Регистрация: 17.05.2015
Сообщений: 3,438
18.08.2015, 22:17  [ТС]
Блин, так всегда, весь день голову ломал а тут написал на форум и просветление))
Если разделить координаты клика на сторону квадрата и отбросить остаток получу координаты блока, а если рассчитывать в int даже не придется откидывать остаток:
C#
1
2
int x = X / 27*27; 
int y = ((Y-30) / 27*27)+30;//здесь пришлось изгалятся, т.к. верхняя строка блоков опущена
Добавлено через 4 минуты
tarasalk, о! еще один вариант, гораздо лучше первоначального)
0
 Аватар для Sanya_sa
912 / 816 / 333
Регистрация: 03.02.2015
Сообщений: 5,276
Записей в блоге: 9
19.08.2015, 09:49
Цитата Сообщение от Рядовой Посмотреть сообщение
Есть варианты ускорить первоначальную процедуру?
Банально всё )
C#
1
2
3
4
5
6
7
8
9
10
11
        int IDblock = 0;
 
        for (int i = 0; i < Block.Count; i++)
            {
                if (Math.Abs(Block[i].posY - e.Y) <= 20 && Math.Abs(Block[i].posX - e.X) <= 20)
                {
                    // здесь смотрим переменную i - это номер блока в листе
                    IDblock = i;
                    break;
                }
            }
e.Y и e.X - координаты клика мыши. Удачи!

Добавлено через 11 часов 5 минут
К стати можно и сразу непосредственно блок получить
C#
1
2
3
4
5
6
7
8
9
            foreach (var b in Block)
            {
                if (Math.Abs(b.posY - e.Y) <= 20 && Math.Abs(b.posX - e.X) <= 20)  
                {
                    // можно например сразу его покрасить
                    b.Col = Color.Black;
                    break;
                 }
            }
1
 Аватар для Рядовой
1524 / 914 / 329
Регистрация: 17.05.2015
Сообщений: 3,438
19.08.2015, 22:00  [ТС]
Более менее закончил игру, насколько мог, оптимизировал. Играть можно, но есть несколько проблем:
1. У чеклистбокса нет цвета трансперент?
2. Как сделать чтобы в чекбоксе не выделялся выбранный компонент голубым? на черном плохо смотрится
3. Сделал фон, всего 120 кб, но притормаживает выезд новых блоков при частых кликах, на белом фоне - без тормозов. Если скачаете - будет видно. Может у меня сама видеокарта тормозит? встроенная на 64мб, а там обновление изображение каждые 4мс, чтобы глаз не замечал.
Вложения
Тип файла: rar блоки2.rar (542.6 Кб, 25 просмотров)
1
 Аватар для Sanya_sa
912 / 816 / 333
Регистрация: 03.02.2015
Сообщений: 5,276
Записей в блоге: 9
20.08.2015, 09:44
рекомендации:
1) Image sprt = (Bitmap)Image.FromFile("C:\\b.png"); Вот это "C:\\b.png" - плохо, например у меня этого файла нет).
Я бы сохранил все в ресурсы (см мой блог "Мяч"). Со звуком по ходу та же проблема.

по Вашим вопросам
1) У чеклистбокса нет цвета трансперент? - не знаю не пользовался им), но у обычного чека(СheckBox) точно есть.
2) Как сделать чтобы в чекбоксе не выделялся выбранный компонент голубым? на черном плохо смотрится. С лёту не скажу, но опять же СheckBox Вам в помощь. В таких случаяи если не устраивают стандартные контролы лучше свой сделать и заточить его под свои задачи.
3) Сделал фон, всего 120 кб, но притормаживает выезд новых блоков при частых кликах, на белом фоне - без тормозов. Если скачаете - будет видно. Может у меня сама видеокарта тормозит? встроенная на 64мб, а там обновление изображение каждые 4мс, чтобы глаз не замечал.
а) GDI+ видеокарта вторична
б) человеческий глаз различает 25 кадров в секунду, от сюда вывод более частые отрисовки смысла делать нет, я так думаю, Вы просто проц загружаете, а глазу всё равно 1000 кадров в секунду пролетело или 25 .
в) посмотрите мой блог "Мяч" там вариант задания скорости (скорости перемещения обьектов и отрисовки - разное)

Удачи

PS мне Ваша игра нравится )

Добавлено через 5 минут
снять выделение
C#
1
2
3
4
private void checkedListBox1_MouseUp(object sender, MouseEventArgs e)
        {
            checkedListBox1.SetSelected(0, false);
        }
1
 Аватар для Рядовой
1524 / 914 / 329
Регистрация: 17.05.2015
Сообщений: 3,438
20.08.2015, 13:32  [ТС]
Sanya_sa, черт, я совсем забыл про ресурсы, ссори
По вашему совету заменил листбокс на простой чекбокс - проблем как не бывало, спасибо)
На счет фона: посчитал - частота обновления картинки глаза - 41 с мелочью мс. Выставил такой шаг таймера - но увы, тормоза остались, у вас тоже?
Таймер с ресурсами прикрепил (звук просто ужас)
Вложения
Тип файла: rar блоки2.rar (1.08 Мб, 38 просмотров)
0
 Аватар для Sanya_sa
912 / 816 / 333
Регистрация: 03.02.2015
Сообщений: 5,276
Записей в блоге: 9
20.08.2015, 13:42
Цитата Сообщение от Рядовой Посмотреть сообщение
Выставил такой шаг таймера - но увы, тормоза остались, у вас тоже?
Цитата Сообщение от Рядовой Посмотреть сообщение
Выставил такой шаг таймера - но увы, тормоза остались, у вас тоже?
это мерцания при "выползании" новых блоков?
0
 Аватар для Рядовой
1524 / 914 / 329
Регистрация: 17.05.2015
Сообщений: 3,438
20.08.2015, 13:47  [ТС]
это мерцания при "выползании" новых блоков?
Нет, когда часто кликаешь, возникает много взрывов и прям видно ход выползания блоков снижается, если не кликать - не тормозит
0
 Аватар для Sanya_sa
912 / 816 / 333
Регистрация: 03.02.2015
Сообщений: 5,276
Записей в блоге: 9
20.08.2015, 17:37
Лучший ответ Сообщение было отмечено Рядовой как решение

Решение

В двух таймерах вызывается Invalidate(). Попробуйте убрать из TimerExp. Но у меня не тормозит и с двумя.

Добавлено через 8 минут
Да и при клике тоже Invalidate(). Думаю слиш комного Invalidate() их

1) При клике - Invalidate() движение новых блоков + Invalidate() клика + Invalidate()TimerExp

2) Интервал TimerExp не имеет смысла делать меньше 40

Добавлено через 1 минуту
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 private void TimerExp_Tick(object sender, EventArgs e)
        {
            for (int t = 0; t < SpeedBoom; t++)
            {
                if (sprite.CurrentFrame >= 16)
                {
                    FlagExp = false;
                    TimerExp.Enabled = false;
                    sprite.CurrentFrame = -1;
                }
                else
                    sprite.GotoNextFrame();
            }
        }
Я бы так сделал. И скорость для движения новых блоков аналогично можно задавать.

Добавлено через 8 минут
label1.Text = "Score: " + Score; Вот эта штука постоянно в таймите тарахти - не айс)
0
 Аватар для Sanya_sa
912 / 816 / 333
Регистрация: 03.02.2015
Сообщений: 5,276
Записей в блоге: 9
20.08.2015, 17:47
Ну как то так. Посмотрите быстрее на Вашем компе стало работать?
Вложения
Тип файла: 7z блоки_оптимизация.7z (785.8 Кб, 34 просмотров)
0
 Аватар для Рядовой
1524 / 914 / 329
Регистрация: 17.05.2015
Сообщений: 3,438
21.08.2015, 01:47  [ТС]
Sanya_sa, отличная идея совместить таймеры)
да, так не тормозит, но тест производителности показал что при частых кликах проц серьезно грузится)
Печально думать что такой простой код так его грузит)
Все понравилось кроме обновления лейбла) уж он то точно тут не причем) это все рекурсивные поиски схожих блоков..
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
21.08.2015, 01:47
Помогаю со студенческими работами здесь

Разбить строку на блоки, а затем эти блоки на отдельные слова
...доброго времени суток, уважаемые форумчане! Возникла задача - разбить строку на блоки, а затем эти блоки на отдельные слова. Не могу...

Пакетированные стандартные блоки - Вложенные стандартные блоки
Кто нибудь может объяснить на примере кода С, как это выглядит?

Бюджет 4500 гр. Конфигурация работа в Office, AutoCAD, игра Assassin, онлайн игра World of Tanks
Собираю компьютер для сестры. Основные требования: работа в Microsoft Office, AutoCAD, игра Assassin, онлайн игра World of Tanks ...

Игра в загадки. Загадать загадку. Если ответ верен – поздравить пользователя. Затем сообщить, что игра окончена.
Всем привет! Меня зовут VitoScaletta, совсем недавно начал обучаться JS, но очень тяжело в голову заходит информация, но я не сдаюсь! В...

Игра в «Одиннадцать предметов», игра Баше.
прошу помощи в создании программы! Разработать программную модель следующей игры двух игроков(пользователь-компьютер),реализовав...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru