Pygame.update does not update after each round - python

I want to explosion to occur instantly or very fast. Is there a way to speed up the formation of the circles or to display the formation of each circle instead of forming all 20 and then displaying?
Ive tried asking many people, my teacher, youtube, and playing around with the location of pygame.display.update()
def explosion(x,y):
explode = True
while explode:
startpoint = x,y
colorchoice = [red,yellow,black,white]
magnitude = 1
while magnitude < 20:
boom_bit_x = x + random.randrange(-1*magnitude,magnitude)
boom_bit_y = y + random.randrange(-1*magnitude,magnitude)
pygame.draw.circle(screen,colorchoice[random.randrange(0,4)],(boom_bit_x, boom_bit_y),random.randrange(4,7))
magnitude += 1
pygame.display.update()
explode = False

You have to handle the events in the application loop. See pygame.event.get() respectively pygame.event.pump():
For each frame of your game, you will need to make some sort of call to the event queue. This ensures your program can internally interact with the rest of the operating system.
def explosion(x,y):
explode = True
while explode:
startpoint = x,y
colorchoice = [red,yellow,black,white]
magnitude = 1
while magnitude < 20:
pygame.event.pump()
boom_bit_x = x + random.randrange(-1*magnitude,magnitude)
boom_bit_y = y + random.randrange(-1*magnitude,magnitude)
pygame.draw.circle(screen,colorchoice[random.randrange(0,4)],(boom_bit_x, boom_bit_y),random.randrange(4,7))
magnitude += 1
pygame.display.update()
explode = False

Related

Pygame Infinite World Generation Broken

So I'm making a basic 2D platformer game with the pygame module in python. Recently I've been trying to implement infinite world generation, but have been having some problems. The generation works fine, however, at the player's spawn, a bunch of random tiles spawn, obstructing the whole spawn area. I can't seem to find what's causing this.
Here's everything you need to replicate my situation:
map generation:
def generate_chunk(x,y):
chunk_data = []
for y_pos in range(CHUNK_SIZE):
for x_pos in range(CHUNK_SIZE):
target_x = x * CHUNK_SIZE + x_pos
target_y = y * CHUNK_SIZE + y_pos
tile_type = 0 # nothing
if target_y > 10:
tile_type = 2 # dirt
elif target_y == 10:
tile_type = 1 # grass
elif target_y < 10:
tile_type = 0
if tile_type != 0:
chunk_data.append([[target_x,target_y],tile_type])
return chunk_data
...
while True:
...
tile_rects = []
for y in range(3):
for x in range(4):
target_x = x - 1 + int(round(scroll[0]/(CHUNK_SIZE*16)))
target_y = y - 1 + int(round(scroll[1]/(CHUNK_SIZE*16)))
target_chunk = str(target_x) + ';' + str(target_y)
if target_chunk not in game_map:
game_map[target_chunk] = generate_chunk(target_x,target_y)
for tile in game_map[target_chunk]:
display.blit(tile_index[tile[1]],(tile[0][0]*16-scroll[0],tile[0][1]*16-scroll[1]))
if tile[1] in [1,2]:
tile_rects.append(pygame.Rect(tile[0][0]*16,tile[0][1]*16,16,16))
full code:
https://github.com/nice-404/Platformer
I can't seem to figure out what is causing the random tile spawning.
(I have been following DaFluffyPotato's platformer tutorial series because I am new to pygame)
After 2 weeks of debugging and further looking into the chunk generating code, I couldn't find out anything. However, I did figure out that the issue only happened in a small area, at the 0 x value. So what I did was I made the player spawn very far away from this, and made a boundary so that it couldn't walk far enough to see the issue. Not really fixing the issue, but at least it works now.

How to measure if a value stayed same for a period of time?

I'm making a smart bicycle backlight with Raspberry Pi and a SenseHat on top of it.
I'm measuring the output values of the SenseHat's accelerometer. There are actually three values reported as x, y, z and what I'm trying to know is whether my bicycle has been stationary for let's say 15 seconds or more. So if these values have been staying the same for over 15 seconds I'll turn off the backlight. And then if they start changing and stay like that for over 15 seconds, I want it to engage and start functioning again.
So far I've implemented strobe effect that auto activates when the bicycle is in idle. A steering detection - I show arrow animations to left and right based on the object detection sensor i put near the handlebar. I also implemented a brake detection. Once the accelerometer detects the braking, i show full red light.
If you check the code, you can see it's a bit tricky since the whole thing is in while loop and I need to make this detection as an if condition and then add else below, put rest of my existing if conditions there (such as deacceleration or turning detection)
So how do I make Python measure certain values for 15 seconds without using time.delay and do things based on whether they change or stay the same?
while True:
ser.flushInput()
ser.flushOutput()
x, y, z = sense.get_accelerometer_raw().values()
x = round(x, 2)
y = round(y, 2)
z = round(z, 2)
print("x=%s, y=%s, z=%s" % (x, y, z))
input = ser.read() #serial input i'm getting from arduino, it tells me if my left or right steering sensors are triggerred.
yon = input.decode("utf-8")
int(yon)
if (z > 0.20): #If deacceleration is detected
fren() # brake function is called
else: # if no breaking is detected...
if (yon == "1"): #if left turn sensor triggered
sag_ok() #show left turn animation on led matrix
elif (yon =="2"): # if right turn sensor triggered
sol_ok() #show right turn animation on led matrix
else: #anything else
strobe() #show strobe effect if nothing else is detected
There's a number of smaller things that need to be addressed first:
input = ser.read(). input is actually a builtin and shouldn't be used as a variable name
int(yon) does nothing. You may well convert it to an int but the result is lost because you don't assign the result back to a name
if (z > 0.20) and all your other if checks - the brackets actually do nothing here; you can drop them.
A bigger thing to address: That loop is going full-pelt on the CPU core for absolutely no reason. Thousands of times a second, constantly. You should introduce a time.sleep to reduce the load.
Given that, you can achieve your desired output with a mixture of a Boolean flag and a record of when the accelerometer last gave 0 values.
import time
import datetime as dt
last_zeros = None
countdown_started = False
while True:
ser.flushInput()
ser.flushOutput()
x, y, z = sense.get_accelerometer_raw().values()
x = round(x, 2)
y = round(y, 2)
z = round(z, 2)
print("x=%s, y=%s, z=%s" % (x, y, z))
if x == 0 and y == 0 and z == 0:
if countdown_started:
duration = (dt.datetime.utcnow() - last_zeros_time).total_seconds()
if duration > 15:
# Do something to turn the light off here
continue
else:
countdown_started = True
last_zeros_time = dt.datetime.utcnow()
else:
countdown_started = False
sensor_input = ser.read()
yon = sensor_input.decode("utf-8")
if (z > 0.20):
fren()
else:
if (yon == "1"):
sag_ok()
elif (yon =="2"):
sol_ok()
else:
strobe()
time.sleep(0.5)
The basic idea is to keep track of the last time when motion (or non-motion) was detected. If it was more than 15 seconds ago, then turn off (on) the light.
Something like this:
from time import monotonic
TAIL_LIGHT_DELAY = 15
time_of_last_motion = monotinic()
time_of_last_stop = monotonic()
while True:
now = monotonic()
motion = (abs(x) > 0.2) or (abs(y) > 0.2) or (abs(z) > 0.2)
if motion:
time_of_last_motion = now
if now - time_of_last_stop > TAIL_LIGHT_DELAY:
turn_on_tail_light()
else:
time_of_last_stop = now
if now - time_of_last_motion > TAIL_LIGHT_DELAY:
turn_off_tail_light()

Trying to properly iterate through pygame sprite group

So I am building a simple infinite run game for school and I am stuck on trying to spawn the obstacles. I am trying to check each obstacle sprite and if it has gone off the screen (the background and obstacles move from right to left). If it has gone off screen, I want to remove the sprite and set up another one on the right side of the screen. But every time an obstacle goes off the left side of the screen, an infinite amount of obstacles start spawning. I am new to pygame and python in general. Any help would be greatly appreciated. Thanks in advance.
def obstacle_off_screen(self):
numDeleted = 0
for cur_sprite in self.all_objects_list:
print("first loop")
if cur_sprite.rect.x < 0:
print("second")
cur_sprite.kill
numDeleted += 1
while numDeleted != 0:
print("third")
self.add_obstacle()
numDeleted -= 1
def add_obstacle(self):
#add parameters
if self.get_Speed() == 15:
x = 1000
y = 400
elif self.get_Speed() == 20:
x = 1000
y = 400
elif self.get_Speed() == 25:
x = 1000
y = 400
elif self.get_Speed() == 30:
x = 1000
y = 400
self.all_objects_list.add(Obstacle('src/paw.gif', [x, y]))
For now, I only have one obstacle that I initially spawn
cur_sprite.kill is a function, so when you want to call it use (), like cur_sprite.kill().
That's your problem. The obstacles out of screen don't get removed from their sprite groups.

addObject() in blender with python

I ran into a little wall here:
my point is, for a empty, to move, then add a plane on the spot, then move, then add a plane etc, and then will end up with a 100X100 plain, so i scripted:
import bge
dunWidth = 100 #meters/tiles
dunHeight = 100 #meters/tiles
b = 0
a = 0
add= bge.logic.getCurrentScene().addObject
def main():
global b, a
cont = bge.logic.getCurrentController()
dunMarker = cont.owner
#Movement Calculation: (X, Y, Z)
while b < dunWidth:
b += 1
add("FloorTile", "DunMarker",0)
dunMarker.applyMovement((1,0,0), False)
while a < dunHeight:
add("FloorTile", "DunMarker",0)
a += 1
dunMarker.applyMovement((0,1,0), False)
#dunMarker.applyMovement((0,-dunHeight,0), False)
main()
but instead, to my surprise, it First add the tile, then goes through the loop ignoring the add(), so the result is a 1x1 tile at 0x0y and the empty ends at 100x100y... how many things Im doing wrong here?Aaaand, since we are here, how would you improve the coding?(trying to learn here ;) )
pd, yeah, Roguelike 3D project
Try positioning dunMarker with worldPosition you may also want to use for loops to get a grid instead of two edges.
import bge
dunWidth = 100 #meters/tiles
dunHeight = 100 #meters/tiles
a=0
b=0
add= bge.logic.getCurrentScene().addObject
def main():
global a,b
cont = bge.logic.getCurrentController()
dunMarker = cont.owner
for b in range(0,dunWidth,2):
dunMarker.worldPosition=(b,a,0)
t=add("FloorTile", "DunMarker",0)
for a in range(0,dunHeight,2):
dunMarker.worldPosition = (b,a,0)
add("FloorTile", "DunMarker",0)
main()

Unexpected results in Conway's Game of Life

I have been trying to write my own version of Conway's Game of Life as practice for Python using Pygame. I first wrote the functions for initializing the game field, and then calculating the next generation. I verified it's functionality using the console to print the results and verify that they returned the expected results (just 2 generations deep by hand on a 5x5 grid).
An important note of how I am calculating the neighbors... Instead of doing a for loop through the entire array and doing for loops to count for each cell, I have implemented an array that holds the neighbor counts. Only making changes when a cells status is changed. This means I don't waste time calculating neighbors for cells that have not changed.
When it came time to use Pygame to display the array with rectangles, I wrote the following program. At first I was drawing the screen by filling in the entire screen white, and then drawing the live cells as black (this can be done by commenting out the else statement in update()). I expected this to work as normal, but when I ran the program all I ended up with was the screen filling in black.
I was perplexed by the result so i drew white rectangles for the unpopulated cells (using the else statement. And got a better looking result, but instead of the cells eventually all dying, they eventually multiplied across the whole screen. This is opposite of what I expected, as I was expecting it to eventually stabilize.
Anyone know what I am doing wrong? I know that this is not the best way of writing this program, I welcome comments of how I can make it better.
RETURN = run simulation
'R' = randomize
'T' = tick one generation
'C' = clear game field
'N' = display neighbor map
import pygame
from pygame.locals import *
import numpy as np
from random import *
import copy
fieldSize = [100,50]
cellSize = 10 # size of >10 is recommended to see neighbor count
windowSize = [fieldSize[0]*cellSize, fieldSize[1]*cellSize]
# calculate the last cell in each axis so it is not done repeatedly
lastCell = [(fieldSize[0]-1), (fieldSize[1]-1)]
dX = float(windowSize[0])/float(fieldSize[0])
dY = float(windowSize[1])/float(fieldSize[1])
colorAlive = [0,125,0]
colorDead = [0, 0, 0]
# todo list
# 1. make cLife take in the field size
# 2. convert random functions to numpy.random.randint
class cLife():
def randomize(self):
self.neighbors = np.zeros(fieldSize)
# fill in the game field with random numbers
for x in range(fieldSize[0]):
for y in range(fieldSize[1]):
if(randint(0,99)<20):
self.gameField[x][y] = 1
self.updateNeighbors([x,y], True)
else:
self.gameField[x][y] = 0
def displayNeighbors(self, surface):
self.drawField(surface)
for x in range(fieldSize[0]):
for y in range(fieldSize[1]):
neighborCount=font.render(str(int(self.neighbors[x][y])), 1,(200,200,200))
surface.blit(neighborCount, (x*dX+dX/3, y*dY+dY/3.5))
pygame.display.flip()
# This is the function to update the neighbor map, the game field is torroidal so the complexity is greatly
# increased. I have handcoded each instruction to avoid countless if statements and for loops.
# Hopefully, this has drastically improved the performance. Using this method also allows me to avoid calculating
# the neighbor map for every single cell because the neighbor map is updated only for the cells affected by a change.
def updateNeighbors(self, pos, status):
if(status == True):
change = 1
else:
change = -1
# testing for the cells in the center of the field (most cells are in the center so this is first)
# cells are filled in starting on the top-left corner going clockwise
if((pos[0]>0 and pos[0]<lastCell[0])and(pos[1]>0 and pos[1]<lastCell[1])):
self.neighbors[pos[0]-1][pos[1]-1] += change
self.neighbors[pos[0]][pos[1]-1] += change
self.neighbors[pos[0]+1][pos[1]-1] += change
self.neighbors[pos[0]+1][pos[1]] += change
self.neighbors[pos[0]+1][pos[1]+1] += change
self.neighbors[pos[0]][pos[1]+1] += change
self.neighbors[pos[0]-1][pos[1]+1] += change
self.neighbors[pos[0]-1][pos[1]] += change
elif(pos[0] == 0): # left edge
if(pos[1] == 0): # top left corner
self.neighbors[lastCell[0]][lastCell[1]] += change
self.neighbors[0][lastCell[1]] += change
self.neighbors[1][lastCell[1]] += change
self.neighbors[1][0] += change
self.neighbors[1][1] += change
self.neighbors[0][1] += change
self.neighbors[lastCell[0]][1] += change
self.neighbors[lastCell[0]][0] += change
elif(pos[1] == lastCell[1]): # bottom left corner
self.neighbors[lastCell[0]][pos[1]-1] += change
self.neighbors[0][pos[1]-1] += change
self.neighbors[1][pos[1]-1] += change
self.neighbors[1][pos[1]] += change
self.neighbors[1][0] += change
self.neighbors[0][0] += change
self.neighbors[lastCell[0]][0] += change
self.neighbors[lastCell[0]][pos[1]] += change
else: # everything else
self.neighbors[lastCell[0]][pos[1]-1] += change
self.neighbors[0][pos[1]-1] += change
self.neighbors[1][pos[1]-1] += change
self.neighbors[1][pos[1]] += change
self.neighbors[1][pos[1]+1] += change
self.neighbors[0][pos[1]+1] += change
self.neighbors[lastCell[0]][pos[1]+1] += change
self.neighbors[lastCell[0]][pos[1]] += change
elif(pos[0] == lastCell[0]): # right edge
if(pos[1] == 0): # top right corner
self.neighbors[pos[0]-1][lastCell[1]] += change
self.neighbors[pos[0]][lastCell[1]] += change
self.neighbors[0][lastCell[1]] += change
self.neighbors[0][0] += change
self.neighbors[0][1] += change
self.neighbors[pos[0]][1] += change
self.neighbors[pos[0]-1][1] += change
self.neighbors[pos[0]-1][0] += change
elif(pos[1] == lastCell[1]): # bottom right corner
self.neighbors[pos[0]-1][pos[1]-1] += change
self.neighbors[pos[0]][pos[1]-1] += change
self.neighbors[0][pos[1]-1] += change
self.neighbors[0][pos[1]] += change
self.neighbors[0][0] += change
self.neighbors[pos[0]][0] += change
self.neighbors[pos[0]-1][0] += change
self.neighbors[pos[0]-1][pos[1]] += change
else: # everything else
self.neighbors[pos[0]-1][pos[1]-1] += change
self.neighbors[pos[0]][pos[1]-1] += change
self.neighbors[0][pos[1]-1] += change
self.neighbors[0][pos[1]] += change
self.neighbors[0][pos[1]+1] += change
self.neighbors[pos[0]][pos[1]+1] += change
self.neighbors[pos[0]-1][pos[1]+1] += change
self.neighbors[pos[0]-1][pos[1]] += change
elif(pos[1] == 0): # top edge, corners already taken care of
self.neighbors[pos[0]-1][lastCell[1]] += change
self.neighbors[pos[0]][lastCell[1]] += change
self.neighbors[pos[0]+1][lastCell[1]] += change
self.neighbors[pos[0]+1][0] += change
self.neighbors[pos[0]+1][1] += change
self.neighbors[pos[0]][1] += change
self.neighbors[pos[0]-1][1] += change
self.neighbors[pos[0]-1][0] += change
elif(pos[1] == lastCell[1]): # bottom edge, corners already taken care of
self.neighbors[pos[0]-1][pos[1]-1] += change
self.neighbors[pos[0]][pos[1]-1] += change
self.neighbors[pos[0]+1][pos[1]-1] += change
self.neighbors[pos[0]+1][pos[1]] += change
self.neighbors[pos[0]+1][0] += change
self.neighbors[pos[0]][0] += change
self.neighbors[pos[0]-1][0] += change
self.neighbors[pos[0]-1][pos[1]] += change
def nextGeneration(self):
# copy the neighbor map, because changes will be made during the update
self.neighborsOld = copy.deepcopy(self.neighbors)
for x in range(fieldSize[0]):
for y in range(fieldSize[1]):
# Any live cell with fewer than two live neighbours dies, as if caused by under-population.
if(self.gameField[x][y] == 1 and self.neighborsOld[x][y] < 2):
self.gameField[x][y] = 0
self.updateNeighbors([x,y], False)
# Any live cell with more than three live neighbours dies, as if by overcrowding.
elif(self.gameField[x][y] == 1 and self.neighborsOld[x][y] >3):
self.gameField[x][y] = 0
self.updateNeighbors([x,y], False)
# Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
elif(self.gameField[x][y] == 0 and self.neighborsOld[x][y] == 3):
self.gameField[x][y] = 1
self.updateNeighbors([x,y], True)
def drawField(self, surface):
surface.fill(colorDead)
# loop through and draw each live cell
for x in range(fieldSize[0]):
for y in range(fieldSize[1]):
if(self.gameField[x][y] == 1):
pygame.draw.rect(surface, colorAlive, [dX*x, dY*y, dX, dY])
pygame.display.flip()
def __init__(self):
# initialize the game field and neighbor map with zeros
self.gameField = np.zeros(fieldSize)
self.neighbors = np.zeros(fieldSize)
# begining of the program
game = cLife()
pygame.init()
surface = pygame.display.set_mode(windowSize)
pygame.display.set_caption("Conway\'s Game of Life")
clock = pygame.time.Clock()
pygame.font.init()
font=pygame.font.Font(None,10)
surface.fill(colorDead)
game.randomize()
game.drawField(surface)
pygame.display.flip()
running = False
while True:
#clock.tick(60)
# handling events
for event in pygame.event.get():
if(event.type == pygame.MOUSEBUTTONDOWN):
mousePos = pygame.mouse.get_pos()
x = int(mousePos[0]/dX)
y = int(mousePos[1]/dY)
if(game.gameField[x][y] == 0):
game.gameField[x][y] = 1
game.updateNeighbors([x, y], True)
game.drawField(surface)
else:
game.gameField[x][y] = 0
game.updateNeighbors([x, y], False)
game.drawField(surface)
elif(event.type == pygame.QUIT):
pygame.quit()
elif(event.type == pygame.KEYDOWN):
# return key starts and stops the simulation
if(event.key == pygame.K_RETURN):
if(running == False):
running = True
else:
running = False
# 't' key ticks the simulation forward one generation
elif(event.key == pygame.K_t and running == False):
game.nextGeneration()
game.drawField(surface)
# 'r' randomizes the playfield
elif(event.key == pygame.K_r):
game.randomize()
game.drawField(surface)
# 'c' clears the game field
elif(event.key == pygame.K_c):
running = False
game.gameField = np.zeros(fieldSize)
game.neighbors = np.zeros(fieldSize)
game.drawField(surface)
# 'n' displays the neighbor map
elif(event.key == pygame.K_n):
game.displayNeighbors(surface)
if(running == True):
game.nextGeneration()
game.drawField(surface)
self.neighborsOld = self.neighbors does not copy the map, it only points to it.
See :
a = [[1,2],[3,4]]
b = a
b[0][0] = 9
>>> a
[[9, 2], [3, 4]]
You need to either make a copy (a[:]) for every row in a, or use the copy module and use deepcopy:
b = [x[:] for x in a]
or
import copy
b = copy.deepcopy(a)
Either way, it results in
b[0][0] = 9
>>> a
[[1, 2], [3, 4]]

Categories