0

I'm trying to create a game in Python tkinter that involves a rocket ship and some asteroids. The problem is, the rocket ship is made up of multiple shapes. I don't need advice on how to simplify the rocket's shape, but if I could get pointers on using images in a canvas, that might be better.
Anyway, I was researching methods on how to combine multiple shapes into a single shape, or moving multiple shapes at once. This involved the use of IDs and tags, and I'm unclear on which I should use and why.
Why do I need to move multiple shapes at once? The rocket ship is made up of multiple shapes, and it needs to move from side to side. I really don't want a bunch of self.canvas.move() methods cluttering up my code, so if anyone could help me, I would greatly appreciate it. Thanks in advance!

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685

1 Answers1

7

Overview

You're speaking of canvas objects. Every canvas object has a unique integer id. No two objects can have the same id. The id is assigned by tkinter and returned to your code when you create the object. This id is necessary to later be able to refer to each individual object.

Tags on the other hand are completely arbitrary (except they can't be a sequence of digits) and assigned by you. You can assign one or more tags to an object (or no tags to an object), and multiple objects can share the same tags.

Usage

Both tags and ids can be used by many of the canvas methods such as move, bbox, coords, etc.

The most common use of tags are to group multiple objects into a single logical object. A ship might have a body, some wings, maybe some other parts. Each of those parts may have a unique id, but you can assign the same tag to all of the parts so that you can move all parts together in unison.

For a concrete example, let's say you make a ship out of a rectangle for the body and a two triangles for wings. Each will have a unique id. If you want to move those three together as if they were one, you might give each of them the tag "ship-1". If you call `canvas.move("ship-1", 10, 0), all three of those objects will be moved ten pixels to the right.

If you create a second ship, you might give the pieces of that ship the tag "ship-2". In that way you can move just "ship-1" or just "ship-2". Further, if you also give each of those objects the tag "Ship" in addition to their unique "ship-" tag, then you can move all ships at once.

Taking it another step further, lets say you are simulating a space battle. Half the ships are the good guys and half are the bad guys. So now, in addition to giving each piece of a ship the tag "ship-1", and also giving each piece of a ship the tag "Ship", you can also give each piece of the ship the tag "good" or "bad"

Use-case

With all of the above in place, you can now do the following:

  • move one individual piece of one ship by using the id
  • move all pieces for the first ship with "ship-1"
  • move all pieces for the second ship with "ship-2"
  • move all of the "good" ships together in formation with "good"
  • move all of the "bad" ships together in formation with "bad"
  • move all ships using "Ship"
  • move everything with the special tag "all" which automatically refers to everything on the canvas.

And, of course, instead of moving you can also change the color of any of those, or delete all of the objects for any of those, move an object or objects on top of or underneath other objects (z-index), etc.

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • Excellent explanations and examples! (And some bonus knowledge). Very clear. Thank you so much! – Christopher Marley Jun 07 '18 at 05:25
  • @BryanOakley, is it possible to use `tags` to utilize the active state? For example in your case, if I have `activefill` for the different ship parts and wanted to have `ship-1` in its entirety be active when my mouse is hovered above, is that possible? I'm still searching but couldn't find an answer, and this post was as close as I got at the moment. – r.ook Jan 11 '19 at 20:48
  • @Idlehands: I don't think so. I think only one canvas object at a time can be the active item. You can certainly simulate it by putting custom bindings on the enter and leave events. – Bryan Oakley Jan 11 '19 at 21:16
  • Thank you @BryanOakley, I assume you mean `tag_bind()` and not `Canvas.bind()` and then handling all the tag conditions inside? That was one workaround I have entertained but would have preferred if there was a simpler method. I will dig further with your suggestion, thanks again. – r.ook Jan 11 '19 at 21:32