Forum Archive

Action.repeat() won't repeat.

Kamozo

Hello, why won't "repmo" repeat itself?
I would like the action to continuously run after "phase_1", yet it only runs once. How do I fix this? Thank you.

        up = A.move_to(self.size.w/2, 350, 9,TIMING_EASE_BACK_OUT)  
        mo = A.move_to(random.randrange(100,924),random.randrange(300,700), 2, TIMING_EASE_BACK_IN_OUT)
        repmo = A.repeat(mo, -1)
        phase_1 = A.sequence(stationary, up) #stationary appears earlier
        self.boss.run_action(A.sequence(phase_1, repmo)) 

This is only a snippet of code, I'm just highlighting the bits that need looking at. For example, although the code doesn't specify, A = Action.

omz

The action does repeat, but the random coordinates are only calculated once, so each repetition moves to the same point (which has the same effect as if it wouldn't repeat at all).

If you want new random coordinates with every repetition, you'd need to use a custom call action.

Kamozo

Ahh, I understand that, thanks.
I'll have to do some more reading now, because the call function confuses me, it doesn't take much code does it? Could you give an example of how I would do it, if that isn't too much to ask?
But anyway, thanks, I'll look into it.

omz

Something like this should work:

up = A.move_to(self.size.w/2, 350, 9, TIMING_EASE_BACK_OUT)
d = 2.0 # duration
# Inline function for the call action:
def move_random():
  x, y = random.randrange(100,924), random.randrange(300,700)
  self.boss.run_action(A.move_to(x, y, d))
# The call action doesn't wait until the move action finishes, so add a wait action for that:
repmo = A.repeat(A.sequence(A.call(move_random), A.wait(d)), -1))
phase_1 = A.sequence(stationary, up)
mo = A.move_to(, 2, TIMING_EASE_BACK_IN_OUT)
self.boss.run_action(A.sequence(phase_1, repmo))

(I actually used a slightly simpler example for testing, so there might be some typos here)

Kamozo

Wow, thank you, that helps me a lot.

Kamozo

Even though it helped me get a better idea of what to do, it still doesn't seem to work.
I'm not sure if it's because of the indentation, but it keeps returning back as invalid syntax on the line:

repmo = A.repeat(A.sequence(A.call(move_random), A.wait(d)), -1))

Its probably because I don't know where to put some parts of the code you've provided.

Here is the full program, except I've removed the bosses movement :

# coding: utf-8

from scene import *
import sound
import random

# one full turn = 6.823
A = Action

big_up = Texture('Big rise.PNG')
big_boss_s = Texture('Big Boss.PNG')
big_boss_b = Texture('BIG BOSS.PNG')
boss_left = Texture('left.PNG')
boss_right = Texture('right.PNG')
boss_off = Texture('floating.PNG')
boss_standing = Texture('standing.PNG')
boss_up = Texture('rising.PNG')
boss_texture = Texture('Boss.PNG')
background = Texture('Background.JPG')
standing_texture = Texture('Standing.PNG')
walk_textures = [Texture('Running1.PNG'),Texture('Running2.PNG')]
hit = Texture('IMG_3808.PNG')

class Game (Scene):

    def setup(self):    

        self.background_color = '#2e2e2e'
        self.bg = SpriteNode('IMG_3929.JPG')
        self.bg.position = (self.size.w / 2, 385)
        self.add_child(self.bg)
        ground = Node(parent=self)
        x = 0
        while x <= self.size.w + 64:
            tile = SpriteNode('plf:Ground_SandCenter', position=(x, 0))
            ground.add_child(tile)
            x += 64         
        self.player = SpriteNode('Standing.PNG')
        self.player.anchor_point = (0.5, 0)
        self.player.position = (200, 32)
        self.add_child(self.player)
        self.walk_step = -1     
        self.items = []
        self.boss_ai()


    def update(self):           
        self.collisions()
        self.boss_animation()
        self.update_player()
        if random.random() < 0.05 and self.t > 7:
            self.attack()


    def update_player(self):
        g = gravity()
        if abs(g.y) > 0.05:
            self.player.x_scale = cmp(g.y, 0)
            x = self.player.position.x
            max_speed = 25
            x = max(0, min(self.size.w, x + g.y * max_speed))
            self.player.position = x, 32
            step = int(self.player.position.x / 40) % 2
            if step != self.walk_step:
                self.player.texture = walk_textures[step]
                sound.play_effect('rpg:Footstep09', 0.05, 1.0 + 0.5 * step)
                self.walk_step = step
        else:
            self.player.texture = standing_texture
            self.walk_step = -1     

    def collisions(self):
        self.player_hitbox = Rect(self.player.position.x - 20, 32, 40, 65)
        for item in list(self.items):
            if item.frame.intersects(self.player_hitbox):
                self.player_hit()


    def move_random():
        x, y = random.randrange(100,924), random.randrange(300,700)
        self.boss.run_action(A.move_to(x, y, d))


    def player_hit(self):
        pass


    def boss_ai(self):
        self.boss = SpriteNode('standing.PNG')
        self.boss.anchor_point = (0.5, 0.3)
        self.boss.position = (self.size.w/2, 90)
        self.boss.speed = 2
        self.add_child(self.boss)
        self.attack()


    def boss_animation(self):
        if self.t > 0.25:
            self.boss.texture = boss_up
        if self.t > 3:
            self.boss.texture = boss_off
        if self.t > 4:
            self.boss.texture = boss_texture


    def attack(self):
        self.sh = SpriteNode('sharooken.PNG')
        sp = 1
        self.sh.position = (self.boss.position)
        self.add_child(self.sh)
        rot = A.repeat(A.rotate_by(6.823, 0.5), -1)
        actions = [A.move_by(random.randrange(-300,300), -(self.size.h + 60), sp), A.remove()]
        self.sh.run_action(A.group(rot, A.sequence(actions)))
        self.items.append(self.sh)







if __name__ == '__main__':
    run(Game(), LANDSCAPE, show_fps=False)

I'm still very much a beginner, so excuse and bad code.

omz

Sorry, there's a closing parenthesis too much, it should be:

repmo = A.repeat(A.sequence(A.call(move_random), A.wait(d)), -1)
Kamozo

Oh yeah, I'm not sure how I didn't notice that.
Where does the code you've provided fit into mine?

Kamozo

I've cleaned it up a little, no syntax errors, yet now the boss won't move at all.

# coding: utf-8

from scene import *
import sound
import random

# one full turn = 6.823
A = Action

big_up = Texture('Big rise.PNG')
big_boss_s = Texture('Big Boss.PNG')
big_boss_b = Texture('BIG BOSS.PNG')
boss_left = Texture('left.PNG')
boss_right = Texture('right.PNG')
boss_off = Texture('floating.PNG')
boss_standing = Texture('standing.PNG')
boss_up = Texture('rising.PNG')
boss_texture = Texture('Boss.PNG')
background = Texture('Background.JPG')
standing_texture = Texture('Standing.PNG')
walk_textures = [Texture('Running1.PNG'),Texture('Running2.PNG')]
hit = Texture('IMG_3808.PNG')

class Game (Scene):

    def setup(self):    

        self.background_color = '#2e2e2e'
        self.bg = SpriteNode('IMG_3929.JPG')
        self.bg.position = (self.size.w / 2, 385)
        self.add_child(self.bg)
        ground = Node(parent=self)
        x = 0
        while x <= self.size.w + 64:
            tile = SpriteNode('plf:Ground_SandCenter', position=(x, 0))
            ground.add_child(tile)
            x += 64         
        self.player = SpriteNode('Standing.PNG')
        self.player.anchor_point = (0.5, 0)
        self.player.position = (200, 32)
        self.add_child(self.player)
        self.walk_step = -1     
        self.items = []
        self.boss_ai()


    def update(self):           
        self.collisions()
        self.boss_animation()
        self.update_player()
        if random.random() < 0.05 and self.t > 7:
            self.attack()


    def update_player(self):
        g = gravity()
        if abs(g.y) > 0.05:
            self.player.x_scale = cmp(g.y, 0)
            x = self.player.position.x
            max_speed = 25
            x = max(0, min(self.size.w, x + g.y * max_speed))
            self.player.position = x, 32
            step = int(self.player.position.x / 40) % 2
            if step != self.walk_step:
                self.player.texture = walk_textures[step]
                sound.play_effect('rpg:Footstep09', 0.05, 1.0 + 0.5 * step)
                self.walk_step = step
        else:
            self.player.texture = standing_texture
            self.walk_step = -1     

    def collisions(self):
        self.player_hitbox = Rect(self.player.position.x - 20, 32, 40, 65)
        for item in list(self.items):
            if item.frame.intersects(self.player_hitbox):
                self.player_hit()


    def move_random():
        x, y = random.randrange(100,924), random.randrange(300,700)
        self.boss.run_action(A.move_to(x, y, d))


    def player_hit(self):
        pass


    def boss_ai(self):
        up = A.move_to(self.size.w/2, 350, 9,TIMING_EASE_BACK_OUT)
        d = 2
        stationary = A.wait(0)
        self.boss = SpriteNode('standing.PNG')
        self.boss.anchor_point = (0.5, 0.3)
        self.boss.position = (self.size.w/2, 90)
        self.boss.speed = 2
        self.add_child(self.boss)
        self.attack()
        repmo = A.repeat(A.sequence(A.call(self.move_random), A.wait(d)), -1)
        phase_1 = A.sequence(stationary, up)

        self.boss.run_action(A.sequence(phase_1, repmo))


    def boss_animation(self):
        if self.t > 0.25:
            self.boss.texture = boss_up
        if self.t > 3:
            self.boss.texture = boss_off
        if self.t > 4:
            self.boss.texture = boss_texture


    def attack(self):
        self.sh = SpriteNode('sharooken.PNG')
        sp = 1
        self.sh.position = (self.boss.position)
        self.add_child(self.sh)
        rot = A.repeat(A.rotate_by(6.823, 0.5), -1)
        actions = [A.move_by(random.randrange(-300,300), -(self.size.h + 60), sp), A.remove()]
        self.sh.run_action(A.group(rot, A.sequence(actions)))
        self.items.append(self.sh)







if __name__ == '__main__':
    run(Game(), LANDSCAPE, show_fps=False)
Kamozo

Nevermind, I've figured it.
Thanks for all your help.

Webmaster4o

@omz said:

Sorry, there's a closing parenthesis too much, it should be:

It sounds much less awkward to an American if you say "there's one too many closing parentheses," but not a big deal. Just putting it out there

chriswilson

I hadn't realised the A.call() thing existed - loads of possibilities for animations!