Форум программистов, компьютерный форум, киберфорум
Assembler: DOS/Real Mode/16-bits
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.54/13: Рейтинг темы: голосов - 13, средняя оценка - 4.54
1 / 1 / 0
Регистрация: 09.03.2018
Сообщений: 30

Перемещение простых геометрических объектов по экрану мышкой

04.09.2020, 14:19. Показов 2847. Ответов 6

Студворк — интернет-сервис помощи студентам
Здравствуйте
Нужно составить программу, которая позволяет перемещать по экрану простые геометрические объекты (треугольник,
прямоугольник и т.п.) с помощью мыши.
Предусмотреть изменение цвета объектов.
Режим экрана графический.
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
04.09.2020, 14:19
Ответы с готовыми решениями:

Имитация движения простых геометрических объектов
Помогите написать программу в visual studio c++ Нужно разработать программу, имитирующую движение таких объектов как круг, треугольник,...

Перемещение объектов мышкой
Здравствуйте, наткнулся на статью http://javascript.ru/ui/draganddrop. Есть, ли аналогичная, но по jQuery? Скиньте пожалуйста. Хочу...

Перемещение объектов мышкой
Добрый день, помогите разобраться! В общем есть кнопка, при клике на нее достается мувиклип из библиотеки, и при отпуске кнопки объект...

6
Модератор
Эксперт по электронике
 Аватар для ФедосеевПавел
8657 / 4491 / 1670
Регистрация: 01.02.2015
Сообщений: 13,899
Записей в блоге: 12
04.09.2020, 16:26
Tonia_, сама по себе задача не сложная, но размер итогового кода будет значительным.
Можно сделать код сильно маленьким за счёт прямой записи в память и разных трюков, но читать и защищать его будет сложно.

Сейчас только начало учебного года и вы вполне можете успеть всё сделать самостоятельно.
Отдельные подзадачи многократно решались, алгоритмы рисования линий реализовывались. Что-то даже в FAQ для раздела Assembler, MASM, TASM рассматривалось и пояснялась теория. FAQ - не идеал, что-то лучше рассматривалось и в темах.

Если будут вопросы - задавайте.
1
 Аватар для Kukuxumushu
1624 / 806 / 146
Регистрация: 13.06.2015
Сообщений: 3,266
04.09.2020, 19:45
Цитата Сообщение от ФедосеевПавел Посмотреть сообщение
сама по себе задача не сложная
Цитата Сообщение от ФедосеевПавел Посмотреть сообщение
за счёт прямой записи в память
Ага, особенно когда объекты будут уводить из края экрана и накладывать друг на друга.
1
2642 / 1653 / 267
Регистрация: 19.02.2010
Сообщений: 4,375
04.09.2020, 20:52
Если бы под Виндой, а не под ДОСом...
Под Виндой, если задать некоторое ограничение насчёт размеров объектов, будет сильно проще.
А именно - объекты предварительно рисуются (в редакторе ресурсов) в размер виндовозного курсора. Вернее, в двух вариантах - как обычный битмап для отрисовки на экране (и тут мне лень думать/вспоминать, как там проще потом будет задавать-менять цвета), и как курсор (но - немного отличаясь при этом от исходного битмапа, дабы показать выделение именно этого объекта). Затем все эти ресурсы надо будет прицепить к проге.
И при нажатии мышой на какой-то из кинутых в окно объектов - этот объект удаляется и виндовозный курсор-стрелка меняется на соответствующий объекту курсор. Последующее таскание объекта по экрану происходит автоматом - в смысле, не надо будет перерисовывать ни фон, ни накрываемых объектов. А при отпускании мышиной кнопки - курсор меняется обратно на стрелку, и объект рисуется битмапом в новом месте.
Т.е. из необходимой для программирования алгоритмики (в смысле - циклы и структуры данных) оставалась бы только работа со списком объектов (их координаты на экране, их цвета, коды объектов) - дабы при нажатии на кнопку мыши искать-определять, какой объект выбрали. Всё остальное выходило бы в виде линейных последовательностей операций. В принципе, и под ДОСом так же будет - но посложнее (вместо использования ряда готовых функций ВинАПИ придётся кодить врукопашную).
1
Модератор
Эксперт по электронике
 Аватар для ФедосеевПавел
