I was writing the python/pygame code for Dice game. However, I have problem about Player's Points. My code can't calculate Player's Points correctly. I really need someone to fix this problem for me.
Here are the rules
Player's Points = 100 points
If Player's Points >= 10, Player's Points - 10 (Keep Playing)
If Player's Points < 10, "Game Over" (End Game)
Five of a Kind: Player's Points + 30
Four of a Kind: Player's Points + 20
Three of Kind: Player's Points + 10
Full House: Player's Points +15
Straight: Player's Points + 20
Two Pair: Player's Points + 5
No Winnings: Player's Points + 0
Here are my code:
gDieMain
#gDieMain.py
import pygame, sys# Imports pygame package, Imports system package
from pygame.locals import * # You will have namespace shortcuts
from gDieClass import gDie
from gDiebuttonClass import simpleButton
from random import *
pygame.init() # Initializes pygame for the program and computer
# Global Variables
PPOINTS = 100
DIENUM = 10
# Color Value
GREY = (128, 128, 128)
GREEN = (0, 100, 0)
LTGREEN = (0, 255, 0)
DKGREEN = (174, 177, 120)
WHITE = (255, 255, 255)
BLACK = (40, 40, 40)
RED = (201, 0, 22)
# Button Value
SIZE = 100
hbXsize = 130
hbYsize = 30
hbBut1XPOS = 85
hbBut2XPOS = 285
hbBut3XPOS = 485
hbBut4XPOS = 685
hbBut5XPOS = 885
hbButYPOS = 215
#Set up the window
DISPLAYWIDTH = 1125
DISPLAYHEIGHT = 600
DISPLAYSURF = pygame.display.set_mode((1200, 600))
pygame.display.set_caption('DICE GAME GRAPHICS')
BGCOLOR = (0, 128, 0)
DISPLAYSURF.fill(BGCOLOR)
# Set up the Player's Points (unfinished)
#PCOLOR = (40, 40, 40)
#POINTFONT = pygame.font.SysFont("Times New Roman", 65)
#PPFONT = pygame.font.SysFont("ScriptinaPro", 120)
#Button Layout
BUTTONWIDTH = 400
BUTTONHEIGHT = BUTTONWIDTH//7
BUTXPOS = (DISPLAYWIDTH - BUTTONWIDTH)//2
BUTYPOS = int(DISPLAYHEIGHT * .70)
HDISPLAYWIDTH = DISPLAYWIDTH//2
HDISPLAYHEIGHT = DISPLAYHEIGHT//2
CENTERBUTXPOS = HDISPLAYWIDTH - DISPLAYWIDTH//16
HSIZE = SIZE//2
GAP = (DISPLAYWIDTH//DIENUM - SIZE)//2
# pygame.font.SysFont()
# create a Font object from the system fonts
# SysFont(name, size, bold=False, italic=False) -> Font
myfont = pygame.font.SysFont("Times New Roman", 65)
#myfont1 = pygame.font.SysFont("Times New Roman", 65)
myfont2 = pygame.font.SysFont("Times New Roman", 35)
# Dice Layout
DIEYPOS = DISPLAYHEIGHT//4
DIE1XPOS = HDISPLAYWIDTH - HSIZE - 2 * GAP - 2 * SIZE
DIE2XPOS = HDISPLAYWIDTH - HSIZE - GAP - SIZE
DIE3XPOS = HDISPLAYWIDTH - HSIZE
DIE4XPOS = HDISPLAYWIDTH + HSIZE + GAP
DIE5XPOS = HDISPLAYWIDTH + HSIZE + 2 * GAP + SIZE
# Dice Position
position1 = (100, 100)
position2 = (300, 100)
position3 = (500, 100)
position4 = (700, 100)
position5 = (900, 100)
# Font Position
myfontPosition1 = (375, 20)
myfontPosition2 = (100, 500)
myfontPosition3 = (240, 260)
# Instantiate Objects
d1 = gDie(SIZE, position1)
d2 = gDie(SIZE, position2)
d3 = gDie(SIZE, position3)
d4 = gDie(SIZE, position4)
d5 = gDie(SIZE, position5)
#Make die object list
b1 = simpleButton(hbXsize, hbYsize, GREEN, LTGREEN, 'Dice 1',
DISPLAYSURF, (hbBut1XPOS, hbButYPOS))
b2 = simpleButton(hbXsize, hbYsize, GREEN, LTGREEN, 'Dice 2',
DISPLAYSURF, (hbBut2XPOS, hbButYPOS))
b3 = simpleButton(hbXsize, hbYsize, GREEN, LTGREEN, 'Dice 3',
DISPLAYSURF, (hbBut3XPOS, hbButYPOS))
b4 = simpleButton(hbXsize, hbYsize, GREEN, LTGREEN, 'Dice 4',
DISPLAYSURF, (hbBut4XPOS, hbButYPOS))
b5 = simpleButton(hbXsize, hbYsize, GREEN, LTGREEN, 'Dice 5',
DISPLAYSURF, (hbBut5XPOS, hbButYPOS))
# Instantiate Roll Buttons
firstRoll = simpleButton(BUTTONWIDTH, BUTTONHEIGHT, GREEN, LTGREEN,
'First Roll (10 pts)', DISPLAYSURF, (BUTXPOS, BUTYPOS))
secondRoll = simpleButton(BUTTONWIDTH, BUTTONHEIGHT, GREEN, LTGREEN,
'Second Roll', DISPLAYSURF, (BUTXPOS, BUTYPOS))
thirdRoll = simpleButton(BUTTONWIDTH, BUTTONHEIGHT, GREEN, LTGREEN,
'Last Roll', DISPLAYSURF, (BUTXPOS, BUTYPOS))
# Text label
#textLabel = simpleButton(600, BUTTONHEIGHT, DKGREEN, LTGREEN,
# '', DISPLAYSURF, (250, 300))
textLabel = simpleButton(600, BUTTONHEIGHT, BLACK, LTGREEN,
'', DISPLAYSURF, (250, 320))
# pygame.font.SysFont()
# create a Font object from the system fonts
# SysFont(name, size, bold=False, italic=False) -> Font
#myfont = pygame.font.SysFont("Sylfaen", 65)
# render text
# render()
# draw text on a new Surface
# render(text, antialias, color, background=None) -> Surface
#label = myfont.render("DICE POKER SIM!", 0, LTGREEN)
# Assign Objects Values
def setValue(dieList):
newDieList = []
for x in dieList:
if not x.get_hold():
dieNumber = randint(1, 6)
x.setValue(dieNumber)
newDieList.append(x.VALUE)
return newDieList
def displayAllDie(surf):
d1.displayDie(surf, position1[0], position1[1])
d2.displayDie(surf, position2[0], position2[1])
d3.displayDie(surf, position3[0], position3[1])
d4.displayDie(surf, position4[0], position4[1])
d5.displayDie(surf, position5[0], position5[1])
def displayButtons():
firstRoll.displayBut()
def displayHoldButtons():
b1.displayBut()
b2.displayBut()
b3.displayBut()
b4.displayBut()
b5.displayBut()
def score(dice):
global PPOINTS
counts = [0] * 7
for value in dice:
counts[value] += 1
if PPOINTS >= 10:
PPOINTS -= 10
if 5 in counts:
PPOINTS += 30
return "Five of a kind: ", "You win 30 points ", PPOINTS
elif 4 in counts:
PPOINTS += 20
return "Four of a kind: ", "You win 20 points ", PPOINTS
elif (3 in counts) and (2 in counts):
PPOINTS += 15
return "Full House: ", "You win 15 points ", PPOINTS
elif 3 in counts:
PPOINTS += 10
return "Three of Kind: ", "You win 10 points ", PPOINTS
elif not (2 in counts) and (counts[1] == 0 or
counts[6] == 0):
PPOINTS += 25
return "Straight: ", "You win 25 points ", PPOINTS
elif counts.count(2) == 2:
PPOINTS += 5
return "Two Pairs: ", "You win 5 points ", PPOINTS
else:
PPOINTS += 0
return "No winning: ", "You win 0 points ", PPOINTS
def stillText(dieList, surf):
a = setValue(dieList)
displayAllDie(surf)
return a
def allDieHold(dieList):
for x in dieList:
x.HOLD = False
def allDieHit(dieList):
for x in dieList:
x.HOLD = True
dieList = [d1, d2, d3, d4, d5]
setValue(dieList)
def main():
setValue(dieList)
displayButtons()
allDieHit(dieList)
allDieHold(dieList)
handresult = ""
handscore = ""
PPOINTS = ""
keepPlaying = True
while keepPlaying: #Main Game Loop
for event in pygame.event.get():
if event.type == QUIT: # Exit the game
pygame.quit()
sys.exit()
elif event.type == KEYDOWN: # Exit the game
if event.key == K_ESCAPE:
pygame.quit()
return
if event.type == MOUSEBUTTONDOWN:
mouseXY = pygame.mouse.get_pos()
if firstRoll.clicked(mouseXY):
firstRoll.display_HILIGHTED()
elif secondRoll.clicked(mouseXY):
secondRoll.display_HILIGHTED()
elif thirdRoll.clicked(mouseXY):
thirdRoll.display_HILIGHTED()
elif d1.clicked(mouseXY):
d1.switch_hold()
elif d2.clicked(mouseXY):
d2.switch_hold()
elif d3.clicked(mouseXY):
d3.switch_hold()
elif d4.clicked(mouseXY):
d4.switch_hold()
elif d5.clicked(mouseXY):
d5.switch_hold()
if event.type == MOUSEBUTTONUP:
if firstRoll.clicked(mouseXY):
DISPLAYSURF.fill(BGCOLOR)
setValue(dieList)
allDieHit(dieList)
allDieHold(dieList)
stillText(dieList, DISPLAYSURF)
secondRoll.displayBut()
firstRoll.inActive()
secondRoll.active()
#thirdRoll.inActive()
#displayHoldButtons()
elif secondRoll.clicked(mouseXY):
stillText(dieList, DISPLAYSURF)
thirdRoll.displayBut()
secondRoll.inActive()
thirdRoll.active()
elif thirdRoll.clicked(mouseXY):
a = stillText(dieList, DISPLAYSURF)
firstRoll.displayBut()
thirdRoll.inActive()
firstRoll.active()
handresult, handscore, PPOINTS= score(a)
print(score(a))
b1.displayBut()
b2.displayBut()
b3.displayBut()
b4.displayBut()
b5.displayBut()
textLabel.LABEL = handresult + str(handscore) + str(PPOINTS)
textLabel.displayBut()
DISPLAYSURF.blit(myfont.render('DICE GAME', True, LTGREEN), myfontPosition1)
#DISPLAYSURF.blit(myfont1.render("Player's Points: 100", True, LTGREEN), myfontPosition2)
DISPLAYSURF.blit(myfont2.render("Click on Dice: Red to Hold and White to Roll", True, LTGREEN), myfontPosition3)
# render()
# draw text on a new Surface
# render(text, antialias, color, background=None) -> Surface
displayAllDie(DISPLAYSURF)
pygame.display.update()
main()
gDieClass
#gDieClass.py
import pygame
from pygame.locals import *
class gDie:
#class that displays a grahical rep. of 6 sided die
def __init__(self, size, pos):
# Globals
#define some values
self.DIESURF = pygame.Surface((size, size), flags=SRCALPHA, depth=32)
self.DIESURF.fill((0, 0, 0, 0))
#Color
self.white = (255, 255, 255)
self.BLACK = (40, 40, 40)
self.RED = (201, 0, 22)
# Information about the Dice
self.POS = pos
self.HEIGHT = size
self.WIDTH = size
self.HOLD = False
self.VALUE = 0
#SIZE and RADIUS
self.SIZE = size
self.RADIUS = self.SIZE//10
HSIZE = self.SIZE//2
QSIZE = self.SIZE//4
#create Pips/Dots in standard places
self.POINT1 = (HSIZE, HSIZE)
self.POINT2 = (QSIZE, QSIZE)
self.POINT3 = (HSIZE + QSIZE, HSIZE + QSIZE)
self.POINT4 = (HSIZE + QSIZE, QSIZE)
self.POINT5 = (QSIZE, HSIZE + QSIZE)
self.POINT6 = (HSIZE + QSIZE, HSIZE)
self.POINT7 = (QSIZE, HSIZE)
def __drawBackground(self):
#create square with rounded corners for dice
if self.HOLD:
color = self.RED
else:
color = self.white
pygame.draw.circle(self.DIESURF, color, (self.RADIUS, self.RADIUS), self.RADIUS)
pygame.draw.circle(self.DIESURF, color, (self.SIZE - self.RADIUS, self.SIZE - self.RADIUS), self.RADIUS)
pygame.draw.circle(self.DIESURF, color, (self.SIZE - self.RADIUS, self.RADIUS), self.RADIUS)
pygame.draw.circle(self.DIESURF, color, (self.RADIUS, self.SIZE - self.RADIUS), self.RADIUS)
pygame.draw.rect(self.DIESURF, color, Rect((self.RADIUS, 0), (self.SIZE - (2 * self.RADIUS), self.SIZE)))
pygame.draw.rect(self.DIESURF, color, Rect((0, self.RADIUS), (self.SIZE, self.SIZE - (2 * self.RADIUS))))
def __makePip(self, point):
# function to make pips
if self.HOLD:
pygame.draw.circle(self.DIESURF, self.white, point, self.RADIUS)
else:
pygame.draw.circle(self.DIESURF, self.BLACK, point, self.RADIUS)
def switch_hold(self):
#self.HOLD = True
self.HOLD = not self.HOLD
return self.HOLD
def get_hold(self):
return self.HOLD
def clicked(self, MOUSEXY):
yesORno = False
P1 = self.POS
P2 = (P1[0] + self.WIDTH, P1[1] + self.HEIGHT)
yesORno = (P1[0] <= MOUSEXY[0] <= P2[0] and
P1[1] <= MOUSEXY[1] <= P2[1])
return yesORno
def setValue(self, value):
# create Die Background
self.__drawBackground()
self.VALUE = value
# create PIPs at value
if value == 1:
pip1 = self.__makePip(self.POINT1)
elif value == 2:
pip2 = self.__makePip(self.POINT2)
pip3 = self.__makePip(self.POINT3)
elif value == 3:
pip1 = self.__makePip(self.POINT1)
pip2 = self.__makePip(self.POINT2)
pip3 = self.__makePip(self.POINT3)
elif value == 4:
pip2 = self.__makePip(self.POINT2)
pip3 = self.__makePip(self.POINT3)
pip4 = self.__makePip(self.POINT4)
pip5 = self.__makePip(self.POINT5)
elif value == 5:
pip1 = self.__makePip(self.POINT1)
pip2 = self.__makePip(self.POINT2)
pip3 = self.__makePip(self.POINT3)
pip4 = self.__makePip(self.POINT4)
pip5 = self.__makePip(self.POINT5)
elif value == 6:
pip2 = self.__makePip(self.POINT2)
pip3 = self.__makePip(self.POINT3)
pip4 = self.__makePip(self.POINT4)
pip5 = self.__makePip(self.POINT5)
pip6 = self.__makePip(self.POINT6)
pip7 = self.__makePip(self.POINT7)
def displayDie(self, surf, x, y):
self.setValue(self.VALUE)
surf.blit(self.DIESURF, (x, y))
gDiebuttonClass
import pygame
from pygame.locals import *
class simpleButton:
# class that creates button objects
def __init__(self, width, height, color, textColor, label, surf, position):
# define and assign some self values
self.ACTIVE = True
self.HILIGHTED = False
self.LABEL = label
self.SURF = surf
self.POS = position
self.BUTCOLOR = color
self.TEXTCOLOR = textColor
# Generate a greyed-out version of color and a highlighted version of color
self.BUTGREYED = (color[0] * .25, color[1] * .25, color[2] * .25)
self.HIGHLIGHTCOLOR = (color[0] + ((255 - color[0])//2),
color[1] + ((255 - color[1])//2),
color[2] + ((255 - color[2])//2))
# Assign and calulate some size values
self.HEIGHT = height
self.WIDTH = width
self.HWIDTH = self.WIDTH//2
self.RADIUS = self.HEIGHT//2
self.THEIGHT = int(self.HEIGHT * .60)
# Create BUTTONSURF
self.BUTTONSURF = pygame.Surface((self.WIDTH, self.HEIGHT), flags=SRCALPHA, depth=32)
self.BUTTONSURF.fill((0, 0, 0, 0))
def __buttonBG(self, color): # draws the button shape
# Helper Method to create button background
# create square with rounded corners
pygame.draw.circle(self.BUTTONSURF, color, (self.RADIUS, self.RADIUS),
self.RADIUS)
pygame.draw.circle(self.BUTTONSURF, color,
(self.WIDTH - self.RADIUS, self.RADIUS), self.RADIUS)
pygame.draw.rect(self.BUTTONSURF, color,
Rect((self.RADIUS, 0), (self.WIDTH - 2 * self.RADIUS,
self.HEIGHT)))
def __buttonText(self): # places text surface on the button surface
# helper funtion to make text surface and blit on BUTTONSURF
# Set up the Font Object and how to Change Fonts
BUTFONT = pygame.font.SysFont("Sylfaen", self.THEIGHT)
# Render a Text Surface
self.TEXTSURF = BUTFONT.render(self.LABEL, True, self.TEXTCOLOR, None)
w, h = self.TEXTSURF.get_size()
XPOS = (self.WIDTH - w)//2
YPOS = (self.HEIGHT - h)//2
# Draw Text
self.BUTTONSURF.blit(self.TEXTSURF, (XPOS, YPOS))
def clicked(self, MOUSEXY):
yesORno = False
P1 = self.POS
P2 = (P1[0] + self.WIDTH, P1[1] + self.HEIGHT)
yesORno = (self.ACTIVE and P1[0] <= MOUSEXY[0] <= P2[0] and
P1[1] <= MOUSEXY[1] <= P2[1])
return yesORno
def active(self):
self.ACTIVE = True
return True
def inActive(self):
self.ACTIVE = False
return False
def changePos(self, X, Y):
self.POS = (X, Y)
return self.POS
def display_HILIGHTED(self):
self.__buttonBG(self.HIGHLIGHTCOLOR)
self.__buttonText()
self.SURF.blit(self.BUTTONSURF, self.POS)
def displayBut(self):
self.__buttonBG(self.BUTCOLOR)
self.__buttonText()
self.SURF.blit(self.BUTTONSURF, self.POS)
You call score(a) twice so points are added twice.
handresult, handscore, PPOINTS = score(a) # first time
print(score(a)) # second time
it should be
handresult, handscore, PPOINTS = score(a)
print(handresult, handscore, PPOINTS)
Related
I'm not managing to get this math correct, and it's a little bit difficult to explain in words. I have managed to create a isometric grid, which you can select the tiles with the mouse perfectly, and I have managed to implement a camera movement using wasd keys and still get the tiles correctly selected, but there is a slightly bug which I can not figure out where is coming from.
This is what happens, but only sometimes, depend where the camera offset is:
when this happens, it is only on the x axis, and not in every tile.
I'm almost giving up on this cause I can't find the bug, thought of posting here to see if anyone had similar problem.
import time
import pygame
import sys
import math
from os import path
from settings import *
from sprites import *
# ------------------------- SETTINGS ---------------------------- #
# COLORS (r, g, b)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
DARKGREY = (40, 40, 40)
LIGHTGREY = (100, 100, 100)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
RED = (255, 0, 0)
YELLOW = (255, 255, 0)
# game settings
WIDTH = 1024
HEIGHT = 768
FPS = 60
title = "Isometric-Based game"
BGCOLOUR = DARKGREY
TILE_X = 80
TILE_Y = 40
WORLD_X, WORLD_Y = 14, 10
ORIGIN_X, ORIGIN_Y = 5, 1
# Debug
pygame.init()
font = pygame.font.Font(None, 25)
CAMERA_SPEED = 300
def get_info(info_list):
display_surface = pygame.display.get_surface()
for i, key in enumerate(info_list):
text = font.render(str(key) + " : " + str(info_list[key]), True, (255, 255, 255), (0, 0, 0))
text_rect = text.get_rect()
text_rect.y = 20 * i
display_surface.blit(text, text_rect)
# ------------------------- SPRITES ---------------------------- #
class Camera:
def __init__(self, game, x, y):
self.game = game
self.x, self.y = self.game.to_screen(x, y)
self.vx, self.vy = 0, 0
def update(self):
self.get_keys()
self.x += self.vx * self.game.dt
self.y += self.vy * self.game.dt
def get_keys(self):
self.vx, self.vy = 0, 0
keys = pygame.key.get_pressed()
if keys[pygame.K_w]:
self.vy = -CAMERA_SPEED
if keys[pygame.K_s]:
self.vy = CAMERA_SPEED
if keys[pygame.K_a]:
self.vx = -CAMERA_SPEED
if keys[pygame.K_d]:
self.vx = CAMERA_SPEED
if self.vx != 0 and self.vy != 0:
self.vx *= 1.0
self.vy *= 0.50
class MouseSelection:
def __init__(self, game, image):
self.game = game
self.image = image
def update(self):
# get mouse x and y
self.mouse_x, self.mouse_y = pygame.mouse.get_pos()
# get the mouse offset position inside the tile
self.offset_x, self.offset_y = self.mouse_x % TILE_X, self.mouse_y % TILE_Y
self.offset_x += self.game.scroll_x % TILE_X # Add camera scroll to offset
self.offset_y += self.game.scroll_y % TILE_Y
# get the cell number
self.cell_x, self.cell_y = (self.mouse_x // TILE_X), (self.mouse_y // TILE_Y)
self.cell_x += int((self.game.scroll_x // TILE_X)) # Add camera scroll to cell
self.cell_y += int((self.game.scroll_y // TILE_Y))
# get the selected cell in iso grid
self.selected_x = (self.cell_y - ORIGIN_Y) + (self.cell_x - ORIGIN_X)
self.selected_y = (self.cell_y - ORIGIN_Y) - (self.cell_x - ORIGIN_X)
# height and width of a quarter of a tile, select the corner of the tile to nodge to a direction
h, w = TILE_Y / 2, TILE_X / 2
if self.offset_y < (h / w) * (w - self.offset_x):
self.selected_x -= 1
if self.offset_y > (h / w) * self.offset_x + h:
self.selected_y += 1
if self.offset_y < (h / w) * self.offset_x - h:
self.selected_y -= 1
if self.offset_y > (h / w) * (2 * w - self.offset_x) + h:
self.selected_x += 1
# translate the selected cell to world coordinate
self.selectedWorld_x, self.selectedWorld_y = self.game.to_screen(self.selected_x, self.selected_y)
def draw(self):
# Draw the selected tile with the camera scroll offset
self.game.screen.blit(self.image, (self.selectedWorld_x - self.game.scroll_x,
self.selectedWorld_y - self.game.scroll_y))
class SpriteSheet:
def __init__(self, image):
self.image = image
self.frames = []
def get_image(self):
for row in range(2):
for col in range(4):
if row == 0:
image = pygame.Surface((TILE_Y, TILE_Y / 2)).convert_alpha()
image.blit(self.image, (0, 0), (col * TILE_X / 2, row * TILE_Y / 2, TILE_X, TILE_Y))
image = pygame.transform.scale(image, (TILE_X, TILE_Y))
else:
image = pygame.Surface((TILE_Y, TILE_Y)).convert_alpha()
image.blit(self.image, (0, 0), (col * TILE_X / 2, row * TILE_Y / 2, TILE_X, TILE_Y * 2))
image = pygame.transform.scale(image, (TILE_X, TILE_Y * 2))
image.set_colorkey(WHITE)
self.frames.append(image)
return self.frames
# ------------------------- GAME LOOP ---------------------------- #
class Game:
def __init__(self):
pygame.init()
self.screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption(title)
self.clock = pygame.time.Clock()
pygame.key.set_repeat(400, 100)
self.debug = {}
self.sprite_sheet_image = pygame.image.load("isometric_whitebg - Copy.png")
self.index = 1
self.scroll_x, self.scroll_y = 0, 0
def new(self):
# initialize all variables and do all the setup for a new game
self.sprite_sheet = SpriteSheet(self.sprite_sheet_image)
self.tile_selected = self.sprite_sheet.get_image()[0]
self.tiles = self.sprite_sheet.get_image()
self.mouse_selection = MouseSelection(self, self.tile_selected)
self.camera = Camera(self, 1, 1)
def run(self):
# game loop - set self.playing = False to end the game
self.playing = True
while self.playing:
self.dt = self.clock.tick(FPS) / 1000
self.events()
self.update()
self.draw()
def quit(self):
pygame.quit()
sys.exit()
def update(self):
# update portion of the game loop
self.camera.update()
self.mouse_selection.update()
self.mx, self.my = pygame.mouse.get_pos()
# -------------------------------------------------- CAMERA SCROLLING ----------------------------------------#
if self.camera.x - self.scroll_x != WIDTH / 2:
self.scroll_x += (self.camera.x - (self.scroll_x + WIDTH / 2)) / 10
if self.camera.y - self.scroll_y != HEIGHT / 2:
self.scroll_y += (self.camera.y - (self.scroll_y + HEIGHT / 2)) / 10
# -------------------------------------------------- CAMERA SCROLLING ----------------------------------------#
self.debug_info()
def to_screen(self, x, y):
screen_x = (ORIGIN_X * TILE_X) + (x - y) * (TILE_X / 2)
screen_y = (ORIGIN_Y * TILE_Y) + (x + y) * (TILE_Y / 2)
return screen_x, screen_y
def draw_world(self):
for y in range(WORLD_Y):
for x in range(WORLD_X):
vWorld_x, vWorld_y = self.to_screen(x, y)
# Invisible tile
if self.index == 0:
self.screen.blit(self.tiles[1], (vWorld_x, vWorld_y))
# Grass
elif self.index == 1:
self.screen.blit(self.tiles[2], (vWorld_x - self.scroll_x, vWorld_y - self.scroll_y))
def draw(self):
self.screen.fill(BGCOLOUR)
self.draw_world()
self.mouse_selection.draw()
get_info(self.debug)
pygame.display.flip()
def debug_info(self):
self.debug["FPS"] = int(self.clock.get_fps())
self.debug["Cell"] = self.mouse_selection.cell_x, self.mouse_selection.cell_y
self.debug["Selected"] = int(self.mouse_selection.selected_x), int(self.mouse_selection.selected_y)
self.debug["Scroll"] = int(self.scroll_x), int(self.scroll_y)
self.debug["Mouse"] = int(self.mx), int(self.my)
self.debug["Mouse_offset"] = int(self.mouse_selection.offset_x), int(self.mouse_selection.offset_y)
def events(self):
# catch all events here
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
self.quit()
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
pass
game = Game()
while True:
game.new()
game.run()
Define the corner points of the map:
map_outline = [
pygame.math.Vector2(left_x, left_y),
pygame.math.Vector2(top_x, top_y),
pygame.math.Vector2(right_x, right_y,
pygame.math.Vector2(bottom_x, bottom_y)
]
With this information you can calculate the x and y axis of the map:
origin = map_outline[0]
x_axis = (map_outline[1] - map_outline[0]) / columns
y_axis = (map_outline[3] - map_outline[0]) / rows
You can use the x-axis and the y-axis to calculate a point in the map as a function of the row and column:
def transform(p, mat2x2):
x = p[0] * mat2x2[0][0] + p[1] * mat2x2[1][0]
y = p[0] * mat2x2[0][1] + p[1] * mat2x2[1][1]
return pygame.math.Vector2(x, y)
p_position = transform((column + 0.5, row + 0.5), (x_axis, y_axis)) + origin
If you want to get the row and column depending on the mouse cursor, you need to do the opposite. You need to calculate the inverse 2x2 matrix from the x and y axis. Using the inverse matrix, you can calculate the row and column as a function of a point on the map:
def inverseMat2x2(m):
a, b, c, d = m[0].x, m[0].y, m[1].x, m[1].y
det = 1 / (a*d - b*c)
return [(d*det, -b*det), (-c*det, a*det)]
m_pos = pygame.mouse.get_pos()
m_grid_pos = transform(pygame.math.Vector2(m_pos) - origin, point_to_grid)
m_col, m_row = int(m_grid_pos[0]), int(m_grid_pos[1])
Also see PyGameExamplesAndAnswers - Isometric
Minimal example:
replit.com/#Rabbid76/Pygame-IsometircMap
import pygame
pygame.init()
window = pygame.display.set_mode((500, 300))
clock = pygame.time.Clock()
colors = {'g': (40, 128, 40), 'd': (90, 60, 40)}
tilemap = [
'gdddg',
'dgddd',
'ggddg',
'ggddg',
'ddddg',
'dgggd'
]
columns, rows = len(tilemap[0]), len(tilemap)
isometric_tiles = {}
for key, color in colors.items():
tile_surf = pygame.Surface((50, 50), pygame.SRCALPHA)
tile_surf.fill(color)
tile_surf = pygame.transform.rotate(tile_surf, 45)
isometric_size = tile_surf.get_width()
tile_surf = pygame.transform.scale(tile_surf, (isometric_size, isometric_size//2))
isometric_tiles[key] = tile_surf
tile_size = (isometric_size, isometric_size//2)
def tileRect(column, row, tile_size):
x = (column + row) * tile_size[0] // 2
y = ((columns - column - 1) + row) * tile_size[1] // 2
return pygame.Rect(x, y, *tile_size)
game_map = pygame.Surface(((columns+rows) * isometric_size // 2, (columns+rows) * isometric_size // 4), pygame.SRCALPHA)
for column in range(columns):
for row in range(rows):
tile_surf = isometric_tiles[tilemap[row][column]]
tile_rect = tileRect(column, row, tile_size)
game_map.blit(tile_surf, tile_rect)
map_rect = game_map.get_rect(center = window.get_rect().center)
map_outline = [
pygame.math.Vector2(0, columns * isometric_size / 4),
pygame.math.Vector2(columns * isometric_size / 2, 0),
pygame.math.Vector2((columns+rows) * isometric_size // 2, rows * isometric_size / 4),
pygame.math.Vector2(rows * isometric_size / 2, (columns+rows) * isometric_size // 4)
]
for pt in map_outline:
pt += map_rect.topleft
origin = map_outline[0]
x_axis = (map_outline[1] - map_outline[0]) / columns
y_axis = (map_outline[3] - map_outline[0]) / rows
def inverseMat2x2(m):
a, b, c, d = m[0].x, m[0].y, m[1].x, m[1].y
det = 1 / (a*d - b*c)
return [(d*det, -b*det), (-c*det, a*det)]
point_to_grid = inverseMat2x2((x_axis, y_axis))
def transform(p, mat2x2):
x = p[0] * mat2x2[0][0] + p[1] * mat2x2[1][0]
y = p[0] * mat2x2[0][1] + p[1] * mat2x2[1][1]
return pygame.math.Vector2(x, y)
font = pygame.font.SysFont(None, 30)
textO = font.render("O", True, (255, 255, 255))
textX = font.render("X", True, (255, 0, 0))
textY = font.render("Y", True, (0, 255, 0))
p_col, p_row = 2, 2
run = True
while run:
clock.tick(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_a and p_col > 0:
p_col -= 1
if event.key == pygame.K_d and p_col < columns-1:
p_col += 1
if event.key == pygame.K_w and p_row > 0:
p_row -= 1
if event.key == pygame.K_s and p_row < rows-1:
p_row += 1
p_position = transform((p_col + 0.5, p_row + 0.5), (x_axis, y_axis)) + origin
m_pos = pygame.mouse.get_pos()
m_grid_pos = transform(pygame.math.Vector2(m_pos) - origin, point_to_grid)
m_col, m_row = int(m_grid_pos[0]), int(m_grid_pos[1])
window.fill((0, 0, 0))
window.blit(game_map, map_rect)
pygame.draw.lines(window, (164, 164, 164), True, map_outline, 3)
pygame.draw.line(window, (255, 0, 0), origin, origin+x_axis, 3)
pygame.draw.line(window, (0, 255, 0), origin, origin+y_axis, 3)
pygame.draw.circle(window, (255, 255, 255), origin, 5)
pygame.draw.circle(window, (255, 0, 0), origin+x_axis, 5)
pygame.draw.circle(window, (0, 255, 0), origin+y_axis, 5)
window.blit(textO, textO.get_rect(topright = origin+(-5, 5)))
window.blit(textX, textX.get_rect(bottomright = origin+x_axis+(-5, -5)))
window.blit(textY, textX.get_rect(topright = origin+y_axis+(-5, 5)))
pygame.draw.ellipse(window, (255, 255, 0), (p_position[0]-16, p_position[1]-8, 32, 16))
if 0 <= m_grid_pos[0] < columns and 0 <= m_grid_pos[1] < rows:
tile_rect = tileRect(m_col, m_row, tile_size).move(map_rect.topleft)
pts = [tile_rect.midleft, tile_rect.midtop, tile_rect.midright, tile_rect.midbottom]
pygame.draw.lines(window, (255, 255, 255), True, pts, 4)
pygame.display.update()
pygame.quit()
exit()
I'm making a game with pygame and pymunk as a physics engine. I'm trying to kill a bullet whenever it hits a player or goes past its lifetime.
When I tried to space.remove(self.shape) and the second bullet hits the player, it gives me an "AssertionError: shape not in space, already removed. I simply changed it to teleport the bullets away, and then learned of the real error.
When I have more than one bullet in the space and a bullet hits the enemy player, all the current bullets teleport away, which means that when I tried to remove one bullet, it called the remove on all the bullets and thats why I had the initial error.
However the problem still remains that one bullet is being treated as every bullet.
Why is something that should be a non-static variable being called as a static variable?
I even tried to use deepcopy to see if that fixed it, but to no avail
This is my chunk of code, apologies since I don't know what is needed to understand it.
The key parts are most likely the Bullet class, the shoot() function in the Player class, and the drawBulletCollision() function
# PyGame template.
# Import modules.
import sys, random, math, time, copy
from typing import List
import pygame
from pygame.locals import *
from pygame import mixer
import pymunk
import pymunk.pygame_util
from pymunk.shapes import Segment
from pymunk.vec2d import Vec2d
pygame.mixer.pre_init(44110, -16, 2, 512)
mixer.init()
# Set up the window.
width, height = 1440, 640
screen = pygame.display.set_mode((width, height))
bg = pygame.image.load("space.png")
def draw_bg():
screen.blit(bg, (0, 0))
#load sounds
#death_fx = pygame.mixer.Sound("")
#death_fx.set_volume(0.25)
shoot_fx = mixer.Sound("shot.wav")
shoot_fx.set_volume(0.25)
#mixer.music.load("video.mp3")
#mixer.music.play()
#time.sleep(2)
#mixer.music.stop()
#gun_mode_fx = pygame.mixer.Sound("")
#gun_mode_fx.set_volume(0.25)
#thrust_mode_fx = pygame.mixer.Sound("")
#thrust_mode_fx.set_volume(0.25)
collision_fx = mixer.Sound("thump.wav")
collision_fx.set_volume(0.25)
ship_group = pygame.sprite.Group()
space = pymunk.Space()
space.gravity = 0, 0
space.damping = 0.6
draw_options = pymunk.pygame_util.DrawOptions(screen)
bulletList = []
playerList = []
environmentList = []
arbiterList = []
b0 = space.static_body
segmentBot = pymunk.Segment(b0, (0,height), (width, height), 4)
segmentTop = pymunk.Segment(b0, (0,0), (width, 0), 4)
segmentLef = pymunk.Segment(b0, (width,0), (width, height), 4)
segmentRit = pymunk.Segment(b0, (0,0), (0, height), 4)
walls = [segmentBot,segmentLef,segmentRit,segmentTop]
for i in walls:
i.elasticity = 1
i.friction = 0.5
i.color = (255,255,255,255)
environmentList.append(i)
class Player(object):
radius = 30
def __init__(self, position, space, color):
self.body = pymunk.Body(mass=5,moment=10)
self.mode = 0 # 0 is gun, 1 is thrust, ? 2 is shield
self.body.position = position
self.shape = pymunk.Circle(self.body, radius = self.radius)
#self.image
#self.shape.friction = 0.9
self.shape.elasticity= 0.2
space.add(self.body,self.shape)
self.angleGun = 0
self.angleThrust = 0
self.health = 100
self.speed = 500
self.gearAngle = 0
self.turningSpeed = 5
self.shape.body.damping = 1000
self.cooldown = 0
self.fireRate = 30
self.shape.collision_type = 1
self.shape.color = color
playerList.append(self)
def force(self,force):
self.shape.body.apply_force_at_local_point(force,(0,0))
def rocketForce(self):
radians = self.angleThrust * math.pi/180
self.shape.body.apply_force_at_local_point((-self.speed * math.cos(radians),-self.speed * math.sin(radians)),(0,0))
def draw(self):
gear = pygame.image.load("gear.png")
gearBox = gear.get_rect(center=self.shape.body.position)
gearRotated = pygame.transform.rotate(gear, self.gearAngle)
#gearRotated.rect.center=self.shape.body.position
x,y = self.shape.body.position
radianGun = self.angleGun * math.pi/180
radianThrust = self.angleThrust * math.pi/180
radiyus = 30 *(100-self.health)/100
screen.blit(gearRotated,gearBox)
self.gearAngle += 1
if radiyus == 30:
radiyus = 32
pygame.draw.circle(screen,self.shape.color,self.shape.body.position,radiyus,0)
pygame.draw.circle(screen,(0,0,0),self.shape.body.position,radiyus,0)
pygame.draw.line(
screen,(0,255,0),
(self.radius * math.cos(radianGun) * 1.5 + x,self.radius * math.sin(radianGun) * 1.5 + y),
(x,y), 5
)
pygame.draw.line(
screen,(200,200,0),
(self.radius * math.cos(radianThrust) * 1.5 + x,self.radius * math.sin(radianThrust) * 1.5 + y),
(x,y), 5
)
#more
def targetAngleGun(self,tAngle):
tempTAngle = tAngle - self.angleGun
tempTAngle = tempTAngle % 360
if(tempTAngle < 180 and not tempTAngle == 0):
self.angleGun -= self.turningSpeed
elif(tempTAngle >= 180 and not tempTAngle == 0):
self.angleGun += self.turningSpeed
self.angleGun = self.angleGun % 360
#print(tAngle, "target Angle")
#print(self.angleGun, "selfangleGun")
#print(tempTAngle, "tempTAngle")
def targetAngleThrust(self,tAngle):
tempTAngle = tAngle - self.angleThrust
tempTAngle = tempTAngle % 360
if(tempTAngle < 180 and not tempTAngle == 0):
self.angleThrust -= self.turningSpeed
elif(tempTAngle >= 180 and not tempTAngle == 0):
self.angleThrust += self.turningSpeed
self.angleThrust = self.angleThrust % 360
#print(tAngle, "target Angle")
#print(self.angleThrust, "selfangleGun")
#print(tempTAngle, "tempTAngle")
def targetAngle(self,tAngle):
if(self.mode == 0):
self.targetAngleGun(tAngle)
elif(self.mode == 1):
self.targetAngleThrust(tAngle)
def shoot(self):
if(self.cooldown == self.fireRate):
x,y = self.shape.body.position
radianGun = self.angleGun * math.pi/180
spawnSpot = (self.radius * math.cos(radianGun) * 1.5 + x,self.radius * math.sin(radianGun)*1.5+y)
self.shape.body.apply_impulse_at_local_point((-20 * math.cos(radianGun),-20 * math.sin(radianGun)),(0,0))
print(spawnSpot)
bT = Bullet(spawnSpot, 5, 50,self.shape.color)
b = copy.deepcopy(bT)
bulletList.append(b)
space.add(b.shape,b.shape.body)
b.getShot(self.angleGun)
self.cooldown = 0
print('pew')
shoot_fx.play()
# HEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEREEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
def tick(self):
self.draw()
if(self.cooldown < self.fireRate):
self.cooldown += 1
#for o in playerList:
# c = self.shape.shapes_collide(o.shape)
# if(len(c.points)>0):
# self.damage(c.points[0].distance/10)
for o in bulletList:
c = self.shape.shapes_collide(o.shape)
#print(c)
for o in walls:
c = self.shape.shapes_collide(o)
if(len(c.points)>0):
self.damage(c.points[0].distance * 3)
def damage(self, damage):
self.health -= abs(damage)
if self.health < 0:
self.health = 0
#maybe make it part of the player class
def drawWallCollision(arbiter, space, data):
for c in arbiter.contact_point_set.points:
r = max(3, abs(c.distance * 5))
r = int(r)
p = tuple(map(int, c.point_a))
pygame.draw.circle(data["surface"], pygame.Color("red"), p, r, 0)
print('magnitude', math.sqrt(arbiter.total_impulse[0]**2 + arbiter.total_impulse[1]**2))
#print('position', p)
#print(data)
print("its all arbitrary")
s1, s2 = arbiter.shapes
collision_fx.play()
def drawBulletCollision(arbiter, space, data):
s1, s2 = arbiter.shapes
for c in arbiter.contact_point_set.points:
magnitude = math.sqrt(arbiter.total_impulse[0]**2 + arbiter.total_impulse[1]**2)
for p in playerList:
avr = ((c.point_a[0] + c.point_b[0])/2, (c.point_a[1] + c.point_b[1])/2)
distance = (math.sqrt((avr[0] - p.shape.body.position[0]) **2 + (avr[1] - p.shape.body.position[1]) **2 ))
if(distance < Bullet.explosionRadius + Player.radius):
if not(s1.color == s2.color):
p.damage(magnitude)
for b in bulletList:
avr = ((c.point_a[0] + c.point_b[0])/2, (c.point_a[1] + c.point_b[1])/2)
distance = (math.sqrt((avr[0] - p.shape.body.position[0]) **2 + (avr[1] - p.shape.body.position[1]) **2 ))
if(distance < Bullet.explosionRadius + Player.radius):
if not(s1.color == s2.color):
b.damage(magnitude)
pygame.draw.circle(data["surface"], pygame.Color("red"), tuple(map(int, c.point_a)), 10, 0)
print('magnitude', magnitude)
#print('position', p)
#print(data)
print("its all arbitrary")
def drawArbitraryCollision(arbiter, space, data):
collision_fx.play()
class Ship(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("gear.png")
self.rect = self.image.get_rect()
self.rect.center = [x, y]
def rotate(self):
self.image = pygame.transform.rotate(self.image,1)
class Bullet(object):
damage = 2
explosionRadius = 5
def __init__(self, position, size, speed,color):
pts = [(-size, -size), (size, -size), (size, size), (-size, size)]
self.body = copy.deepcopy(pymunk.Body(mass=0.1,moment=1))
self.shape = copy.deepcopy(pymunk.Poly(self.body, pts))
self.shape.body.position = position
self.shape.friction = 0.5
self.shape.elasticity = 1
self.shape.color = color
self.speed = speed
self.size = size
self.shape.collision_type = 2
#space.add(self.body,self.shape)
#bulletList.append(self)
self.lifetime = 0
def getShot(self,angle):
radians = angle * math.pi/180
self.shape.body.apply_impulse_at_local_point((self.speed * math.cos(radians),self.speed * math.sin(radians)),(0,0))
def tick(self):
self.lifetime += 1
if(self.lifetime > 300):
self.shape.body.position = (10000,30)
def damage(self, damage):
self.lifetime = 300
#VELOCITY OF BULLET STARTS WITH VELOCITY OF PLAYER
#MAKE VOLUME OF SOUND DEPEND ON THE IMPULSE FOR THE IMPACTS
#error on purpose so you notice this
#INSTANCES NOT WORKING????
def runPyGame():
# Initialise PyGame.
pygame.init()
# Set up the clock. This will tick every frame and thus maintain a relatively constant framerate. Hopefully.
fps = 60.0
fpsClock = pygame.time.Clock()
running = True
font = pygame.font.SysFont("Arial", 16)
p1 = Player((240,240),space,(132, 66, 245,255))
p2 = Player((1200,400),space,(47, 247, 184,255))
space.add(segmentBot,segmentTop,segmentLef,segmentRit)
# Main game loop.
ch = space.add_collision_handler(1, 0)
ch.data["surface"] = screen
ch.post_solve = drawWallCollision
ch = space.add_collision_handler(1, 2)
ch.data["surface"] = screen
ch.post_solve = drawBulletCollision
ch = space.add_collision_handler(0, 2)
ch.data["surface"] = screen
ch.post_solve = drawArbitraryCollision
dt = 1/fps # dt is the time since last frame.
while True: # Loop forever!
keys = pygame.key.get_pressed()
for event in pygame.event.get():
# We need to handle these events. Initially the only one you'll want to care
# about is the QUIT event, because if you don't handle it, your game will crash
# whenever someone tries to exit.
if event.type == QUIT:
pygame.quit() # Opposite of pygame.init
sys.exit() # Not including this line crashes the script on Windows.
if event.type == KEYDOWN:
if event.key == pygame.K_s:
p1.mode = -(p1.mode - 0.5) + 0.5
print(p1.mode)
if (event.key == pygame.K_k and p1.mode == 0):
p1.shoot()
if event.key == pygame.K_KP_5:
p2.mode = -(p2.mode - 0.5) + 0.5
print(p2.mode)
if (event.key == pygame.K_m and p2.mode == 0):
p2.shoot()
#b = Bullet((200,200),51,51)
if(keys[K_w]):
p1.targetAngle(90)
if(keys[K_q]):
p1.targetAngle(45)
if(keys[K_a]):
p1.targetAngle(0)
if(keys[K_z]):
p1.targetAngle(315)
if(keys[K_x]):
p1.targetAngle(270)
if(keys[K_c]):
p1.targetAngle(225)
if(keys[K_d]):
p1.targetAngle(180)
if(keys[K_e]):
p1.targetAngle(135)
if(keys[K_k] and p1.mode == 1):
p1.rocketForce()
if(keys[K_KP_8]):
p2.targetAngle(90)
if(keys[K_KP_7]):
p2.targetAngle(45)
if(keys[K_KP_4]):
p2.targetAngle(0)
if(keys[K_KP_1]):
p2.targetAngle(315)
if(keys[K_KP_2]):
p2.targetAngle(270)
if(keys[K_KP_3]):
p2.targetAngle(225)
if(keys[K_KP_6]):
p2.targetAngle(180)
if(keys[K_KP_9]):
p2.targetAngle(135)
if(keys[K_m] and p2.mode == 1):
p2.rocketForce()
# Handle other events as you wish.
screen.fill((250, 250, 250)) # Fill the screen with black.
# Redraw screen here.
### Draw stuff
draw_bg()
space.debug_draw(draw_options)
for i in playerList:
i.tick()
screen.blit(
font.render("P1 Health: " + str(p1.health), True, pygame.Color("white")),
(50, 10),
)
screen.blit(
font.render("P2 Health: " + str(p2.health), True, pygame.Color("white")),
(50, 30),
)
for i in bulletList:
i.tick()
ship_group.draw(screen)
# Flip the display so that the things we drew actually show up.
pygame.display.update()
dt = fpsClock.tick(fps)
space.step(0.01)
pygame.display.update()
runPyGame()
I cant point to the exact error since the code is quite long and depends on files I dont have. But here is a general advice for troubleshooting:
Try to give a name to each shape when you create them, and then print it out. Also print out the name of each shape that you add or remove from the space. This should show which shape you are actually removing and will probably make it easy to understand whats wrong.
For example:
...
self.shape = pymunk.Circle(self.body, radius = self.radius)
self.shape.name = "circle 1"
print("Created", self.shape.name)
...
print("Adding", self.shape.name)
space.add(self.body,self.shape)
...
(Note that you need to reset the name of shapes you copy, since otherwise the copy will have the same name.)
I'm new to programming and I'm struggling to figure out how to get this to work. I'm trying to build a simple game called "Pet pandemic" and you basically just press start and the "pets" marked by different colored dots roam around on a grid in the window. Some of the pets spawn in with the "virus". While roaming the pets will see if they are within a certain distance from one another and if so they will transmit the virus to the other who doesn't have it already, in turn updating the status of that pet to have the "virus" and there dot image will update to be red. The game will run until every "pet" has the "virus". I'm struggling to implement a way to spawn the "pets" with unique names like "Alex" or "Doug". I would like to use a list of names I have that's in a .csv file for this.
Thank you for your time.
Here are the files:
https://drive.google.com/drive/folders/1tjEY6Eo1nKKtEr0st1CUFkcnBvvbiMn1?usp=sharing
import pygame
import random
import math
import time
# Window settings
WIDTH = 960
HEIGHT = 660
TITLE = "PET PANDEMIC"
FPS = 60
#create window
pygame.init()
screen = pygame.display.set_mode([WIDTH, HEIGHT])
pygame.display.set_caption(TITLE)
clock = pygame.time.Clock()
#Game Stages
START = 0
PLAYING = 1
END = 2
#Define colors
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
BLUE = (132, 201, 217)
# Load fonts
title_font = default_font = pygame.font.Font("fonts/recharge bd.ttf", 60)
default_font = pygame.font.Font(None, 55)
# Load images
has_v_img = pygame.image.load("red_dot.png").convert_alpha()
no_v_img = pygame.image.load("grey_dot.png").convert_alpha()
no_v_mask_img = pygame.image.load("black_dot.png").convert_alpha()
#Game classes
class Pet(pygame.sprite.Sprite):
def __init__(self, name, x, y):
super().__init__()
self.wearing_mask = random.randint(0, 1) # 0 = no, 1 = yes.
self.has_virus = random.randint(0, 6) # 6 = Virus
if self.has_virus == 6:
self.image = has_v_img
elif self.wearing_mask != 1 and self.has_virus != 6:
self.image = no_v_mask_img
else:
self.image = no_v_img
self.rect = self.image.get_rect()
self.rect.center = x, y
self.name = name
self.dir = random.randint(0, 3)
self.is_alive = True
self.print_name()
def print_name(self):
amnt_w_virus = 0
if self.has_virus == 6:
print("Spawned {} ".format(self.name) + "With The Virus!")
amnt_w_virus += 1
else:
print("Spawned {}.".format(self.name))
return amnt_w_virus
def check_distance(self, other):
distance = math.sqrt(((self.x - other.x) ** 2) + ((self.y - other.y) ** 2))
if distance < 6 and self.has_virus == 6:
other.has_virus = 6
print(self.name + " Was In Range Of " + other.name + " And Gave Them The Virus.")
amnt_w_virus += 1
else:
return amnt_w_virus
def roam(self):
while game_running:
if self.is_alive == True:
time.sleep(1.5)
self.dir = random.randint(0, 3)
self.move()
def move(self):
if self.dir == 0:
self.rect.y += 1
elif self.dir == 1:
self.rect.x += 1
elif self.dir == 2:
self.rect.y -= 1
elif self.dir == 3:
self.rect.x -= 1
if self.rect.left < 0:
self.rect.left = 0
elif self.rect.top > HEIGHT:
self.rect.top = HEIGHT
elif self.rect.right > WIDTH:
self.rect.right = WIDTH
print(self.name + " Moved Forward In Direction " + str(self.dir) + " (" + str(self.x) + "," + str(self.y) + ").")
class Players(pygame.sprite.Group):
def __init__(self, *sprites):
super().__init__(*sprites)
def update(self, *args):
super().update(*args)
self.check_distance()
self.roam()
# Setup
def new_game():
global players
#Random Spawn Location Inside Window
start_x = random.randint(0,WIDTH)
start_y = random.randint(0,HEIGHT)
#Open List Of Names To Use For The Pets
f = open("names.csv", "r")
reader = csv.reader(f)
name = []
for row in reader:
name.append(row)
pet = {}
#Here Im trying to spawn the pets and assign them unique names from the list but this code is all messed up
for item in name:
name = '{}'.format(item)
pet[name] = pet.get(name, Pet(name=name))
pets = Pet([name], start_x, start_y)
#making players = a sprite group of all the pets
players = Players(pets)
#trying to calculate the number of pets without the virus
players.amount_alive = len(players) - amnt_w_virus
print(players.amnt_alive)
#grid overlay
def draw_grid(width, height, scale):
for x in range(0, WIDTH, scale):
pygame.draw.line(screen, WHITE, [x, 0], [x, HEIGHT], 1)
for y in range(0, HEIGHT, scale):
pygame.draw.line(screen, WHITE, [0, y], [WIDTH, y], 1)
def display_stats():
infected_text = default_font.render("Infected: " + str(amnt_w_virus), True, WHITE)
rect = infected_text.get_rect()
rect.top = 20
rect.left = 20
screen.blit(infected_text, rect)
non_infected_text = default_font.render("Non-Infected: " + str(players.amount_alive), True, WHITE)
rect = non_infected_text.get_rect()
rect.top = 20
rect.right = WIDTH - 20
screen.blit(non_infected_text, rect)
time_text = default_font.render("Time: " + str(time.time), True, WHITE)
rect = time_text.get_rect()
rect.bottom = HEIGHT - 20
rect.left = 20
screen.blit(time_text, rect)
def start_screen():
screen.fill(BLACK)
title_text = title_font.render(TITLE, True, WHITE)
rect = title_text.get_rect()
rect.centerx = WIDTH // 2
rect.bottom = HEIGHT // 2 - 15
screen.blit(title_text, rect)
sub_text = default_font.render("Press Any Key To Start The Spread", True, WHITE)
rect = sub_text.get_rect()
rect.centerx = WIDTH // 2
rect.top = HEIGHT // 2 + 15
screen.blit(sub_text, rect)
def end_screen():
end_text = default_font.render("GAME OVER, EVERYONE IS INFECTED.", True, WHITE)
rect = end_text.get_rect()
rect.centerx = WIDTH // 2
rect.centery = HEIGHT // 2
screen.blit(end_text, rect)
# Game loop
new_game()
stage = START
running = True
while running:
# Input handling
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if stage == START:
stage = PLAYING
elif stage == END:
if event.key == pygame.K_r:
new_game()
stage = START
# Game logic
if stage != START:
players.update()
if len(players) == 0:
stage = END
# Drawing Code
screen.fill(BLUE)
draw_grid(960, 660, 20)
players.draw(screen)
display_stats()
pygame.display.flip()
if stage == START:
start_screen()
elif stage == END:
end_screen()
# Update screen
pygame.display.update()
# Limit refresh rate of game loop
clock.tick(FPS)
# Close window and quit
pygame.quit() ```
You are overwriting the object called name:
for item in name:
name = '{}'.format(item) ### BAD BAD BAD BAD BAD
pet[name] = pet.get(name, Pet(name=name))
pets = Pet([name], start_x, start_y)
#making players = a sprite group of all the pets
players = Players(pets)
If you actually wanted to do that then you need to preserve the items in name by converting it to a list.
for item in list(name):
name = '{}'.format(item)
pet[name] = pet.get(name, Pet(name=name))
pets = Pet([name], start_x, start_y)
#making players = a sprite group of all the pets
players = Players(pets)
I'm sure that you didn't actually want to do that though so just use a different variable name (e.g. _name).
for item in name:
_name = '{}'.format(item)
pet[_name] = pet.get(_name, Pet(name=_name))
pets = Pet([_name], start_x, start_y)
#making players = a sprite group of all the pets
players = Players(pets)
So I want it to count the score every time the snake eats a candy.
I haven't tried much, but I tried to find existing codes and adding them to mine but that just broke the game. I also tried to make my own score board by watching a tutorial, but I don't know where the code should go like at the beginning or end.
import pygame
import random
score = 0
welcome = ("Welcome to our snake game")
print(welcome)
class cube:
height = 20
w = 500
def __init__(movee,start,x=1,y=0,color=(0,0,0)):
movee.pos = start
movee.x = 1
movee.y = 0
movee.color = color
def move(movee, x, y):
movee.x = x
movee.y = y
movee.pos = (movee.pos[0] + movee.x, movee.pos[1] + movee.y)
def draw(movee, surface, eyes=False):
leng = movee.w // movee.height
i = movee.pos[0]
j = movee.pos[1]
pygame.draw.rect(surface, movee.color, (i*leng+1,j*leng+1, leng-2, leng-2))
class snake:
body = []
turns = {}
def __init__(movee, color, pos):
movee.color = color
movee.head = cube(pos)
movee.body.append(movee.head)
def move(movee):
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
keys = pygame.key.get_pressed()
for key in keys:
if keys[pygame.K_LEFT]:
movee.x = -1
movee.y = 0
movee.turns[movee.head.pos[:]] = [movee.x, movee.y]
elif keys[pygame.K_RIGHT]:
movee.x = 1
movee.y = 0
movee.turns[movee.head.pos[:]] = [movee.x, movee.y]
elif keys[pygame.K_UP]:
movee.x = 0
movee.y = -1
movee.turns[movee.head.pos[:]] = [movee.x, movee.y]
elif keys[pygame.K_DOWN]:
movee.x = 0
movee.y = 1
movee.turns[movee.head.pos[:]] = [movee.x, movee.y]
for i, c in enumerate(movee.body):
p = c.pos[:]
if p in movee.turns:
turn = movee.turns[p]
c.move(turn[0],turn[1])
if i == len(movee.body)-1:
movee.turns.pop(p)
else:
if c.x == -1 and c.pos[0] <= 0: c.pos = (c.height-1, c.pos[1])
elif c.x == 1 and c.pos[0] >= c.height-1: c.pos = (0,c.pos[1])
elif c.y == 1 and c.pos[1] >= c.height-1: c.pos = (c.pos[0], 0)
elif c.y == -1 and c.pos[1] <= 0: c.pos = (c.pos[0],c.height-1)
else: c.move(c.x,c.y)
def add(movee):
tail = movee.body[-1]
dx, dy = tail.x, tail.y
if dx == 1 and dy == 0:
movee.body.append(cube((tail.pos[0]-1,tail.pos[1])))
elif dx == -1 and dy == 0:
movee.body.append(cube((tail.pos[0]+1,tail.pos[1])))
elif dx == 0 and dy == 1:
movee.body.append(cube((tail.pos[0],tail.pos[1]-1)))
elif dx == 0 and dy == -1:
movee.body.append(cube((tail.pos[0],tail.pos[1]+1)))
movee.body[-1].x = dx
movee.body[-1].y = dy
def draw(movee, surface):
for i, c in enumerate(movee.body):
if i ==0:
c.draw(surface, True)
else:
c.draw(surface)
def drawingAGrid(w, height, surface):
sizein = w // height
x = 0
y = 0
for l in range(height):
x = x + sizein
y = y + sizein
def redrawGrid(surface):
global height, width, s, snack
surface.fill((255,255,255))
s.draw(surface)
snack.draw(surface)
drawingAGrid(width, height, surface)
pygame.display.update()
def Candy(height, item):
positions = item.body
while True:
x = random.randrange(height)
y = random.randrange(height)
if len(list(filter(lambda z:z.pos == (x,y), positions))) > 0:
continue
else:
break
return (x,y)
def gameloop():
global width, height, s, snack, x_pos, y_pos, reset
width = 500
height = 20
win = pygame.display.set_mode((width, width))
s = snake((255, 0, 0), (10, 10))
snack = cube(Candy(height, s), color=(0, 0, 0))
flag = True
clock = pygame.time.Clock()
x_pos, y_pos = s.body[0].pos
while flag:
pygame.time.delay(50)
clock.tick(7)
s.move()
x, y = s.body[0].pos
if not -1 <= x - x_pos <= 1 or not -1 <= y - y_pos <= 1:
movee.reset((10,10))
x_pos, y_pos = s.body[0].pos
if s.body[0].pos == snack.pos:
s.add()
snack = cube(Candy(height, s), color=(0, 0, 0))
redrawGrid(win)
gameloop()
I just want like a scoreboard in any of the corners counting the score.
Use pygame.freetype to render text. e,g, crated a pygame.freetype.SysFont object:
import pygame.freetype
pygame.init()
font = pygame.freetype.SysFont('Times New Roman', 30)
The score is the number of body parts. Use str to convert a number to a text and .render() to render a text to a pygame.Surface object:
score = len(s.body)
text_surf, text_rect = font.render(str(score), (255, 0, 0), size=30)
Define a margin to the border of the window, calculate the text position (e.g. bottom right) and .blit the text to the window surfrace:
margin = 10
text_pos = (width - text_rect.width - margin, width - text_rect.height - margin)
surface.blit(text_surf, text_pos)
Function redrawGrid:
def redrawGrid(surface):
global height, width, s, snack
surface.fill((255,255,255))
s.draw(surface)
snack.draw(surface)
drawingAGrid(width, height, surface)
score = len(s.body)
text_surf, text_rect = font.render(str(score), (255, 0, 0), size=30)
margin = 10
text_pos = (width - text_rect.width - margin, width - text_rect.height - margin)
surface.blit(text_surf, text_pos)
pygame.display.update()
Here is a function from my program, it called when a key is pressed. What is supposed to happen is the key is pressed and a corresponding note is played, and a sine wave appears on the screen also. The sound plays fine, so I won't post any more code for the sound, but it is just the visual side of things that don't work, why won't this wave show?
WINDOWWIDTH = 640 # width of the program's window, in pixels
WINDOWHEIGHT = 480 # height in pixels
WIN_CENTERX = int(WINDOWWIDTH / 2) # the midpoint for the width of the window
WIN_CENTERY = int(WINDOWHEIGHT / 2) # the midpoint for the height of the window
DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
fontObj = pygame.font.SysFont('freesansbold.ttf', 16)
FPSCLOCK = pygame.time.Clock()
# set up a bunch of constants
BLUE = ( 0, 0, 255)
WHITE = (255, 255, 255)
DARKRED = (128, 0, 0)
DARKBLUE = ( 0, 0, 128)
RED = (255, 0, 0)
GREEN = ( 0, 255, 0)
DARKGREEN = ( 0, 128, 0)
YELLOW = (255, 255, 0)
DARKYELLOW = (128, 128, 0)
BLACK = ( 0, 0, 0)
BGCOLOR = WHITE
FPS = 160 # frames per second to run at
pause = False
# making text Surface and Rect objects for various labels
sinLabelSurf = fontObj.render('sine', True, RED, BGCOLOR)
squareLabelSurf = fontObj.render('square', True, BLUE, BGCOLOR)
sinLabelRect = sinLabelSurf.get_rect()
squareLabelRect = squareLabelSurf.get_rect()
def MakeSineWave(freq=1000):
#### visual part ####
xPos = 0
step = 0
AMPLITUDE = 80 # how many pixels tall the waves with rise/fall.
posRecord = {'sin': [], 'line': []}
yPos = -1 * math.sin(step) * AMPLITUDE
posRecord['sin'].append((int(xPos), int(yPos) + WIN_CENTERY))
# draw the sine ball and label
pygame.draw.circle(DISPLAYSURF, DARKRED, (int(xPos), int(yPos) + WIN_CENTERY), 10)
sinLabelRect.center = (int(xPos), int(yPos) + WIN_CENTERY + 20)
DISPLAYSURF.blit(sinLabelSurf, sinLabelRect)
# draw the waves from the previously recorded ball positions
for x, y in posRecord['sin']:
pygame.draw.circle(DISPLAYSURF, DARKRED, (x, y), 4)
# draw the border
pygame.draw.rect(DISPLAYSURF, BLACK, (0, 0, WINDOWWIDTH, WINDOWHEIGHT), 1)
pygame.display.update()
FPSCLOCK.tick(FPS)
if not pause:
xPos += 0.5
if xPos > WINDOWWIDTH:
xPos = 0
posRecord = {'sin': []}
step = 0
else:
step += 0.008
#### audial part ####
return MakeSound(SineWave(freq))
You run MakeSineWave only once - when button is pressed - but code which draws wave have to be run all the time in all loop. It draws longer wave in every loop.
It seems you ask in another question how to draw all wave and move only red ball - and answer need differen changes in MakeSineWave then changes for this question.
EDIT: It is working code - but there is a mess - it needs less code directly in mainloop but more code in some new functions.
import pygame
from pygame.locals import *
import math
import numpy
#----------------------------------------------------------------------
# functions
#----------------------------------------------------------------------
def SineWave(freq=1000, volume=16000, length=1):
num_steps = length * SAMPLE_RATE
s = []
for n in range(num_steps):
value = int(math.sin(n * freq * (6.28318/SAMPLE_RATE) * length) * volume)
s.append( [value, value] )
return numpy.array(s)
#-------------------
def SquareWave(freq=1000, volume=100000, length=1):
num_steps = length * SAMPLE_RATE
s = []
length_of_plateau = int( SAMPLE_RATE / (2*freq) )
print num_steps, length_of_plateau
counter = 0
state = 1
for n in range(num_steps):
value = state * volume
s.append( [value, value] )
counter += 1
if counter == length_of_plateau:
counter = 0
state *= -1
return numpy.array(s)
#-------------------
def MakeSound(arr):
return pygame.sndarray.make_sound(arr)
#-------------------
def MakeSquareWave(freq=1000):
return MakeSound(SquareWave(freq))
#-------------------
def MakeSineWave(freq=1000):
return MakeSound(SineWave(freq))
#-------------------
def DrawSineWave():
# sine wave
yPos = -1 * math.sin(step) * AMPLITUDE
posRecord['sin'].append((int(xPos), int(yPos) + WIN_CENTERY))
if showSine:
# draw the sine ball and label
pygame.draw.circle(screen, RED, (int(xPos), int(yPos) + WIN_CENTERY), 10)
sinLabelRect.center = (int(xPos), int(yPos) + WIN_CENTERY + 20)
screen.blit(sinLabelSurf, sinLabelRect)
# draw the waves from the previously recorded ball positions
if showSine:
for x, y in posRecord['sin']:
pygame.draw.circle(screen, DARKRED, (x, y), 4)
#-------------------
def DrawSquareWave():
# square wave
posRecord['square'].append((int(xPos), int(yPosSquare) + WIN_CENTERY))
if showSquare:
# draw the square ball and label
pygame.draw.circle(screen, GREEN, (int(xPos), int(yPosSquare) + WIN_CENTERY), 10)
squareLabelRect.center = (int(xPos), int(yPosSquare) + WIN_CENTERY + 20)
screen.blit(squareLabelSurf, squareLabelRect)
# draw the waves from the previously recorded ball positions
if showSquare:
for x, y in posRecord['square']:
pygame.draw.circle(screen, BLUE, (x, y), 4)
#----------------------------------------------------------------------
# constants - (uppercase name)
#----------------------------------------------------------------------
# set up a bunch of constants
WHITE = (255, 255, 255)
DARKRED = (128, 0, 0)
RED = (255, 0, 0)
BLACK = ( 0, 0, 0)
GREEN = ( 0, 255, 0)
BLUE = ( 0, 0, 255)
BGCOLOR = WHITE
WINDOWWIDTH = 1200 # width of the program's window, in pixels
WINDOWHEIGHT = 720 # height in pixels
WIN_CENTERX = int(WINDOWWIDTH / 2) # the midpoint for the width of the window
WIN_CENTERY = int(WINDOWHEIGHT / 2) # the midpoint for the height of the window
FPS = 160 # frames per second to run at
AMPLITUDE = 80 # how many pixels tall the waves with rise/fall.
#-------------------
SAMPLE_RATE = 22050 ## This many array entries == 1 second of sound.
SINE_WAVE_TYPE = 'Sine'
SQUARE_WAVE_TYPE = 'Square'
#----------------------------------------------------------------------
# main program
#----------------------------------------------------------------------
#-------------------
# variables (which don't depend on pygame)
#-------------------
sound_types = {SINE_WAVE_TYPE:SQUARE_WAVE_TYPE, SQUARE_WAVE_TYPE:SINE_WAVE_TYPE}
current_type = SINE_WAVE_TYPE
current_played = { 'z': None, 'c': None }
current_drawn = None
#-------------------
# variables that track visibility modes
showSine = True
showSquare = True
xPos = 0
step = 0 # the current input f
posRecord = {'sin': [], 'square': []} # keeps track of the ball positions for drawing the waves
yPosSquare = AMPLITUDE # starting position
#-------------------
# start program
#-------------------
pygame.init()
screen = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT), pygame.HWSURFACE | pygame.DOUBLEBUF)
pygame.display.set_caption('Nibbles!')
# making text Surface and Rect objects for various labels
pygame.display.set_caption('Trig Waves')
fontObj = pygame.font.Font('freesansbold.ttf', 16)
### HERE
squareLabelSurf = fontObj.render('square', True, BLUE, BGCOLOR)
squareLabelRect = squareLabelSurf.get_rect()
sinLabelSurf = fontObj.render('sine', True, RED, BGCOLOR)
sinLabelRect = sinLabelSurf.get_rect()
#-------------------
# mainloop
#-------------------
fps_clock = pygame.time.Clock()
_running = True
while _running:
#-------------------
# events
#-------------------
for event in pygame.event.get():
if event.type == pygame.QUIT:
_running = False
# some keys don't depend on `current_type`
elif event.type == KEYDOWN:
if event.key == K_ESCAPE:
_running = False
if event.key == K_RETURN:
current_type = sound_types[current_type] #Toggle
print 'new type:', current_type
# some keys depend on `current_type`
if current_type == SINE_WAVE_TYPE:
if event.type == KEYDOWN:
#lower notes DOWN
if event.key == K_z:
print current_type, 130.81
current_played['z'] = MakeSineWave(130.81)
current_played['z'].play()
current_drawn = DrawSineWave
elif event.key == K_c:
print current_type, 180.81
current_played['c'] = MakeSineWave(180.81)
current_played['c'].play()
current_drawn = DrawSineWave
elif event.type == KEYUP:
#lower notes UP
if event.key == K_z:
current_played['z'].fadeout(350)
current_drawn = None
#sine - reset data
xPos = 0
posRecord['sin'] = []
step = 0
elif event.key == K_c:
current_played['c'].fadeout(350)
current_drawn = None
#sine - reset data
xPos = 0
posRecord['sin'] = []
step = 0
elif current_type == SQUARE_WAVE_TYPE:
if event.type == KEYDOWN:
#lower notes DOWN
if event.key == K_z:
print current_type, 130.81
current_played['z'] = MakeSquareWave(130.81)
current_played['z'].play()
current_drawn = DrawSquareWave
elif event.key == K_c:
print current_type, 180.81
current_played['c'] = MakeSquareWave(180.81)
current_played['c'].play()
current_drawn = DrawSquareWave
elif event.type == KEYUP:
#lower notes UP
if event.key == K_z:
current_played['z'].fadeout(350)
current_drawn = None
# square - reset data
xPos = 0
yPosSquare = AMPLITUDE
posRecord['square'] = []
step = 0
elif event.key == K_c:
current_played['c'].fadeout(350)
current_drawn = None
# square - reset data
xPos = 0
yPosSquare = AMPLITUDE
posRecord['square'] = []
step = 0
#-------------------
# draws
#-------------------
# fill the screen to draw from a blank state
screen.fill(BGCOLOR)
if current_drawn:
current_drawn()
pygame.display.update()
#-------------------
# moves
#-------------------
if current_drawn:
xPos += 1.0 #0.5
if xPos > WINDOWWIDTH:
#sine ### HERE
xPos = 0
posRecord['sin'] = []
step = 0
# square ### HERE
yPosSquare = AMPLITUDE
posRecord['square'] = []
else:
#sine ### HERE
step += 0.008
#step %= 2 * math.pi
# square ### HERE
# jump top and bottom every 100 pixels
if xPos % 100 == 0:
yPosSquare *= -1
# add vertical line
for x in range(-AMPLITUDE, AMPLITUDE):
posRecord['square'].append((int(xPos), int(x) + WIN_CENTERY))
#-------------------
# FPS
#-------------------
fps_clock.tick(FPS)
#-------------------
# end program
#-------------------
pygame.quit()
#----------------------------------------------------------------------