반응형

스레드 클래스를 상속받는 클래스를 정의하고 사용해 보자.

 

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
import time
import threading
 
class Worker(threading.Thread):
    def __init__(self, name, count, delay):
        super().__init__()
        self.name = name
        self.count = count
        self.delay = delay
 
    # 스레드 클래스를 상속하는 클래스는 run()를 재정의 해야 한다.
    # 객체를 만들고 start()를 실행하면 run()가 실행된다.
    def run(self):
        print(f"{self.name} job started.")
        for i in range(self.count):
            print(f"{self.name} job: {i}.")
            time.sleep(self.delay)
        print(f"{self.name} job finished.")
 
            
print("Main started.")
 
thread_1 = Worker("First"50.5)
#thread_1.daemon = True
# 데몬 스레드로 설정되면 메인 스레드 종료시 서브 스레드도 종료된다.
thread_1.start()
#thread_1.join()
# join()을 실행한 스레드가 종료할 때까지 나머지 스레드는 대기한다.
 
thread_2 = Worker("Second"50.5)
#thread_2.daemon = True
thread_2.start()
#thread_2.join()
 
print(f"■ Number of threads: {threading.active_count()}")
 
time.sleep(1)
 
print("Main finished.")
 

 

 

 

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
import time
import threading
 
class Worker(threading.Thread):
    def __init__(self, name, count, delay):
        super().__init__()
        self.name = name
        self.count = count
        self.delay = delay
        
    def run(self):
        print(f"{self.name} job started.")
        for i in range(self.count):
            print(f"{self.name} job: {i}.")
            time.sleep(self.delay)
        print(f"{self.name} job finished.")
 
thread_1 = Worker("First"50.5)
thread_2 = Worker("Second"50.5)
thread_3 = Worker("Third"50.5)
threads = [thread_1, thread_2, thread_3]
 
print(f"■ Number of threads: {threading.active_count()}")
# 활성화된 스레드는 메인스레드 뿐이므로 1이 표시된다.
 
for thread in threads:
    thread.start()
    thread.join()
 

 

 

 

thread - Thread-based parallelism

 

반응형
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
import time
import threading
 
def Job(name, count, delay):
    print(f"{name} job started.")
    for i in range(count):
        print(f"{name} job: {i}.")
        time.sleep(delay)
    print(f"{name} job finished.")
 
print("Main started.")
 
thread_1 = threading.Thread(target=Job, args=("First"50.5))
thread_1.start()
 
thread_2 = threading.Thread(target=Job, args=("Second"50.5))
thread_2.start()
 
print(f"■ Number of threads: {threading.active_count()}")
 
time.sleep(1)
 
print("Main finished.")
 

 

 

■ threading.Thread(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)

- target is the callable object to be invoked by the run() method. Defaults to None, meaning nothing is called.
- args is a list or tuple of arguments for the target invocation. Defaults to ().

 

 

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
import time
import threading
 
def Job(name, count, delay):
    print(f"{name} job started.")
    for i in range(count):
        print(f"{name} job: {i}.")
        time.sleep(delay)
    print(f"{name} job finished.")
 
print("Main started.")
 
thread_1 = threading.Thread(target=Job, args=("First"50.5))
thread_1.daemon = True
thread_1.start()
 
thread_2 = threading.Thread(target=Job, args=("Second"50.5))
thread_2.daemon = True
thread_2.start()
 
print(f"■ Number of threads: {threading.active_count()}")
 
time.sleep(1)
 
print("Main finished.")
 

 

 

 

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
import time
import threading
 
def Job(name, count, delay):
    print(f"{name} job started.")
    for i in range(count):
        print(f"{name} job: {i}.")
        time.sleep(delay)
    print(f"{name} job finished.")
 
print("Main started.")
 
thread_1 = threading.Thread(target=Job, args=("First"50.5))
thread_1.start()
thread_1.join()
 
thread_2 = threading.Thread(target=Job, args=("Second"50.5))
thread_2.start()
thread_2.join()
 
print(f"■ Number of threads: {threading.active_count()}")
 
time.sleep(1)
 
print("Main finished.")
 

 

 

■ join(timeout=None)

