pyglet: changing the image of a sprite instance when pressing a button - python

This code displays the image assassin1.png on a black background. As soon as I press the key the image moves to the right and stops moving as soon as I release the key.
As soon as I press the key it should also change to the image assassin2.png and when I release the key it should change back to assassin1.png.
This code however never displays the assassin2.png image while moving. Why is this so and how can I fix this?
import pyglet
class Assassin(pyglet.sprite.Sprite):
def __init__(self, batch, img):
pyglet.sprite.Sprite.__init__(self, img, x = 50, y = 30)
def stand(self):
self.img = pyglet.image.load("assassin1.png")
return self
def move(self):
self.img = pyglet.image.load('assassin2.png')
return self
class Game(pyglet.window.Window):
def __init__(self):
pyglet.window.Window.__init__(self, width = 315, height = 220)
self.batch_draw = pyglet.graphics.Batch()
self.player = Assassin(batch = self.batch_draw, img = pyglet.image.load("assassin1.png"))
self.keys_held = []
self.schedule = pyglet.clock.schedule_interval(func = self.update, interval = 1/60.)
def on_draw(self):
self.clear()
self.batch_draw.draw()
self.player.draw()
def on_key_press(self, symbol, modifiers):
self.keys_held.append(symbol)
if symbol == pyglet.window.key.RIGHT:
self.player = self.player.move()
print "The 'RIGHT' key was pressed"
def on_key_release(self, symbol, modifiers):
self.keys_held.pop(self.keys_held.index(symbol))
self.player = self.player.stand()
print "The 'RIGHT' key was released"
def update(self, interval):
if pyglet.window.key.RIGHT in self.keys_held:
self.player.x += 50 * interval
if __name__ == "__main__":
window = Game()
pyglet.app.run()

