Simple (Very Easy to Make) RPG Game Simulation in Python and Turtle
The code creates a very simple/easy RPG game, with 2 classes Jedi
and Orc
. The data is visualized using turtle
. Each class has a method of attack
(lightsaber_attack
for Jedi
), which has an argument that must be either a Jedi
or Orc
instance. The .health
attribute of the attacked one will be reduced by .power
of the attacker. If .health
is not positive, then the image of the character will disappear. By design, each character can attack itself.
Simulation
luke.lightsaber_attack( orc_1 )
luke.lightsaber_attack( orc_2 )
orc_1.attack( luke )
orc_2.attack( orc_2 )
Questions
- How can I make the code to be easily understood by teenagers? (in a tutorial)
- How can I make it more compact?
- Are there any missing important features of Python's OOP that are important to be explained to students? (other than
super
and inheritance)
Image Links
- jedi.gif
- orc.gif
- darkorc.gif
damaged.gif
Full code
import turtle
import time
jedi_gif = "/home/asus/Arief_tempo/images/random/jedi.gif"
orc_gif = "orc.gif"
darkorc_gif = "darkorc.gif"
damaged_gif = "damaged.gif"
turtle.register_shape( jedi_gif )
turtle.register_shape( orc_gif )
turtle.register_shape( darkorc_gif )
turtle.register_shape( damaged_gif )
class JediLuke:
def __init__(self):
self.power = 300
self.health = 300
self.img = turtle.Turtle( shape = jedi_gif )
self.damaged_img = turtle.Turtle( shape = damaged_gif, visible = False )
self.img.penup()
self.damaged_img.penup()
def lightsaber_attack(self, enemy):
self.img.setpos(enemy.img.pos()[0], enemy.img.pos()[1])
enemy.damaged_img.showturtle()
enemy.health += - self.power
time.sleep(1)
enemy.damaged_img.hideturtle()
if enemy.health < 0:
enemy.img.hideturtle()
self.img.setpos(200, 0)
def change_pos(self, pos):
self.img.setpos(pos[0], pos[1])
self.damaged_img.setpos(pos[0], pos[1] + 150)
class Orc:
def __init__(self, health, gif_image):
self.power = 100
self.health = health
self.img = turtle.Turtle( shape = gif_image )
self.damaged_img = turtle.Turtle( shape = damaged_gif, visible = False )
self.img.penup()
self.damaged_img.penup()
def attack(self, enemy):
current_pos = self.img.pos()
self.img.setpos(enemy.img.pos()[0], enemy.img.pos()[1])
enemy.damaged_img.showturtle()
enemy.health += - self.power
time.sleep(1)
enemy.damaged_img.hideturtle()
if enemy.health < 0:
enemy.img.hideturtle()
self.img.setpos(current_pos[0], current_pos[1])
def change_pos(self, pos):
self.img.setpos(pos[0], pos[1])
self.damaged_img.setpos(pos[0], pos[1] + 150)
luke = JediLuke()
luke.change_pos( [200, 0] )
orc_1 = Orc( health = 400 , gif_image = orc_gif)
orc_1.change_pos( [-200, 100] )
orc_2 = Orc( health = 200, gif_image = darkorc_gif )
orc_2.change_pos( [-200, -100] )
python object-oriented game role-playing-game turtle-graphics
add a comment |
The code creates a very simple/easy RPG game, with 2 classes Jedi
and Orc
. The data is visualized using turtle
. Each class has a method of attack
(lightsaber_attack
for Jedi
), which has an argument that must be either a Jedi
or Orc
instance. The .health
attribute of the attacked one will be reduced by .power
of the attacker. If .health
is not positive, then the image of the character will disappear. By design, each character can attack itself.
Simulation
luke.lightsaber_attack( orc_1 )
luke.lightsaber_attack( orc_2 )
orc_1.attack( luke )
orc_2.attack( orc_2 )
Questions
- How can I make the code to be easily understood by teenagers? (in a tutorial)
- How can I make it more compact?
- Are there any missing important features of Python's OOP that are important to be explained to students? (other than
super
and inheritance)
Image Links
- jedi.gif
- orc.gif
- darkorc.gif
damaged.gif
Full code
import turtle
import time
jedi_gif = "/home/asus/Arief_tempo/images/random/jedi.gif"
orc_gif = "orc.gif"
darkorc_gif = "darkorc.gif"
damaged_gif = "damaged.gif"
turtle.register_shape( jedi_gif )
turtle.register_shape( orc_gif )
turtle.register_shape( darkorc_gif )
turtle.register_shape( damaged_gif )
class JediLuke:
def __init__(self):
self.power = 300
self.health = 300
self.img = turtle.Turtle( shape = jedi_gif )
self.damaged_img = turtle.Turtle( shape = damaged_gif, visible = False )
self.img.penup()
self.damaged_img.penup()
def lightsaber_attack(self, enemy):
self.img.setpos(enemy.img.pos()[0], enemy.img.pos()[1])
enemy.damaged_img.showturtle()
enemy.health += - self.power
time.sleep(1)
enemy.damaged_img.hideturtle()
if enemy.health < 0:
enemy.img.hideturtle()
self.img.setpos(200, 0)
def change_pos(self, pos):
self.img.setpos(pos[0], pos[1])
self.damaged_img.setpos(pos[0], pos[1] + 150)
class Orc:
def __init__(self, health, gif_image):
self.power = 100
self.health = health
self.img = turtle.Turtle( shape = gif_image )
self.damaged_img = turtle.Turtle( shape = damaged_gif, visible = False )
self.img.penup()
self.damaged_img.penup()
def attack(self, enemy):
current_pos = self.img.pos()
self.img.setpos(enemy.img.pos()[0], enemy.img.pos()[1])
enemy.damaged_img.showturtle()
enemy.health += - self.power
time.sleep(1)
enemy.damaged_img.hideturtle()
if enemy.health < 0:
enemy.img.hideturtle()
self.img.setpos(current_pos[0], current_pos[1])
def change_pos(self, pos):
self.img.setpos(pos[0], pos[1])
self.damaged_img.setpos(pos[0], pos[1] + 150)
luke = JediLuke()
luke.change_pos( [200, 0] )
orc_1 = Orc( health = 400 , gif_image = orc_gif)
orc_1.change_pos( [-200, 100] )
orc_2 = Orc( health = 200, gif_image = darkorc_gif )
orc_2.change_pos( [-200, -100] )
python object-oriented game role-playing-game turtle-graphics
4
As an aside: Luke Skywalker attacking orcs is a jarring mix-up of universes.
– Reinderien
Dec 28 '18 at 15:45
2
I upvoted @Reinderien 's comment, but I also +1 this question because Luke Skywalker. Fighting Orcs.
– bruglesco
Dec 28 '18 at 16:10
5
Please do not update the code in your question to incorporate feedback from answers, doing so goes against the Question + Answer style of Code Review. This is not a forum where you should keep the most updated version in your question. Please see what you may and may not do after receiving answers.
– Mast
Dec 28 '18 at 17:22
@Mast noted....
– Arief Anbiya
Jan 2 at 13:37
why name the attacks differently?
– Maarten Fabré
2 days ago
add a comment |
The code creates a very simple/easy RPG game, with 2 classes Jedi
and Orc
. The data is visualized using turtle
. Each class has a method of attack
(lightsaber_attack
for Jedi
), which has an argument that must be either a Jedi
or Orc
instance. The .health
attribute of the attacked one will be reduced by .power
of the attacker. If .health
is not positive, then the image of the character will disappear. By design, each character can attack itself.
Simulation
luke.lightsaber_attack( orc_1 )
luke.lightsaber_attack( orc_2 )
orc_1.attack( luke )
orc_2.attack( orc_2 )
Questions
- How can I make the code to be easily understood by teenagers? (in a tutorial)
- How can I make it more compact?
- Are there any missing important features of Python's OOP that are important to be explained to students? (other than
super
and inheritance)
Image Links
- jedi.gif
- orc.gif
- darkorc.gif
damaged.gif
Full code
import turtle
import time
jedi_gif = "/home/asus/Arief_tempo/images/random/jedi.gif"
orc_gif = "orc.gif"
darkorc_gif = "darkorc.gif"
damaged_gif = "damaged.gif"
turtle.register_shape( jedi_gif )
turtle.register_shape( orc_gif )
turtle.register_shape( darkorc_gif )
turtle.register_shape( damaged_gif )
class JediLuke:
def __init__(self):
self.power = 300
self.health = 300
self.img = turtle.Turtle( shape = jedi_gif )
self.damaged_img = turtle.Turtle( shape = damaged_gif, visible = False )
self.img.penup()
self.damaged_img.penup()
def lightsaber_attack(self, enemy):
self.img.setpos(enemy.img.pos()[0], enemy.img.pos()[1])
enemy.damaged_img.showturtle()
enemy.health += - self.power
time.sleep(1)
enemy.damaged_img.hideturtle()
if enemy.health < 0:
enemy.img.hideturtle()
self.img.setpos(200, 0)
def change_pos(self, pos):
self.img.setpos(pos[0], pos[1])
self.damaged_img.setpos(pos[0], pos[1] + 150)
class Orc:
def __init__(self, health, gif_image):
self.power = 100
self.health = health
self.img = turtle.Turtle( shape = gif_image )
self.damaged_img = turtle.Turtle( shape = damaged_gif, visible = False )
self.img.penup()
self.damaged_img.penup()
def attack(self, enemy):
current_pos = self.img.pos()
self.img.setpos(enemy.img.pos()[0], enemy.img.pos()[1])
enemy.damaged_img.showturtle()
enemy.health += - self.power
time.sleep(1)
enemy.damaged_img.hideturtle()
if enemy.health < 0:
enemy.img.hideturtle()
self.img.setpos(current_pos[0], current_pos[1])
def change_pos(self, pos):
self.img.setpos(pos[0], pos[1])
self.damaged_img.setpos(pos[0], pos[1] + 150)
luke = JediLuke()
luke.change_pos( [200, 0] )
orc_1 = Orc( health = 400 , gif_image = orc_gif)
orc_1.change_pos( [-200, 100] )
orc_2 = Orc( health = 200, gif_image = darkorc_gif )
orc_2.change_pos( [-200, -100] )
python object-oriented game role-playing-game turtle-graphics
The code creates a very simple/easy RPG game, with 2 classes Jedi
and Orc
. The data is visualized using turtle
. Each class has a method of attack
(lightsaber_attack
for Jedi
), which has an argument that must be either a Jedi
or Orc
instance. The .health
attribute of the attacked one will be reduced by .power
of the attacker. If .health
is not positive, then the image of the character will disappear. By design, each character can attack itself.
Simulation
luke.lightsaber_attack( orc_1 )
luke.lightsaber_attack( orc_2 )
orc_1.attack( luke )
orc_2.attack( orc_2 )
Questions
- How can I make the code to be easily understood by teenagers? (in a tutorial)
- How can I make it more compact?
- Are there any missing important features of Python's OOP that are important to be explained to students? (other than
super
and inheritance)
Image Links
- jedi.gif
- orc.gif
- darkorc.gif
damaged.gif
Full code
import turtle
import time
jedi_gif = "/home/asus/Arief_tempo/images/random/jedi.gif"
orc_gif = "orc.gif"
darkorc_gif = "darkorc.gif"
damaged_gif = "damaged.gif"
turtle.register_shape( jedi_gif )
turtle.register_shape( orc_gif )
turtle.register_shape( darkorc_gif )
turtle.register_shape( damaged_gif )
class JediLuke:
def __init__(self):
self.power = 300
self.health = 300
self.img = turtle.Turtle( shape = jedi_gif )
self.damaged_img = turtle.Turtle( shape = damaged_gif, visible = False )
self.img.penup()
self.damaged_img.penup()
def lightsaber_attack(self, enemy):
self.img.setpos(enemy.img.pos()[0], enemy.img.pos()[1])
enemy.damaged_img.showturtle()
enemy.health += - self.power
time.sleep(1)
enemy.damaged_img.hideturtle()
if enemy.health < 0:
enemy.img.hideturtle()
self.img.setpos(200, 0)
def change_pos(self, pos):
self.img.setpos(pos[0], pos[1])
self.damaged_img.setpos(pos[0], pos[1] + 150)
class Orc:
def __init__(self, health, gif_image):
self.power = 100
self.health = health
self.img = turtle.Turtle( shape = gif_image )
self.damaged_img = turtle.Turtle( shape = damaged_gif, visible = False )
self.img.penup()
self.damaged_img.penup()
def attack(self, enemy):
current_pos = self.img.pos()
self.img.setpos(enemy.img.pos()[0], enemy.img.pos()[1])
enemy.damaged_img.showturtle()
enemy.health += - self.power
time.sleep(1)
enemy.damaged_img.hideturtle()
if enemy.health < 0:
enemy.img.hideturtle()
self.img.setpos(current_pos[0], current_pos[1])
def change_pos(self, pos):
self.img.setpos(pos[0], pos[1])
self.damaged_img.setpos(pos[0], pos[1] + 150)
luke = JediLuke()
luke.change_pos( [200, 0] )
orc_1 = Orc( health = 400 , gif_image = orc_gif)
orc_1.change_pos( [-200, 100] )
orc_2 = Orc( health = 200, gif_image = darkorc_gif )
orc_2.change_pos( [-200, -100] )
python object-oriented game role-playing-game turtle-graphics
python object-oriented game role-playing-game turtle-graphics
edited 2 days ago
Mast
7,43863686
7,43863686
asked Dec 28 '18 at 14:50
Arief Anbiya
512214
512214
4
As an aside: Luke Skywalker attacking orcs is a jarring mix-up of universes.
– Reinderien
Dec 28 '18 at 15:45
2
I upvoted @Reinderien 's comment, but I also +1 this question because Luke Skywalker. Fighting Orcs.
– bruglesco
Dec 28 '18 at 16:10
5
Please do not update the code in your question to incorporate feedback from answers, doing so goes against the Question + Answer style of Code Review. This is not a forum where you should keep the most updated version in your question. Please see what you may and may not do after receiving answers.
– Mast
Dec 28 '18 at 17:22
@Mast noted....
– Arief Anbiya
Jan 2 at 13:37
why name the attacks differently?
– Maarten Fabré
2 days ago
add a comment |
4
As an aside: Luke Skywalker attacking orcs is a jarring mix-up of universes.
– Reinderien
Dec 28 '18 at 15:45
2
I upvoted @Reinderien 's comment, but I also +1 this question because Luke Skywalker. Fighting Orcs.
– bruglesco
Dec 28 '18 at 16:10
5
Please do not update the code in your question to incorporate feedback from answers, doing so goes against the Question + Answer style of Code Review. This is not a forum where you should keep the most updated version in your question. Please see what you may and may not do after receiving answers.
– Mast
Dec 28 '18 at 17:22
@Mast noted....
– Arief Anbiya
Jan 2 at 13:37
why name the attacks differently?
– Maarten Fabré
2 days ago
4
4
As an aside: Luke Skywalker attacking orcs is a jarring mix-up of universes.
– Reinderien
Dec 28 '18 at 15:45
As an aside: Luke Skywalker attacking orcs is a jarring mix-up of universes.
– Reinderien
Dec 28 '18 at 15:45
2
2
I upvoted @Reinderien 's comment, but I also +1 this question because Luke Skywalker. Fighting Orcs.
– bruglesco
Dec 28 '18 at 16:10
I upvoted @Reinderien 's comment, but I also +1 this question because Luke Skywalker. Fighting Orcs.
– bruglesco
Dec 28 '18 at 16:10
5
5
Please do not update the code in your question to incorporate feedback from answers, doing so goes against the Question + Answer style of Code Review. This is not a forum where you should keep the most updated version in your question. Please see what you may and may not do after receiving answers.
– Mast
Dec 28 '18 at 17:22
Please do not update the code in your question to incorporate feedback from answers, doing so goes against the Question + Answer style of Code Review. This is not a forum where you should keep the most updated version in your question. Please see what you may and may not do after receiving answers.
– Mast
Dec 28 '18 at 17:22
@Mast noted....
– Arief Anbiya
Jan 2 at 13:37
@Mast noted....
– Arief Anbiya
Jan 2 at 13:37
why name the attacks differently?
– Maarten Fabré
2 days ago
why name the attacks differently?
– Maarten Fabré
2 days ago
add a comment |
4 Answers
4
active
oldest
votes
jedi_gif = "/home/asus/Arief_tempo/images/random/jedi.gif"
It's unclear why this image has an absolute path but no others do. They should probably all be relative, as the other three are.
Especially if this is for a tutorial, you need to add docstrings to all of your functions.
This:
self.img.setpos(enemy.img.pos()[0], enemy.img.pos()[1])
can use argument expansion, i.e.:
self.img.setpos(*enemy.img.pos())
That pattern can be used elsewhere you're indexing into the position.
This:
enemy.health += - self.power
should be
enemy.health -= self.power
Thanks. Why need docstrings? the functions will be explained in class. If I usef(*pos)
then I need to explain further about function to the kids (which makes the subject a bit more tedious to them), but usingf(pos[0], pos[1])
would be more obvious.
– Arief Anbiya
Dec 29 '18 at 13:01
"Explaining it [presumably verbally] in class" is not good enough. The code should document itself. You should be able to hand a copy to a programmer who has not attended your class and have some reasonable expectation that they'll understand what's going on.
– Reinderien
Dec 29 '18 at 16:59
add a comment |
Just a note of something that was particularly jarring when viewing your code; for stylistic reasons, you shouldn't have spaces on either side of the arguments:
turtle.register_shape( jedi_gif )
Instead you want:
turtle.register_shape(jedi_gif)
This is covered in PEP 8 in the section Whitespace in Expressions and Statements. It's good to follow PEP 8 because it makes it easier for others (and in the long run, yourself) to read your code:
add a comment |
One guiding principle in programming is to write DRY code, Don't Repeat Yourself. Your JediLuke
class and your Orc
class are almost the same. Since you are already teaching about classes, you should also teach about inheritance (maybe later, but eventually).
import turtle
import time
class Entity:
def __init__(self, power, health, img, damaged_img, *position):
self.power = power
self.health = health
self.img = turtle.Turtle(shape=img)
self.damaged_img = turtle.Turtle(shape=damaged_img, visible=False)
self.img.penup()
self.damaged_img.penup()
self.set_position(*position)
def attack(self, enemy):
"""Attack an enemy"""
current_pos = self.img.pos()
self.img.setpos(*enemy.img.pos())
enemy.damaged(self.power)
self.img.setpos(*current_pos)
def damaged(self, power):
"""Take damage from `power`"""
self.damaged_img.showturtle()
self.health -= power
time.sleep(1)
self.damaged_img.hideturtle()
if self.health <= 0:
self.img.hideturtle()
def set_position(self, pos):
self.img.setpos(*pos)
self.damaged_img.setpos(pos[0], pos[1] + 150)
class Jedi(Entity):
def lightsaber_attack(self, enemy):
super().attack(enemy)
attack = None # to ensure it cannot be called...
class Orc(Entity):
pass
if __name__ == "__main__":
jedi_gif = "jedi.gif"
orc_gif = "orc.gif"
darkorc_gif = "darkorc.gif"
damaged_gif = "damaged.gif"
turtle.register_shape(jedi_gif)
turtle.register_shape(orc_gif)
turtle.register_shape(darkorc_gif)
turtle.register_shape(damaged_gif)
luke = Jedi(200, 0)
orc_1 = Orc(400, orc_gif, -200, 100)
orc_2 = Orc(200, darkorc_gif, -200, -100)
This also has the calling code under an if __name__ == "__main__"
guard to allow importing from this script and the whitespace fixed according to PEP8.
add a comment |
I just wanted to add use os path for cross compatibility with other os's. Since mac uses a "/", and windows ""
otherwise if you copy your code to windows and run the script you will get an error saying it's not a valid directory
use
from os import path
path.join("Directory1", "Directory2", "filename.gif")
# Equal to "Directory1/Directory2/filename.gif
# or "Directory1Directory2filename.gif
New contributor
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f210494%2fsimple-very-easy-to-make-rpg-game-simulation-in-python-and-turtle%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
jedi_gif = "/home/asus/Arief_tempo/images/random/jedi.gif"
It's unclear why this image has an absolute path but no others do. They should probably all be relative, as the other three are.
Especially if this is for a tutorial, you need to add docstrings to all of your functions.
This:
self.img.setpos(enemy.img.pos()[0], enemy.img.pos()[1])
can use argument expansion, i.e.:
self.img.setpos(*enemy.img.pos())
That pattern can be used elsewhere you're indexing into the position.
This:
enemy.health += - self.power
should be
enemy.health -= self.power
Thanks. Why need docstrings? the functions will be explained in class. If I usef(*pos)
then I need to explain further about function to the kids (which makes the subject a bit more tedious to them), but usingf(pos[0], pos[1])
would be more obvious.
– Arief Anbiya
Dec 29 '18 at 13:01
"Explaining it [presumably verbally] in class" is not good enough. The code should document itself. You should be able to hand a copy to a programmer who has not attended your class and have some reasonable expectation that they'll understand what's going on.
– Reinderien
Dec 29 '18 at 16:59
add a comment |
jedi_gif = "/home/asus/Arief_tempo/images/random/jedi.gif"
It's unclear why this image has an absolute path but no others do. They should probably all be relative, as the other three are.
Especially if this is for a tutorial, you need to add docstrings to all of your functions.
This:
self.img.setpos(enemy.img.pos()[0], enemy.img.pos()[1])
can use argument expansion, i.e.:
self.img.setpos(*enemy.img.pos())
That pattern can be used elsewhere you're indexing into the position.
This:
enemy.health += - self.power
should be
enemy.health -= self.power
Thanks. Why need docstrings? the functions will be explained in class. If I usef(*pos)
then I need to explain further about function to the kids (which makes the subject a bit more tedious to them), but usingf(pos[0], pos[1])
would be more obvious.
– Arief Anbiya
Dec 29 '18 at 13:01
"Explaining it [presumably verbally] in class" is not good enough. The code should document itself. You should be able to hand a copy to a programmer who has not attended your class and have some reasonable expectation that they'll understand what's going on.
– Reinderien
Dec 29 '18 at 16:59
add a comment |
jedi_gif = "/home/asus/Arief_tempo/images/random/jedi.gif"
It's unclear why this image has an absolute path but no others do. They should probably all be relative, as the other three are.
Especially if this is for a tutorial, you need to add docstrings to all of your functions.
This:
self.img.setpos(enemy.img.pos()[0], enemy.img.pos()[1])
can use argument expansion, i.e.:
self.img.setpos(*enemy.img.pos())
That pattern can be used elsewhere you're indexing into the position.
This:
enemy.health += - self.power
should be
enemy.health -= self.power
jedi_gif = "/home/asus/Arief_tempo/images/random/jedi.gif"
It's unclear why this image has an absolute path but no others do. They should probably all be relative, as the other three are.
Especially if this is for a tutorial, you need to add docstrings to all of your functions.
This:
self.img.setpos(enemy.img.pos()[0], enemy.img.pos()[1])
can use argument expansion, i.e.:
self.img.setpos(*enemy.img.pos())
That pattern can be used elsewhere you're indexing into the position.
This:
enemy.health += - self.power
should be
enemy.health -= self.power
answered Dec 28 '18 at 15:59
Reinderien
3,842821
3,842821
Thanks. Why need docstrings? the functions will be explained in class. If I usef(*pos)
then I need to explain further about function to the kids (which makes the subject a bit more tedious to them), but usingf(pos[0], pos[1])
would be more obvious.
– Arief Anbiya
Dec 29 '18 at 13:01
"Explaining it [presumably verbally] in class" is not good enough. The code should document itself. You should be able to hand a copy to a programmer who has not attended your class and have some reasonable expectation that they'll understand what's going on.
– Reinderien
Dec 29 '18 at 16:59
add a comment |
Thanks. Why need docstrings? the functions will be explained in class. If I usef(*pos)
then I need to explain further about function to the kids (which makes the subject a bit more tedious to them), but usingf(pos[0], pos[1])
would be more obvious.
– Arief Anbiya
Dec 29 '18 at 13:01
"Explaining it [presumably verbally] in class" is not good enough. The code should document itself. You should be able to hand a copy to a programmer who has not attended your class and have some reasonable expectation that they'll understand what's going on.
– Reinderien
Dec 29 '18 at 16:59
Thanks. Why need docstrings? the functions will be explained in class. If I use
f(*pos)
then I need to explain further about function to the kids (which makes the subject a bit more tedious to them), but using f(pos[0], pos[1])
would be more obvious.– Arief Anbiya
Dec 29 '18 at 13:01
Thanks. Why need docstrings? the functions will be explained in class. If I use
f(*pos)
then I need to explain further about function to the kids (which makes the subject a bit more tedious to them), but using f(pos[0], pos[1])
would be more obvious.– Arief Anbiya
Dec 29 '18 at 13:01
"Explaining it [presumably verbally] in class" is not good enough. The code should document itself. You should be able to hand a copy to a programmer who has not attended your class and have some reasonable expectation that they'll understand what's going on.
– Reinderien
Dec 29 '18 at 16:59
"Explaining it [presumably verbally] in class" is not good enough. The code should document itself. You should be able to hand a copy to a programmer who has not attended your class and have some reasonable expectation that they'll understand what's going on.
– Reinderien
Dec 29 '18 at 16:59
add a comment |
Just a note of something that was particularly jarring when viewing your code; for stylistic reasons, you shouldn't have spaces on either side of the arguments:
turtle.register_shape( jedi_gif )
Instead you want:
turtle.register_shape(jedi_gif)
This is covered in PEP 8 in the section Whitespace in Expressions and Statements. It's good to follow PEP 8 because it makes it easier for others (and in the long run, yourself) to read your code:
add a comment |
Just a note of something that was particularly jarring when viewing your code; for stylistic reasons, you shouldn't have spaces on either side of the arguments:
turtle.register_shape( jedi_gif )
Instead you want:
turtle.register_shape(jedi_gif)
This is covered in PEP 8 in the section Whitespace in Expressions and Statements. It's good to follow PEP 8 because it makes it easier for others (and in the long run, yourself) to read your code:
add a comment |
Just a note of something that was particularly jarring when viewing your code; for stylistic reasons, you shouldn't have spaces on either side of the arguments:
turtle.register_shape( jedi_gif )
Instead you want:
turtle.register_shape(jedi_gif)
This is covered in PEP 8 in the section Whitespace in Expressions and Statements. It's good to follow PEP 8 because it makes it easier for others (and in the long run, yourself) to read your code:
Just a note of something that was particularly jarring when viewing your code; for stylistic reasons, you shouldn't have spaces on either side of the arguments:
turtle.register_shape( jedi_gif )
Instead you want:
turtle.register_shape(jedi_gif)
This is covered in PEP 8 in the section Whitespace in Expressions and Statements. It's good to follow PEP 8 because it makes it easier for others (and in the long run, yourself) to read your code:
answered Dec 28 '18 at 17:39
Graham
970113
970113
add a comment |
add a comment |
One guiding principle in programming is to write DRY code, Don't Repeat Yourself. Your JediLuke
class and your Orc
class are almost the same. Since you are already teaching about classes, you should also teach about inheritance (maybe later, but eventually).
import turtle
import time
class Entity:
def __init__(self, power, health, img, damaged_img, *position):
self.power = power
self.health = health
self.img = turtle.Turtle(shape=img)
self.damaged_img = turtle.Turtle(shape=damaged_img, visible=False)
self.img.penup()
self.damaged_img.penup()
self.set_position(*position)
def attack(self, enemy):
"""Attack an enemy"""
current_pos = self.img.pos()
self.img.setpos(*enemy.img.pos())
enemy.damaged(self.power)
self.img.setpos(*current_pos)
def damaged(self, power):
"""Take damage from `power`"""
self.damaged_img.showturtle()
self.health -= power
time.sleep(1)
self.damaged_img.hideturtle()
if self.health <= 0:
self.img.hideturtle()
def set_position(self, pos):
self.img.setpos(*pos)
self.damaged_img.setpos(pos[0], pos[1] + 150)
class Jedi(Entity):
def lightsaber_attack(self, enemy):
super().attack(enemy)
attack = None # to ensure it cannot be called...
class Orc(Entity):
pass
if __name__ == "__main__":
jedi_gif = "jedi.gif"
orc_gif = "orc.gif"
darkorc_gif = "darkorc.gif"
damaged_gif = "damaged.gif"
turtle.register_shape(jedi_gif)
turtle.register_shape(orc_gif)
turtle.register_shape(darkorc_gif)
turtle.register_shape(damaged_gif)
luke = Jedi(200, 0)
orc_1 = Orc(400, orc_gif, -200, 100)
orc_2 = Orc(200, darkorc_gif, -200, -100)
This also has the calling code under an if __name__ == "__main__"
guard to allow importing from this script and the whitespace fixed according to PEP8.
add a comment |
One guiding principle in programming is to write DRY code, Don't Repeat Yourself. Your JediLuke
class and your Orc
class are almost the same. Since you are already teaching about classes, you should also teach about inheritance (maybe later, but eventually).
import turtle
import time
class Entity:
def __init__(self, power, health, img, damaged_img, *position):
self.power = power
self.health = health
self.img = turtle.Turtle(shape=img)
self.damaged_img = turtle.Turtle(shape=damaged_img, visible=False)
self.img.penup()
self.damaged_img.penup()
self.set_position(*position)
def attack(self, enemy):
"""Attack an enemy"""
current_pos = self.img.pos()
self.img.setpos(*enemy.img.pos())
enemy.damaged(self.power)
self.img.setpos(*current_pos)
def damaged(self, power):
"""Take damage from `power`"""
self.damaged_img.showturtle()
self.health -= power
time.sleep(1)
self.damaged_img.hideturtle()
if self.health <= 0:
self.img.hideturtle()
def set_position(self, pos):
self.img.setpos(*pos)
self.damaged_img.setpos(pos[0], pos[1] + 150)
class Jedi(Entity):
def lightsaber_attack(self, enemy):
super().attack(enemy)
attack = None # to ensure it cannot be called...
class Orc(Entity):
pass
if __name__ == "__main__":
jedi_gif = "jedi.gif"
orc_gif = "orc.gif"
darkorc_gif = "darkorc.gif"
damaged_gif = "damaged.gif"
turtle.register_shape(jedi_gif)
turtle.register_shape(orc_gif)
turtle.register_shape(darkorc_gif)
turtle.register_shape(damaged_gif)
luke = Jedi(200, 0)
orc_1 = Orc(400, orc_gif, -200, 100)
orc_2 = Orc(200, darkorc_gif, -200, -100)
This also has the calling code under an if __name__ == "__main__"
guard to allow importing from this script and the whitespace fixed according to PEP8.
add a comment |
One guiding principle in programming is to write DRY code, Don't Repeat Yourself. Your JediLuke
class and your Orc
class are almost the same. Since you are already teaching about classes, you should also teach about inheritance (maybe later, but eventually).
import turtle
import time
class Entity:
def __init__(self, power, health, img, damaged_img, *position):
self.power = power
self.health = health
self.img = turtle.Turtle(shape=img)
self.damaged_img = turtle.Turtle(shape=damaged_img, visible=False)
self.img.penup()
self.damaged_img.penup()
self.set_position(*position)
def attack(self, enemy):
"""Attack an enemy"""
current_pos = self.img.pos()
self.img.setpos(*enemy.img.pos())
enemy.damaged(self.power)
self.img.setpos(*current_pos)
def damaged(self, power):
"""Take damage from `power`"""
self.damaged_img.showturtle()
self.health -= power
time.sleep(1)
self.damaged_img.hideturtle()
if self.health <= 0:
self.img.hideturtle()
def set_position(self, pos):
self.img.setpos(*pos)
self.damaged_img.setpos(pos[0], pos[1] + 150)
class Jedi(Entity):
def lightsaber_attack(self, enemy):
super().attack(enemy)
attack = None # to ensure it cannot be called...
class Orc(Entity):
pass
if __name__ == "__main__":
jedi_gif = "jedi.gif"
orc_gif = "orc.gif"
darkorc_gif = "darkorc.gif"
damaged_gif = "damaged.gif"
turtle.register_shape(jedi_gif)
turtle.register_shape(orc_gif)
turtle.register_shape(darkorc_gif)
turtle.register_shape(damaged_gif)
luke = Jedi(200, 0)
orc_1 = Orc(400, orc_gif, -200, 100)
orc_2 = Orc(200, darkorc_gif, -200, -100)
This also has the calling code under an if __name__ == "__main__"
guard to allow importing from this script and the whitespace fixed according to PEP8.
One guiding principle in programming is to write DRY code, Don't Repeat Yourself. Your JediLuke
class and your Orc
class are almost the same. Since you are already teaching about classes, you should also teach about inheritance (maybe later, but eventually).
import turtle
import time
class Entity:
def __init__(self, power, health, img, damaged_img, *position):
self.power = power
self.health = health
self.img = turtle.Turtle(shape=img)
self.damaged_img = turtle.Turtle(shape=damaged_img, visible=False)
self.img.penup()
self.damaged_img.penup()
self.set_position(*position)
def attack(self, enemy):
"""Attack an enemy"""
current_pos = self.img.pos()
self.img.setpos(*enemy.img.pos())
enemy.damaged(self.power)
self.img.setpos(*current_pos)
def damaged(self, power):
"""Take damage from `power`"""
self.damaged_img.showturtle()
self.health -= power
time.sleep(1)
self.damaged_img.hideturtle()
if self.health <= 0:
self.img.hideturtle()
def set_position(self, pos):
self.img.setpos(*pos)
self.damaged_img.setpos(pos[0], pos[1] + 150)
class Jedi(Entity):
def lightsaber_attack(self, enemy):
super().attack(enemy)
attack = None # to ensure it cannot be called...
class Orc(Entity):
pass
if __name__ == "__main__":
jedi_gif = "jedi.gif"
orc_gif = "orc.gif"
darkorc_gif = "darkorc.gif"
damaged_gif = "damaged.gif"
turtle.register_shape(jedi_gif)
turtle.register_shape(orc_gif)
turtle.register_shape(darkorc_gif)
turtle.register_shape(damaged_gif)
luke = Jedi(200, 0)
orc_1 = Orc(400, orc_gif, -200, 100)
orc_2 = Orc(200, darkorc_gif, -200, -100)
This also has the calling code under an if __name__ == "__main__"
guard to allow importing from this script and the whitespace fixed according to PEP8.
edited Dec 31 '18 at 13:18
answered Dec 30 '18 at 13:16
Graipher
23.6k53585
23.6k53585
add a comment |
add a comment |
I just wanted to add use os path for cross compatibility with other os's. Since mac uses a "/", and windows ""
otherwise if you copy your code to windows and run the script you will get an error saying it's not a valid directory
use
from os import path
path.join("Directory1", "Directory2", "filename.gif")
# Equal to "Directory1/Directory2/filename.gif
# or "Directory1Directory2filename.gif
New contributor
add a comment |
I just wanted to add use os path for cross compatibility with other os's. Since mac uses a "/", and windows ""
otherwise if you copy your code to windows and run the script you will get an error saying it's not a valid directory
use
from os import path
path.join("Directory1", "Directory2", "filename.gif")
# Equal to "Directory1/Directory2/filename.gif
# or "Directory1Directory2filename.gif
New contributor
add a comment |
I just wanted to add use os path for cross compatibility with other os's. Since mac uses a "/", and windows ""
otherwise if you copy your code to windows and run the script you will get an error saying it's not a valid directory
use
from os import path
path.join("Directory1", "Directory2", "filename.gif")
# Equal to "Directory1/Directory2/filename.gif
# or "Directory1Directory2filename.gif
New contributor
I just wanted to add use os path for cross compatibility with other os's. Since mac uses a "/", and windows ""
otherwise if you copy your code to windows and run the script you will get an error saying it's not a valid directory
use
from os import path
path.join("Directory1", "Directory2", "filename.gif")
# Equal to "Directory1/Directory2/filename.gif
# or "Directory1Directory2filename.gif
New contributor
New contributor
answered 2 days ago
Davidhall
11
11
New contributor
New contributor
add a comment |
add a comment |
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f210494%2fsimple-very-easy-to-make-rpg-game-simulation-in-python-and-turtle%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
4
As an aside: Luke Skywalker attacking orcs is a jarring mix-up of universes.
– Reinderien
Dec 28 '18 at 15:45
2
I upvoted @Reinderien 's comment, but I also +1 this question because Luke Skywalker. Fighting Orcs.
– bruglesco
Dec 28 '18 at 16:10
5
Please do not update the code in your question to incorporate feedback from answers, doing so goes against the Question + Answer style of Code Review. This is not a forum where you should keep the most updated version in your question. Please see what you may and may not do after receiving answers.
– Mast
Dec 28 '18 at 17:22
@Mast noted....
– Arief Anbiya
Jan 2 at 13:37
why name the attacks differently?
– Maarten Fabré
2 days ago