## Rotating an image by direction of analogue stick?

### Rotating an image by direction of analogue stick?

I'm essentially trying to make a game in this style: http://www.youtube.com/watch?v=ZZfTi-cq27s

I'm wondering how i can get the rotation to be done using an analogue stick (i'm using an xbox 360 controller). I've managed to get the movement working using the left analogue stick, now just trying to get the rotation done by the other. I've got an image and attached it to a rect and that's what i'm using as a character. I can get values for how much the analogue stick is being pushed in the x and y axis but i'm unsure on how to translate this into a direction, and even more unsure as to how to then rotate an image based on that. I'm pretty new python and pygame so if you need any other info or anything let me know.

Last edited by stranac on Tue Dec 03, 2013 9:24 pm, edited 1 time in total.
Reason: First post lock.
ArrenMog

Posts: 5
Joined: Tue Dec 03, 2013 7:55 pm

### Re: Rotating an image by direction of analogue stick?

Welcome.

If you know how to get the x and y parts of the analog stick, then you can find the angle with:
Code: Select all
`angle_in_radians = math.atan2(y,x)angle = math.degrees(angle_in_radians)`
You then use this angle to rotate and move your player.

I would be interested to see the code you have so far.
-Mek
• Use code tags when posting code.
• Include any errors with your post (in code tags).
• Make examples the minimum length to demonstrate your issue.

Mekire

Posts: 1711
Joined: Thu Feb 07, 2013 11:33 pm
Location: Tucson, Arizona

### Re: Rotating an image by direction of analogue stick?

Thanks for the help but i now have another issue, i'm trying to rotate a sprite by a given angle (10 degrees) every tick. At the moment my sprite simply judders back and forth and i'm not sure why, I just want it to rotate. A similar version of the code works for non animated sprites but i'm struggling to get it to work for this animated sprite. I'm using Python 3.3, Pygame and easypg. I have listed my code below, first the class i'm calling from easypg, then the class I am creating for my sprite that is using the sprite class from easypg as a super class, and then finally my main game section. I know there's quite a lot to take in but any help is welcome. The zip files easypg take are simply zips of images that it cycles through to produce an animated sprite, and the state selects which images to cycle through.

Thanks!

Easypg Sprite class

Code: Select all
`class Sprite(pygame.sprite.Sprite):    """A sprite consisting of (potentially) multiple images.       It is assumed that the sprite can be in different states.  For each       state, there can be different sets of sprite images representing       the eight compass directions, and for each direction there can be a       stack of images representing an animation sequence.       The images themselves can be in a single directory or Zip archive       and the main part of the filename (excluding the extension) should       have the following format:           [<state>]_[<direction>]_<num>       <state> is optional.  If present, it consists of a short string of       ASCII alphabetic characters.       <direction> is also optional.  If present, it must be one of the       following strings: 'n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw'       <num> is two decimal digits.  An image numbered 00 is required,       but images numbered 01...99 are optional.       Images are loaded into a dictionary called 'images'.  Note that this       dictionary is not defined here.  IT MUST BE DEFINED IN A SUBCLASS,       ideally as a class variable so that the loaded images can be shared       by all instances of that subclass.       Keys of this dictionary are states, with '-' representing an       undefined state; values are themselves dictionaries, each of which       has compass directions as keys (with '-' representing an undefined       direction) and a corresponding list of Pygame surfaces as the       value associated with each key.  This list of Pygame surfaces is       used as an animation sequence for a particular state/direction.    """    image_regexp = re.compile('([a-zA-Z]*)_([a-zA-Z]*)_(\d\d)')    def __init__(self, screen, path,                 alpha=False, background=None, position=None,                 state='-', direction='-'):        """Creates a Sprite object for the given Pygame display surface,           using the images at the given location.           The required 'path' argument is either a path to a directory           or a path to a Zip archive, containing sprite images.           If the images have full alpha transparency, this should be           indicated by setting the 'alpha' argument to True; otherwise,           it is assumed that the colour of the pixel in the top-left           corner of each sprite image is a background colour that should           be transparent when the sprite is rendered on screen.  If some           other specific colour represents the background, this can be           provided as a 3-tuple using the 'background' argument.           By default, the sprite will be positioned in the centre of the           the display surface on which it is drawn. Other coordinates can           be specified as a 2-tuple using the 'position' argument.           An initial state and direction can be specified if needed;           they default to '-', meaning 'undefined'.        """        super().__init__()        self.screen = screen        self.alpha = alpha        self.background = background        self.state = state        self.direction = direction        if not hasattr(self, 'images'):            raise SpriteError('no image store defined')        elif not isinstance(self.images, dict):            raise SpriteError('image store must be a dictionary')        if os.path.isfile(path) and path.endswith('.zip'):            self._load_from_zip(path)        elif os.path.isdir(path):            self._load_from_dir(path)        else:            raise SpriteError('invalid image location')        self.frame = 0        self.counter = self.anim_delay = 3        self.sequence = self.images[self.state][self.direction]        self.image = self.sequence[self.frame]        self.rect = self.image.get_rect()        if position:            self.rect.center = position        else:            w, h = self.screen.get_size()            self.rect.center = (w // 2, h // 2)    def _load_from_dir(self, path):        contents = sorted(os.listdir(path))        for (state, direction, _), name in self._find_images(contents):            image_path = os.path.join(path, name)            if self.alpha:                image = pygame.image.load(image_path).convert_alpha()            else:                image = pygame.image.load(image_path).convert()                self._set_background(image)            self.images[state][direction].append(image)    def _load_from_zip(self, path):        archive = zipfile.ZipFile(path)        contents = sorted(archive.namelist())        for (state, direction, _), name in self._find_images(contents):            data = archive.open(name).read()            source = io.BytesIO(data)            if self.alpha:                image = pygame.image.load(source).convert_alpha()            else:                image = pygame.image.load(source).convert()                self._set_background(image)            self.images[state][direction].append(image)    def _find_images(self, names):        found = collections.OrderedDict()        for name in names:            match = self.image_regexp.match(name)            if match:                # Valid image file, so record details in dictionary                state = match.group(1) or '-'                direction = match.group(2) or '-'                num = match.group(3)                found[(state, direction, num)] = name                # Prepare image store to hold loaded images                if state not in self.images:                    self.images[state] = {}                if direction not in self.images[state]:                    self.images[state][direction] = []        return found.items()    def _set_background(self, image):        if self.background:            image.set_colorkey(self.background)        else:            colour = image.get_at((0, 0))            image.set_colorkey(colour)    def update(self):        """Updates this sprite.           The implementation provided here simply invokes the check_state,           animate, move and check_bounds methods.        """        self.check_state()        self.animate()        self.move()        self.check_bounds()    def check_state(self):        """Checks this sprite's state, changing it if necessary.           The implementation provided here is a stub that can be           overridden in subclasses.        """    def animate(self):        """Animates this sprite by changing its image at regular intervals."""        self.counter -= 1        if self.counter == 0:            self.counter = self.anim_delay            self.frame += 1            if self.frame >= len(self.sequence):                self.frame = 0            self.image = self.sequence[self.frame]    def move(self):        """Moves this sprite.           The implementation provided here is a stub that can be           overridden in subclasses.        """    def check_bounds(self):        """Checks whether this sprite is within bounds and modifies           sprite properties if necessary.           The implementation provided here is a stub that can be           overridden in subclasses.        """`

My Player class

Code: Select all
`class Player( Sprite ):    images = {}            def __init__(self, screen, velocity=(3, 3)):                super().__init__(screen, 'player.zip', state='angry')        self.vx, self.vy = velocity        self.sizex, self.sizey = screen.get_size()        self.controller = pygame.joystick.Joystick(0)        self.controller.init()        self.angle = 0    def move (self):##        keys = pygame.key.get_pressed()##        if keys[pygame.K_LEFT]:##            self.rect.centerx -= self.vx##        if keys[pygame.K_RIGHT]:##            self.rect.centerx += self.vx##        if keys[pygame.K_UP]:##            self.rect.centery -= self.vy##        if keys[pygame.K_DOWN]:##            self.rect.centery += self.vy        self.rect.centerx += int(self.vx*self.controller.get_axis(0))        self.rect.centery += int(self.vy*self.controller.get_axis(1))                self.rotatedchar = pygame.transform.rotate(self.image, self.angle)        self.rect = self.rotatedchar.get_rect(center = self.rect.center)        self.angle += 10        width, height = self.screen.get_size()        if self.rect.centerx < 0:            self.rect.centerx = width - 1        elif self.rect.centerx >= width:            self.rect.centerx = 0        if self.rect.centery < 0:            self.rect.centery = height - 1        elif self.rect.centery >= height:            self.rect.centery = 0`

My main game code

Code: Select all
`import pygameimport spritespygame.init()# Configure displaysize = (640, 480)screen = pygame.display.set_mode(size)pygame.display.set_caption('CR11 Lab 5')# Define some coloursgrey = (180, 180, 180)red = (255, 0, 0)green = (0, 255, 0)blue = (0, 0, 255)# Create a background image and display itbackground = pygame.Surface(size).convert()background.fill(grey)screen.blit(background, (0, 0))# TODO: Create sprite and sprite groupchar = sprites.Player( screen )enemy0 = sprites.Monster( screen )enemy1 = sprites.Monster( screen, velocity = (4, 2) )enemy2 = sprites.Monster( screen, velocity = (3, 8) )other = pygame.sprite.Group( char )monsters = pygame.sprite.Group( enemy0, enemy1, enemy2 )# Define variables to control the actionclock = pygame.time.Clock()running = True# Enter the main event loop...while running:    clock.tick(30)   # max 30 fps    for event in pygame.event.get():        if event.type == pygame.QUIT:            running = False    # TODO: Clear, update and redraw sprite group    other.clear( screen, background )    #monsters.clear( screen, background )    other.update()    #monsters.update()    other.draw( screen )        #monsters.draw( screen )    #pygame.sprite.groupcollide(other, monsters, True, False)    pygame.display.flip()`
ArrenMog

Posts: 5
Joined: Tue Dec 03, 2013 7:55 pm

### Re: Rotating an image by direction of analogue stick?

I've added an example to my sample repo showing rotation of an animated sprite.

https://github.com/Mekire/meks-pygame-samples/blob/master/rotation_animation/rotate_animate.py

The screen displays four versions of the same sprite.
• One static
• One rotating only
• One animated only
• And one animated and rotating

You will need to download the repo for it to work as it relies on an image:

Let me know if you have any questions.

-Mek
• Use code tags when posting code.
• Include any errors with your post (in code tags).
• Make examples the minimum length to demonstrate your issue.

Mekire

Posts: 1711
Joined: Thu Feb 07, 2013 11:33 pm
Location: Tucson, Arizona

### Re: Rotating an image by direction of analogue stick?

Hey man just had a quick look through all of this and thanks a lot man, about to download it all and try and get it running now but thanks man, it looks like you put a lot of time into this response so thank you!
ArrenMog

Posts: 5
Joined: Tue Dec 03, 2013 7:55 pm