Задать вопрос
@Retr0Hacker

Как сделать движение по кругу по нажатия кнопки?

Доброго времени суток
На повестке дня у меня вот такая задачка: "Создайте в окне Windows кнопку и статический текст. При нажатии кнопки кнопка начинается двигаться (например, по кругу). При повторном нажатии движение останавливается. В статическом окне текста выводятся координаты."

Выглядит это все как-вот так:
6346bef178d52105977806.png

Я сделал так что при нажатии на кнопку она начинает двигаться квадратиком, однако:
1) Мне нужно движение по кругу
2) Я не знаю как это реализовать(

По идеи мне нужно находить синус по координатам кнопки, постепенно их увеличивая, и таким образом двигать кнопку по кругу. И если с постепенным увеличением координат(X, Y) я частично справился, то вот с синусом совсем беда.

И плюс даже движение квадратом у меня реализовано очень калечно. Я просто сделал 4 цикла фор:
.ELSEIF eax == WM_COMMAND
		mov eax, hButton
		.IF eax == lParam
			invoke SetTimer, hButton, IDT_TIMER, 10000, NULL
			mov X, 10
			mov Y, 100
			.WHILE X < 500
				add X, del_x
				invoke function, X, Y
			.endw
			
			.WHILE Y < 500
				add Y, del_y
				invoke function, X, Y
			.endw
			
			.WHILE X > 10
				sub X, del_x
				invoke function, X, Y
			.endw
			
			.WHILE Y > 100
				sub Y, del_y
				invoke function, X, Y
			.endw	
		.endif


Подскажите как можно решить мою проблему?

.Inc файл
include windows.inc
   include user32.inc
   include kernel32.inc
   
   includelib user32.lib
   includelib kernel32.lib

WinMain proto :DWORD,:DWORD,:DWORD,:DWORD

.data
   ClassName db "MainWinClass",0
   AppName  db "Main Window",0
   
   new_el_class_name  db 'Button',0
   new_el_caption 	  db 'Push me!!!',0
   
   lb_format db "x: %d, y: %d", 0
   list_el_class_name db 'ListBox',0
   
   IDT_TIMER = 1001
   del_x = 10
   del_y = 10
   
.data?
   hInstance dd ?
   CommandLine dd ?
   hButton dd ?
   hList dd ?
   X dd ?
   Y dd ?


.asm файл
.586
.model flat,stdcall
option casemap:none
;include RADbg.inc
include Four.Inc
.code

start:
	invoke GetModuleHandle, NULL
	mov    hInstance,eax
	
	invoke GetCommandLine
	mov    CommandLine,eax
	
	invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
	invoke ExitProcess,eax

WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
	LOCAL wc:WNDCLASSEX
	LOCAL msg:MSG
	LOCAL hwnd:HWND
	
	mov   wc.cbSize,SIZEOF WNDCLASSEX
	mov   wc.style, CS_HREDRAW or CS_VREDRAW
	mov   wc.lpfnWndProc, OFFSET WndProc
	mov   wc.cbClsExtra,NULL
	mov   wc.cbWndExtra,NULL
	push  hInstance
	pop   wc.hInstance
	mov   wc.hbrBackground,COLOR_BACKGROUND
	mov   wc.lpszMenuName,NULL
	mov   wc.lpszClassName,OFFSET ClassName
	
	invoke LoadIcon,NULL,IDI_APPLICATION
	mov   wc.hIcon,eax
	mov   wc.hIconSm,eax
	
	invoke LoadCursor,NULL,IDC_ARROW
	mov   wc.hCursor,eax
	
	invoke RegisterClassEx, addr wc
	INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
           WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
           CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
           hInst,NULL
	mov   hwnd,eax
	
	INVOKE CreateWindowEx, 0, ADDR new_el_class_name, ADDR new_el_caption,\
           WS_CHILD + WS_VISIBLE, 10, 100, 80, 30, hwnd, 0, hInstance, 0
	mov hButton, eax
	
	INVOKE CreateWindowEx, 0, ADDR list_el_class_name, 0,\
           WS_CHILD + WS_BORDER + WS_VISIBLE, 600, 150, 160, 300, hwnd, 0, hInstance, 0
	mov hList, eax
	
	
	invoke ShowWindow, hwnd,SW_SHOWNORMAL
	invoke UpdateWindow, hwnd
	
	.WHILE TRUE
		invoke GetMessage, ADDR msg,NULL,0,0
		.BREAK .IF (!eax)
		invoke TranslateMessage, ADDR msg
		invoke DispatchMessage, ADDR msg
	.ENDW
	
	mov     eax,msg.wParam
	ret
WinMain endp

function proc _x: DWORD, _y: DWORD
	invoke SetWindowPos, hButton, HWND_TOP, _x, _y, 80, 30, SWP_SHOWWINDOW
	invoke Sleep, 100
	ret
function endp

WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
	LOCAL sbuf[255]:byte
	
	mov eax, uMsg
	.IF eax == WM_DESTROY
		invoke PostQuitMessage,NULL
	.ELSEIF eax == WM_CREATE
	.ELSEIF eax == WM_COMMAND
		mov eax, hButton
		.IF eax == lParam
			invoke SetTimer, hButton, IDT_TIMER, 10000, NULL
			mov X, 10
			mov Y, 100
			.WHILE X < 500
				add X, del_x
				invoke function, X, Y
			.endw
			
			.WHILE Y < 500
				add Y, del_y
				invoke function, X, Y
			.endw
			
			.WHILE X > 10
				sub X, del_x
				invoke function, X, Y
			.endw
			
			.WHILE Y > 100
				sub Y, del_y
				invoke function, X, Y
			.endw
;			
		.endif
	.ELSE
		invoke DefWindowProc,hWnd,uMsg,wParam,lParam		
		ret
	.ENDIF
	
	xor eax,eax
	ret
WndProc endp


end start
  • Вопрос задан
  • 146 просмотров
Подписаться 1 Простой Комментировать
Пригласить эксперта
Ответы на вопрос 3
mayton2019
@mayton2019
Bigdata Engineer
Движение по кругу задается параметрически. Задаешь параметр fi (фи) пробегающий от 0.0 до 2*Pi радиан.
Далее косинус фи дает тебе иксовую координату. А синус игрековую. Координаты нормированы от -1.0 до 1.0
и их еще надо умножить на пол поперечника окна и сдвинуть на центр координат окна.

Как это делается в WinGDI я не помню. Но тригонометрия - это хитрая штука для ассебмлера. И я тебе советую
сделать макет на языке С и сгенерировать ассемблерный выход и посмотреть что так и как.

А потом уже интересующие тебе функции перенести в твой исходник.
Ответ написан
Комментировать
freeExec
@freeExec
Участник OpenStreetMap
Движение по кругу это синус или косинус.
Что-то вроде
cos(a) = x/r
x^2 + y^2 = r^2

Решаем уравнения для каждого угла A
Ответ написан
@AlexSku
не буду отвечать из-за модератора
1) Насколько я помню, sin и cos это команды арифметического сопроцессора (встроен в основной).
2) Либо без синусов и косинусов по алгоритму Брезенхема для окружности.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы