반응형

AnimatedSprite나 AnimationPlayer를 사용하지 않고 Sprite만으로도 간단한 애니메이션을 만들 수 있다.

 

Sprite2D를 추가하고 Texture를 지정한다. Hframes는 8, Vframes는 7로 조절한다.

 

Scale을 적절히 조절하고 스크립트도 추가한다.

 

char_blue.png
0.02MB

 

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
using Godot;
 
public partial class Control : Sprite2D
{
    public override async void _Process(double delta)
    {
        if (Input.IsActionJustPressed("ui_accept"))
        {
            // 점프 애니메이션
            for (int i = 32; i < 40; i++)
            {
                await ToSignal(GetTree().CreateTimer(0.2),
                    SceneTreeTimer.SignalName.Timeout);
                Frame = i;
            }
        }
 
        if (Input.IsActionJustPressed("ui_cancel"))
        {
            // 전체 애니메이션
            for (int v = 0; v < Vframes; v++)
                for (int h = 0; h < Hframes; h++)
                {
                    await ToSignal(GetTree().CreateTimer(0.2),
                        SceneTreeTimer.SignalName.Timeout);
                    FrameCoords = new Vector2I(h, v);
                }
        }
    }
}
 

 

위와 같은 코드를 작성한다.

엔터키를 누르면 점프, ESC키를 누르면 전체 애니메이션이 플레이 된다. 애니메이션이 플레이 되는 동안 키를 여러번 동시에 누르면 애니메이션이 겹친다.

 

 

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

OpenGL 화면에 Pygame 이미지(스프라이트)를 렌더링 해 보자.

 

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
import pygame
from pygame.locals import *
 
from OpenGL.GL import *
from OpenGL.GLU import *
 
verticies = ((1-1-1), (11-1), (-11-1), (-1-1-1),
             (1-11), (111), (-1-11), (-111))
edges = ((0,1), (0,3), (0,4), (2,1), (2,3), (2,7), (6,3), (6,4),
         (6,7), (5,1), (5,4), (5,7))
 
def drawCube():
    glBegin(GL_LINES)
    for edge in edges:
        for vertex in edge:
            glVertex3fv(verticies[vertex])
    glEnd()
 
def drawImage(x, y):
    image = pygame.image.load("player.png").convert()
    image.set_colorkey(image.get_at((00)))
    image = pygame.transform.scale(image, (image.get_width()*1.5,
                                           image.get_height()*1.5))
    imageData = pygame.image.tostring(image, "RGBA"True)
    glWindowPos2d(x-image.get_width()/2, y-image.get_height()/2)
    glDrawPixels(image.get_width(), image.get_height(), GL_RGBA,
                 GL_UNSIGNED_BYTE, imageData)
 
pygame.init()
clock = pygame.time.Clock()
display = (640480)
pygame.display.set_mode(display, DOUBLEBUF | OPENGL)
 
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
 
gluPerspective(45, (display[0]/display[1]), 0.150.0)
glTranslatef(0.00.0-5)
 
run = True
while run:    
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
 
    glRotatef(1311)
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
    drawCube()
    drawImage(display[0]/2, display[1]/2)
    
    pygame.display.flip()
    clock.tick(60)
 
pygame.quit()
exit()
 

 

 

 

반응형
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
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
import pygame
 
pygame.init()
pygame.display.set_caption("Super fun game development")
screen = pygame.display.set_mode((640480))
clock = pygame.time.Clock()
 
# 이미지 로드 함수.
def LoadImage(path, scale=None, colorkey=None):
    image = pygame.image.load(path).convert()
 
    if scale is not None:
        image = pygame.transform.scale(image, (image.get_width()*scale, image.get_height()*scale))
 
    if colorkey is not None:
        if colorkey == -1:
            colorkey = image.get_at((00))
        image.set_colorkey(colorkey)
 
    return image
 
# pygame.sprite.Sprite 클래스를 상속하는 클래스는 update()를 재정의하고 image, rect 속성을 가져야한다.
class Cat(pygame.sprite.Sprite):
    def __init__(self, position):
        #super(Cat, self).__init__()        
        pygame.sprite.Sprite.__init__(self)
 
        self.elapsedTime = 0
        self.limitTime = 1000/8
        # 1초에 한 사이클. Cat의 Run 동작은 8프레임이다.
        
        self.direction = 1
        self.speed = 4
        self.index = 0
        self.images = [
            LoadImage("Run1.png"0.5-1), LoadImage("Run2.png"0.5-1), LoadImage("Run3.png"0.5-1),
            LoadImage("Run4.png"0.5-1), LoadImage("Run5.png"0.5-1), LoadImage("Run6.png"0.5-1),
            LoadImage("Run7.png"0.5-1), LoadImage("Run8.png"0.5-1) ]
        self.image = self.images[self.index]
        self.rect = self.image.get_rect(center=position)
 
    def flip_image(self):
        self.images = [pygame.transform.flip(image, TrueFalsefor image in self.images]
        # list comprehension
 
    def update(self):
        # 1초에 8프레임 업데이트.
        self.elapsedTime += clock.get_time()
        if self.elapsedTime < self.limitTime:
            pass
        else:
            self.elapsedTime = 0
            self.index += 1
            if self.index >= len(self.images):
                self.index = 0
            self.image = self.images[self.index]
 
def main():
    cat = Cat(position=(screen.get_width()/2, screen.get_height()/2))
    #all_sprites = pygame.sprite.Group(cat)
    all_sprites = pygame.sprite.Group()
    # 스프라이트 오브젝트를 관리하기 위한 컨테이너 클래스
    all_sprites.add(cat)
    # 스프라이트를 삭제할 때는 all_sprites.remove(cat)
    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 cat.direction > 0:
                cat.flip_image()
                cat.direction = -1
            cat.rect.move_ip(-cat.speed, 0)
            
        if keys[pygame.K_RIGHT]:
            if cat.direction < 0:
                cat.flip_image()
                cat.direction = 1
            cat.rect.move_ip(cat.speed, 0)
 
        all_sprites.update()
        # 그룹에 속한 모든 스프라이트의 update()를 호출한다.
        
        screen.fill("blue")        
        all_sprites.draw(screen)
        # 그룹에 속한 모든 스프라이트의 image, rect 속성을 이용해 screen에 출력한다.
        # 그룹은 스프라이트의 순서(z-order)를 임의로 정한다.
        pygame.display.flip()
 
        clock.tick(60)
 
    pygame.quit()
 
if __name__ == '__main__':
   main()
 

 

Cat.zip
0.49MB

 

고양이가 자연스럽게 걷고있다.

 

※ 참고

Z-Order에 따라 스프라이트를 그려야 한다면 아래 링크를 확인하자.

LayeredUpdates

This group is fully compatible with pygame.sprite.Sprite.
You can set the default layer through kwargs using 'default_layer' and an integer for the layer. The default layer is 0.
If the sprite you add has an attribute _layer then that layer will be used. If the **kwarg contains 'layer' then the sprites passed will be added to that layer (overriding the sprite.layer attribute). If neither sprite has attribute layer nor **kwarg then the default layer is used to add the sprites.

 

반응형
Posted by J-sean
: