반응형

Lerp 선형보간을 살펴보자.

 

#include <iostream>
#include <vector>
#include <numeric> // For std::accumulate
#include <iomanip> // For std::setprecision
#include <algorithm> // For std::generate, std::transform

int main() {
	const int steps = 10; // steps를 바꾸면 벡터의 크기와 간격이 바뀌게 된다. 예를 들어 steps를 20으로 설정하면, vec에는 0부터 20까지의 값이 채워지게 된다.
	std::vector<float> vec(steps + 1); // steps + 1을 사용하여 벡터의 크기를 설정하는 이유는 0부터 steps까지의 값을 포함하기 위해서이다.

	std::iota(vec.begin(), vec.end(), 0); //
	// iota는 벡터의 시작부터 끝까지 연속된 값을 채워넣는 함수이다. 여기서는 0부터 시작하여 1씩 증가하는 값을 vec에 채워넣는다.
	// 간격을 바꾸고 싶다면 std::generate나 std::transform을 사용할 수 있다.

	//std::generate(vec.begin(), vec.end(), [n = 0.0f]() mutable { return n++; });
	// generate는 벡터의 각 요소에 대해 지정된 함수를 호출하여 값을 생성하는 함수이다.
	// n은 람다 함수 내부에서만 사용되는 상태 변수로, 람다 함수가 호출될 때마다 0으로 초기화되는 것이 아니라, 이전 호출에서 증가된
	// 값을 유지한다. 마치 static 변수처럼 동작한다. 따라서 vec에는 0.0f, 1.0f, 2.0f, ..., 10.0f가 채워지게 된다. mutable 키워드는
	// 람다 함수 내부에서 n 변수를 수정할 수 있도록 허용한다. 만약 mutable이 없었다면, n은 람다 함수 내부에서 상수로 간주되어 수정할
	// 수 없게 된다.

	//std::transform(vec.begin(), vec.end(), vec.begin(), [n = 0.0f](float v) mutable { return n++; });
	// transform는 벡터에서 값을 읽어와서 새로운 값을 생성하여 다른 벡터에 저장하는 함수이다. (여기서는 벡터의 기존 값은 사용하지 않는다)
	// std::transform는 벡터의 각 요소에 대해 지정된 함수를 적용하여 새로운 값을 생성하는 함수이다. 여기서는 vec의 각 요소에 대해 람다 함수를
	// 적용하여 0.0f부터 시작하여 1씩 증가하는 값을 vec에 채워넣는다. 람다 함수는 n이라는 상태 변수를 사용하여 현재 값을 유지하며, 호출될 때마다
	// 증가시킨다. 결과적으로 vec에는 0.0f, 1.0f, 2.0f, ..., 10.0f가 채워지게 된다.
	// v는 std::transform가 vec의 각 요소를 람다 함수에 전달할 때 사용되는 매개변수이지만, 여기서는 실제로 사용되지 않는다. 현재 람다 함수는
	// n이라는 상태 변수를 사용하여 값을 생성하기 때문에, v는 단지 std::transform의 요구 사항을 충족하기 위해 존재하는 매개변수일 뿐이다.

	for (const float& num : vec) {
		std::cout << num << " ";
	}
	std::cout << std::endl;

	for (float& num : vec) {
		num /= steps; // steps로 나누어 0.0f부터 1.0f까지의 값을 갖도록 한다. 예를 들어, steps가 10이면 vec에는 0.0f, 0.1f, 0.2f, ..., 1.0f가 채워지게 된다.
		std::cout << num << " ";
	}
	std::cout << std::endl;

	float start = 0.0f;
	float end = 100.0f;

	std::cout << std::fixed << std::setprecision(1);
	// std::fixed는 소수점 아래 자릿수를 고정하는 형식 지정자이며, std::setprecision(1)은 소수점 아래 1자리까지 표시하도록 설정한다. 따라서 출력되는 숫자는
	// 항상 소수점 아래 1자리까지 표시되고, 필요에 따라 0으로 채워진다. 예를 들어, 0.0f는 0.0으로, 0.1f는 0.1로, ..., 1.0f는 1.0으로 출력된다.
	for (float& t : vec) {
		std::cout << "t: " << t << " -> " << std::lerp(start, end, t) << std::endl;
		// std::lerp는 선형 보간 함수로, start와 end 사이의 값을 t에 따라 계산하여 반환한다. t가 0.0f이면 start가 반환되고, t가 1.0f이면 end가 반환된다.
		// t가 0.5f이면 start와 end의 중간값이 반환된다. 따라서 vec에 저장된 값에 따라 start와 end 사이의 다양한 값이 출력된다.
	}

	return 0;
}

 

 

반응형
Posted by J-sean
:
반응형

캐릭터가 마우스를 따라 천천히 회전 하도록 해 보자.

 

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
import pygame
 
pygame.init()
pygame.display.set_caption("Super fun game development")
screen = pygame.display.set_mode((640480))
clock = pygame.time.Clock()
 
class Player(pygame.sprite.Sprite):
    def __init__(self, pos):
        super().__init__()
        self.image = pygame.image.load("player.png").convert()
        self.image.set_colorkey(self.image.get_at((00)))
        self.image = pygame.transform.scale(self.image,
                    (self.image.get_width()*1.5self.image.get_height()*1.5))
        self.original_image = self.image
        # 원본 이미지 보관.
        self.rect = self.image.get_rect(center=pos)
        self.pos = pygame.math.Vector2(pos)
        # pos를 벡터로 변환.
 
        self.preangle = 0
 
    def rotate(self):        
        direction = pygame.mouse.get_pos() - self.pos
        # 플레이어에서 마우스로의 벡터.
        radius, angle = direction.as_polar()
        # radius는 마우스까지의 거리, angle은 방위각.
        # 오른쪽=0(-0), 아래=90, 왼쪽=180(-180), 위=-90
        
        if abs(angle - self.preangle) < 0.5:
        # 이전 프레임의 각도와 현재 각도의 차이가 0.5도 미만이면 보간 없이 회전한다.
            self.image = pygame.transform.rotate(self.original_image, -angle+180)
            # 이미지를 회전하고 각도 보정. 이전 프레임의 회전된 이미지가 아닌
            # 원본 이미지를 이용한다.
            self.rect = self.image.get_rect(center=self.rect.center)
            # rect 재설정.
            self.preangle = angle
        else:
            angle = pygame.math.lerp(self.preangle, angle, 0.02)
            # 이전 프레임의 각도와 현재 각도 사이를 프레임당 2% 보간(interpolate)한다.
            self.preangle = angle        
            self.image = pygame.transform.rotate(self.original_image, -angle+180)
            self.rect = self.image.get_rect(center=self.rect.center)
 
    def update(self):
        self.rotate()
 
def main():
    all_sprites = pygame.sprite.Group(Player(screen.get_rect().center))
 
    running = True
 
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
                running = False 
    
        all_sprites.update()
    
        screen.fill("black")
        all_sprites.draw(screen)
    
        pygame.display.flip()
        clock.tick(60)
 
    pygame.quit()
 
if __name__ == '__main__':
   main()
 

 

 

캐릭터가 마우스를 향해 천천히 회전한다.

캐릭터를 중점으로 마우스가 2/4분면과 3/4분면 경계를 지날때는 생각과 다르게 반대 방향으로 회전한다.

 

반응형
Posted by J-sean
:
반응형

액추에이터(Actuator)는 시스템을 움직이거나 제어하는 데 쓰이는 기계 장치이다. 그 중 리니어 액추에이터(Linear Actuator)는 모터의 선형 운동을 직선 운동으로 바꿔 주는 장치이다.


알리 익스프레스에서 주문한지 12일 만에 대한통운으로 배송 되었다.


Linear Actuator: $62.05

Stroke: 20~80mm

Max RPM: 120

Torque: 12V 15kgf·cm

           24V 20kgf·cm

https://www.aliexpress.com/item/10000209705566.html?spm=a2g0s.9042311.0.0.27424c4dpiWCEi


스피드 컨트롤러의 어댑터 입출력 표기가 잘 못 되어 있다.



전압을 1~24V로 조절하여 속도를 조절 한다.


555 DC모터.


테스트는 영상으로 확인 하자.


반응형
Posted by J-sean
: