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
I want to fix the auto updating of the following code:
import pygame
import time
import random
pygame.init()
pygame.mixer.music.load('song.mp3')
pygame.mixer.music.play(0)
white = (255,255,255)
black = (0,0,0)
red = (255,0,0)
green = (0,155,0)
display_width = 800
display_height = 600
gameDisplay = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption('KALM Creation')
#Score
score=0
#img=pygame.image.load("1.png")
#intro=pygame.image.load("intro.png")
foodimg=pygame.image.load("food.png")
#Our Icon For The Game
icon=pygame.image.load('icon1.jpg')
pygame.display.set_icon(icon)
clock = pygame.time.Clock()
AppleThickness=30
block_size = 10
FPS = 30
smallfont = pygame.font.SysFont("comicsansms", 25)
medfont = pygame.font.SysFont("comicsansms", 50)
largefont = pygame.font.SysFont("comicsansms", 80)
#The score function
def scoredisplay(scoredef=0):
text=smallfont.render("Score :%s" %(scoredef) ,True ,black)
gameDisplay.blit(text,[0,0])
#The random function of apple
def randAppleGen():
randAppleX = round(random.randrange(0, display_width-AppleThickness))
randAppleY = round(random.randrange(0, display_height-AppleThickness))
return randAppleX,randAppleY
randAppleX,randAppleY=randAppleGen()
#Starting Of the game
def game_intro():
intro = True
while intro:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key ==pygame.K_c:
intro = False
if event.key ==pygame.K_q:
pygame.quit()
quit()
gameDisplay.fill(white)
message_to_screen("Welcome To Eat it Game",
green,
-200,
size="medium")
message_to_screen("This Game is created by KALM Creations",
black,
-30,
size="small")
message_to_screen("Eat the food to gain a score!",
black,
10,
size="small")
message_to_screen("Avoid the rock , if you hit them you lose!",
black,
50,
size="small")
message_to_screen("Press 'C' to play the game or 'Q' to quit.",
black,
150,
size="small")
pygame.display.update()
clock.tick(15)
#Snake aka the object which is moving (in green colour)
def snake(lead_x,lead_y,block_size):
pygame.draw.rect(gameDisplay, green, [lead_x,lead_y,block_size,block_size])
#Text Size
def text_objects(text,color, size):
if size=="small":
textSurface=smallfont.render(text, True ,color)
elif size=="medium":
textSurface=medfont.render(text, True ,color)
elif size=="large":
textSurface=largefont.render(text, True ,color)
return textSurface,textSurface.get_rect()
#Message to screen
def message_to_screen(msg,color,y_displace=0,size="small"):
textSurf,textRect=text_objects(msg,color,size)
textRect.center = (display_width / 2),(display_height / 2)+y_displace
gameDisplay.blit(textSurf,textRect)
# The game run up
def gameLoop():
score=0
gameExit = False
gameOver = False
lead_x = display_width/2
lead_y = display_height/2
lead_x_change = 0
lead_y_change = 0
randAppleX,randAppleY=randAppleGen()
while not gameExit:
while gameOver == True:
gameDisplay.fill(white)
message_to_screen("Game over",
red,
y_displace=-50,
size="large")
message_to_screen("Press C to play again or Q to quit",
black,
y_displace=50,
size="medium")
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
gameExit = True
gameOver = False
if event.key == pygame.K_c:
gameLoop()
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
lead_x_change = -block_size
lead_y_change = 0
elif event.key == pygame.K_RIGHT:
lead_x_change = block_size
lead_y_change = 0
elif event.key == pygame.K_UP:
lead_y_change = -block_size
lead_x_change = 0
elif event.key == pygame.K_DOWN:
lead_y_change = block_size
lead_x_change = 0
if lead_x >= display_width or lead_x < 0 or lead_y >= display_height or lead_y < 0:
gameOver = True
gameDisplay.blit(foodimg,(randAppleX,randAppleY))
lead_x += lead_x_change
lead_y += lead_y_change
gameDisplay.fill(white)
gameDisplay.blit(foodimg,(randAppleX,randAppleY))
snake(lead_x,lead_y,block_size)
scoredisplay()
pygame.display.update()
if lead_x > randAppleX and lead_x < randAppleY + AppleThickness or lead_x + block_size>randAppleX and lead_x + block_size< randAppleX + AppleThickness:
if lead_y > randAppleY and lead_y< randAppleY + AppleThickness or lead_y + block_size>randAppleY and lead_y + block_size< randAppleY + AppleThickness:
randAppleX,randAppleY=randAppleGen()
score+=1
scoredisplay(score)
elif lead_y +block_size >randAppleY and lead_y +block_size < randAppleY:
randAppleX,randAppleY=randAppleGen()
score+=1
scoredisplay(score)
'''
Now when i run this game , the score keeps on updating.I want it to do like when the snake collides with 'foodimg',
it should add +1 to the score.Also sometimes even if the snake does not touch the food , the food is moved to a random
position.How do i fix this bug?
'''
scoredisplay(score)
pygame.display.update()
clock.tick(FPS)
pygame.quit()
quit()
game_intro()
gameLoop()
#Episode 36
In this the score is always under updation , i want to fix this also that when the snake doesn't collide with the food, the food sometimes move to a random position.How do i fix these two errors?Here is the 2 images used in the code.
icon1
Food
You were calling scoredisplay() without an input at one point and calling it unnecessarily in other places. Below is amended code:
import pygame
import time
import random
pygame.init()
pygame.mixer.music.load('song.mp3')
pygame.mixer.music.play(0)
white = (255,255,255)
black = (0,0,0)
red = (255,0,0)
green = (0,155,0)
display_width = 800
display_height = 600
gameDisplay = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption('KALM Creation')
#Score
score=0
#img=pygame.image.load("1.png")
#intro=pygame.image.load("intro.png")
foodimg=pygame.image.load("food.png")
#Our Icon For The Game
icon=pygame.image.load('icon1.jpg')
pygame.display.set_icon(icon)
clock = pygame.time.Clock()
AppleThickness=30
block_size = 10
FPS = 30
smallfont = pygame.font.SysFont("comicsansms", 25)
medfont = pygame.font.SysFont("comicsansms", 50)
largefont = pygame.font.SysFont("comicsansms", 80)
#The score function
def scoredisplay(scoredef=0):
text=smallfont.render("Score :%s" %(scoredef) ,True ,black)
gameDisplay.blit(text,[0,0])
#The random function of apple
def randAppleGen():
randAppleX = round(random.randrange(0, display_width-AppleThickness))
randAppleY = round(random.randrange(0, display_height-AppleThickness))
return randAppleX,randAppleY
randAppleX,randAppleY=randAppleGen()
#Starting Of the game
def game_intro():
intro = True
while intro:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key ==pygame.K_c:
intro = False
if event.key ==pygame.K_q:
pygame.quit()
quit()
gameDisplay.fill(white)
message_to_screen("Welcome To Eat it Game",
green,
-200,
size="medium")
message_to_screen("This Game is created by KALM Creations",
black,
-30,
size="small")
message_to_screen("Eat the food to gain a score!",
black,
10,
size="small")
message_to_screen("Avoid the rock , if you hit them you lose!",
black,
50,
size="small")
message_to_screen("Press 'C' to play the game or 'Q' to quit.",
black,
150,
size="small")
pygame.display.update()
clock.tick(15)
#Snake aka the object which is moving (in green colour)
def snake(lead_x,lead_y,block_size):
pygame.draw.rect(gameDisplay, green, [lead_x,lead_y,block_size,block_size])
#Text Size
def text_objects(text,color, size):
if size=="small":
textSurface=smallfont.render(text, True ,color)
elif size=="medium":
textSurface=medfont.render(text, True ,color)
elif size=="large":
textSurface=largefont.render(text, True ,color)
return textSurface,textSurface.get_rect()
#Message to screen
def message_to_screen(msg,color,y_displace=0,size="small"):
textSurf,textRect=text_objects(msg,color,size)
textRect.center = (display_width / 2),(display_height / 2)+y_displace
gameDisplay.blit(textSurf,textRect)
# The game run up
def gameLoop():
score=0
gameExit = False
gameOver = False
lead_x = display_width/2
lead_y = display_height/2
lead_x_change = 0
lead_y_change = 0
randAppleX,randAppleY=randAppleGen()
while not gameExit:
while gameOver == True:
gameDisplay.fill(white)
message_to_screen("Game over",
red,
y_displace=-50,
size="large")
message_to_screen("Press C to play again or Q to quit",
black,
y_displace=50,
size="medium")
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
gameExit = True
gameOver = False
if event.key == pygame.K_c:
gameLoop()
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
lead_x_change = -block_size
lead_y_change = 0
elif event.key == pygame.K_RIGHT:
lead_x_change = block_size
lead_y_change = 0
elif event.key == pygame.K_UP:
lead_y_change = -block_size
lead_x_change = 0
elif event.key == pygame.K_DOWN:
lead_y_change = block_size
lead_x_change = 0
if lead_x >= display_width or lead_x < 0 or lead_y >= display_height or lead_y < 0:
gameOver = True
gameDisplay.blit(foodimg,(randAppleX,randAppleY))
lead_x += lead_x_change
lead_y += lead_y_change
gameDisplay.fill(white)
gameDisplay.blit(foodimg,(randAppleX,randAppleY))
snake(lead_x,lead_y,block_size)
pygame.display.update()
if lead_x > randAppleX and lead_x < randAppleY + AppleThickness or lead_x + block_size>randAppleX and lead_x + block_size< randAppleX + AppleThickness:
if lead_y > randAppleY and lead_y< randAppleY + AppleThickness or lead_y + block_size>randAppleY and lead_y + block_size< randAppleY + AppleThickness:
randAppleX,randAppleY=randAppleGen()
score+=1
elif lead_y +block_size >randAppleY and lead_y +block_size < randAppleY:
randAppleX,randAppleY=randAppleGen()
score+=1
scoredisplay(score)
pygame.display.update()
clock.tick(FPS)
pygame.quit()
quit()
game_intro()
gameLoop()
#Episode 36
If you want to move the target if not collected, set up a timer that counts up every tick. If the counter goes above a certain number then move the target, if the player collects the target in time reset the counter.
Hope this helps :)
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()
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()