8657 / 4491 / 1670
Регистрация: 01.02.2015
Сообщений: 13,899
Записей в блоге: 12
04.09.2020, 21:15
Kukuxumushu,
Это уже детали. Можно ограничить перемещение и фигуры и курсора мыши (менять ограничение при захвате и отпускании фигуры) для постоянного полного изображения фигуры без обрезания. Ещё что-нибудь учудить.

Можно менять курсор мыши в зависимости от режима - свободное перемещение (стрелка), перемещение фигуры (кулак), выбор цвета (пипетка).

Можно красиво оформить экран - основное окно для фигуры, дополнительное окно для выбора цвета мышкой, окно с подсказками. Окна можно залить фоновым цветом, обрамить рамкой. Внизу сделать строку состояния с отображением координат мыши, фигуры, цвета, режима мыши. Можно менять графический режим - разрешение.

Когда готова основа - найдётся и что улучшать.

Не по теме:

А! Понял!
Мы по разному воспринимаем ТЗ.
Образно:
Я - разговариваю с коллегой - хвастаюсь, что уже решал каждую подзадачу и не вижу проблем со знанием способов решения и с поиском образцов.
Вы - разговариваете с заказчиком - показываете общие трудозатраты (искренне сомневаюсь, что Вы не представляете способы решения, особенно с учётом гораздо меньших реальных требований к программе со стороны преподавателя).

1
Модератор
1245 / 676 / 292
Регистрация: 10.11.2019
Сообщений: 1,406
05.09.2020, 14:48
Лучший ответ Сообщение было отмечено ФедосеевПавел как решение

Решение

Частой ошибкой начинающих программистов является то, что они, следуя указаниям из книг,
пытаются создать программу, которая напрямую выводит изображение в видеопамять компьютера.
При этом как правило возникает следующий результат. Вывести точку или линию можно достаточно
быстро, но при выводе сложного изображения мы сталкиваемся с такими эффектами как мерцание,
резкое замедление скорости. Легко можно проверить то, что функции BIOS по выводу точки
в графических режимах работают настолько медленно, что не пригодны для практики.
Между тем, в профессионально написанных программах (в том числе в Windows)
и играх мы таких проблем не наблюдаем. Всё дело в том, что обмен компьютера с видеокартой,
происходит примерно в 10 (а иногда в 50, см тесты) медленней, чем при работе центрального процессора
с ОЗУ (RAM). Программа vidspeed.com наглядно демонстрирует это. Более того.
Чтение из видеопамяти происходит ещё медленнее, чем запись, поэтому
операция "чтение-модификация-запись" создает большие проблемы, если работать
с видеоплатой напрямую. Есть выход: использовать описанные в книгах алгоритмы отображения
графики, но в качестве видео буфера применять не видео память, а оперативную память
компьютера. При этом сразу достигается выигрыш в быстродействии в несколько десятков раз.
Затем особой подпрограммой (она у нас называется sync) результирующее изображение
пересылается на видеокарту. Такой подход называется двойной буферизацией.
Есть ещё вариант - переключение видеостраниц, когда вся память (например
"старого" VGA 256 кбайт) разбивается на страницы (например на 4 по 64 кбайт).
Видеокарта отображает одну страницу, а программа в это время рисует на другой
(невидимой), затем страницы очень быстро переключаются с помощью регистров
видеокарты. В плане быстродействия эти два способы сравнимы - на современных
компьютерах быстрее работает двойная буферизация, в эмуляторе DOSBOX почти
нет разницы. Однако переключение страниц имеет большой недостаток - например
режим 320*200*256 цветов VGA с 4 страницами (mode X) совершенно не поддерживается
BIOS. т е для того, чтобы вывести даже отладочную информацию, требуется сначала написать
программу отрисовки букв. Очевидно, что этот режим слишком сложен.

Поэтому мы будем использовать стандартный режим BIOS VGA 13h и рисовать
изображение в обычном ОЗУ. Здесь есть ещё одна трудность:
мы не видим результат при записи в буфер RAM до тех пор, пока не выполнена
команда sync. Это очень осложняет отладку. Мы можем просто промахнуться при записи байта
мимо нашего видео буфера, и программа или эмулятор зависнет, прежде чем мы выполним
команду sync. Здесь можно предложить такой выход: мы сначала пишем и отлаживаем программу
для работы в обычной видеопамяти, а затем переделываем низкоуровневые подпрограммы
(plot, cls, sync) для работы с буфером RAM.

Идея программы такая: мы в бесконечном цикле
опрашиваем состояние мышки, и если левая кнопка мышки не нажата,
то вызываем подпрограмму selectmobs, которая выбирает объект под
курсором. Если же лкм нажата, мы вызываем подпрограммы

Assembler
1
2
3
    call cls    ; стереть невидимую память
    call drawtest   ; нарисовать изображение в невидимой памяти
    call sync   ; копировать изображение на экран

Может показаться, что подпрограммы cls и sync довольно медленные,
так как они имеют дело с памятью целого экрана. Но на самом деле
эти подпрограммы оптимизированы с помощью команды rep movsd,
в то время как отрисовка линий в центральной подпрограмме drawtest
требует массы операций с координатами и адресами точек.
Для построения линий нам нужна быстродействующая подпрограмма.

Такая подпрограмма основана на алгоритме Брезенхема и была
переведена напрямую с примера на языке QBasic

пример на QBasic

QBasic/QuickBASIC
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
' Реализация алгоритма Брезенхема построения линии
' См подпрограмму drawline в ассемблерном тексте
DECLARE SUB drawLine (x1%, y1%, x2%, y2%, col%)
'qbasic
DEFINT A-Z
SCREEN 7
FOR i = 0 TO 200 STEP 20
drawLine 0, 0, 319, i, 14
drawLine 0, 199, 319, i, 15
NEXT i
 
SUB drawLine (x1, y1, x2, y2, col)
deltaX = ABS(x2 - x1)
deltaY = ABS(y2 - y1)
IF x1 < x2 THEN signX = 1 ELSE signX = -1
IF y1 < y2 THEN signY = 1 ELSE signY = -1
    
er = deltaX - deltaY
 
PSET (x2, y2), col
 
WHILE (x1 <> x2) OR (y1 <> y2)
PSET (x1, y1), col
er2 = er * 2
IF (er2 > -deltaY) THEN er = er - deltaY: x1 = x1 + signX
IF (er2 < deltaX) THEN er = er + deltaX: y1 = y1 + signY
WEND
END SUB
Подпрограмма drawline уже достаточно легко позволяет рисовать фигуры
из ломаных, см подпрограмму drawshape. Нужно лишь рассчитать координаты
точек линии относительно центра фигуры, например для квадрата:

Assembler
1
2
3
4
5
6
7
shape4  label word ; квадрат
    dw 4
    dw -40,-32
    dw 40,-32
    dw 40,32
    dw -40,32
    dw -40,-32
(с учетом того, что режим 320*200 имеет коэффициент растяжения 1.2)
Первое слово - число линий, далее идут координаты x,y относительно центра фигуры.

Программа movobj написана как com файл, хотя сегмента фактически 2 - за вершиной стека
идёт видеобуфер (64000 байт) Программа предназначена для запуска в DosBox, хотя
у меня на XP нормально запускается и без эмулятора.

bat - файл компиляции

Windows Batch file
1
2
3
4
5
6
@echo off
path c:\ваш_путь_к_tasm
tasm movobj.asm,,lst
tlink /t movobj
del movobj.obj
del movobj.map
И наконец сам текст программы:

Программа movobj.asm

Assembler
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
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
; Программа отрисовки объектов и их перемещения мышкой
; Использовался Turbo Assembler 4.0
; Компилируется в COM файл
 
    .286
    .model small
    .code
    assume ds:_text
 
; вызов функций мыши
mouse   macro val
    mov ax,val
    int 33h
    endm
 
mouseShow macro
    mouse 1
    endm
 
mouseHide macro
    mouse 2
    endm
 
mousePoll macro
    mouse 3
    endm
 
codesize = 2000h
; начало программы
    org 100h
start:  mov sp,codesize-2
    jmp beg
 
; включается файл проведения линии по алгоритму Брезенхема
; (подпрограммы plot - вывод точки, drawline - вывод линии, invoke - макро вывода линии)
;   include linebrez.inc
 
; linebrez.inc начало **********
 
; аргументы вызова - координаты линии и цвет
; эти переменные заносятся в стек перед вызовом drawline
; см invoke
x1  equ word ptr [bp+12]
y1  equ word ptr [bp+10]
x2  equ word ptr [bp+8]
y2  equ word ptr [bp+6]
col equ byte ptr [bp+4]
 
; внутренние переменные drawline
; эти переменные существуют только в процессе работы drawline
deltaX  equ word ptr [bp-2]
deltaY  equ word ptr [bp-4]
signX   equ word ptr [bp-6]
signY   equ word ptr [bp-8]
er  equ word ptr [bp-10]
er2 equ word ptr [bp-12]
 