- Wait until the thread terminates. This blocks the calling thread until the thread whose join() method is called terminates – either normally or through an unhandled exception – or until the optional timeout occurs.
- When the timeout argument is present and not None, it should be a floating point number specifying a timeout for the operation in seconds (or fractions thereof). As join() always returns None, you must call is_alive() after join() to decide whether a timeout happened – if the thread is still alive, the join() call timed out.
- When the timeout argument is not present or None, the operation will block until the thread terminates.
- A thread can be joined many times.

 

 

반응형
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
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
import pygame
 
pygame.init()
screen = pygame.display.set_mode((640480))
pygame.display.set_caption("Example code for the cursors module")
 
# 시스템 커서 생성
systemCursor = pygame.cursors.Cursor(pygame.SYSTEM_CURSOR_NO)
#pygame.SYSTEM_CURSOR_ARROW       arrow
#pygame.SYSTEM_CURSOR_IBEAM       i-beam
#pygame.SYSTEM_CURSOR_WAIT        wait
#pygame.SYSTEM_CURSOR_CROSSHAIR   crosshair
#pygame.SYSTEM_CURSOR_WAITARROW   small wait cursor
#                                 (or wait if not available)
#pygame.SYSTEM_CURSOR_SIZENWSE    double arrow pointing
#                                 northwest and southeast
#pygame.SYSTEM_CURSOR_SIZENESW    double arrow pointing
#                                 northeast and southwest
#pygame.SYSTEM_CURSOR_SIZEWE      double arrow pointing
#                                 west and east
#pygame.SYSTEM_CURSOR_SIZENS      double arrow pointing
#                                 north and south
#pygame.SYSTEM_CURSOR_SIZEALL     four pointed arrow pointing
#                                 north, south, east, and west
#pygame.SYSTEM_CURSOR_NO          slashed circle or crossbones
#pygame.SYSTEM_CURSOR_HAND        hand
 
# 비트맵 커서 생성.
bitmapCursor1 = pygame.cursors.Cursor(*pygame.cursors.arrow)
#pygame.cursors.arrow
#pygame.cursors.diamond
#pygame.cursors.broken_x
#pygame.cursors.tri_left
#pygame.cursors.tri_right
 
custom_strings = (           # size: 24x24
  "XX                      ",
  "XXX                     ",
  "XXXX                    ",
  "XX.XX                   ",
  "XX..XX                  ",
  "XX...XX                 ",
  "XX    XX                ",
  "XX     XX               ",
  "XX      XX              ",
  "XX       XX             ",
  "XX        XX            ",
  "XX        XXX           ",
  "XX      XXXXX           ",
  "XX XXX..XX              ",
  "XXXX XX..XX             ",
  "XX   XX..XX             ",
  "     XX..XX             ",
  "      XX..XX            ",
  "      XX..XX            ",
  "       XXXX             ",
  "       XX               ",
  "                        ",
  "                        ",
  "                        ")
 
bitmapCursor2 = pygame.cursors.Cursor(
    (2424), (00), *pygame.cursors.compile(custom_strings))
# Cursor클래스 인수: Cursor(size, hotspot, xormasks, andmasks)
# size는 8의 배수. hotspot은 클릭 지점. xormasks와 andmasks는
# pygame.cursors.compile()로 만들 수 있다. compile()에는 직접
# 만든 스트링이나 아래 상수 대입 가능.
#pygame.cursors.thickarrow_strings
#pygame.cursors.sizer_x_strings
#pygame.cursors.sizer_y_strings
#pygame.cursors.sizer_xy_strings
#pygame.cursor.textmarker_strings
 
# Surface 커서 생성.
surf = pygame.Surface((4040)) # 이미지를 로드할 수 도 있다.
surf.fill((1205050))        # 이미지를 로드하는 경우 불필요한 코드
surfaceCursor = pygame.cursors.Cursor((2020), surf)
 
cursors = [systemCursor, bitmapCursor1, bitmapCursor2, surfaceCursor]
cursor_index = 0
 
pygame.mouse.set_cursor(cursors[cursor_index])
 
clock = pygame.time.Clock()
going = True
while going:
    clock.tick(60)
    screen.fill((07530))
    pygame.display.flip()
 
    for event in pygame.event.get():
        if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and
                                        event.key == pygame.K_ESCAPE):
            going = False
 
        # 마우스 버튼이 눌리면 커서를 바꾼다.
        if event.type == pygame.MOUSEBUTTONDOWN:
            cursor_index += 1
            cursor_index %= len(cursors)
            pygame.mouse.set_cursor(cursors[cursor_index])
 
pygame.quit()
 

 

 

마우스를 클릭할 때 마다 커서가 바뀐다.

 

반응형
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
import pygame
 
pygame.init()
 
def main():
    clock = pygame.time.Clock()
 
    joysticks = {}
    # 조이스틱을 관리하기 위한 딕셔너리.
 
    done = False
    while not done:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                done = True
 
            if event.type == pygame.JOYBUTTONDOWN:
                print("Joystick button pressed.")
                            
            if event.type == pygame.JOYBUTTONUP:
                print("Joystick button released.")
 
            if event.type == pygame.JOYAXISMOTION:
                print("Joystick axis motion detected.")
                
            if event.type == pygame.JOYDEVICEADDED:
                joy = pygame.joystick.Joystick(event.device_index)
                # 컴퓨터에 연결된 물리적 조이스틱에 접근하기 위한 Joystick 클래스 생성.
                # Joystick 클래스 생성자 인수에는 0 부터 pygame.joystick.get_count()-1 까지 대입한다.
                # event.device_index는 0부터 연결된 조이스틱의 숫자 -1 까지 증가하는거 같다.
                joysticks[joy.get_instance_id()] = joy
                # joysticks 딕셔너리에 새로 생성된 Joystick 클래스를 추가한다.
                # joy.get_instance_id() 는 joystick의 instance ID를 반환한다. 이 값은 Joystick 클래스
                # 생성자 인수로 넣은 값과 같은거 같다. event.instance_id 와 같은 값을 가진다.
                print(f"Joystick #{joy.get_instance_id()} connencted")
 
            if event.type == pygame.JOYDEVICEREMOVED:
                del joysticks[event.instance_id]
                # 조이스틱을 분리하면 joysticks 딕셔너리에서 분리된 조이스틱을 삭제한다.
                print(f"Joystick #{event.instance_id} disconnected")
 
        for joystick in joysticks.values():
        # dictionary.values() 는 dict_values라는 리스트 객체를 리턴하며 이 안에는 값의 목록만 들어 있다.
            jid = joystick.get_instance_id()
            name = joystick.get_name()
            guid = joystick.get_guid()
 
            axes = joystick.get_numaxes()
            for i in range(axes):
                axis = joystick.get_axis(i)
                if axis > 0.1 or axis < -0.1:
                    print(f"ID: {jid} Name: {name}, GUID: {guid}, Axis #{i}, Value: {axis:>6.3f}")
 
            buttons = joystick.get_numbuttons()
            for i in range(buttons):
                button = joystick.get_button(i)
                if button != 0:
                    print(f"ID: {jid} Name: {name}, GUID: {guid}, Button #{i:>2} Value: {button}")
                    
    clock.tick(30)
 
if __name__ == "__main__":
    main()
    pygame.quit()
 

 

조이스틱이 하나만 연결되어 있다면 조금 더 간단히 상태를 확인 할 수 있다.

 

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
import pygame
 
pygame.init()
 
joy = None
jid = None
name = None
guid = None
 