I looked at the pyglet's source code and i think the problem is here:
self.img = pyglet.image.load(...
The image is stored in self.image variable, not self.img. So changing to:
self.image = pyglet.image.load(...
should update the image that the sprite is using.

Related

Updating location of circle with mouse movement breaks on fast mouse movement, tkinter-python

I am making a draggable point(a circle). The code works, however, while dragging, if the mouse motion is quick the point stops moving. I have taken help from this code for making this program. I will be using this point later on for other purposes. Here is my full code,
from tkinter import *
import sys,os,string,time
class Point():
def __init__(self,canvas,x,y):
self.canvas = canvas
# It could be that we start dragging a widget
# And release it while its on another
# Hence when we land on a widget we set self.loc to 1
# And when we start dragging it we set self.dragged to 1
self.loc = self.dragged = 0
self.x = x
self.y = y
self.radius = 5
self.point = canvas.create_oval(self.x-self.radius,self.y-self.radius,self.x+self.radius,self.y+self.radius,fill="green",tag="Point")
canvas.tag_bind("Point","<ButtonPress-1>",self.down)
canvas.tag_bind("Point","<ButtonRelease-1>",self.chkup)
canvas.tag_bind("Point","<Enter>",self.enter)
canvas.tag_bind("Point","<Leave>",self.leave)
def down(self,event):
self.loc = 1
self.dragged = 0
event.widget.bind("<Motion>",self.motion)
canvas.itemconfigure(self.point,fill = "red")
def motion(self,event):
root.config(cursor = "exchange")
cnv = event.widget
cnv.itemconfigure(self.point,fill = "red")
self.x,self.y = cnv.canvasx(event.x), cnv.canvasy(event.y)
got = canvas.coords(self.point,self.x-self.radius,self.y-self.radius,self.x+self.radius,self.y+self.radius)
def enter(self,event):
canvas.itemconfigure(self.point,fill="blue")
self.loc = 1
if self.dragged == event.time:
self.up(event)
def up(self,event):
event.widget.unbind("<Motion>")
canvas.itemconfigure(self.point,fill="green")
self.canvas.update()
def chkup(self,event):
event.widget.unbind("<Motion>")
root.config(cursor = "")
canvas.itemconfigure(self.point,fill="green")
if self.loc: # is button released in the same widget as pressed
self.up(event)
else:
self.dragged = event.time
def leave(self,event):
self.up(event)
root = Tk()
root.title("Drag and Drop")
canvas = Canvas(root,width = 256, height = 256, borderwidth = 1)
point = Point(canvas,128,128)
canvas.pack()
root.mainloop()
Your problem is that your <Leave> binding can fire if you move the mouse outside of the tiny circle faster than you can process the move. That causes the binding for <Motion> to be disabled.
My recommendation is to a) don't bind on <Leave> to disable the binding, and b) bind on <B1-Motion> so that the binding is active only while the button is pressed.

Python Pyglet Using External Fonts For Labels

I'm working on a project at the moment and I have been trying to change the fonts of the labels in the pyglet library to fonts that I found online but I couldn't get it to work. I tried searching online for an hour now and nothing seems to be working. Added some code for reference:
font.add_file('ZukaDoodle.ttf')
ZukaDoodle = font.load('ZukaDoodle.ttf', 16)
PlayLabel = pyglet.text.Label('Go', font_name='ZukaDoodle', font_size=100, x=window.width // 2,
y=window.height - 450, anchor_x='center', anchor_y='center',
batch=buttons_batch,
color=(0, 0, 0, 1000), width=250, height=130)
So the error is pretty simple. The loaded font-name is not ZukaDoodle, it's Zuka Doodle with a space. Here's a working executable sample:
from pyglet import *
from pyglet.gl import *
font.add_file('ZukaDoodle.ttf')
ZukaDoodle = font.load('ZukaDoodle.ttf', 16)
key = pyglet.window.key
class main(pyglet.window.Window):
def __init__ (self, width=800, height=600, fps=False, *args, **kwargs):
super(main, self).__init__(width, height, *args, **kwargs)
self.x, self.y = 0, 0
self.keys = {}
self.mouse_x = 0
self.mouse_y = 0
self.PlayLabel = pyglet.text.Label('Go', font_name='Zuka Doodle', font_size=100,
x=self.width // 2,
y=self.height - 450,
anchor_x='center', anchor_y='center',
color=(255, 0, 0, 255),
width=250, height=130)
self.alive = 1
def on_draw(self):
self.render()
def on_close(self):
self.alive = 0
def on_mouse_motion(self, x, y, dx, dy):
self.mouse_x = x
def on_key_release(self, symbol, modifiers):
try:
del self.keys[symbol]
except:
pass
def on_key_press(self, symbol, modifiers):
if symbol == key.ESCAPE: # [ESC]
self.alive = 0
self.keys[symbol] = True
def render(self):
self.clear()
self.PlayLabel.draw()
## Add stuff you want to render here.
## Preferably in the form of a batch.
self.flip()
def run(self):
while self.alive == 1:
self.render()
# -----------> This is key <----------
# This is what replaces pyglet.app.run()
# but is required for the GUI to not freeze
#
event = self.dispatch_events()
if __name__ == '__main__':
x = main()
x.run()
The key difference here is font_name='Zuka Doodle'.
Also, the alpha channel usually doesn't need to be higher than 255 since that's the max value of a colored byte, so unless you're using 16-bit color representation per channel, 255 will be the maximum value.

atan2 isn't providing me with the angle I want

I'm trying to write a game in pygame, involving a moving object with a "turret" that swivels to follow a mouse. As of now, I'm mostly trying to expand upon examples, so the code's not entirely mine (credit to Sean J. McKiernan for his sample programs); however, this portion is. Below is my code; I use the center of rect (the "base" shape and the point around which the "turret" swivels) as the base point, and the position of the mouse as the other point. By subtracting the mouse's displacement from the displacement of the "center," I effectively get a vector between the two points and find the angle between that vector and the x-axis with atan2. Below is the code I use to do that:
def get_angle(self, mouse):
x_off = (mouse[0]-self.rect.centerx)
y_off = (mouse[1]-self.rect.centery)
self.angle = math.degrees(math.atan2(-y_off, x_off) % 2*math.pi)
self.hand = pg.transform.rotate(self.original_hand, self.angle)
self.hand_rect = self.hand.get_rect(center=self.hand_rect.center)
According to multiple tutorials I've reviewed, this SHOULD be the correct code; however, I discovered later that those tutorials (and, in fact, this tutorial) were all for Python 2.7, while I am trying to write in Python 3.6. I don't think that should make a difference in this scenario, though. As it stands, the view appears to depend entirely upon the "character's" position on the screen. If the "character" is in one corner, the reaction of the "turret" is different than the reaction if the "character" is in the middle of the screen. However, this shouldn't matter; the position of the "character" relative to the mouse is the exact same no matter where on the screen they are. Any ideas, or do I need to supply more code?
Edit: Apparently, more code is required. Rather than attempt to extricate only the entirely necessary parts, I've provided the entire code sample, so everyone can run it. As a side note, the "Bolt" things (intended to fire simple yellow blocks) don't work either, but I'm just trying to get the arm working before I start in on debugging that.
Edit the second: I have discovered that the "Bolt" system works within a certain distance of the origin (0,0 in the window coordinate system), and that the arm also works within a much lesser distance. I added the line Block(pg.Color("chocolate"), (0,0,100,100)) under the "walls" grouping as a decision point, and the block was positioned in the top left corner. I've corrected Bolt by changing screen_rect to viewport in the control loop; however, I don't know why the "arm" swinging is dependent on adjacency to the origin. The positions of the mouse and "character" SHOULD be absolute. Am I missing something?
"""
Basic moving platforms using only rectangle collision.
-Written by Sean J. McKiernan 'Mekire'
Edited for a test of "arms"
"""
import os
import sys
import math
import pygame as pg
CAPTION = "Moving Platforms"
SCREEN_SIZE = (700,700)
BACKGROUND_COLOR = (50, 50, 50)
COLOR_KEY = (255, 255, 255)
class _Physics(object):
"""A simplified physics class. Psuedo-gravity is often good enough."""
def __init__(self):
"""You can experiment with different gravity here."""
self.x_vel = self.y_vel = 0
self.grav = 0.4
self.fall = False
def physics_update(self):
"""If the player is falling, add gravity to the current y velocity."""
if self.fall:
self.y_vel += self.grav
else:
self.y_vel = 0
class Player(_Physics, object):
def __init__(self,location,speed):
_Physics.__init__(self)
HAND = pg.image.load("playertst2.png").convert()
HAND.set_colorkey(COLOR_KEY)
self.image = pg.image.load('playertst.png').convert()
self.rect = self.image.get_rect(topleft=location)
self.speed = speed
self.jump_power = -9.0
self.jump_cut_magnitude = -3.0
self.on_moving = False
self.collide_below = False
self.original_hand = HAND
self.fake_hand = self.original_hand.copy()
self.hand = self.original_hand.copy()
self.hand_rect = self.hand.get_rect(topleft=location)
self.angle = self.get_angle(pg.mouse.get_pos())
def check_keys(self, keys):
"""Find the player's self.x_vel based on currently held keys."""
self.x_vel = 0
if keys[pg.K_LEFT] or keys[pg.K_a]:
self.x_vel -= self.speed
if keys[pg.K_RIGHT] or keys[pg.K_d]:
self.x_vel += self.speed
def get_position(self, obstacles):
"""Calculate the player's position this frame, including collisions."""
if not self.fall:
self.check_falling(obstacles)
else:
self.fall = self.check_collisions((0,self.y_vel), 1, obstacles)
if self.x_vel:
self.check_collisions((self.x_vel,0), 0, obstacles)
def check_falling(self, obstacles):
"""If player is not contacting the ground, enter fall state."""
if not self.collide_below:
self.fall = True
self.on_moving = False
def check_moving(self,obstacles):
"""
Check if the player is standing on a moving platform.
If the player is in contact with multiple platforms, the prevously
detected platform will take presidence.
"""
if not self.fall:
now_moving = self.on_moving
any_moving, any_non_moving = [], []
for collide in self.collide_below:
if collide.type == "moving":
self.on_moving = collide
any_moving.append(collide)
else:
any_non_moving.append(collide)
if not any_moving:
self.on_moving = False
elif any_non_moving or now_moving in any_moving:
self.on_moving = now_moving
def check_collisions(self, offset, index, obstacles):
"""
This function checks if a collision would occur after moving offset
pixels. If a collision is detected, the position is decremented by one
pixel and retested. This continues until we find exactly how far we can
safely move, or we decide we can't move.
"""
unaltered = True
self.rect[index] += offset[index]
self.hand_rect[index] += offset[index]
while pg.sprite.spritecollideany(self, obstacles):
self.rect[index] += (1 if offset[index]<0 else -1)
self.hand_rect[index] += (1 if offset[index]<0 else -1)
unaltered = False
return unaltered
def check_above(self, obstacles):
"""When jumping, don't enter fall state if there is no room to jump."""
self.rect.move_ip(0, -1)
collide = pg.sprite.spritecollideany(self, obstacles)
self.rect.move_ip(0, 1)
return collide
def check_below(self, obstacles):
"""Check to see if the player is contacting the ground."""
self.rect.move_ip((0,1))
collide = pg.sprite.spritecollide(self, obstacles, False)
self.rect.move_ip((0,-1))
return collide
def jump(self, obstacles):
"""Called when the user presses the jump button."""
if not self.fall and not self.check_above(obstacles):
self.y_vel = self.jump_power
self.fall = True
self.on_moving = False
def jump_cut(self):
"""Called if player releases the jump key before maximum height."""
if self.fall:
if self.y_vel < self.jump_cut_magnitude:
self.y_vel = self.jump_cut_magnitude
def get_angle(self, mouse):
x_off = (mouse[0]-self.rect.centerx)
y_off = (mouse[1]-self.rect.centery)
self.angle = math.degrees(math.atan2(-y_off, x_off) % (2*math.pi))
self.hand = pg.transform.rotate(self.original_hand, self.angle)
self.hand_rect = self.hand.get_rect(center=self.hand_rect.center)
"""
offset = (mouse[1]-self.hand_rect.centery, mouse[0]-self.hand_rect.centerx)
self.angle = math.atan2(-offset[0], offset[1]) % (2 * math.pi)
self.angle = math.degrees(self.angle)
self.hand = pg.transform.rotate(self.original_hand, self.angle)
self.hand_rect = self.hand.get_rect(center=self.rect.center)
self.angle = 135-math.degrees(math.atan2(*offset))
self.hand = pg.transform.rotate(self.original_hand, self.angle)
self.hand_rect = self.hand.get_rect(topleft=self.rect.topleft)
"""
def pre_update(self, obstacles):
"""Ran before platforms are updated."""
self.collide_below = self.check_below(obstacles)
self.check_moving(obstacles)
def update(self, obstacles, keys):
"""Everything we need to stay updated; ran after platforms update."""
self.check_keys(keys)
self.get_position(obstacles)
self.physics_update()
def get_event(self, event, bolts):
if event.type == pg.MOUSEBUTTONDOWN and event.button == 1:
bolts.add(Bolt(self.rect.center))
elif event.type == pg.MOUSEMOTION:
self.get_angle(event.pos)
def draw(self, surface):
"""Blit the player to the target surface."""
surface.blit(self.image, self.rect)
surface.blit(self.hand, self.hand_rect)
class Bolt(pg.sprite.Sprite):
def __init__(self, location):
pg.sprite.Sprite.__init__(self)
"""self.original_bolt = pg.image.load('bolt.png')"""
"""self.angle = -math.radians(angle-135)"""
"""self.image = pg.transform.rotate(self.original_bolt, angle)"""
"""self.image = self.original_bolt"""
self.image=pg.Surface((5,10)).convert()
self.image.fill(pg.Color("yellow"))
self.rect = self.image.get_rect(center=location)
self.move = [self.rect.x, self.rect.y]
self.speed_magnitude = 5
"""self.speed = (self.speed_magnitude*math.cos(self.angle), self.speed_magnitude*math.sin(self.angle))"""
"""self.speed = (5,0)"""
self.done = False
def update(self, screen_rect, obstacles):
self.move[0] += self.speed_magnitude
"""self.move[1] += self.speed[1]"""
self.rect.topleft = self.move
self.remove(screen_rect, obstacles)
def remove(self, screen_rect, obstacles):
if not self.rect.colliderect(screen_rect):
self.kill()
class Block(pg.sprite.Sprite):
"""A class representing solid obstacles."""
def __init__(self, color, rect):
"""The color is an (r,g,b) tuple; rect is a rect-style argument."""
pg.sprite.Sprite.__init__(self)
self.rect = pg.Rect(rect)
self.image = pg.Surface(self.rect.size).convert()
self.image.fill(color)
self.type = "normal"
class MovingBlock(Block):
"""A class to represent horizontally and vertically moving blocks."""
def __init__(self, color, rect, end, axis, delay=500, speed=2, start=None):
"""
The moving block will travel in the direction of axis (0 or 1)
between rect.topleft and end. The delay argument is the amount of time
(in miliseconds) to pause when reaching an endpoint; speed is the
platforms speed in pixels/frame; if specified start is the place
within the blocks path to start (defaulting to rect.topleft).
"""
Block.__init__(self, color, rect)
self.start = self.rect[axis]
if start:
self.rect[axis] = start
self.axis = axis
self.end = end
self.timer = 0.0
self.delay = delay
self.speed = speed
self.waiting = False
self.type = "moving"
def update(self, player, obstacles):
"""Update position. This should be done before moving any actors."""
obstacles = obstacles.copy()
obstacles.remove(self)
now = pg.time.get_ticks()
if not self.waiting:
speed = self.speed
start_passed = self.start >= self.rect[self.axis]+speed
end_passed = self.end <= self.rect[self.axis]+speed
if start_passed or end_passed:
if start_passed:
speed = self.start-self.rect[self.axis]
else:
speed = self.end-self.rect[self.axis]
self.change_direction(now)
self.rect[self.axis] += speed
self.move_player(now, player, obstacles, speed)
elif now-self.timer > self.delay:
self.waiting = False
def move_player(self, now, player, obstacles, speed):
"""
Moves the player both when on top of, or bumped by the platform.
Collision checks are in place to prevent the block pushing the player
through a wall.
"""
if player.on_moving is self or pg.sprite.collide_rect(self,player):
axis = self.axis
offset = (speed, speed)
player.check_collisions(offset, axis, obstacles)
if pg.sprite.collide_rect(self, player):
if self.speed > 0:
self.rect[axis] = player.rect[axis]-self.rect.size[axis]
else:
self.rect[axis] = player.rect[axis]+player.rect.size[axis]
self.change_direction(now)
def change_direction(self, now):
"""Called when the platform reaches an endpoint or has no more room."""
self.waiting = True
self.timer = now
self.speed *= -1
"""class Spell(pg.sprite.Sprite):
def __init__(self, location, angle)"""
class Control(object):
"""Class for managing event loop and game states."""
def __init__(self):
"""Initalize the display and prepare game objects."""
self.screen = pg.display.get_surface()
self.screen_rect = self.screen.get_rect()
self.clock = pg.time.Clock()
self.fps = 60.0
self.keys = pg.key.get_pressed()
self.done = False
self.player = Player((50,875), 4)
self.viewport = self.screen.get_rect()
self.level = pg.Surface((1000,1000)).convert()
self.level_rect = self.level.get_rect()
self.win_text,self.win_rect = self.make_text()
self.obstacles = self.make_obstacles()
self.bolts = pg.sprite.Group()
def make_text(self):
"""Renders a text object. Text is only rendered once."""
font = pg.font.Font(None, 100)
message = "You win. Celebrate."
text = font.render(message, True, (100,100,175))
rect = text.get_rect(centerx=self.level_rect.centerx, y=100)
return text, rect
def make_obstacles(self):
"""Adds some arbitrarily placed obstacles to a sprite.Group."""
walls = [Block(pg.Color("chocolate"), (0,980,1000,20)),
Block(pg.Color("chocolate"), (0,0,20,1000)),
Block(pg.Color("chocolate"), (980,0,20,1000))]
static = [Block(pg.Color("darkgreen"), (250,780,200,100)),
Block(pg.Color("darkgreen"), (600,880,200,100)),
Block(pg.Color("darkgreen"), (20,360,880,40)),
Block(pg.Color("darkgreen"), (950,400,30,20)),
Block(pg.Color("darkgreen"), (20,630,50,20)),
Block(pg.Color("darkgreen"), (80,530,50,20)),
Block(pg.Color("darkgreen"), (130,470,200,215)),
Block(pg.Color("darkgreen"), (20,760,30,20)),
Block(pg.Color("darkgreen"), (400,740,30,40))]
moving = [MovingBlock(pg.Color("olivedrab"), (20,740,75,20), 325, 0),
MovingBlock(pg.Color("olivedrab"), (600,500,100,20), 880, 0),
MovingBlock(pg.Color("olivedrab"),
(420,430,100,20), 550, 1, speed=3, delay=200),
MovingBlock(pg.Color("olivedrab"),
(450,700,50,20), 930, 1, start=930),
MovingBlock(pg.Color("olivedrab"),
(500,700,50,20), 730, 0, start=730),
MovingBlock(pg.Color("olivedrab"),
(780,700,50,20), 895, 0, speed=-1)]
return pg.sprite.Group(walls, static, moving)
def update_viewport(self):
"""
The viewport will stay centered on the player unless the player
approaches the edge of the map.
"""
self.viewport.center = self.player.rect.center
self.viewport.clamp_ip(self.level_rect)
def event_loop(self):
"""We can always quit, and the player can sometimes jump."""
for event in pg.event.get():
if event.type == pg.QUIT or self.keys[pg.K_ESCAPE]:
self.done = True
elif event.type == pg.KEYDOWN:
if event.key == pg.K_SPACE:
self.player.jump(self.obstacles)
elif event.type == pg.KEYUP:
if event.key == pg.K_SPACE:
self.player.jump_cut()
elif event.type == pg.MOUSEMOTION or event.type == pg.MOUSEBUTTONDOWN:
self.player.get_event(event, self.bolts)
def update(self):
"""Update the player, obstacles, and current viewport."""
self.keys = pg.key.get_pressed()
self.player.pre_update(self.obstacles)
self.obstacles.update(self.player, self.obstacles)
self.player.update(self.obstacles, self.keys)
self.update_viewport()
self.bolts.update(self.screen_rect, self.obstacles)
def draw(self):
"""
Draw all necessary objects to the level surface, and then draw
the viewport section of the level to the display surface.
"""
self.level.fill(pg.Color("lightblue"))
self.obstacles.draw(self.level)
self.level.blit(self.win_text, self.win_rect)
self.player.draw(self.level)
self.bolts.draw(self.level)
self.screen.blit(self.level, (0,0), self.viewport)
def display_fps(self):
"""Show the programs FPS in the window handle."""
caption = "{} - FPS: {:.2f}".format(CAPTION, self.clock.get_fps())
pg.display.set_caption(caption)
def main_loop(self):
"""As simple as it gets."""
while not self.done:
self.event_loop()
self.update()
self.draw()
pg.display.update()
self.clock.tick(self.fps)
self.display_fps()
if __name__ == "__main__":
os.environ['SDL_VIDEO_CENTERED'] = '1'
pg.init()
pg.display.set_caption(CAPTION)
pg.display.set_mode(SCREEN_SIZE)
PLAYERIMG = pg.image.load("playertst.png").convert()
PLAYERIMG.set_colorkey(COLOR_KEY)
run_it = Control()
run_it.main_loop()
pg.quit()
sys.exit()
The % 2*pi unnecessary, and your get_angle function has no return value, but you do an assignment to self.angle = self.get_angle, but that is not the issue. The issue is that the mouse position is relative to the screen (i.e. clicking in the top right area of your game screen will always yield (0,480) if your screen is 640x480), while the position of the (character) rectangle is given in your game play area, which is larger than the screen, ergo if you move the character and thus the view shifts, you are getting coordinates in two different coordinate systems. You will have to keep track of where the view is in your game play area and add the offset to the mouse coordinates.

Controlling pygame animation through text input

I need to create a fighting game that gives prompts and accepts input through text, such as a raw input and then performs the animation, while still have the characters animated, e.g. moving back and forth in a ready to fight stance. How would I go about this?
Please note that this is not going to be your typical answer. StackOverflow is to help after all that you can do on your part when you are stuck, it's not meant as a place to come for code, but since I'm assuming other people new to programming will also be confused on things such as these. So I'm going to write some code, and some psuedo code, just so that you get the just of what you would do in such a scenario.
# TODO put your imports up here
pygame.init()
clock = pygame.time.Clock()
gameSurface = pygame.display.set_mode((600, 400)) # 2/3 aspect ratio
FPS = 40 # Set to your own Frames per second
class Animator:
def __init__(self, surface, rows, cols, time_between_frames, on_finish):
self.images = []
self.current_image = 0
self.time_between_frames = time_between_frames # time animator waits before changing surface
self.current_time # tracks time for frames to change
self.on_finish = on_finish # function to call when animation finishes
surf_width = (surface.get_width() / cols) # calculate width
surf_height = (surface.get_height() / rows) # calculate height
for x in range(cols):
for y in range(rows):
surf = pygame.Surface(surface.get_size()) # temp surface
from_rect = pygame.Rect(x * surf_width, y * surf_height, surf_width, surf_height) # rect to blit from
surf.blit(surface, (0,0), from_rect) # draw to temp surface
self.images.append(surf) # add temp surface to the images list
def update(delta):
self.current_time += delta # update current time
if (self.current_time >= self.time_between_frames): # if time to switch surfaces
self.current_time -= self.time_between_frames # take away time from current time
self.current_image += 1 # change image
if self.current_image >= len(self.images): # if current image would throw an out of bounds exception
self.current_image = 0 # reset the current image to the first
def get_frame(self):
return self.images[self.current_image]
class Player:
resting = 0
abdomenKick = 1
def __init__(self, x, y):
self.x = x
self.y = y
self.action = Player.resting
self.restingAnimation = Animation(pygame.image.load("resting.png"), 2, 3, 500)
self.abdomenKickAnimation = Animation(pygame.image.load("abdomenKick.png"), 4, 6, 50)
self.currentAnimation = self.restingAnimation
def update(self, delta):
self.currentAnimation.update(delta)
def draw(self, surface):
surface.blit(self.currentAnimation.get_frame(), (self.x, self.y))
def abdomenKick(self):
self.currentAnimation = self.restingAnimation
class Game:
def __init__(self):
self.player = Player()
def update(self, delta):
self.player.update(delta)
def draw_screen(self, surface):
self.player.draw(surface)
def gameLoop():
game = Game()
while True:
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == A:
game.player.abdomenKick() #Or whatever move you have
game.update(clock.get_rawtime())
game.draw_screen()
clock.tick(FPS)
So here is just a brief showcase you can call it of what this might look like.

Periodically changing images(sprites?) in pyglet

How to make this code work: Just have pyglet installed and change "assassin1.png" and "assassin2.png" with the name of an images stored in the directory where you saved this code to a file.
import pyglet
class Assassin(pyglet.sprite.Sprite):
def __init__(self, batch):
pyglet.sprite.Sprite.__init__(self, pyglet.resource.image("assassin1.png"))
self.x = 50
self.y = 30
def forward_movement(self):
pass # How do I continously change between 'assassin1.png' and 'assassin2.png'?
class Game(pyglet.window.Window):
def __init__(self):
pyglet.window.Window.__init__(self, width = 315, height = 220)
self.batch_draw = pyglet.graphics.Batch()
self.player = Assassin(batch = self.batch_draw)
self.fps_display = pyglet.clock.ClockDisplay()
self.keys_held = []
self.schedule = pyglet.clock.schedule_interval(func = self.update, interval = 1/60.)
def on_draw(self):
self.clear()
self.fps_display.draw()
self.batch_draw.draw()
self.player.draw()
def on_key_press(self, symbol, modifiers):
self.keys_held.append(symbol)
if symbol == pyglet.window.key.RIGHT:
self.player.forward_movement()
print "The 'RIGHT' key was pressed"
def on_key_release(self, symbol, modifiers):
self.keys_held.pop(self.keys_held.index(symbol))
def update(self, interval):
if pyglet.window.key.RIGHT in self.keys_held:
self.player.x += 50 * interval
if __name__ == "__main__":
window = Game()
pyglet.app.run()
Description: This code creates a black background screen, where the fps are displayed and an
image "assassin1.png" is displayed at position (50, 30). As long as the right direction button is held down the image will move to the right.
Goal: I would like to implement that whenever the right direction button is held and the image is moving, the assassin1.png image is changed periodically (every 0.25 secs or so) with a second image assassin2.png. This in order to create the vague illusion that the image is walking.
How do I achieve this goal?
I already created an empty forward_movement() method in the Assassin class which would seem an appropriate place to put the code to achieve my goal. But if you would want to place the code in another place thats ok too.
The pyglet.sprite.Sprite class allows you to edit its image to an animation at anytime. So, in the sprites constructor, we define a walk animation:
def __init__(self, batch):
# The image to display when not moving
self._img_main = pyglet.image.load('assassin.png')
self._img_right_1 = pyglet.image.load('assassin1.png')
self._img_right_2 = pyglet.image.load('assassin2.png')
self.anim_right = pyglet.image.Animation.from_image_sequence([
self._img_right_1, self._img_right_2], 0.5, True)
# 0.5 is the number in seconds between frames
# True means to keep looping (We stop it later)
pyglet.sprite.Sprite.__init__(self, self._img_main)
#...
Next we add a function to make it easier to change animations:
def forward_movement(self, flag=True):
if flag:
self.image = self.anim_right # Now our sprite animates
else:
self.image = self._img_main
Finally we call the function at the appropriate time:
#...
def on_key_press(self, symbol, modifiers):
self.keys_held.append(symbol)
if symbol == pyglet.window.key.RIGHT:
self.player.forward_movement(True)
print "The 'RIGHT' key was pressed"
def on_key_release(self, symbol, modifiers):
self.keys_held.pop(self.keys_held.index(symbol))
if symbol == pyglet.window.key.RIGHT:
self.player.forward_movement(False) # We have stopped moving
#...
And voilĂ ! When the user has the right-key down, the sprite moves and animates!

Categories