Python Pygame Player is ALWAYS centered - python

I've seen the pages on like scrolling cameras, and the camera movement, but I just want it simpler. I don't want the camera to follow the player off screen, I just want the camera to always center on the player, like the player is always in the center of the screen.
If you need, heres the files + code:
my main.py
import pygame, sys
from pygame.locals import *
from engineTiles import Tile
from classlibEntities import *
import Functions
from interaction import interaction
pygame.init()
pygame.font.init()
invalids = (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,
19,37,55,73,91,109,127,145,163,181,
182,183,184,185,186,187,188,189,190,
191,192,193,194,195,196,197,198,
36,54,72,90,108,126,144,162,180,198)
SCREENWIDTH = 720
SCREENHEIGHT = 440
DrawNumbers = True
window = pygame.display.set_mode((SCREENWIDTH, SCREENHEIGHT))
for y in range(0, window.get_height(), 40):
for x in range(0, window.get_width(), 40):
if Tile.total_tiles in invalids:
Tile(x, y, 'solid')
else:
Tile(x, y, 'empty')
pygame.display.set_caption("Until Death - Core Architecture Build 04")
fpsclock = pygame.time.Clock()
FPS = 60
zombie1 = EntityZombie(200, 240)
player = EntityPlayer(400, 120)
# ------- Main Game Loop -------
while True:
interaction(window, player)
# ------- All GameLogic -------
Tile.draw_tiles(window)
if DrawNumbers == True:
Tile.draw_tilenumbers(window)
player.draw(window)
EntityZombie.draw_zombies(window)
pygame.display.update()
fpsclock.tick(FPS)
Any my tile class
import pygame, Functions
class Tile(pygame.Rect):
List = []
width, height = 40, 40
total_tiles = 1
H, V = 1, 18
def __init__(self, x, y, Type):
self.type = Type
self.number = Tile.total_tiles
Tile.total_tiles += 1
if Type == 'empty':
self.walkable = True
else:
self.walkable = False
pygame.Rect.__init__(self, (x, y), (Tile.width, Tile.height))
Tile.List.append(self)
#staticmethod
def get_tile(number):
for tile in Tile.List:
if tile.number == number:
return tile
#staticmethod
def draw_tiles(window):
for tile in Tile.List:
if not(tile.type == 'empty'):
if tile.type == 'solid':
pygame.draw.rect(window, [40, 40, 40], tile)
else:
pygame.draw.rect(window, [0, 0, 0], tile)
#staticmethod
def draw_tilenumbers(window):
for tile in Tile.List:
Functions.text_to_screen(window, tile.number, tile.x, tile.y)
And finally the class that has the player stuff in it.
import pygame
from engineTiles import Tile
class Entity(pygame.Rect):
width, height = 40, 40
def __init__(self, x, y):
pygame.Rect.__init__(self, x, y, EntityPlayer.width, EntityPlayer.height)
def __str__(self):
return str(self.get_number())
def get_number(self):
return ((self.x / self.width) + Tile.H) + (self.y / self.height) * Tile.V
def get_tile(self):
return Tile.get_tile(self.get_number())
class EntityZombie(Entity):
List = []
def __init__(self, x, y):
Entity.__init__(self, x, y)
EntityZombie.List.append(self)
#staticmethod
def draw_zombies(window):
for zombie in EntityZombie.List:
pygame.draw.rect(window, [210, 24, 77], zombie)
class EntityPlayer(Entity):
def __init__(self, x, y):
Entity.__init__(self, x, y)
def draw(self, window):
r = int (self.width / 2)
pygame.draw.circle(window, [77, 234, 156], (self.x + r, self.y + r), r)

What you need to do is have all the co-ordinates of the objects when you blit them, but before you blit them, subtract the player position. So if the player had moved 50 pixels down, subtract 50 pixels from all your objects before you blit them ie. move them 50 pixels up. Make sure you measure the amount the player has moved is measured in pixels, not in tiles!

