How to make a sprite jump in Pyglet? - python

I've been making a personal project to remake a modified version of SUper Mario Bros.
So far, I've been able to add in the Mario sprite along with the ground and bricks. Now, I'm stuck with how to make Mario jump. Does anyone know how to do it?
EDIT: I already made a class for Mario, but can't get the jump to work. Any ideas why?
class mario(pyglet.sprite.Sprite):
def __init__(self, batch):
self._img_main = pyglet.image.load("Mario_Right.png")
self.img_right1 = pyglet.image.load("Mario_Walk_Right1.png")
self.img_right2 = pyglet.image.load("Mario_Walk_Right2.png")
self.anim_right = pyglet.image.Animation.from_image_sequence([self.img_right1, self.img_right2], 0.5, True)
pyglet.sprite.Sprite.__init__(self, self._img_main)
self.time = 0
def forward_movement(self, flag=True):
if flag:
self.image = self.anim_right
else:
self.image = self._img_main
def jump(self,flag=True):
print time.time()-self.time
self.y -= -10 +20**(time.time()-self.time+.2)
def on_key_press(self, symbol, modifiers):
self.keys_held.append(symbol)
if symbol == pyglet.window.key.RIGHT:
self.player.forward_movement(True)
if symbol == pyglet.window.key.LEFT:
self.player.time=time.time()
self.player.jump()

Try to create gravity on your code. First, create a class for your Mario. Set up their positions and speed. Put up method jump on your Mario.
#put this in your init
self.time = 0
#put this in your condition
if keymap[pyglet.window.key.RIGHT]:
self.mario.time = time.time()
self.mario.jump()
def jump(self):
print time.time()-self.time
self.y -= -10 +20**(time.time()-self.time+.2)

Related

Is there a way to change my_sprite or my_group to change the animation displayed?

I'm making animated sprites in pygame, and would like help finding a way to flip from one to the other? The current code looks something like this:
class normal(pygame.sprite.Sprite):
def __init__(self):
#etc, list of images to create the animation
class tall(pygame.sprite.Sprite):
def __init__(self):
#rinse and repeat with a different set of images
I already have an idea for how to trigger the change via keystroke. But I'm not sure which variable to change, and to what. When I try to change with the following code, nothing happens
fps = 25
pygame.init()
my_sprite = normal()
my_group = pygame.sprite.Group(my_sprite)
#etc until we get to the part where it changes
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RETURN:
if my_sprite == normal():
my_sprite = tall()
fps = 30
else:
my_sprite = normal()
fps = 25
I'm not sure exactly what isn't working in my code as it doesn't come back with an error. Can someone point me in the right direction?
It's not working because when the code calls normal() it's creating a new instance of an object. So the call:
if my_sprite == normal():
Is saying "is my existing sprite object == this new sprite object", which is never true. You can use the python function to type() of the object to do the same thing, or add your own type-function as I have presented in the code below.
I would track the state of the sprite inside the class, and use some functions grow() and shrink() to change the size automatically.
class GrowingSprite( pygame.sprite.Sprite, x, y ):
def __init__( self ):
#etc, list of images to create the animation
self.image_short = ... # load "short" image
self.image_tall = ... # load "tall" image
# Set the initial state
self.image = self.image_short # start short
self.rect = self.image.get_rect()
self.rect.centerx = x
self.rect.centery = y
self.state = 'short'
def getState( self ):
return self.state
def grow( self ):
self.state = 'tall'
self.image = self.image_tall
current_x = self.rect.centerx # preserve existing location
current_y = self.rect.centery
self.rect = self.image.get_rect()
self.rect.center = ( current_x, current_y )
def shrink( self ):
self.state = 'short'
self.image = self.image_short
current_x = self.rect.centerx # preserve existing location
current_y = self.rect.centery
self.rect = self.image.get_rect()
self.rect.center = ( current_x, current_y )
I found a workaround that is a bit redundant, but it makes it possible to expand it in case there are more groups
It requires making two groups that can be pulled back and fourth, and changing the foo.draw(screen) to the new group. This is how it looks
nml_sprite = normal()
tal_sprite = tall()
tg = 1 #this is nothing more than a switch to trigger the change
tal_group = pygame.sprite.Group(tal_sprite)
nml_group = pygame.sprite.Group(nml_sprite)
cursprite = nml_group #this variable determines which sprite set is loaded
...
...
if event.key == pygame.K_RETURN:
if tg == 1:
curspt = tal_group
tg = 2
else:
curspt = nml_group
tg = 2
...
...
nml_group.update()
tal_group.update()
curspt.draw(screen)
...

How to create free game collision with pyglet?

