I am trying to create an animation of a rectangle in pygame but I struggle to animate it over the given frame-rate.
class Muscle(pygame.sprite.Sprite):
def __init__(self, screen, posX=200, posY=200, contraction=0.5, extension=1.5, length=10, thickness=5, min_len=0.2,max_len=1.5, power=20):
super(Muscle, self).__init__()
self.screen = screen
self.contraction = contraction
self.relaxation = relaxation
self.length = length
self.thickness = thickness
if power < 1:
self.power = 1
power = 1
else:
self.power = power
self.image = pygame.Surface((length, thickness))
color_index = 5 * power
self.image.fill((255, color_index, color_index))
self.rect = self.image.get_rect()
self.rect.x = posX
self.rect.y = posY
def render(self):
self.screen.blit(self.image, (self.rect.x, self.rect.y))
def contract(self):
expected_width = self.length * self.contraction
counter = 0
while self.image.get_width() > expected_width:
self.image = pygame.transform.scale(self.image, (self.rect.width, self.image.get_height()))
self.rect.x += 1;
self.rect.width -= 2
self.render()
counter += 1
def extend(self):
expected_width = self.length * self.relaxation
counter = 0
while self.image.get_width() < expected_width:
self.image = pygame.transform.scale(self.image, (self.rect.width, self.image.get_height()))
self.rect.x -= 1;
self.rect.width += 2
self.render()
#print("Relaxation:" + str(counter))
counter += 1
If I call the contract and extend methods separately, they resize the image of the rectangle successfully, but I would like to perform it over time, without interrupting my main loop which draws the environment and the sprite.
The simplest solution would be to call extend or contract once per frame, but then the animation would be frame rate bound.
import pygame
class Muscle(pygame.sprite.Sprite):
def __init__(self, screen, posX=200, posY=200, contraction=0.5,
extension=1.5, length=40, thickness=20, min_len=0.2,max_len=1.5, power=20):
super(Muscle, self).__init__()
self.screen = screen
self.contracting = False # To check if the muscle is contracting or extending.
self.contraction = contraction
self.relaxation = 1
self.length = length
self.thickness = thickness
if power < 1:
self.power = 1
power = 1
else:
self.power = power
self.image = pygame.Surface((length, thickness))
color_index = 5 * power
self.image.fill((255, color_index, color_index))
self.rect = self.image.get_rect()
self.rect.x = posX
self.rect.y = posY
# This method gets called every frame.
def update(self):
if self.contracting:
self.contract()
else:
self.extend()
def render(self):
self.screen.blit(self.image, (self.rect.x, self.rect.y))
def contract(self):
expected_width = self.length * self.contraction
counter = 0
if self.image.get_width() > expected_width:
self.image = pygame.transform.scale(self.image, (self.rect.width, self.image.get_height()))
self.rect.x += 1
self.rect.width -= 2
self.render()
counter += 1
def extend(self):
expected_width = self.length * self.relaxation
counter = 0
if self.image.get_width() < expected_width:
self.image = pygame.transform.scale(self.image, (self.rect.width, self.image.get_height()))
self.rect.x -= 1
self.rect.width += 2
self.render()
counter += 1
def main():
screen = pygame.display.set_mode((640, 480))
clock = pygame.time.Clock()
muscle = Muscle(screen)
all_sprites = pygame.sprite.Group(muscle)
done = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
# Change the state of the muscle.
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_c:
muscle.contracting = True
elif event.type == pygame.KEYUP:
if event.key == pygame.K_c:
muscle.contracting = False
all_sprites.update()
screen.fill((30, 30, 30))
all_sprites.draw(screen)
pygame.display.flip()
clock.tick(30)
if __name__ == '__main__':
pygame.init()
main()
pygame.quit()
Alternatively, you can call extend or contract after some time interval. Check out these answers to see how you can implement a timer.
Related
This question already has answers here:
Animated sprite from few images
(4 answers)
How do I create animated sprites using Sprite Sheets in Pygame?
(1 answer)
Closed 3 months ago.
So I am pretty new to pygame, I am trying to do my player to shoot bullets so I decided after watching some video to create a group with all my bullets, however my bullets are animated.
I am trying to use a draw function that would draw my every frame , but I also used pygame.sprite.Group() that allows me to use only the normal draw function. Again I am a total noob and I would really appreciate some help ,thanks !
`
mainloop.py
import pygame
from Player import player
from test import Bullet
pygame.init()
DISPLAY_W, DISPLAY_H = 480, 270
canvas = pygame.Surface((DISPLAY_W, DISPLAY_H))
window = pygame.display.set_mode(((DISPLAY_W, DISPLAY_H)))
running = True
clock = pygame.time.Clock()
house = pygame.image.load('house.png').convert()
bullet_group = pygame.sprite.Group()
bro = player()
while running:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
bro.LEFT_KEY, bro.FACING_LEFT = True, True
elif event.key == pygame.K_RIGHT:
bro.RIGHT_KEY, bro.FACING_LEFT = True, False
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
bro.LEFT_KEY = False
elif event.key == pygame.K_RIGHT:
bro.RIGHT_KEY = False
if event.type == pygame.MOUSEBUTTONDOWN:
bullet_group.add(bro.create_bullet())
bro.update()
canvas.blit(house, (0, 0))
bro.draw(canvas)
bullet_group.draww(canvas)
bullet_group.update()
window.blit(canvas, (0, 0))
pygame.display.update()
`
`
test.py
import pygame
from Sprite import Spritesheet
class Bullet(pygame.sprite.Sprite):
def __init__(self, pos_x, pos_y):
pygame.sprite.Sprite.__init__(self)
self.load_frames()
self.FACING_LEFT = False
self.image = self.frames_left[0]
self.velocity = 0
self.rect = self.image.get_rect(center=(pos_x, pos_y))
self.current_frame = 0
self.last_updated = 0
self.velocity = 0
self.current_image = self.frames_left[0]
def draww(self, display):
display.blit(self.current_image, self.rect)
def update(self):
self.rect.x += 5
self.animate()
def animate(self):
now = pygame.time.get_ticks()
if now - self.last_updated > 200:
self.last_updated = now
self.current_frame = (self.current_frame +
1) % len(self.frames_left)
self.current_image = self.frames_left[self.current_frame]
def load_frames(self):
sprite = Spritesheet('broforce.png')
self.frames_left = [sprite.parse_sprite(
'Sheet/g1.png'), sprite.parse_sprite('Sheet/g1.png'), sprite.parse_sprite('Sheet/g2.png'), sprite.parse_sprite('Sheet/g3.png'), sprite.parse_sprite('Sheet/g4.png'), ]
self.frames_right = []
for frame in self.frames_left:
self.frames_right.append(pygame.transform.flip(frame, True, False))
`
`
player.py
import pygame
from Sprite import Spritesheet
from test import Bullet
class player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.LEFT_KEY, self.RIGHT_KEY, self.FACING_LEFT = False, False, False
self.load_frames()
self.rect = self.idle_frames_left[0].get_rect()
self.rect.midbottom = (240, 244)
self.current_frame = 0
self.last_updated = 0
self.velocity = 0
self.state = 'idle'
self.current_image = self.idle_frames_left[0]
def create_bullet(self):
return Bullet(self.rect.x, self.rect.y)
def draw(self, display):
display.blit(self.current_image, self.rect)
def update(self):
self.velocity = 0
if self.LEFT_KEY:
self.velocity = -3
elif self.RIGHT_KEY:
self.velocity = 3
self.rect.x += self.velocity
self.set_state()
self.animate()
def set_state(self):
self.state = ' idle'
if self.velocity > 0:
self.state = 'moving right'
elif self.velocity < 0:
self.state = 'moving left'
def animate(self):
now = pygame.time.get_ticks()
if self.state == ' idle':
if now - self.last_updated > 200:
self.last_updated = now
self.current_frame = (
self.current_frame + 1) % len(self.idle_frames_left)
if self.FACING_LEFT:
self.current_image = self.idle_frames_left[self.current_frame]
elif not self.FACING_LEFT:
self.current_image = self.idle_frames_right[self.current_frame]
else:
if now - self.last_updated > 60:
self.last_updated = now
self.current_frame = (
self.current_frame + 1) % len(self.walking_frames_left)
if self.state == 'moving left':
self.current_image = self.walking_frames_left[self.current_frame]
elif self.state == 'moving right':
self.current_image = self.walking_frames_right[self.current_frame]
def load_frames(self):
sprite = Spritesheet('broforce.png')
self.idle_frames_left = [sprite.parse_sprite('Sheet/1.png')]
self.walking_frames_left = [sprite.parse_sprite('Sheet/2.png'), sprite.parse_sprite(
'Sheet/3.png'), sprite.parse_sprite('Sheet/4.png'), sprite.parse_sprite('Sheet/5.png'), sprite.parse_sprite('Sheet/1.png')]
self.idle_frames_right = []
for frame in self.idle_frames_left:
self.idle_frames_right.append(
pygame.transform.flip(frame, True, False))
self.walking_frames_right = []
for frame in self.walking_frames_left:
self.walking_frames_right.append(
pygame.transform.flip(frame, True, False))
`
Well I don't really know what to try
Ive been having a problem with animating different frames of a sprite. My program runs at 60 FPS and some of my sprites dont have nearly enough frames to look smooth and give enough time to be visible to the user. For example my explosion sprite, has 6 frames in it. While the game runs at 60FPS, this means that the whole animation is only visible for 1/10 of a second.
I have already tried the following functions: Pygame.wait and Pygame.delay and the "//" floor function. Pygame.wait/delay both completely pause the program which will mean that just to see the explosion the user would have to stop whatever they are doing and I don't want to have to duplicate frames to come to 30 or 60 frames, that just seems inefficient.
Explosion array:
Expl = [pygame.image.load("EX1.png"),pygame.image.load("EX2.png"),pygame.image.load("EX3.png"),pygame.image.load("EX4.png"),pygame.image.load("EX5.png"),pygame.image.load("EX6.png")]
Where it happens:
if self.explosionc + 1 >= 6:
self.explosionc = 0
elif self.vel > 0:
win.blit(Expl[self.explosionc // 5],(self.x,self.y))
self.explosionc +=1
The player class, if you need that much info
class Player(pygame.sprite.Sprite):
def __init__(self,x,y,width,height):
self.x = x
self.y = y
self.width = width
self.height = height
self.vel = 5
self.health = 10
self.visible = True
self.explosions = False
self.explosionc = 0
self.hitbox = (self.x + 5,self.y + 10,60,60)
self.canshoot = True
self.dead = False
def draw(self,win):
global bgvel
if self.y > 600:
win.blit(EFTNA,(self.x,self.y))
for enemy in enemies:
enemy.vel = 2
#bgvel = 1
elif self.y <= 600 and self.y > 400:
win.blit(EFTAL,(self.x,self.y))
for enemy in enemies:
enemy.vel = 3
#bgvel = 2
elif self.y <= 400 and self.y > 350:
win.blit(EFTAM,(self.x,self.y))
for enemy in enemies:
enemy.vel = 4
#bgvel = 3
elif self.y <= 450:
win.blit(EFTAH,(self.x,self.y))
for enemy in enemies:
enemy.vel = 5
#bgvel = 4
self.hitbox = (self.x + 5,self.y + 10,60,60)
#pygame.draw.rect(win,(255,0,0),self.hitbox,2)
if self.y + self.height > HEIGHT:
self.y -= self.vel
if self.x < 0:
self.x += self.vel
if self.x + self.width > WIDTH:
self.x -= self.vel
if self.explosions == True:
print("I exploded")
self.canshoot = False
self.dead = True
index = self.explosionc//10
if self.vel > 0:
win.blit(Expl[index % 6],(self.x,self.y))
self.explosionc += 1
#if self.explosionc >= 6*10:
# self.explosionc = 0
self.visible = False
def hit(self):
if self.health > 0:
self.health -=1
else:
self.explosions = True
I expect the program to wait a certain amount of time between each frame without pausing the entire program. I have heard that "flooring" is a good way to do this but it just doesn't seem to be effective as it either makes it completely invisible to the human eye or no effect.
You can use pygame.time.get_ticks() to use time to control how long you display frame
start_time = pygame.time.get_ticks()
while running:
current_time = pygame.time.get_ticks()
if current_time - start_time >= expected_delay_in_ms:
change_frame_in_animation()
start_time = current_time
I create start_time before while running but you have to create it when you start animation.
You can also use pygame.time.set_timer() to create own event every few miliseconds. And then you can use this event to change frame in animation
pygame.time.set_timer(pygame.USEREVENT+1, expected_delay_in_ms)
while running:
for event in pygame.event.get():
if event.type = pygame.USEREVENT+1:
change_frame_in_animation()
I use pygame.time.set_timer() before while running but you have to use it when you start animation.
EDIT: Using your new code in question it could be (but I can't test it)
In self.__init__ I define
self.frame_delay = 200 # 200 milliseconds
When player die I set self.start_delay = 0 - it should display first frame without delay.
def hit(self):
if self.health > 0:
self.health -= 1
else:
self.explosions = True
self.start_delay = 0 # or pygame.time.get_ticks()
In draw I use self.start_delay to compare with current_time and self.frame_delay
if self.explosions == True:
current_time = pygame.time.get_ticks()
if current_time - self.start_delay >= self.frame_delay:
self.start_delay = current_time
print("I exploded")
self.canshoot = False
self.dead = True
self.explosionc = (self.explosionc + 1) % 6
if self.vel > 0: # ???
win.blit(Expl[self.explosionc],(self.x,self.y))
self.visible = False
I calculate next frame with
self.explosionc = (self.explosionc + 1) % 6
I don't know only why you use if self.vel > 0:
Full code
class Player(pygame.sprite.Sprite):
def __init__(self,x,y,width,height):
self.x = x
self.y = y
self.width = width
self.height = height
self.vel = 5
self.health = 10
self.visible = True
self.explosions = False
self.explosionc = 0
self.hitbox = (self.x + 5,self.y + 10,60,60)
self.canshoot = True
self.dead = False
self.frame_delay = 200 # 200 milliseconds
def draw(self,win):
global bgvel
if self.y > 600:
win.blit(EFTNA,(self.x,self.y))
for enemy in enemies:
enemy.vel = 2
#bgvel = 1
elif self.y <= 600 and self.y > 400:
win.blit(EFTAL,(self.x,self.y))
for enemy in enemies:
enemy.vel = 3
#bgvel = 2
elif self.y <= 400 and self.y > 350:
win.blit(EFTAM,(self.x,self.y))
for enemy in enemies:
enemy.vel = 4
#bgvel = 3
elif self.y <= 450:
win.blit(EFTAH,(self.x,self.y))
for enemy in enemies:
enemy.vel = 5
#bgvel = 4
self.hitbox = (self.x + 5,self.y + 10,60,60)
#pygame.draw.rect(win,(255,0,0),self.hitbox,2)
if self.y + self.height > HEIGHT:
self.y -= self.vel
if self.x < 0:
self.x += self.vel
if self.x + self.width > WIDTH:
self.x -= self.vel
if self.explosions == True:
current_time = pygame.time.get_ticks()
if current_time - self.start_delay >= self.frame_delay:
self.start_delay = current_time
print("I exploded")
self.canshoot = False
self.dead = True
self.explosionc = (self.explosionc + 1) % 6
if self.vel > 0: # ???
win.blit(Expl[self.explosionc],(self.x,self.y))
self.visible = False
def hit(self):
if self.health > 0:
self.health -= 1
else:
self.explosions = True
self.start_delay = 0 # or pygame.time.get_ticks()
I'm trying to make a sort visualiser using Ruby and Gosu. When the user left clicks it will sort the numbers out using a insertion sort. When the user right clicks it will sort the numbers out using a bubble sort. So far the only the insertion sort works but the bubble sort crashes after sorting out the first number. Does anyone know why? Thanks.
require 'gosu'
module ZOrder
BACKGROUND, MIDDLE, TOP = *0..2
end
SCREEN_WIDTH = 600 # needs to be COUNT * COLUMN_WIDTH
SCREEN_HEIGHT = 200 # Should be multiple of 100
MAX_VALUE = 100 # the range of the data 1 to 100
COUNT = 30 # Number of items
COL_WIDTH = 20 # suggested at least 10
class Column
# have a pointer to the neighbouring cells
attr_accessor :height, :value
def initialize(value)
#value = value
#height = (SCREEN_HEIGHT/MAX_VALUE) * value
end
end
class GameWindow < Gosu::Window
def initialize
super SCREEN_WIDTH, SCREEN_HEIGHT, false
self.caption = "Sort Visualiser"
#path = nil
#do_insert = false
#do_bubble = false
#columns = Array.new(COUNT)
column_index = 0
while (column_index < COUNT)
col = Column.new(rand(MAX_VALUE + 1))
#columns[column_index] = col
column_index += 1
end
#text_font = Gosu::Font.new(10)
end
def needs_cursor?
true
end
def insertion_sort(loop)
j = loop
done = false
while ((j > 0) and (!done))
if (#columns[j].value < #columns[j - 1].value)
temp = #columns[j - 1]
#columns[j - 1] = #columns[j]
#columns[j] = temp
else
done = true
end
j = j - 1
end
end
def bubble_sort(loop2)
j = loop2
i = loop2 + 1
done = false
while ((j > 0) and (!done))
if (#columns[j].value > #columns[i].value)
temp = #columns[j]
#columns[j] = #columns[i]
#columns[i] = temp
else
done = true
end
j = j - 1
end
end
def button_down(id)
case id
when Gosu::MsLeft
#do_insert = true
#loop = 0
#do_bubble = false
when Gosu::MsRight
#do_bubble = true
#loop2 = 0
#do_insert = false
end
end
def update
if (#do_insert)
puts "Doing insert #{#loop}"
if #loop < (COUNT)
insertion_sort(#loop)
#loop += 1
sleep(0.5)
else
#do_insert = false
end
end
if (#do_bubble)
puts "Doing bubble #{#loop2}"
if #loop2 < (COUNT)
bubble_sort(#loop2)
#loop2 += 1
sleep(0.5)
else
#do_bubble = false
end
end
end
def draw
column_index = 0
while (column_index < #columns.length)
color = Gosu::Color::GREEN
Gosu.draw_rect((column_index * COL_WIDTH), SCREEN_HEIGHT - #columns[column_index].height, COL_WIDTH, #columns[column_index].height, color, ZOrder::MIDDLE, mode=:default)
#text_font.draw("#{#columns[column_index].value}", (column_index * COL_WIDTH) + 5, SCREEN_HEIGHT - 10, ZOrder::TOP, 1.0, 1.0, Gosu::Color::RED)
column_index += 1
end
end
end
window = GameWindow.new
window.show
EDIT: Added in the rest of the code and removed some tags
I made a program for school few weeks ego.. i have finished it yet.
for some reason, when i am trying to run the program now, it doesn't work, although it worked well in the last time a tried.
I am sure that i didn't change anything in the code, but there is always a chance that something has changed and i didn't payed attention..
I need to pass it to my teacher in these days and i have no idea what is wrong with the program.
I will glad to get some help here..
here is the code:
import wx
import winsound
import wx.grid as gridlib
from random import randint
OPTIONS = [1, 2, 3, 4, 5, 6, 7, 8, 9, "DEL", 0, "SEND"]
# these are the events' IDs sent to a function when you click a button.
# the OPTIONS_ID is in the same order of OPTIONS.
OPTIONS_ID = [-31984,-31983,-31982,-31981,-31980,-31979, -31978, -31977, -31976, -31975, -31974, -31973, -31985] # the built in wxpython IDs for the buttons
GAME_POSITION = (400, 100)
GAME_SIZE = [900, 600]
def RandomNum():
count = 5
while count > 4:
num = randint(1000, 9999)
digits = str(num)
count = 0
for digit in digits:
for digit2 in digits:
if digit == digit2:
count = count + 1
return digits
class Frame(wx.Frame): # class for all the frames in our game.
def __init__(self, parent, id, title, pos, size):
wx.Frame.__init__(self, parent, id, title, pos, size)
self.panel = wx.Panel(self)
self.fdf = wx.TextCtrl(self.panel, size=(275, 75), pos=(520, 20))
self.count = 0
self.turnsCounter = 0
self.numbers = RandomNum()
self.bulls = 0
self.cows = 0
self.counter_of_turns = 0
self.check = False
self.grid = gridlib.Grid(self.panel, pos = (85, 150), size=(323, 212))
self.grid.CreateGrid(10, 3)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.panel, 1, wx.EXPAND)
sizer.Add(self.grid, 1, wx.EXPAND)
self.panel.SetSizer(sizer)
for i in range(10):
for j in range(4):
self.grid.SetReadOnly(i, j)
self.grid.SetColLabelValue(0, "guess")
self.grid.SetColLabelValue(1, "cows")
self.grid.SetColLabelValue(2, "bulls")
def message_dialog(self, message, caption, style=wx.YES_NO, position=GAME_POSITION):
if message != "": # making sure not to execute a message if its empety
message = wx.MessageDialog(None, message, caption, style, position)
answer = message.ShowModal()
if answer == wx.ID_YES:
self.reset()
else:
self.Destroy()
else:
return -1
# this function creates a textbox at a specific position with a specific size.
def write(self, panel, txt, pos, size=20, font_family=wx.SWISS, font_style = wx.NORMAL,font_weight = wx.BOLD, underline = False, color=wx.WHITE):
# create a textbox at a specific position with a specific size.
your_txt = wx.StaticText(panel, -1, txt, pos)
your_txt.SetFont(wx.Font(size,font_family,font_style,font_weight,underline))
your_txt.SetForegroundColour(color)
# same as above, just for a button.
def create_button(self, panel, txt, position, width, height, color, disable):
Size = wx.Size(width, height)
self.button = wx.Button(panel, -1, txt, position, Size)
self.button.SetBackgroundColour(color)
self.border = wx.BoxSizer(wx.VERTICAL)
self.border.Add(self.button)
self.Bind(wx.EVT_BUTTON, lambda evt: self.OnButton(evt), self.button)
if disable == True:
self.button.Disable()
def count_bulls(self, txtctrl, seria):
for i in range(4):
if seria[i] == txtctrl[i]:
self.bulls += 1
replacement = self.bulls
self.bulls = 0
return replacement
def count_cows(self, txtctrl, seria):
for i in range(4):
if seria[i] != txtctrl[i] and seria[i] in txtctrl:
self.cows += 1
replacement = self.cows
self.cows = 0
return replacement
def reset(self):
self.fdf.Clear()
self.grid.ClearGrid()
self.count = 0
self.turnsCounter = 0
self.numbers = RandomNum()
self.bulls = 0
self.cows = 0
self.counter_of_turns = 0
self.check = False
for child in self.panel.GetChildren():
if child.GetLabel() != "SEND":
child.Enable()
else:
child.Disable()
if self.count == 0:
if child.GetLabel() == "DEL" or child.GetLabel() == "0":
child.Disable()
def OnButton(self, event):
print repr(event.Id) + ","
print self.numbers
if event.Id in OPTIONS_ID: # if indeed an option button was pressed
exited = -1 # exited is 5100 if the user exited his dialog box
# assigning the events to the button.
for i in range(13):
if event.Id != -31985 and event.Id != -31975 and event.Id != -31974 and event.Id != -31973 and event.Id == OPTIONS_ID[i]:
self.fdf.AppendText(str(OPTIONS[i]))
self.count += 1
if event.Id == -31974:
self.fdf.AppendText(str(OPTIONS[10]))
self.count += 1
if event.Id == -31985:
self.reset()
if event.Id == -31973:
self.counter_of_turns += 1
print self.numbers
print self.fdf.GetValue()
cows = self.count_cows(self.fdf.GetValue(), self.numbers)
bulls = self.count_bulls(self.fdf.GetValue(), self.numbers)
self.grid.SetCellValue(self.turnsCounter,0, self.fdf.GetValue())
self.grid.SetCellValue(self.turnsCounter, 1, str(cows))
self.grid.SetCellValue(self.turnsCounter, 2, str(bulls))
self.fdf.Clear()
self.count = 0
if self.turnsCounter < 9:
self.turnsCounter += 1
if bulls == 4:
self.check = True
winsound.PlaySound('The_Power_-_Snap_1_.wav', winsound.SND_ASYNC | winsound.SND_LOOP)
self.message_dialog("Well done! you won this game..\n You won the game in %s turns .. \n Play again ? " % self.counter_of_turns , "You won!")
winsound.PlaySound(None, 0)
if event.Id == -31975:
if self.count > 0:
self.count -= 1
self.fdf.Remove(self.fdf.GetLastPosition()-1, self.fdf.GetLastPosition())
if self.count == 4:
for child in self.panel.GetChildren():
if isinstance(child, wx.Button):
try:
int(child.GetLabel())
except ValueError:
if child.GetLabel() == "SEND":
child.Enable()
else:
child.Disable()
elif self.check == False:
for child in self.panel.GetChildren():
if child.GetLabel() != "SEND":
child.Enable()
else:
child.Disable()
if self.count == 0:
if child.GetLabel() == "DEL" or child.GetLabel() == "0":
child.Disable()
#for child in self.panel.GetChildren():
#if isinstance(child, wx.Button):
#if child.GetLabel() in self.fdf.GetValue():
#child.Disable()
if self.counter_of_turns == 10 and self.check == False:
self.message_dialog("YOU LOST :( \n THE NUMBERS WERE %s \n PLAY AGAIN ?" % self.numbers,"Bad news ..")
class Game(wx.App):
def OnInit(self): # upon game opening
# I would like the options window to be the first window's parent
# so I will first set up our options window:
window = Frame(None, -1, "Good Luck!", GAME_POSITION, GAME_SIZE)
first_panel = window.panel
window.SetBackgroundColour(wx.BLACK)
window.write(first_panel, "BULLS AND COWS!", (50, 50), size=(35))
countX = 500
countY = 100
window.create_button(first_panel,"restart!", (50, 400), 100, 100, wx.WHITE, False)
for option in OPTIONS:
if str(option) == "SEND" or str(option) == "DEL":
window.create_button(first_panel,str(option), (countX, countY), 100, 100, wx.GREEN, True)
elif str(option) == "0":
window.create_button(first_panel,str(option), (countX, countY), 100, 100, wx.WHITE, True)
else:
window.create_button(first_panel,str(option), (countX, countY), 100, 100, wx.WHITE, False)
countX += 110
if str(option) == "3" or str(option) == "6" or str(option) == "9":
countY += 110
countX = 500
window.Show(True)
return True
def main():
MasterMind = Game()
MasterMind.MainLoop()
if __name__ == '__main__':
main()
PLEASE NOTE:
I upgraded my windows to windows 10 few days ego, it means that it doesn't work since the upgrade if it means something. (sorry if the grammer of my english not so well, it is not my native language..).
In my computer works fine (Python 2.7.11 and windows 7). If you import this class in another file, make sure if you call the main function.
It's a pygame question, and the list basically holds the positions that the user has been in. However instead of being a snake of length "x", it just goes on and on from wherever the user starts.
Find the code posted below, I think the issue is primarily with where the pop is placed, but I can't be sure. If you think so, just CTRL + F "pop"
import pygame
running = 1
screen = pygame.display.set_mode((640,480))
clock = pygame.time.Clock()
UP = (0,-1)
DOWN = (0,1)
LEFT = (-1,0)
RIGHT = (1,0)
#Creating a worm
class WormFromTheFuture:
def __init__(self,initial_x,initial_y,wormlength):
self.x = initial_x
self.y = initial_y
self.length = wormlength
self.body = []
self.dirx = 1
self.diry = 1
def worm_assignment (self, arbtry):
self.dirx, self.diry = arbtry
def worm_moves (self):
self.x += self.dirx
self.y += self.diry
def worm_draw (self, surface):
self.body.insert(0, (self.x,self.y))
if len(self.body) > self.length:
self.body.pop()
for x,y in self.body:
surface.set_at((x,y), (255,255,255))
wormy = WormFromTheFuture (320,240,10)
while running:
wormy.worm_draw(screen)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = 0
pygame.quit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP: wormy.worm_assignment (UP)
if event.key == pygame.K_DOWN: wormy.worm_assignment(DOWN)
if event.key == pygame.K_RIGHT: wormy.worm_assignment(RIGHT)
if event.key == pygame.K_LEFT: wormy.worm_assignment (LEFT)
wormy.worm_moves()
clock.tick(100)
pygame.display.flip()
You can clear the screen with black using a function like:
def clear(self, screen):
screen.fill((0,0,0))
And just call that before any other drawing occurs:
wormy.clear(screen)
wormy.worm_draw(screen)
I think you may be forgetting to undraw the part of the worm that's being popped.