Related

Create an inventory for a python game

So I try to create an inventory for the python game Dodger. In the inventory I want to be able to select different players to play the game. But when I run the game, only the option images/player.png is chosen. How can I fix that? thanks
This is what I have tried so far:
//Inventory.py
import pygame
import pygwidgets
import pyghelpers
import random
from Player import Player
import Constants
from Constants import *
class Inventory(pyghelpers.Scene):
def __init__(self, window):
self.window = window
self.player = Player(window)
self.player0 = pygwidgets.CustomButton(self.window, (30, 250), 'images/player_inv.png')
self.player1 = pygwidgets.CustomButton(self.window, (280, 250), 'images/player1_inv.jpg')
self.player2 = pygwidgets.CustomButton(self.window, (30, 450), 'images/char1_inv.png')
self.inventory = []
self.image = pygwidgets.Image(self.window,(0, 0),'images/inventory.png')
self.quitButton = pygwidgets.CustomButton(self.window,
(30, 650),
up='images/quitNormal.png',
down='images/quitDown.png',
over='images/quitOver.png',
disabled='images/quitDisabled.png')
self.backButton = pygwidgets.CustomButton(self.window,
(240, 650),
up='images/backNormal.png',
down='images/backDown.png',
over='images/backOver.png',
disabled='images/backDisabled.png')
def getSceneKey(self):
return SCENE_INVENTORY
def enter(self, data):
pass
def handleInputs(self, eventsList, keyPressedList):
for event in eventsList:
if self.quitButton.handleEvent(event):
self.quit()
elif self.backButton.handleEvent(event):
self.goToScene(Constants.SCENE_PLAY)
if self.player0.handleEvent(event):
self.player.imagelink = 'images/player.png'
self.goToScene(Constants.SCENE_PLAY)
elif self.player1.handleEvent(event):
self.player.imagelink = 'images/player1.jpg'
self.goToScene(Constants.SCENE_PLAY)
elif self.player2.handleEvent(event):
self.player.imagelink = 'images/player2.png'
self.goToScene(Constants.SCENE_PLAY)
def update(self):
pass
def draw(self):
self.image.draw()
self.quitButton.draw()
self.backButton.draw()
self.player0.draw()
self.player1.draw()
self.player2.draw()
//Player.py
import pygame
import pygwidgets
from Constants import *
class Player():
def __init__(self, window):
self.window = window
self.imagelink = 'images/player.png'
self.image = pygwidgets.Image(window,
(-100, -100), self.imagelink)
playerRect = self.image.getRect()
self.maxX = WINDOW_WIDTH - playerRect.width
self.maxY = GAME_HEIGHT - playerRect.height
# Every frame, move the Player icon to the mouse position
# Limits the x- and y-coordinates to the game area of the window
def update(self, x, y):
if x < 0:
x = 0
elif x > self.maxX:
x = self.maxX
if y < 0:
y = 0
elif y > self.maxY:
y = self.maxY
self.image.setLoc((x, y))
return self.image.getRect()
def draw(self):
self.image.draw()
enter image description here
With your code Player.imagelink = 'images/player1.jpg', you are modifying a class attribute and not a class instance attribute. You can fix this by changing self.player.imagelink = 'images/player1.jpg'. You will need to make similar changes for each line that includes Player.imagelink = ...

Why is my pyglet program slow while rendering 128 particles?

Why is my program slow while rendering 128 particles? I think that's not enough to get less than 30 fps.
All I do is rendering 128 particles and giving them some basic gravitation
on_draw function
def on_draw(self, time=None):
glClearColor(0.0, 0.0, 0.0, 1.0)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glLoadIdentity()
self.particles.append(Particle())
for particle in self.particles:
particle.draw()
if particle.is_dead:
self.particles.remove(particle)
Particle class
class Particle:
def __init__(self, **kwargs):
self.acceleration = Vector2(0, 0.05)
self.velocity = Vector2(random.uniform(-1, 1), random.uniform(-1, 0))
self.position = Vector2()
self.time_to_live = 255
self.numpoints = 50
self._vertices = []
for i in range(self.numpoints):
angle = math.radians(float(i) / self.numpoints * 360.0)
x = 10 * math.cos(angle) + self.velocity[0] + 300
y = 10 * math.sin(angle) + self.velocity[1] + 400
self._vertices += [x, y]
def update(self, time=None):
self.velocity += self.acceleration
self.position -= self.velocity
self.time_to_live -= 2
def draw(self):
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glPushMatrix()
glTranslatef(self.position[0], self.position[1], 0)
pyglet.graphics.draw(self.numpoints, GL_TRIANGLE_FAN, ('v2f', self._vertices), ('c4B', self.color))
glPopMatrix()
self.update()
#property
def is_dead(self):
if self.time_to_live <= 0:
return True
return False
#property
def color(self):
return tuple(color for i in range(self.numpoints) for color in (255, 255, 255, self.time_to_live))
I'm not overly happy about using GL_TRIANGLE_FAN because it's caused a lot of odd shapes when using batched rendering. So consider moving over to GL_TRIANGLES instead and simply add all the points to the object rather than leaning on GL to close the shape for you.
That way, you can easily move over to doing batched rendering:
import pyglet
from pyglet.gl import *
from collections import OrderedDict
from time import time, sleep
from math import *
from random import randint
key = pyglet.window.key
class CustomGroup(pyglet.graphics.Group):
def set_state(self):
#pyglet.gl.glLineWidth(5)
#glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
#glColor4f(1, 0, 0, 1) #FFFFFF
#glLineWidth(1)
#glEnable(texture.target)
#glBindTexture(texture.target, texture.id)
pass
def unset_state(self):
glLineWidth(1)
#glDisable(texture.target)
class Particle():
def __init__(self, x, y, batch, particles):
self.batch = batch
self.particles = particles
self.group = CustomGroup()
self.add_point(x, y)
def add_point(self, x, y):
colors = ()#255,0,0
sides = 50
radius = 25
deg = 360/sides
points = ()#x, y # Starting point is x, y?
prev = None
for i in range(sides):
n = ((deg*i)/180)*pi # Convert degrees to radians
point = int(radius * cos(n)) + x, int(radius * sin(n)) + y
if prev:
points += x, y
points += prev
points += point
colors += (255, i*int(255/sides), 0)*3 # Add a color pair for each point (r,g,b) * points[3 points added]
prev = point
points += x, y
points += prev
points += points[2:4]
colors += (255, 0, 255)*3
self.particles[len(self.particles)] = self.batch.add(int(len(points)/2), pyglet.gl.GL_TRIANGLES, self.group, ('v2i/stream', points), ('c3B', colors))
class main(pyglet.window.Window):
def __init__ (self, demo=False):
super(main, self).__init__(800, 600, fullscreen = False, vsync = True)
#print(self.context.config.sample_buffers)
self.x, self.y = 0, 0
self.sprites = OrderedDict()
self.batches = OrderedDict()
self.batches['default'] = pyglet.graphics.Batch()
self.active_batch = 'default'
for i in range(1000):
self.sprites[len(self.sprites)] = Particle(randint(0, 800), randint(0, 600), self.batches[self.active_batch], self.sprites)
self.alive = True
self.fps = 0
self.last_fps = time()
self.fps_label = pyglet.text.Label(str(self.fps) + ' fps', font_size=12, x=3, y=self.height-15)
def on_draw(self):
self.render()
def on_close(self):
self.alive = 0
def on_key_press(self, symbol, modifiers):
if symbol == key.ESCAPE: # [ESC]
self.alive = 0
def render(self):
self.clear()
#self.bg.draw()
self.batches[self.active_batch].draw()
self.fps += 1
if time()-self.last_fps > 1:
self.fps_label.text = str(self.fps) + ' fps'
self.fps = 0
self.last_fps = time()
self.fps_label.draw()
self.flip()
def run(self):
while self.alive == 1:
self.render()
# -----------> This is key <----------
# This is what replaces pyglet.app.run()
# but is required for the GUI to not freeze
#
event = self.dispatch_events()
if __name__ == '__main__':
x = main(demo=True)
x.run()
Bare in mind, on my nVidia 1070 I managed to get roughly 35fps out of this code, which isn't mind blowing. But it is 1000 objects * sides, give or take.
What I've changed is essentially this:
self.batch.add(int(len(points)/2), pyglet.gl.GL_TRIANGLES, self.group, ('v2i/stream', points), ('c3B', colors))
and in your draw loop, you'll do:
self.batch.draw()
Instead of calling Particle.draw() for each particle object.
What this does is that it'll send all the objects to the graphics card in one gigantic batch rather than having to tell the graphics card what to render object by object.
As #thokra pointed out, your code is more CPU intensive than GPU intensive.
Hopefully this fixes it or gives you a few pointers.
Most of this code is taking from a LAN project I did with a good friend of mine a while back:
https://github.com/Torxed/pyslither/blob/master/main.py
Because I didn't have all your code, mainly the main loop. I applied your problem to my own code and "solved " it by tweaking it a bit. Again, hope it helps and steal ideas from that github project if you need to. Happy new year!

