I want the obstacle sprite, which are asteroids, to fall from the top of the screen to the bottom. I havent added any code to mess with the collisions of the asteroids, gravity, etc. because I can't even get the sprite to appear on the screen. Here is my code below (I tried using sprite classes but for me personally it made it a lot more confusing and difficult, so I chose not to.)
from sys import exit
from random import randint
def animation_state():
global player_surface, player_index, player_rect
player_index += 0.15
if player_index >= len(player_right_walk):
player_index = 0
if LEFT == True:
player_surface = player_left_walk[int(player_index)]
elif RIGHT == True:
player_surface = player_right_walk[int(player_index)]
if LEFT == False and RIGHT == False:
player_surface = pygame.image.load('graphics/dino_idle_right.png').convert_alpha()
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
player_surface = pygame.image.load('graphics/dino_idle_left.png').convert_alpha()
elif event.key == pygame.K_RIGHT:
player_surface = pygame.image.load('graphics/dino_idle_right.png').convert_alpha()
screen.blit(player_surface,player_rect)
def player_control():
global LEFT, RIGHT
player_velocity = 0
player_gravity = 0
player_gravity += 3
player_rect.y += player_gravity
if player_rect.bottom >= 500:
player_rect.bottom = 500
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
player_velocity -= 6
LEFT = True
RIGHT = False
if player_rect.x < -50:
player_rect.x = 800
elif keys[pygame.K_RIGHT]:
player_velocity += 6
LEFT = False
RIGHT = True
if player_rect.x > 800:
player_rect.x = -50
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or pygame.K_RIGHT:
player_velocity = 0
player_rect.x += player_velocity
def display_score():
current_time = int(pygame.time.get_ticks() / 1000) - start_time
score_surface = font.render('Score: ' + str(current_time),False,(64,64,64))
score_rect = score_surface.get_rect(center = (375, 30))
screen.blit(score_surface, score_rect)
return current_time
def game_over_screen():
player_stand = pygame.image.load('graphics/dino_stand.png').convert_alpha()
player_stand = pygame.transform.rotozoom(player_stand,0,4).convert_alpha()
player_stand_rect = player_stand.get_rect(center = (375,280))
game_name = font.render('Personal Project Game', False, (111,196,169))
game_name_rect = game_name.get_rect(center = (375,100))
game_message = font.render('Press Space to start',False, 'Black')
game_message_rect = game_message.get_rect(center = (375, 500))
screen.blit(background_surface,(0,0))
screen.blit(player_stand,player_stand_rect)
screen.blit(game_name,game_name_rect)
screen.blit(game_message,game_message_rect)
def asteroid_animation_state():
global asteroid_surface, asteroid_index, asteroid_rect
asteroid_1 = pygame.image.load('graphics/asteroid_1.png').convert_alpha()
asteroid_1 = pygame.transform.rotozoom(asteroid_1,-45,0)
asteroid_2 = pygame.image.load('graphics/asteroid_2.png').convert_alpha()
asteroid_2 = pygame.transform.rotozoom(asteroid_2,-45,0)
asteroid_frames = [asteroid_1,asteroid_2]
asteroid_index = 0
asteroid_surface = asteroid_frames[asteroid_index]
asteroid_rect = asteroid_surface.get_rect(midtop = (randint(0,751),-20))
asteroid_index += 0.1
if asteroid_index >= len(asteroid_frames):
asteroid_index = 0
asteroid_surface = asteroid_frames[int(asteroid_index)]
asteroid_rect.bottom += 10
if asteroid_rect.bottom >=600:
asteroid_rect.bottom = -20
screen.blit(asteroid_surface,asteroid_rect)
pygame.init()
pygame.display.set_caption('Escape Extinction')
screen = pygame.display.set_mode((750,563))
clock = pygame.time.Clock()
LEFT = False
RIGHT = False
start_time = 0
score = 0
font = pygame.font.Font('fonts/atari-font-full-version/atari_full.ttf', 25)
player_right_1 = pygame.image.load('graphics/dino_1_right.png').convert_alpha()
player_right_2 = pygame.image.load('graphics/dino_2_right.png').convert_alpha()
player_right_3 = pygame.image.load('graphics/dino_3_right.png').convert_alpha()
player_right_4 = pygame.image.load('graphics/dino_4_right.png').convert_alpha()
player_left_1 = pygame.image.load('graphics/dino_1_left.png').convert_alpha()
player_left_2 = pygame.image.load('graphics/dino_2_left.png').convert_alpha()
player_left_3 = pygame.image.load('graphics/dino_3_left.png').convert_alpha()
player_left_4 = pygame.image.load('graphics/dino_4_left.png').convert_alpha()
player_right_walk = [player_right_1,player_right_2,player_right_3,player_right_4]
player_left_walk = [player_left_1,player_left_2,player_left_3,player_left_4]
player_index = 0
#player_surface_right = player_right_walk[player_index]
#player_surface_left = player_left_walk[player_index]
player_surface = player_right_walk[player_index]
player_rect = player_surface.get_rect(midbottom = (375,300))
background_surface = pygame.image.load('graphics/jumperbackground.png').convert()
ground_surface = pygame.image.load('graphics/grass.png').convert()
#obstacle_timer = pygame.USEREVENT + 1
#pygame.time.set_timer(obstacle_timer,1400)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
#if event.type == obstacle_timer:
# obstacle.add(Asteroid('asteroid'))
screen.blit(background_surface,(0,0))
screen.blit(ground_surface,(0,480))
player_control()
animation_state()
display_score()
asteroid_animation_state()
pygame.display.update()
clock.tick(60)
Reading the documentation on the pygame.transform.rotozoom() function :
rotozoom(surface, angle, scale) -> Surface
This is a combined scale and rotation transform. The resulting Surface will be a filtered 32-bit Surface. The scale argument is a floating point value that will be multiplied by the current resolution. The angle argument is a floating point value that represents the counterclockwise degrees to rotate. A negative rotation angle will rotate clockwise.
So your image loading code is scaling the images by a factor of 0. So the resultant surface would have a zero size.
Probably you meant this to be 1.0, which would leave them the original size.
asteroid_1 = pygame.image.load('graphics/asteroid_1.png').convert_alpha()
asteroid_1 = pygame.transform.rotozoom( asteroid_1, -45, 1.0 )
asteroid_2 = pygame.image.load('graphics/asteroid_2.png').convert_alpha()
asteroid_2 = pygame.transform.rotozoom( asteroid_2, -45, 1.0 )
Related
im building a game in pygame in which a hot air balloon is constantly going up and spikes are coming down and hot air balloon has to dodge them. However i dont know how to randomly generate nicely spaced spikes which constantly moving downwards im having issue with randomly generating downward moving spikes.
here is the code:
import pygame
import random
import math
pygame.init()
clock = pygame.time.Clock()
screenwid = 400
screenhigh = 500
screen = pygame.display.set_mode((screenwid, screenhigh))
grey = (240,240,240)
black = (0,0,0)
initvel = 3
player_x = 100
player_y = 250
spikex= -100
spikey = -100
xchange = 0
ychange = 0
baloon = pygame.image.load('C:/Users/aliab/Downloads/hotair balloom.png')
baloon = pygame.transform.scale(baloon,(300, 300))
spike = pygame.image.load('C:/Users/aliab/Downloads/spikes.png')
spike = pygame.transform.scale(spike,(300, 300))
bg = pygame.image.load('E:/bgparacute.jpg')
def balloon(x,y):
screen.blit(baloon,(x,y ))
def spikee(x,y):
screen.blit(spike,(x,y ))
y = 0
run = True
while run:
rel_y = y % bg.get_rect().height
screen.blit(bg,(0,rel_y - bg.get_rect().height))
if rel_y < screenhigh:
screen.blit(bg, (0, rel_y))
y +=1
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
xchange = -initvel
ychange = 0
if event.key == pygame.K_RIGHT:
xchange = initvel
ychange = 0
if event.key == pygame.K_UP:
ychange = -initvel
xchange = 0
if event.key == pygame.K_DOWN:
ychange = initvel
xchange = 0
if spikey == 100:
print('hihiohug')
spikex = random.randint(0, 400)
spikey = random.randint(-20, 10)
spikey += 2
player_x += xchange
player_y += ychange
balloon(player_x,player_y)
spikee(spikex, spikey)
clock.tick(60)
pygame.display.update()
pygame.quit()
I tried out your program. If you are looking to only have a few spikes on your screen, theoretically, you could just individually define the spikes and then randomly generate their starting position as in your code with some simple tweaks.
import pygame
import random
import math
pygame.init()
clock = pygame.time.Clock()
screenwid = 400
screenhigh = 500
screen = pygame.display.set_mode((screenwid, screenhigh))
grey = (240,240,240)
black = (0,0,0)
initvel = 2
player_x = 100
player_y = 250
spikex1 = -100
spikey1 = -100
spikex2 = -40
spikey2 = -100
xchange = 0
ychange = 0
baloon = pygame.image.load('Balloon.png')
baloon = pygame.transform.scale(baloon,(240, 240))
spike1 = pygame.image.load('Mine.png') # Multiple spike definitions (very simplistic)
spike1 = pygame.transform.scale(spike1,(30, 30))
spike2 = pygame.image.load('Mine.png')
spike2 = pygame.transform.scale(spike2,(30, 30))
bg = pygame.image.load('background-day.png')
def balloon(x,y):
screen.blit(baloon,(x,y ))
def spikee(x,y):
screen.blit(spike1,(x,y ))
screen.blit(spike2,(x,y ))
y = 0
run = True
while run:
rel_y = y % bg.get_rect().height
screen.blit(bg,(0,rel_y - bg.get_rect().height))
if rel_y < screenhigh:
screen.blit(bg, (0, rel_y))
y +=1
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
xchange = -initvel
ychange = 0
if event.key == pygame.K_RIGHT:
xchange = initvel
ychange = 0
if event.key == pygame.K_UP:
ychange = -initvel
xchange = 0
if event.key == pygame.K_DOWN:
ychange = initvel
xchange = 0
if event.type == pygame.KEYUP: # Allow for a little more control of the balloon
xchange = 0
ychange = 0
if spikey1 == 280:
print('hihiohug')
spikex1 = random.randint(0, 300)
spikey1 = random.randint(-100, 10) # Adjust the random start above the screen for the spike
if spikey2 == 280:
print('hihiohug')
spikex2 = random.randint(0, 300)
spikey2 = random.randint(-100, 10) # Adjust the random start above the screen for the spike
spikey1 += 1
spikey2 += 1
player_x += xchange
player_y += ychange
balloon(player_x,player_y)
spikee(spikex1, spikey1)
spikee(spikex2, spikey2)
clock.tick(60)
pygame.display.update()
pygame.quit()
This produced randomly generated spikes (mines in my test).
However, you might want to define an array of spikes that are randomly placed just off of the display. As an example of that, I am including a link to GitHub for you to pull down a simple game I call "Submarine".
Submarine Game
It is an arcade like game where the submarine tries to avoid hitting underwater mines. It effectively is running in a horizontal fashion as opposed to your vertical action, but the underlying premises are alike. It has an array set up for storing underwater mine images that then appear on the screen.
Give that a try and see if that moves you forward in your game.
EDIT: I've now flipped the sprite, but when the animation plays on the flipped sprite, it has a black background instead of blending in with the major background. Just updated my code to the current situation. (2/8/2021)
I'm trying to flip a sprite in pygame, for example, I don't want them running left but looking right, which is what is happening right now.
The part that is giving me issues is the second comment that says ISSUES.
Here is my code (spritesheet is a class that transforms the image into a surface):
import pygame
import os
import sys
import random
from pygame.locals import *
import spritesheet
import time
pygame.init()
clock = pygame.time.Clock()
FPS = 60
prev_time = time.time()
pygame.display.set_caption('Platformer')
BG_COLOR = (50, 50, 50)
BLACK = (0, 0, 0)
WIN_SIZE = [1920,1080]
WIN = pygame.display.set_mode((WIN_SIZE[0], WIN_SIZE[1]), 0, 32)
# CONFIGURING Animations
IDLE_INDEX = 0
RUN_INDEX = 0
moving_right = False
moving_left = False
lookingRight = True
speed = 4
animation_tick = 8
player_location = [50, 50]
player_y_momentum = 0
player_rect = pygame.Rect(player_location[0] + 155, player_location[1] + 140, 70, 133)
def retrieve_list(animType, image):
if animType == "idle":
IDLE_FRAMES = []
IDLE_STEPS = 9
sprite_sheet = spritesheet.SpriteSheet(image)
for step in range(IDLE_STEPS):
newFRAME = sprite_sheet.get_image(step, 120, 80, 3.5, BLACK)
IDLE_FRAMES.append(newFRAME)
return IDLE_FRAMES
if animType == "run":
RUN_FRAMES = []
RUN_STEPS = 9
sprite_sheet = spritesheet.SpriteSheet(image)
for step in range(RUN_STEPS):
newFRAME = sprite_sheet.get_image(step, 120, 80, 3.5, BLACK)
RUN_FRAMES.append(newFRAME)
return RUN_FRAMES
sprite_sheet_img_IDLE = pygame.image.load('Spritesheets/Outline/120x80_PNGSheets/_Idle.png')
sprite_sheet_img_RUN = pygame.image.load('Spritesheets/Outline/120x80_PNGSheets/_Run.png')
IDLE_FRAMES = retrieve_list("idle", sprite_sheet_img_IDLE)
RUN_FRAMES = retrieve_list("run", sprite_sheet_img_RUN)
currentANIMATION = "idle"
playingAnim = None
while True:
clock.tick(FPS)
now = time.time()
dt = now - prev_time
prev_time = now
WIN.fill(BG_COLOR)
if currentANIMATION == "idle":
if player_location[1] > WIN_SIZE[1] - IDLE_FRAMES[IDLE_INDEX].get_height():
player_y_momentum = -player_y_momentum
else:
player_y_momentum += 0.2
player_location[1] += player_y_momentum
elif currentANIMATION == "run":
if player_location[1] > WIN_SIZE[1] - RUN_FRAMES[RUN_INDEX].get_height():
player_y_momentum = -player_y_momentum
else:
player_y_momentum += 0.2
player_location[1] += player_y_momentum
if moving_right:
currentANIMATION = "run"
if not lookingRight:
lookingRight = True
WIN.fill(BG_COLOR)
playingAnim = WIN.blit(RUN_FRAMES[RUN_INDEX], (player_location[0], player_location[1]))
player_location[0] += speed
if moving_left:
currentANIMATION = "run"
if lookingRight:
lookingRight = False
leftFrame = pygame.transform.flip(RUN_FRAMES[RUN_INDEX], True, False)
WIN.fill(BG_COLOR)
playingAnim = WIN.blit(leftFrame, (player_location[0], player_location[1]))
player_location[0] -= speed
elif moving_right != True and moving_left != True:
currentANIMATION = "idle"
WIN.fill(BG_COLOR)
playingAnim = WIN.blit(IDLE_FRAMES[IDLE_INDEX], (player_location[0], player_location[1]))
player_rect.x = player_location[0] + 155
player_rect.y = player_location[1] + 140
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_RIGHT or event.key == ord('d'):
moving_right = True
if event.key == K_LEFT or event.key == ord('a'):
moving_left = True
if event.type == KEYUP:
if event.key == K_RIGHT or event.key == ord('d'):
moving_right = False
if event.key == K_LEFT or event.key == ord('a'):
moving_left = False
pygame.display.update()
if animation_tick == 8: # change 20 to how ever many ticks in between animation frames
if currentANIMATION == "idle":
if IDLE_INDEX < 8:
IDLE_INDEX += 1
else:
IDLE_INDEX = 0
if currentANIMATION == "run":
if RUN_INDEX < 8:
RUN_INDEX += 1
else:
RUN_INDEX = 0
animation_tick = 0 # reset tick back to 0 after changing frame
else:
animation_tick += 1 # add 1 each iteration of the while loop
Here are the spritesheets if you want to replicate my situation:
running spritesheet:
idle spritesheet:
I've tried flipping the original surface, but then the image gets messed up with black around it, and it doesn't play the animation.
pygame.transform.flip does not flip the image in place, but returns a new image that is flipped:
flipped_image = pygame.transform.flip(image, True, False)
Forgot to add .convert_alpha() when I was flipping the image. Apparently when the image is flipped it recreates the black rectangle.
After hours of searching, I still can't figure out why only the most recently spawned circle is affected by the collision detection. I commented out the code in question. I experimented with sprites and that may be the answer but I still got the same results.
import pygame,random
pygame.init()
width,height,radius = 1280,720,20
class Ball():
def __init__(self):
self.x = 0
self.y = 0
self.vx = 0
self.vy = 0
def make_ball():
ball = Ball()
ball.x = random.randrange(radius, width - radius)
ball.y = random.randrange(radius, 100)
ball.vx = random.randint(1,2)
ball.vy = 0
return ball
def main():
rect_x = 60
display = pygame.display.set_mode((width,height))
pygame.display.set_caption("BOUNCE")
running = True
ball_list = []
ball = make_ball()
ball_list.append(ball)
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
ball = make_ball()
ball_list.append(ball)
for ball in ball_list:
ball.x += ball.vx
ball.vy += 0.02
ball.y += ball.vy
if ball.y >= height - radius:
ball.vy *= -1
if ball.x >= width - radius or ball.x <= radius:
ball.vx *= -1
display.fill((0,0,0))
for ball in ball_list:
random_color = (random.randint(1,255),random.randint(1,255),random.randint(1,255))
circle = pygame.draw.circle(display,random_color,(int(ball.x), int(ball.y)),radius)
rectangle = pygame.draw.rect(display,(255,255,255),(int(rect_x),660,60,60))
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT and rect_x > 0:
rect_x -= 2
if event.key == pygame.K_RIGHT and rect_x < width - 60:
rect_x += 2
'''if pygame.Rect(circle).colliderect(rectangle) == True: ###THIS IS THE BAD CODE!
print('Your Score:',pygame.time.get_ticks())
running = False'''
text = pygame.font.Font(None,120).render(str(pygame.time.get_ticks()),True,(255,255,255))
display.blit(text,(50,50))
pygame.display.flip()
pygame.quit()
if __name__ == "__main__":
main()
Indentation and code organization is the key to this. the offending section is (comments removed):
for ball in ball_list:
random_color = (random.randint(1,255),random.randint(1,255),random.randint(1,255))
circle = pygame.draw.circle(display,random_color,(int(ball.x), int(ball.y)),radius)
rectangle = pygame.draw.rect(display,(255,255,255),(int(rect_x),660,60,60))
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT and rect_x > 0:
rect_x -= 2
if event.key == pygame.K_RIGHT and rect_x < width - 60:
rect_x += 2
if pygame.Rect(circle).colliderect(rectangle) == True:
print('Your Score:',pygame.time.get_ticks())
running = False
You had all the correct pieces, but the order in which you are doing them is off as well as the indentation:
for ball in ball_list:
random_color = (random.randint(1,255),random.randint(1,255),random.randint(1,255))
circle = pygame.draw.circle(display,random_color,(int(ball.x), int(ball.y)),radius)
rectangle = pygame.draw.rect(display,(255,255,255),(int(rect_x),660,60,60))
if pygame.Rect(circle).colliderect(rectangle):
print('Your Score:',pygame.time.get_ticks())
running = False
This will now run through every ball in the list and check each one for collision. notice the colliderect if statement is indented into the for loop. Also notice i removed the KEYDOWN check from in the middle of it all
Speaking of that I would recommend using:
pressed = pygame.key.get_pressed()
if pressed[pygame.K_LEFT] and rect_x > 0:
rect_x -= 2
if pressed[pygame.K_RIGHT] and rect_x < width - 60:
rect_x += 2
for ball in ball_list:
# for loop from above
instead of what you had. This works best for when you want to allow for holding a key down. pygame.key.get_pressed() gets the state of all the keys all the time, not just when an event happens
For my code, I would like the chickens (enemies) to move 4 different ways:
vertical, horizontal, diagonal and following the player (pig).
Each chicken should have its own movement and move independently. Only two chickens can go in diagonal.
I have only programmed their vertical and horizontal movements but there is a problem with them; sometimes, they all move horizontally, sometimes, vertically. Sometimes they don't move at all.
Here is my code:
def game_loop():
x_change = 0
y_change = 0
foodCounter = 0
Score = 0
list = ["Vertical","Vertical","Horizontal","Horizontal","Follow","Diagonal1","Diagonal2"]
baddies = []
item = 0
x = (display_width * 0.45)
y = (display_height * 0.8)
foodx = random.randrange(48, display_width - 48)
foody = random.randrange(54, display_height - 54)
gameExit = False
while not gameExit:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change = -8
if event.key == pygame.K_RIGHT:
x_change = 8
if event.key == pygame.K_UP:
y_change = -8
if event.key == pygame.K_DOWN:
y_change = 8
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_change = 0
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
y_change = 0
if x > 705:
x_change = 0
x = 705
if x < -10:
x_change = 0
x = -10
if y < -15:
y_change = 0
y = -15
if y > 505:
y_change = 0
y = 505
x += x_change
y += y_change
gameDisplay.fill(white)
gameDisplay.blit(background,(-50,-50))
food = pygame.Rect(foodx, foody,48 , 54)
if foodCounter == 0:
gameDisplay.blit(foodImage, food)
player = pygame.Rect(x, y,108,105)
if player.colliderect(food):
foodCounter += -1
Score += 1
foodx = random.randrange(48, display_width - 48)
foody = random.randrange(54, display_height - 54)
foodCounter += 1
item = random.randint(1, len(list))
print(item)
if item == 1 or item == 2:
newchicken = {'rect':pygame.Rect(random.randint(0,display_width-45),0,45,63),
'surface':pygame.transform.scale(enemyImage,(45,63)),
'vertical': "vertical",
'down': "down"
}
item = 0
baddies.append(newchicken)
if item == 3 or item == 4:
newchicken = {'rect':pygame.Rect(0,random.randint(0,display_height-45),45,63),
'surface': pygame.transform.scale(enemyImage, (45,63)),
'horizontal': "horizontal",
'right': "right"
}
item = 0
baddies.append(newchicken)
if item == 6:
newchicken = {'rect':pygame.Rect(200,0,45,63),
'surface':pygame.transform.scale(enemyImage,(45,63)),
'diagonal1': "diagonal1"
}
if "Diagonal1" in list:
list.remove("Diagonal1")
item = 0
baddies.append(newchicken)
if len(list) == 7:
if item == 7:
newchicken = {'rect':pygame.Rect(100,600,45,63),
'surface':pygame.transform.scale(enemyImage,(45,63)),
'diagonal2': "diagonal2"
}
if "Diagonal2" in list:
list.remove("Diagonal2")
item = 0
baddies.append(newchicken)
if len(list) == 6:
if item == 6:
newchicken = {'rect':pygame.Rect(100,600,45,63),
'surface':pygame.transform.scale(enemyImage,(45,63)),
'diagonal2': "diagonal2"
}
if "Diagonal2" in list:
list.remove("Diagonal2")
item = 0
baddies.append(newchicken)
gameDisplay.blit(pigImage, player)
for b in baddies:
gameDisplay.blit(b['surface'],b['rect'])
for b in baddies:
if "vertical" in newchicken:
if "down" in newchicken:
if not b['rect'].bottom >= 600:
b['rect'].move_ip(0, 2)
if b['rect'].bottom >= 600 :
del newchicken['down']
newchicken["up"] = "up"
if "up" in newchicken:
if not b['rect'].top <= 0:
b['rect'].move_ip(0,-2)
if b['rect'].top <= 0:
del newchicken ['up']
newchicken["down"] = "down"
if "horizontal" in newchicken:
print ("horizontal")
if "right" in newchicken:
if not b['rect'].right >= 800:
b['rect'].move_ip(2,0)
if b['rect'].right >= 800:
del newchicken['right']
newchicken['left'] = "left"
if "left" in newchicken:
if not b['rect'].left <= 0:
b['rect'].move_ip(-2,0)
if b['rect'].left <= 0:
del newchicken ['left']
newchicken['right'] = "right"
pygame.display.update()
clock.tick(60)
game_loop()
Your code does not work because you always check for keys in newchicken when you iterate over baddies, while I guess you should check b instead.
But what you should do instead is to change your code in a way that seperates the different logical concerns of your game. Also, just use a class instead of a dict to group data and behaviour that belongs together.
Let's think a bit:
We have some kind of entity that basically consists of three things: an image, a position, and a behavior. You already know this, because you created these dicts:
newchicken = {'rect':pygame.Rect(100,600,45,63),
'surface':pygame.transform.scale(enemyImage,(45,63)),
'diagonal2': "diagonal2"
}
Let's tweak this a bit and use a Sprite (really, read the docs), which already has these things (more or less). Our class class could look like this (and don't tell me you don't want to use classes. That's stupid IMHO since you already use dozens of classes):
class Animal(pg.sprite.Sprite):
def __init__(self, color, pos, logic, *groups):
super().__init__(*groups)
self.image = pg.surface.Surface((40, 40))
self.image.fill(color)
self.rect = self.image.get_rect(topleft=pos)
self.logic = logic
self.direction = pg.Vector2((0, 0))
def update(self):
self.logic(self)
So, we have an image (which is just a plain rect so we have a working game at the end that everybody can copy/paste and run), a rect that stores the position, a mysterious logic argument that's a function (the "AI" of our animal) which will be called every tick, and a direction, which defines in which direction out animal will walk.
So, let's create the actual logic that will move out animals. We create three functions, one for vertical movement, one for horizontal movement, and one that will always walk towards the mouse cursor:
def move_vertical(animal):
if animal.direction.length() == 0:
animal.direction = pg.Vector2(5, 0)
animal.rect.move_ip(*animal.direction)
if not screen_rect.contains(animal.rect):
animal.direction *= -1
animal.rect.move_ip(animal.direction)
def move_horizontal(animal):
if animal.direction.length() == 0:
animal.direction = pg.Vector2(0, 5)
animal.rect.move_ip(*animal.direction)
if not screen_rect.contains(animal.rect):
animal.direction *= -1
animal.rect.move_ip(animal.direction)
def move_to_mouse(animal):
pos = pg.mouse.get_pos()
v = pg.Vector2(pos) - pg.Vector2(animal.rect.center)
if v.length() > 0:
v.normalize_ip()
v *= 5
animal.rect.move_ip(*v)
If we now want to create an Animal, we simply pass one of those functions to the constructor. No need for massive if/else blocks in your main loop (note how clean and simple it is in the end).
So, here's our final example. Note how we create four animals: two that move vertically, one that moves horizontally, and one that follows the mouse.
import pygame as pg
pg.init()
clock = pg.time.Clock()
running = True
screen = pg.display.set_mode((640, 480))
screen.fill((255, 255, 255))
screen_rect = screen.get_rect()
def move_vertical(animal):
if animal.direction.length() == 0:
animal.direction = pg.Vector2(5, 0)
animal.rect.move_ip(*animal.direction)
if not screen_rect.contains(animal.rect):
animal.direction *= -1
animal.rect.move_ip(animal.direction)
def move_horizontal(animal):
if animal.direction.length() == 0:
animal.direction = pg.Vector2(0, 5)
animal.rect.move_ip(*animal.direction)
if not screen_rect.contains(animal.rect):
animal.direction *= -1
animal.rect.move_ip(animal.direction)
def move_to_mouse(animal):
pos = pg.mouse.get_pos()
v = pg.Vector2(pos) - pg.Vector2(animal.rect.center)
if v.length() > 0:
v.normalize_ip()
v *= 5
animal.rect.move_ip(*v)
class Animal(pg.sprite.Sprite):
def __init__(self, color, pos, logic, *groups):
super().__init__(*groups)
self.image = pg.surface.Surface((40, 40))
self.image.fill(color)
self.rect = self.image.get_rect(topleft=pos)
self.logic = logic
self.direction = pg.Vector2((0, 0))
def update(self):
self.logic(self)
sprites = pg.sprite.Group()
Animal(pg.color.Color('yellow'), ( 10, 10), move_vertical, sprites)
Animal(pg.color.Color('red'), (200, 400), move_vertical, sprites)
Animal(pg.color.Color('orange'), (500, 100), move_horizontal, sprites)
Animal(pg.color.Color('brown'), (100, 200), move_to_mouse, sprites)
while running:
for e in pg.event.get():
if e.type == pg.QUIT:
running = False
sprites.update()
screen.fill((255, 255, 255))
sprites.draw(screen)
pg.display.update()
clock.tick(60)
Okay so I'm making a test for making a racing game...
And I want the car to move in the direction it's pointing.
Here is my code.
import pygame, sys
from pygame.locals import *
pygame.init()
mainClock = pygame.time.Clock()
degree = 0
WHITE = 250,250,250
rect2 = pygame.rect = (100,100,50,50)
WINDOWWIDTH = 1200
WINDOWHEIGHT = 750
thing = pygame.image.load('car.png')
screen = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT), 0, 32)
pygame.display.set_caption('Teh test')
left = False
right = False
while True:
rect2 = pygame.rect = (100,100,50,50)
if right == True:
degree -= 2
if left == True:
degree += 2
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == ord('a'):
left = True
if event.key == ord('d'):
right = True
if event.type == KEYUP:
if event.key == ord('a'):
left = False
if event.key == ord('d'):
right = False
pygame.draw.rect(screen,WHITE,rect2)
screen.fill((40, 40, 40))
thing2 = pygame.transform.rotate(thing,degree)
screen.blit(thing2,(100,100))
pygame.display.update()
mainClock.tick(60)
So like I said I want to know how to move the car in the direction it's pointing.
I tried to think of a way but I couldn't think of anything. So there isn't really anything to correct.
(If there are any questions I'll edit my question to answer it.) Please make sure you know pygame before answering.
You'll want to use trigonometry to calculate how much you want to move in the x and y directions, so that the car ends up moving in the correct direction. To calculate this, you can do this:
dx = math.cos(math.radians(degree))
dy = math.sin(math.radians(degree))
position = (position[0] + dx * SPEED, position[1] - dy * SPEED)
Note that you'll also need to initialize a position variable somewhere at the start of your code like this:
position = (100, 100)
Then, you have to change the blit line of code so you draw at the position variable, instead of at (100, 100) all of the time:
screen.blit(thing2, position)
Edit: Working example
import pygame, sys
from pygame.locals import *
import math
pygame.init()
mainClock = pygame.time.Clock()
degree = 0
WHITE = 250,250,250
rect2 = pygame.rect = (100,100,50,50)
WINDOWWIDTH = 1200
WINDOWHEIGHT = 750
thing = pygame.image.load('car.png')
screen = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT), 0, 32)
pygame.display.set_caption('Teh test')
left = False
right = False
position = (100, 100)
while True:
rect2 = pygame.rect = (100,100,50,50)
if right == True:
degree -= 2
if left == True:
degree += 2
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == ord('a'):
left = True
if event.key == ord('d'):
right = True
if event.type == KEYUP:
if event.key == ord('a'):
left = False
if event.key == ord('d'):
right = False
pygame.draw.rect(screen,WHITE,rect2)
screen.fill((40, 40, 40))
thing2 = pygame.transform.rotate(thing,degree)
dx = math.cos(math.radians(degree))
dy = math.sin(math.radians(degree))
position = (position[0] + dx, position[1] - dy)
screen.blit(thing2, position)
pygame.display.update()
mainClock.tick(60)
Working example to kabb answer
import pygame, sys
from pygame.locals import *
import math # math library
pygame.init()
mainClock = pygame.time.Clock()
degree = 0
WHITE = 250,250,250
rect2 = pygame.rect = (100,100,50,50)
WINDOWWIDTH = 1200
WINDOWHEIGHT = 750
thing = pygame.image.load('car.png')
screen = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT), 0, 32)
pygame.display.set_caption('Teh test')
left = False
right = False
forward = False
backward = False
thing2_x = 100
thing2_y = 100
speed = 20
while True:
rect2 = pygame.rect = (100,100,50,50)
if right: # don't need == True
degree -= 2
while degree < 0:
degree += 360
elif left: # don't need == True
degree += 2
while degree > 359:
degree -= 360
dx = math.cos(math.radians(degree))
dy = math.sin(math.radians(degree))
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
pygame.quit()
sys.exit()
elif event.key == K_a: # use constants K_a
left = True
elif event.key == K_d: # use constants K_d
right = True
elif event.key == K_w: # use constants K_w
forward = True
elif event.key == K_s: # use constants K_s
backward = True
if event.type == KEYUP:
if event.key == K_a: # use constants K_a
left = False
elif event.key == K_d: # use constants K_d
right = False
elif event.key == K_w: # use constants K_w
forward = False
elif event.key == K_s: # use constants K_s
backward = False
if forward:
thing2_y -= int(speed * dx)
thing2_x -= int(speed * dy)
elif backward:
thing2_y += int(speed * dx)
thing2_x += int(speed * dy)
pygame.draw.rect(screen,WHITE,rect2)
screen.fill((40, 40, 40))
thing2 = pygame.transform.rotate(thing,degree)
screen.blit(thing2,(thing2_x,thing2_y))
pygame.display.update()
mainClock.tick(60)