def main():
    clock = pygame.time.Clock()
    done = False
 
    while not done:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                done = True
 
            if event.type == pygame.JOYBUTTONDOWN:
                print("Joystick button pressed.")
                buttons = joy.get_numbuttons()
                for i in range(buttons):
                    button = joy.get_button(i)
                    if button != 0:
                        print(f"ID: {jid} Name: {name}, GUID: {guid}, Button #{i:>2} Value: {button}")
                            
            if event.type == pygame.JOYBUTTONUP:
                print("Joystick button released.")
 
            if event.type == pygame.JOYAXISMOTION:
                print("Joystick axis motion detected.")
                # 방향 버튼을 눌렀을 때 -1, 0, 1 같은 정수가 나오지 않을 수 도 있다.
                if joy.get_axis(0> 0.5:                    
                    print(f"ID: {jid} Name: {name}, GUID: {guid}, Axis: L/R Value: RIGHT")
                if joy.get_axis(0< -0.5:
                    print(f"ID: {jid} Name: {name}, GUID: {guid}, Axis: L/R, Value: LEFT")
                if joy.get_axis(1> 0.5:
                    print(f"ID: {jid} Name: {name}, GUID: {guid}, Axis: U/D, Value: DOWN")
                if joy.get_axis(1< -0.5:
                    print(f"ID: {jid} Name: {name}, GUID: {guid}, Axis: U/D, Value: UP")
 
            if event.type == pygame.JOYDEVICEADDED:
                joy = pygame.joystick.Joystick(event.device_index)
                jid = joy.get_instance_id()
                name = joy.get_name()
                guid = joy.get_guid()
                print(f"Joystick #{joy.get_instance_id()} connencted")
 
            if event.type == pygame.JOYDEVICEREMOVED:
                print(f"Joystick #{event.instance_id} disconnected")
 
    clock.tick(30)
 
if __name__ == "__main__":
    main()
    pygame.quit()
 

 

 

버튼을 누를때 마다 상태를 표시한다.

 

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

움직이던 물체의 속도가 갑자기 0이 되는 것은 자연스럽지 못하다. 자연스럽게 천천히 멈추는 캐릭터를 만들어 보자.

 

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
import pygame
 
pygame.init()
pygame.display.set_caption("Super fun game development")
screen = pygame.display.set_mode((640480))
clock = pygame.time.Clock()
running = True
 
player = pygame.image.load("player.png").convert()
player.set_colorkey(player.get_at((00)))
player_size = (player.get_width()*1.5, player.get_height()*1.5)
player = pygame.transform.scale(player, player_size)
player_pos = player.get_rect()
player_pos.center = (screen.get_width()/2, screen.get_height()/2)
player_speed = 4
player_direction = -1
 
left_released = False
right_released = False
slipcount = 0
slipduration = 60
# 캐릭터 미끄러지는 동작 관련 변수들.
 
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
 
        # 왼쪽, 오른쪽 방향키를 떼는 순간.
        if event.type == pygame.KEYUP and event.key == pygame.K_LEFT:
            left_released = True
            right_released = False
            slipcount = 0    
        elif event.type == pygame.KEYUP and event.key == pygame.K_RIGHT:
            right_released = True
            left_released = False
            slipcount = 0
        # 캐릭터의 미끄러지는 동작이 끝나기 전에 반대 방향 키를 누르는 경우에 대비.
 
    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT]:
        if player_direction > 0:
            player = pygame.transform.flip(player, TrueFalse)
            player_direction = -1
        player_pos.move_ip(-player_speed, 0)
    if keys[pygame.K_RIGHT]:
        if player_direction < 0:
            player = pygame.transform.flip(player, TrueFalse)
            player_direction = 1            
        player_pos.move_ip(player_speed, 0)
    
    # 왼쪽으로 이동 중 키를 놓았을때 slipduration 프레임 동안 미끄러진다.
    if left_released == True:
        player_pos.move_ip(-pygame.math.lerp(player_speed, 0, (slipcount/slipduration)), 0)
        slipcount += 1
 
        # sliupduration이 지나면 초기화.
        if slipcount > slipduration:
            slipcount = 0
            left_released = False
    
    # 오른쪽으로 이동 중 키를 놓았을때 slipduration 프레임 동안 미끄러진다.
    if right_released == True:
        player_pos.move_ip(pygame.math.lerp(player_speed, 0, (slipcount/slipduration)), 0)
        slipcount += 1
 
        # sliupduration이 지나면 초기화.
        if slipcount > slipduration:
            slipcount = 0
            right_released = False
        
    screen.fill("black")
    screen.blit(player, player_pos)
    
    pygame.display.flip()
    clock.tick(60)
 
pygame.quit()
 

 

 

공룡이 바로 멈추지 않고 약간 더 움직인다.

 

이번엔 관성이 적용된 것처럼 천천히 출발하고 천천히 멈추는 캐릭터를 만들어 보자.

 

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
import pygame
 
pygame.init()
pygame.display.set_caption("Super fun game development")
screen = pygame.display.set_mode((640480))
clock = pygame.time.Clock()
running = True
 
player = pygame.image.load("player.png").convert()
player.set_colorkey(player.get_at((00)))
player_size = (player.get_width()*1.5, player.get_height()*1.5)
player = pygame.transform.scale(player, player_size)
player_pos = player.get_rect()
player_pos.center = (screen.get_width()/2, screen.get_height()/2)
player_direction = -1
 
player_speed = 0
player_speed_step = 0.1
player_max_speed = 4
# 속도 관련 변수들.
 
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
 
    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT]:
        if player_direction > 0:
            player = pygame.transform.flip(player, TrueFalse)
            player_direction = -1
        if (abs(player_speed) <= player_max_speed):
            player_speed -= player_speed_step
            if player_speed < -player_max_speed:
                player_speed = -player_max_speed
    # 왼쪽 방향키를 누르면 속도가 음의 방향으로 player_speed_step 씩 증가하다
    # player_max_speed 에서 멈춘다.
 
    if keys[pygame.K_RIGHT]:
        if player_direction < 0:
            player = pygame.transform.flip(player, TrueFalse)
            player_direction = 1
        if (abs(player_speed) <= player_max_speed):
            player_speed += player_speed_step
            if player_speed > player_max_speed:
                player_speed = player_max_speed
    # 오른쪽 방향키를 누르면 속도가 양의 방향으로 player_speed_step 씩 증가하다
    # player_max_speed 에서 멈춘다.
 
    # 왼쪽으로 가는 도중 오른쪽 방향키를 동시에 누른다고 오른쪽으로 가지는
    # 않지만 오른쪽을 바라본다. 하지만 오른쪽으로 가는 도중 왼쪽 방향키를
    # 동시에 눌러도 바라보는 방향이 바뀌지는 않는다. 이유는 왼쪽 방향키
    # 검사보다 오른쪽 방향키 검사(오른쪽으로 바라보게 하는)가 나중에 오기
    # 때문이다. 두 방향 중 나중에 검사하는 오른쪽 방향이 항상 적용되는 것이다.
 
    if not keys[pygame.K_LEFT] and not keys[pygame.K_RIGHT]:
        if player_speed > 0:
            player_speed -= player_speed_step
        elif player_speed < 0:
            player_speed += player_speed_step
    # 오른쪽이나 왼쪽 방향키를 누르고 있지 않으면 속도가 0에 가까워진다.
    
    if abs(player_speed) < 0.1:
        player_speed = 0
    # 속도의 절대값이 0.1보다 작으면 0으로 변경한다.
 
    player_pos.move_ip(player_speed, 0)
 
    screen.fill("black")
    screen.blit(player, player_pos)
    
    pygame.display.flip()
    clock.tick(60)
 
pygame.quit()
 

 

 

매 프레임마다 player_speed_step 만큼 속도가 증감된다.

 

반응형
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
:
반응형

스프라이트 그룹의 충돌을 감지해 보자.

 

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
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, position):
        pygame.sprite.Sprite.__init__(self)
 
        self.direction = -1
        self.speed = 4
        self.image = pygame.image.load("player.png").convert()
        self.image.set_colorkey(self.image.get_at((00)))
        self.size = (self.image.get_width()*1.5self.image.get_height()*1.5)
        self.image = pygame.transform.scale(self.image, self.size)
        self.rect = self.image.get_rect(center=position)
 
    def flip_image(self):
        self.image = pygame.transform.flip(self.image, TrueFalse)
        
    def update(self):
        pass
# 플레이어 클래스
 
class Bubble(pygame.sprite.Sprite):
    def __init__(self, position):
        pygame.sprite.Sprite.__init__(self)
 
        self.image = pygame.image.load("bubble.png").convert()
        self.image.set_colorkey(self.image.get_at((00)))
        self.size = (self.image.get_width()*6self.image.get_height()*6)
        self.image = pygame.transform.scale(self.image, self.size)
        self.rect = self.image.get_rect(center=position)
        self.collided = False
 
    def update(self):
        if self.collided == True:
            self.rect.top -= 1
# 버블 클래스
# 충돌(self.collided)을 감지하면 위치(self.rect.top)가 변한다.
 
def main():
    player = Player((screen.get_width()/2, screen.get_height()/2))
    player_sprite = pygame.sprite.Group(player)
    # 플레이어 스프라이트 그룹
 
    bubbles = [
        Bubble((40, screen.get_height()/2)),
        Bubble((160, screen.get_height()/2)),
        Bubble((480, screen.get_height()/2)),
        Bubble((600, screen.get_height()/2))]
    bubble_sprites = pygame.sprite.Group(bubbles)
    # 버블 스프라이트 그룹
 
    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
 
        keys = pygame.key.get_pressed()
        if keys[pygame.K_LEFT]:
            if player.direction > 0:
                player.flip_image()
                player.direction = -1
            player.rect.move_ip(-player.speed, 0)
        if keys[pygame.K_RIGHT]:
            if player.direction < 0:
                player.flip_image()
                player.direction = 1
            player.rect.move_ip(player.speed, 0)
 
        collision = pygame.sprite.spritecollide(player, bubble_sprites, False)
        for bubble in collision:
            bubble.collided = True
        # 플레이어와 버블의 충돌을 감지하고 충돌한 버블의 collided 값을 True로 바꾼다.
 
        player_sprite.update()
        bubble_sprites.update()
 
        screen.fill("black")
        player_sprite.draw(screen)
        bubble_sprites.draw(screen)
    
        pygame.display.flip()
        clock.tick(60)
 
    pygame.quit()
 
if __name__ == '__main__':
   main()
 

 

 

공룡과 충돌한 버블은 하늘로 올라간다.

※ 참고

pygame.sprite.spritecollideany()
Simple test if a sprite intersects anything in a group.
● spritecollideany(sprite, group, collided = None) -> Sprite Collision with the returned sprite.
● spritecollideany(sprite, group, collided = None) -> None No collision
If the sprite collides with any single sprite in the group, a single sprite from the group is returned. On no collision None is returned.

If you don't need all the features of the pygame.sprite.spritecollide() function, this function will be a bit quicker.

The collided argument is a callback function used to calculate if two sprites are colliding. It should take two sprites as values and return a bool value indicating if they are colliding. If collided is not passed, then all sprites must have a "rect" value, which is a rectangle of the sprite area, which will be used to calculate the collision.

 

반응형
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
#import numpy as np
import bezier
import pygame
 
pygame.init()
pygame.display.set_caption("Super fun game development")
screen = pygame.display.set_mode((640480))
clock = pygame.time.Clock()
running = True
 
#nodes = np.asfortranarray([
#    [0.0, 640.0*2/4, 640.0*3/4, 640.0],
#    [0.0, 960.0, -960.0, 960.0],
#    ])
#curve = bezier.Curve(nodes, degree=3)
 
#nodes = np.asfortranarray([
#    [0.0, 640.0*2/4, 640.0*3/4, 640.0],
#    [0.0, 960.0, -960.0, 960.0],
#    ])
 
#nodes = np.array([
#    [0.0, 640.0*2/4, 640.0*3/4, 640.0],
#    [0.0, 960.0, -960.0, 960.0],
#    ])
 
nodes = [
    [0.0640.0*2/4640.0*3/4640.0],
    [0.0960.0-960.0960.0],
    ]
# 곡선 위 노드 행렬. 행은 차원, 열은 노드의 좌표를 나타낸다.
# (0, 0), (640*2/4, 960), (640*3/4, -960), (640, 960)
 
curve = bezier.Curve.from_nodes(nodes)
# 베지어 곡선을 생성한다. 차수는 node로부터 계산한다.
 
index = 0.0
 
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
 
    screen.fill("black")
 
    index += 0.005
    if index > 1:
        index = 0.0
 
    coord = curve.evaluate(index)
    # 베지어 곡선 위 index 지점 좌표를 계산한다. index는 1을 넘을 수 있다.
    pygame.draw.circle(screen, "yellow", (coord[0][0], coord[1][0]), 100)
    pygame.display.flip()
 
    clock.tick(60)
 
pygame.quit()
 

 

 

베지어 곡선을 따라 원이 이동한다.

 

반응형
Posted by J-sean
: