Hello I am currently working on a game in pygame and I am now trying to add a ground, gravity and jump. When I run the code I get an attribute error. Please help if you have a fix, here is the code:
import pygame, sys, time
from pygame.locals import *
pygame.init()
# A few variables
zx = 320
zy = 320
x = 25
y = 320
velX = 0
velY = 0
gravity = .50
ground = 720
clock = pygame.time.Clock()
# Screen
size = 1280, 720
screen = pygame.display.set_mode(size)
pygame.display.set_caption('Moon Survival!')
# Moon
moon = pygame.image.load('images/arena2.jpg')
pygame.display.update()
# Player
class Player(pygame.sprite.Sprite):
global gravity
def __init__(self, x, y):
# Player dimensions and position
self.x = x
self.y = y
self.width = 80
self.height = 80
# Player image and animation
self.i0 = pygame.image.load('images/soldier.png')
self.i1 = pygame.image.load('images/soldier2.png')
self.timeTarget = 10
self.timeNum = 0
self.currentImage = 0
# Jump and gravity
self.vSpeed = 1
self.jumpForce = 8
self.maxVspeed = 3
self.isJumping = False
# Jump inputs
def getInput(self):
keys = pygame.key.get_pressed()
if keys[pygame.K_SPACE]:
if not self.isJumping:
self.isJumping = True
# PLayer updates
def update(self):
# Jumping
self.getInput()
self.vSpeed += gravity
if self.vSpeed > self.maxVspeed:
self.vSpeed = self.maxVspeed
self.y += self.vSpeed
if self.y >= ground.y:
self.vSpeed = 0
self.y = ground.y
self.isJumping = False
if self.isJumping:
self.vSpeed += -self.jumpForce
# Animations
#self.timeNum += 1
if (self.timeNum == self.timeTarget):
if (self.currentImage == 0):
self.currentImage = 0
else:
self.currentImage = 0
self.timeNum = 0
self.render()
# Player rendering
def render(self):
if (self.currentImage == 0):
screen.blit(self.i0, (self.x, self.y))
#else:
#screen.blit(self.i1, (self.x, self.y))
# Zombies
zombie = pygame.image.load('images/zombie.png')
pygame.display.update()
# Sprite variables
player = Player(25, 320)
# Game loop
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
# Movement
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_a:
velX = -5
if event.key == pygame.K_d:
velX = +5
if event.type == pygame.KEYUP:
if event.key == pygame.K_a:
velX = 0
if event.key == pygame.K_d:
velX = 0
# Image blitting
screen.blit(moon, (0,0))
screen.blit(zombie, (zx, zy))
# Movement variables
player.x += velX
player.y += velY
player.update()
# Screen wrap
if player.x >= 1240:
player.x = 1
if player.x <= 0:
player.x = 1240
# Display updating
clock.tick(75)
pygame.display.update()
Any help will be greatly appreciated, thank you.
In some places you try to use int value as object:
ground = 720
self.y = ground.y # error !!!
ground is number int(integer) not object with .y
You could use pygame.Rect()
ground = pygame.Rect(0, 750, 0, 0) # (x, y, width, heigh)
and then you can use ground.x, ground.y, and others - see pygame.Rect().
.
btw: you should move #Movement code, # Movement variablescode, # Screen wrap code into Player class as functions and call that functions in main loop - to make main loop more readable.
# Movement variablescode, # Screen wrap code could be in player.update
# Movement code could be in Player class as event_handler(self, event)
def event_handler(self, event):
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_a:
velX = -5
elif event.key == pygame.K_d:
velX = +5
elif event.type == pygame.KEYUP:
if event.key in (pygame.K_a, pygame.K_d):
velX = 0
(you can use elif as above)
Now you can use this in main loop player.event_handler(event)
EDIT:
I made many modifications in your code - but I had no time to finish it.
Player still doesn't jump. But you have 10 moving zombies, pause (press P) and all in classes.
import pygame
import random
# Player
class Player(pygame.sprite.Sprite):
def __init__(self, x, y, gravity):
# Player dimensions and position
self.gravity = gravity
# Player image and animation
self.images = []
self.images.append(pygame.image.load('images/soldier.png'))
self.images.append(pygame.image.load('images/soldier2.png'))
#~ self.images.append(pygame.image.load('ball1.png'))
#~ self.images.append(pygame.image.load('ball2.png'))
self.maxImage = len(self.images)
self.currentImage = 0
#~ self.rect = pygame.Rect(x, y, 80, 80)
self.rect = self.images[0].get_rect()
self.rect.x = x
self.rect.y = y
self.timeTarget = 10
self.timeNum = 0
self.velX = 0
self.velY = 0
# Jump and gravity
self.vSpeed = 1
self.jumpForce = 8
self.maxVspeed = 3
self.isJumping = False
# Jump inputs
def handle_events(self, event):
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
if not self.isJumping:
self.isJumping = True
elif event.key == pygame.K_a:
self.velX = -5
elif event.key == pygame.K_d:
self.velX = +5
elif event.type == pygame.KEYUP:
if event.key in (pygame.K_a, pygame.K_d):
self.velX = 0
print "isJumping:", self.isJumping
# PLayer updates
def update(self, ground):
# Jumping
self.vSpeed -= self.gravity
if self.vSpeed > self.maxVspeed:
self.vSpeed = self.maxVspeed
self.rect.y -= self.vSpeed
if self.isJumping:
self.vSpeed -= self.jumpForce
if self.rect.bottom >= ground.y:
self.vSpeed = 0
self.rect.bottom = ground.y
self.isJumping = False
# Animations
if self.timeNum == self.timeTarget:
self.currentImage += 1
if self.currentImage >= self.maxImage:
self.currentImage = 0
self.timeNum = 0
self.rect.centerx += self.velX
self.rect.centery += self.velY
# Screen wrap
if self.rect.right > 1280:
self.rect.left = 0
elif self.rect.left < 0:
self.rect.right = 1280
# Player rendering
def render(self, surface):
surface.blit(self.images[self.currentImage], self.rect)
#----------------------------------------------------------------------
class Zombie():
def __init__(self, x, y):
self.image = pygame.image.load('images/zombie.png')
#~ self.image = pygame.image.load('ball2.png')
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.direction_left = True
def update(self, surface_rect):
if self.direction_left:
self.rect.x -= 1
if self.rect.left <= surface_rect.left:
self.direction_left = not self.direction_left
else:
self.rect.x += 1
if self.rect.right >= surface_rect.right:
self.direction_left = not self.direction_left
def render(self, surface):
surface.blit(self.image, self.rect)
#----------------------------------------------------------------------
class Background():
def __init__(self):
self.image = pygame.image.load('images/arena2.jpg')
#~ self.image = pygame.image.load('background.jpg')
self.rect = self.image.get_rect()
def render(self, surface):
surface.blit(self.image, self.rect)
#----------------------------------------------------------------------
class Game():
def __init__(self):
pygame.init()
# A few variables
self.gravity = .50
self.ground = pygame.Rect(0, 720, 0, 0)
# Screen
size = (1280, 720)
self.screen = pygame.display.set_mode(size)
pygame.display.set_caption('Moon Survival!')
# Moon / Background
self.moon = Background()
# Zombies
self.zombies = []
for i in range(10):
self.zombies.append( Zombie(random.randint(0,1280), random.randint(0,720)) )
# Player
self.player = Player(25, 320, self.gravity)
# Font for text
self.font = pygame.font.SysFont(None, 72)
# Pause - center on screen
self.pause_text = self.font.render("PAUSE", -1, (255,0,0))
self.pause_rect = self.pause_text.get_rect(center = self.screen.get_rect().center)
def run(self):
clock = pygame.time.Clock()
# "state machine"
RUNNING = True
PAUSED = False
GAME_OVER = False
# Game loop
while RUNNING:
# (all) Events
for event in pygame.event.get():
if event.type == pygame.QUIT:
RUNNING = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
RUNNING = False
elif event.key == pygame.K_p:
PAUSED = not PAUSED
# Player/Zomies events
if not PAUSED and not GAME_OVER:
self.player.handle_events(event)
# (all) Movements / Updates
if not PAUSED and not GAME_OVER:
self.player.update(self.ground)
for z in self.zombies:
z.update(self.screen.get_rect())
# (all) Display updating
self.moon.render(self.screen)
for z in self.zombies:
z.render(self.screen)
self.player.render(self.screen)
if PAUSED:
self.screen.blit(self.pause_text, self.pause_rect)
pygame.display.update()
# FTP
clock.tick(75)
# --- the end ---
pygame.quit()
#---------------------------------------------------------------------
Game().run()
Related
i'm on ideal gas theory simulation project and i want to ask you how exactly adding all particle's speed when i press arrow up. Because in my code, it didn't work.
I tried adding speed at initial process and loop but nothing work.
You can see right away what I'm trying to do.
edited for more understanding
sorry if i didn't put english
import pygame, sys, random, math
from pygame.locals import *
pygame.init()
#colour
white = [255,255,255]
black = [0,0,0]
red = [255,0,0]
green = [0,255,0]
blue = [0,0,255]
#setup window
(width,height)=(800,600)
window=pygame.display.set_mode((width,height))
pygame.display.set_caption('ideal gas')
#setup fps window
FPS=30
clock=pygame.time.Clock()
def bounceparticle(p1,p2):
dx=p1.x-p2.x
dy=p1.y-p2.y
distance=math.hypot(dx,dy)
if distance<p1.size+p2.size:
tangent=math.atan2(dy,dx)
angle=0.5*math.pi+tangent
angle1=2*tangent-p1.angle
angle2=2*tangent-p2.angle
speed1=p2.speed+p2.fire #so that every bounce increases speed
speed2=p1.speed+p1.fire #so that every bounce increases speed
(p1.angle, p1.speed) = (angle1, speed1)
(p2.angle, p2.speed) = (angle2, speed2)
p1.x += math.sin(angle)
p1.y -= math.cos(angle)
p2.x -= math.sin(angle)
p2.y += math.cos(angle)
#partikel
class Partikel:
def __init__(self,(x,y)):
self.x = x
self.y = y
self.size = 4
self.speed = 0
self.angle = 0
self.colour = blue #it need a recursion function to define changing particle's colour
self.fire = 0
def partikel_on_windows(self):
pygame.draw.circle(window,self.colour,[int(self.x),int(self.y)],self.size)
def move(self):
self.x += math.sin(self.angle) * self.speed
self.y -= math.cos(self.angle) * self.speed
#self.speed += self.fire #it can increase the speed but it takes 100 times pressed arrow up keyboard
def bounce(self):
if self.x>=width-self.size:
self.x=2*(width-self.size)-self.x
self.angle=-self.angle
self.speed += self.fire
elif self.x<=self.size:
self.x=2*self.size-self.x
self.angle=-self.angle
self.speed += self.fire
if self.y>=height-50-self.size:
self.y=2*(height-50-self.size)-self.y
self.angle=math.pi-self.angle
self.speed += self.fire
elif self.y<=self.size:
self.y=2*self.size-self.y
self.angle=math.pi-self.angle
self.speed += self.fire
number_of_particles = 200
myparticle = []
for n in range(number_of_particles):
centralpoint = random.randint(10,50)
x = random.randint(centralpoint,width-centralpoint)
y = random.randint(centralpoint,height-centralpoint)
partikel=Partikel((x,y))
partikel.angle=random.uniform(0,math.pi*2)
partikel.speed = 2
#partikel.fire = 0 #it can increase the speed but it takes 100 times pressed arrow up keyboard
#partikel.colour= [0,0,[255-partikel.speed]] #can't change the colour
myparticle.append(partikel)
# main game loop
while True:
for event in pygame.event.get():
pygame.key.set_repeat(1,50)
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == K_UP:
partikel.fire += 5
if event.key == K_DOWN:
partikel.fire -= 5
"""if event.type == pygame.KEYUP:
if event.key == K_UP:
partikel.fire = 0
if event.key == K_DOWN:
partikel.fire = 0"""
window.fill(black)
#partikel.fire = 1 #still can't
for i in range(len(myparticle)):
partikel = myparticle[i]
partikel.move()
partikel.bounce()
partikel.partikel_on_windows()
#partikel.fire = 0 #can't controling from keyboard
#partikel.colour= [0,0,[255-partikel.speed]]
for partikel2 in myparticle[i+1:]:
bounceparticle(partikel,partikel2)
pygame.display.update()
clock.tick(FPS)
You have to add to every particle in list.
I use variable speed which I change using key and later I add it to every particle in loop:
for i in range(len(partikel_ku)):
partikel.cepat += speed
Every click increases/decreases speed.
Full code:
import pygame
import random
import math
import sys
# --- constants ---- (UPPER_CASE_NAMES)
PUTIH = (255, 255, 255)
HITAM = (0, 0, 0)
MERAH = (255, 0, 0)
HIJAU = (0, 255, 0)
BIRU = (0, 0, 255)
LEBAR = 800
TINGGI = 600
FPS = 30
# --- classes --- (CamelCaseNames)
class Partikel:
def __init__(self, pos):
x, y = pos
self.x = x
self.y = y
self.size = 4
self.cepat = 0
self.sudut = 0
self.warna = BIRU
self.api = 0
def partikel_di_layar(self):
pygame.draw.circle(jendela, self.warna, [int(self.x), int(self.y)], self.size)
def gerak(self):
self.x += math.sin(self.sudut) * self.cepat
self.y -= math.cos(self.sudut) * self.cepat
def mantul(self):
if self.x >= LEBAR-self.size:
self.x = 2 * (LEBAR-self.size) - self.x
self.sudut = -self.sudut
elif self.x <= self.size:
self.x = 2 * self.size - self.x
self.sudut = -self.sudut
if self.y >= TINGGI - 50 - self.size:
self.y = 2 * (TINGGI - 50 - self.size) - self.y
self.sudut = math.pi - self.sudut
elif self.y <= self.size:
self.y = 2 * self.size - self.y
self.sudut = math.pi - self.sudut
# --- functions --- (lower_case_names)
def pantulan(p1, p2):
dx = p1.x - p2.x
dy = p1.y - p2.y
jarak = math.hypot(dx,dy)
if jarak < p1.size + p2.size:
tangen = math.atan2(dy, dx)
sudut = 0.5 * math.pi + tangen
sudut1 = 2 * tangen - p1.sudut
sudut2 = 2 * tangen - p2.sudut
cepat1 = p2.cepat + p2.api
cepat2 = p1.cepat + p1.api
p1.sudut = sudut1
p1.cepat = cepat1
p2.sudut = sudut2
p2.cepat = cepat2
p1.x += math.sin(sudut)
p1.y -= math.cos(sudut)
p2.x -= math.sin(sudut)
p2.y += math.cos(sudut)
# --- main ---
bnyk_partikel = 100
partikel_ku = []
# - init -
pygame.init()
jendela = pygame.display.set_mode((LEBAR, TINGGI))
pygame.display.set_caption('Animasi Bola')
pygame.key.set_repeat(1, 50)
# - objects -
for n in range(bnyk_partikel):
cp = random.randint(10, 50)
x = random.randint(cp, LEBAR - cp)
y = random.randint(cp, TINGGI - cp)
partikel = Partikel((x,y))
partikel.sudut = random.uniform(0, math.pi*2)
partikel.cepat = 2
partikel_ku.append(partikel)
speed = 0
# - mainloop -
clock=pygame.time.Clock()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
speed += 1
elif event.key == pygame.K_DOWN:
speed -= 1
elif event.type == pygame.KEYUP:
if event.key == pygame.K_UP:
speed = 0
elif event.key == pygame.K_DOWN:
speed = 0
jendela.fill(HITAM)
#partikel.api = 1 #masih g bisa
for i in range(len(partikel_ku)):
partikel = partikel_ku[i]
partikel.cepat += speed
partikel.gerak()
partikel.mantul()
partikel.partikel_di_layar()
partikel.api = 1 #tak bisa dipanggil dari kontrol keyboard
#partikel.warna= [0,0,[255-partikel.cepat]]
for partikel2 in partikel_ku[i+1:]:
pantulan(partikel,partikel2)
pygame.display.update()
clock.tick(FPS)
BTW: read PEP 8 -- Style Guide for Python Code
import pygame, sys
pygame.init()
surf = pygame.display.set_mode((1280, 720))
black = (0, 0, 0)
surf.fill(black)
fps_clock = pygame.time.Clock()
pygame.display.flip()
class Player(pygame.sprite.Sprite):
def __init__(self, name, xx, yy):
self.name = name
self.image = pygame.Surface((22, 22))
self.image.fill((130, 100, 200))
self.rect = self.image.get_rect(x = xx, y = yy)
self.x_vel = 0
self.y_vel = 0
def speed(self, speed):
self.speed = speed
def update(self, keys):
if keys[pygame.K_DOWN]:
self.y_vel = 3
elif keys[pygame.K_UP]:
self.y_vel = -3
else:
self.y_vel = 0
if keys[pygame.K_LEFT]:
self.x_vel = -3
elif keys[pygame.K_RIGHT]:
self.x_vel = 3
else:
self.x_vel = 0
self.rect.x += self.x_vel
self.rect.y += self.y_vel
def update1(self, keys):
if keys[pygame.K_s]:
self.y_vel = 3
elif keys[pygame.K_w]:
self.y_vel = -3
else:
self.y_vel = 0
if keys[pygame.K_a]:
self.x_vel = -3
elif keys[pygame.K_d]:
self.x_vel = 3
else:
self.x_vel = 0
self.rect.x += self.x_vel
self.rect.y += self.y_vel
def draw(self, surface):
surf.fill(black)
surface.blit(self.image, self.rect)
player = Player('Tank', 100, 300)
player2 = Player('Tank2', 200, 500)
def main():
while True:
keys = pygame.key.get_pressed()
player.draw(surf)
player2.draw(surf)
player.update(keys)
player2.update1(keys)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
pygame.display.update()
fps_clock.tick(60)
main()
Trying to create 2 sprites, one which can be controlled using the arrow keys, the other using the WASD keyset. It only blits one sprite on the image, which can be controlled using WASD. The other can be controlled by arrow keys if player2.update1(keys) is commented. Please don't beat down on me that much, still kind of a novice.
The problem is that you fill the whole screen with black before you draw each player. That means that when player two is drawn player one gets drawn over with black. Remove line 52 surf.fill(black) from def draw() and add it to the main game loop so that it is only called once.
def main():
while True:
surf.fill(black)
This question already has answers here:
Image rotation while moving
(2 answers)
Move Character with Vector
(2 answers)
Closed 2 years ago.
I made a program where an object will rotate towards your mouse on the screen. now I need to make it so that the object will rotate towards another moving object. here is my code:
import pygame
import math
import sys
from pygame.locals import *;
from sys import exit
pygame.init()
blk = pygame.Color(0,0,0)
BG = ('BG.png')
pygame.init()
screen = pygame.display.set_mode((800, 600))
B_G = pygame.image.load(BG).convert_alpha()
clock = pygame.time.Clock()
pygame.mouse.set_visible(False)
fpsclock = pygame.time.Clock()
class Shork(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load('SHORK.png')
screen = pygame.display.get_surface()
self.x = 62
self.y = 50
self.direction = "down"
def Moving(self):
if self.direction == "right":
self.x += 2
elif self.direction == "left":
self.x -= 2
elif self.direction == "down":
self.y += 2
elif self.direction == "up":
self.y -= 2
def Path(self):
if self.x == 62 and self.y == 538:
self.direction = "right"
if self.x == 246 and self.y == 538:
self.direction = "up"
if self.x == 246 and self.y == 366:
self.direction = "left"
if self.x == 176 and self.y == 366:
self.direction = "up"
if self.x == 176 and self.y == 114:
self.direction = "right"
if self.x == 530 and self.y == 114:
self.direction = "down"
if self.x == 530 and self.y == 366:
self.direction = "left"
if self.x == 460 and self.y == 366:
self.direction = "down"
if self.x == 460 and self.y == 538:
self.direction = "right"
if self.x == 644 and self.y == 538:
self.direction = "up"
if self.y == 0:
sys.exit()
Shork = Shork()
Run = True
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == MOUSEBUTTONDOWN and event.button == 1:
print("test1")
elif event.type == MOUSEBUTTONDOWN and event.button == 3:
print("test3")
while Run:
fpsclock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
Run = False
pos = pygame.mouse.get_pos()
angle = 360-math.atan2(pos[1]-300,pos[0]-400)*180/math.pi
rotimage = pygame.transform.rotate(B_G,angle)
Shork.Moving()
Shork.Path()
screen.blit(Shork.image, (Shork.x, Shork.y))
pygame.display.update()
rect = rotimage.get_rect(center=(400,300))
screen.blit(rotimage,rect)
pygame.display.update()
screen.fill(blk)
BG is the object that I need to rotate and SHORK is the object that BG needs to rotate towards.
The middle portion of the code is just pathing for an object to follow.
The code that I am struggling with is this:
pos = pygame.mouse.get_pos()
angle = 360-math.atan2(pos[1]-300,pos[0]-400)*180/math.pi
rotimage = pygame.transform.rotate(B_G,angle)
Shork.Moving()
Shork.Path()
screen.blit(Shork.image, (Shork.x, Shork.y))
pygame.display.update()
rect = rotimage.get_rect(center=(400,300))
screen.blit(rotimage,rect)
pygame.display.update()
This currently works for following the mouse but I cannot for the life of me figure out how to make BG rotate towards SHORK.
P.S. I am just starting to learn python so please try to be patient. :)
You need to change angle to use Shork's x/y value instead of pos. You should also probably update Shork's values before calculating the angle, so I moved Shork.Moving and Shork.Path to the beginning of the block.
Shork.Moving()
Shork.Path()
pos = pygame.mouse.get_pos()
angle = 360-math.atan2(Shork.y-300,Shork.x-400)*180/math.pi
rotimage = pygame.transform.rotate(B_G,angle)
screen.blit(Shork.image, (Shork.x, Shork.y))
pygame.display.update()
rect = rotimage.get_rect(center=(400,300))
screen.blit(rotimage,rect)
pygame.display.update()
If this may help you here is a repo of a complete game with several levels which I wrote some years ago while learning Python and Pygame. It has rotating spaceships rotating to any angle, enemy ships that turn and follow you, enemy ships that turn and flee when shot at (artificial intelligence), ateroids etc.
Space Gladiator - The Spiritual Warrior
I recommend to use vectors.
# To get the distance to the mouse just subtract the position vector
# of the sprite from the mouse position.
x, y = pg.mouse.get_pos() - self.pos
self.angle = math.degrees(math.atan2(y, x))
# Rotate the image (keep a copy of the original image around).
self.image = pg.transform.rotozoom(self.orig_image, -self.angle, 1)
self.rect = self.image.get_rect(center=self.rect.center)
You can also get the angle of a pygame.math.Vector2 by calling its as_polar method which returns the polar coordinates.
distance = pg.mouse.get_pos() - self.pos
radius, self.angle = distance.as_polar()
Here's a minimal working example with a moving sprite that rotates toward the mouse (move left and right with 'a' and 'd').
import sys
import math
import pygame as pg
from pygame.math import Vector2
pg.init()
BLUEGREEN = pg.Color(0, 90, 100)
GREEN = pg.Color('springgreen1')
class Player(pg.sprite.Sprite):
def __init__(self, x, y, *spritegroups):
super().__init__(spritegroups)
self.image = pg.Surface((50, 30), pg.SRCALPHA)
pg.draw.polygon(self.image, GREEN, ((1, 1), (49, 14), (1, 29)))
self.orig_image = self.image
self.rect = self.image.get_rect(center=(x, y))
self.pos = Vector2(x, y)
self.vel = Vector2(0, 0)
self.angle = 0
def handle_event(self, event):
if event.type == pg.KEYDOWN:
if event.key == pg.K_a:
self.vel.x = -3.5
elif event.key == pg.K_d:
self.vel.x = 3.5
if event.type == pg.KEYUP:
if event.key == pg.K_a and self.vel.x < 0:
self.vel.x = 0
elif event.key == pg.K_d and self.vel.x > 0:
self.vel.x = 0
def update(self):
# Update the position vector by adding the velocity vector.
self.pos += self.vel
self.rect.center = self.pos
# Get the distance and angle to the target.
x, y = pg.mouse.get_pos() - self.pos
self.angle = math.degrees(math.atan2(y, x))
# Rotate the image (rotozoom looks better than transform.rotate).
self.image = pg.transform.rotozoom(self.orig_image, -self.angle, 1)
self.rect = self.image.get_rect(center=self.rect.center)
def main():
screen = pg.display.set_mode((640, 480))
pg.display.set_caption('Rotation')
clock = pg.time.Clock()
sprite_group = pg.sprite.Group()
player = Player(200, 300, sprite_group)
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
player.handle_event(event)
sprite_group.update()
screen.fill(BLUEGREEN)
sprite_group.draw(screen)
pg.display.flip()
clock.tick(30)
if __name__ == '__main__':
main()
pg.quit()
sys.exit()
I am trying to make a alternate way to create "gravity" with python 2.7. I need the game to move the x position of the ball 25 pixels to the right AND the y position of the ball 25 pixels up. So here a piece of my current program:
def jump(self):
false = 0
global false
while self.rect.top < 750 and false == 0:
self.rect.top += 50
self.rect.left += 50
while self.rect.top <= 750:
false = 1
self.rect.top -= 50
self.rect.left += 50
First, how do I make the program do the lines 5 and 6/ 9 and 10 at the same time? My next question will need this source code:
import pygame, sys
import time
pygame.init()
screen = pygame.display.set_mode([1500,750])
background = pygame.Surface(screen.get_size())
background.fill([255, 255, 255])
class Attacker(pygame.sprite.Sprite):
def __init__(self, image_file, location):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(image_file)
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = location
def jump(self):
false = 0
global false
while self.rect.top < 750 and false == 0:
self.rect.top += 50
self.rect.left += 50
while self.rect.top <= 750:
false = 1
self.rect.top -= 50
self.rect.left += 50
my_ball = Attacker('wackyball.bmp', [300, 300])
running = True
while running:
screen.fill([255, 255, 255])
screen.blit(my_ball.image, my_ball.rect)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
my_ball.rect.top = my_ball.rect.top - 200
elif event.key == pygame.K_DOWN:
my_ball.rect.top = my_ball.rect.top + 125
elif event.key == pygame.K_RIGHT:
my_ball.rect.left += 175
elif event.key == pygame.K_LEFT:
my_ball.rect.left -= 125
elif event.key == pygame.K_SPACE:
my_ball.jump()
screen.blit(background, (0, 0))
screen.blit(my_ball.image, my_ball.rect)
pygame.display.flip()
pygame.quit()
When ever I press the spacebar so my guy will "jump" (do the jump function), my game crashes. Why does this happen?
Your game is crashing because it's getting inside the while loop and not returning.(inside the second while loop)
If you want to simulate gravity, you need to move the char a little bit every frame, the way you are doing you will move it all the way up, then all the way down in a single frame, meaning it won't appear to move.
Here's some ideas that might help you.
import pygame, sys
import time
pygame.init()
screen = pygame.display.set_mode([1500,750])
background = pygame.Surface(screen.get_size())
background.fill([255, 255, 255])
class Attacker(pygame.sprite.Sprite):
def __init__(self, image_file, location):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(image_file)
self.rect = self.image.get_rect()
self.x_pos, self.y_pos = location
self.rect.x, self.rect.y = location
self.jumping = False
self.falling = False
self.direction = 1
def jump(self):
if self.y_pos > CEILING:
self.x_pos += 1*self.direction
self.y_pos -= 5
else:
self.jumping = False
self.falling = True
self.update_pos()
def fall(self):
if self.y_pos < FLOOR:
self.x_pos += 1*self.direction
self.y_pos += 5
else:
self.falling = False
self.update_pos()
def update_pos(self):
self.rect.x = self.x_pos
self.rect.y = self.y_pos
FLOOR = 700
CEILING = 300
my_ball = Attacker('wackyball.bmp',[300, FLOOR])
running = True
while running:
if my_ball.jumping:
my_ball.jump()
if my_ball.falling:
my_ball.fall()
screen.blit(my_ball.image, my_ball.rect)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
my_ball.y_pos -= 5
elif event.key == pygame.K_DOWN:
my_ball.y_pos += 5
elif event.key == pygame.K_RIGHT:
my_ball.direction = 1
my_ball.x_pos += 5
elif event.key == pygame.K_LEFT:
my_ball.direction = -1
my_ball.x_pos -= 5
elif event.key == pygame.K_SPACE:
if not my_ball.falling:
my_ball.jumping = True
my_ball.update_pos()
screen.blit(background, (0, 0))
screen.blit(my_ball.image, my_ball.rect)
pygame.display.flip()
pygame.quit()
I need to make the balls in this code move around randomly. I am not sure what I am doing wrong. I am new to programming and this may be badly coded so any help would be appreciated. Right now the code makes a character in the middle of the screen that you can move up or down and it makes one ball in the top left corner of the screen that does not move. I want multiple balls on the screen and eventually I want the balls to be moving around randomly and if they collide with the character you lose this simple game.
from pygame import *
import random
class Ball(sprite.Sprite):
def __init__(self, numballs, balls = []):
sprite.Sprite.__init__(self)
self.image = image.load('ball.png')
self.rect = self.image.get_rect()
self.numballs = numballs
self.balls = balls
def multipleBalls(self):
for count in range(self.numballs):
self.balls.append(dict)
self.balls[count] = {'x': 0, 'y': 0, 'xmove': random.randint(1,2), 'ymove':random.randint(1,2)}
def ballMove(self):
for count in range(self.numballs):
self.balls[count]['x'] = self.balls[count]['x'] + self.balls[count]['xmove']
self.balls[count]['y'] = self.balls[count]['y'] + self.balls[count]['ymove']
def ballsOnScreen(self):
for count in range(self.numballs):
self.screen.blit(self.image, (self.balls[count]['x'], self.balls[count]['y']))
def ballBarrier(self):
for count in range(self.numballs):
if self.balls[count]['x'] > 620:
self.balls[count]['xmove'] = random.randint(-2, 0)
if self.balls[count]['x'] < -10:
self.balls[count]['xmove'] = random.randint(0, 2)
if self.balls[count]['y'] > 470:
self.balls[count]['ymove'] = random.randint(-2, 0)
if self.balls[count]['y'] < -10:
self.balls[count]['ymove'] = random.randint(0, 2)
def manageBall(self):
self.multipleBalls()
self.ballsOnScreen()
self.ballMove()
self.ballBarrier()
class Character(sprite.Sprite):
def __init__(self, xy):
sprite.Sprite.__init__(self)
self.image = image.load('character.png')
self.rect = self.image.get_rect()
self.rect.centerx, self.rect.centery = xy
self.movementspeed = 1
self.velocity = 0
def down(self):
self.velocity += self.movementspeed
def up(self):
self.velocity -= self.movementspeed
def characterMove(self, dy):
if self.rect.bottom + dy > 480:
self.rect.bottom = 480
elif self.rect.top + dy < 0:
self.rect.top = 0
else:
self.rect.y += dy
def update(self):
self.characterMove(self.velocity)
class Game(object):
def __init__(self):
init()
key.set_repeat(1, 30)
self.screen = display.set_mode((640, 480))
self.clock = time.Clock()
display.set_caption('Game')
event.set_allowed([QUIT, KEYDOWN, KEYUP])
self.background = Surface((640, 480))
self.background.fill((0,0,0))
self.screen.blit(self.background, (0,0))
display.flip()
self.sprites = sprite.RenderUpdates()
self.character = Character((320, 240))
self.sprites.add(self.character)
self.ball = Ball(5)
self.sprites.add(self.ball)
def run(self):
running = True
while running == True:
self.clock.tick(60)
running = self.handleEvents()
display.set_caption('game %d fps' % self.clock.get_fps())
for sprite in self.sprites:
sprite.update()
self.sprites.clear(self.screen, self.background)
dirty = self.sprites.draw(self.screen)
display.update(dirty)
self.ball.manageBall()
def handleEvents(self):
for e in event.get():
if e.type == QUIT:
return False
elif e.type == KEYDOWN:
if e.key == K_ESCAPE:
return False
if e.key == K_UP:
self.character.up()
if e.key == K_DOWN:
self.character.down()
return True
def main():
game = Game()
game.run()
main()
I've never used the Sprite class before so this was a good exercise. :)
I fixed your code, just change the image paths back to your icon locations and you should be good to go. The print statements might need reformatting if you're running an older version of Python.
I take out the forced call to the Sprite init method in the Ball and Character classes, it won't let me add them to the game.sprites render group. Not sure why.
I'm running Python 3.2.2 and Pygame 1.9.2pre so YMMV. :)
Controls:
UP / DOWN = Move your dude.
R = add a new, random ball.
from pygame import *
import random
SCREEN_WIDTH = 640
SCREEN_HEIGHT = 480
FPS = 60
class Ball(sprite.Sprite):
def __init__(self, xy = (0,0), xm = 0, ym = 0):
sprite.Sprite.__init__(self)
self.img_load('evil_balloon_32x32.png')
self.rect.centerx, self.rect.centery = xy
self.xmove = xm
self.ymove = ym
def update(self):
self.move()
self.ballBarrier()
def move(self):
self.rect.x += self.xmove
self.rect.y += self.ymove
def img_load(self, filename):
self.image = image.load(filename)
self.rect = self.image.get_rect()
def ballBarrier(self):
"""
Checks to make sure ball is within bounds, adjusts movement speed if it's not
"""
if self.rect.right > SCREEN_WIDTH:
self.xmove = random.randint(-2, 0)
if self.rect.left < 0:
self.xmove = random.randint(0, 2)
if self.rect.bottom > SCREEN_HEIGHT:
self.ymove = random.randint(-2, 0)
if self.rect.top < 0:
self.ymove = random.randint(0, 2)
class ball_manager():
def __init__(self, numballs = 5, balls = []):
self.blist = balls
if numballs > 0:
self.multipleBalls(numballs) # moved this here so balls get init'd only once
def update(self):
"""
Update position of all balls
"""
for ball in self.blist:
self.ballMove(ball)
def add_ball(self, xy = (0,0), xm = 0, ym = 0):
self.blist.append(Ball(xy, xm, ym)) # appends a random ball
def multipleBalls(self, numballs):
for i in range(numballs):
self.add_ball((random.randint(0, SCREEN_WIDTH),
random.randint(0, SCREEN_HEIGHT)),
random.randint(-2,2),
random.randint(-2,2))
class Character(sprite.Sprite):
def __init__(self, xy):
sprite.Sprite.__init__(self)
self.img_load()
self.rect.centerx, self.rect.centery = xy
self.movementspeed = 1
self.velocity = 0
def down(self):
self.velocity += self.movementspeed
def up(self):
self.velocity -= self.movementspeed
def characterMove(self, dy):
if self.rect.bottom + dy > SCREEN_HEIGHT:
self.rect.bottom = SCREEN_HEIGHT
self.velocity = 0
elif self.rect.top + dy < 0:
self.rect.top = 0
self.velocity = 0
else:
self.rect.y += dy
def update(self):
self.characterMove(self.velocity)
def img_load(self):
self.image = image.load("scary_clown_32x32.png")
self.rect = self.image.get_rect()
class Game(object):
def __init__(self):
init()
key.set_repeat(1, 30)
self.screen = display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
self.clock = time.Clock()
display.set_caption('Game')
event.set_allowed([QUIT, KEYDOWN, KEYUP])
self.background = Surface((SCREEN_WIDTH, SCREEN_HEIGHT))
self.background.fill((0,0,0))
self.screen.blit(self.background, (0,0))
display.flip()
self.sprites = sprite.RenderUpdates()
self.character = Character((SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2))
self.sprites.add(self.character)
self.balls = ball_manager(5)
for ball in self.balls.blist:
self.sprites.add(ball)
def run(self):
running = True
while running == True:
self.clock.tick(FPS)
running = self.handleEvents()
display.set_caption('game %d fps' % self.clock.get_fps())
self.sprites.clear(self.screen, self.background)
for sprite in self.sprites:
sprite.update()
dirty = self.sprites.draw(self.screen)
display.update(dirty)
def handleEvents(self):
for e in event.get():
if e.type == QUIT:
return False
elif e.type == KEYDOWN:
if e.key == K_ESCAPE:
return False
if e.key == K_UP:
self.character.up()
if e.key == K_DOWN:
self.character.down()
if e.key == K_r:
self.sprites.add(Ball((random.randint(0, SCREEN_WIDTH),
random.randint(0, SCREEN_HEIGHT)),
random.randint(-2,2),
random.randint(-2,2)))
return True
def main():
game = Game()
game.run()
quit()
main()
sys.exit()