; вывод точки
; x=cx, y=dx, color=al
plot:   push di
    push es
    cmp cx,320 ; координаты выходят за границы экрана ?
    jnc pl1
    cmp dx,200
    jnc pl1
    push ax
    mov ax,320 ; di=320*y+x
    mul dx
    add ax,cx
    mov di,ax
; отрисовка в обычной памяти, а не в видео
    mov ax,cs ; 0A000h
    add ax,codesize/16
    mov es,ax
    pop ax
    mov es:[di],al ; выводим точку
pl1:    pop es
    pop di
    ret
 
; вывод линии
; SUB drawLine (x1, y1, x2, y2, col)
; Пример вызова:
; invoke drawline, <10,10,310,10,15>
 
drawline proc
    push bp   ; пролог Сохраняем bp в стеке
    mov bp,sp ; далее мы адресуем переменные с помощью bp
    sub sp,16 ; выделяем место под локальные переменные
    push ax
    push bx
    push cx
    push dx
;deltaX = ABS(x2 - x1)
    mov ax,x2
    sub ax,x1
    jge lin1
    neg ax
lin1:   mov deltaX,ax
;deltaY = ABS(y2 - y1)
    mov ax,y2
    sub ax,y1
    jge lin2
    neg ax
lin2:   mov deltaY,ax
;IF x1 < x2 THEN signX = 1 ELSE signX = -1
    mov bx,1
    mov ax,x1
    cmp ax,x2
    JL  lin3
    neg bx
lin3:   mov signX,bx
;iF y1 < y2 THEN signY = 1 ELSE signY = -1
    mov bx,1
    mov ax,y1
    cmp ax,y2
    JL  lin4
    neg bx
lin4:   mov signY,bx
;er = deltaX - deltaY
    mov ax,deltaX
    sub ax,deltaY
    mov er,ax
;PSET (x2, y2), col
    mov cx,x2
    mov dx,y2
    mov al,col
    call plot
; основной цикл построения линии
;WHILE (x1 <> x2) OR (y1 <> y2)
wil1:   mov ax,x1
    cmp ax,x2
    jnz wil2
    mov ax,y1
    cmp ax,y2
    jnz wil2
    jmp wend
wil2:   
;PSET (x1, y1), col
    mov cx,x1
    mov dx,y1
    mov al,col
    call plot
;er2 = er * 2
    mov ax,er
    add ax,ax
    mov er2,ax
;IF (er2 > -deltaY) THEN er = er - deltaY: x1 = x1 + signX
    mov ax,er2
    add ax,deltaY
    JLE lin5
    mov ax,er
    sub ax,deltaY
    mov er,ax
    mov ax,x1
    add ax,signX
    mov x1,ax
lin5:
;IF (er2 < deltaX) THEN er = er + deltaX: y1 = y1 + signY
    mov ax,er2
    cmp ax,deltaX
    jge lin6
    mov ax,er
    add ax,deltaX
    mov er,ax
    mov ax,y1
    add ax,signY
    mov y1,ax
;WEND
lin6:   jmp wil1
wend:   pop dx
    pop cx
    pop bx
    pop ax
    mov sp,bp ; эпилог, восстанавливаем sp
    pop bp    ; восстанавливаем bp
    ret 10    ; делаем возврат и продвигаем стек на 5*2=10 байт (т к 5 аргументов хранилось в стеке)
drawline endp
 
; макро вызова drawline См lst.lst, какой код генерит это макро
 
invoke macro CallProc,Params
    IRP P,<Params>
        mov ax, P
        push ax
        
    endm
    call CallProc
endm
 
; linebrez.inc конец  **********
 
prnbuf  db "000",0 ; буфер вывода числа
 
; установить позицию курсора
setcur  macro yy
    mov al,yy
    call setcursub
    endm
 
setcursub:pusha
    mov dl,0  ; cursorx=0
    mov dh,al ; cursory=al
    mov bh,0
    mov ah,2
    int 10h
    popa
    ret
 
; очистить видео буфер
cls:    push es
    pusha
    mov ax,cs     ; буфер находится по сегменту cs+codesize/16:0 ...
    add ax,codesize/16
    mov es,ax
    mov di,0
    mov cx,320*200/4 ; ... длина буфера 64000 байт
    db  66h   ; префикс 32разрядного режима
    xor ax,ax ; xor eax,eax т е eax=0
    db  66h   ; префикс 32разрядного режима
    rep stosw ; rep stosd
    popa
    pop es
    ret
 
; переписать буфер в видео память VGA 
sync:   push ds
    push es
    pusha
; этот фрагмент устраняет мерцание курсора мыши
    mov dx,3DAh
syncwt1:in   al,dx ; ожидать начала обратного хода луча видеоразвертки
    test al,8
    jnz   syncwt1
syncwt2:in   al,dx
    test al,8
    jz   syncwt2
; конец фрагмента
    mouseHide ; скрыть курсор мыши
    mov ax,0A000h ; сегмент видео VGA
    mov es,ax
    mov di,0
    mov ax,cs     ; сегмент видеобуфера
    add ax,codesize/16
    mov ds,ax
    mov si,0
    mov cx,320*200/4 ; 16000 dword
    db  66h ; rep movsd prefix
    rep movsw ; выполняется операция rep movsd 386 процессора
    mouseShow ; показать курсор мыши
    popa
    pop es
    pop ds
    ret
 
; напечатать строку ds:si в видео режиме
prnstring:pusha
; поставьте if 1 чтобы скрыть отладочный вывод
if 0
    mov ah,2  ; опрос флагов клавиатуры
    int 16h
    test al,4 ; ctrl button нажата ?
    jz prnlin1 ; если нет, то не выводим строку
endif
prnlin0:lodsb      ; ax=очередной байт текста
    cmp al,0   ; конец строки ?
    jz prnlin1
    mov ah,0Eh
    mov bl,15 ; цвет выводимого символа
    int 10h
    jmp prnlin0
prnlin1:popa
    ret
 
prnword: ; вывод значения AX в текстовый буфер
    pusha
    mov  di,offset prnbuf+2
    mov cx,3 ; вывести AX как 3 десятичные цифры
pw1:    mov dx,0
    mov bx,10
    div bx
    add dl,"0"
    mov ds:[di],dl
    dec di
    loop pw1    
    mov si,offset prnbuf ; вывести текстовый буфер на экран
    call prnstring
    popa
    ret
 
; геометрические фигуры Координаты 0, 0 - центр фигуры
; первое слово - число линий фигуры
; далее идут координаты вершин
shape3 label word ; треугольник
  dw 3
  dw   0 ,-42 
  dw -45 , 21 
  dw  45 , 21
  dw   0 ,-42 
 
shape4  label word ; квадрат
    dw 4
    dw -40,-32
    dw 40,-32
    dw 40,32
    dw -40,32
    dw -40,-32
 
shapestar label word ; звезда
  dw 5
  dw  0 ,-42 
  dw -30 , 33
  dw  48 ,-13 
  dw -48 ,-13 
  dw  30 , 33 
  dw   0 ,-42 
 
shape32 label word ; окружность
  dw 32
  dw  0 ,-33 
  dw -8 ,-33 
  dw -15 ,-31 
  dw -22 ,-28 
  dw -28 ,-24 
  dw -33 ,-19 
  dw -37 ,-13 
  dw -39 ,-7 
  dw -40 , 0 
  dw -39 , 7 
  dw -37 , 13 
  dw -33 , 19 
  dw -28 , 24 
  dw -22 , 28 
  dw -15 , 31 
  dw -8 , 33 
  dw  0 , 33 
  dw  8 , 33 
  dw  15 , 31 
  dw  22 , 28 
  dw  28 , 24 
  dw  33 , 19 
  dw  37 , 13 
  dw  39 , 7 
  dw  40 , 0 
  dw  39 ,-7 
  dw  37 ,-13 
  dw  33 ,-19 
  dw  28 ,-24 
  dw  22 ,-28 
  dw  15 ,-31 
  dw  8 ,-33 
  dw  0 ,-33 
 
; число объектов (мобов) на экране
nmobs = 6
; структуры мобов. x,y соответствуют центру фигуры
; длина структуры - 8 байт
;         x,  y, цвет, адрес фигуры
mob1 dw  80, 50, 15, offset shapestar
mob2 dw 240, 50, 14, offset shapestar
mob3 dw  80,140, 13, offset shape4
mob4 dw 240,140, 12, offset shape4
mob5 dw 160, 80, 11, offset shape3
mob6 dw 160,140, 10, offset shape32
 
