Python Turtle class inheritance not working - python

I am trying to create a snake with an edited Turtles class. So I create a SnakeSegment class which has Turtle class as a parent. I then add a variable to the SnakeSegment class and also I set things like the colour and speed of the Turtle.
I then create my snake class where I bring in my SnakeSegments. The problem is the snake segments don't bring in their colour which I initiated in the snake segment class.
I think I have got the inheritance wrong, but I am not sure.
I have 2 files: components.py and main.py
components.py:
from turtle import Turtle
class SnakeSegment(Turtle):
def __init__(self, givenListPosition):
super().__init__()
self.segment = Turtle()
self.segment.shape("square")
self.segment.color('white')
self.segment.speed(1)
self.segment.penup()
self.listPosition = givenListPosition
class Snake:
def __init__(self, screen):
self.theScreen = screen
self.pastPositions = [(0.00, 0.00), (-20.00, 0.00), (-30.00, 0.00)]
self.t1 = SnakeSegment(0)
self.t2 = SnakeSegment(1)
self.t2.goto(self.pastPositions[int(self.t2.listPosition)])
self.t3 = SnakeSegment(2)
self.t2.goto(self.pastPositions[int(self.t3.listPosition)])
main.py:
from components import *
from turtle import Screen
screen = Screen()
screen.setup(width=600, height=600)
screen.bgcolor("black")
screen.title("Snake Game")
snake = Snake(screen)
snake.theScreen.exitonclick()

I'm not sure I get your final goal and you did not show how your Turtle class looks. However, it appears you are using a mix of inheritance and composition which doesn't seem correct whatever your goal is. You have to decide if SnakeSegment is a Turtle (inheritance) or has a Turtle (composition) in your data model.
With inheritance, SnakeSegment will have all methods and attributes of the base Turtle class (which I assume has some of the "shape", "color" etc methods) and will "be" a Turtle from any point of view. You could then write something like this
class SnakeSegment(Turtle):
def __init__(self, givenListPosition):
super().__init__()
self.shape("square")
self.color('white')
self.speed(1)
self.penup()
self.listPosition = givenListPosition
With composition instead, SnakeSegment doesn't inherit from anything, it just has a member which is an instance of the Turtle class. In that case, something like that would be used
class SnakeSegment:
def __init__(self, givenListPosition):
self.segment = Turtle()
self.segment.shape("square")
self.segment.color('white')
self.segment.speed(1)
self.segment.penup()
self.listPosition = givenListPosition
I'd suggest you start from that and before taking a decision on your data model, have a read about mixins as well (i.e. https://www.pythontutorial.net/python-oop/python-mixin/)

Related

Drawing Basic Animations in Python

Hello I am trying to create something like this box with controllable dots
I need to be able to move and interact with the dots. I have tried turtle and pyglet, but neither of them seem to do what I want them to do.
Turtle is letting me create dots but it doesnt seem to play well with oop. I'm a super noob at python oop so maybe I'm just doing it wrong but I can't seem to make an turtle object that I can actually use how I want. I would ideally be able to use my own methods built off of the turtle methods, and create and call on data unique to each turtle.
import turtle
import time
import random
wn = turtle.Screen()
wn.title("simulation")
wn.bgcolor("tan")
def rng(whatisrandom):
match whatisrandom:
case 'coords': return(random.randint(-400,400) , random.randint(-400,400))
case 'heading':return(random.randint(0,359))
case 'forward':return(random.randint(0,50))
class bug():
def __init__(self) -> None:
self = turtle.Turtle(shape = "circle",visible=False)
self.speed(0)
self.penup()
self.setpos(rng('coords'))
self.showturtle()
self.speed(1)
self.forward(20)
def move(self):
self.setheading(rng('heading'))
self.forward(rng('forward'))
bug1 = bug()
bug1.move()
wn.mainloop()
this is the error message.
self.setheading(rng('heading'))
^^^^^^^^^^^^
AttributeError: 'bug' object has no attribute 'heading'
I ultimately want to animate these little bugs with neural nets and train them to do different movements, and eventually interact with each other.
This appears to be a misunderstanding of how to subclass an object in Python. Let's rearrange things a bit:
from turtle import Screen, Turtle
from random import randint
class Bug(Turtle):
def __init__(self):
super().__init__(shape='circle', visible=False)
self.speed('fastest')
self.penup()
self.setposition(Bug.rng('coords'))
self.showturtle()
self.speed('slowest')
self.forward(20)
def move(self):
self.setheading(Bug.rng('heading'))
self.forward(Bug.rng('forward'))
#staticmethod
def rng(whatisrandom):
if whatisrandom == 'coords':
return randint(-400, 400), randint(-400, 400)
if whatisrandom == 'heading':
return randint(0, 359)
if whatisrandom == 'forward':
return randint(0, 50)
return None
screen = Screen()
screen.title("Simulation")
screen.bgcolor('tan')
bug1 = Bug()
bug1.move()
screen.mainloop()
I don't have an issue with your match statement, I'm just unfamiliar with it and haven't updated my Python sufficiently!

Paddle object from class wont appear

I want to make a flappy bird game and am currently trying to turn paddle a into a class but it wont appear while it should.
Im also not getting any error messages and the code can run but without any signs of paddle x(the object from the class).
this is the code:
class Paddle:
Paddle = turtle.Turtle()
Paddle.penup()
Paddle.goto(0,0)
def __init__(self,shape,color,stretch_wid,stretch_len):
self.shape = shape
self.color = color
self.stretch_wid = stretch_wid
self.stretch_len = stretch_len
paddle_x = Paddle("square","white",5,5)
paddle_a = turtle.Turtle()
paddle_a.shape("square")
paddle_a.color("white")
paddle_a.shapesize(stretch_wid=20,stretch_len=5)
paddle_a.penup()
paddle_a.goto(150,-250)
I already tried putting the 3 lines of codes after the "class Paddle:" under the class and then also changing the "Paddle" into paddle_x but then it says "'Paddle' object has no attribute 'penup'".
First time asking a question.
Thanks in advance.
Having worked with object inheritance with some polygon classes, I believe you will need to reference the "Turtle" object within the class definition of your "Paddle" object as in the following code snippet.
import turtle
class Paddle(turtle.Turtle): # Define as a child of the Turtle object
def __init__(self,shape,color,stretch_wid,stretch_len):
turtle.Turtle.__init__(self) # Use the Turtle object's initialization
self.shape = shape
self.color = color
self.stretch_wid = stretch_wid
self.stretch_len = stretch_len
paddle_x = Paddle("square","white",5,5)
paddle_x.penup()
paddle_x.goto(0,0)
print(paddle_x.shape)
paddle_a = turtle.Turtle()
paddle_a.shape("square")
paddle_a.color("white")
paddle_a.shapesize(stretch_wid=20,stretch_len=5)
paddle_a.penup()
paddle_a.goto(150,-250)
It kind of utilizes the C++ method of initializing a child object based upon the parent (or "super") class. When trying that code snippet out, the screen appears briefly with a turtle pointer and prints out the paddle value requested in the test.
#Una:~/Python_Programs/Paddle$ python3 Paddle.py
square
You might give that a try.
Additional notes.
Referring to your comments and getting a better understanding of what you are trying to do with your "Paddle" class with a one-off initialization of the attributes, following is a slightly revised version of the sample code.
import turtle
class Paddle(turtle.Turtle): # Define as a child of the Turtle object
def __init__(self,shape,color,stretch_wid,stretch_len):
turtle.Turtle.__init__(self) # Use the Turtle objects initialization
self.shape(shape)
self.color(color)
self.shapesize(stretch_wid = stretch_wid, stretch_len=stretch_len)
paddle_x = Paddle("square","blue",5,5)
paddle_x.penup()
paddle_x.goto(0,0)
paddle_a = turtle.Turtle()
paddle_a.shape("square")
paddle_a.color("white")
paddle_a.shapesize(stretch_wid=20,stretch_len=5)
paddle_a.penup()
paddle_a.goto(150,-250)
while True:
pass
That produces a square as per your specifications.
I made the square a blue color since my background happened to be white.
Give that a try.

Class cross referencing?

I come from a C++ background and I am a bit lost without the whole pointer concept in python. Or at least it's unclear.
For instance, I want to create a game of tick tack toe using OOP in Python. I have a couple classes like so:
class Game(object):
def __init__(self, player1, player2):
self.board = [['','',''],
['','',''],
['','','']]
self.players = [player1, player2]
class Player(object):
def __init__(self, game, marking):
self.game = game
self.marking = marking # either 'X' or 'O'
It seems obvious that the game needs to have a reference to the two players and that a player is also part of a game, and should, therefore, have a reference to the game. However, the above code doesn't work because there is no way I can create a player without a creating a game first. But to create a game I need two players.
I could add in these references afterwards by doing something like: player.game = some_game_reference but this seems unpythonic and tedious to keep up with.
What is the best and most pythonic way of accomplishing this?
You can just have one class or the other updates its arguments. For example, create the players first, then have the game update the players with itself:
class Game(object):
def __init__(self, player1, player2):
self.board = [['','',''],
['','',''],
['','','']]
self.players = [player1, player2]
player1.game = self
player2.game = self
player1.marking = 'X'
player2.marking = 'O'
# Neither game nor marking make sense to set initially, until
# the players are added to a game.
class Player(object):
def __init__(self):
pass
p1 = Player()
p2 = Player()
g = Game(p1, p2)
(Whether you need this kind of coupling is, as others have pointed out, a separate design issue.)
Just to show the other direction is just as feasible:
class Player(object):
def __init__(self, game, marking):
self.game = game
self.marking = marking
game.players.append(self)
class Game(object):
def __init__(self):
self.board = [['','',''],
['','',''],
['','','']]
g = Game()
p1 = Player(g, 'X')
p2 = Player(g, 'O')
Hopefully, though, you'll agree that it makes more sense for the game to assign each player a marking. Here, you might try to add more than 2 players to a game, or add two X or two O players.

Why don't my sprites animate when I add a self.image in update function?

I'm currrently learning pyglet, and there is a teeny problem. I called a superclass of the init of pyglet.sprite.Sprite in my player class, but when I try to change the self.image from the update function (or any function that is not the init), it doesn't animate anymore, in fact, it just displays the first element in the array conatining the images for my animation. Thanks. Here is are my codes:
import pyglet
from pyglet.window import key
import physicalobject, resources
class Player(physicalobject.PhysicalObject): #PhysicalObject is just another pyglet.sprite.Sprite superclass
def __init__(self, *args, **kwargs):
super(Player,self).__init__(img=resources.right_anim, *args, **kwargs)
# some codes here....
def update(self, dt):
super(Player,self).update(dt)
#... codes
if self.look_right:
self.image = resources.right_anim
elif self.look_left:
self.image = resources.left_anim

Passing window name as parameter to a class

I created a class containing a method to position a window anywhere on the screen. I am using PyQt4 for GUI programming. I wrote following class:
from PyQt4 import QtGui
class setWindowPosition:
def __init__(self, xCoord, yCoord, windowName, parent = None):
self.x = xCoord
self.y = yCoord
self.wName = windowName;
def AdjustWindow(self):
screen = QtGui.QDesktopWidget().screenGeometry()
size = self.geometry()
self.move((screen.width()-size.width())/2, (screen.height()-size.height())/2)
This code needs correction. Any file that imports this class will pass three parameters: desired_X_Position, desired_Y_position and its own name to this class. The method AdjustWindow should accept these three parameters and position the calling window to the desired coordinates.
In the above code, though I have passed the parameters, but not following how to modify the AdjustWindow method.
It is not entirely clear what you are trying to ask, But, you access the values in the method the same way you set them in the constructor.
from PyQt4 import QtGui
class setWindowPosition:
def __init__(self, xCoord, yCoord, windowName, parent = None):
self.x = xCoord
self.y = yCoord
self.wName = windowName;
def AdjustWindow(self):
print self.x, self.y, self.wName //See Here
//now use them how you want
screen = QtGui.QDesktopWidget().screenGeometry()
size = self.geometry()
self.move((screen.width()-size.width())/2, (screen.height()-size.height())/2)
EDIT:
I found this page which seems to be where you grabbed the code from.
Your class is not inheriting from QtGui.QWidget so calls to geometry() and move() are going to fail. Once you do that, it looks like it the code would be:
def AdjustWindow(self):
self.move(self.x, self.y)
However, you still need to figure out how to have your class as the one that controls the window with windowName. It seems like this package is for making GUIs and not controlling external windows. I could be wrong as I have only read enough to make this answer.

Categories