I'm programming game pong in python and I wan't the ball to be faster everytime it bounces of a bat. So I tried to add
global SPEED
SPEED + 25
into a function higher_speed which will trigger everytime when the ball bounces of the bat.
short version of game code here:
...
BALL_SIZE = 20
BAT_WIDTH = 10
BAT_HEIGHT = 100
SPEED = 250 # (in pixels per second)
BAT_SPEED = SPEED * 1.5 # (in pixels per second)
...
def higher_speed(SPEED, x):
x = 25
global SPEED
SPEED + x
return SPEED
# bounce left
if ball_position[0] < BAT_WIDTH + BALL_SIZE / 2:
if bat_min < bat_position[0] < bat_max:
# bat bounces ball
BALL_SPEED[0] = abs(BALL_SPEED[0])
global SPEED
higher_speed()
else:
# bat hadn't bounced the ball, player loses
score[1] += 1
reset()
# bounce right
if ball_position[0] > WIDTH7777 - (BAT_WIDTH + BALL_SIZE / 2):
if bat_min < bat_position[1] < bat_max:
BALL_SPEED[0] = -abs(BALL_SPEED[0])
higher_speed()
else:
score[0] += 1
reset()
...
Please help. I appreciate your time :).
Several things here:
First of all, the value is not being changed because it is not assigned in the first place, your function should look like this:
def higher_speed(SPEED, x):
x=25
global SPEED
SPEED += x
Second, if you're overwriting x at the beginning of the function and using SPEED as global, why pass it?:
def higher_speed():
global SPEED
SPEED += 25
Third, according to Python's PEP8 standards, capitalized words are only for constants, it would be a good use to the speed increase, so it should look like this:
SPEED_INCREASE = 25
def higher_speed():
global speed
speed += SPEED_INCREASE
And last, in general is a bad idea using global variables you can check this article or google it, so try to avoid it, then it should look like this:
def higher_speed(speed):
return speed+SPEED_INCREASE
speed = higher_speed(speed)
or you could set this inline:
speed += SPEED_INCREASE
I hope it helped!
Related
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.
I am doing text game practice for school and we have to make four different functions to it. I have done health points system, and now i would like to print how many percentages player have used of total amounta.
This is my hp system:
def hela(player_health, hit):
return player_health - hit
player_health_points = 15
dog_hit_value = 4
pistol_hit_value = 15
brasnuckles_hit_value = 3
punch_hit_value = 1
kick_hit_value = 2
player_health_points = hela(player_health_points, dog_hit_value,)
player_health_points = hela(player_health_points, brasnuckles_hit_value)
print('You have ' + str(player_health_points) + ' HP left!')*
And this is what i have done now and lost my rest brains with it:
def hp_left_percentage(x,y):
vastaus = x - y
return vastaus
health = 16
tulos = hp_left_percentage(health,player_health_points)
print(tulos)
Questions:
Why i have to add one for def hp_left_percentage health getting it show right value?
Now def hp_left_percentage shows me how much player have healt, with numeric amount. How i can get function print it percentages?
I hope you can understand what i mean :)
If I understand your question correctly, you want to display the percentage of health left, not just the absolute number? Right now your health_left_percentage just shows the number difference in HP. To calculate the percentage you can change it to this:
def hp_left_percentage(x,y):
# I assume, 'y' is the damage here.
vastaus = (x - y) / x
print(f'You have {vastaus:.0%} HP left!')
This way the function will automatically calculate the percentage and return it in proper formatting. I suggest reading up on f-strings for a clean way to display strings with variables the way you want them to be.
Hope this helps. Let me know if I misunderstood you.
EDIT
If the player gets hit two or more times, then you should store intial HP in a global variable and change the function like this:
initial_hp = 100
def hp_left_percentage(x, y):
vastaus = (x - y) / initial_hp
return vastaus
perc_left = hp_left_percentage(x, y)
print(f'You have {perc_left:.0%} HP left!')
Do you mean something like this ?
def hp_left_percentage(x,y):
vastaus = x - y
percentage = '{0:.2f}'.format((vastaus / x * 100))
return vastaus
I was in vacation, so have not writed here. Thanks for all answers.
This is what i have done.
def hela(player_health, hit):
return player_health - hit
def hp_left_percentage(x, y):
vastaus = 1 - (x - y) / initial_hp
return vastaus
player_health_points = 15
dog_hit_value = 4
player_health = 15
initial_hp = 15
player_health_points = hela(player_health_points, dog_hit_value,)
perc_left = hp_left_percentage(player_health, player_health_points)
print(f'You have {perc_left:.2%} HP left!')
I want to make more than two turtles when I run the modules.
So I declared two variables on turtle but there's only one turtle I can see.
What's wrong with my code?
import turtle
t1=turtle.Turtle()
t2=turtle.Turtle()
colors = ["red", "blue", "green"]
turtle.bgcolor("yellow")
t1.speed(3)
t1.width(5)
length1 = 10
t2.speed(3)
t2.width(5)
length2 = 10
while length1 < 500:
t1.fd(length1)
t1.pencolor(colors[length1%3])
t1.right (89)
length1 += 3 #length1 = length1 + 3
while length2 < 500:
t2.fd(length2)
t2.pencolor(pink)
t2.left (89)
length2 += 4 #length2 = length2 + 4
input()
Your turtles are moving one by one. The first while loop does the job with t1, and when it's done, the second while will take care of t2. It's like "t1, make your first step. Then, t1, make your second. (and repeat this until length1 isn't less than 500 anymore.) Now t1 is done, so t2, make your first step. t2, your second step. (and it continues.)"
Instead, you want them to take turns making each of their steps. That's like "t1, make your first step. Then, t2, make your first. t1, make your second step. t2, your turn for your second step. (and it continues.)"
So your while loop should look like:
t1.pencolor(colors[length1 % 3])
t2.pencolor("pink")
while length1 < 500 or length2 < 500:
if length1 < 500:
t1.fd(length1)
t1.right(89)
length1 += 3 # length1 = length1 + 3
if length2 < 500:
t2.fd(length2)
t2.left(89)
length2 += 4 # length2 = length2 + 4
(Note you don't have to set the pencolor each time you move the turtle.)
there's only one turtle I can see
Is there literally only one turtle, or do you run out of patience waiting for the first turtle to finish before the second turtle starts (and breaks, due to the unquoted 'pink')? If this is about wanting to see both turtles in action at the same time, as folks have concluded, here's my approach:
Short of using threads, I use generators to allow the two turtles to run in a coroutine-like fashion. The advantage is that the turtles can share the exact same code, if they want to, or they can use completely different code. But it avoids duplicating code or maintaining unrelated code in the same while loop:
from turtle import Screen, Turtle
screen = Screen()
screen.bgcolor("yellow")
t1 = Turtle()
t1.pencolor('blue')
t2 = Turtle()
t2.pencolor('pink')
def pattern(turtle, increment, angle):
turtle.speed('fast')
turtle.width(5)
length = 10
while length < 500:
turtle.forward(length)
turtle.right(angle)
length += increment
yield 0
generator1 = pattern(t1, 3, 89)
generator2 = pattern(t2, 4, -89)
while next(generator1, 1) + next(generator2, 1) < 2:
pass
screen.exitonclick()
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.
I made an attempt to solve Uncle Bobs bowling game kata (http://www.butunclebob.com/ArticleS.UncleBob.TheBowlingGameKata) but didn't really find a solution that felt pythonic enough.
This solution is more or less an adaptation of Martins C++ solution and uses array indexes to calculate scores for strikes and spares. It works but doesn't feel quite as pythonic as I would like it to be.
class Game():
def __init__(self):
self.rolls = []
def roll(self, pins):
self.rolls.append(pins)
def score_c(self):
total_score = 0
frame_index = 0
for frame in range(10):
if self.rolls[frame_index] == 10:
total_score += 10 + self.rolls[frame_index + 1] + self.rolls[frame_index + 2]
frame_index +=1
elif self.rolls[frame_index] + self.rolls[frame_index + 1] == 10:
total_score += 10 + self.rolls[frame_index + 1]
frame_index += 2
else:
total_score += self.rolls[frame_index] + self.rolls[frame_index + 1]
frame_index += 2
return total_score
I could have used convenience functions for strike and spare conditions, but you get the picture.
But I thought there must be a way to do it without accessing the rolls array directly though indexes. That feels like a very c-like way of doing it and incrementing frame_index directly definitely doesn't feel right in python. So I think there must be a neater way to do it. I made an attempt below which didn't really work for perfect games.
This one use a generator to provide frames which felt pretty neat but it also meant that 0 had to be added for strikes to make complete 2 roll frames.
class Game():
def __init__(self):
self.rolls = []
def _frame_iterator(self):
for i in range(0, 20, 2):
yield (self.rolls[i], self.rolls[i+1])
def roll(self, pins):
self.rolls.append(pins)
if pins == 10:
self.rolls.append(0)
def score(self):
total_score = 0
spare = False
strike = False
for frame in self._frame_iterator():
if spare:
total_score += frame[0]
spare = False
if strike:
total_score += frame[1]
strike = False
if frame[0] + frame[1] == 10:
spare = True
if frame[0] == 10:
strike = True
total_score += frame[0] + frame[1]
return total_score
My questions are basically, has anyone solved the bowling kata in Python in a different and more pythonic way than uncle bobs C++ solution? And suggestions how to improve on my attempt?
This is definitely a different approach (implementing most of the rules in roll(), instead of score()), and I think it's pretty pythonic too.
class Game(object):
def __init__(self):
self._score = [[]]
def roll(self, pins):
# start new frame if needed
if len(self._score[-1]) > 1 or 10 in self._score[-1]:
self._score.append([])
# add bonus points to the previous frames
for frame in self._score[-3:-1]:
if sum(frame[:2]) >= 10 and len(frame) < 3:
frame.append(pins)
# add normal points to current frame
for frame in self._score[-1:10]:
frame.append(pins)
def score(self):
return sum(sum(x) for x in self._score)
The main idea here is instead of storing all rolls in a single list, to make a list of frames that contains a list of rolls (and bonus points) for each frame.
What makes it pythonic is for example the generator expression in the score method.
Another pythonic example is the use of list slices. A previous version of middle part of roll() I did looked like:
for i in [2, 3]:
if len(self._score) >= i:
sum(self._score[-i][:2]) >= 10 and len(self._score[-i]) < 3:
self._score[-i].append(pins)
The elegant thing of the current version using a list slice is that you don't have to check whether the list is long enough to look 1 or 2 frames back. Moreover, you get a nice local variable (frame = self._score[-i]) for free, without having to dedicate a separate line for it.