Naming/Calling Generated Object w/ Classes - python

The goal is to generate 25 objects using the same class.
I am currently using this code to create the object:
class Card:
def __init__(self,pos):
self.flipping = False
self.images = loadanimationimages()
self.frame = 0
self.pos = pos
def flip():
self.flipping = True
def update():
if self.flipping:
self.frame += 1
self.frame %= len(self.images)
def draw(screen):
screen.blit(pygame.transform.smoothscale(self.images[self.frame],
self.pos),55*scale).convert_alpha() #Continued.
def updatecards(): #Create the cards.
cards = []
for x in range(5):
for y in range(5):
cards.append(Card((x*92*scale+offsetx*scale,y*92*scale+offsety*scale)))
I know I have to call card.flip() but I don't know how to call the individual cards. Help?

cards[10].flip()
Seeing as you've stored each individual card in a list ([]) and it's simply indexed by an integer, so to call the card number 10, you do cards[9].<function> etc.
Another way would be to flip the card before adding them into the cards list but that would probably ruin your game :)
while 1:
cardNr = int(raw_input('Flip a card, any card of the total ' + str(len(cards)) + ': '))
cards[cardNr-1].flip() # -1 because humans don't count from 0 normally :)
Would flip a card the user chose to flip.
Since you're using a GUI, here's some sample code for ya:
while 1:
ev = pygame.event.get()
for event in ev:
if event.type == pygame.MOUSEBUTTONUP:
mouse = pygame.mouse.get_pos()
clicked_cards = [c for c in cards if c.clicked(mouse)]
for card in clicked_cards:
if card:
card.flip()
Now add a function to your card that does:
def clicked(self, mouse):
if mouse.x >= self.x and mouse.x <= self.x+self.width:
if mouse.y >= self.y and mouse.y <= self.y+self.height:
return self
return False
There's a better way to do it if i'm not mistaken via card.Rect.collidepoint but since i moved over to other GUI libraries quite early on using Pygame, you would need to read up here:
http://www.pygame.org/docs/ref/rect.html
Pygame mouse clicking detection

Related

How to Level Up

I'm currently working on building the game Pong. One aspect of the game is displaying the current level. What I want to happen is have 3 levels. When the score is equal to 5, I want to display "Level 2". When the score is equal to 10, I want to display "Level 3" and then at 15 I want to display "You Win!" What's happening right now is as soon as the score is equal to 5, the Level number counts up every time it updates the window (super fast). Where or how do I write this so that it functions the way I want?
I created a function in the Pong class called level_up for this.
import arcade
import random
# These are Global constants to use throughout the game
SCREEN_WIDTH = 400
SCREEN_HEIGHT = 300
BALL_RADIUS = 10
PADDLE_WIDTH = 10
PADDLE_HEIGHT = 50
MOVE_AMOUNT = 5
SCORE_HIT = 1
SCORE_MISS = 5
LEVEL_UP = 1
"""Point will identify the x and y coordinates of the ball"""
class Point:
def __init__(self):
"""The __init__ initializes the x and y coordinates"""
self.x=float(0)
self.y=float(0)
"""Velocity will identify the velocity"""
class Velocity:
def __init__(self):
"""The __init__ initializes the x and y velocity"""
self.dx=float(0)
self.dy=float(0)
"""Ball will identify the coordinates and the movement of the ball"""
class Ball:
def __init__(self):
"""The __init__ will initialize the Point and Velocity class values"""
self.center=Point()
#self.center will call the self.x and self.y float values that are found in the Point class.
self.velocity=Velocity()
#self.velocity will call the self.dx and self.dy values that are found in the Velocity class.
self.velocity.dx=2
self.velocity.dy=2
def draw(self):
"""This creates the ball"""
arcade.draw_circle_filled(self.center.x, self.center.y,
BALL_RADIUS, arcade.color.FLUORESCENT_YELLOW)
def advance(self):
self.center.x += self.velocity.dx
self.center.y += self.velocity.dy
def bounce_horizontal(self):
self.velocity.dx *=-1
def bounce_vertical(self):
self.velocity.dy *=-1
def restart(self):
self.center.x=0
self.center.y=random.uniform(0,SCREEN_HEIGHT)
self.velocity.dx=random.uniform(1,8)
self.velocity.dy=random.uniform(0,8)
"""Paddle will represent the paddle"""
class Paddle:
def __init__(self):
"""The __init__ will initialize the location of the paddle"""
self.center=Point()
#self.center calls the Point class
self.center.x=SCREEN_WIDTH
self.center.y=SCREEN_HEIGHT//2
def draw(self):
arcade.draw_rectangle_filled(self.center.x, self.center.y,
PADDLE_WIDTH, PADDLE_HEIGHT, arcade.color.FLUORESCENT_PINK)
def move_up(self):
self.center.y+=MOVE_AMOUNT
if self.center.y > SCREEN_HEIGHT:
self.center.y -= MOVE_AMOUNT
def move_down(self):
self.center.y-=MOVE_AMOUNT
if self.center.y < 0:
self.center.y += MOVE_AMOUNT
class Pong(arcade.Window):
"""
This class handles all the game callbacks and interaction
It assumes the following classes exist:
Point
Velocity
Ball
Paddle
This class will then call the appropriate functions of
each of the above classes.
You are welcome to modify anything in this class,
but should not have to if you don't want to.
"""
def __init__(self, width, height):
"""
Sets up the initial conditions of the game
:param width: Screen width
:param height: Screen height
"""
super().__init__(width, height)
self.ball = Ball()
self.paddle = Paddle()
self.score = 0
self.level = 1
# These are used to see if the user is
# holding down the arrow keys
self.holding_left = False
self.holding_right = False
arcade.set_background_color(arcade.color.BLACK)
def on_draw(self):
"""
Called automatically by the arcade framework.
Handles the responsiblity of drawing all elements.
"""
# clear the screen to begin drawing
arcade.start_render()
# draw each object
self.ball.draw()
self.paddle.draw()
self.draw_score()
self.draw_level()
def draw_score(self):
"""
Puts the current score on the screen
"""
score_text = "Score: {}".format(self.score)
start_x = 190
start_y = SCREEN_HEIGHT - 20
arcade.draw_text(score_text, start_x=start_x, start_y=start_y, font_size=12,
color=arcade.color.DEEP_SKY_BLUE)
def draw_level(self):
"""Displays the level"""
level_text = f"LEVEL {self.level}"
start_x= 175
start_y=SCREEN_HEIGHT - 40
arcade.draw_text(level_text, start_x=start_x, start_y=start_y, font_size=20,
color=arcade.color.ELECTRIC_GREEN)
def update(self, delta_time):
"""
Update each object in the game.
:param delta_time: tells us how much time has actually elapsed
"""
# Move the ball forward one element in time
self.ball.advance()
# Check to see if keys are being held, and then
# take appropriate action
self.check_keys()
# check for ball at important places
self.check_miss()
self.check_hit()
self.check_bounce()
def check_hit(self):
"""
Checks to see if the ball has hit the paddle
and if so, calls its bounce method.
:return:
"""
too_close_x = (PADDLE_WIDTH / 2) + BALL_RADIUS
too_close_y = (PADDLE_HEIGHT / 2) + BALL_RADIUS
if (abs(self.ball.center.x - self.paddle.center.x) < too_close_x and
abs(self.ball.center.y - self.paddle.center.y) < too_close_y and
self.ball.velocity.dx > 0):
# we are too close and moving right, this is a hit!
self.ball.bounce_horizontal()
self.score += SCORE_HIT
def level_up(self):
if self.score ==5:
self.level += LEVEL_UP
if self.score ==10:
self.level += LEVEL_UP
def check_miss(self):
"""
Checks to see if the ball went past the paddle
and if so, restarts it.
"""
if self.ball.center.x > SCREEN_WIDTH:
# We missed!
self.score -= SCORE_MISS
self.ball.restart()
def check_bounce(self):
"""
Checks to see if the ball has hit the borders
of the screen and if so, calls its bounce methods.
"""
if self.ball.center.x < 0 and self.ball.velocity.dx < 0:
self.ball.bounce_horizontal()
if self.ball.center.y < 0 and self.ball.velocity.dy < 0:
self.ball.bounce_vertical()
if self.ball.center.y > SCREEN_HEIGHT and self.ball.velocity.dy > 0:
self.ball.bounce_vertical()
def check_keys(self):
"""
Checks to see if the user is holding down an
arrow key, and if so, takes appropriate action.
"""
if self.holding_left:
self.paddle.move_down()
if self.holding_right:
self.paddle.move_up()
def on_key_press(self, key, key_modifiers):
"""
Called when a key is pressed. Sets the state of
holding an arrow key.
:param key: The key that was pressed
:param key_modifiers: Things like shift, ctrl, etc
"""
if key == arcade.key.LEFT or key == arcade.key.DOWN:
self.holding_left = True
if key == arcade.key.RIGHT or key == arcade.key.UP:
self.holding_right = True
def on_key_release(self, key, key_modifiers):
"""
Called when a key is released. Sets the state of
the arrow key as being not held anymore.
:param key: The key that was pressed
:param key_modifiers: Things like shift, ctrl, etc
"""
if key == arcade.key.LEFT or key == arcade.key.DOWN:
self.holding_left = False
if key == arcade.key.RIGHT or key == arcade.key.UP:
self.holding_right = False
# Creates the game and starts it going
window = Pong(SCREEN_WIDTH, SCREEN_HEIGHT)
arcade.run()
I just answered my own question, I changed the level_up function to say:
def level_up(self):
if self.score ==5 and self.level==1:
self.level += LEVEL_UP
if self.score ==10 and self.level==2:
self.level += LEVEL_UP

How to keep generating random numers from a differant class than the class you're using the numbers for

I need to keep gerating random accelarations for my random movemement in my brain class to change the direction and the possibility to clone the movement from my dots,but right it generates one number and keeps adding it to my velocity.In short my dot is moving in a straight line.How do I fix this.
I haven't tried much because I just don't know how to do it. I'm a beginner so I just don't know the specific code.
def wander(self):
if self.pos[0] < 5 or self.pos[0] > WIDTH - 5 or self.pos[1] < 5 or self.pos[1] > HEIGHT - 5:
self.vel = 0
else:
self.vel = self.vel + acc
self.pos = self.pos +self.vel
#--------------------------------------------------------------------------
#--------------------------------------------------------------------------
class brain:
acc = 0.02 * np.random.random(2) - 0.01
#--------------------------------------------------------------------------
dots = []
for i in range(200): #generate n cells
Dot = dot()
dots.append(Dot)
#--------------------------------------------------------------------------
def mainloop():
while True:
for event in pygame.event.get():
if event.type== QUIT: #if pressing the X, quit the program
pygame.quit() #stop pygame
sys.exit() #stop the program
screen.fill((0,0,0)) #clear the screen;
for i in dots: #update all dots
i.wander()
i.draw()
pygame.display.update() #update display
mainloop()
Right now you're initializing your brain class (the entire class, not even each instance individually) with a single shared acc value -- so you're picking one random number and then using it for the entire life of your program, which makes it not very random at all. (For another example of this phenomenon: https://xkcd.com/221/)
Try something like:
class Brain:
def __init__(self):
self.acc = 0.0
def think(self):
self.acc = 0.02 * np.random.random(2) - 0.01
and then make sure to call think() at the start of wander, or any other time the brain needs to update itself.

Issue with while loop in game.

I'm making a game and it has different tiles obviously. But I've come to an issue in my main Game while loop.
def play():
player = player1()
while True:
room = ClubWorld.tile_at(player.x, player.y)
print(room.intro_text())
choose_action(room, player)
Example of a Tile in my game:
class GirlTile(MapTile):
def __init__(self,x,y):
self.meet_girl = Girls()
super().__init__(x, y)
def intro_text(self):
return "Hey whats up, my name is {}".format(self.meet_girl.name)
This loop keeps going as long as I'm on a game tile. It produces the available actions you have and lets the other functions know your position. it also outputs that tiles intro text, where my problem lies. I want the game to only output the intro text upon entry into a tile, once that happens i only want it to display the actions available. Suggestions?
You can keep previous_room and compare with room:
def play():
player = player1()
previous_room = None
while True:
room = ClubWorld.tile_at(player.x, player.y)
if room != previous_room:
print(room.intro_text())
previous_room = room
choose_action(room, player)
Or keep player previous position previous_x, previous_y and compare with new position
def play():
player = player1()
previous_x = None
previous_y = None
while True:
if player.x != previous_x or player.y != previous_y :
room = ClubWorld.tile_at(player.x, player.y)
print(room.intro_text())
previous_x = player.x
previous_y = player.y
choose_action(room, player)

Pygame through SSH does not register keystrokes (Raspberry Pi 3)

So I got raspi 3 and simple 8x8 LED matrix. After some playing with it I decided to make a simple snake game (displaying on that matrix) with pygame's events, I have no prior experience with pygame. There is no screen/display connected besides the led matrix.
So the problem at first was "pygame.error: video system not initialized", though I think i got it fixed by setting an env variable:
os.putenv('DISPLAY', ':0.0')
Now that I got it working I run it...and nothing happens, like no keystrokes are registered. Just this "junk", I don't know how to call it The dot on LED matrix is not moving. If i alter the snake's x or y position somewhere in the loop it moves as intended.
My code:
#!/usr/bin/python2
import pygame
import max7219.led as led
from max7219.font import proportional, SINCLAIR_FONT, TINY_FONT, CP437_FONT
import numpy as nqp
import os
SIZE = (8, 8)
class Board:
def __init__(self, size, snake):
"Board object for snake game"
self.matrix = np.zeros(size, dtype=np.int8)
self.device = led.matrix()
self.snake = snake
def draw(self):
#add snake
self.matrix = np.zeros(SIZE, dtype=np.int8)
self.matrix[self.snake.x][self.snake.y] = 1
for x in range(8):
for y in range(8):
self.device.pixel(x, y, self.matrix[x][y], redraw=False)
self.device.flush()
def light(self, x, y):
"light specified pixel"
self.matrix[x][y] = 1
def dim(self, x, y):
"off specified pixel"
self.matrix[x][y] = 0
class Snake:
def __init__(self):
"Object representing an ingame snake"
self.length = 1
self.x = 3
self.y = 3
if __name__=="__main__":
os.putenv('DISPLAY', ':0.0')
pygame.init()
snake = Snake()
board = Board(SIZE, snake)
done = False
while not done:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
snake.y -= 1
elif event.key == pygame.K_DOWN:
snake.y += 1
elif event.key == pygame.K_LEFT:
snake.x -= 1
elif event.key == pygame.K_RIGHT:
snake.x += 1
board.draw()
I'm using pygame because I don't know anything else (Well I can't use pygame either but I just don't know of any alternatives). If it can be done simpler I will be happy to do it. Thank You in advance!
You should be able to use curses. Here's a simple example:
import curses
def main(screen):
key = ''
while key != 'q':
key = screen.getkey()
screen.addstr(0, 0, 'key: {:<10}'.format(key))
if __name__ == '__main__':
curses.wrapper(main)
You'll see that your key presses are registered - they're just strings.
However, this runs in blocking mode. Assuming that your code needs to do other things, you can turn nodelay on:
def main(screen):
screen.nodelay(True)
key = ''
while key != 'q':
try:
key = screen.getkey()
except curses.error:
pass # no keypress was ready
else:
screen.addstr(0, 0, 'key: {:<10}'.format(key))
In your scenario you probably would put this inside your game loop that's drawing out to your 8x8 display, so it would look something like this:
game = SnakeGame()
while game.not_done:
try:
key = screen.getkey()
except curses.error:
key = None
if key == 'KEY_UP':
game.turn_up()
elif key == 'KEY_DOWN':
game.turn_down()
elif key == 'KEY_LEFT':
game.turn_left()
elif key == 'KEY_RIGHT':
game.turn_right()
game.tick()
One thing to note - this approach will take 100% of your CPU, so if you don't have some other way to limit what your app is doing it can cause you some problems. You could extend this approach using threading/multiprocessing, if you find that to be something that you need.

How to make a sprite jump in Pyglet?

I've been making a personal project to remake a modified version of SUper Mario Bros.
So far, I've been able to add in the Mario sprite along with the ground and bricks. Now, I'm stuck with how to make Mario jump. Does anyone know how to do it?
EDIT: I already made a class for Mario, but can't get the jump to work. Any ideas why?
class mario(pyglet.sprite.Sprite):
def __init__(self, batch):
self._img_main = pyglet.image.load("Mario_Right.png")
self.img_right1 = pyglet.image.load("Mario_Walk_Right1.png")
self.img_right2 = pyglet.image.load("Mario_Walk_Right2.png")
self.anim_right = pyglet.image.Animation.from_image_sequence([self.img_right1, self.img_right2], 0.5, True)
pyglet.sprite.Sprite.__init__(self, self._img_main)
self.time = 0
def forward_movement(self, flag=True):
if flag:
self.image = self.anim_right
else:
self.image = self._img_main
def jump(self,flag=True):
print time.time()-self.time
self.y -= -10 +20**(time.time()-self.time+.2)
def on_key_press(self, symbol, modifiers):
self.keys_held.append(symbol)
if symbol == pyglet.window.key.RIGHT:
self.player.forward_movement(True)
if symbol == pyglet.window.key.LEFT:
self.player.time=time.time()
self.player.jump()
Try to create gravity on your code. First, create a class for your Mario. Set up their positions and speed. Put up method jump on your Mario.
#put this in your init
self.time = 0
#put this in your condition
if keymap[pyglet.window.key.RIGHT]:
self.mario.time = time.time()
self.mario.jump()
def jump(self):
print time.time()-self.time
self.y -= -10 +20**(time.time()-self.time+.2)

Categories