; половина размера квадрата захвата моба мышкой 
; (квадрат 64*64)
grabsiz = 32
; номер выбранного моба
select  dw 0
; смещение центра моба относительно координаты курсора мышки
seldx   dw 0
seldy   dw 0
mycol   dw 0
 
; выбрать моб 
selectmobs:pusha
    mov bx,nmobs ; начинаем с последнего (верхнего) моба
    mov si,offset mob1+8*(nmobs-1) ; адрес моба
sm0:    mov ax,[si]  ; найти смещение центра моба относит курсора мышки ; ax=координата x моба
    sub ax,cx    ; seldx=x_моба-x_мыши
    mov seldx,ax
    mov ax,2[si] ; seldy=y_моба-y_мыши
    sub ax,dx
    mov seldy,ax
    call sqin ; мышка попадает в квадрат выбора ?
    jnc sm1   ; да, записать номер моба
    sub si,8  ; перейти к другому мобу
    dec bx    ; bx используется как счётчик цикла, т к cx хранит координату x мыши
    jnz sm0
sm1:    mov select,bx ; если ни один моб не выбран, select=0
    popa
    ret
; попадает ли мышка в квадрат выбора ?
sqin:   cmp seldx,grabsiz
    jg  sqin1
    cmp seldx,-grabsiz
    jL  sqin1
    cmp seldy,grabsiz
    jg  sqin1
    cmp seldy,-grabsiz
    jL  sqin1
    clc ; да, сбросить флаг С
    ret
sqin1:  stc ; нет, установить флаг C
    ret 
; переместить объект, утянутый мышкой
movmobs:cmp select,0 ; нет выбранных мобов - выход
    jz  mov1
    pusha
    mov ax,select
    dec ax
    shl ax,3; ax=ax*8, где 8 - длина mob
    mov si,offset mob1
    add si,ax ; si - адрес выбранного моба
    mov ax,cx
    add ax,seldx
    mov [si],ax ; x=mousex+seldx
    mov ax,dx
    add ax,seldy
    mov [si+2],ax ; y=mousey+seldy
    popa
mov1:   ret
 
 
; нарисовать мобы
drawmobs:pusha
    mov bx,1 ; двигаемся от первого (нижнего) моба к верхнему
    mov si,offset mob1
dm1:    lodsw
    mov cx,ax ; cx=x
    lodsw
    mov dx,ax ; dx=y
    lodsw
    mov mycol,ax ; col=цвет
    lodsw     ; si=адрес фигуры
    push si
    mov si,ax
    call drawshape ; нарисовать фигуру
    pop si
    inc bx
    cmp bx,nmobs ; следующий моб
    jle dm1
    popa
    ret         
 
drawform:
    mov mycol,10 ; зеленый
    mov si,offset shapestar
; рисовать фигуру
; si=адрес фигуры
; cx,dx - координаты центра фигуры
drawshape:
    lodsw
    mov di,ax ; di=число линий фигуры
draw1:  lodsw     ; загрузить координату x фигуры (начало отрезка)
    add ax,cx ; x1=x+cx
    push ax;  =x1 ; поместить x1 в стек
    lodsw     ; загрузить координату y фигуры
    add ax,dx
    push ax;  =y1
    lodsw     ; аналогично загрузить и записать в стек координаты конца отрезка
    add ax,cx
    push ax ; =x2
    lodsw
    add  ax,dx
    push ax;  =y2
    mov  ax,mycol ; ax=цвет фигуры
    push ax; =col 
    call drawline ; провести линию см brez.inc
    sub si,4    ; продвинуть si на 2 переменных назад, чтобы нарисовать ломаную
    dec di
    jnz draw1   ; конец цикла рисования ломаной
    ret
 
; построение картинки в видео буфере
drawtest:
    call movmobs ; двигать мобы
    call drawmobs ; рисовать мобы
; Используйте эту строку в тестовых целях
;   invoke drawline, <10,10,310,10,15> ; провести отрезок из точки 10,10 в точку 310,10 цветом 15 (белым)
    ret
 
oldcx   dw 0
olddx   dw 0
 
ismoved:cmp oldcx,cx
    jnz ism1
    cmp olddx,dx
ism1:   ret
 
; вывод сообщения об ошибке, если драйвер мыши не найден
emess   db "Error: mouse driver not found",13,10,"$"
exiterr:mov ax,3 ; вернуться в текстовый режим
    int 10h
    mov dx,offset emess ; печать сообщения
    mov ah,9
    int 21h
    mov ax,4C01h ; выход в DOS с кодом ошибки 1
    int 21h
 