I have started working on a 2d game that is comparable to Terraria in terms of what I am dealing with. My problem is as follows The world is made of tiles/blocks then there is the player. I can't seem to find a way to make the player collide with the tiles, why not a set ground level? because if there isn't a tile under the player he should fall and what if the players on a hill? So long story short I need a way to make the player collide with the tile beneath them.
So here is what I have tried: making a simplified grid to verify if the is a tile below, a for loop where I compared all the tiles to the players feet but this was too much data to feed and I couldn't find a way to say check the tile under, above, left, and right of the player and only those positions. I am going to try to show useful code but it will be a bit jumbled seeing as I cant pas't all the files in.
class Physics:
#classmethod
def fall(cls, dt, o, world, mod):
if world.grid_fill[(o.grid_pos[0], o.grid_pos[1]-1)] == "Filled":
o.falling = False
else:
o.y -= o.height//8*dt
o.update_pos(o.x, o.y)
#classmethod
def run_physics(cls, dt, o, world):
for obj in o:
Physics.fall(dt, obj, world, None)
# player and Physics are in 2 different files as is world and the main loop
class Player:
def __init__(self, sprite, x, y, world):
self.img = sprite
self.img.set_position(x, y)
self.key_handler = key.KeyStateHandler()
self.type = "Player"
self.x = x
self.y = y
self.pos = (self.x, self.y)
self.grid_pos = world.pix_cords[self.pos]
self.width = self.img.width
self.height = self.img.height
self.speed = self.width//4
self.falling = False
def update_pos(self, x, y):
self.img.set_position(x, y)
def draw(self):
self.img.draw()
def check_fall(self, tile):
if self.y - self.height//2 == tile.y + tile.height:
return False
else:
return True
def update(self):
if self.key_handler[key.A]:
self.x -= self.speed
if self.key_handler[key.D]:
self.x += self.speed
if self.key_handler[key.W]:
self.y += self.speed
self.update_pos(self.x, self.y)
Before you say I didn't show how the ground is made that is because I can explain this by just saying it is made using a batch draw and all sprite cornets are centered to the sprite. Alright, when I run this code the player falls indefinitely but I want it to stop when there is a tile under it.
If you need to see the batch for the tile I will but I don't know if that is needed and if you see anything unprofessional about how this is written I am always willing to learn how to write more professionally.
This was a stupid question. Just need to make a simplified positioning system based on the blocks, not sprites.

How do i instance sprites in Pygame? Do i need too?

So im working on a game for some coursework in my computing course, im almost finished but for the life of me i cant get multiple of the Spider sprite to spawn in at the correct locations or reset properly between levels. I've tried adding different instances to groups before but i always get a different error with each method that i try. the code is below and im fairly new to pygame so sorry for the messy code..
#
class Spider(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load( 'Assets/Level-Assets/Level 1/Enemies/Spider_Down.png')
self.rect = self.image.get_rect()
self.Health = 3
self.Spawned = False
self.range = 100
self.Gravity= 6
self.pos_difference = 0
self.Active = False
self.Fall = False
self.Spiders = []
##################################################################################################################
def Set_Position(self):
if self.Spawned == False:
self.rect.center = (World.mapx, World.mapy)
Enemies.add(self)
self.Spawned = True
else:
self.rect.center = self.rect.center
######################################################################################################################
def update(self):
self.pos_difference = Player.rect.centery - self.rect.centery
if Player.rect.centerx >= self.rect.centerx -4 or Player.rect.centerx >= self.rect.centerx + 4:
if Player.rect.centery > self.rect.centery:
if self.pos_difference < 200:
self.Active = True
self.Fall = True
if self.Active == True:
if self.Fall == True:
self.rect.centery += self.Gravity
This is the code for the Spider, its not actually doing anything until it is called within the World class, which is where i believe the majority of the problem is...
def DisplayWorld(self):
self.MapLoad = False
for Row in range(len(self.newMap)):
for Col in range(len(self.newMap[Row])):
self.mapx = Col * 64
self.mapy = ((Row + self.Height_modifier) * 64)
self.tile_pos = (self.mapx, self.mapy )
if int(self.newMap[Row][Col]) == 1:
self.rect = self.Brick_Center.get_rect(left = (self.mapx) , bottom = (self.mapy))
self.World_sprites.add(World)
self.Camera_Pos_Check()
Player.Collision_Check()
Spider.Collision_Check()
Shoot.Collision_Check()
self.World_sprites.draw(screen)
elif int(self.newMap[Row][Col]) == 2:
Enemies.add(Spider(screen))
def main():
play = True
while play:
if pygame.key.get_pressed()[pygame.K_ESCAPE]:
play = False
if not Sprites.sprites():
Sprites.add(Player,Spider)
print(Sprites)
clock.tick(CLOCKRATE)
pygame.mouse.set_visible(False)
for event in pygame.event.get():
if event.type == pygame.QUIT:
play = False
screen.blit(bgi,(0,0))
screen.blit(bgi,(0,500))
World.findLevel()
Sprites.update()
Enemies.draw(screen)
Sprites.draw(screen)
if Shoot.bullet == True:
Shoot.update()
for b in range(len(Shoot.bullets)):
screen.blit(Shoot.image, (Shoot.bullets[b][0],Shoot.bullets[b][1]))
UI.Health_Display()
pygame.display.flip()
Sprites = pygame.sprite.Group()
Enemies = pygame.sprite.Group()
UI = User_Interface()
World = World()
Player = Proto()
Shoot = Shoot()
Portal = Portals()
Spider = Spider()
main()
I've found your problem: you overwrite your Spider class by an instance of it (Spider()) and then give it the same name. Thus you're consistently adding the same single spider to your enemies list. Instead, you should remove this definition on the bottom of your file and where ever you're adding the (multiple) spider(s), you should create this instance.
In a more general remark, it is considered bad style (and not too great for performance) to use global variables as widely as you do. It'd be much better to pass them around between functions and classes. Also, the CamelCase capitalization you use for all of your variables is commonly only used for classes. I'd recommend checking up on pep8 to learn more about how to use common Python styles. It makes these kinds of problems easier to spot, less likely to occur, and simplifies the reading for anyone involved. Using these points properly might even improve your grade significantly ;).

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.

Trying to shoot a projectile originating from a character in Pygame (with statement for all_sprites)

I am trying to fire a projectile from a character, with that projectile being the mudball image. I have referenced my class MUDBALL to be included in all_sprites. In my first approach I get an error saying: AttributeError: 'TRUMP' object has no attribute 'rect' when I try and include MUDBALL in all_sprites. That approach is in the code below along with the Game class definitions. In the second approach I try and code the all_sprites statement into the shoot method of the of the TRUMP class. I understand I only need one of these 2 pieces of code to work. I have tried to include the code necessary while omitting everything else to minimize confusion.
import pygame as pg
class Game:
def __init__(self):
# initialize game window, etc
pg.init()
pg.mixer.init()
self.screen = pg.display.set_mode((WIDTH, HEIGHT))
pg.display.set_caption(TITLE)
self.clock = pg.time.Clock()
self.running = True
self.font_name = pg.font.match_font(FONT_NAME)
self.load_data()
def load_data(self):
# load high score
self.dir = path.dirname(__file__)
img_dir = path.join(self.dir, 'img')
with open(path.join(self.dir, HS_FILE), 'r') as f:
try:
self.highscore = int(f.read())
except:
self.highscore = 0
# load spritesheet image
self.spritesheet = Spritesheet(path.join(img_dir, SPRITESHEET))
def new(self):
# start a new game
self.score = 0
self.all_sprites = pg.sprite.Group()
self.platforms = pg.sprite.Group()
self.player = Player(self)
#ME: TRUMP added to all sprites!!!
self.trump = TRUMP(self)
self.all_sprites.add(self.trump)
#***First attempt at adding mudball to all_sprites
self.mudball = MUDBALL(TRUMP.rect.centerx, TRUMP.rect.centery)
self.all_sprites.add(self.mudball)
#game class continues...
class TRUMP(pg.sprite.Sprite):
def __init__(self, game):
pg.sprite.Sprite.__init__(self)
self.game = game
self.current_frame2 = 0
self.last_update2 = 0
self.load_images()
#TRUMP class continued etc... Second attempt with shoot def is below.
def shoot(self):
mudball = MUDBALL(self.rect.centerx, self.rect.centery)
Game.all_sprites.add(mudball)
mudballs.add(mudball)
class MUDBALL(pg.sprite.Sprite):
def __init__(self, x, y):
pg.sprite.Sprite.__init__(self)
self.image = pg.image.load("MUDBALL.png")
self.rect = self.image.get_rect()
self.rect.bottom = y
self.rect.centerx = x
self.speedx = -10
def update(self):
self.rect.x += self.speedx
# kill if moves off screen
if self.rect.centerx < 0:
self.kill
Shoot is a method of the TRUMP class! In second attempt I try and add MUDBALL to all sprites within the shoot definition of the TRUMP class. That doesn't work. again in this approach I take out the code from the previous approach. That attempt, which is just below, returns: NameError: name 'Game' is not defined. I don't know how to proceed.
The problem may be with your line
self.mudball = MUDBALL(self)
MUDBALL's __init__ method requires x, y arguments; instead, you passed it an object and nothing. That would be enough to cause the error you're seeing.
Response to OP update:
That's correct: Game is not defined. That one line is the only place in your posted code where the symbol appears. As you've coded this, you have the attachment backwards: all_sprites is an attribute (variable field) of Game. In other words, all_sprites is attached to Game, not the other way around. The only way to get to all_sprites is through Game ... except that Game isn't defined anywhere.
A friend of mine helped me. He says "TRUMP is your class ... it does not have rect as an attribute only an instance of TRUMP will have rect as an attribute." I don't understand this yet. But want to thank everyone who helped me along.
self.mudball = MUDBALL(self.trump.rect.centerx, self.trump.rect.centery)
self.all_sprites.add(self.mudball)

Categories