Need help rotating an object towards another moving object [duplicate] - python-2.7

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()

Related

Pygame : Controlling two sprites

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)

Pygame independent moving images on the screen

I am new to Python and Pygame. I want to have a screen in pygame with multiple copies of the same images moving around independently. I have tried to write it as a class and then call instances of it inside the while loop, but it doesn't work. Could someone show how can i basically do such a thing using a class?
I've tried to keep everything simple
Example:
import pygame
pygame.init()
WHITE = (255,255,255)
BLUE = (0,0,255)
window_size = (400,400)
screen = pygame.display.set_mode(window_size)
clock = pygame.time.Clock()
class Image():
def __init__(self,x,y,xd,yd):
self.image = pygame.Surface((40,40))
self.image.fill(BLUE)
self.x = x
self.y = y
self.x_delta = xd
self.y_delta = yd
def update(self):
if 0 <= self.x + self.x_delta <= 360:
self.x += self.x_delta
else:
self.x_delta *= -1
if 0 <= self.y + self.y_delta <= 360:
self.y += self.y_delta
else:
self.y_delta *= -1
screen.blit(self.image,(self.x,self.y))
list_of_images = []
list_of_images.append(Image(40,80,2,0))
list_of_images.append(Image(160,240,0,-2))
done = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
screen.fill(WHITE)
for image in list_of_images:
image.update()
pygame.display.update()
clock.tick(30)
pygame.quit()
Each image can be called individually from the list and moved by simply changing Image.x/y to whatever you want

Check collision between two imported pictures

I'm trying to recreate a game, however all I need is to create a game-over feature that occurs when the player collides or fails to jump over the rock. I've tried to do the check collision yet the player is passing through. What should I do or change in order to display the game over screen when the player collides with the rock? Here is my sample code:
#--- Player Definition
class Player(pygame.sprite.Sprite):
#- Constructor
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.playing = False
self.image = pygame.image.load("bcquestchar.png")
self.rect = self.image.get_rect()
self.color = BLUE
self.rect.x = 50
self.rect.y = 210
self.goalY= 450
self.gameover = False
#- Allows Player to Jump
def jump(self):
self.goalY -= 25
#- Imports & Displays player_image
def draw(self, screen):
screen.blit(player_image, [self.rect.x, self.rect.y])
#--- Rock definition
class Rock(pygame.sprite.Sprite):
#- Constructor
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("bcrocks.png")
self.rect = self.image.get_rect()
self.rect.x = random.randrange (0, 200)
self.rect.y = 335
#- Moves Rock
def move(self):
self.rect.x -= 3
#- Imports & Displays rock_image
def draw(self, screen):
screen.blit(self.image, [self.rect.x + 700, self.rect.y])
# Loop until user closes pygame
done = False
# How fast the screen updates
clock = pygame.time.Clock()
# Creates player
rock = Rock()
player = Player()
obstacles = pygame.sprite.Group()
obstacles.add(rock)
if pygame.sprite.spritecollide(player, obstacles, False):
player.gameover = True
#----- Main Program Loop -----#
while not done:
#movesound.play()
#- Calls in draw_background function
draw_background (screen, 0, 0)
#- Tracks Events
speed = 1
#--- Main Event Loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = False
#- User is playing when M1 is clicked
elif event.type == pygame.MOUSEBUTTONDOWN:
player.playing = True
#- User jumps when playing and has not lost
if(player.gameover == False and player.playing == True):
player.jump()
#- Is the player playing?
if(player.playing == True):
# Jump up when the up arrow is pressed
if event.type == pygame.MOUSEBUTTONDOWN:
currently_jumping = True
going_up = True
#hopsound.play()
if currently_jumping == True:
if player.rect.y < 188:
going_up = False
elif going_up == False and player.rect.y > 215:
currently_jumping = False
if going_up:
player.rect.y -= 2
elif going_up == False:
player.rect.y += 2
elif currently_jumping == False:
if(player.rect.y > 600 or player.rect.y < 0):
player.gameover = True
if(player.rect.y < 210):#player.goalY):
player_moving_up = False
elif(player.rect.y > 210):#player.goalY):
player_moving_up = True
if player_moving_up == True or player_moving_up == True:
player.rect.y += 1
player.rect.y -= 1
player.goalY += 3
if(timer3 > 120):
timer3 = 0
if(player.playing == True and player.gameover == False):
score += 30
#--- Draw and Move Rocks
for rock in obstacles:
rock.draw(screen)
if(player.gameover == False):
rock.move()
rock.draw(screen)
#rock.checkCollision(player.x, player.y)
if pygame.sprite.spritecollide(player, obstacles, False):
obstacles.remove(rock)
#----- Gameover
if(player.gameover == True):
player.goalY = 600
font = pygame.font.SysFont('Ariel', 50, True, False)
text = font.render("Game Over", True, WHITE)
screen.blit(text, [150, 100])
Code edited
Make Rock() also a pygame.sprite.Sprite class and if possible, put in a pygame.sprite.Group(). In that case, you can use if pygame.sprite.spritecollide() to check for detection:
rock = Rock()
player = Player()
obstacles = pygame.sprite.Group()
obsatcles.add(rock)
if pygame.sprite.spritecollide(player, obstacles, False):
pass #Do something
The good thing about using pygame.sprite.Group() is that you can use that to help detect collisions with the player and any other obstacle. Let's assume you have three items in obstacles, in which they are all rock's:
for rock in obstacles:
if pygame.sprite.spritecollide(player, obstacles, False):
obstacles.remove(rock) #Removes the obstacle
Put the group outside the sprite classes and before the while loop.
For the rock, use this in your init function:
self.rect = self.image.get_rect()
So it would be:
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("filename.png")
self.rect = pygame.image.get_rect()
Then add this to your while loop:
for rock in obstacles:
rock.move()
rock.draw()
Your final class (excluding the last two functions) would be:
class Rock(pygames.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("bcrocks.png")
self.rect = self.image.get_rect()
self.rect.x = random.randrange (0, 200)
self.rect.y = 335

Making program do two things at the same time and command crashes game

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()

Pygame - AttributeError: 'int' object has no attribute 'y'

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()