Sprite in Pyglet not doing what I want

I am trying to have a circle that, when clicked, moves somewhere else on the screen. However, when I click the circle, nothing happens.
#IMPORT STUFF
import pyglet as pg
from random import randint
mouse = pg.window.mouse
#VARS
window = pg.window.Window(width = 640, height = 480)
score = 0
circleImg = pg.image.load("circle.png")
circle = pg.sprite.Sprite(circleImg, randint(1, window.width), randint(1, window.height))
text = pg.text.Label("Click red!", font_name = "Times New Roman", font_size = 18, x = 260, y = 10)
#DETECT MOUSE PRESS ON CIRCLE
#window.event
def on_mouse_press(x, y, button, modifiers):
if x == circle.x and y == circle.y:
circle.x = randint(1, window.width)
circle.y = randint(1, window.height)
#window.event
def on_draw():
window.clear()
text.draw()
circle.draw()
pg.app.run()
import pyglet
from pyglet.gl import *
from random import randint
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
class Circle(pyglet.sprite.Sprite):
def __init__(self, radiance=5, x=0, y=0):
self.texture = pyglet.image.load('circle.png')
super(Circle, self).__init__(self.texture)
def click(self, x, y):
if x >= self.x and y >= self.y:
if x <= self.x + self.texture.width and y <= self.y + self.texture.height:
return self
mouse = pyglet.window.mouse
#VARS
window = pyglet.window.Window(width = 640, height = 480)
score = 0
#circleImg = pyglet.image.load("circle.png")
#circle = pyglet.sprite.Sprite(circleImg, randint(1, window.width), randint(1, window.height))
circle = Circle(x=50, y=50)
text = pyglet.text.Label("Click red!", font_name = "Times New Roman", font_size = 18, x = 260, y = 10)
#DETECT MOUSE PRESS ON CIRCLE
#window.event
def on_mouse_press(x, y, button, modifiers):
if circle.click(x, y):
print('Clicked in circle')
circle.x = randint(0, window.width - 10)
circle.y = randint(0, window.height - 10)
#window.event
def on_draw():
window.clear()
text.draw()
circle.draw()
pyglet.app.run()
A short description of what this does is it creates a custom class called Circle that inherits the Sprite class. It loads the circle.png as a texture with a alpha channel that gets blended by the GL library.
We add a custom function called click that checks if the lowest x,y coordinates are higher than the circles lowest x,y, then we check if the cursor is below x+width and same for y of the image region.
If that's the case, we return the circle sprite class as a True value in case we want to use the sprite.
Future enhancements:
You should draw the circle using gl functions, hence why I've defined radiance in the class definitions. However radiance here is never used, it's a placeholder for the future.
This is so you can use math to defined if you actually clicked within the circle, but this is beyond my scope of quick answers.. I would have to do a lot of debugging myself in order to get the math to add up (it's not my strong side).
What makes it work now is that we use the image width, height, x and y data to crudely check if we're within the image, aka "the circle".
trying to draw over sprite or change picture pyglet
As a bonus, I'll add this answer to the list of enhancements because it contains some stuff that might be useful. One would be to replace 90% of your code with a custom pyglet.window.Window class to replace global variables and decorators and stuff.
And it would look something like this:
import pyglet
from pyglet.gl import *
from random import randint
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
key = pyglet.window.key
class Circle(pyglet.sprite.Sprite):
def __init__(self, radiance=5, x=0, y=0):
self.texture = pyglet.image.load('circle.png')
super(Circle, self).__init__(self.texture)
def click(self, x, y):
if x >= self.x and y >= self.y:
if x <= self.x + self.texture.width and y <= self.y + self.texture.height:
return self
class MainScreen(pyglet.window.Window):
def __init__ (self):
super(MainScreen, self).__init__(800, 600, fullscreen = False)
self.x, self.y = 0, 0
self.bg = pyglet.sprite.Sprite(pyglet.image.load('background.jpg'))
self.sprites = {}
self.sprites['circle'] = Circle(x=50, y=50)
self.sprites['label'] = pyglet.text.Label("Click red!", font_name = "Times New Roman", font_size = 18, x = 260, y = 10)
self.alive = 1
def on_draw(self):
self.render()
def on_close(self):
self.alive = 0
def on_mouse_press(self, x, y, button, modifiers):
if self.sprites['circle'].click(x, y):
print('Clicked in circle')
self.sprites['circle'].x = randint(0, self.width - 10)
self.sprites['circle'].y = randint(0, self.height - 10)
def on_key_press(self, symbol, modifiers):
if symbol == key.ESCAPE: # [ESC]
self.alive = 0
def render(self):
self.clear()
self.bg.draw()
for sprite_name, sprite_obj in self.sprites.items():
sprite_obj.draw()
self.flip()
def run(self):
while self.alive == 1:
self.render()
# -----------> This is key <----------
# This is what replaces pyglet.app.run()
# but is required for the GUI to not freeze
#
event = self.dispatch_events()
x = MainScreen()
x.run()
I'm not familiar with pyglet, but I'm guessing the problem is that you're checking whether x == circle.x etc, which means it only moves when you click the single pixel at the exact centre of the circle. Try some kind of maximum distance from the centre (e.g. a hypotenuse math.sqrt( (x-circle.x)**2 + (y-circle.y)**2) < circle.radius

Turn-based game map in python

I am making a turn-based game in python and I have some problems with game map.
This is the code:
import pygame, sys
from pygame.locals import *
pygame.init()
class Map(object):
def __init__(self, x, y, SURF):
self.x = x
self.y = y
self.SURF = SURF
def createNewMap(self, D1, D2):
create a D1xD2 map
self.Map = []
self.D1 = D1
self.D2 = D2
for n in range(self.D1):
current = ['']*self.D2
self.Map.append(current)
return self.Map
def drawMap(self):
draw the D1xD2 map from (x,y) position. grass.gif represent 1 grass box. the map contain D1xD2 grass boxes.
imgObj = pygame.image.load('images\\textures\grass.gif')
imgObj = pygame.transform.scale(imgObj, (40, 40))
xc = self.x
yc = self.y
for itemY in self.Map:
for itemX in self.Map[self.Map.index(itemY)]:
self.SURF.blit(imgObj, (xc, yc))
xc += 40
yc += 40
xc = self.x
i want when the mouse is above a box, i want to changes it with another texture box(grass1.gif). how can i do this?
You can do that by getting the current mouse position and then checking whether that is in the bounds of the box. Here is an unrelated example:
mouse_pos = pygame.mouse.get_pos()
for rectange in my_objects_list:
if rectangle.collidepoint(mouse_pos):
#do something ...

Menu for a game made in Pygame

I have no clue how I would implement a game menu into the game I've made, I was thinking about having buttons for instructions credits and a 'play game' button. So would someone mind helping me out in figuring how to make a simple menu in pygame or livewires? Thanks in advance :)
This is the complete code to my game:
# Asteroid Dodger
# Player must avoid asteroids
# make the score a global variable rather than tied to the asteroid.
import pygame
from livewires import games, color
import math, random
#score
games.init(screen_width = 640, screen_height = 480, fps = 50)
score = games.Text(value = 0, size = 25, color = color.green,
top = 5, right = games.screen.width - 10)
games.screen.add(score)
#lives
lives = games.Text(value = 3, size = 25, color = color.green,
top = 5, left = games.screen.width - 620)
games.screen.add(lives)
#inventory
inventory=[]
#Asteroid images
images = [games.load_image("asteroid_small.bmp"),
games.load_image("asteroid_med.bmp"),
games.load_image("asteroid_big.bmp")]
class Ship(games.Sprite):
"""
A Ship controlled by player that explodes when it by Asteroids.
"""
image = games.load_image("player.bmp")
VELOCITY_STEP = .05
def __init__(self):
""" Initialize Ship object """
super(Ship, self).__init__(image = Ship.image,
bottom = games.screen.height)
def update(self):
global inventory
""" uses A and D keys to move the ship """
if games.keyboard.is_pressed(games.K_a):
self.dx -= Ship.VELOCITY_STEP * 2
if games.keyboard.is_pressed(games.K_d):
self.dx += Ship.VELOCITY_STEP * 2
if self.left < 0:
self.left = 0
if self.right > games.screen.width:
self.right = games.screen.width
self.check_collison()
def ship_destroy(self):
self.destroy()
new_explosion = Explosion(x = self.x, y = self.y)
games.screen.add(new_explosion)
def check_collison(self):
""" Check for overlapping sprites in the ship. """
global lives
for items in self.overlapping_sprites:
items.handle_caught()
if lives.value <=0:
self.ship_destroy()
class Explosion(games.Animation):
sound = games.load_sound("explosion.wav")
images = ["explosion1.bmp",
"explosion2.bmp",
"explosion3.bmp",
"explosion4.bmp",
"explosion5.bmp",
"explosion6.bmp",
"explosion7.bmp",
"explosion8.bmp",
"explosion9.bmp"]
def __init__(self, x, y):
super(Explosion, self).__init__(images = Explosion.images,
x = x, y = y,
repeat_interval = 4, n_repeats = 1,
is_collideable = False)
Explosion.sound.play()
class Asteroid(games.Sprite):
global lives
global score
global inventory
"""
A asteroid which falls through space.
"""
image = games.load_image("asteroid_med.bmp")
speed = 3
def __init__(self, x,image, y = 10):
""" Initialize a asteroid object. """
super(Asteroid, self).__init__(image = image,
x = x, y = y,
dy = Asteroid.speed)
def update(self):
""" Check if bottom edge has reached screen bottom. """
if self.bottom>games.screen.height:
self.destroy()
score.value+=10
def handle_caught(self):
if lives.value>0:
lives.value-=1
self.destroy_asteroid()
if lives.value <= 0:
self.destroy_asteroid()
self.end_game()
def destroy_asteroid(self):
self.destroy()
def die(self):
self.destroy()
def end_game(self):
""" End the game. """
end_message = games.Message(value = "Game Over",
size = 90,
color = color.red,
x = games.screen.width/2,
y = games.screen.height/2,
lifetime = 5 * games.screen.fps,
after_death = games.screen.quit)
games.screen.add(end_message)
class Spawner(games.Sprite):
global images
"""
Spawns the asteroids
"""
image = games.load_image("spawner.bmp")
def __init__(self, y = 10, speed = 5, odds_change = 50):
super(Spawner, self).__init__(image = Spawner.image,
x = games.screen.width / 2,
y = y,
dx = speed)
self.odds_change = odds_change
self.time_til_drop = 0
def update(self):
""" Determine if direction needs to be reversed. """
if self.left < 0 or self.right > games.screen.width:
self.dx = -self.dx
elif random.randrange(self.odds_change) == 0:
self.dx = -self.dx
self.check_drop()
self.check_for_lives()
def check_drop(self):
""" Decrease countdown or drop asteroid and reset countdown. """
if self.time_til_drop > 0:
self.time_til_drop -= 0.7
else:
asteroid_size = random.choice(images)
new_asteroid = Asteroid(x = self.x,image = asteroid_size)
games.screen.add(new_asteroid)
# makes it so the asteroid spawns slightly below the spawner
self.time_til_drop = int(new_asteroid.height * 1.3 / Asteroid.speed) + 1
def check_for_lives(self):
droplives = random.randrange(0, 4000)
if droplives == 5:
lifetoken = Extralives(x = self.x)
g ames.screen.add(lifetoken)
class Extralives(games.Sprite):
global lives
image = games.load_image('addlives.png')
speed = 2
sound = games.load_sound("collectlives.wav")
def __init__(self,x,y = 10):
""" Initialize a asteroid object. """
super(Extralives, self).__init__(image = Extralives.image,
x = x, y = y,
dy = Extralives.speed)
def update(self):
""" Check if bottom edge has reached screen bottom. """
if self.bottom>games.screen.height:
self.destroy()
def handle_caught(self):
Extralives.sound.play()
lives.value+=1
self.destroy()
def main():
""" Play the game. """
bg = games.load_image("space.jpg", transparent = False)
games.screen.background = bg
the_spawner = Spawner()
games.screen.add(the_spawner)
pygame.mixer.music.load("Jumpshot.ogg")
pygame.mixer.music.play()
the_ship = Ship()
games.screen.add(the_ship)
games.mouse.is_visible = False
games.screen.event_grab = True
games.screen.mainloop()
#starts the game
main()
The Pygbutton module provides a way to create buttons in Pygame programs. You can download it via "pip install pygbutton". There are demos on the github: https://github.com/asweigart/pygbutton
Try this code out:
Game Menu function
def game_intro():
intro = True
while intro:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
gameDisplay.fill(white)
titleText = gameDisplay.blit(title, (170, 200)) # title is an image
titleText.center = ((display_width / 2), (display_height / 2))
# button(x, y, w, h, inactive, active, action=None)
button(100, 350, 195, 80, startBtn, startBtn_hover, game_loop)
button(300, 350, 195, 80, creditsBtn, creditsBtn_hover, #Your function)
pygame.display.update()
clock.tick(15)
you can call this menu above your game loop.
Button function
Pygame doesn't have buttons but it is pretty easy to make one!
def button(x, y, w, h, inactive, active, action=None):
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
if x + w > mouse[0] > x and y + h > mouse[1] > y:
gameDisplay.blit(active, (x, y))
if click[0] == 1 and action is not None:
action()
else:
gameDisplay.blit(inactive, (x, y))
you can call this function inside your game menu like this:
#Example function call
button(340, 560, 400, 200, randomBtn, randomBtn_hover, random_func)
Here's what each parameter means in button():
x: x-coordinate of button
y: y-coordinate of button
w: button width(in pixels)
h: button height(in pixels)
active: the picture of the button when it is active(e.g when the mouse is hovering ver it)
inactive: the picture of the button when it is idle
action: the function to be executed when the button is pressed
Note: It is better to make a button function since it is easier to make one and it saves a lot of time
Hope this helped!

Categories

Resources