; начало основной программы
 
beg:    cld
    push cs ;ds=es=cs
    pop  ds
    push cs
    pop  es
    mov ax,13h ; установить граф режим VGA 13h - 320*200 256 цветов
    int 10h
    mouse 0   ; инит мышку
    cmp ax,-1
    jnz  exiterr ; мышка не найдена - выход
    mouseShow      ; показать курсор мыши
; нарисовать сцену на экране
    call cls ; стереть буфер
    call drawtest ; рисовать в буфере сцену
    call sync ; копировать результат на экран
; основной цикл
main:   mov ah,1 ; клавиша нажата - выход
    int 16h
    jnz exit
    mov oldcx,cx
    mov olddx,dx
    mousePoll ; опрос состояния мышки
        ; возвращает cx,dx - координаты, bx - биты кнопок мышки
    shr cx,1  ; 320w screen
; вывод отладочной инф (если нажата клавиша ctrl)
    setcur 0
    mov ax,cx ; mousex
    call prnword
    setcur 1    
    mov ax,dx ; mousey
    call prnword
    setcur 2    
    mov ax,bx ; mouse buttons
    call prnword
    test bx,1 ; нажата левая кнопка мыщки ?
    jz  ma1   ; нет - выбирать объект
    call ismoved ; мышка была сдвинута при нажатой левой кнопке ?
    jz  main     ; нет - ничего не делать
    call cls  ; да - передвинуть выбранный объект и перерисовать сцену
    call drawtest
    call sync
    jmp main  ; конец основного цикла
 
ma1:    call selectmobs ; выбрать объект
    setcur 3
    mov ax,select   ; напечатать номер объекта
    call prnword
    jmp main        ; возврат к началу основного цикла
 
exit:   mov ah,0 ; выход из программы Поглотить код нажатой клавиши
    int 16h
    mouseHide  ; скрыть курсор мыши
    mov ax,3 ; вернуться в текстовый режим
    int 10h
    mov ax,4C00h ; выход в DOS
    int 21h
 
    end start
См zip, если возникнут проблемы с копированием
Вложения
Тип файла: zip movobj.zip (5.3 Кб, 10 просмотров)
2
Модератор
Эксперт по электронике
 Аватар для ФедосеевПавел
8657 / 4491 / 1670
Регистрация: 01.02.2015
Сообщений: 13,899
Записей в блоге: 12
05.09.2020, 15:21
qbfan, классно!

А если объекты характеризовать не только перечислением координат, а ещё и указателями на процедуры отрисовки - тогда окружность будет ближе к идеальной.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
05.09.2020, 15:21
Помогаю со студенческими работами здесь

Перемещение объектов на форме мышкой
Здравствуйте. Возникла необходимость перемещать, уже в запущенной программе, объекты интерфейса... например Shape захватить мышкой и...

Выделение и перемещение объектов мышкой
Доброго времени суток! Интересует вопрос выделения объектов мышкой и последующее их перемещение через кнопки клавы (напр. стрелочки). В...

Перемещение мышкой нарисованных объектов
Помогите мне пожалуйста. Мне нужно чтобы нарисованный в программе прямоугольник можно былобы перемещать мышкой. Всё бы хорошо, но самый...

Перемещение объектов OvalShape по форме мышкой
Подскажите как это реализовать, пожалуйста!

Написать программу движения 3-х разных геометрических фигур по экрану
Написать программу движения 3-х разных геометрических фигур по экрану (горизонтально или вертикально). Фигуры не сталкиваются. Они должны...


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

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Новые блоги и статьи
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. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
SDL3 для Web (WebAssembly): Работа со звуком через SDL3_mixer
8Observer8 08.02.2026
Содержание блога Пошагово создадим проект для загрузки звукового файла и воспроизведения звука с помощью библиотеки SDL3_mixer. Звук будет воспроизводиться по клику мышки по холсту на Desktop и по. . .
SDL3 для Web (WebAssembly): Основы отладки веб-приложений на SDL3 по USB и Wi-Fi, запущенных в браузере мобильных устройств
8Observer8 07.02.2026
Содержание блога Браузер Chrome имеет средства для отладки мобильных веб-приложений по USB. В этой пошаговой инструкции ограничимся работой с консолью. Вывод в консоль - это часть процесса. . .
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru